@wafflebase/cli 0.4.8 → 0.5.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.
Files changed (83) hide show
  1. package/dist/bin.js +99693 -11
  2. package/package.json +7 -6
  3. package/dist/bin.d.ts +0 -2
  4. package/dist/client/dry-run.d.ts +0 -5
  5. package/dist/client/dry-run.js +0 -16
  6. package/dist/client/http-client.d.ts +0 -59
  7. package/dist/client/http-client.js +0 -178
  8. package/dist/commands/api-keys.d.ts +0 -2
  9. package/dist/commands/api-keys.js +0 -54
  10. package/dist/commands/cells.d.ts +0 -2
  11. package/dist/commands/cells.js +0 -108
  12. package/dist/commands/ctx.d.ts +0 -5
  13. package/dist/commands/ctx.js +0 -56
  14. package/dist/commands/docs.d.ts +0 -3
  15. package/dist/commands/docs.js +0 -320
  16. package/dist/commands/login.d.ts +0 -2
  17. package/dist/commands/login.js +0 -220
  18. package/dist/commands/logout.d.ts +0 -2
  19. package/dist/commands/logout.js +0 -10
  20. package/dist/commands/root.d.ts +0 -18
  21. package/dist/commands/root.js +0 -37
  22. package/dist/commands/schema.d.ts +0 -2
  23. package/dist/commands/schema.js +0 -28
  24. package/dist/commands/sheets-export.d.ts +0 -2
  25. package/dist/commands/sheets-export.js +0 -52
  26. package/dist/commands/sheets-import.d.ts +0 -2
  27. package/dist/commands/sheets-import.js +0 -88
  28. package/dist/commands/sheets.d.ts +0 -2
  29. package/dist/commands/sheets.js +0 -17
  30. package/dist/commands/slides.d.ts +0 -3
  31. package/dist/commands/slides.js +0 -227
  32. package/dist/commands/status.d.ts +0 -2
  33. package/dist/commands/status.js +0 -22
  34. package/dist/commands/tabs.d.ts +0 -2
  35. package/dist/commands/tabs.js +0 -20
  36. package/dist/config/config.d.ts +0 -38
  37. package/dist/config/config.js +0 -135
  38. package/dist/config/session.d.ts +0 -49
  39. package/dist/config/session.js +0 -74
  40. package/dist/docs/content.d.ts +0 -37
  41. package/dist/docs/content.js +0 -90
  42. package/dist/docs/docx-export.d.ts +0 -23
  43. package/dist/docs/docx-export.js +0 -14
  44. package/dist/docs/docx-import.d.ts +0 -36
  45. package/dist/docs/docx-import.js +0 -70
  46. package/dist/docs/dom-polyfill.d.ts +0 -1
  47. package/dist/docs/dom-polyfill.js +0 -29
  48. package/dist/docs/fontkit-measurer.d.ts +0 -41
  49. package/dist/docs/fontkit-measurer.js +0 -64
  50. package/dist/docs/image-fetcher.d.ts +0 -37
  51. package/dist/docs/image-fetcher.js +0 -38
  52. package/dist/docs/import.d.ts +0 -72
  53. package/dist/docs/import.js +0 -146
  54. package/dist/docs/page-range.d.ts +0 -29
  55. package/dist/docs/page-range.js +0 -74
  56. package/dist/docs/page-slice.d.ts +0 -45
  57. package/dist/docs/page-slice.js +0 -61
  58. package/dist/docs/paginate.d.ts +0 -13
  59. package/dist/docs/paginate.js +0 -19
  60. package/dist/docs/pdf-export.d.ts +0 -47
  61. package/dist/docs/pdf-export.js +0 -95
  62. package/dist/output/binary.d.ts +0 -37
  63. package/dist/output/binary.js +0 -47
  64. package/dist/output/csv.d.ts +0 -4
  65. package/dist/output/csv.js +0 -25
  66. package/dist/output/formatter.d.ts +0 -4
  67. package/dist/output/formatter.js +0 -41
  68. package/dist/output/json.d.ts +0 -1
  69. package/dist/output/json.js +0 -3
  70. package/dist/output/table.d.ts +0 -4
  71. package/dist/output/table.js +0 -14
  72. package/dist/schema/registry.d.ts +0 -42
  73. package/dist/schema/registry.js +0 -375
  74. package/dist/slides/content.d.ts +0 -41
  75. package/dist/slides/content.js +0 -122
  76. package/dist/slides/import.d.ts +0 -82
  77. package/dist/slides/import.js +0 -170
  78. package/dist/slides/pptx-export.d.ts +0 -6
  79. package/dist/slides/pptx-export.js +0 -10
  80. package/dist/slides/pptx-import.d.ts +0 -35
  81. package/dist/slides/pptx-import.js +0 -49
  82. package/dist/util/csv-parse.d.ts +0 -21
  83. package/dist/util/csv-parse.js +0 -99
