agent-spreadsheet-sdk 0.12.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 +226 -0
- package/package.json +36 -0
- package/src/backend.js +388 -0
- package/src/capabilities.js +79 -0
- package/src/errors.js +103 -0
- package/src/index.js +21 -0
- package/src/mcp-backend.js +497 -0
- package/src/wasm-backend.js +393 -0
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
const { freezeCapabilities, WASM_CAPABILITIES } = require("./capabilities")
|
|
2
|
+
const {
|
|
3
|
+
requireCapability,
|
|
4
|
+
requiredString,
|
|
5
|
+
normalizeSheetPageResult,
|
|
6
|
+
normalizeGridExportResult,
|
|
7
|
+
normalizeTransformBatchResult,
|
|
8
|
+
normalizeDescribeWorkbookResult,
|
|
9
|
+
normalizeNamedRangesResult,
|
|
10
|
+
normalizeSheetOverviewResult,
|
|
11
|
+
normalizeFindValueResult,
|
|
12
|
+
normalizeReadTableResult
|
|
13
|
+
} = require("./backend")
|
|
14
|
+
const { SpreadsheetSdkError, normalizeBackendError } = require("./errors")
|
|
15
|
+
|
|
16
|
+
function normalizeSheetNames(items) {
|
|
17
|
+
return items.map((item) => {
|
|
18
|
+
if (typeof item === "string") {
|
|
19
|
+
return item
|
|
20
|
+
}
|
|
21
|
+
if (item && typeof item === "object" && typeof item.name === "string") {
|
|
22
|
+
return item.name
|
|
23
|
+
}
|
|
24
|
+
throw new SpreadsheetSdkError("invalid sheet summary in listSheets response", {
|
|
25
|
+
code: "INVALID_RESPONSE",
|
|
26
|
+
backend: "wasm",
|
|
27
|
+
operation: "listSheets"
|
|
28
|
+
})
|
|
29
|
+
})
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function normalizeListSheetsResult(result) {
|
|
33
|
+
if (Array.isArray(result)) {
|
|
34
|
+
return normalizeSheetNames(result)
|
|
35
|
+
}
|
|
36
|
+
if (result && typeof result === "object") {
|
|
37
|
+
if (Array.isArray(result.sheets)) {
|
|
38
|
+
return normalizeSheetNames(result.sheets)
|
|
39
|
+
}
|
|
40
|
+
if (Array.isArray(result.sheet_names)) {
|
|
41
|
+
return normalizeSheetNames(result.sheet_names)
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
throw new SpreadsheetSdkError("invalid listSheets response", {
|
|
45
|
+
code: "INVALID_RESPONSE",
|
|
46
|
+
backend: "wasm",
|
|
47
|
+
operation: "listSheets"
|
|
48
|
+
})
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function normalizeRangeValuesResult(result, fallbackSheetName) {
|
|
52
|
+
if (!result || typeof result !== "object") {
|
|
53
|
+
throw new SpreadsheetSdkError("invalid rangeValues response", {
|
|
54
|
+
code: "INVALID_RESPONSE",
|
|
55
|
+
backend: "wasm",
|
|
56
|
+
operation: "rangeValues"
|
|
57
|
+
})
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const sheetName = typeof result.sheetName === "string"
|
|
61
|
+
? result.sheetName
|
|
62
|
+
: typeof result.sheet_name === "string"
|
|
63
|
+
? result.sheet_name
|
|
64
|
+
: fallbackSheetName
|
|
65
|
+
|
|
66
|
+
const values = Array.isArray(result.values) ? result.values : []
|
|
67
|
+
return { sheetName, values }
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
class WasmBackend {
|
|
71
|
+
/**
|
|
72
|
+
* @param {{
|
|
73
|
+
* bindings: Record<string, unknown>,
|
|
74
|
+
* capabilities?: import("./capabilities").BackendCapabilities
|
|
75
|
+
* }} params
|
|
76
|
+
*/
|
|
77
|
+
constructor(params) {
|
|
78
|
+
if (!params || !params.bindings || typeof params.bindings !== "object") {
|
|
79
|
+
throw new SpreadsheetSdkError("WasmBackend requires bindings object", {
|
|
80
|
+
code: "INVALID_ARGUMENT",
|
|
81
|
+
backend: "wasm"
|
|
82
|
+
})
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
this.kind = "wasm"
|
|
86
|
+
this._bindings = params.bindings
|
|
87
|
+
this._capabilities = freezeCapabilities(params.capabilities || WASM_CAPABILITIES)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
getCapabilities() {
|
|
91
|
+
return this._capabilities
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
async createSession(input = {}) {
|
|
95
|
+
requireCapability(this, "supportsSessionLifecycle", "createSession")
|
|
96
|
+
const workbookBytes = input.workbookBytes || input.bytes
|
|
97
|
+
if (!workbookBytes) {
|
|
98
|
+
throw new SpreadsheetSdkError("missing required field 'workbookBytes'", {
|
|
99
|
+
code: "INVALID_ARGUMENT",
|
|
100
|
+
backend: this.kind,
|
|
101
|
+
operation: "createSession"
|
|
102
|
+
})
|
|
103
|
+
}
|
|
104
|
+
return this._call("createSession", workbookBytes)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
async describeWorkbook(input = {}) {
|
|
108
|
+
requireCapability(this, "supportsDescribeWorkbook", "describeWorkbook")
|
|
109
|
+
const sessionId = requiredString(input.sessionId || input.session_id || input.contextId, "sessionId")
|
|
110
|
+
const result = await this._call("describeWorkbook", sessionId)
|
|
111
|
+
return normalizeDescribeWorkbookResult(result, sessionId)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
async namedRanges(input = {}) {
|
|
115
|
+
requireCapability(this, "supportsNamedRanges", "namedRanges")
|
|
116
|
+
const sessionId = requiredString(input.sessionId || input.session_id || input.contextId, "sessionId")
|
|
117
|
+
const result = await this._call("namedRanges", sessionId)
|
|
118
|
+
return normalizeNamedRangesResult(result, sessionId)
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
async verifyWorkbook(input = {}) {
|
|
122
|
+
requireCapability(this, "supportsVerification", "verifyWorkbook")
|
|
123
|
+
return input
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
async verifyTargets(input = {}) {
|
|
127
|
+
requireCapability(this, "supportsVerification", "verifyTargets")
|
|
128
|
+
return input
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
async verifyErrors(input = {}) {
|
|
132
|
+
requireCapability(this, "supportsVerification", "verifyErrors")
|
|
133
|
+
return input
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
async defineName(input = {}) {
|
|
137
|
+
requireCapability(this, "supportsNamedRangeMutations", "defineName")
|
|
138
|
+
const sessionId = requiredString(input.sessionId || input.session_id || input.contextId, "sessionId")
|
|
139
|
+
const name = requiredString(input.name, "name")
|
|
140
|
+
const refersTo = requiredString(input.refersTo || input.refers_to, "refersTo")
|
|
141
|
+
return this._call("defineName", sessionId, {
|
|
142
|
+
name,
|
|
143
|
+
refersTo: refersTo,
|
|
144
|
+
scope: input.scope,
|
|
145
|
+
scopeSheetName: input.scopeSheetName ?? input.scope_sheet_name
|
|
146
|
+
})
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
async updateName(input = {}) {
|
|
150
|
+
requireCapability(this, "supportsNamedRangeMutations", "updateName")
|
|
151
|
+
const sessionId = requiredString(input.sessionId || input.session_id || input.contextId, "sessionId")
|
|
152
|
+
const name = requiredString(input.name, "name")
|
|
153
|
+
return this._call("updateName", sessionId, {
|
|
154
|
+
name,
|
|
155
|
+
refersTo: input.refersTo ?? input.refers_to,
|
|
156
|
+
scope: input.scope,
|
|
157
|
+
scopeSheetName: input.scopeSheetName ?? input.scope_sheet_name
|
|
158
|
+
})
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
async deleteName(input = {}) {
|
|
162
|
+
requireCapability(this, "supportsNamedRangeMutations", "deleteName")
|
|
163
|
+
const sessionId = requiredString(input.sessionId || input.session_id || input.contextId, "sessionId")
|
|
164
|
+
const name = requiredString(input.name, "name")
|
|
165
|
+
return this._call("deleteName", sessionId, {
|
|
166
|
+
name,
|
|
167
|
+
scope: input.scope,
|
|
168
|
+
scopeSheetName: input.scopeSheetName ?? input.scope_sheet_name
|
|
169
|
+
})
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
async sheetOverview(input = {}) {
|
|
173
|
+
requireCapability(this, "supportsSheetOverview", "sheetOverview")
|
|
174
|
+
const sessionId = requiredString(input.sessionId || input.session_id || input.contextId, "sessionId")
|
|
175
|
+
const sheetName = requiredString(input.sheetName || input.sheet_name, "sheetName")
|
|
176
|
+
const result = await this._call("sheetOverview", sessionId, {
|
|
177
|
+
...input,
|
|
178
|
+
sheetName,
|
|
179
|
+
maxRegions: input.maxRegions ?? input.max_regions,
|
|
180
|
+
maxHeaders: input.maxHeaders ?? input.max_headers,
|
|
181
|
+
includeHeaders: input.includeHeaders ?? input.include_headers
|
|
182
|
+
})
|
|
183
|
+
return normalizeSheetOverviewResult(result, sheetName, sessionId)
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
async listSheets(input = {}) {
|
|
187
|
+
requireCapability(this, "supportsListSheets", "listSheets")
|
|
188
|
+
const sessionId = requiredString(input.sessionId || input.session_id || input.contextId, "sessionId")
|
|
189
|
+
const result = await this._call("listSheets", sessionId)
|
|
190
|
+
return normalizeListSheetsResult(result)
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
async rangeValues(input = {}) {
|
|
194
|
+
requireCapability(this, "supportsRangeValues", "rangeValues")
|
|
195
|
+
const sessionId = requiredString(input.sessionId || input.session_id || input.contextId, "sessionId")
|
|
196
|
+
const sheetName = requiredString(input.sheetName || input.sheet_name, "sheetName")
|
|
197
|
+
const ranges = input.ranges
|
|
198
|
+
|
|
199
|
+
const result = await this._call("rangeValues", sessionId, {
|
|
200
|
+
sheetName,
|
|
201
|
+
ranges
|
|
202
|
+
})
|
|
203
|
+
|
|
204
|
+
return normalizeRangeValuesResult(result, sheetName)
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
async findValue(input = {}) {
|
|
208
|
+
requireCapability(this, "supportsFindValue", "findValue")
|
|
209
|
+
const sessionId = requiredString(input.sessionId || input.session_id || input.contextId, "sessionId")
|
|
210
|
+
const query = requiredString(input.query, "query")
|
|
211
|
+
|
|
212
|
+
const result = await this._call("findValue", sessionId, {
|
|
213
|
+
...input,
|
|
214
|
+
query,
|
|
215
|
+
sheetName: input.sheetName ?? input.sheet_name,
|
|
216
|
+
caseSensitive: input.caseSensitive ?? input.case_sensitive,
|
|
217
|
+
limit: input.limit,
|
|
218
|
+
offset: input.offset
|
|
219
|
+
})
|
|
220
|
+
|
|
221
|
+
return normalizeFindValueResult(result, sessionId)
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
async readTable(input = {}) {
|
|
225
|
+
requireCapability(this, "supportsReadTable", "readTable")
|
|
226
|
+
const sessionId = requiredString(input.sessionId || input.session_id || input.contextId, "sessionId")
|
|
227
|
+
|
|
228
|
+
const result = await this._call("readTable", sessionId, {
|
|
229
|
+
...input,
|
|
230
|
+
sheetName: input.sheetName ?? input.sheet_name,
|
|
231
|
+
includeHeaders: input.includeHeaders ?? input.include_headers,
|
|
232
|
+
includeTypes: input.includeTypes ?? input.include_types
|
|
233
|
+
})
|
|
234
|
+
|
|
235
|
+
return normalizeReadTableResult(result, sessionId, input.sheetName || input.sheet_name)
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
async sheetPage(input = {}) {
|
|
239
|
+
requireCapability(this, "supportsSheetPage", "sheetPage")
|
|
240
|
+
const sessionId = requiredString(input.sessionId || input.session_id || input.contextId, "sessionId")
|
|
241
|
+
const sheetName = requiredString(input.sheetName || input.sheet_name, "sheetName")
|
|
242
|
+
|
|
243
|
+
const result = await this._call("sheetPage", sessionId, {
|
|
244
|
+
...input,
|
|
245
|
+
sheetName,
|
|
246
|
+
startRow: input.startRow ?? input.start_row,
|
|
247
|
+
pageSize: input.pageSize ?? input.page_size,
|
|
248
|
+
columnsByHeader: input.columnsByHeader ?? input.columns_by_header,
|
|
249
|
+
includeFormulas: input.includeFormulas ?? input.include_formulas,
|
|
250
|
+
includeStyles: input.includeStyles ?? input.include_styles,
|
|
251
|
+
includeHeader: input.includeHeader ?? input.include_header
|
|
252
|
+
})
|
|
253
|
+
|
|
254
|
+
return normalizeSheetPageResult(result, sheetName)
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
async gridExport(input = {}) {
|
|
258
|
+
requireCapability(this, "supportsGridExport", "gridExport")
|
|
259
|
+
const sessionId = requiredString(input.sessionId || input.session_id || input.contextId, "sessionId")
|
|
260
|
+
const sheetName = requiredString(input.sheetName || input.sheet_name, "sheetName")
|
|
261
|
+
|
|
262
|
+
const result = await this._call("gridExport", sessionId, {
|
|
263
|
+
...input,
|
|
264
|
+
sheetName,
|
|
265
|
+
range: input.range
|
|
266
|
+
})
|
|
267
|
+
|
|
268
|
+
return normalizeGridExportResult(result)
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
async transformBatch(input = {}) {
|
|
272
|
+
requireCapability(this, "supportsTransformBatch", "transformBatch")
|
|
273
|
+
const sessionId = requiredString(input.sessionId || input.session_id || input.contextId, "sessionId")
|
|
274
|
+
|
|
275
|
+
// Convert SDK generic `mode: "preview"` to Wasm specific `dryRun` if missing options
|
|
276
|
+
const options = input.options ?? {}
|
|
277
|
+
if (input.mode === "preview" && options.dryRun === undefined) {
|
|
278
|
+
options.dryRun = true
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
const result = await this._call("transformBatch", sessionId, input.ops || [], options)
|
|
282
|
+
|
|
283
|
+
return normalizeTransformBatchResult(result)
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
async replaceInFormulas() {
|
|
287
|
+
requireCapability(this, "supportsReplaceInFormulas", "replaceInFormulas")
|
|
288
|
+
throw new SpreadsheetSdkError("replaceInFormulas is not implemented for WASM backend (fork-only)", {
|
|
289
|
+
code: "UNSUPPORTED",
|
|
290
|
+
backend: this.kind,
|
|
291
|
+
operation: "replaceInFormulas"
|
|
292
|
+
})
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
async exportWorkbook(input = {}) {
|
|
296
|
+
requireCapability(this, "supportsExportWorkbook", "exportWorkbook")
|
|
297
|
+
const sessionId = requiredString(input.sessionId || input.session_id || input.contextId, "sessionId")
|
|
298
|
+
return this._call("exportWorkbook", sessionId)
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
async disposeSession(input = {}) {
|
|
302
|
+
requireCapability(this, "supportsSessionLifecycle", "disposeSession")
|
|
303
|
+
const sessionId = requiredString(input.sessionId || input.session_id || input.contextId, "sessionId")
|
|
304
|
+
return this._call("disposeSession", sessionId)
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
async createFork() {
|
|
308
|
+
requireCapability(this, "supportsForkLifecycle", "createFork")
|
|
309
|
+
throw new SpreadsheetSdkError("createFork is not implemented for WASM backend", {
|
|
310
|
+
code: "UNSUPPORTED",
|
|
311
|
+
backend: this.kind,
|
|
312
|
+
operation: "createFork"
|
|
313
|
+
})
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
async listForks() {
|
|
317
|
+
requireCapability(this, "supportsForkLifecycle", "listForks")
|
|
318
|
+
throw new SpreadsheetSdkError("listForks is not implemented for WASM backend", {
|
|
319
|
+
code: "UNSUPPORTED",
|
|
320
|
+
backend: this.kind,
|
|
321
|
+
operation: "listForks"
|
|
322
|
+
})
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
async saveFork() {
|
|
326
|
+
requireCapability(this, "supportsForkLifecycle", "saveFork")
|
|
327
|
+
throw new SpreadsheetSdkError("saveFork is not implemented for WASM backend", {
|
|
328
|
+
code: "UNSUPPORTED",
|
|
329
|
+
backend: this.kind,
|
|
330
|
+
operation: "saveFork"
|
|
331
|
+
})
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
async discardFork() {
|
|
335
|
+
requireCapability(this, "supportsForkLifecycle", "discardFork")
|
|
336
|
+
throw new SpreadsheetSdkError("discardFork is not implemented for WASM backend", {
|
|
337
|
+
code: "UNSUPPORTED",
|
|
338
|
+
backend: this.kind,
|
|
339
|
+
operation: "discardFork"
|
|
340
|
+
})
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
async listStagedChanges() {
|
|
344
|
+
requireCapability(this, "supportsStaging", "listStagedChanges")
|
|
345
|
+
throw new SpreadsheetSdkError("listStagedChanges is not implemented for WASM backend", {
|
|
346
|
+
code: "UNSUPPORTED",
|
|
347
|
+
backend: this.kind,
|
|
348
|
+
operation: "listStagedChanges"
|
|
349
|
+
})
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
async applyStagedChange() {
|
|
353
|
+
requireCapability(this, "supportsStaging", "applyStagedChange")
|
|
354
|
+
throw new SpreadsheetSdkError("applyStagedChange is not implemented for WASM backend", {
|
|
355
|
+
code: "UNSUPPORTED",
|
|
356
|
+
backend: this.kind,
|
|
357
|
+
operation: "applyStagedChange"
|
|
358
|
+
})
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
async discardStagedChange() {
|
|
362
|
+
requireCapability(this, "supportsStaging", "discardStagedChange")
|
|
363
|
+
throw new SpreadsheetSdkError("discardStagedChange is not implemented for WASM backend", {
|
|
364
|
+
code: "UNSUPPORTED",
|
|
365
|
+
backend: this.kind,
|
|
366
|
+
operation: "discardStagedChange"
|
|
367
|
+
})
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
async _call(binding, ...args) {
|
|
371
|
+
const fn = this._bindings[binding]
|
|
372
|
+
if (typeof fn !== "function") {
|
|
373
|
+
throw new SpreadsheetSdkError(`wasm bindings missing '${binding}'`, {
|
|
374
|
+
code: "INVALID_ARGUMENT",
|
|
375
|
+
backend: this.kind,
|
|
376
|
+
operation: binding
|
|
377
|
+
})
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
try {
|
|
381
|
+
return await fn(...args)
|
|
382
|
+
} catch (error) {
|
|
383
|
+
throw normalizeBackendError(error, {
|
|
384
|
+
backend: this.kind,
|
|
385
|
+
operation: binding
|
|
386
|
+
})
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
module.exports = {
|
|
392
|
+
WasmBackend
|
|
393
|
+
}
|