@mccaskie-labs/workbench-config 0.2.2 → 0.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/capabilities/ai.json +183 -3
- package/capabilities/image-search.json +154 -3
- package/capabilities/images.json +192 -3
- package/capabilities/pdf.json +87 -3
- package/dist/capabilities.gen.d.ts +485 -6
- package/dist/capabilities.gen.js +614 -10
- package/dist/capability-schema.d.ts +1 -1
- package/dist/capability-schema.js +1 -1
- package/dist/skills.js +6 -3
- package/package.json +1 -1
package/capabilities/pdf.json
CHANGED
|
@@ -7,13 +7,14 @@
|
|
|
7
7
|
"status": "built",
|
|
8
8
|
"delivery": {
|
|
9
9
|
"choice": "optional",
|
|
10
|
-
"intro": "PDFs such as invoices and receipts, printed with the project's logo and colours."
|
|
11
|
-
"when": "The client wants a PDF: an invoice, receipt, quote, certificate, report or anything else to download or print."
|
|
10
|
+
"intro": "PDFs such as invoices and receipts, printed with the project's logo and colours."
|
|
12
11
|
},
|
|
13
12
|
"surfaces": {
|
|
14
13
|
"package": [
|
|
15
14
|
"createPdfMaker",
|
|
16
|
-
"WorkbenchPdfError"
|
|
15
|
+
"WorkbenchPdfError",
|
|
16
|
+
"checkLayout",
|
|
17
|
+
"fillLayout"
|
|
17
18
|
]
|
|
18
19
|
},
|
|
19
20
|
"limits": [
|
|
@@ -95,6 +96,89 @@
|
|
|
95
96
|
"note": "Prints the app's own HTML holding an image from a host not in allowOrigins; the PDF is made and the browser reports that image's request as blocked"
|
|
96
97
|
}
|
|
97
98
|
],
|
|
99
|
+
"offer": {
|
|
100
|
+
"pattern": "drafts",
|
|
101
|
+
"when": "The client wants a PDF: an invoice, receipt, quote, certificate, report or anything else to download or print.",
|
|
102
|
+
"say": "I'll make this with Workbench PDFs, printed with your logo and colours. I'll show you a few layouts to pick from. The one you pick is saved, so every one looks the same from then on.",
|
|
103
|
+
"answers_file": "workbench/pdf/<name>.json",
|
|
104
|
+
"per": "document",
|
|
105
|
+
"generator": "npx workbench-pdf generate",
|
|
106
|
+
"answers_format": "the saved layout. `npx workbench-pdf pick <name> <round>-<draft>` writes it from the draft the client picked, with the draft's request id, model and cost; never write one from nothing. It holds the document's `fields` (each value is text the app formats first, money and dates through the country pack), its `blocks` with `{field}` placeholders, and made-up `sample` values. To change a saved layout in the client's words (move a block, rename a heading, add a field), edit the file and run the generator, which refuses a layout that doesn't check. In the app, print with `pdfMakerFor(env).document(PDF_LAYOUTS.<name>.document(data), { size: PDF_LAYOUTS.<name>.size })`. Drafts and their previews stay in `workbench/pdf/drafts/`, which isn't committed.",
|
|
107
|
+
"questions": [
|
|
108
|
+
{
|
|
109
|
+
"id": "pdf.what",
|
|
110
|
+
"sets": [
|
|
111
|
+
"layout.name",
|
|
112
|
+
"layout.about"
|
|
113
|
+
],
|
|
114
|
+
"ask": "What is this document, and what is it for?",
|
|
115
|
+
"style": "cards",
|
|
116
|
+
"answers": [
|
|
117
|
+
{
|
|
118
|
+
"label": "An invoice",
|
|
119
|
+
"value": "invoice",
|
|
120
|
+
"means": "What a customer owes, with the items and the total."
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
"label": "A receipt",
|
|
124
|
+
"value": "receipt",
|
|
125
|
+
"means": "Proof a customer paid."
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
"label": "A quote",
|
|
129
|
+
"value": "quote",
|
|
130
|
+
"means": "What a job would cost, before the customer agrees."
|
|
131
|
+
}
|
|
132
|
+
],
|
|
133
|
+
"other": {
|
|
134
|
+
"kind": "text",
|
|
135
|
+
"min": 3,
|
|
136
|
+
"max": 200,
|
|
137
|
+
"description": "What the document is, in a few words: a certificate, a run sheet, a booking confirmation."
|
|
138
|
+
},
|
|
139
|
+
"note": "The answer's value is the layout's name (lower case and underscores: run_sheet). The client's own words, with anything they add about who reads it, go in --about.",
|
|
140
|
+
"must_ask": true
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
"id": "pdf.size",
|
|
144
|
+
"sets": "layout.size",
|
|
145
|
+
"ask": "Which paper size?",
|
|
146
|
+
"style": "cards",
|
|
147
|
+
"answers": [
|
|
148
|
+
{
|
|
149
|
+
"label": "A4",
|
|
150
|
+
"value": "A4",
|
|
151
|
+
"means": "Used almost everywhere outside North America."
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
"label": "US Letter",
|
|
155
|
+
"value": "Letter",
|
|
156
|
+
"means": "Used in the United States and Canada."
|
|
157
|
+
}
|
|
158
|
+
],
|
|
159
|
+
"note": "Recommend US Letter only when the readers are in the United States or Canada. Pass it to the drafts command as --size."
|
|
160
|
+
}
|
|
161
|
+
],
|
|
162
|
+
"not_asked": [
|
|
163
|
+
{
|
|
164
|
+
"sets": "layout.colours",
|
|
165
|
+
"why": "The logo, colours and fonts come from the brand (brand.json and the admins' brand page), so every document matches the rest of the app. To restyle a part of the layout, use project.css (see Restyling)."
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
"sets": "layout.contents",
|
|
169
|
+
"why": "The drafts propose what each layout shows. The client changes a picked layout in plain words, and you edit the saved file."
|
|
170
|
+
}
|
|
171
|
+
],
|
|
172
|
+
"drafts": {
|
|
173
|
+
"of": "layouts for this document",
|
|
174
|
+
"surface": "ai",
|
|
175
|
+
"alias": "claude-default",
|
|
176
|
+
"count": 3,
|
|
177
|
+
"max_rounds": 3,
|
|
178
|
+
"job": "pdf.drafts",
|
|
179
|
+
"command": "npx workbench-pdf drafts <name> --about \"<what it is for, in the client's words>\" --size <A4 or Letter>"
|
|
180
|
+
}
|
|
181
|
+
},
|
|
98
182
|
"styles": {
|
|
99
183
|
"prefix": "wb-pdf-"
|
|
100
184
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const MANIFEST_VERSION: "
|
|
1
|
+
export declare const MANIFEST_VERSION: "15786d683e1e";
|
|
2
2
|
export declare const capabilities: {
|
|
3
3
|
readonly ai: {
|
|
4
4
|
readonly $schema: "./schema.json";
|
|
@@ -194,10 +194,152 @@ export declare const capabilities: {
|
|
|
194
194
|
readonly expect: "pass";
|
|
195
195
|
readonly cost_hint_usd: 0.008;
|
|
196
196
|
}];
|
|
197
|
+
readonly offer: {
|
|
198
|
+
readonly pattern: "feature_or_content";
|
|
199
|
+
readonly when: "The client wants the app to write, summarise, sort, answer questions or pull details out of text with AI, as a feature visitors use, or wants wording for the site written once.";
|
|
200
|
+
readonly say: "I'll do this with Workbench AI, which uses Claude through Workbench, so the app holds no AI key and spending has a monthly cap.";
|
|
201
|
+
readonly answers_file: "workbench/ai/<name>.json";
|
|
202
|
+
readonly per: "feature or piece of wording";
|
|
203
|
+
readonly answers_format: "For a feature: `{ \"format\": 1, \"route\": \"feature\", \"name\", \"about\" (the client's words), \"who\", \"cap_usd\", \"keep\", \"job\" }`, where `job` is the `X-Workbench-Job` the feature's calls send (`<name>` with dots, such as `quotes.estimate`), so its spending shows on its own line in Control. Write it, then build the feature with the package. For wording made once: `npx workbench-ai pick <name> <round>-<draft>` writes it from the draft the client picked, with the round's request ids and cost; never write one from nothing. Then put the wording into the strings catalogue (the workbench-strings skill), keyed for where it is shown. Drafts and their previews stay in `workbench/ai/drafts/`, which isn't committed.";
|
|
204
|
+
readonly questions: readonly [{
|
|
205
|
+
readonly id: "ai.route";
|
|
206
|
+
readonly sets: "route";
|
|
207
|
+
readonly ask: "Is this something visitors use on the site, or something made once for the site?";
|
|
208
|
+
readonly style: "cards";
|
|
209
|
+
readonly answers: readonly [{
|
|
210
|
+
readonly label: "Visitors use it";
|
|
211
|
+
readonly value: "feature";
|
|
212
|
+
readonly means: "A feature on the site that calls the AI each time someone uses it, such as a question box or a summary of what they paste in.";
|
|
213
|
+
}, {
|
|
214
|
+
readonly label: "Made once for the site";
|
|
215
|
+
readonly value: "content";
|
|
216
|
+
readonly means: "Wording for a page, written once and kept: an About page, a welcome, product descriptions.";
|
|
217
|
+
}];
|
|
218
|
+
readonly must_ask: true;
|
|
219
|
+
readonly note: "Ask it even when the client's words seem to say, as a quick check: the two routes are built and paid for differently.";
|
|
220
|
+
}, {
|
|
221
|
+
readonly id: "ai.who";
|
|
222
|
+
readonly sets: "feature.who";
|
|
223
|
+
readonly ask: "Who may use it?";
|
|
224
|
+
readonly style: "cards";
|
|
225
|
+
readonly answers: readonly [{
|
|
226
|
+
readonly label: "People who are signed in";
|
|
227
|
+
readonly value: "signed_in";
|
|
228
|
+
readonly means: "Anyone with an account. Each use is tied to a person, so misuse can be traced and stopped.";
|
|
229
|
+
}, {
|
|
230
|
+
readonly label: "Admins only";
|
|
231
|
+
readonly value: "admins";
|
|
232
|
+
readonly means: "Only the business's own admins, for example a tool for writing their own posts.";
|
|
233
|
+
}, {
|
|
234
|
+
readonly label: "Anyone visiting";
|
|
235
|
+
readonly value: "anyone";
|
|
236
|
+
readonly means: "No sign-in. The page checks for bots (Turnstile) and limits how often one visitor can use it.";
|
|
237
|
+
}];
|
|
238
|
+
readonly when: {
|
|
239
|
+
readonly id: "ai.route";
|
|
240
|
+
readonly is: readonly ["feature"];
|
|
241
|
+
};
|
|
242
|
+
readonly note: "Signed in means `requireUser` and admins means `app_admins`, as the workbench-sign-in skill says. For anyone, check Turnstile on every use and keep a per-visitor limit; say plainly that strangers can run up the cost. Pass `subject` on every call so the Gateway can tell people apart: `user:<id>` for a signed-in person, and for anyone a random id kept in a cookie (`visitor:<id>`), never an email address or name.";
|
|
243
|
+
}, {
|
|
244
|
+
readonly id: "ai.cap";
|
|
245
|
+
readonly sets: "feature.cap_usd";
|
|
246
|
+
readonly ask: "How much may it spend in a month, at most? When it's reached, the feature stops until next month.";
|
|
247
|
+
readonly style: "cards";
|
|
248
|
+
readonly answers: readonly [{
|
|
249
|
+
readonly label: "US$5 a month";
|
|
250
|
+
readonly value: 5;
|
|
251
|
+
readonly means: "A small trial, or light use.";
|
|
252
|
+
}, {
|
|
253
|
+
readonly label: "US$20 a month";
|
|
254
|
+
readonly value: 20;
|
|
255
|
+
readonly means: "Steady use by a small business's visitors.";
|
|
256
|
+
}, {
|
|
257
|
+
readonly label: "US$50 a month";
|
|
258
|
+
readonly value: 50;
|
|
259
|
+
readonly means: "Heavy use. It can be raised later.";
|
|
260
|
+
}];
|
|
261
|
+
readonly other: {
|
|
262
|
+
readonly kind: "money";
|
|
263
|
+
readonly min: 1;
|
|
264
|
+
readonly max: 1000;
|
|
265
|
+
readonly description: "US dollars a month, whole or with cents.";
|
|
266
|
+
};
|
|
267
|
+
readonly must_ask: true;
|
|
268
|
+
readonly when: {
|
|
269
|
+
readonly id: "ai.route";
|
|
270
|
+
readonly is: readonly ["feature"];
|
|
271
|
+
};
|
|
272
|
+
readonly note: "Say roughly what one use costs (usually a cent or two with claude-default) so the owner can judge. The cap is the project's production cap for the `ai` tool in the Gateway, shared by every feature that uses it: set it with Workbench Control's `gw_budget_set` (env production, tool ai, monthly_usd). Raising a cap waits for the owner's approval on Control's approval page. When it is reached, calls fail with `budget_exceeded`: the page says the feature is resting until next month, never an error.";
|
|
273
|
+
}, {
|
|
274
|
+
readonly id: "ai.sensitive";
|
|
275
|
+
readonly sets: "feature.keep";
|
|
276
|
+
readonly ask: "Will people type in sensitive personal details, such as their health, religion, money troubles or someone else's private information?";
|
|
277
|
+
readonly style: "cards";
|
|
278
|
+
readonly answers: readonly [{
|
|
279
|
+
readonly label: "No";
|
|
280
|
+
readonly value: "no";
|
|
281
|
+
readonly means: "Workbench keeps what each call sent and got back, so a problem can be traced.";
|
|
282
|
+
}, {
|
|
283
|
+
readonly label: "Yes";
|
|
284
|
+
readonly value: "yes";
|
|
285
|
+
readonly means: "This feature's calls are marked not to be kept: Workbench records only that each call happened and what it cost.";
|
|
286
|
+
}];
|
|
287
|
+
readonly must_ask: true;
|
|
288
|
+
readonly when: {
|
|
289
|
+
readonly id: "ai.route";
|
|
290
|
+
readonly is: readonly ["feature"];
|
|
291
|
+
};
|
|
292
|
+
readonly note: "With yes, pass `keep: false` on this feature's calls. If most of the app handles such details, suggest switching keeping off for the whole project instead (Workbench Control's `gw_keep_set`, env production, on false). Record it as `keep` (true or false) in the answers file.";
|
|
293
|
+
}, {
|
|
294
|
+
readonly id: "ai.what";
|
|
295
|
+
readonly sets: readonly ["content.name", "content.about"];
|
|
296
|
+
readonly ask: "What wording do you need?";
|
|
297
|
+
readonly style: "cards";
|
|
298
|
+
readonly answers: readonly [{
|
|
299
|
+
readonly label: "A page's main text";
|
|
300
|
+
readonly value: "page_text";
|
|
301
|
+
readonly means: "Such as an About page or a services page.";
|
|
302
|
+
}, {
|
|
303
|
+
readonly label: "A short blurb";
|
|
304
|
+
readonly value: "blurb";
|
|
305
|
+
readonly means: "A line or two for the top of a page or a card.";
|
|
306
|
+
}, {
|
|
307
|
+
readonly label: "Descriptions";
|
|
308
|
+
readonly value: "descriptions";
|
|
309
|
+
readonly means: "For products or services.";
|
|
310
|
+
}];
|
|
311
|
+
readonly other: {
|
|
312
|
+
readonly kind: "text";
|
|
313
|
+
readonly min: 3;
|
|
314
|
+
readonly max: 200;
|
|
315
|
+
readonly description: "What the wording is, in a few words.";
|
|
316
|
+
};
|
|
317
|
+
readonly when: {
|
|
318
|
+
readonly id: "ai.route";
|
|
319
|
+
readonly is: readonly ["content"];
|
|
320
|
+
};
|
|
321
|
+
readonly note: "Name the piece after where it goes (about_us, home_blurb): lower case and underscores. The client's own words, with any facts they give (when they started, where they are), go in --about, because the drafts never invent facts and leave [gaps] for the owner instead.";
|
|
322
|
+
}];
|
|
323
|
+
readonly not_asked: readonly [{
|
|
324
|
+
readonly sets: "model";
|
|
325
|
+
readonly why: "Features use claude-default unless the work needs more (claude-best) or speed matters more than depth (claude-fast). Choose from what the feature does; the client can't judge models.";
|
|
326
|
+
}, {
|
|
327
|
+
readonly sets: "voice";
|
|
328
|
+
readonly why: "The tone comes from the project's voice and spelling, set once for the whole site.";
|
|
329
|
+
}];
|
|
330
|
+
readonly drafts: {
|
|
331
|
+
readonly of: "wording";
|
|
332
|
+
readonly surface: "ai";
|
|
333
|
+
readonly alias: "claude-default";
|
|
334
|
+
readonly count: 3;
|
|
335
|
+
readonly max_rounds: 3;
|
|
336
|
+
readonly job: "ai.drafts";
|
|
337
|
+
readonly command: "npx workbench-ai drafts text <name> --about \"<what it is for, with the client's facts>\"";
|
|
338
|
+
};
|
|
339
|
+
};
|
|
197
340
|
readonly delivery: {
|
|
198
341
|
readonly choice: "built_in";
|
|
199
342
|
readonly intro: "Writing, summarising and answering questions with Claude, with a monthly spending cap.";
|
|
200
|
-
readonly when: "The client wants the app to write, summarise, sort, answer questions or pull details out of text with AI, as a feature visitors use or as something made once for the site.";
|
|
201
343
|
};
|
|
202
344
|
};
|
|
203
345
|
readonly analytics: {
|
|
@@ -1643,10 +1785,132 @@ export declare const capabilities: {
|
|
|
1643
1785
|
readonly smoke: true;
|
|
1644
1786
|
readonly cost_hint_usd: 0.001;
|
|
1645
1787
|
}];
|
|
1788
|
+
readonly offer: {
|
|
1789
|
+
readonly pattern: "feature_or_content";
|
|
1790
|
+
readonly when: "The client wants to find existing pictures on the web, for the site itself or as a search visitors use.";
|
|
1791
|
+
readonly say: "I'll do this with Workbench picture search, which searches the web through Workbench, so the app holds no search key and spending has a monthly cap.";
|
|
1792
|
+
readonly answers_file: "workbench/image-search/<name>.json";
|
|
1793
|
+
readonly per: "feature or picture";
|
|
1794
|
+
readonly answers_format: "For a feature: `{ \"format\": 1, \"route\": \"feature\", \"name\", \"about\" (the client's words), \"who\", \"cap_usd\", \"job\" }`, where `job` is the `X-Workbench-Job` the feature's calls send (`<name>` with dots, such as `quotes.estimate`), so its spending shows on its own line in Control. Write it, then build the feature with the package. For a picture found once: `npx workbench-ai pick <name> <round>-<draft> --licence \"<the owner's words>\"` downloads it to `public/images/<name>.jpg` (or .png) and writes the answers file with where it came from and the licence; never write one from nothing, and never pick one without the licence answer. Show the credit the licence asks for beside the picture. Drafts and their previews stay in `workbench/image-search/drafts/`, which isn't committed.";
|
|
1795
|
+
readonly questions: readonly [{
|
|
1796
|
+
readonly id: "image-search.route";
|
|
1797
|
+
readonly sets: "route";
|
|
1798
|
+
readonly ask: "Is this something visitors use on the site, or something made once for the site?";
|
|
1799
|
+
readonly style: "cards";
|
|
1800
|
+
readonly answers: readonly [{
|
|
1801
|
+
readonly label: "Visitors use it";
|
|
1802
|
+
readonly value: "feature";
|
|
1803
|
+
readonly means: "A search on the site that finds pictures for whoever uses it.";
|
|
1804
|
+
}, {
|
|
1805
|
+
readonly label: "Made once for the site";
|
|
1806
|
+
readonly value: "content";
|
|
1807
|
+
readonly means: "A picture for the site, found once and kept.";
|
|
1808
|
+
}];
|
|
1809
|
+
readonly must_ask: true;
|
|
1810
|
+
readonly note: "Ask it even when the client's words seem to say, as a quick check: the two routes are built and paid for differently.";
|
|
1811
|
+
}, {
|
|
1812
|
+
readonly id: "image-search.who";
|
|
1813
|
+
readonly sets: "feature.who";
|
|
1814
|
+
readonly ask: "Who may use it?";
|
|
1815
|
+
readonly style: "cards";
|
|
1816
|
+
readonly answers: readonly [{
|
|
1817
|
+
readonly label: "People who are signed in";
|
|
1818
|
+
readonly value: "signed_in";
|
|
1819
|
+
readonly means: "Anyone with an account. Each use is tied to a person, so misuse can be traced and stopped.";
|
|
1820
|
+
}, {
|
|
1821
|
+
readonly label: "Admins only";
|
|
1822
|
+
readonly value: "admins";
|
|
1823
|
+
readonly means: "Only the business's own admins, for example a tool for writing their own posts.";
|
|
1824
|
+
}, {
|
|
1825
|
+
readonly label: "Anyone visiting";
|
|
1826
|
+
readonly value: "anyone";
|
|
1827
|
+
readonly means: "No sign-in. The page checks for bots (Turnstile) and limits how often one visitor can use it.";
|
|
1828
|
+
}];
|
|
1829
|
+
readonly when: {
|
|
1830
|
+
readonly id: "image-search.route";
|
|
1831
|
+
readonly is: readonly ["feature"];
|
|
1832
|
+
};
|
|
1833
|
+
readonly note: "Signed in means `requireUser` and admins means `app_admins`, as the workbench-sign-in skill says. For anyone, check Turnstile on every use and keep a per-visitor limit; say plainly that strangers can run up the cost. Pass `subject` on every call so the Gateway can tell people apart: `user:<id>` for a signed-in person, and for anyone a random id kept in a cookie (`visitor:<id>`), never an email address or name.";
|
|
1834
|
+
}, {
|
|
1835
|
+
readonly id: "image-search.cap";
|
|
1836
|
+
readonly sets: "feature.cap_usd";
|
|
1837
|
+
readonly ask: "How much may it spend in a month, at most? When it's reached, the feature stops until next month.";
|
|
1838
|
+
readonly style: "cards";
|
|
1839
|
+
readonly answers: readonly [{
|
|
1840
|
+
readonly label: "US$5 a month";
|
|
1841
|
+
readonly value: 5;
|
|
1842
|
+
readonly means: "A small trial, or light use.";
|
|
1843
|
+
}, {
|
|
1844
|
+
readonly label: "US$20 a month";
|
|
1845
|
+
readonly value: 20;
|
|
1846
|
+
readonly means: "Steady use by a small business's visitors.";
|
|
1847
|
+
}, {
|
|
1848
|
+
readonly label: "US$50 a month";
|
|
1849
|
+
readonly value: 50;
|
|
1850
|
+
readonly means: "Heavy use. It can be raised later.";
|
|
1851
|
+
}];
|
|
1852
|
+
readonly other: {
|
|
1853
|
+
readonly kind: "money";
|
|
1854
|
+
readonly min: 1;
|
|
1855
|
+
readonly max: 1000;
|
|
1856
|
+
readonly description: "US dollars a month, whole or with cents.";
|
|
1857
|
+
};
|
|
1858
|
+
readonly must_ask: true;
|
|
1859
|
+
readonly when: {
|
|
1860
|
+
readonly id: "image-search.route";
|
|
1861
|
+
readonly is: readonly ["feature"];
|
|
1862
|
+
};
|
|
1863
|
+
readonly note: "Say roughly what one use costs (about a tenth of a cent a search) so the owner can judge. The cap is the project's production cap for the `search` tool in the Gateway, shared by every feature that uses it: set it with Workbench Control's `gw_budget_set` (env production, tool search, monthly_usd). Raising a cap waits for the owner's approval on Control's approval page. When it is reached, calls fail with `budget_exceeded`: the page says the feature is resting until next month, never an error.";
|
|
1864
|
+
}, {
|
|
1865
|
+
readonly id: "image-search.licence";
|
|
1866
|
+
readonly sets: "content.licence";
|
|
1867
|
+
readonly ask: "Does the site have the right to use this picture?";
|
|
1868
|
+
readonly style: "cards";
|
|
1869
|
+
readonly answers: readonly [{
|
|
1870
|
+
readonly label: "Yes, it's ours";
|
|
1871
|
+
readonly value: "own";
|
|
1872
|
+
readonly means: "The business took it or owns it.";
|
|
1873
|
+
}, {
|
|
1874
|
+
readonly label: "Yes, it's free to use";
|
|
1875
|
+
readonly value: "free";
|
|
1876
|
+
readonly means: "Its page says so, with a licence such as CC BY. Say which.";
|
|
1877
|
+
}, {
|
|
1878
|
+
readonly label: "No, find another";
|
|
1879
|
+
readonly value: "none";
|
|
1880
|
+
readonly means: "Pick another result, or make one with AI pictures instead.";
|
|
1881
|
+
}];
|
|
1882
|
+
readonly other: {
|
|
1883
|
+
readonly kind: "text";
|
|
1884
|
+
readonly min: 3;
|
|
1885
|
+
readonly max: 200;
|
|
1886
|
+
readonly description: "What gives the site the right to use it.";
|
|
1887
|
+
};
|
|
1888
|
+
readonly must_ask: true;
|
|
1889
|
+
readonly when: {
|
|
1890
|
+
readonly id: "image-search.route";
|
|
1891
|
+
readonly is: readonly ["content"];
|
|
1892
|
+
};
|
|
1893
|
+
readonly note: "Ask after the client picks a result, showing its page link. A search result is a lead, not permission. Pass the client's words as --licence; with no, don't pick it.";
|
|
1894
|
+
}];
|
|
1895
|
+
readonly not_asked: readonly [{
|
|
1896
|
+
readonly sets: "query";
|
|
1897
|
+
readonly why: "The client's description is the search: pass it as --about, shortened to the words that matter.";
|
|
1898
|
+
}, {
|
|
1899
|
+
readonly sets: "filters";
|
|
1900
|
+
readonly why: "Results narrower than 600 pixels are dropped; anything finer (shape, site) is for a feature to do in its own code.";
|
|
1901
|
+
}];
|
|
1902
|
+
readonly drafts: {
|
|
1903
|
+
readonly of: "found pictures";
|
|
1904
|
+
readonly surface: "image-search";
|
|
1905
|
+
readonly count: 4;
|
|
1906
|
+
readonly max_rounds: 3;
|
|
1907
|
+
readonly job: "image-search.drafts";
|
|
1908
|
+
readonly command: "npx workbench-ai drafts search <name> --about \"<what to search for>\"";
|
|
1909
|
+
};
|
|
1910
|
+
};
|
|
1646
1911
|
readonly delivery: {
|
|
1647
1912
|
readonly choice: "built_in";
|
|
1648
1913
|
readonly intro: "Finding existing pictures on the web.";
|
|
1649
|
-
readonly when: "The client wants to find existing pictures on the web, for the site itself or as a search visitors use.";
|
|
1650
1914
|
};
|
|
1651
1915
|
};
|
|
1652
1916
|
readonly images: {
|
|
@@ -1800,10 +2064,159 @@ export declare const capabilities: {
|
|
|
1800
2064
|
readonly refusal: "invalid_request";
|
|
1801
2065
|
readonly cost_hint_usd: 0;
|
|
1802
2066
|
}];
|
|
2067
|
+
readonly offer: {
|
|
2068
|
+
readonly pattern: "feature_or_content";
|
|
2069
|
+
readonly when: "The client wants a picture made by AI, such as an illustration, a hero image or a product mock-up, as a feature visitors use or once for the site.";
|
|
2070
|
+
readonly say: "I'll make this with Workbench pictures, made by AI through Workbench, so the app holds no image key and spending has a monthly cap.";
|
|
2071
|
+
readonly answers_file: "workbench/images/<name>.json";
|
|
2072
|
+
readonly per: "feature or picture";
|
|
2073
|
+
readonly answers_format: "For a feature: `{ \"format\": 1, \"route\": \"feature\", \"name\", \"about\" (the client's words), \"who\", \"cap_usd\", \"job\" }`, where `job` is the `X-Workbench-Job` the feature's calls send (`<name>` with dots, such as `quotes.estimate`), so its spending shows on its own line in Control. Write it, then build the feature with the package. For a picture made once: `npx workbench-ai pick <name> <round>-<draft>` copies the picked picture to `public/images/<name>.png` (or .jpg) and writes the answers file with its prompt, model, request id and cost; never write one from nothing. Show it on the page from `/images/<name>.png`, with alt text that says what it shows. Drafts and their previews stay in `workbench/images/drafts/`, which isn't committed.";
|
|
2074
|
+
readonly questions: readonly [{
|
|
2075
|
+
readonly id: "images.route";
|
|
2076
|
+
readonly sets: "route";
|
|
2077
|
+
readonly ask: "Is this something visitors use on the site, or something made once for the site?";
|
|
2078
|
+
readonly style: "cards";
|
|
2079
|
+
readonly answers: readonly [{
|
|
2080
|
+
readonly label: "Visitors use it";
|
|
2081
|
+
readonly value: "feature";
|
|
2082
|
+
readonly means: "A feature that makes a new picture each time someone uses it, such as a mock-up of their own design.";
|
|
2083
|
+
}, {
|
|
2084
|
+
readonly label: "Made once for the site";
|
|
2085
|
+
readonly value: "content";
|
|
2086
|
+
readonly means: "A picture for the site, made once and kept: a hero image, an illustration for a page.";
|
|
2087
|
+
}];
|
|
2088
|
+
readonly must_ask: true;
|
|
2089
|
+
readonly note: "Ask it even when the client's words seem to say, as a quick check: the two routes are built and paid for differently.";
|
|
2090
|
+
}, {
|
|
2091
|
+
readonly id: "images.who";
|
|
2092
|
+
readonly sets: "feature.who";
|
|
2093
|
+
readonly ask: "Who may use it?";
|
|
2094
|
+
readonly style: "cards";
|
|
2095
|
+
readonly answers: readonly [{
|
|
2096
|
+
readonly label: "People who are signed in";
|
|
2097
|
+
readonly value: "signed_in";
|
|
2098
|
+
readonly means: "Anyone with an account. Each use is tied to a person, so misuse can be traced and stopped.";
|
|
2099
|
+
}, {
|
|
2100
|
+
readonly label: "Admins only";
|
|
2101
|
+
readonly value: "admins";
|
|
2102
|
+
readonly means: "Only the business's own admins, for example a tool for writing their own posts.";
|
|
2103
|
+
}, {
|
|
2104
|
+
readonly label: "Anyone visiting";
|
|
2105
|
+
readonly value: "anyone";
|
|
2106
|
+
readonly means: "No sign-in. The page checks for bots (Turnstile) and limits how often one visitor can use it.";
|
|
2107
|
+
}];
|
|
2108
|
+
readonly when: {
|
|
2109
|
+
readonly id: "images.route";
|
|
2110
|
+
readonly is: readonly ["feature"];
|
|
2111
|
+
};
|
|
2112
|
+
readonly note: "Signed in means `requireUser` and admins means `app_admins`, as the workbench-sign-in skill says. For anyone, check Turnstile on every use and keep a per-visitor limit; say plainly that strangers can run up the cost. Pass `subject` on every call so the Gateway can tell people apart: `user:<id>` for a signed-in person, and for anyone a random id kept in a cookie (`visitor:<id>`), never an email address or name.";
|
|
2113
|
+
}, {
|
|
2114
|
+
readonly id: "images.cap";
|
|
2115
|
+
readonly sets: "feature.cap_usd";
|
|
2116
|
+
readonly ask: "How much may it spend in a month, at most? When it's reached, the feature stops until next month.";
|
|
2117
|
+
readonly style: "cards";
|
|
2118
|
+
readonly answers: readonly [{
|
|
2119
|
+
readonly label: "US$5 a month";
|
|
2120
|
+
readonly value: 5;
|
|
2121
|
+
readonly means: "A small trial, or light use.";
|
|
2122
|
+
}, {
|
|
2123
|
+
readonly label: "US$20 a month";
|
|
2124
|
+
readonly value: 20;
|
|
2125
|
+
readonly means: "Steady use by a small business's visitors.";
|
|
2126
|
+
}, {
|
|
2127
|
+
readonly label: "US$50 a month";
|
|
2128
|
+
readonly value: 50;
|
|
2129
|
+
readonly means: "Heavy use. It can be raised later.";
|
|
2130
|
+
}];
|
|
2131
|
+
readonly other: {
|
|
2132
|
+
readonly kind: "money";
|
|
2133
|
+
readonly min: 1;
|
|
2134
|
+
readonly max: 1000;
|
|
2135
|
+
readonly description: "US dollars a month, whole or with cents.";
|
|
2136
|
+
};
|
|
2137
|
+
readonly must_ask: true;
|
|
2138
|
+
readonly when: {
|
|
2139
|
+
readonly id: "images.route";
|
|
2140
|
+
readonly is: readonly ["feature"];
|
|
2141
|
+
};
|
|
2142
|
+
readonly note: "Say roughly what one use costs (about US$0.07 a picture with image-default) so the owner can judge. The cap is the project's production cap for the `images` tool in the Gateway, shared by every feature that uses it: set it with Workbench Control's `gw_budget_set` (env production, tool images, monthly_usd). Raising a cap waits for the owner's approval on Control's approval page. When it is reached, calls fail with `budget_exceeded`: the page says the feature is resting until next month, never an error.";
|
|
2143
|
+
}, {
|
|
2144
|
+
readonly id: "images.what";
|
|
2145
|
+
readonly sets: readonly ["content.name", "content.about"];
|
|
2146
|
+
readonly ask: "What picture do you need?";
|
|
2147
|
+
readonly style: "cards";
|
|
2148
|
+
readonly answers: readonly [{
|
|
2149
|
+
readonly label: "A hero image";
|
|
2150
|
+
readonly value: "hero";
|
|
2151
|
+
readonly means: "The large picture across the top of a page.";
|
|
2152
|
+
}, {
|
|
2153
|
+
readonly label: "An illustration";
|
|
2154
|
+
readonly value: "illustration";
|
|
2155
|
+
readonly means: "A drawing for a page or a section.";
|
|
2156
|
+
}, {
|
|
2157
|
+
readonly label: "A product mock-up";
|
|
2158
|
+
readonly value: "mockup";
|
|
2159
|
+
readonly means: "A product shown in use or in a setting.";
|
|
2160
|
+
}];
|
|
2161
|
+
readonly other: {
|
|
2162
|
+
readonly kind: "text";
|
|
2163
|
+
readonly min: 3;
|
|
2164
|
+
readonly max: 200;
|
|
2165
|
+
readonly description: "What the picture is, in a few words.";
|
|
2166
|
+
};
|
|
2167
|
+
readonly when: {
|
|
2168
|
+
readonly id: "images.route";
|
|
2169
|
+
readonly is: readonly ["content"];
|
|
2170
|
+
};
|
|
2171
|
+
readonly note: "Name the picture after where it goes (home_hero): lower case and underscores. The client's own words about what it shows and the feel they want go in --about.";
|
|
2172
|
+
}, {
|
|
2173
|
+
readonly id: "images.shape";
|
|
2174
|
+
readonly sets: "content.aspect";
|
|
2175
|
+
readonly ask: "What shape should it be?";
|
|
2176
|
+
readonly style: "cards";
|
|
2177
|
+
readonly answers: readonly [{
|
|
2178
|
+
readonly label: "Landscape (3:2)";
|
|
2179
|
+
readonly value: "3:2";
|
|
2180
|
+
readonly means: "Wider than tall, the usual shape for a page.";
|
|
2181
|
+
}, {
|
|
2182
|
+
readonly label: "Wide banner (16:9)";
|
|
2183
|
+
readonly value: "16:9";
|
|
2184
|
+
readonly means: "For a picture across the top of a page.";
|
|
2185
|
+
}, {
|
|
2186
|
+
readonly label: "Square (1:1)";
|
|
2187
|
+
readonly value: "1:1";
|
|
2188
|
+
readonly means: "For cards and social posts.";
|
|
2189
|
+
}, {
|
|
2190
|
+
readonly label: "Portrait (2:3)";
|
|
2191
|
+
readonly value: "2:3";
|
|
2192
|
+
readonly means: "Taller than wide.";
|
|
2193
|
+
}];
|
|
2194
|
+
readonly when: {
|
|
2195
|
+
readonly id: "images.route";
|
|
2196
|
+
readonly is: readonly ["content"];
|
|
2197
|
+
};
|
|
2198
|
+
readonly note: "Recommend the banner for a hero image. Pass it to the drafts command as --aspect.";
|
|
2199
|
+
}];
|
|
2200
|
+
readonly not_asked: readonly [{
|
|
2201
|
+
readonly sets: "model";
|
|
2202
|
+
readonly why: "Drafts and features use image-default. image-pro costs about twice as much for finer detail and image-openai is cheapest; suggest one only when the client asks about quality or cost.";
|
|
2203
|
+
}, {
|
|
2204
|
+
readonly sets: "references";
|
|
2205
|
+
readonly why: "A reference picture (to make something like it) is only for a feature that needs one, and works with Google aliases only; offer it when the client mentions one.";
|
|
2206
|
+
}];
|
|
2207
|
+
readonly drafts: {
|
|
2208
|
+
readonly of: "pictures";
|
|
2209
|
+
readonly surface: "images";
|
|
2210
|
+
readonly alias: "image-default";
|
|
2211
|
+
readonly count: 3;
|
|
2212
|
+
readonly max_rounds: 3;
|
|
2213
|
+
readonly job: "images.drafts";
|
|
2214
|
+
readonly command: "npx workbench-ai drafts image <name> --about \"<what it shows, in the client's words>\" --aspect <shape>";
|
|
2215
|
+
};
|
|
2216
|
+
};
|
|
1803
2217
|
readonly delivery: {
|
|
1804
2218
|
readonly choice: "built_in";
|
|
1805
2219
|
readonly intro: "Pictures made by AI from a description.";
|
|
1806
|
-
readonly when: "The client wants a picture made by AI, such as an illustration, a hero image or a product mock-up, as a feature visitors use or once for the site.";
|
|
1807
2220
|
};
|
|
1808
2221
|
};
|
|
1809
2222
|
readonly pdf: {
|
|
@@ -1814,7 +2227,7 @@ export declare const capabilities: {
|
|
|
1814
2227
|
readonly summary: "workbench-pdf prints an app's content as a PDF with its brand.json logo, colours and fonts, in the app's own Worker through its Browser Rendering binding (BROWSER). Nothing goes through the Gateway and the app holds no Cloudflare token. The standard layout takes plain-text blocks; html() takes the app's own markup.";
|
|
1815
2228
|
readonly status: "built";
|
|
1816
2229
|
readonly surfaces: {
|
|
1817
|
-
readonly package: readonly ["createPdfMaker", "WorkbenchPdfError"];
|
|
2230
|
+
readonly package: readonly ["createPdfMaker", "WorkbenchPdfError", "checkLayout", "fillLayout"];
|
|
1818
2231
|
};
|
|
1819
2232
|
readonly limits: readonly [{
|
|
1820
2233
|
readonly id: "pdf.blocks";
|
|
@@ -1881,13 +2294,79 @@ export declare const capabilities: {
|
|
|
1881
2294
|
readonly cost_hint_usd: 0;
|
|
1882
2295
|
readonly note: "Prints the app's own HTML holding an image from a host not in allowOrigins; the PDF is made and the browser reports that image's request as blocked";
|
|
1883
2296
|
}];
|
|
2297
|
+
readonly offer: {
|
|
2298
|
+
readonly pattern: "drafts";
|
|
2299
|
+
readonly when: "The client wants a PDF: an invoice, receipt, quote, certificate, report or anything else to download or print.";
|
|
2300
|
+
readonly say: "I'll make this with Workbench PDFs, printed with your logo and colours. I'll show you a few layouts to pick from. The one you pick is saved, so every one looks the same from then on.";
|
|
2301
|
+
readonly answers_file: "workbench/pdf/<name>.json";
|
|
2302
|
+
readonly per: "document";
|
|
2303
|
+
readonly generator: "npx workbench-pdf generate";
|
|
2304
|
+
readonly answers_format: "the saved layout. `npx workbench-pdf pick <name> <round>-<draft>` writes it from the draft the client picked, with the draft's request id, model and cost; never write one from nothing. It holds the document's `fields` (each value is text the app formats first, money and dates through the country pack), its `blocks` with `{field}` placeholders, and made-up `sample` values. To change a saved layout in the client's words (move a block, rename a heading, add a field), edit the file and run the generator, which refuses a layout that doesn't check. In the app, print with `pdfMakerFor(env).document(PDF_LAYOUTS.<name>.document(data), { size: PDF_LAYOUTS.<name>.size })`. Drafts and their previews stay in `workbench/pdf/drafts/`, which isn't committed.";
|
|
2305
|
+
readonly questions: readonly [{
|
|
2306
|
+
readonly id: "pdf.what";
|
|
2307
|
+
readonly sets: readonly ["layout.name", "layout.about"];
|
|
2308
|
+
readonly ask: "What is this document, and what is it for?";
|
|
2309
|
+
readonly style: "cards";
|
|
2310
|
+
readonly answers: readonly [{
|
|
2311
|
+
readonly label: "An invoice";
|
|
2312
|
+
readonly value: "invoice";
|
|
2313
|
+
readonly means: "What a customer owes, with the items and the total.";
|
|
2314
|
+
}, {
|
|
2315
|
+
readonly label: "A receipt";
|
|
2316
|
+
readonly value: "receipt";
|
|
2317
|
+
readonly means: "Proof a customer paid.";
|
|
2318
|
+
}, {
|
|
2319
|
+
readonly label: "A quote";
|
|
2320
|
+
readonly value: "quote";
|
|
2321
|
+
readonly means: "What a job would cost, before the customer agrees.";
|
|
2322
|
+
}];
|
|
2323
|
+
readonly other: {
|
|
2324
|
+
readonly kind: "text";
|
|
2325
|
+
readonly min: 3;
|
|
2326
|
+
readonly max: 200;
|
|
2327
|
+
readonly description: "What the document is, in a few words: a certificate, a run sheet, a booking confirmation.";
|
|
2328
|
+
};
|
|
2329
|
+
readonly must_ask: true;
|
|
2330
|
+
readonly note: "The answer's value is the layout's name (lower case and underscores: run_sheet). The client's own words, with anything they add about who reads it, go in --about.";
|
|
2331
|
+
}, {
|
|
2332
|
+
readonly id: "pdf.size";
|
|
2333
|
+
readonly sets: "layout.size";
|
|
2334
|
+
readonly ask: "Which paper size?";
|
|
2335
|
+
readonly style: "cards";
|
|
2336
|
+
readonly answers: readonly [{
|
|
2337
|
+
readonly label: "A4";
|
|
2338
|
+
readonly value: "A4";
|
|
2339
|
+
readonly means: "Used almost everywhere outside North America.";
|
|
2340
|
+
}, {
|
|
2341
|
+
readonly label: "US Letter";
|
|
2342
|
+
readonly value: "Letter";
|
|
2343
|
+
readonly means: "Used in the United States and Canada.";
|
|
2344
|
+
}];
|
|
2345
|
+
readonly note: "Recommend US Letter only when the readers are in the United States or Canada. Pass it to the drafts command as --size.";
|
|
2346
|
+
}];
|
|
2347
|
+
readonly not_asked: readonly [{
|
|
2348
|
+
readonly sets: "layout.colours";
|
|
2349
|
+
readonly why: "The logo, colours and fonts come from the brand (brand.json and the admins' brand page), so every document matches the rest of the app. To restyle a part of the layout, use project.css (see Restyling).";
|
|
2350
|
+
}, {
|
|
2351
|
+
readonly sets: "layout.contents";
|
|
2352
|
+
readonly why: "The drafts propose what each layout shows. The client changes a picked layout in plain words, and you edit the saved file.";
|
|
2353
|
+
}];
|
|
2354
|
+
readonly drafts: {
|
|
2355
|
+
readonly of: "layouts for this document";
|
|
2356
|
+
readonly surface: "ai";
|
|
2357
|
+
readonly alias: "claude-default";
|
|
2358
|
+
readonly count: 3;
|
|
2359
|
+
readonly max_rounds: 3;
|
|
2360
|
+
readonly job: "pdf.drafts";
|
|
2361
|
+
readonly command: "npx workbench-pdf drafts <name> --about \"<what it is for, in the client's words>\" --size <A4 or Letter>";
|
|
2362
|
+
};
|
|
2363
|
+
};
|
|
1884
2364
|
readonly styles: {
|
|
1885
2365
|
readonly prefix: "wb-pdf-";
|
|
1886
2366
|
};
|
|
1887
2367
|
readonly delivery: {
|
|
1888
2368
|
readonly choice: "optional";
|
|
1889
2369
|
readonly intro: "PDFs such as invoices and receipts, printed with the project's logo and colours.";
|
|
1890
|
-
readonly when: "The client wants a PDF: an invoice, receipt, quote, certificate, report or anything else to download or print.";
|
|
1891
2370
|
};
|
|
1892
2371
|
};
|
|
1893
2372
|
readonly "sign-in": {
|