@stablebaseline/sdk 0.4.2 → 0.4.3

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/openapi.json CHANGED
@@ -2184,7 +2184,7 @@
2184
2184
  "/tools/listDocuments": {
2185
2185
  "post": {
2186
2186
  "summary": "listDocuments",
2187
- "description": "List documents in a project, workspace, or folder. Supports query search and date filtering.",
2187
+ "description": "List AND grep documents in a project, workspace, or folder. `query` does a full-content search across each document's body (not just the title) and returns the matching lines — like grep across your docs. Each returned document includes `contentMatches: [{line, text, context?}]` and `matchCount`; the `text` is anchor-ready (paste it straight into editDocument's oldText). Use isRegex:true for regular-expression search (e.g. \"TODO\\(.*\\)\", \"ACME-\\d+\"), caseSensitive for exact case, and contextLines for surrounding lines (grep -C). versionTimestamp is returned per document so you can edit straight from the results without a getDocument round-trip. Also supports date filtering.",
2188
2188
  "operationId": "listDocuments",
2189
2189
  "tags": [
2190
2190
  "documents"
@@ -2206,7 +2206,24 @@
2206
2206
  "type": "string"
2207
2207
  },
2208
2208
  "query": {
2209
- "type": "string"
2209
+ "type": "string",
2210
+ "description": "Search text. Matched against title, friendlyId AND full document content. Returns the matching lines per document (grep). Case-insensitive unless caseSensitive:true; treated as a regex if isRegex:true."
2211
+ },
2212
+ "isRegex": {
2213
+ "type": "boolean",
2214
+ "description": "Treat `query` as a JavaScript regular expression (grep -E). Default false (literal substring). Regex search requires a project/workspace/folder scope and scans a bounded window of documents."
2215
+ },
2216
+ "caseSensitive": {
2217
+ "type": "boolean",
2218
+ "description": "Case-sensitive matching. Default false."
2219
+ },
2220
+ "contextLines": {
2221
+ "type": "number",
2222
+ "description": "Lines of surrounding context to include with each match (grep -C). 0-5, default 0."
2223
+ },
2224
+ "maxMatchesPerDocument": {
2225
+ "type": "number",
2226
+ "description": "Cap on matching lines returned per document. 1-20, default 5."
2210
2227
  },
2211
2228
  "limit": {
2212
2229
  "type": "number"
@@ -2231,7 +2248,7 @@
2231
2248
  "items": {
2232
2249
  "type": "string"
2233
2250
  },
2234
- "description": "Field projection. Valid fields: id, title, friendlyId, friendlyIdNumber, projectId, folderId, createdAt, updatedAt, href."
2251
+ "description": "Field projection for the document metadata. Valid fields: id, title, friendlyId, friendlyIdNumber, projectId, folderId, createdAt, updatedAt, href. (contentMatches/matchCount are always included when query is set.)"
2235
2252
  }
2236
2253
  }
2237
2254
  }
