@flyingrobots/bijou-mcp 4.4.0 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -3
- package/dist/output.d.ts +18 -0
- package/dist/output.d.ts.map +1 -0
- package/dist/output.js +48 -0
- package/dist/output.js.map +1 -0
- package/dist/server.js +8 -2
- package/dist/server.js.map +1 -1
- package/dist/tools/accordion.d.ts.map +1 -1
- package/dist/tools/accordion.js +3 -2
- package/dist/tools/accordion.js.map +1 -1
- package/dist/tools/alert.d.ts.map +1 -1
- package/dist/tools/alert.js +3 -2
- package/dist/tools/alert.js.map +1 -1
- package/dist/tools/badge.d.ts.map +1 -1
- package/dist/tools/badge.js +3 -2
- package/dist/tools/badge.js.map +1 -1
- package/dist/tools/box.d.ts.map +1 -1
- package/dist/tools/box.js +5 -4
- package/dist/tools/box.js.map +1 -1
- package/dist/tools/breadcrumb.d.ts.map +1 -1
- package/dist/tools/breadcrumb.js +3 -2
- package/dist/tools/breadcrumb.js.map +1 -1
- package/dist/tools/constrain.d.ts.map +1 -1
- package/dist/tools/constrain.js +3 -2
- package/dist/tools/constrain.js.map +1 -1
- package/dist/tools/dag.d.ts.map +1 -1
- package/dist/tools/dag.js +4 -3
- package/dist/tools/dag.js.map +1 -1
- package/dist/tools/docs.d.ts +23 -0
- package/dist/tools/docs.d.ts.map +1 -0
- package/dist/tools/docs.js +1106 -0
- package/dist/tools/docs.js.map +1 -0
- package/dist/tools/docs.test.d.ts +2 -0
- package/dist/tools/docs.test.d.ts.map +1 -0
- package/dist/tools/docs.test.js +121 -0
- package/dist/tools/docs.test.js.map +1 -0
- package/dist/tools/enumerated-list.d.ts.map +1 -1
- package/dist/tools/enumerated-list.js +3 -2
- package/dist/tools/enumerated-list.js.map +1 -1
- package/dist/tools/explainability.d.ts.map +1 -1
- package/dist/tools/explainability.js +3 -2
- package/dist/tools/explainability.js.map +1 -1
- package/dist/tools/hyperlink.d.ts.map +1 -1
- package/dist/tools/hyperlink.js +3 -2
- package/dist/tools/hyperlink.js.map +1 -1
- package/dist/tools/inspector.d.ts.map +1 -1
- package/dist/tools/inspector.js +3 -2
- package/dist/tools/inspector.js.map +1 -1
- package/dist/tools/kbd.d.ts.map +1 -1
- package/dist/tools/kbd.js +3 -2
- package/dist/tools/kbd.js.map +1 -1
- package/dist/tools/log.d.ts.map +1 -1
- package/dist/tools/log.js +3 -2
- package/dist/tools/log.js.map +1 -1
- package/dist/tools/output.test.d.ts +2 -0
- package/dist/tools/output.test.d.ts.map +1 -0
- package/dist/tools/output.test.js +105 -0
- package/dist/tools/output.test.js.map +1 -0
- package/dist/tools/paginator.d.ts.map +1 -1
- package/dist/tools/paginator.js +3 -2
- package/dist/tools/paginator.js.map +1 -1
- package/dist/tools/progress.d.ts.map +1 -1
- package/dist/tools/progress.js +3 -2
- package/dist/tools/progress.js.map +1 -1
- package/dist/tools/separator.d.ts.map +1 -1
- package/dist/tools/separator.js +3 -2
- package/dist/tools/separator.js.map +1 -1
- package/dist/tools/skeleton.d.ts.map +1 -1
- package/dist/tools/skeleton.js +3 -2
- package/dist/tools/skeleton.js.map +1 -1
- package/dist/tools/stepper.d.ts.map +1 -1
- package/dist/tools/stepper.js +3 -2
- package/dist/tools/stepper.js.map +1 -1
- package/dist/tools/table.d.ts.map +1 -1
- package/dist/tools/table.js +3 -2
- package/dist/tools/table.js.map +1 -1
- package/dist/tools/tabs.d.ts.map +1 -1
- package/dist/tools/tabs.js +3 -2
- package/dist/tools/tabs.js.map +1 -1
- package/dist/tools/timeline.d.ts.map +1 -1
- package/dist/tools/timeline.js +3 -2
- package/dist/tools/timeline.js.map +1 -1
- package/dist/tools/tree.d.ts.map +1 -1
- package/dist/tools/tree.js +3 -2
- package/dist/tools/tree.js.map +1 -1
- package/dist/types.d.ts +2 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,1106 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { brailleChartSurface, guidedFlow, markdown, perfOverlaySurface, preferenceListSurface, sparkline, spinnerFrame, statsPanelSurface, stripAnsi, surfaceToString, timer, } from '@flyingrobots/bijou';
|
|
3
|
+
import { plainStyle } from '@flyingrobots/bijou/adapters/test';
|
|
4
|
+
import { mcpContext } from '../context.js';
|
|
5
|
+
import { buildStructuredToolResult, structuredToolOutputShape, withOutputMode, } from '../output.js';
|
|
6
|
+
const DEFAULT_INTERACTION_PROFILES = {
|
|
7
|
+
interactive: 'Rendered through a plain-style interactive context with Unicode structure and no ANSI color.',
|
|
8
|
+
static: 'Matches the interactive MCP output because the wrapper returns a plain-text rendering rather than a live terminal state.',
|
|
9
|
+
pipe: 'Not separately lowered by the MCP wrapper; the returned result is already plain text suitable for logs, prompts, and transcripts.',
|
|
10
|
+
accessible: 'No dedicated accessible lowering is exposed by this MCP wrapper yet, so callers should treat the plain-text structure as the accessible fallback.',
|
|
11
|
+
};
|
|
12
|
+
const DEFAULT_DOCS_ONLY_INTERACTION_PROFILES = {
|
|
13
|
+
interactive: 'No dedicated MCP render tool is exposed today. bijou_docs documents this first-party family directly and can synthesize a representative plain-text example when examples are requested.',
|
|
14
|
+
static: 'Matches the docs-only interactive sample because bijou_docs returns a plain-text reference rendering rather than a live terminal session.',
|
|
15
|
+
pipe: 'The synthesized example output is already plain text suitable for logs, prompts, and transcripts.',
|
|
16
|
+
accessible: 'No dedicated accessible lowering is exposed for this docs-only entry yet, so callers should treat the plain-text sample and guidance as the accessible fallback.',
|
|
17
|
+
};
|
|
18
|
+
export const MCP_DOCS_CATALOG = [
|
|
19
|
+
{
|
|
20
|
+
toolName: 'bijou_table',
|
|
21
|
+
family: 'table()',
|
|
22
|
+
category: 'Data and Structure',
|
|
23
|
+
summary: 'Rectangular data grid with headers and box-drawing borders.',
|
|
24
|
+
aliases: ['table', 'grid', 'rows', 'columns'],
|
|
25
|
+
useWhen: [
|
|
26
|
+
'Your data is naturally row-and-column shaped.',
|
|
27
|
+
'People need to compare values across consistent fields.',
|
|
28
|
+
],
|
|
29
|
+
avoidWhen: [
|
|
30
|
+
'The structure is hierarchical rather than tabular.',
|
|
31
|
+
'You need narrative prose more than aligned comparison.',
|
|
32
|
+
],
|
|
33
|
+
related: ['dag()', 'tree()', 'enumeratedList()'],
|
|
34
|
+
exampleArgs: {
|
|
35
|
+
columns: [{ header: 'Service' }, { header: 'Status' }],
|
|
36
|
+
rows: [['api', 'healthy'], ['worker', 'healthy']],
|
|
37
|
+
width: 40,
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
toolName: 'bijou_tree',
|
|
42
|
+
family: 'tree()',
|
|
43
|
+
category: 'Data and Structure',
|
|
44
|
+
summary: 'Nested hierarchy with Unicode connectors.',
|
|
45
|
+
aliases: ['tree', 'hierarchy', 'outline', 'nested'],
|
|
46
|
+
useWhen: [
|
|
47
|
+
'The data has parent-child nesting.',
|
|
48
|
+
'Expansion order matters more than cross-node comparison.',
|
|
49
|
+
],
|
|
50
|
+
avoidWhen: [
|
|
51
|
+
'You need many-to-many relationships or cross-links.',
|
|
52
|
+
'The data is better scanned as rows and columns.',
|
|
53
|
+
],
|
|
54
|
+
related: ['dag()', 'enumeratedList()', 'table()'],
|
|
55
|
+
exampleArgs: {
|
|
56
|
+
nodes: [
|
|
57
|
+
{
|
|
58
|
+
label: 'docs',
|
|
59
|
+
children: [{ label: 'design-system' }, { label: 'release' }],
|
|
60
|
+
},
|
|
61
|
+
],
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
toolName: 'bijou_dag',
|
|
66
|
+
family: 'dag()',
|
|
67
|
+
category: 'Data and Structure',
|
|
68
|
+
summary: 'Directed graph with boxed nodes and routed edges.',
|
|
69
|
+
aliases: ['dag', 'graph', 'dependency graph', 'flow graph'],
|
|
70
|
+
useWhen: [
|
|
71
|
+
'Relationships are graph-shaped rather than purely hierarchical.',
|
|
72
|
+
'You need to show dependencies, branches, or converging flows.',
|
|
73
|
+
],
|
|
74
|
+
avoidWhen: [
|
|
75
|
+
'A linear timeline or step list would explain the flow more clearly.',
|
|
76
|
+
'The structure is simple enough for a tree or breadcrumb.',
|
|
77
|
+
],
|
|
78
|
+
related: ['tree()', 'timeline()', 'table()'],
|
|
79
|
+
exampleArgs: {
|
|
80
|
+
nodes: [
|
|
81
|
+
{ id: 'build', label: 'Build', edges: ['test'] },
|
|
82
|
+
{ id: 'test', label: 'Test', edges: ['deploy'] },
|
|
83
|
+
{ id: 'deploy', label: 'Deploy' },
|
|
84
|
+
],
|
|
85
|
+
maxWidth: 60,
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
toolName: 'bijou_enumerated_list',
|
|
90
|
+
family: 'enumeratedList()',
|
|
91
|
+
category: 'Data and Structure',
|
|
92
|
+
summary: 'List renderer for bullets, ordered steps, letters, or roman numerals.',
|
|
93
|
+
aliases: ['enumerated list', 'list', 'bullet list', 'ordered list'],
|
|
94
|
+
useWhen: [
|
|
95
|
+
'You need a lightweight ordered or unordered list.',
|
|
96
|
+
'Sequence matters but rich container chrome would be overkill.',
|
|
97
|
+
],
|
|
98
|
+
avoidWhen: [
|
|
99
|
+
'Items need per-row metadata or aligned fields.',
|
|
100
|
+
'The structure is better represented as tabs, steps, or a tree.',
|
|
101
|
+
],
|
|
102
|
+
related: ['stepper()', 'timeline()', 'table()'],
|
|
103
|
+
exampleArgs: {
|
|
104
|
+
items: ['Build', 'Test', 'Deploy'],
|
|
105
|
+
style: 'arabic',
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
toolName: 'bijou_box',
|
|
110
|
+
family: 'box()',
|
|
111
|
+
category: 'Containers and Layout',
|
|
112
|
+
summary: 'Generic bordered container for prose, status, or grouped content.',
|
|
113
|
+
aliases: ['box', 'panel', 'container'],
|
|
114
|
+
useWhen: [
|
|
115
|
+
'Content needs a visible boundary or title.',
|
|
116
|
+
'You want a neutral container that does not imply workflow state.',
|
|
117
|
+
],
|
|
118
|
+
avoidWhen: [
|
|
119
|
+
'The content wants a more opinionated component such as alert or inspector.',
|
|
120
|
+
'The output is simple enough to stay as plain text.',
|
|
121
|
+
],
|
|
122
|
+
related: ['headerBox()', 'alert()', 'inspector()'],
|
|
123
|
+
exampleArgs: {
|
|
124
|
+
content: 'Release ready for canary.',
|
|
125
|
+
title: 'status',
|
|
126
|
+
},
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
toolName: 'bijou_header_box',
|
|
130
|
+
family: 'headerBox()',
|
|
131
|
+
category: 'Containers and Layout',
|
|
132
|
+
summary: 'Compact labeled container with a heading and optional detail line.',
|
|
133
|
+
aliases: ['header box', 'summary panel', 'heading panel'],
|
|
134
|
+
useWhen: [
|
|
135
|
+
'A compact callout needs a strong label up front.',
|
|
136
|
+
'You want a container with more voice than a generic box.',
|
|
137
|
+
],
|
|
138
|
+
avoidWhen: [
|
|
139
|
+
'You need multi-section detail instead of a headline summary.',
|
|
140
|
+
'The content is only one line and does not need chrome.',
|
|
141
|
+
],
|
|
142
|
+
related: ['box()', 'inspector()', 'alert()'],
|
|
143
|
+
exampleArgs: {
|
|
144
|
+
label: 'Release',
|
|
145
|
+
detail: 'stable',
|
|
146
|
+
},
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
toolName: 'bijou_separator',
|
|
150
|
+
family: 'separator()',
|
|
151
|
+
category: 'Containers and Layout',
|
|
152
|
+
summary: 'Horizontal rule with optional centered label.',
|
|
153
|
+
aliases: ['separator', 'divider', 'rule'],
|
|
154
|
+
useWhen: [
|
|
155
|
+
'You need a clear break between sections.',
|
|
156
|
+
'A short label should orient the next block of content.',
|
|
157
|
+
],
|
|
158
|
+
avoidWhen: [
|
|
159
|
+
'You need an actual container rather than a visual divider.',
|
|
160
|
+
'The surrounding layout already makes section boundaries obvious.',
|
|
161
|
+
],
|
|
162
|
+
related: ['box()', 'headerBox()', 'tabs()'],
|
|
163
|
+
exampleArgs: {
|
|
164
|
+
label: 'release queue',
|
|
165
|
+
width: 32,
|
|
166
|
+
},
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
toolName: 'bijou_constrain',
|
|
170
|
+
family: 'constrain()',
|
|
171
|
+
category: 'Containers and Layout',
|
|
172
|
+
summary: 'Text truncation helper for bounded width and height.',
|
|
173
|
+
aliases: ['constrain', 'truncate', 'clamp', 'ellipsis'],
|
|
174
|
+
useWhen: [
|
|
175
|
+
'Free-form text must fit a strict width or height.',
|
|
176
|
+
'A preview should stay honest without rewriting the source text.',
|
|
177
|
+
],
|
|
178
|
+
avoidWhen: [
|
|
179
|
+
'You actually need wrapping instead of truncation.',
|
|
180
|
+
'The source content is important enough to merit a scrollable container.',
|
|
181
|
+
],
|
|
182
|
+
related: ['box()', 'markdown()', 'table()'],
|
|
183
|
+
exampleArgs: {
|
|
184
|
+
content: 'This is a long release note preview that should be clipped before it overruns the surrounding layout.',
|
|
185
|
+
maxWidth: 26,
|
|
186
|
+
},
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
toolName: 'bijou_alert',
|
|
190
|
+
family: 'alert()',
|
|
191
|
+
category: 'Feedback and Status',
|
|
192
|
+
summary: 'Severity callout with icon and bordered container.',
|
|
193
|
+
aliases: ['alert', 'warning', 'error', 'success', 'info'],
|
|
194
|
+
useWhen: [
|
|
195
|
+
'A message needs strong severity signaling.',
|
|
196
|
+
'The reader should treat the content as a callout rather than ambient copy.',
|
|
197
|
+
],
|
|
198
|
+
avoidWhen: [
|
|
199
|
+
'You need transient notification behavior rather than a static panel.',
|
|
200
|
+
'The state is low-stakes enough for a badge or note.',
|
|
201
|
+
],
|
|
202
|
+
related: ['badge()', 'log()', 'explainability()'],
|
|
203
|
+
exampleArgs: {
|
|
204
|
+
message: 'Canary error budget is almost exhausted.',
|
|
205
|
+
variant: 'warning',
|
|
206
|
+
},
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
toolName: 'bijou_note',
|
|
210
|
+
family: 'note()',
|
|
211
|
+
category: 'Feedback and Status',
|
|
212
|
+
summary: 'Calm explanatory note for form flows and inline guidance without alert-level urgency.',
|
|
213
|
+
aliases: ['note', 'helper text', 'supporting note', 'inline guidance'],
|
|
214
|
+
useWhen: [
|
|
215
|
+
'You need supportive explanatory text that should not compete with primary status messaging.',
|
|
216
|
+
'A form, guided flow, or inspector needs clarifying context without turning into an alert.',
|
|
217
|
+
],
|
|
218
|
+
avoidWhen: [
|
|
219
|
+
'The message carries urgency, severity, or a required next action.',
|
|
220
|
+
'The content is long-form prose that should live in markdown() or guidedFlow().',
|
|
221
|
+
],
|
|
222
|
+
related: ['alert()', 'markdown()', 'group() / wizard()'],
|
|
223
|
+
exampleArgs: {
|
|
224
|
+
title: 'Deploy window',
|
|
225
|
+
message: 'Rotate credentials after the canary completes.',
|
|
226
|
+
},
|
|
227
|
+
},
|
|
228
|
+
{
|
|
229
|
+
toolName: 'bijou_progress_bar',
|
|
230
|
+
family: 'progressBar()',
|
|
231
|
+
category: 'Feedback and Status',
|
|
232
|
+
summary: 'Static completion bar with optional percent label.',
|
|
233
|
+
aliases: ['progress', 'progress bar', 'percent', 'completion'],
|
|
234
|
+
useWhen: [
|
|
235
|
+
'A single bounded percentage is the important state.',
|
|
236
|
+
'You need a compact progress signal inside another surface.',
|
|
237
|
+
],
|
|
238
|
+
avoidWhen: [
|
|
239
|
+
'The workflow has named steps rather than a pure percent.',
|
|
240
|
+
'The state is indeterminate and should be shown as loading instead.',
|
|
241
|
+
],
|
|
242
|
+
related: ['stepper()', 'timeline()', 'skeleton()'],
|
|
243
|
+
exampleArgs: {
|
|
244
|
+
percent: 72,
|
|
245
|
+
width: 20,
|
|
246
|
+
},
|
|
247
|
+
},
|
|
248
|
+
{
|
|
249
|
+
toolName: 'bijou_stepper',
|
|
250
|
+
family: 'stepper()',
|
|
251
|
+
category: 'Feedback and Status',
|
|
252
|
+
summary: 'Horizontal step-progress indicator with completed and active states.',
|
|
253
|
+
aliases: ['stepper', 'steps', 'wizard progress', 'workflow'],
|
|
254
|
+
useWhen: [
|
|
255
|
+
'The process has named sequential stages.',
|
|
256
|
+
'You want to show both completed and upcoming steps.',
|
|
257
|
+
],
|
|
258
|
+
avoidWhen: [
|
|
259
|
+
'The flow branches or loops like a graph.',
|
|
260
|
+
'Only a raw percentage matters.',
|
|
261
|
+
],
|
|
262
|
+
related: ['timeline()', 'progressBar()', 'tabs()'],
|
|
263
|
+
exampleArgs: {
|
|
264
|
+
steps: [{ label: 'Build' }, { label: 'Test' }, { label: 'Deploy' }],
|
|
265
|
+
current: 1,
|
|
266
|
+
},
|
|
267
|
+
},
|
|
268
|
+
{
|
|
269
|
+
toolName: 'bijou_timeline',
|
|
270
|
+
family: 'timeline()',
|
|
271
|
+
category: 'Feedback and Status',
|
|
272
|
+
summary: 'Vertical sequence of timestamp-like events with status markers.',
|
|
273
|
+
aliases: ['timeline', 'history', 'event stream', 'chronology'],
|
|
274
|
+
useWhen: [
|
|
275
|
+
'Order over time is the main story.',
|
|
276
|
+
'Each event needs a short label and optional detail.',
|
|
277
|
+
],
|
|
278
|
+
avoidWhen: [
|
|
279
|
+
'The relationship is graph-shaped rather than sequential.',
|
|
280
|
+
'You only need the current step, not the event history.',
|
|
281
|
+
],
|
|
282
|
+
related: ['stepper()', 'log()', 'dag()'],
|
|
283
|
+
exampleArgs: {
|
|
284
|
+
events: [
|
|
285
|
+
{ label: 'Build', status: 'success' },
|
|
286
|
+
{ label: 'Deploy', description: 'Canary 25%', status: 'active' },
|
|
287
|
+
],
|
|
288
|
+
},
|
|
289
|
+
},
|
|
290
|
+
{
|
|
291
|
+
toolName: 'bijou_log',
|
|
292
|
+
family: 'log()',
|
|
293
|
+
category: 'Feedback and Status',
|
|
294
|
+
summary: 'Single structured log line with severity treatment.',
|
|
295
|
+
aliases: ['log', 'log line', 'event', 'status line'],
|
|
296
|
+
useWhen: [
|
|
297
|
+
'You need terse operational events.',
|
|
298
|
+
'Severity should be visible without a full alert box.',
|
|
299
|
+
],
|
|
300
|
+
avoidWhen: [
|
|
301
|
+
'The message needs explanation, evidence, or grouped detail.',
|
|
302
|
+
'You are rendering a multi-row history rather than one event.',
|
|
303
|
+
],
|
|
304
|
+
related: ['timeline()', 'alert()', 'badge()'],
|
|
305
|
+
exampleArgs: {
|
|
306
|
+
level: 'info',
|
|
307
|
+
message: 'Deployment completed.',
|
|
308
|
+
},
|
|
309
|
+
},
|
|
310
|
+
{
|
|
311
|
+
toolName: 'bijou_badge',
|
|
312
|
+
family: 'badge()',
|
|
313
|
+
category: 'Feedback and Status',
|
|
314
|
+
summary: 'Compact inline status pill.',
|
|
315
|
+
aliases: ['badge', 'pill', 'status chip', 'label'],
|
|
316
|
+
useWhen: [
|
|
317
|
+
'A short state label should stay inline with surrounding content.',
|
|
318
|
+
'You need low-chrome categorical emphasis.',
|
|
319
|
+
],
|
|
320
|
+
avoidWhen: [
|
|
321
|
+
'The message needs body text or explanation.',
|
|
322
|
+
'The state changes over time and deserves a richer progress surface.',
|
|
323
|
+
],
|
|
324
|
+
related: ['alert()', 'log()', 'progressBar()'],
|
|
325
|
+
exampleArgs: {
|
|
326
|
+
text: 'LIVE',
|
|
327
|
+
variant: 'success',
|
|
328
|
+
},
|
|
329
|
+
},
|
|
330
|
+
{
|
|
331
|
+
toolName: 'bijou_tabs',
|
|
332
|
+
family: 'tabs()',
|
|
333
|
+
category: 'Navigation',
|
|
334
|
+
summary: 'Horizontal section switcher with one active tab.',
|
|
335
|
+
aliases: ['tabs', 'tab bar', 'sections', 'navigation tabs'],
|
|
336
|
+
useWhen: [
|
|
337
|
+
'People switch between peer views or sections.',
|
|
338
|
+
'One active choice should be visible at a glance.',
|
|
339
|
+
],
|
|
340
|
+
avoidWhen: [
|
|
341
|
+
'The choices are sequential workflow steps.',
|
|
342
|
+
'The navigation is path-like rather than peer-to-peer.',
|
|
343
|
+
],
|
|
344
|
+
related: ['breadcrumb()', 'paginator()', 'stepper()'],
|
|
345
|
+
exampleArgs: {
|
|
346
|
+
items: [{ label: 'Overview' }, { label: 'Logs' }, { label: 'Settings' }],
|
|
347
|
+
active: 1,
|
|
348
|
+
},
|
|
349
|
+
},
|
|
350
|
+
{
|
|
351
|
+
toolName: 'bijou_breadcrumb',
|
|
352
|
+
family: 'breadcrumb()',
|
|
353
|
+
category: 'Navigation',
|
|
354
|
+
summary: 'Path trail showing where the current surface sits inside a hierarchy.',
|
|
355
|
+
aliases: ['breadcrumb', 'path', 'location trail'],
|
|
356
|
+
useWhen: [
|
|
357
|
+
'Location context matters more than peer switching.',
|
|
358
|
+
'You need to show depth inside a hierarchy.',
|
|
359
|
+
],
|
|
360
|
+
avoidWhen: [
|
|
361
|
+
'Users choose between peer views rather than nested locations.',
|
|
362
|
+
'The hierarchy is dense enough to need a tree.',
|
|
363
|
+
],
|
|
364
|
+
related: ['tabs()', 'tree()', 'paginator()'],
|
|
365
|
+
exampleArgs: {
|
|
366
|
+
items: ['Home', 'Docs', 'API'],
|
|
367
|
+
},
|
|
368
|
+
},
|
|
369
|
+
{
|
|
370
|
+
toolName: 'bijou_paginator',
|
|
371
|
+
family: 'paginator()',
|
|
372
|
+
category: 'Navigation',
|
|
373
|
+
summary: 'Compact indicator for current page or viewport position.',
|
|
374
|
+
aliases: ['paginator', 'pagination', 'page indicator', 'page dots'],
|
|
375
|
+
useWhen: [
|
|
376
|
+
'The user needs lightweight position awareness across pages.',
|
|
377
|
+
'Full tabs or breadcrumbs would be too heavy for the surface.',
|
|
378
|
+
],
|
|
379
|
+
avoidWhen: [
|
|
380
|
+
'Page labels matter more than page count.',
|
|
381
|
+
'The navigation is hierarchical rather than sequential.',
|
|
382
|
+
],
|
|
383
|
+
related: ['tabs()', 'breadcrumb()', 'stepper()'],
|
|
384
|
+
exampleArgs: {
|
|
385
|
+
current: 2,
|
|
386
|
+
total: 5,
|
|
387
|
+
style: 'dots',
|
|
388
|
+
},
|
|
389
|
+
},
|
|
390
|
+
{
|
|
391
|
+
toolName: 'bijou_explainability',
|
|
392
|
+
family: 'explainability()',
|
|
393
|
+
category: 'Rich Panels',
|
|
394
|
+
summary: 'Decision card with rationale, evidence, confidence, and next action.',
|
|
395
|
+
aliases: ['explainability', 'explanation', 'decision card', 'ai rationale'],
|
|
396
|
+
useWhen: [
|
|
397
|
+
'A recommendation or decision needs supporting evidence.',
|
|
398
|
+
'You want the reader to audit reasoning, not just accept output.',
|
|
399
|
+
],
|
|
400
|
+
avoidWhen: [
|
|
401
|
+
'The content is simple status or prose without structured rationale.',
|
|
402
|
+
'A generic box or inspector already carries enough context.',
|
|
403
|
+
],
|
|
404
|
+
related: ['inspector()', 'alert()', 'note()'],
|
|
405
|
+
exampleArgs: {
|
|
406
|
+
title: 'Choose table()',
|
|
407
|
+
label: 'Recommendation',
|
|
408
|
+
rationale: 'The data is rectangular and the reader needs aligned field comparison.',
|
|
409
|
+
evidence: [
|
|
410
|
+
{ label: 'Shape', value: 'rows × columns' },
|
|
411
|
+
{ label: 'Need', value: 'compare values side by side' },
|
|
412
|
+
],
|
|
413
|
+
confidence: 'high',
|
|
414
|
+
},
|
|
415
|
+
},
|
|
416
|
+
{
|
|
417
|
+
toolName: 'bijou_inspector',
|
|
418
|
+
family: 'inspector()',
|
|
419
|
+
category: 'Rich Panels',
|
|
420
|
+
summary: 'Detail panel with a primary value and structured supporting sections.',
|
|
421
|
+
aliases: ['inspector', 'detail panel', 'detail view', 'property panel'],
|
|
422
|
+
useWhen: [
|
|
423
|
+
'A single object or resource needs focused inspection.',
|
|
424
|
+
'You need a primary value plus labeled supporting sections.',
|
|
425
|
+
],
|
|
426
|
+
avoidWhen: [
|
|
427
|
+
'The content is really an alert or recommendation.',
|
|
428
|
+
'A flat table or list is enough.',
|
|
429
|
+
],
|
|
430
|
+
related: ['explainability()', 'box()', 'headerBox()'],
|
|
431
|
+
exampleArgs: {
|
|
432
|
+
title: 'Service',
|
|
433
|
+
currentValue: 'healthy',
|
|
434
|
+
currentValueLabel: 'Status',
|
|
435
|
+
supportingText: 'us-west-2',
|
|
436
|
+
supportingTextLabel: 'Region',
|
|
437
|
+
sections: [{ title: 'Deploy', content: 'Canary complete.' }],
|
|
438
|
+
},
|
|
439
|
+
},
|
|
440
|
+
{
|
|
441
|
+
toolName: 'bijou_accordion',
|
|
442
|
+
family: 'accordion()',
|
|
443
|
+
category: 'Rich Panels',
|
|
444
|
+
summary: 'Collapsible sections for progressive disclosure.',
|
|
445
|
+
aliases: ['accordion', 'collapsible', 'disclosure', 'expand/collapse'],
|
|
446
|
+
useWhen: [
|
|
447
|
+
'Not every section should be open at once.',
|
|
448
|
+
'The reader benefits from progressive disclosure.',
|
|
449
|
+
],
|
|
450
|
+
avoidWhen: [
|
|
451
|
+
'Everything should remain visible together for comparison.',
|
|
452
|
+
'The user is switching peer views rather than expanding sections.',
|
|
453
|
+
],
|
|
454
|
+
related: ['tabs()', 'inspector()', 'box()'],
|
|
455
|
+
exampleArgs: {
|
|
456
|
+
sections: [
|
|
457
|
+
{ title: 'Deploy', content: 'Roll canaries to 25%.', expanded: true },
|
|
458
|
+
{ title: 'Rollback', content: 'Restore the previous stable build.' },
|
|
459
|
+
],
|
|
460
|
+
},
|
|
461
|
+
},
|
|
462
|
+
{
|
|
463
|
+
toolName: 'bijou_kbd',
|
|
464
|
+
family: 'kbd()',
|
|
465
|
+
category: 'Utility',
|
|
466
|
+
summary: 'Keyboard keycap renderer for inline shortcut hints.',
|
|
467
|
+
aliases: ['kbd', 'keycap', 'shortcut key', 'keyboard hint'],
|
|
468
|
+
useWhen: [
|
|
469
|
+
'You need to show a shortcut inline.',
|
|
470
|
+
'The key label should read like UI chrome rather than plain prose.',
|
|
471
|
+
],
|
|
472
|
+
avoidWhen: [
|
|
473
|
+
'The shortcut is incidental and plain text is enough.',
|
|
474
|
+
'You need a full help table rather than one key hint.',
|
|
475
|
+
],
|
|
476
|
+
related: ['hyperlink()', 'badge()', 'tabs()'],
|
|
477
|
+
exampleArgs: {
|
|
478
|
+
key: 'Ctrl+P',
|
|
479
|
+
},
|
|
480
|
+
},
|
|
481
|
+
{
|
|
482
|
+
toolName: 'bijou_hyperlink',
|
|
483
|
+
family: 'hyperlink()',
|
|
484
|
+
category: 'Utility',
|
|
485
|
+
summary: 'Terminal hyperlink with explicit plain-text fallback behavior.',
|
|
486
|
+
aliases: ['hyperlink', 'link', 'url', 'osc 8'],
|
|
487
|
+
useWhen: [
|
|
488
|
+
'The destination matters and should stay explicit.',
|
|
489
|
+
'A plain-text fallback still needs to make sense when OSC 8 is unavailable.',
|
|
490
|
+
],
|
|
491
|
+
avoidWhen: [
|
|
492
|
+
'You are just styling text without a destination.',
|
|
493
|
+
'The raw URL alone is clearer than link text.',
|
|
494
|
+
],
|
|
495
|
+
related: ['kbd()', 'markdown()', 'box()'],
|
|
496
|
+
exampleArgs: {
|
|
497
|
+
text: 'Bijou docs',
|
|
498
|
+
url: 'https://github.com/flyingrobots/bijou',
|
|
499
|
+
},
|
|
500
|
+
},
|
|
501
|
+
{
|
|
502
|
+
toolName: 'bijou_skeleton',
|
|
503
|
+
family: 'skeleton()',
|
|
504
|
+
category: 'Utility',
|
|
505
|
+
summary: 'Placeholder loading surface for still-unavailable content.',
|
|
506
|
+
aliases: ['skeleton', 'placeholder', 'loading', 'shimmer'],
|
|
507
|
+
useWhen: [
|
|
508
|
+
'Content is loading and the future shape matters.',
|
|
509
|
+
'You need a compact visual placeholder rather than a spinner alone.',
|
|
510
|
+
],
|
|
511
|
+
avoidWhen: [
|
|
512
|
+
'The state is determinate enough for a progress bar or stepper.',
|
|
513
|
+
'The load is instantaneous and placeholder chrome adds noise.',
|
|
514
|
+
],
|
|
515
|
+
related: ['progressBar()', 'badge()', 'alert()'],
|
|
516
|
+
exampleArgs: {
|
|
517
|
+
width: 24,
|
|
518
|
+
lines: 2,
|
|
519
|
+
},
|
|
520
|
+
},
|
|
521
|
+
{
|
|
522
|
+
toolName: 'bijou_markdown',
|
|
523
|
+
family: 'markdown()',
|
|
524
|
+
category: 'Narrative and Content',
|
|
525
|
+
summary: 'Mode-aware terminal markdown renderer for headings, lists, code blocks, links, and quotes.',
|
|
526
|
+
aliases: ['markdown', 'md', 'rich text', 'docs prose'],
|
|
527
|
+
useWhen: [
|
|
528
|
+
'Source text already exists as markdown and should stay authored that way.',
|
|
529
|
+
'You need headings, lists, quotes, and inline emphasis without rebuilding the prose by hand.',
|
|
530
|
+
],
|
|
531
|
+
avoidWhen: [
|
|
532
|
+
'The content is structured data that should be table-, tree-, or graph-shaped.',
|
|
533
|
+
'You need one focused callout rather than a narrative document block.',
|
|
534
|
+
],
|
|
535
|
+
related: ['hyperlink()', 'box()', 'guidedFlow()'],
|
|
536
|
+
exampleArgs: {
|
|
537
|
+
source: '# Release\n\n- Build\n- Test\n- Deploy',
|
|
538
|
+
width: 32,
|
|
539
|
+
},
|
|
540
|
+
},
|
|
541
|
+
{
|
|
542
|
+
toolName: 'bijou_guided_flow',
|
|
543
|
+
family: 'guidedFlow()',
|
|
544
|
+
category: 'Narrative and Content',
|
|
545
|
+
summary: 'Structured explainability block for posture, steps, sections, and next action.',
|
|
546
|
+
aliases: ['guided flow', 'runbook', 'operator guide', 'playbook'],
|
|
547
|
+
useWhen: [
|
|
548
|
+
'Readers need a guided operational story instead of an undifferentiated text dump.',
|
|
549
|
+
'You want summary, steps, supporting sections, and a next action inside one coherent block.',
|
|
550
|
+
],
|
|
551
|
+
avoidWhen: [
|
|
552
|
+
'A lightweight list, table, or alert would explain the state more directly.',
|
|
553
|
+
'The content is free-form markdown rather than a guided operational flow.',
|
|
554
|
+
],
|
|
555
|
+
related: ['explainability()', 'markdown()', 'stepper()'],
|
|
556
|
+
exampleArgs: {
|
|
557
|
+
title: 'Release canary',
|
|
558
|
+
label: 'Flow',
|
|
559
|
+
summary: 'Roll canaries to 25% before global promote.',
|
|
560
|
+
steps: [
|
|
561
|
+
{ title: 'Build', status: 'complete' },
|
|
562
|
+
{ title: 'Canary', status: 'current', detail: 'Watch error budget for 15 minutes.' },
|
|
563
|
+
{ title: 'Promote', status: 'pending' },
|
|
564
|
+
],
|
|
565
|
+
nextAction: 'Hold at 25% until latency stays green.',
|
|
566
|
+
width: 48,
|
|
567
|
+
},
|
|
568
|
+
},
|
|
569
|
+
{
|
|
570
|
+
toolName: 'bijou_preference_list',
|
|
571
|
+
family: 'preferenceListSurface()',
|
|
572
|
+
category: 'Forms and Settings',
|
|
573
|
+
summary: 'Structured settings list with toggles, actions, descriptions, and selected-row state.',
|
|
574
|
+
aliases: ['preference list', 'settings list', 'preferences', 'settings panel'],
|
|
575
|
+
useWhen: [
|
|
576
|
+
'Settings need sectioned rows, values, and secondary descriptions.',
|
|
577
|
+
'A shell or page needs a settings surface rather than an ad hoc list of toggles.',
|
|
578
|
+
],
|
|
579
|
+
avoidWhen: [
|
|
580
|
+
'You only need one or two status pills or buttons.',
|
|
581
|
+
'The content is narrative guidance rather than configurable rows.',
|
|
582
|
+
],
|
|
583
|
+
related: ['tabs()', 'box()', 'guidedFlow()'],
|
|
584
|
+
exampleArgs: {
|
|
585
|
+
sections: [
|
|
586
|
+
{
|
|
587
|
+
id: 'shell',
|
|
588
|
+
title: 'Shell',
|
|
589
|
+
rows: [
|
|
590
|
+
{ id: 'theme', label: 'Theme', valueLabel: 'Verdant Plum', kind: 'choice' },
|
|
591
|
+
{ id: 'perf', label: 'Perf HUD', checked: true, kind: 'toggle', description: 'Show development perf overlay.' },
|
|
592
|
+
],
|
|
593
|
+
},
|
|
594
|
+
],
|
|
595
|
+
width: 42,
|
|
596
|
+
selectedRowId: 'perf',
|
|
597
|
+
},
|
|
598
|
+
},
|
|
599
|
+
{
|
|
600
|
+
toolName: 'bijou_text_entry',
|
|
601
|
+
family: 'input() / textarea()',
|
|
602
|
+
category: 'Forms and Settings',
|
|
603
|
+
summary: 'Short-form and multiline text-entry prompts for collecting authored input rather than choosing from a fixed set.',
|
|
604
|
+
aliases: ['text entry', 'input', 'textarea', 'text field', 'free-form text'],
|
|
605
|
+
useWhen: [
|
|
606
|
+
'The user needs to enter original text rather than choose a predefined value.',
|
|
607
|
+
'The difference between short-form and multiline entry matters to the task.',
|
|
608
|
+
],
|
|
609
|
+
avoidWhen: [
|
|
610
|
+
'The result is really a choice from a stable option set.',
|
|
611
|
+
'A static content block or note would be more honest than an editable prompt.',
|
|
612
|
+
],
|
|
613
|
+
related: ['select() / filter()', 'group() / wizard()', 'note()'],
|
|
614
|
+
exampleArgs: {
|
|
615
|
+
inputTitle: 'Cluster name',
|
|
616
|
+
inputDefault: 'prod-us-west-2',
|
|
617
|
+
textareaTitle: 'Rollback notes',
|
|
618
|
+
textareaValue: 'Drain traffic\nPromote stable build',
|
|
619
|
+
},
|
|
620
|
+
},
|
|
621
|
+
{
|
|
622
|
+
toolName: 'bijou_single_choice',
|
|
623
|
+
family: 'select() / filter()',
|
|
624
|
+
category: 'Forms and Settings',
|
|
625
|
+
summary: 'Single-choice prompt family for visible-list selection and searchable narrowing.',
|
|
626
|
+
aliases: ['single choice', 'select', 'filter', 'dropdown', 'combo box'],
|
|
627
|
+
useWhen: [
|
|
628
|
+
'The user is choosing one durable value from a known option set.',
|
|
629
|
+
'Search/narrowing helps, but the end result is still one selected value.',
|
|
630
|
+
],
|
|
631
|
+
avoidWhen: [
|
|
632
|
+
'The user is building a set rather than making one choice.',
|
|
633
|
+
'The interaction is command dispatch rather than stored selection state.',
|
|
634
|
+
],
|
|
635
|
+
related: ['multiselect()', 'input() / textarea()', 'group() / wizard()'],
|
|
636
|
+
exampleArgs: {
|
|
637
|
+
title: 'Release channel',
|
|
638
|
+
options: ['stable', 'canary', 'nightly'],
|
|
639
|
+
selected: 'canary',
|
|
640
|
+
},
|
|
641
|
+
},
|
|
642
|
+
{
|
|
643
|
+
toolName: 'bijou_multiple_choice',
|
|
644
|
+
family: 'multiselect()',
|
|
645
|
+
category: 'Forms and Settings',
|
|
646
|
+
summary: 'Checkbox-style set builder for choosing several durable values.',
|
|
647
|
+
aliases: ['multiple choice', 'multiselect', 'checkboxes', 'set selection'],
|
|
648
|
+
useWhen: [
|
|
649
|
+
'The user is building a set of selected values.',
|
|
650
|
+
'The options read like members of one coherent collection.',
|
|
651
|
+
],
|
|
652
|
+
avoidWhen: [
|
|
653
|
+
'Only one choice is valid.',
|
|
654
|
+
'The rows are commands or actions instead of lasting state.',
|
|
655
|
+
],
|
|
656
|
+
related: ['select() / filter()', 'confirm()', 'group() / wizard()'],
|
|
657
|
+
exampleArgs: {
|
|
658
|
+
title: 'Deploy targets',
|
|
659
|
+
options: ['api', 'web', 'worker'],
|
|
660
|
+
selected: ['web', 'worker'],
|
|
661
|
+
},
|
|
662
|
+
},
|
|
663
|
+
{
|
|
664
|
+
toolName: 'bijou_binary_decision',
|
|
665
|
+
family: 'confirm()',
|
|
666
|
+
category: 'Forms and Settings',
|
|
667
|
+
summary: 'Explicit yes-or-no confirmation prompt for genuinely binary decisions.',
|
|
668
|
+
aliases: ['binary decision', 'confirm', 'yes no', 'confirmation'],
|
|
669
|
+
useWhen: [
|
|
670
|
+
'The choice is honestly binary and the consequence of yes versus no matters.',
|
|
671
|
+
'A simple confirmation is clearer than a larger staged form.',
|
|
672
|
+
],
|
|
673
|
+
avoidWhen: [
|
|
674
|
+
'The user really has multiple options or tradeoffs to compare.',
|
|
675
|
+
'The prompt needs rich evidence or explanation instead of a binary gate.',
|
|
676
|
+
],
|
|
677
|
+
related: ['alert()', 'multiselect()', 'group() / wizard()'],
|
|
678
|
+
exampleArgs: {
|
|
679
|
+
title: 'Continue deployment',
|
|
680
|
+
defaultValue: true,
|
|
681
|
+
answer: 'y',
|
|
682
|
+
},
|
|
683
|
+
},
|
|
684
|
+
{
|
|
685
|
+
toolName: 'bijou_multi_field_forms',
|
|
686
|
+
family: 'group() / wizard()',
|
|
687
|
+
category: 'Forms and Settings',
|
|
688
|
+
summary: 'Grouped and staged form orchestration for related inputs, progress, and branching flow.',
|
|
689
|
+
aliases: ['group', 'wizard', 'multi-step form', 'staged form', 'grouped form'],
|
|
690
|
+
useWhen: [
|
|
691
|
+
'Several related inputs belong together under one goal or workflow.',
|
|
692
|
+
'Progress, grouping, or branching matters more than one isolated prompt.',
|
|
693
|
+
],
|
|
694
|
+
avoidWhen: [
|
|
695
|
+
'The task only needs one simple field.',
|
|
696
|
+
'The fields are unrelated and should not be bundled into one flow.',
|
|
697
|
+
],
|
|
698
|
+
related: ['input() / textarea()', 'select() / filter()', 'confirm()', 'stepper()'],
|
|
699
|
+
exampleArgs: {
|
|
700
|
+
stepLabel: 'Step 2 of 3',
|
|
701
|
+
stepTitle: 'Approval',
|
|
702
|
+
fields: [
|
|
703
|
+
'Cluster name? [prod-us-west-2]',
|
|
704
|
+
'Release channel?',
|
|
705
|
+
'1. stable',
|
|
706
|
+
'2. canary',
|
|
707
|
+
'3. nightly',
|
|
708
|
+
'> 2',
|
|
709
|
+
'Continue deployment? [Y/n]',
|
|
710
|
+
'> y',
|
|
711
|
+
],
|
|
712
|
+
},
|
|
713
|
+
},
|
|
714
|
+
{
|
|
715
|
+
toolName: 'bijou_spinner',
|
|
716
|
+
family: 'spinnerFrame() / createSpinner()',
|
|
717
|
+
category: 'Feedback and Status',
|
|
718
|
+
summary: 'Inline spinner glyphs and live spinner controller for indeterminate work.',
|
|
719
|
+
aliases: ['spinner', 'loading spinner', 'busy indicator', 'working'],
|
|
720
|
+
useWhen: [
|
|
721
|
+
'Work is in flight but there is no honest percentage yet.',
|
|
722
|
+
'You need a compact live-status affordance rather than a large placeholder.',
|
|
723
|
+
],
|
|
724
|
+
avoidWhen: [
|
|
725
|
+
'Progress is determinate enough for a progress bar or stepper.',
|
|
726
|
+
'The load state wants a full skeleton or empty-state narrative instead.',
|
|
727
|
+
],
|
|
728
|
+
related: ['progressBar()', 'skeleton()', 'timer()'],
|
|
729
|
+
exampleArgs: {
|
|
730
|
+
tick: 3,
|
|
731
|
+
label: 'Build',
|
|
732
|
+
},
|
|
733
|
+
},
|
|
734
|
+
{
|
|
735
|
+
toolName: 'bijou_timer',
|
|
736
|
+
family: 'timer() / createTimer() / createStopwatch()',
|
|
737
|
+
category: 'Feedback and Status',
|
|
738
|
+
summary: 'Static and live timer family for countdowns, stopwatches, and elapsed-time readouts.',
|
|
739
|
+
aliases: ['timer', 'countdown', 'stopwatch', 'elapsed time'],
|
|
740
|
+
useWhen: [
|
|
741
|
+
'Time remaining or elapsed time is the core signal.',
|
|
742
|
+
'You need a compact time readout that can degrade across output modes.',
|
|
743
|
+
],
|
|
744
|
+
avoidWhen: [
|
|
745
|
+
'The user needs task progression rather than wall-clock duration.',
|
|
746
|
+
'A timestamp label is enough and no live timer semantics are needed.',
|
|
747
|
+
],
|
|
748
|
+
related: ['progressBar()', 'spinnerFrame() / createSpinner()', 'perfOverlaySurface()'],
|
|
749
|
+
exampleArgs: {
|
|
750
|
+
ms: 150000,
|
|
751
|
+
label: 'Deploy',
|
|
752
|
+
},
|
|
753
|
+
},
|
|
754
|
+
{
|
|
755
|
+
toolName: 'bijou_sparkline',
|
|
756
|
+
family: 'sparkline()',
|
|
757
|
+
category: 'Data Visualization',
|
|
758
|
+
summary: 'Compact inline trend graph using Unicode block characters.',
|
|
759
|
+
aliases: ['sparkline', 'inline chart', 'trend line', 'micro chart'],
|
|
760
|
+
useWhen: [
|
|
761
|
+
'You need a tiny trend summary inline with a metric.',
|
|
762
|
+
'A full chart would be too heavy for the available space.',
|
|
763
|
+
],
|
|
764
|
+
avoidWhen: [
|
|
765
|
+
'The chart needs axes, dense labels, or higher detail.',
|
|
766
|
+
'The audience needs exact values rather than a quick trend read.',
|
|
767
|
+
],
|
|
768
|
+
related: ['brailleChartSurface()', 'statsPanelSurface()', 'perfOverlaySurface()'],
|
|
769
|
+
exampleArgs: {
|
|
770
|
+
values: [1, 5, 3, 8, 2, 7],
|
|
771
|
+
width: 8,
|
|
772
|
+
},
|
|
773
|
+
},
|
|
774
|
+
{
|
|
775
|
+
toolName: 'bijou_braille_chart',
|
|
776
|
+
family: 'brailleChartSurface()',
|
|
777
|
+
category: 'Data Visualization',
|
|
778
|
+
summary: 'High-density filled area chart using Unicode Braille sub-pixels.',
|
|
779
|
+
aliases: ['braille chart', 'area chart', 'dense chart', 'tiny chart'],
|
|
780
|
+
useWhen: [
|
|
781
|
+
'You need more visual density than a sparkline can provide.',
|
|
782
|
+
'The chart should stay text-native but still show trend shape clearly.',
|
|
783
|
+
],
|
|
784
|
+
avoidWhen: [
|
|
785
|
+
'Exact values or labeled axes matter more than density.',
|
|
786
|
+
'A single metric trend is compact enough for sparkline().',
|
|
787
|
+
],
|
|
788
|
+
related: ['sparkline()', 'statsPanelSurface()', 'perfOverlaySurface()'],
|
|
789
|
+
exampleArgs: {
|
|
790
|
+
values: [1, 4, 2, 8, 3, 7, 5],
|
|
791
|
+
width: 16,
|
|
792
|
+
height: 4,
|
|
793
|
+
},
|
|
794
|
+
},
|
|
795
|
+
{
|
|
796
|
+
toolName: 'bijou_stats_panel',
|
|
797
|
+
family: 'statsPanelSurface()',
|
|
798
|
+
category: 'Data Visualization',
|
|
799
|
+
summary: 'Aligned metrics panel with labels, values, and optional inline sparklines.',
|
|
800
|
+
aliases: ['stats panel', 'metrics panel', 'telemetry panel', 'perf panel'],
|
|
801
|
+
useWhen: [
|
|
802
|
+
'Several metrics belong together inside one compact panel.',
|
|
803
|
+
'Labels, values, and small trends should stay aligned and readable.',
|
|
804
|
+
],
|
|
805
|
+
avoidWhen: [
|
|
806
|
+
'You only need one metric and a badge or inline value would do.',
|
|
807
|
+
'The content is narrative or workflow guidance rather than telemetry.',
|
|
808
|
+
],
|
|
809
|
+
related: ['sparkline()', 'brailleChartSurface()', 'perfOverlaySurface()'],
|
|
810
|
+
exampleArgs: {
|
|
811
|
+
entries: [
|
|
812
|
+
{ label: 'FPS', value: '60' },
|
|
813
|
+
{ label: 'frame', value: '16.7 ms', sparkline: [15.8, 16.1, 16.7, 16.4, 17.0] },
|
|
814
|
+
],
|
|
815
|
+
title: 'Perf',
|
|
816
|
+
width: 28,
|
|
817
|
+
},
|
|
818
|
+
},
|
|
819
|
+
{
|
|
820
|
+
toolName: 'bijou_perf_overlay',
|
|
821
|
+
family: 'perfOverlaySurface()',
|
|
822
|
+
category: 'Data Visualization',
|
|
823
|
+
summary: 'Prebuilt performance dashboard combining a stats panel and braille chart.',
|
|
824
|
+
aliases: ['perf overlay', 'performance overlay', 'telemetry overlay', 'fps overlay'],
|
|
825
|
+
useWhen: [
|
|
826
|
+
'You need an immediately useful perf HUD without composing several primitives yourself.',
|
|
827
|
+
'Frame timing, terminal size, and memory should be visible together as one overlay.',
|
|
828
|
+
],
|
|
829
|
+
avoidWhen: [
|
|
830
|
+
'The app only needs one inline metric or a small sparkline.',
|
|
831
|
+
'The shell should stay clean and no telemetry overlay belongs on screen.',
|
|
832
|
+
],
|
|
833
|
+
related: ['statsPanelSurface()', 'brailleChartSurface()', 'sparkline()'],
|
|
834
|
+
exampleArgs: {
|
|
835
|
+
fps: 60,
|
|
836
|
+
frameTimeMs: 16.7,
|
|
837
|
+
frameTimeHistory: [15.8, 16.1, 16.7, 16.4, 17.0],
|
|
838
|
+
width: 80,
|
|
839
|
+
height: 24,
|
|
840
|
+
title: 'Perf',
|
|
841
|
+
},
|
|
842
|
+
},
|
|
843
|
+
{
|
|
844
|
+
toolName: 'bijou_branding',
|
|
845
|
+
family: 'loadRandomLogo() / gradientText()',
|
|
846
|
+
category: 'Narrative and Content',
|
|
847
|
+
summary: 'Expressive branding helpers for deliberate splash, celebratory, and docs-opening moments.',
|
|
848
|
+
aliases: ['branding', 'logo', 'gradient text', 'splash', 'hero'],
|
|
849
|
+
useWhen: [
|
|
850
|
+
'The interface needs a deliberate branded or celebratory moment.',
|
|
851
|
+
'Expressive emphasis helps open or orient the experience without carrying critical state.',
|
|
852
|
+
],
|
|
853
|
+
avoidWhen: [
|
|
854
|
+
'Routine app chrome or task-critical labels need maximum scanability.',
|
|
855
|
+
'Decoration would compete with the actual work or hide meaning behind color.',
|
|
856
|
+
],
|
|
857
|
+
related: ['markdown()', 'box()', 'renderByMode()'],
|
|
858
|
+
exampleArgs: {
|
|
859
|
+
logo: 'BIJOU',
|
|
860
|
+
headline: 'Release ready',
|
|
861
|
+
},
|
|
862
|
+
},
|
|
863
|
+
{
|
|
864
|
+
toolName: 'bijou_mode_aware_authoring',
|
|
865
|
+
family: 'renderByMode()',
|
|
866
|
+
category: 'Utility',
|
|
867
|
+
summary: 'Authoring helper for building one semantic primitive that lowers honestly across output modes.',
|
|
868
|
+
aliases: ['renderByMode', 'mode-aware primitive', 'custom primitive', 'lowering'],
|
|
869
|
+
useWhen: [
|
|
870
|
+
'An app needs a domain-specific primitive that does not belong in the shared component catalog.',
|
|
871
|
+
'The same semantic thing must lower honestly across interactive, pipe, and accessible modes.',
|
|
872
|
+
],
|
|
873
|
+
avoidWhen: [
|
|
874
|
+
'An existing Bijou family already matches the job.',
|
|
875
|
+
'Mode branching would only chase cosmetics instead of preserving meaning.',
|
|
876
|
+
],
|
|
877
|
+
related: ['note()', 'badge()', 'markdown()'],
|
|
878
|
+
exampleArgs: {
|
|
879
|
+
semanticThing: 'build health',
|
|
880
|
+
interactive: '[build][healthy]',
|
|
881
|
+
pipe: 'build health: healthy',
|
|
882
|
+
accessible: 'Build health is healthy.',
|
|
883
|
+
},
|
|
884
|
+
},
|
|
885
|
+
];
|
|
886
|
+
const DOCS_ONLY_EXAMPLE_RENDERERS = {
|
|
887
|
+
bijou_markdown: (args) => stripAnsi(markdown(String(args['source'] ?? ''), {
|
|
888
|
+
width: typeof args['width'] === 'number' ? args['width'] : undefined,
|
|
889
|
+
ctx: mcpContext(typeof args['width'] === 'number' ? args['width'] : undefined),
|
|
890
|
+
})),
|
|
891
|
+
bijou_note: (args) => {
|
|
892
|
+
const title = typeof args['title'] === 'string' ? args['title'] : undefined;
|
|
893
|
+
const message = String(args['message'] ?? '');
|
|
894
|
+
return title ? `Note (${title}): ${message}` : `Note: ${message}`;
|
|
895
|
+
},
|
|
896
|
+
bijou_guided_flow: (args) => stripAnsi(guidedFlow({
|
|
897
|
+
...args,
|
|
898
|
+
ctx: mcpContext(typeof args['width'] === 'number' ? args['width'] : undefined),
|
|
899
|
+
})),
|
|
900
|
+
bijou_preference_list: (args) => surfaceToString(preferenceListSurface(args['sections'], {
|
|
901
|
+
width: Number(args['width'] ?? 40),
|
|
902
|
+
selectedRowId: typeof args['selectedRowId'] === 'string' ? args['selectedRowId'] : undefined,
|
|
903
|
+
ctx: mcpContext(typeof args['width'] === 'number' ? args['width'] : undefined),
|
|
904
|
+
}), plainStyle()),
|
|
905
|
+
bijou_text_entry: (args) => {
|
|
906
|
+
const inputTitle = String(args['inputTitle'] ?? 'Cluster name');
|
|
907
|
+
const inputDefault = String(args['inputDefault'] ?? '');
|
|
908
|
+
const textareaTitle = String(args['textareaTitle'] ?? 'Details');
|
|
909
|
+
const textareaValue = String(args['textareaValue'] ?? '');
|
|
910
|
+
return `${inputTitle}? [${inputDefault}]\n${textareaTitle}?\n${textareaValue}`;
|
|
911
|
+
},
|
|
912
|
+
bijou_single_choice: (args) => {
|
|
913
|
+
const title = String(args['title'] ?? 'Select one');
|
|
914
|
+
const options = Array.isArray(args['options']) ? args['options'].map(String) : [];
|
|
915
|
+
const selected = String(args['selected'] ?? options[0] ?? '');
|
|
916
|
+
const numbered = options.map((option, index) => `${index + 1}. ${option}`).join('\n');
|
|
917
|
+
const selectedIndex = Math.max(options.findIndex((option) => option === selected), 0) + 1;
|
|
918
|
+
return `${title}?\n${numbered}\n> ${selectedIndex}\nSelected: ${selected}`;
|
|
919
|
+
},
|
|
920
|
+
bijou_multiple_choice: (args) => {
|
|
921
|
+
const title = String(args['title'] ?? 'Select one or more');
|
|
922
|
+
const options = Array.isArray(args['options']) ? args['options'].map(String) : [];
|
|
923
|
+
const selected = new Set(Array.isArray(args['selected']) ? args['selected'].map(String) : []);
|
|
924
|
+
const lines = options.map((option) => `[${selected.has(option) ? 'x' : ' '}] ${option}`);
|
|
925
|
+
return `${title}?\n${lines.join('\n')}\nSelected: ${Array.from(selected).join(', ')}`;
|
|
926
|
+
},
|
|
927
|
+
bijou_binary_decision: (args) => {
|
|
928
|
+
const title = String(args['title'] ?? 'Continue');
|
|
929
|
+
const defaultValue = args['defaultValue'] === false ? '[y/N]' : '[Y/n]';
|
|
930
|
+
const answer = String(args['answer'] ?? '');
|
|
931
|
+
return `${title}? ${defaultValue}\n> ${answer}`;
|
|
932
|
+
},
|
|
933
|
+
bijou_multi_field_forms: (args) => {
|
|
934
|
+
const stepLabel = String(args['stepLabel'] ?? 'Step 1 of 1');
|
|
935
|
+
const stepTitle = String(args['stepTitle'] ?? 'Details');
|
|
936
|
+
const fields = Array.isArray(args['fields']) ? args['fields'].map(String) : [];
|
|
937
|
+
return `${stepLabel}: ${stepTitle}\n${fields.join('\n')}`;
|
|
938
|
+
},
|
|
939
|
+
bijou_spinner: (args) => spinnerFrame(Number(args['tick'] ?? 0), {
|
|
940
|
+
label: typeof args['label'] === 'string' ? args['label'] : undefined,
|
|
941
|
+
}),
|
|
942
|
+
bijou_timer: (args) => stripAnsi(timer(Number(args['ms'] ?? 0), {
|
|
943
|
+
label: typeof args['label'] === 'string' ? args['label'] : undefined,
|
|
944
|
+
ctx: mcpContext(),
|
|
945
|
+
})),
|
|
946
|
+
bijou_sparkline: (args) => sparkline(args['values'] ?? [], { width: typeof args['width'] === 'number' ? args['width'] : undefined }),
|
|
947
|
+
bijou_braille_chart: (args) => surfaceToString(brailleChartSurface(args['values'] ?? [], {
|
|
948
|
+
width: Number(args['width'] ?? 0),
|
|
949
|
+
height: Number(args['height'] ?? 0),
|
|
950
|
+
ctx: mcpContext(typeof args['width'] === 'number' ? args['width'] : undefined),
|
|
951
|
+
}), plainStyle()),
|
|
952
|
+
bijou_stats_panel: (args) => surfaceToString(statsPanelSurface(args['entries'] ?? [], {
|
|
953
|
+
title: typeof args['title'] === 'string' ? args['title'] : undefined,
|
|
954
|
+
width: Number(args['width'] ?? 28),
|
|
955
|
+
ctx: mcpContext(typeof args['width'] === 'number' ? args['width'] : undefined),
|
|
956
|
+
}), plainStyle()),
|
|
957
|
+
bijou_perf_overlay: (args) => surfaceToString(perfOverlaySurface({
|
|
958
|
+
fps: Number(args['fps'] ?? 0),
|
|
959
|
+
frameTimeMs: Number(args['frameTimeMs'] ?? 0),
|
|
960
|
+
frameTimeHistory: args['frameTimeHistory'] ?? [],
|
|
961
|
+
width: Number(args['width'] ?? 80),
|
|
962
|
+
height: Number(args['height'] ?? 24),
|
|
963
|
+
}, {
|
|
964
|
+
title: typeof args['title'] === 'string' ? args['title'] : undefined,
|
|
965
|
+
ctx: mcpContext(typeof args['width'] === 'number' ? args['width'] : undefined),
|
|
966
|
+
}), plainStyle()),
|
|
967
|
+
bijou_branding: (args) => {
|
|
968
|
+
const logo = String(args['logo'] ?? 'BIJOU');
|
|
969
|
+
const headline = String(args['headline'] ?? '');
|
|
970
|
+
return `${logo}\n${headline}`.trimEnd();
|
|
971
|
+
},
|
|
972
|
+
bijou_mode_aware_authoring: (args) => {
|
|
973
|
+
const semanticThing = String(args['semanticThing'] ?? 'semantic thing');
|
|
974
|
+
return [
|
|
975
|
+
`${semanticThing}:`,
|
|
976
|
+
`interactive -> ${String(args['interactive'] ?? '[rich output]')}`,
|
|
977
|
+
`pipe -> ${String(args['pipe'] ?? 'plain fallback')}`,
|
|
978
|
+
`accessible -> ${String(args['accessible'] ?? 'explicit reading-order fallback')}`,
|
|
979
|
+
].join('\n');
|
|
980
|
+
},
|
|
981
|
+
};
|
|
982
|
+
function normalizeDocsTerm(value) {
|
|
983
|
+
return value.toLowerCase().replace(/[^a-z0-9]+/g, ' ').trim();
|
|
984
|
+
}
|
|
985
|
+
function scoreDocsEntry(entry, normalizedQuery) {
|
|
986
|
+
if (normalizedQuery === '')
|
|
987
|
+
return 1;
|
|
988
|
+
const primaryFields = [
|
|
989
|
+
entry.toolName,
|
|
990
|
+
entry.family,
|
|
991
|
+
entry.category,
|
|
992
|
+
...entry.aliases,
|
|
993
|
+
].map(normalizeDocsTerm);
|
|
994
|
+
const secondaryFields = [
|
|
995
|
+
entry.summary,
|
|
996
|
+
...entry.related,
|
|
997
|
+
].map(normalizeDocsTerm);
|
|
998
|
+
if (primaryFields.some(value => value === normalizedQuery))
|
|
999
|
+
return 100;
|
|
1000
|
+
if (primaryFields.some(value => value.startsWith(normalizedQuery)))
|
|
1001
|
+
return 80;
|
|
1002
|
+
let score = primaryFields.some(value => value.includes(normalizedQuery)) ? 40 : 0;
|
|
1003
|
+
if (secondaryFields.some(value => value === normalizedQuery))
|
|
1004
|
+
score += 20;
|
|
1005
|
+
if (secondaryFields.some(value => value.includes(normalizedQuery)))
|
|
1006
|
+
score += 10;
|
|
1007
|
+
const tokens = normalizedQuery.split(/\s+/).filter(Boolean);
|
|
1008
|
+
for (const token of tokens) {
|
|
1009
|
+
if (primaryFields.some(value => value.includes(token)))
|
|
1010
|
+
score += 10;
|
|
1011
|
+
else if (secondaryFields.some(value => value.includes(token)))
|
|
1012
|
+
score += 4;
|
|
1013
|
+
}
|
|
1014
|
+
return score;
|
|
1015
|
+
}
|
|
1016
|
+
function exampleText(result) {
|
|
1017
|
+
return result.content.find((block) => block.type === 'text')?.text
|
|
1018
|
+
?? (typeof result.structuredContent?.['rendered'] === 'string'
|
|
1019
|
+
? result.structuredContent['rendered']
|
|
1020
|
+
: '');
|
|
1021
|
+
}
|
|
1022
|
+
function resolvedInteractionProfiles(entry, mcpExposed) {
|
|
1023
|
+
return {
|
|
1024
|
+
...(mcpExposed ? DEFAULT_INTERACTION_PROFILES : DEFAULT_DOCS_ONLY_INTERACTION_PROFILES),
|
|
1025
|
+
...entry.interactionProfiles,
|
|
1026
|
+
};
|
|
1027
|
+
}
|
|
1028
|
+
export function createDocsTool(tools) {
|
|
1029
|
+
const toolMap = new Map(tools.map(tool => [tool.name, tool]));
|
|
1030
|
+
const documentedEntries = MCP_DOCS_CATALOG.map((entry) => {
|
|
1031
|
+
const tool = toolMap.get(entry.toolName);
|
|
1032
|
+
const docsOnlyRenderer = DOCS_ONLY_EXAMPLE_RENDERERS[entry.toolName];
|
|
1033
|
+
if (tool === undefined && docsOnlyRenderer === undefined) {
|
|
1034
|
+
throw new Error(`[bijou-mcp] bijou_docs catalog entry "${entry.toolName}" has no matching tool registration or docs-only example renderer`);
|
|
1035
|
+
}
|
|
1036
|
+
return { entry, tool, docsOnlyRenderer, mcpExposed: tool !== undefined };
|
|
1037
|
+
});
|
|
1038
|
+
const inputShape = withOutputMode({
|
|
1039
|
+
query: z.string().optional().describe('Tool or component query (for example "table", "dag", or "progress").'),
|
|
1040
|
+
limit: z.number().int().positive().max(50).optional().describe('Maximum number of entries to return.'),
|
|
1041
|
+
includeExamples: z.boolean().optional().describe('Include rendered example output and sample input for the returned entries. Defaults to true when the result set is small.'),
|
|
1042
|
+
});
|
|
1043
|
+
const inputSchema = z.object(inputShape);
|
|
1044
|
+
return {
|
|
1045
|
+
name: 'bijou_docs',
|
|
1046
|
+
description: 'Query machine-readable documentation for the bijou-mcp render-tool surface plus the full public first-party Bijou component-family surface, including docs-only families that do not yet have dedicated MCP renderers. Returns usage guidance, interaction-profile notes, related tools, sample input, and optional rendered example output.',
|
|
1047
|
+
inputSchema: inputShape,
|
|
1048
|
+
outputSchema: structuredToolOutputShape,
|
|
1049
|
+
handler: async (args) => {
|
|
1050
|
+
const input = inputSchema.parse(args);
|
|
1051
|
+
const normalizedQuery = normalizeDocsTerm(input.query ?? '');
|
|
1052
|
+
const ranked = documentedEntries
|
|
1053
|
+
.map(({ entry, tool, docsOnlyRenderer, mcpExposed }) => ({
|
|
1054
|
+
entry,
|
|
1055
|
+
tool,
|
|
1056
|
+
docsOnlyRenderer,
|
|
1057
|
+
mcpExposed,
|
|
1058
|
+
score: scoreDocsEntry(entry, normalizedQuery),
|
|
1059
|
+
}))
|
|
1060
|
+
.filter(({ score }) => normalizedQuery === '' || score > 0)
|
|
1061
|
+
.sort((a, b) => b.score - a.score || a.entry.family.localeCompare(b.entry.family));
|
|
1062
|
+
const limit = input.limit ?? (normalizedQuery === '' ? ranked.length : 3);
|
|
1063
|
+
const selected = ranked.slice(0, limit);
|
|
1064
|
+
const includeExamples = input.includeExamples ?? normalizedQuery !== '';
|
|
1065
|
+
const entries = await Promise.all(selected.map(async ({ entry, tool, docsOnlyRenderer, mcpExposed }) => {
|
|
1066
|
+
const result = {
|
|
1067
|
+
tool: entry.toolName,
|
|
1068
|
+
mcpExposed,
|
|
1069
|
+
family: entry.family,
|
|
1070
|
+
category: entry.category,
|
|
1071
|
+
summary: entry.summary,
|
|
1072
|
+
useWhen: entry.useWhen,
|
|
1073
|
+
avoidWhen: entry.avoidWhen,
|
|
1074
|
+
interactionProfiles: resolvedInteractionProfiles(entry, mcpExposed),
|
|
1075
|
+
related: entry.related,
|
|
1076
|
+
aliases: entry.aliases,
|
|
1077
|
+
};
|
|
1078
|
+
if (entry.exampleArgs !== undefined) {
|
|
1079
|
+
result['exampleInput'] = entry.exampleArgs;
|
|
1080
|
+
}
|
|
1081
|
+
if (includeExamples && entry.exampleArgs !== undefined) {
|
|
1082
|
+
if (tool !== undefined) {
|
|
1083
|
+
result['exampleOutput'] = exampleText(await tool.handler(entry.exampleArgs));
|
|
1084
|
+
}
|
|
1085
|
+
else if (docsOnlyRenderer !== undefined) {
|
|
1086
|
+
result['exampleOutput'] = docsOnlyRenderer(entry.exampleArgs);
|
|
1087
|
+
}
|
|
1088
|
+
}
|
|
1089
|
+
return result;
|
|
1090
|
+
}));
|
|
1091
|
+
const payload = {
|
|
1092
|
+
scope: 'bijou-mcp',
|
|
1093
|
+
note: 'This catalog covers the current bijou-mcp render-tool surface plus the public first-party Bijou component-family surface, including docs-only families that are documented here before they gain dedicated MCP render tools. Broader DOGFOOD-level field-guide extraction remains future expansion.',
|
|
1094
|
+
documentedEntries: documentedEntries.length,
|
|
1095
|
+
documentedTools: documentedEntries.filter(({ mcpExposed }) => mcpExposed).length,
|
|
1096
|
+
docsOnlyEntries: documentedEntries.filter(({ mcpExposed }) => !mcpExposed).length,
|
|
1097
|
+
returnedEntries: entries.length,
|
|
1098
|
+
query: input.query ?? null,
|
|
1099
|
+
includeExamples,
|
|
1100
|
+
entries,
|
|
1101
|
+
};
|
|
1102
|
+
return buildStructuredToolResult(JSON.stringify(payload, null, 2), payload, input.output ?? 'text');
|
|
1103
|
+
},
|
|
1104
|
+
};
|
|
1105
|
+
}
|
|
1106
|
+
//# sourceMappingURL=docs.js.map
|