@@ -1,41 +0,0 @@
1
- import { formatJson } from './json.js';
2
- import { formatTable } from './table.js';
3
- import { formatCsv } from './csv.js';
4
- export function format(data, fmt) {
5
- switch (fmt) {
6
- case 'json':
7
- return formatJson(data);
8
- case 'table':
9
- return formatTable(data);
10
- case 'csv':
11
- return formatCsv(data);
12
- }
13
- }
14
- export function output(data, fmt, quiet) {
15
- if (quiet)
16
- return;
17
- console.log(format(data, fmt));
18
- }
19
- /**
20
- * Preserve a structured `code` from any thrown `Error` subclass that
21
- * carries one (e.g., `InvalidDocxError`'s `code = 'INVALID_DOCX'`).
22
- * Skill files document those codes, so silently flattening every
23
- * failure to `'ERROR'` made agents unable to branch on the cause.
24
- */
25
- function errorCode(error) {
26
- if (error instanceof Error && 'code' in error) {
27
- const code = error.code;
28
- if (typeof code === 'string' && code.length > 0)
29
- return code;
30
- }
31
- return 'ERROR';
32
- }
33
- export function outputError(error, quiet) {
34
- if (quiet) {
35
- process.exitCode = 1;
36
- return;
37
- }
38
- const message = error instanceof Error ? error.message : String(error);
39
- console.error(JSON.stringify({ error: { code: errorCode(error), message } }, null, 2));
40
- process.exitCode = 1;
41
- }
@@ -1 +0,0 @@
1
- export declare function formatJson(data: unknown): string;
@@ -1,3 +0,0 @@
1
- export function formatJson(data) {
2
- return JSON.stringify(data, null, 2);
3
- }
@@ -1,4 +0,0 @@
1
- /**
2
- * Format an array of objects as an aligned text table.
3
- */
4
- export declare function formatTable(data: unknown): string;
@@ -1,14 +0,0 @@
1
- /**
2
- * Format an array of objects as an aligned text table.
3
- */
4
- export function formatTable(data) {
5
- if (!Array.isArray(data) || data.length === 0)
6
- return '(no results)';
7
- const rows = data;
8
- const keys = Object.keys(rows[0]);
9
- const widths = keys.map((key) => Math.max(key.length, ...rows.map((row) => String(row[key] ?? '').length)));
10
- const header = keys.map((k, i) => k.padEnd(widths[i])).join(' ');
11
- const separator = widths.map((w) => '-'.repeat(w)).join(' ');
12
- const lines = rows.map((row) => keys.map((k, i) => String(row[k] ?? '').padEnd(widths[i])).join(' '));
13
- return [header, separator, ...lines].join('\n');
14
- }
@@ -1,42 +0,0 @@
1
- export type SafetyLevel = 'read-only' | 'write' | 'destructive';
2
- /**
3
- * Per-command safety variant — used by `docs.import` to spell out that
4
- * the same command is `write` by default but `destructive` with
5
- * `--replace`. Skill agents read this to decide when extra confirmation
6
- * is needed.
7
- */
8
- export interface SafetyVariant {
9
- when: string;
10
- safety: SafetyLevel;
11
- creates?: string;
12
- modifies?: string;
13
- removes?: string;
14
- }
15
- export interface CommandSchema {
16
- name: string;
17
- description: string;
18
- safety: SafetyLevel;
19
- parameters: Record<string, {
20
- type: string;
21
- required: boolean;
22
- description: string;
23
- default?: string;
24
- }>;
25
- response: Record<string, unknown>;
26
- /**
27
- * Singular / legacy / namespace-stripped names that should resolve to
28
- * this canonical entry. `getCommandSchema('cell.get')` returns the
29
- * `sheets.cells.get` schema because `'cell.get'` appears here.
30
- */
31
- aliases?: string[];
32
- /** Optional per-flag safety overrides (currently only `docs.import`). */
33
- variants?: SafetyVariant[];
34
- }
35
- /**
36
- * Look up a schema entry by canonical name or any registered alias.
37
- * Aliases let scripts and skills written against the v0.3.x singular
38
- * names (`cell.get`, `doc.list`, `import`) keep working after the
39
- * v0.3.7 namespace shuffle.
40
- */
41
- export declare function getCommandSchema(name: string): CommandSchema | undefined;
42
- export declare function getAllCommandSchemas(): CommandSchema[];
@@ -1,375 +0,0 @@
1
- const registry = [
2
- {
3
- name: 'login',
4
- description: 'Authenticate via GitHub OAuth in the browser',
5
- safety: 'write',
6
- parameters: {
7
- '--server': { type: 'string', required: false, description: 'Server URL', default: 'https://api.wafflebase.io' },
8
- },
9
- response: { user: 'string', workspace: 'string' },
10
- },
11
- {
12
- name: 'logout',
13
- description: 'Clear session and log out',
14
- safety: 'write',
15
- parameters: {},
16
- response: {},
17
- },
18
- {
19
- name: 'status',
20
- description: 'Show current auth state',
21
- safety: 'read-only',
22
- parameters: {},
23
- response: { user: 'string', server: 'string', workspace: 'string', session: 'string' },
24
- },
25
- {
26
- name: 'ctx.list',
27
- description: 'List workspaces',
28
- safety: 'read-only',
29
- parameters: {},
30
- response: { type: 'array', items: { id: 'string', name: 'string', active: 'boolean' } },
31
- },
32
- {
33
- name: 'ctx.switch',
34
- description: 'Switch active workspace',
35
- safety: 'write',
36
- parameters: {
37
- 'name-or-id': { type: 'string', required: true, description: 'Workspace name or ID' },
38
- },
39
- response: { workspace: 'string' },
40
- },
41
- // Docs (word-processor) namespace
42
- {
43
- name: 'docs.list',
44
- description: 'List documents in workspace',
45
- safety: 'read-only',
46
- parameters: {
47
- '--type': { type: 'string', required: false, description: 'Filter by document type (doc|sheet)' },
48
- },
49
- response: { type: 'array', items: { id: 'string', title: 'string', type: 'string', createdAt: 'string' } },
50
- aliases: ['doc.list', 'document.list', 'documents.list'],
51
- },
52
- {
53
- name: 'docs.create',
54
- description: 'Create a new document',
55
- safety: 'write',
56
- parameters: {
57
- title: { type: 'string', required: true, description: 'Document title' },
58
- '--type': { type: 'string', required: false, description: 'Document type (doc|sheet)', default: 'sheet' },
59
- },
60
- response: { id: 'string', title: 'string', type: 'string' },
61
- aliases: ['doc.create', 'document.create', 'documents.create'],
62
- },
63
- {
64
- name: 'docs.get',
65
- description: 'Show document metadata',
66
- safety: 'read-only',
67
- parameters: {
68
- 'doc-id': { type: 'string', required: true, description: 'Document ID' },
69
- },
70
- response: { id: 'string', title: 'string', type: 'string', createdAt: 'string' },
71
- aliases: ['doc.get', 'document.get', 'documents.get'],
72
- },
73
- {
74
- name: 'docs.rename',
75
- description: 'Rename a document',
76
- safety: 'write',
77
- parameters: {
78
- 'doc-id': { type: 'string', required: true, description: 'Document ID' },
79
- title: { type: 'string', required: true, description: 'New title' },
80
- },
81
- response: { id: 'string', title: 'string' },
82
- aliases: ['doc.rename', 'document.rename', 'documents.rename'],
83
- },
84
- {
85
- name: 'docs.delete',
86
- description: 'Delete a document',
87
- safety: 'destructive',
88
- parameters: {
89
- 'doc-id': { type: 'string', required: true, description: 'Document ID' },
90
- },
91
- response: { id: 'string' },
92
- aliases: ['doc.delete', 'document.delete', 'documents.delete'],
93
- },
94
- {
95
- name: 'docs.content',
96
- description: 'Read document content as JSON, Markdown, or plain text',
97
- safety: 'read-only',
98
- parameters: {
99
- 'doc-id': { type: 'string', required: true, description: 'Document ID' },
100
- '--format': { type: 'string', required: false, description: 'Output format (json|md|text)', default: 'json' },
101
- '--pages': { type: 'string', required: false, description: 'Page range (e.g. 1-3,5)' },
102
- '--include-header-footer': { type: 'boolean', required: false, description: 'Include header/footer (md/text)', default: 'false' },
103
- '--inline-images': { type: 'boolean', required: false, description: 'Inline data: image URLs (md only)', default: 'false' },
104
- '--out': { type: 'string', required: false, description: 'Output file (- for stdout)' },
105
- '--force': { type: 'boolean', required: false, description: 'Overwrite existing output file', default: 'false' },
106
- },
107
- response: { type: 'object', description: 'Document JSON, Markdown text, or plaintext per --format' },
108
- aliases: ['doc.content', 'document.content', 'documents.content'],
109
- },
110
- {
111
- name: 'docs.export',
112
- description: 'Export a document to PDF or DOCX',
113
- safety: 'read-only',
114
- parameters: {
115
- 'doc-id': { type: 'string', required: true, description: 'Document ID' },
116
- file: { type: 'string', required: true, description: 'Output path or - for stdout' },
117
- '--format': { type: 'string', required: false, description: 'Output format (pdf|docx); default from extension' },
118
- '--pages': { type: 'string', required: false, description: 'Page range (PDF only)' },
119
- '--include-header-footer': { type: 'boolean', required: false, description: 'Include header/footer regions', default: 'true' },
120
- '--force': { type: 'boolean', required: false, description: 'Overwrite existing output file', default: 'false' },
121
- },
122
- response: { type: 'binary', description: 'PDF or DOCX bytes' },
123
- aliases: ['doc.export', 'document.export', 'documents.export'],
124
- },
125
- {
126
- name: 'docs.import',
127
- description: 'Import a .docx file as a new (or replacement) document',
128
- // Default safety is `write` (create new doc); `--replace` flips it
129
- // to destructive. Variants spell this out for skill agents.
130
- safety: 'write',
131
- parameters: {
132
- file: { type: 'string', required: true, description: 'Source .docx path or - for stdin' },
133
- '--title': { type: 'string', required: false, description: 'Document title (default: file basename)' },
134
- '--replace': { type: 'string', required: false, description: 'Existing document ID to replace' },
135
- '--yes': { type: 'boolean', required: false, description: 'Skip --replace confirmation', default: 'false' },
136
- },
137
- response: { id: 'string', title: 'string', replaced: 'boolean' },
138
- variants: [
139
- { when: 'default', safety: 'write', creates: 'new document' },
140
- { when: '--replace given', safety: 'destructive', modifies: 'existing document content' },
141
- ],
142
- aliases: ['doc.import', 'document.import', 'documents.import'],
143
- },
144
- // Slides (presentation) namespace
145
- {
146
- name: 'slides.list',
147
- description: 'List slide decks in workspace',
148
- safety: 'read-only',
149
- parameters: {},
150
- response: { type: 'array', items: { id: 'string', title: 'string', type: 'string', createdAt: 'string' } },
151
- aliases: ['slide.list', 'deck.list', 'decks.list'],
152
- },
153
- {
154
- name: 'slides.create',
155
- description: 'Create a new slide deck',
156
- safety: 'write',
157
- parameters: {
158
- title: { type: 'string', required: true, description: 'Deck title' },
159
- },
160
- response: { id: 'string', title: 'string', type: 'string' },
161
- aliases: ['slide.create', 'deck.create', 'decks.create'],
162
- },
163
- {
164
- name: 'slides.get',
165
- description: 'Show slide deck metadata',
166
- safety: 'read-only',
167
- parameters: {
168
- 'doc-id': { type: 'string', required: true, description: 'Document ID' },
169
- },
170
- response: { id: 'string', title: 'string', type: 'string', createdAt: 'string' },
171
- aliases: ['slide.get', 'deck.get', 'decks.get'],
172
- },
173
- {
174
- name: 'slides.rename',
175
- description: 'Rename a slide deck',
176
- safety: 'write',
177
- parameters: {
178
- 'doc-id': { type: 'string', required: true, description: 'Document ID' },
179
- title: { type: 'string', required: true, description: 'New title' },
180
- },
181
- response: { id: 'string', title: 'string' },
182
- aliases: ['slide.rename', 'deck.rename', 'decks.rename'],
183
- },
184
- {
185
- name: 'slides.delete',
186
- description: 'Delete a slide deck',
187
- safety: 'destructive',
188
- parameters: {
189
- 'doc-id': { type: 'string', required: true, description: 'Document ID' },
190
- },
191
- response: { id: 'string' },
192
- aliases: ['slide.delete', 'deck.delete', 'decks.delete'],
193
- },
194
- {
195
- name: 'slides.content',
196
- description: 'Read deck content as JSON, Markdown, or plain text',
197
- safety: 'read-only',
198
- parameters: {
199
- 'doc-id': { type: 'string', required: true, description: 'Document ID' },
200
- '--format': { type: 'string', required: false, description: 'Output format (json|md|text)', default: 'json' },
201
- '--notes': { type: 'boolean', required: false, description: 'Include speaker notes (md/text)', default: 'false' },
202
- '--out': { type: 'string', required: false, description: 'Output file (- for stdout)' },
203
- '--force': { type: 'boolean', required: false, description: 'Overwrite existing output file', default: 'false' },
204
- },
205
- response: { type: 'object', description: 'Deck JSON, Markdown text, or plaintext per --format' },
206
- aliases: ['slide.content', 'deck.content', 'decks.content'],
207
- },
208
- {
209
- name: 'slides.import',
210
- description: 'Import a .pptx file as a new (or replacement) slide deck',
211
- // Default safety is `write` (create new deck); `--replace` flips it
212
- // to destructive, mirroring `docs.import`.
213
- safety: 'write',
214
- parameters: {
215
- file: { type: 'string', required: true, description: 'Source .pptx path or - for stdin' },
216
- '--title': { type: 'string', required: false, description: 'Deck title (default: file basename)' },
217
- '--replace': { type: 'string', required: false, description: 'Existing deck ID to replace' },
218
- '--yes': { type: 'boolean', required: false, description: 'Skip --replace confirmation', default: 'false' },
219
- },
220
- response: { id: 'string', title: 'string', replaced: 'boolean' },
221
- variants: [
222
- { when: 'default', safety: 'write', creates: 'new slide deck' },
223
- { when: '--replace given', safety: 'destructive', modifies: 'existing deck content' },
224
- ],
225
- aliases: ['slide.import', 'deck.import', 'decks.import'],
226
- },
227
- {
228
- name: 'slides.export',
229
- description: 'Export a slide deck to PPTX',
230
- safety: 'read-only',
231
- parameters: {
232
- 'doc-id': { type: 'string', required: true, description: 'Document ID' },
233
- file: { type: 'string', required: true, description: 'Output path or - for stdout' },
234
- '--format': { type: 'string', required: false, description: 'Output format (pptx); default from extension' },
235
- '--force': { type: 'boolean', required: false, description: 'Overwrite existing output file', default: 'false' },
236
- },
237
- response: { type: 'binary', description: 'PPTX bytes' },
238
- aliases: ['slide.export', 'deck.export', 'decks.export'],
239
- },
240
- // Sheets namespace — canonical names live under sheets.*
241
- {
242
- name: 'sheets.tabs.list',
243
- description: 'List tabs in a spreadsheet document',
244
- safety: 'read-only',
245
- parameters: {
246
- 'doc-id': { type: 'string', required: true, description: 'Document ID' },
247
- },
248
- response: { type: 'array', items: { id: 'string', name: 'string', type: 'string' } },
249
- aliases: ['tab.list', 'tabs.list', 'sheet.tabs.list', 'sheet.tab.list', 'sheets.tab.list'],
250
- },
251
- {
252
- name: 'sheets.cells.get',
253
- description: 'Get cells from a spreadsheet tab',
254
- safety: 'read-only',
255
- parameters: {
256
- 'doc-id': { type: 'string', required: true, description: 'Document ID' },
257
- range: { type: 'string', required: false, description: 'Cell range (e.g. A1:C10)', default: 'all' },
258
- '--tab': { type: 'string', required: false, description: 'Tab ID', default: 'tab-1' },
259
- },
260
- response: {
261
- type: 'array',
262
- items: { ref: 'string', value: 'string | null', formula: 'string | null', style: 'object | null' },
263
- },
264
- aliases: ['cell.get', 'cells.get', 'sheet.cells.get', 'sheet.cell.get', 'sheets.cell.get'],
265
- },
266
- {
267
- name: 'sheets.cells.set',
268
- description: 'Set a single cell value',
269
- safety: 'write',
270
- parameters: {
271
- 'doc-id': { type: 'string', required: true, description: 'Document ID' },
272
- ref: { type: 'string', required: true, description: 'Cell reference (e.g. A1)' },
273
- value: { type: 'string', required: true, description: 'Cell value or formula' },
274
- '--tab': { type: 'string', required: false, description: 'Tab ID', default: 'tab-1' },
275
- },
276
- response: { ref: 'string', value: 'string', formula: 'string | null' },
277
- aliases: ['cell.set', 'cells.set', 'sheet.cells.set', 'sheet.cell.set', 'sheets.cell.set'],
278
- },
279
- {
280
- name: 'sheets.cells.batch',
281
- description: 'Batch update cells',
282
- safety: 'write',
283
- parameters: {
284
- 'doc-id': { type: 'string', required: true, description: 'Document ID' },
285
- '--tab': { type: 'string', required: false, description: 'Tab ID', default: 'tab-1' },
286
- '--data': { type: 'string', required: false, description: 'JSON data (or pipe from stdin)' },
287
- },
288
- response: { updated: 'number' },
289
- aliases: ['cell.batch', 'cells.batch', 'sheet.cells.batch', 'sheet.cell.batch', 'sheets.cell.batch'],
290
- },
291
- {
292
- name: 'sheets.cells.delete',
293
- description: 'Delete a single cell',
294
- safety: 'destructive',
295
- parameters: {
296
- 'doc-id': { type: 'string', required: true, description: 'Document ID' },
297
- ref: { type: 'string', required: true, description: 'Cell reference' },
298
- '--tab': { type: 'string', required: false, description: 'Tab ID', default: 'tab-1' },
299
- },
300
- response: { ref: 'string', deleted: 'boolean' },
301
- aliases: ['cell.delete', 'cells.delete', 'sheet.cells.delete', 'sheet.cell.delete', 'sheets.cell.delete'],
302
- },
303
- {
304
- name: 'sheets.import',
305
- description: 'Import CSV/JSON into a spreadsheet tab',
306
- safety: 'write',
307
- parameters: {
308
- 'doc-id': { type: 'string', required: true, description: 'Document ID' },
309
- file: { type: 'string', required: true, description: 'File path or - for stdin' },
310
- '--tab': { type: 'string', required: false, description: 'Target tab', default: 'tab-1' },
311
- '--file-format': { type: 'string', required: false, description: 'File format (csv, json)' },
312
- '--start': { type: 'string', required: false, description: 'Top-left cell', default: 'A1' },
313
- },
314
- response: { imported: 'number' },
315
- aliases: ['import', 'sheet.import'],
316
- },
317
- {
318
- name: 'sheets.export',
319
- description: 'Export spreadsheet tab data to CSV/JSON',
320
- safety: 'read-only',
321
- parameters: {
322
- 'doc-id': { type: 'string', required: true, description: 'Document ID' },
323
- file: { type: 'string', required: true, description: 'File path or - for stdout' },
324
- '--tab': { type: 'string', required: false, description: 'Source tab', default: 'tab-1' },
325
- '--range': { type: 'string', required: false, description: 'Cell range (e.g. A1:D100)' },
326
- '--file-format': { type: 'string', required: false, description: 'File format (csv, json)' },
327
- },
328
- response: { type: 'string', description: 'Formatted cell data' },
329
- aliases: ['export', 'sheet.export'],
330
- },
331
- // API keys namespace
332
- {
333
- name: 'api-keys.create',
334
- description: 'Create a new API key',
335
- safety: 'write',
336
- parameters: {
337
- name: { type: 'string', required: true, description: 'Key name' },
338
- },
339
- response: { id: 'string', name: 'string', prefix: 'string', key: 'string' },
340
- aliases: ['api-key.create'],
341
- },
342
- {
343
- name: 'api-keys.list',
344
- description: 'List API keys in workspace',
345
- safety: 'read-only',
346
- parameters: {},
347
- response: { type: 'array', items: { id: 'string', name: 'string', prefix: 'string' } },
348
- aliases: ['api-key.list'],
349
- },
350
- {
351
- name: 'api-keys.revoke',
352
- description: 'Revoke an API key',
353
- safety: 'destructive',
354
- parameters: {
355
- 'key-id': { type: 'string', required: true, description: 'API key ID' },
356
- },
357
- response: { id: 'string' },
358
- aliases: ['api-key.revoke'],
359
- },
360
- ];
361
- /**
362
- * Look up a schema entry by canonical name or any registered alias.
363
- * Aliases let scripts and skills written against the v0.3.x singular
364
- * names (`cell.get`, `doc.list`, `import`) keep working after the
365
- * v0.3.7 namespace shuffle.
366
- */
367
- export function getCommandSchema(name) {
368
- const direct = registry.find((c) => c.name === name);
369
- if (direct)
370
- return direct;
371
- return registry.find((c) => c.aliases?.includes(name));
372
- }
373
- export function getAllCommandSchemas() {
374
- return registry;
375
- }
@@ -1,41 +0,0 @@
1
- import { type SlidesDocument } from '@wafflebase/slides/node';
2
- export declare const VALID_SLIDES_CONTENT_FORMATS: readonly ["json", "md", "text"];
3
- export type SlidesContentFormat = (typeof VALID_SLIDES_CONTENT_FORMATS)[number];
4
- export declare const SLIDES_LOSSY_NOTICE: string;
5
- export declare function parseSlidesContentFormat(value: string): SlidesContentFormat;
6
- /**
7
- * Surface for `runSlidesContent` to talk back to the CLI without taking
8
- * a direct dependency on `process.stdout` / `process.stderr` / `fs`.
9
- * Mirrors `ContentIO` in `../docs/content.ts`; the command wires the
10
- * real implementations, tests inject in-memory collectors.
11
- */
12
- export interface SlidesContentIO {
13
- stdout: (text: string) => void;
14
- stderr: (line: string) => void;
15
- /** Write `text` to `path`. Throws if the file exists and `force` is false. */
16
- writeFile: (path: string, text: string, force: boolean) => void;
17
- }
18
- export declare const defaultSlidesContentIO: SlidesContentIO;
19
- export interface RunSlidesContentArgs {
20
- deck: SlidesDocument;
21
- format: SlidesContentFormat;
22
- /** Include speaker notes (`Slide.notes`) after each slide's body. */
23
- notes?: boolean;
24
- out?: string;
25
- force?: boolean;
26
- quiet?: boolean;
27
- }
28
- /**
29
- * Pure orchestration for `slides content`: takes an already-fetched
30
- * `SlidesDocument` plus user flags, produces the rendered output, and
31
- * routes it through the supplied IO surface.
32
- *
33
- * - `json`: the raw deck JSON (lossless — themes, layouts, geometry,
34
- * styling all preserved).
35
- * - `md` / `text`: per-slide text extraction only. Slides have no single
36
- * linear text stream, so we walk each slide's elements in document
37
- * order, pull every `TextBody`'s blocks (text boxes, shape labels,
38
- * table cells), and serialize them with the docs serializers. Shapes,
39
- * images, connectors, positioning and theming are dropped.
40
- */
41
- export declare function runSlidesContent(args: RunSlidesContentArgs, io?: SlidesContentIO): void;
@@ -1,122 +0,0 @@
1
- import { writeFileSync, existsSync } from 'node:fs';
2
- import { serializeMarkdown, serializeText, } from '@wafflebase/docs';
3
- import { flattenElements, } from '@wafflebase/slides/node';
4
- export const VALID_SLIDES_CONTENT_FORMATS = ['json', 'md', 'text'];
5
- export const SLIDES_LOSSY_NOTICE = 'Lossy conversion: only text is extracted (shapes, images, connectors, ' +
6
- 'layout, theming, and positioning are dropped). See cli.md for details.';
7
- export function parseSlidesContentFormat(value) {
8
- if (!VALID_SLIDES_CONTENT_FORMATS.includes(value)) {
9
- throw new Error(`Invalid --format "${value}". Use one of: ${VALID_SLIDES_CONTENT_FORMATS.join(', ')}.`);
10
- }
11
- return value;
12
- }
13
- export const defaultSlidesContentIO = {
14
- stdout: (text) => {
15
- process.stdout.write(text);
16
- if (!text.endsWith('\n'))
17
- process.stdout.write('\n');
18
- },
19
- stderr: (line) => {
20
- console.error(line);
21
- },
22
- writeFile: (path, text, force) => {
23
- if (existsSync(path) && !force) {
24
- throw new Error(`Refusing to overwrite "${path}". Pass --force to allow overwrite.`);
25
- }
26
- writeFileSync(path, text.endsWith('\n') ? text : text + '\n', 'utf-8');
27
- },
28
- };
29
- /**
30
- * Pure orchestration for `slides content`: takes an already-fetched
31
- * `SlidesDocument` plus user flags, produces the rendered output, and
32
- * routes it through the supplied IO surface.
33
- *
34
- * - `json`: the raw deck JSON (lossless — themes, layouts, geometry,
35
- * styling all preserved).
36
- * - `md` / `text`: per-slide text extraction only. Slides have no single
37
- * linear text stream, so we walk each slide's elements in document
38
- * order, pull every `TextBody`'s blocks (text boxes, shape labels,
39
- * table cells), and serialize them with the docs serializers. Shapes,
40
- * images, connectors, positioning and theming are dropped.
41
- */
42
- export function runSlidesContent(args, io = defaultSlidesContentIO) {
43
- const { deck, format, notes = false, out, force = false, quiet = false } = args;
44
- let text;
45
- if (format === 'json') {
46
- text = JSON.stringify(deck, null, 2);
47
- }
48
- else {
49
- if (!quiet)
50
- io.stderr(SLIDES_LOSSY_NOTICE);
51
- text = serializeDeck(deck, format, notes);
52
- }
53
- if (!out || out === '-') {
54
- io.stdout(text);
55
- return;
56
- }
57
- io.writeFile(out, text, force);
58
- if (!quiet)
59
- io.stderr(`Wrote to ${out}`);
60
- }
61
- /**
62
- * Render every slide as a `## Slide N` (md) / `Slide N` (text) section
63
- * followed by the slide's extracted text. Sections are joined with a
64
- * blank line so the stream reads as one document.
65
- */
66
- function serializeDeck(deck, format, notes) {
67
- const sections = deck.slides.map((slide, i) => serializeSlide(slide, i + 1, format, notes));
68
- return sections.join('\n\n');
69
- }
70
- function serializeSlide(slide, number, format, notes) {
71
- const blocks = collectSlideBlocks(slide);
72
- const body = serializeBlocks(blocks, format);
73
- const parts = [];
74
- parts.push(format === 'md' ? `## Slide ${number}` : `Slide ${number}`);
75
- if (body.length > 0)
76
- parts.push(body);
77
- if (notes && slide.notes.length > 0) {
78
- const notesBody = serializeBlocks(slide.notes, format);
79
- if (notesBody.length > 0) {
80
- parts.push(format === 'md' ? '### Notes' : 'Notes:');
81
- parts.push(notesBody);
82
- }
83
- }
84
- return parts.join('\n\n');
85
- }
86
- /**
87
- * Collect every text block from a slide's elements, in document order.
88
- * Groups are flattened so nested text is included.
89
- */
90
- function collectSlideBlocks(slide) {
91
- const blocks = [];
92
- for (const el of flattenElements(slide.elements)) {
93
- for (const body of textBodiesOf(el)) {
94
- blocks.push(...body.blocks);
95
- }
96
- }
97
- return blocks;
98
- }
99
- /** Extract every `TextBody` carried by a single element. */
100
- function textBodiesOf(el) {
101
- switch (el.type) {
102
- case 'text':
103
- // `TextElement.data` is a `TextBody` (intersection with fill/stroke).
104
- return [el.data];
105
- case 'shape':
106
- return el.data.text ? [el.data.text] : [];
107
- case 'table':
108
- return el.data.rows.flatMap((row) => row.cells.map((cell) => cell.body));
109
- default:
110
- // image / connector carry no text; group is handled by flatten.
111
- return [];
112
- }
113
- }
114
- /**
115
- * Serialize a flat `Block[]` via the docs serializers by wrapping them
116
- * in a synthetic `Document`. The serializers read only `doc.blocks`
117
- * (header/footer are opt-in and never set here), so the cast is safe.
118
- */
119
- function serializeBlocks(blocks, format) {
120
- const doc = { blocks };
121
- return format === 'md' ? serializeMarkdown(doc) : serializeText(doc);
122
- }