@@ -2816,7 +2833,7 @@
2816
2833
  "/tools/editDocument": {
2817
2834
  "post": {
2818
2835
  "summary": "editDocument",
2819
- "description": "Edit a document: the PREFERRED tool for small targeted changes. Two patch dialects — do NOT mix them in one call. (1) ANCHOR patches {oldText, newText, before?, after?} — RECOMMENDED: replace an exact snippet of existing text with new text. oldText must match the document byte-for-byte AND be unique; if it occurs more than once, add `before`/`after` (short nearby surrounding text) to disambiguate. A no-match returns nearby context; an ambiguous match returns the occurrence count. Anchors do NOT drift, so you don't need fresh line numbers and they survive concurrent edits. Use newText:\"\" to delete. (2) LINE patches {startLine, endLine, replacement} — 1-based and INCLUSIVE: call getDocument first for line numbers; replace line 5 with {startLine:5,endLine:5}; INSERT before line N (deleting nothing) with {startLine:N,endLine:N-1}; append to an L-line document with {startLine:L+1,endLine:L}. Line numbers are ABSOLUTE and GO STALE after ANY edit — re-call getDocument before further line patches; out-of-range patches are rejected with the current line count. versionTimestamp from getDocument is required for optimistic locking, EXCEPT when dryRun:true. Set dryRun:true to apply the patches and get the resulting text back WITHOUT saving (verify before committing — kills retry loops). Do not edit or delete DIAGRAM/IMAGE marker lines (rejected with guidance) — use dedicated diagram/image tools. To @-mention a person, insert `<!-- REFERENCE: {\"type\":\"user\",\"id\":\"<user_uuid>\",\"label\":\"Name\"} -->`; look up the user_id via listAssignablePrincipals. Mentioned users are notified automatically.",
2836
+ "description": "Edit a document: the PREFERRED tool for small targeted changes. Two patch dialects — do NOT mix them in one call. (1) ANCHOR patches {oldText, newText, before?, after?} — RECOMMENDED: replace an exact snippet of existing text with new text. oldText must match the document byte-for-byte AND be unique; if it occurs more than once, either expand oldText until it is unique, or add `before`/`after` (the EXACT text immediately before/after the match) to disambiguate. A no-match returns nearby context; an ambiguous match returns the occurrence count. Anchors do NOT drift, so you don't need fresh line numbers and they survive concurrent edits. Use newText:\"\" to delete. (2) LINE patches {startLine, endLine, replacement} — 1-based and INCLUSIVE: call getDocument first for line numbers; replace line 5 with {startLine:5,endLine:5}; INSERT before line N (deleting nothing) with {startLine:N,endLine:N-1}; append to an L-line document with {startLine:L+1,endLine:L}. Line numbers are ABSOLUTE and GO STALE after ANY edit — re-call getDocument before further line patches; out-of-range patches are rejected with the current line count. versionTimestamp from getDocument is required for optimistic locking, EXCEPT when dryRun:true. Set dryRun:true to apply the patches and get the resulting text back WITHOUT saving (verify before committing — kills retry loops). Do not edit or delete DIAGRAM/IMAGE marker lines (rejected with guidance) — use dedicated diagram/image tools. To @-mention a person, insert `<!-- REFERENCE: {\"type\":\"user\",\"id\":\"<user_uuid>\",\"label\":\"Name\"} -->`; look up the user_id via listAssignablePrincipals. Mentioned users are notified automatically.",
2820
2837
  "operationId": "editDocument",
2821
2838
  "tags": [
2822
2839
  "documents"
@@ -3862,7 +3879,7 @@
3862
3879
  "/tools/designWhiteboard": {
3863
3880
  "post": {
3864
3881
  "summary": "designWhiteboard",
3865
- "description": "Design a complete, visually polished whiteboard from a natural-language goal using the PREMIUM multi-agent pipeline (the same one the in-app assistant uses): it browses the stencil/icon library, composes the board, renders it, critiques the rendered image, and refines — far better than hand-placing shapes. COST + APPROVAL: this costs 50 credits per board and requires the user's explicit approval. Call it FIRST without `confirm` to get the exact cost + the workspace credit balance; show that to the user and only call again with `confirm: true` once they agree. If they decline (or lack credits), build the board directly with the standard whiteboard tools (addWhiteboardElements / insertWhiteboardDiagram / listWhiteboardStencils) at no extra charge. It runs in the BACKGROUND and returns immediately with a sessionId; the board fills in over 1-3 minutes. The 50 credits are refunded automatically if the design fails on our side.",
3882
+ "description": "Design a complete, visually polished whiteboard from a natural-language goal using the PREMIUM multi-agent pipeline (the same one the in-app assistant uses): it browses the stencil/icon library, composes the board, renders it, critiques the rendered image, and refines — far better than hand-placing shapes. COST + APPROVAL: this costs 50 credits per board and requires the user's explicit approval. Call it FIRST without `confirm` to get the exact cost + the workspace credit balance; show that to the user and only call again with `confirm: true` once they agree. If they decline (or lack credits), build the board directly with the standard whiteboard tools (addWhiteboardElements / insertWhiteboardDiagram / listWhiteboardStencils) at no extra charge. It runs in the BACKGROUND and returns immediately with a sessionId; the board fills in over 1-3 minutes. The 50 credits are refunded automatically if the design fails on our side. Optional `designProfile: 'branded-executive'` instead builds an ON-BRAND, fully-editable McKinsey-style SLIDE DECK themed by the org's brand kit (palette/fonts) — use it when the user wants polished branded business slides; it builds in-process and the board is ready on return. Optional `designProfile: 'illustrated'` instead builds an editable-illustration board: pick it for illustrated, image-based, picture-style, richly-drawn or educational explainer boards (e.g. illustrate photosynthesis, an illustrated diagram of the water cycle, a textbook-style visual). It generates a rich text-free vector illustration and overlays real, editable text labels with leader lines on top. It is gated per organisation; if it is not enabled the call returns a clear message, so fall back to the standard design. Optional `designProfile: 'image'` instead builds a single, polished, on-brand IMAGE board with all the text baked into the picture (no editable shapes): pick 'image' when the user wants a single finished image, poster or infographic they will refine by AI mask edits rather than by moving editable shapes. It is also gated per organisation; if it is not enabled the call returns a clear message.",
3866
3883
  "operationId": "designWhiteboard",
3867
3884
  "tags": [
3868
3885
  "whiteboards"
@@ -3893,6 +3910,22 @@
3893
3910
  "confirm": {
3894
3911
  "type": "boolean",
3895
3912
  "description": "Set true ONLY after the user has approved the 50-credit cost. Leave unset/false on the first call to receive the cost quote + balance."
3913
+ },
3914
+ "designProfile": {
3915
+ "type": "string",
3916
+ "enum": [
3917
+ "standard",
3918
+ "branded-executive",
3919
+ "illustrated",
3920
+ "image",
3921
+ "agentic",
3922
+ "agentic-deck"
3923
+ ],
3924
+ "description": "Optional. 'standard' (default) = the general multi-agent design. 'agentic' = an AI-chat-style agentic slide composer that drives the whiteboard tools and self-corrects from renders, composing ONE polished slide. 'agentic-deck' = the same agentic composer run over a planned storyline, building a multi-slide deck (each slide on its own frame, tiled left to right). 'branded-executive' = an on-brand, McKinsey-style editable SLIDE DECK themed by the org's brand kit (pair with brandKitId, or omit for the org default). 'illustrated' = an editable-illustration board: a rich text-free vector illustration with real editable text labels and leader lines placed on top. 'image' = a single polished, on-brand IMAGE board with all the text baked into the picture (no editable shapes), which the user then refines with AI mask edits. 'illustrated' and 'image' are each gated per organisation; if not enabled the call returns a clear message."
3925
+ },
3926
+ "brandKitId": {
3927
+ "type": "string",
3928
+ "description": "Optional brand kit id (from listBrandKits) to theme a branded-executive deck. If omitted, the org's built-in default is used."
3896
3929
  }
3897
3930
  },
3898
3931
  "required": [
@@ -3977,6 +4010,277 @@
3977
4010
  }
3978
4011
  }
3979
4012
  },
4013
+ "/tools/designComponent": {
4014
+ "post": {
4015
+ "summary": "designComponent",
4016
+ "description": "Design ONE reusable, on-brand SLIDE COMPONENT and add it to the org's component library so every future branded deck (designWhiteboard designProfile:'branded-executive') can use it. This is the self-improving design loop: an agent AUTHORS the component as a declarative template (a gradient/shadow/curve SVG skin + a native editable PPTX shape + reflowing bound-text slots), RENDERS it, a vision critic COMPARES the render to your brief and lists gaps, and it FIXES + re-renders until polished — then validates and stores it. Use it to grow the deck component catalogue beyond the built-ins (e.g. a 'kpi.delta' stat with an up/down arrow, a 'quote.card', a 'logo.strip'). Browse-first: if a component with this `key` already exists it is reused (pass force:true to redesign). Provide example `sampleSlots` so it can lay out real content, and a `projectId` for the small preview board it builds. Returns the stored component, the per-round critique trail, and the preview board id. It uses a few AI calls + renders (no flat credit charge); the new component is then free to reuse forever.",
4017
+ "operationId": "designComponent",
4018
+ "tags": [
4019
+ "uncategorized"
4020
+ ],
4021
+ "requestBody": {
4022
+ "required": false,
4023
+ "content": {
4024
+ "application/json": {
4025
+ "schema": {
4026
+ "type": "object",
4027
+ "properties": {
4028
+ "key": {
4029
+ "type": "string",
4030
+ "description": "The component key, lowercase dotted, e.g. 'kpi.delta'. This is how decks reference it; reused if it already exists."
4031
+ },
4032
+ "title": {
4033
+ "type": "string",
4034
+ "description": "A short human title, e.g. 'KPI with delta arrow'."
4035
+ },
4036
+ "description": {
4037
+ "type": "string",
4038
+ "description": "What the component IS, WHEN to use it, and what it should LOOK like (the richer the better — this drives both the designer and the critic)."
4039
+ },
4040
+ "projectId": {
4041
+ "type": "string",
4042
+ "description": "Project to create the small preview board in (where the render iterations are shown)."
4043
+ },
4044
+ "sampleSlots": {
4045
+ "type": "object",
4046
+ "description": "Example slot content to render with, e.g. { value: '47%', label: 'Revenue growth', delta: '+12 pts' }. The slot keys become the component's editable fields.",
4047
+ "additionalProperties": true
4048
+ },
4049
+ "boxCols": {
4050
+ "type": "number",
4051
+ "description": "Optional width in grid columns (2-12, default 4)."
4052
+ },
4053
+ "boxRows": {
4054
+ "type": "number",
4055
+ "description": "Optional height in grid rows (2-12, default 5)."
4056
+ },
4057
+ "category": {
4058
+ "type": "string",
4059
+ "description": "Optional catalogue category (e.g. 'data', 'narrative', 'comparison')."
4060
+ },
4061
+ "tags": {
4062
+ "type": "array",
4063
+ "items": {
4064
+ "type": "string"
4065
+ },
4066
+ "description": "Optional search tags."
4067
+ },
4068
+ "referenceImageUrl": {
4069
+ "type": "string",
4070
+ "description": "Optional URL of a reference image the component should match; the critic compares the render to it."
4071
+ },
4072
+ "force": {
4073
+ "type": "boolean",
4074
+ "description": "Redesign even if a component with this key already exists (default false = reuse)."
4075
+ }
4076
+ },
4077
+ "required": [
4078
+ "key",
4079
+ "title",
4080
+ "description",
4081
+ "projectId",
4082
+ "sampleSlots"
4083
+ ]
4084
+ }
4085
+ }
4086
+ }
4087
+ },
4088
+ "responses": {
4089
+ "200": {
4090
+ "description": "Tool result (shape varies per tool — refer to the tool's docs for the exact return value).",
4091
+ "content": {
4092
+ "application/json": {
4093
+ "schema": {
4094
+ "type": "object",
4095
+ "additionalProperties": true
4096
+ }
4097
+ }
4098
+ }
4099
+ },
4100
+ "400": {
4101
+ "description": "Validation error.",
4102
+ "content": {
4103
+ "application/json": {
4104
+ "schema": {
4105
+ "$ref": "#/components/schemas/ErrorResponse"
4106
+ }
4107
+ }
4108
+ }
4109
+ },
4110
+ "401": {
4111
+ "description": "Missing or invalid credentials.",
4112
+ "content": {
4113
+ "application/json": {
4114
+ "schema": {
4115
+ "$ref": "#/components/schemas/ErrorResponse"
4116
+ }
4117
+ }
4118
+ }
4119
+ },
4120
+ "403": {
4121
+ "description": "Authenticated but lacking the required permission or feature flag.",
4122
+ "content": {
4123
+ "application/json": {
4124
+ "schema": {
4125
+ "$ref": "#/components/schemas/ErrorResponse"
4126
+ }
4127
+ }
4128
+ }
4129
+ },
4130
+ "404": {
4131
+ "description": "Resource not found.",
4132
+ "content": {
4133
+ "application/json": {
4134
+ "schema": {
4135
+ "$ref": "#/components/schemas/ErrorResponse"
4136
+ }
4137
+ }
4138
+ }
4139
+ },
4140
+ "422": {
4141
+ "description": "Body did not match the tool's input schema.",
4142
+ "content": {
4143
+ "application/json": {
4144
+ "schema": {
4145
+ "$ref": "#/components/schemas/ErrorResponse"
4146
+ }
4147
+ }
4148
+ }
4149
+ },
4150
+ "500": {
4151
+ "description": "Server error.",
4152
+ "content": {
4153
+ "application/json": {
4154
+ "schema": {
4155
+ "$ref": "#/components/schemas/ErrorResponse"
4156
+ }
4157
+ }
4158
+ }
4159
+ }
4160
+ }
4161
+ }
4162
+ },
4163
+ "/tools/editWhiteboardImageRegion": {
4164
+ "post": {
4165
+ "summary": "editWhiteboardImageRegion",
4166
+ "description": "Mask-edit (inpaint) one region of an image element on a whiteboard. Given the target image element id and a paint MASK (a PNG where WHITE marks the area to regenerate and BLACK is kept), it regenerates only the masked region using the prompt and replaces the image IN PLACE (same position + size). This is mainly used by the in-app image-board mask editor for boards designed with designProfile:'image'. It costs a small flat credit charge (refunded automatically if the edit fails on our side). It is gated per organisation behind the same 'whiteboard_design_image' feature as the image design profile; if that is not enabled the call returns a clear message.",
4167
+ "operationId": "editWhiteboardImageRegion",
4168
+ "tags": [
4169
+ "whiteboards"
4170
+ ],
4171
+ "requestBody": {
4172
+ "required": false,
4173
+ "content": {
4174
+ "application/json": {
4175
+ "schema": {
4176
+ "type": "object",
4177
+ "properties": {
4178
+ "documentId": {
4179
+ "type": "string",
4180
+ "description": "The whiteboard document that holds the image element."
4181
+ },
4182
+ "elementId": {
4183
+ "type": "string",
4184
+ "description": "The id of the image element on the board to edit (from getWhiteboard includeElements=true)."
4185
+ },
4186
+ "maskBase64": {
4187
+ "type": "string",
4188
+ "description": "A PNG mask (base64, with or without a data: prefix) the same shape as the image. WHITE pixels are regenerated; BLACK pixels are preserved."
4189
+ },
4190
+ "prompt": {
4191
+ "type": "string",
4192
+ "description": "What to put in the masked area, in plain language (e.g. 'replace the car with a red bicycle')."
4193
+ },
4194
+ "strength": {
4195
+ "type": "number",
4196
+ "description": "Optional 0..1 — how far the regenerated area may diverge from the original. Ignored by FLUX Fill (which balances via the prompt); leave unset unless using a non-Fill inpaint model."
4197
+ }
4198
+ },
4199
+ "required": [
4200
+ "documentId",
4201
+ "elementId",
4202
+ "maskBase64",
4203
+ "prompt"
4204
+ ]
4205
+ }
4206
+ }
4207
+ }
4208
+ },
4209
+ "responses": {
4210
+ "200": {
4211
+ "description": "Tool result (shape varies per tool — refer to the tool's docs for the exact return value).",
4212
+ "content": {
4213
+ "application/json": {
4214
+ "schema": {
4215
+ "type": "object",
4216
+ "additionalProperties": true
4217
+ }
4218
+ }
4219
+ }
4220
+ },
4221
+ "400": {
4222
+ "description": "Validation error.",
4223
+ "content": {
4224
+ "application/json": {
4225
+ "schema": {
4226
+ "$ref": "#/components/schemas/ErrorResponse"
4227
+ }
4228
+ }
4229
+ }
4230
+ },
4231
+ "401": {
4232
+ "description": "Missing or invalid credentials.",
4233
+ "content": {
4234
+ "application/json": {
4235
+ "schema": {
4236
+ "$ref": "#/components/schemas/ErrorResponse"
4237
+ }
4238
+ }
4239
+ }
4240
+ },
4241
+ "403": {
4242
+ "description": "Authenticated but lacking the required permission or feature flag.",
4243
+ "content": {
4244
+ "application/json": {
4245
+ "schema": {
4246
+ "$ref": "#/components/schemas/ErrorResponse"
4247
+ }
4248
+ }
4249
+ }
4250
+ },
4251
+ "404": {
4252
+ "description": "Resource not found.",
4253
+ "content": {
4254
+ "application/json": {
4255
+ "schema": {
4256
+ "$ref": "#/components/schemas/ErrorResponse"
4257
+ }
4258
+ }
4259
+ }
4260
+ },
4261
+ "422": {
4262
+ "description": "Body did not match the tool's input schema.",
4263
+ "content": {
4264
+ "application/json": {
4265
+ "schema": {
4266
+ "$ref": "#/components/schemas/ErrorResponse"
4267
+ }
4268
+ }
4269
+ }
4270
+ },
4271
+ "500": {
4272
+ "description": "Server error.",
4273
+ "content": {
4274
+ "application/json": {
4275
+ "schema": {
4276
+ "$ref": "#/components/schemas/ErrorResponse"
4277
+ }
4278
+ }
4279
+ }
4280
+ }
4281
+ }
4282
+ }
4283
+ },
3980
4284
  "/tools/createWhiteboard": {
3981
4285
  "post": {
3982
4286
  "summary": "createWhiteboard",
@@ -4471,9 +4775,11 @@
4471
4775
  "doodle",
4472
4776
  "frame",
4473
4777
  "image",
4474
- "stencil"
4778
+ "stencil",
4779
+ "chart",
4780
+ "table"
4475
4781
  ],
4476
- "description": "Element kind. 'sticky' = a first-class sticky/post-it note (solid fill + auto-fitting bound label; set text + backgroundColor) — use this for sticky notes, NOT a stencil. 'stencil' = a hand-drawn library graphic from listWhiteboardStencils, of kind 'symbol' (one atomic labelled node — flowchart box, BPMN task, org node: set `id` + `text` + width/height, text auto-fits, connect arrows via start/end {id}) or 'template' (a multi-element layout — Alerts, Forms, Tables, Charts: place whole, then customise its returned children by id; do NOT set a single `text`). Set `stencil` (fuzzy name, one call) or `stencilKey` (exact). 'image' with `iconPath` = a software-architecture icon from listArchitectureIcons. Reserve rectangle/ellipse/diamond for when no standard form fits."
4782
+ "description": "Element kind. 'sticky' = a first-class sticky/post-it note (solid fill + auto-fitting bound label; set text + backgroundColor) — use this for sticky notes, NOT a stencil. 'stencil' = a hand-drawn library graphic from listWhiteboardStencils, of kind 'symbol' (one atomic labelled node — flowchart box, BPMN task, org node: set `id` + `text` + width/height, text auto-fits, connect arrows via start/end {id}) or 'template' (a multi-element layout — Alerts, Forms, Tables, Charts: place whole, then customise its returned children by id; do NOT set a single `text`). Set `stencil` (fuzzy name, one call) or `stencilKey` (exact). 'image' with `iconPath` = a software-architecture icon from listArchitectureIcons. 'chart' = a NATIVE, fully-editable data chart (column/bar/line/area/pie/donut/scatter/sparkline/combo/stackedColumn/groupedColumn/radar/gauge) built from real Excalidraw shapes — bars/lines/wedges plus axes, gridlines and a legend — for ANY data, metric, KPI, trend, comparison or breakdown: set chartType + series (+ categories + options). ALWAYS prefer a 'chart' over hand-drawing bars/lines or a wireframe 'chart' stencil. 'table' = a NATIVE, fully-editable GRID (real rectangles + bound, word-wrapped cells, auto-sized columns + rows, a header band, optional zebra striping / per-column colours) for ANY tabular data, list or matrix — set columns + rows (+ options). ALWAYS prefer a 'table' over hand-drawing a grid of boxes. Reserve rectangle/ellipse/diamond for when no standard form fits."
4477
4783
  },
4478
4784
  "stencil": {
4479
4785
  "type": "string",
@@ -4529,23 +4835,127 @@
4529
4835
  },
4530
4836
  "text": {
4531
4837
  "type": "string",
4532
- "description": "Label/caption. On a shape it's a centered auto-wrapped bound label (prefer over a separate type:'text'); on a type:'sticky' it's the note text; on a type:'stencil' of kind 'symbol' it fills + re-fits its single label (IGNORED for 'template' stencils — customise their children by id instead)."
4838
+ "description": "Label/caption. To label a shape, set `text` on the SHAPE itself — it becomes a BOUND label that the server word-wraps with real font metrics, auto-fits, and positions (centred by default) INSIDE the shape. Never drop a separate type:'text' element on top of a shape, and never hand-compute a label's x/y/width — the server does the geometry (like the editor does when you type into a shape). On a type:'sticky' it's the note text; on a type:'stencil' of kind 'symbol' it fills + re-fits its single label (IGNORED for 'template' stencils — customise their children by id instead). Use a standalone type:'text' only for free-floating text that belongs to no shape."
4533
4839
  },
4534
4840
  "fitText": {
4535
4841
  "type": "boolean",
4536
4842
  "description": "Auto-shrink the bound label's font size so the text always fits inside the shape — no overflow (default true). Set false to keep your exact fontSize even if it spills."
4537
4843
  },
4538
- "backgroundColor": {
4844
+ "fontSize": {
4845
+ "type": "number",
4846
+ "description": "Text size in px. Establish HIERARCHY: titles ~28-40, section headings ~22-28, body/labels ~16-20. Applies to a standalone text, a shape's bound label, a sticky, or an icon caption. Bound labels still auto-shrink to fit unless fitText:false."
4847
+ },
4848
+ "fontFamily": {
4539
4849
  "type": "string",
4540
- "description": "Fill colour: a name ('blue'/'green'/'yellow'/'pink'/'violet'/'orange'/'teal'/…) or a hex value."
4850
+ "description": "Font style: 'hand-drawn' (sketchy Excalidraw look, the default), 'sans' (clean/professional — use for business, dashboards, formal diagrams), or 'code' (monospace). Pass this to control the look instead of leaving everything hand-drawn."
4541
4851
  },
4542
- "start": {
4543
- "type": "object",
4544
- "description": "For arrows/lines: { id } of the source shape (auto-clips to the edge + auto-routes around shapes in between)."
4852
+ "strokeColor": {
4853
+ "type": "string",
4854
+ "description": "TEXT colour (for text/labels) or line/border colour (for shapes, arrows, lines, doodles): a name ('blue'/'green'/'red'/'orange'/'violet'/'teal'/…) or a hex value. Use a brand or theme colour for titles/emphasis; default is near-black."
4855
+ },
4856
+ "textAlign": {
4857
+ "type": "string",
4858
+ "enum": [
4859
+ "left",
4860
+ "center",
4861
+ "right"
4862
+ ],
4863
+ "description": "Horizontal alignment of the text within its box — the equivalent of the toolbar's align buttons. Bound labels default to 'center'."
4864
+ },
4865
+ "verticalAlign": {
4866
+ "type": "string",
4867
+ "enum": [
4868
+ "top",
4869
+ "middle",
4870
+ "bottom"
4871
+ ],
4872
+ "description": "Vertical alignment of a bound label inside its shape (toolbar parity). Defaults to 'middle' (centred)."
4873
+ },
4874
+ "backgroundColor": {
4875
+ "type": "string",
4876
+ "description": "Fill colour: a name ('blue'/'green'/'yellow'/'pink'/'violet'/'orange'/'teal'/…) or a hex value."
4877
+ },
4878
+ "start": {
4879
+ "type": "object",
4880
+ "description": "For arrows/lines: { id } of the source shape (auto-clips to the edge + auto-routes around shapes in between)."
4545
4881
  },
4546
4882
  "end": {
4547
4883
  "type": "object",
4548
4884
  "description": "For arrows/lines: { id } of the target shape."
4885
+ },
4886
+ "title": {
4887
+ "type": "string",
4888
+ "description": "For type:'chart' — the chart's title, drawn at the top of the chart."
4889
+ },
4890
+ "chartType": {
4891
+ "type": "string",
4892
+ "enum": [
4893
+ "column",
4894
+ "bar",
4895
+ "line",
4896
+ "area",
4897
+ "pie",
4898
+ "donut",
4899
+ "scatter",
4900
+ "sparkline",
4901
+ "combo",
4902
+ "stackedColumn",
4903
+ "groupedColumn",
4904
+ "radar",
4905
+ "gauge"
4906
+ ],
4907
+ "description": "For type:'chart' — the chart family. column=vertical bars (default), bar=horizontal bars, line/area=trends, pie/donut=parts-of-whole, scatter=points, sparkline=tiny inline trend (no axes/legend), combo=bars+line (dual axis via a series with axis:'right'), stackedColumn/groupedColumn=multi-series, radar, gauge."
4908
+ },
4909
+ "categories": {
4910
+ "type": "array",
4911
+ "items": {
4912
+ "type": "string"
4913
+ },
4914
+ "description": "For type:'chart' — x-axis category labels, e.g. ['Jan','Feb','Mar','Apr']."
4915
+ },
4916
+ "series": {
4917
+ "type": "array",
4918
+ "description": "For type:'chart' — one or more data series. Each: { name:string, data:number[], type?:'bar'|'line'|'area' (per-series, for combo), color?:string (hex), axis?:'left'|'right' (dual axis), markers?:boolean (line point markers) }. For pie/donut use ONE series whose data maps to categories.",
4919
+ "items": {
4920
+ "type": "object",
4921
+ "additionalProperties": true
4922
+ }
4923
+ },
4924
+ "options": {
4925
+ "type": "object",
4926
+ "description": "For type:'chart' — { legend?:boolean|'top'|'bottom'|'right', gridlines?:boolean|'x'|'y'|'both'|'none', dataLabels?:boolean, yAxis?:boolean, xAxis?:boolean, yMin?:number, yMax?:number, smooth?:boolean, valueFormat?:'%'|'$'|'k', palette?:string[] (hex), donutHole?:number }. For type:'table' — { headerFill?:string (hex), headerTextColor?:string, zebra?:boolean, rowFill?:string, altRowFill?:string, columnColors?:string[] (per-column hex), fontSize?:number, headerFontSize?:number, borderColor?:string, align?:'left'|'center'|'right' }.",
4927
+ "additionalProperties": true
4928
+ },
4929
+ "columns": {
4930
+ "type": "array",
4931
+ "description": "For type:'table' — column headers: string[] (e.g. ['Task','Owner','Status']) or [{ header:string, width?:number, align?:'left'|'center'|'right' }].",
4932
+ "items": {
4933
+ "oneOf": [
4934
+ {
4935
+ "type": "string"
4936
+ },
4937
+ {
4938
+ "type": "object"
4939
+ }
4940
+ ]
4941
+ }
4942
+ },
4943
+ "rows": {
4944
+ "type": "array",
4945
+ "description": "For type:'table' — data rows; each row is an array of cell values (string|number) aligned to columns, e.g. [['T-1','Sam','Done'],['T-2','Lee','WIP']].",
4946
+ "items": {
4947
+ "type": "array",
4948
+ "items": {
4949
+ "oneOf": [
4950
+ {
4951
+ "type": "string"
4952
+ },
4953
+ {
4954
+ "type": "number"
4955
+ }
4956
+ ]
4957
+ }
4958
+ }
4549
4959
  }
4550
4960
  },
4551
4961
  "required": [
@@ -7502,7 +7912,7 @@
7502
7912
  "/tools/listImprovements": {
7503
7913
  "post": {
7504
7914
  "summary": "listImprovements",
7505
- "description": "List improvements in a project. Supports filtering by status, type, priority, and query.",
7915
+ "description": "List AND grep improvements in a project. `query` searches the title, friendlyId and problem statement, not just the title (substring by default; set isRegex:true for a regular expression, caseSensitive:true for exact case). Supports filtering by status, type, priority. For ranked semantic + text search use searchImprovements.",
7506
7916
  "operationId": "listImprovements",
7507
7917
  "tags": [
7508
7918
  "improvements"
@@ -7555,7 +7965,15 @@
7555
7965
  },
7556
7966
  "query": {
7557
7967
  "type": "string",
7558
- "description": "Search title, friendly_id, problem_statement."
7968
+ "description": "Grep across title, friendlyId and problem_statement. Substring by default; a regular expression when isRegex:true; case-insensitive unless caseSensitive:true."
7969
+ },
7970
+ "isRegex": {
7971
+ "type": "boolean",
7972
+ "description": "Treat query as a regular expression (grep -E), e.g. \"ACME-\\d+\". Default false (literal substring)."
7973
+ },
7974
+ "caseSensitive": {
7975
+ "type": "boolean",
7976
+ "description": "Case-sensitive matching. Default false."
7559
7977
  },
7560
7978
  "sortField": {
7561
7979
  "type": "string",
@@ -9529,7 +9947,7 @@
9529
9947
  "/tools/searchImprovements": {
9530
9948
  "post": {
9531
9949
  "summary": "searchImprovements",
9532
- "description": "Search improvements using hybrid text + semantic search. Returns ranked results.",
9950
+ "description": "Locate any artefact (document / whiteboard / diagram / plan / task / improvement / compliance) by name or friendly id — AND ranked semantic search over improvements.\n\n• CROSS-ARTEFACT FINDER MODE (pass `types`): matches title + friendly id (e.g. \"DOC-123\", \"WBD-9\", \"PLN-4\", \"TAS-7\", \"IMP-2\") + description across every artefact type. Returns a typed navigable list ({ artefacts: [{ result_type, id, friendly_id, title, snippet, document_id, project_id, href }] }). This is the tool to use to find an artefact by its name or id — NOT kg_search (which retrieves knowledge from inside content). Pass types:[\"document\",\"whiteboard\",\"plan\",\"task\",\"improvement\",\"compliance\"] (or a subset) to search those types; an empty or all-inclusive list searches everything.\n\n• IMPROVEMENT SEMANTIC MODE (omit `types`): hybrid full-text + vector search over improvements only. Returns ranked { improvements }.",
9533
9951
  "operationId": "searchImprovements",
9534
9952
  "tags": [
9535
9953
  "improvements"
@@ -9543,7 +9961,22 @@
9543
9961
  "properties": {
9544
9962
  "query": {
9545
9963
  "type": "string",
9546
- "description": "Search query."
9964
+ "description": "Search query — a name fragment or a friendly id."
9965
+ },
9966
+ "types": {
9967
+ "type": "array",
9968
+ "items": {
9969
+ "type": "string",
9970
+ "enum": [
9971
+ "document",
9972
+ "whiteboard",
9973
+ "improvement",
9974
+ "task",
9975
+ "plan",
9976
+ "compliance"
9977
+ ]
9978
+ },
9979
+ "description": "Switches on the cross-artefact finder. Artefact types to search (subset of document, whiteboard, improvement, task, plan, compliance). Empty / all = every type. Omit entirely for the improvements-only semantic search."
9547
9980
  },
9548
9981
  "projectId": {
9549
9982
  "type": "string",
@@ -9555,7 +9988,11 @@
9555
9988
  },
9556
9989
  "limit": {
9557
9990
  "type": "number",
9558
- "description": "Max results (default 20, max 50)."
9991
+ "description": "Max results (default 20 semantic / 30 cross-artefact, max 50)."
9992
+ },
9993
+ "offset": {
9994
+ "type": "number",
9995
+ "description": "Pagination offset (cross-artefact mode)."
9559
9996
  }
9560
9997
  },
9561
9998
  "required": [
@@ -9643,7 +10080,7 @@
9643
10080
  "/tools/listPlans": {
9644
10081
  "post": {
9645
10082
  "summary": "listPlans",
9646
- "description": "List plans in a project. Supports filtering by status, priority, and query.",
10083
+ "description": "List AND grep plans in a project. `query` searches the title, friendlyId and description, not just the title (substring by default; set isRegex:true for a regular expression, caseSensitive:true for exact case). Supports filtering by status and priority.",
9647
10084
  "operationId": "listPlans",
9648
10085
  "tags": [
9649
10086
  "plans"
@@ -9668,7 +10105,15 @@
9668
10105
  },
9669
10106
  "query": {
9670
10107
  "type": "string",
9671
- "description": "Search title, friendly_id, description."
10108
+ "description": "Grep across title, friendlyId and description. Substring by default; a regular expression when isRegex:true; case-insensitive unless caseSensitive:true."
10109
+ },
10110
+ "isRegex": {
10111
+ "type": "boolean",
10112
+ "description": "Treat query as a regular expression (grep -E), e.g. \"ACME-\\d+\". Default false (literal substring)."
10113
+ },
10114
+ "caseSensitive": {
10115
+ "type": "boolean",
10116
+ "description": "Case-sensitive matching. Default false."
9672
10117
  },
9673
10118
  "sortField": {
9674
10119
  "type": "string",
@@ -11532,7 +11977,7 @@
11532
11977
  "/tools/listTasks": {
11533
11978
  "post": {
11534
11979
  "summary": "listTasks",
11535
- "description": "List tasks in a plan. Supports filtering by status, priority, phaseId, and query.",
11980
+ "description": "List AND grep tasks in a plan. `query` searches the title, friendlyId and description, not just the title (substring by default; set isRegex:true for a regular expression, caseSensitive:true for exact case). Supports filtering by status, priority and phaseId.",
11536
11981
  "operationId": "listTasks",
11537
11982
  "tags": [
11538
11983
  "plans"
@@ -11561,7 +12006,15 @@
11561
12006
  },
11562
12007
  "query": {
11563
12008
  "type": "string",
11564
- "description": "Search title and friendly_id."
12009
+ "description": "Grep across title, friendlyId and description. Substring by default; a regular expression when isRegex:true; case-insensitive unless caseSensitive:true."
12010
+ },
12011
+ "isRegex": {
12012
+ "type": "boolean",
12013
+ "description": "Treat query as a regular expression (grep -E), e.g. \"ACME-\\d+\". Default false (literal substring)."
12014
+ },
12015
+ "caseSensitive": {
12016
+ "type": "boolean",
12017
+ "description": "Case-sensitive matching. Default false."
11565
12018
  },
11566
12019
  "sortField": {
11567
12020
  "type": "string",
@@ -13179,7 +13632,7 @@
13179
13632
  "/tools/kg_search": {
13180
13633
  "post": {
13181
13634
  "summary": "kg_search",
13182
- "description": "Unified Knowledge Graph retrieval. PICK THE MODE THAT FITS THE QUERY:\n\n• mode='local' (default) — for SPECIFIC factual questions (\"what does §15 say about deposits?\", \"who is the Chief Counsel?\"). FTS+vector RRF over individual document chunks. Returns precise excerpts with citations.\n\n• mode='global' — for THEMATIC / OVERVIEW / SUMMARY questions (\"what are the main themes\", \"give me an overview of the project\", \"what topics does this cover\"). Returns Louvain community summaries + curated wiki pages — far better than 'local' for big-picture queries because community summaries already aggregate across many chunks. ALWAYS PREFER over 'local' when the user asks for themes / summary / overview / topic landscape.\n\n• mode='graph' — for RELATIONSHIP questions (\"what's connected to entity X?\", \"who cites Section 5?\"). 1-hop entity-neighbourhood walk. Pass query OR srcEntityId.\n\n• mode='path' — for CONNECTION questions (\"how does X relate to Y?\"). Shortest path between two entities. Pass srcEntityId AND dstEntityId.\n\n• mode='ppr' — for MULTI-HOP discovery (\"what's relevant to X, even indirectly?\"). Personalised PageRank over AUTHORED-vs-EXTRACTED weighted edges, seeded by query-similar entities. Best when 'local' returns too few results and the answer requires walking through several entity hops.\n\nQuick decision tree:\n- User asks for an overview/summary/themes → 'global'\n- User asks a specific question with a clear answer → 'local'\n- User asks 'how is X connected to Y' → 'path' (with both entity IDs)\n- User asks 'what's near entity X' → 'graph' (with srcEntityId)\n- 'local' returned nothing useful and the question is broad → retry with 'ppr'",
13635
+ "description": "Unified Knowledge Graph KNOWLEDGE retrieval — facts, themes and relationships from INSIDE document CONTENT. This is NOT an artefact finder: do NOT use it to locate a document / whiteboard / diagram / plan / task / improvement by its TITLE or friendly id (e.g. \"DOC-123\", \"find the GTM plan\"). For locating an artefact by name or id use listDocuments / listWhiteboards / listPlans / listTasks / searchImprovements (they match title + friendly id). Use kg_search only to ANSWER A QUESTION from the knowledge contained in the artefacts.\n\nPICK THE MODE THAT FITS THE QUERY:\n\n• mode='local' (default) — for SPECIFIC factual questions (\"what does §15 say about deposits?\", \"who is the Chief Counsel?\"). FTS+vector RRF over individual document chunks. Returns precise excerpts with citations.\n\n• mode='global' — for THEMATIC / OVERVIEW / SUMMARY questions (\"what are the main themes\", \"give me an overview of the project\", \"what topics does this cover\"). Returns Louvain community summaries + curated wiki pages — far better than 'local' for big-picture queries because community summaries already aggregate across many chunks. ALWAYS PREFER over 'local' when the user asks for themes / summary / overview / topic landscape.\n\n• mode='graph' — for RELATIONSHIP questions (\"what's connected to entity X?\", \"who cites Section 5?\"). 1-hop entity-neighbourhood walk. Pass query OR srcEntityId.\n\n• mode='path' — for CONNECTION questions (\"how does X relate to Y?\"). Shortest path between two entities. Pass srcEntityId AND dstEntityId.\n\n• mode='ppr' — for MULTI-HOP discovery (\"what's relevant to X, even indirectly?\"). Personalised PageRank over AUTHORED-vs-EXTRACTED weighted edges, seeded by query-similar entities. Best when 'local' returns too few results and the answer requires walking through several entity hops.\n\nQuick decision tree:\n- User asks for an overview/summary/themes → 'global'\n- User asks a specific question with a clear answer → 'local'\n- User asks 'how is X connected to Y' → 'path' (with both entity IDs)\n- User asks 'what's near entity X' → 'graph' (with srcEntityId)\n- 'local' returned nothing useful and the question is broad → retry with 'ppr'",
13183
13636
  "operationId": "kg_search",
13184
13637
  "tags": [
13185
13638
  "knowledge_graph"
@@ -21585,6 +22038,362 @@
21585
22038
  }
21586
22039
  }
21587
22040
  },
22041
+ "/tools/createBrandKit": {
22042
+ "post": {
22043
+ "summary": "createBrandKit",
22044
+ "description": "Create a per-org BRAND KIT (palette/fonts/logo) that themes branded-executive slides and document exports. Build it from one of: a `logoUrl` (AUTO-EXTRACT palette/fonts via the vision model), an `officeUrl` (an existing .pptx/.docx — extracts theme colours, fonts, logo, watermark + embedded font files), or explicit `tokens`. Auth: can_admin_org. Tiered: free 0, pro 1, enterprise unlimited. Optionally set it as the default at a scope in one call.",
22045
+ "operationId": "createBrandKit",
22046
+ "tags": [
22047
+ "uncategorized"
22048
+ ],
22049
+ "requestBody": {
22050
+ "required": false,
22051
+ "content": {
22052
+ "application/json": {
22053
+ "schema": {
22054
+ "type": "object",
22055
+ "properties": {
22056
+ "organizationId": {
22057
+ "type": "string",
22058
+ "description": "Org that owns the kit."
22059
+ },
22060
+ "name": {
22061
+ "type": "string",
22062
+ "description": "Display name (e.g. the brand/company name)."
22063
+ },
22064
+ "logoUrl": {
22065
+ "type": "string",
22066
+ "description": "Image URL of the logo to extract palette/fonts from (PNG/JPG/SVG). Omit if passing officeUrl or tokens."
22067
+ },
22068
+ "officeUrl": {
22069
+ "type": "string",
22070
+ "description": "URL of an existing .pptx or .docx to extract the brand from (theme colours + fonts + logo + watermark + embedded fonts). Max 25MB. Omit if passing logoUrl or tokens."
22071
+ },
22072
+ "tokens": {
22073
+ "type": "object",
22074
+ "description": "Explicit DTCG brand tokens { color:{brand:{primary,primaryText,ink,bg,surface,muted,border,positive,warning,negative}}, font:{heading,body} }. Omit to extract from logoUrl/officeUrl.",
22075
+ "additionalProperties": true
22076
+ },
22077
+ "guidance": {
22078
+ "type": "string",
22079
+ "description": "Optional extra guidance for the extractor (e.g. 'use the teal, not the grey')."
22080
+ },
22081
+ "setDefaultScope": {
22082
+ "type": "string",
22083
+ "enum": [
22084
+ "organization",
22085
+ "workspace",
22086
+ "project"
22087
+ ],
22088
+ "description": "Optionally set the new kit as default at this scope."
22089
+ },
22090
+ "setDefaultScopeId": {
22091
+ "type": "string",
22092
+ "description": "Workspace/project id when setDefaultScope is workspace/project."
22093
+ }
22094
+ },
22095
+ "required": [
22096
+ "organizationId",
22097
+ "name"
22098
+ ]
22099
+ }
22100
+ }
22101
+ }
22102
+ },
22103
+ "responses": {
22104
+ "200": {
22105
+ "description": "Tool result (shape varies per tool — refer to the tool's docs for the exact return value).",
22106
+ "content": {
22107
+ "application/json": {
22108
+ "schema": {
22109
+ "type": "object",
22110
+ "additionalProperties": true
22111
+ }
22112
+ }
22113
+ }
22114
+ },
22115
+ "400": {
22116
+ "description": "Validation error.",
22117
+ "content": {
22118
+ "application/json": {
22119
+ "schema": {
22120
+ "$ref": "#/components/schemas/ErrorResponse"
22121
+ }
22122
+ }
22123
+ }
22124
+ },
22125
+ "401": {
22126
+ "description": "Missing or invalid credentials.",
22127
+ "content": {
22128
+ "application/json": {
22129
+ "schema": {
22130
+ "$ref": "#/components/schemas/ErrorResponse"
22131
+ }
22132
+ }
22133
+ }
22134
+ },
22135
+ "403": {
22136
+ "description": "Authenticated but lacking the required permission or feature flag.",
22137
+ "content": {
22138
+ "application/json": {
22139
+ "schema": {
22140
+ "$ref": "#/components/schemas/ErrorResponse"
22141
+ }
22142
+ }
22143
+ }
22144
+ },
22145
+ "404": {
22146
+ "description": "Resource not found.",
22147
+ "content": {
22148
+ "application/json": {
22149
+ "schema": {
22150
+ "$ref": "#/components/schemas/ErrorResponse"
22151
+ }
22152
+ }
22153
+ }
22154
+ },
22155
+ "422": {
22156
+ "description": "Body did not match the tool's input schema.",
22157
+ "content": {
22158
+ "application/json": {
22159
+ "schema": {
22160
+ "$ref": "#/components/schemas/ErrorResponse"
22161
+ }
22162
+ }
22163
+ }
22164
+ },
22165
+ "500": {
22166
+ "description": "Server error.",
22167
+ "content": {
22168
+ "application/json": {
22169
+ "schema": {
22170
+ "$ref": "#/components/schemas/ErrorResponse"
22171
+ }
22172
+ }
22173
+ }
22174
+ }
22175
+ }
22176
+ }
22177
+ },
22178
+ "/tools/listBrandKits": {
22179
+ "post": {
22180
+ "summary": "listBrandKits",
22181
+ "description": "List an organisation's BRAND KITS (palette/fonts/logo), newest first. Use a returned `id` as brandKitId for a design call or setDefaultBrandKit. Auth: can_admin_org.",
22182
+ "operationId": "listBrandKits",
22183
+ "tags": [
22184
+ "uncategorized"
22185
+ ],
22186
+ "requestBody": {
22187
+ "required": false,
22188
+ "content": {
22189
+ "application/json": {
22190
+ "schema": {
22191
+ "type": "object",
22192
+ "properties": {
22193
+ "organizationId": {
22194
+ "type": "string"
22195
+ }
22196
+ },
22197
+ "required": [
22198
+ "organizationId"
22199
+ ]
22200
+ }
22201
+ }
22202
+ }
22203
+ },
22204
+ "responses": {
22205
+ "200": {
22206
+ "description": "Tool result (shape varies per tool — refer to the tool's docs for the exact return value).",
22207
+ "content": {
22208
+ "application/json": {
22209
+ "schema": {
22210
+ "type": "object",
22211
+ "additionalProperties": true
22212
+ }
22213
+ }
22214
+ }
22215
+ },
22216
+ "400": {
22217
+ "description": "Validation error.",
22218
+ "content": {
22219
+ "application/json": {
22220
+ "schema": {
22221
+ "$ref": "#/components/schemas/ErrorResponse"
22222
+ }
22223
+ }
22224
+ }
22225
+ },
22226
+ "401": {
22227
+ "description": "Missing or invalid credentials.",
22228
+ "content": {
22229
+ "application/json": {
22230
+ "schema": {
22231
+ "$ref": "#/components/schemas/ErrorResponse"
22232
+ }
22233
+ }
22234
+ }
22235
+ },
22236
+ "403": {
22237
+ "description": "Authenticated but lacking the required permission or feature flag.",
22238
+ "content": {
22239
+ "application/json": {
22240
+ "schema": {
22241
+ "$ref": "#/components/schemas/ErrorResponse"
22242
+ }
22243
+ }
22244
+ }
22245
+ },
22246
+ "404": {
22247
+ "description": "Resource not found.",
22248
+ "content": {
22249
+ "application/json": {
22250
+ "schema": {
22251
+ "$ref": "#/components/schemas/ErrorResponse"
22252
+ }
22253
+ }
22254
+ }
22255
+ },
22256
+ "422": {
22257
+ "description": "Body did not match the tool's input schema.",
22258
+ "content": {
22259
+ "application/json": {
22260
+ "schema": {
22261
+ "$ref": "#/components/schemas/ErrorResponse"
22262
+ }
22263
+ }
22264
+ }
22265
+ },
22266
+ "500": {
22267
+ "description": "Server error.",
22268
+ "content": {
22269
+ "application/json": {
22270
+ "schema": {
22271
+ "$ref": "#/components/schemas/ErrorResponse"
22272
+ }
22273
+ }
22274
+ }
22275
+ }
22276
+ }
22277
+ }
22278
+ },
22279
+ "/tools/setDefaultBrandKit": {
22280
+ "post": {
22281
+ "summary": "setDefaultBrandKit",
22282
+ "description": "Set or clear the default BRAND KIT at a scope: organization, workspace, or project. Defaults cascade most-specific-first (a per-board/document override beats project beats workspace beats organization). Pass brandKitId:null to clear. Auth: org owner/admin.",
22283
+ "operationId": "setDefaultBrandKit",
22284
+ "tags": [
22285
+ "uncategorized"
22286
+ ],
22287
+ "requestBody": {
22288
+ "required": false,
22289
+ "content": {
22290
+ "application/json": {
22291
+ "schema": {
22292
+ "type": "object",
22293
+ "properties": {
22294
+ "scope": {
22295
+ "type": "string",
22296
+ "enum": [
22297
+ "organization",
22298
+ "workspace",
22299
+ "project"
22300
+ ]
22301
+ },
22302
+ "scopeId": {
22303
+ "type": "string",
22304
+ "description": "The org/workspace/project id for the chosen scope."
22305
+ },
22306
+ "brandKitId": {
22307
+ "type": [
22308
+ "string",
22309
+ "null"
22310
+ ],
22311
+ "description": "Brand kit to make default, or null to clear."
22312
+ }
22313
+ },
22314
+ "required": [
22315
+ "scope",
22316
+ "scopeId"
22317
+ ]
22318
+ }
22319
+ }
22320
+ }
22321
+ },
22322
+ "responses": {
22323
+ "200": {
22324
+ "description": "Tool result (shape varies per tool — refer to the tool's docs for the exact return value).",
22325
+ "content": {
22326
+ "application/json": {
22327
+ "schema": {
22328
+ "type": "object",
22329
+ "additionalProperties": true
22330
+ }
22331
+ }
22332
+ }
22333
+ },
22334
+ "400": {
22335
+ "description": "Validation error.",
22336
+ "content": {
22337
+ "application/json": {
22338
+ "schema": {
22339
+ "$ref": "#/components/schemas/ErrorResponse"
22340
+ }
22341
+ }
22342
+ }
22343
+ },
22344
+ "401": {
22345
+ "description": "Missing or invalid credentials.",
22346
+ "content": {
22347
+ "application/json": {
22348
+ "schema": {
22349
+ "$ref": "#/components/schemas/ErrorResponse"
22350
+ }
22351
+ }
22352
+ }
22353
+ },
22354
+ "403": {
22355
+ "description": "Authenticated but lacking the required permission or feature flag.",
22356
+ "content": {
22357
+ "application/json": {
22358
+ "schema": {
22359
+ "$ref": "#/components/schemas/ErrorResponse"
22360
+ }
22361
+ }
22362
+ }
22363
+ },
22364
+ "404": {
22365
+ "description": "Resource not found.",
22366
+ "content": {
22367
+ "application/json": {
22368
+ "schema": {
22369
+ "$ref": "#/components/schemas/ErrorResponse"
22370
+ }
22371
+ }
22372
+ }
22373
+ },
22374
+ "422": {
22375
+ "description": "Body did not match the tool's input schema.",
22376
+ "content": {
22377
+ "application/json": {
22378
+ "schema": {
22379
+ "$ref": "#/components/schemas/ErrorResponse"
22380
+ }
22381
+ }
22382
+ }
22383
+ },
22384
+ "500": {
22385
+ "description": "Server error.",
22386
+ "content": {
22387
+ "application/json": {
22388
+ "schema": {
22389
+ "$ref": "#/components/schemas/ErrorResponse"
22390
+ }
22391
+ }
22392
+ }
22393
+ }
22394
+ }
22395
+ }
22396
+ },
21588
22397
  "/tools/updateOrgFeatureFlags": {
21589
22398
  "post": {
21590
22399
  "summary": "updateOrgFeatureFlags",
@@ -21769,35 +22578,55 @@
21769
22578
  "object",
21770
22579
  "array",
21771
22580
  "null"
21772
- ]
22581
+ ],
22582
+ "items": {
22583
+ "type": "string"
22584
+ },
22585
+ "description": "Visible column ids (string[]) when an array."
21773
22586
  },
21774
22587
  "column_widths": {
21775
22588
  "type": [
21776
22589
  "object",
21777
22590
  "array",
21778
22591
  "null"
21779
- ]
22592
+ ],
22593
+ "items": {
22594
+ "type": "number"
22595
+ },
22596
+ "description": "Column widths — a { colId: px } map, or a number[] when an array."
21780
22597
  },
21781
22598
  "column_order": {
21782
22599
  "type": [
21783
22600
  "object",
21784
22601
  "array",
21785
22602
  "null"
21786
- ]
22603
+ ],
22604
+ "items": {
22605
+ "type": "string"
22606
+ },
22607
+ "description": "Ordered column ids (string[]) when an array."
21787
22608
  },
21788
22609
  "sort_config": {
21789
22610
  "type": [
21790
22611
  "object",
21791
22612
  "array",
21792
22613
  "null"
21793
- ]
22614
+ ],
22615
+ "items": {
22616
+ "type": "object"
22617
+ },
22618
+ "description": "Sort rules — array of { id, desc } when an array."
21794
22619
  },
21795
22620
  "filter_config": {
21796
22621
  "type": [
21797
22622
  "object",
21798
22623
  "array",
21799
22624
  "null"
21800
- ]
22625
+ ],
22626
+ "items": {
22627
+ "type": "object"
22628
+ },
22629
+ "description": "Filter state — usually a { pageSize, tab, filters } object."
21801
22630
  }
21802
22631
  },
21803
22632
  "required": [