@components-kit/open-workbook 0.1.1 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -0
- package/assets/backend/dist/runtime-service.d.ts +150 -191
- package/assets/backend/dist/runtime-service.d.ts.map +1 -1
- package/assets/backend/dist/runtime-service.js +92 -8
- package/assets/backend/dist/runtime-service.js.map +1 -1
- package/assets/excel-addin/dist/connection.d.ts.map +1 -1
- package/assets/excel-addin/dist/connection.js +4 -1
- package/assets/excel-addin/dist/connection.js.map +1 -1
- package/assets/excel-addin/dist/excel-executor.d.ts +7 -2
- package/assets/excel-addin/dist/excel-executor.d.ts.map +1 -1
- package/assets/excel-addin/dist/excel-executor.js +204 -40
- package/assets/excel-addin/dist/excel-executor.js.map +1 -1
- package/assets/excel-addin/manifest.xml +1 -1
- package/assets/excel-addin/scripts/dev-server.mjs +46 -0
- package/assets/instructions/open-workbook-excel/references/tool-selection.md +4 -2
- package/assets/instructions/open-workbook-excel/references/workflows.md +7 -4
- package/assets/mcp-server/dist/index.js +73 -7
- package/assets/mcp-server/dist/index.js.map +1 -1
- package/dist/index.js +181 -36
- package/dist/index.js.map +1 -1
- package/package.json +6 -6
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { mkdir, readFile, stat, unlink, writeFile } from "node:fs/promises";
|
|
2
2
|
import { createHash } from "node:crypto";
|
|
3
3
|
import path from "node:path";
|
|
4
|
-
import { BackupManager, BatchCompiler, DefaultPermissionPolicy, buildFormulaDependencyGraph, attachConflictGuidance, extractFormulaReferences, hashStable, LockManager, parseA1Address, PlanManager, SnapshotManager, TaskRegistry, TemplateRegistry, TransactionManager, traceDependents, tracePrecedents } from "@components-kit/open-workbook-excel-core";
|
|
4
|
+
import { BackupManager, BatchCompiler, DefaultPermissionPolicy, buildFormulaDependencyGraph, attachConflictGuidance, extractFormulaReferences, hashStable, LockManager, formatA1Address, parseA1Address, PlanManager, SnapshotManager, TaskRegistry, TemplateRegistry, TransactionManager, traceDependents, tracePrecedents } from "@components-kit/open-workbook-excel-core";
|
|
5
5
|
import { makeRollbackConflict } from "@components-kit/open-workbook-excel-core";
|
|
6
6
|
import { getToolCatalogSummary, PromptCatalog, ResourceCatalog, makeId, runtimeError } from "@components-kit/open-workbook-protocol";
|
|
7
7
|
import { SessionRegistry } from "./session-registry.js";
|
|
8
8
|
import { NativeFileBridge } from "./native-file-bridge.js";
|
|
9
9
|
import { RuntimeStateStore } from "./state-store.js";
|
|
10
|
+
const runtimeVersion = process.env.OPEN_WORKBOOK_VERSION ?? "0.1.3";
|
|
10
11
|
export class RuntimeService {
|
|
11
12
|
sessions = new SessionRegistry();
|
|
12
13
|
backups = new BackupManager();
|
|
@@ -913,6 +914,12 @@ export class RuntimeService {
|
|
|
913
914
|
const activeSession = this.sessions.getActive();
|
|
914
915
|
return {
|
|
915
916
|
ok: true,
|
|
917
|
+
runtime: {
|
|
918
|
+
service: "open-workbook-backend",
|
|
919
|
+
packageName: "@components-kit/open-workbook-backend",
|
|
920
|
+
version: runtimeVersion,
|
|
921
|
+
pid: process.pid
|
|
922
|
+
},
|
|
916
923
|
activeAddinConnected: Boolean(activeSession),
|
|
917
924
|
fileBridge: this.fileBridge.getStatus(),
|
|
918
925
|
sessions: this.sessions.list(),
|
|
@@ -2703,11 +2710,9 @@ export class RuntimeService {
|
|
|
2703
2710
|
return cleaningError(input.workbookId, "normalize_headers", target, read.error);
|
|
2704
2711
|
}
|
|
2705
2712
|
const headerRowIndex = input.headerRowIndex ?? detectHeaderCandidates(read.values, 10)[0]?.rowIndex ?? 0;
|
|
2706
|
-
const
|
|
2707
|
-
const before = values[headerRowIndex] ?? [];
|
|
2713
|
+
const before = read.values[headerRowIndex] ?? [];
|
|
2708
2714
|
const normalized = dedupeHeaders(before.map((value) => normalizeHeader(String(value ?? ""))));
|
|
2709
|
-
|
|
2710
|
-
const result = await this.writeCleanValues(target, values, "Normalize headers");
|
|
2715
|
+
const result = await this.writeCleanValues(headerRowTarget(target, headerRowIndex), [normalized], "Normalize headers");
|
|
2711
2716
|
return cleaningReport(input.workbookId, "normalize_headers", target, changedCellCount([before], [normalized]), { headerRowIndex, headers: normalized }, result);
|
|
2712
2717
|
}
|
|
2713
2718
|
async cleanTrimWhitespace(input) {
|
|
@@ -3132,6 +3137,22 @@ export class RuntimeService {
|
|
|
3132
3137
|
async resizeTable(request) {
|
|
3133
3138
|
return this.mutateTable("table.resize", request, `Before resizing table ${request.tableName}`, await this.getTableBackupRanges(request));
|
|
3134
3139
|
}
|
|
3140
|
+
async reorderTableColumns(request) {
|
|
3141
|
+
const infoResult = await this.getTableInfo(request);
|
|
3142
|
+
const info = infoResult.info;
|
|
3143
|
+
if (!info) {
|
|
3144
|
+
return {
|
|
3145
|
+
ok: false,
|
|
3146
|
+
error: runtimeError("NOT_FOUND", `Table ${request.tableName} could not be read before column reorder.`, { retryable: false }),
|
|
3147
|
+
table: infoResult
|
|
3148
|
+
};
|
|
3149
|
+
}
|
|
3150
|
+
const validation = validateTableColumnOrder(info, request.columnOrder);
|
|
3151
|
+
if (!validation.ok) {
|
|
3152
|
+
return validation;
|
|
3153
|
+
}
|
|
3154
|
+
return this.mutateTable("table.reorder_columns", request, `Before reordering columns in table ${request.tableName}`, await this.getTableBackupRanges(request));
|
|
3155
|
+
}
|
|
3135
3156
|
async appendTableRows(request) {
|
|
3136
3157
|
return this.mutateTable("table.append_rows", request, `Before appending rows to table ${request.tableName}`, await this.getTableBackupRanges(request));
|
|
3137
3158
|
}
|
|
@@ -3261,15 +3282,18 @@ export class RuntimeService {
|
|
|
3261
3282
|
workbookId: request.workbookId,
|
|
3262
3283
|
goal: reason,
|
|
3263
3284
|
scopes: tableMutationScopes(request, ranges),
|
|
3264
|
-
destructiveLevel: method.includes("resize") || method.includes("copy_structure") ? "structure" : "values"
|
|
3285
|
+
destructiveLevel: method.includes("resize") || method.includes("copy_structure") || method.includes("reorder_columns") ? "structure" : "values"
|
|
3265
3286
|
}, async () => {
|
|
3266
3287
|
const backup = await this.createWorkbookBackup({
|
|
3267
3288
|
workbookId: request.workbookId,
|
|
3268
3289
|
reason,
|
|
3269
3290
|
ranges
|
|
3270
3291
|
});
|
|
3292
|
+
if (!("backup" in backup)) {
|
|
3293
|
+
return backup;
|
|
3294
|
+
}
|
|
3271
3295
|
const result = await client.request(method, request);
|
|
3272
|
-
return { ok: true, backup, result };
|
|
3296
|
+
return { ok: true, backup: backup.backup, result };
|
|
3273
3297
|
});
|
|
3274
3298
|
}
|
|
3275
3299
|
async mutateFormulas(method, request, reason, validate) {
|
|
@@ -5331,6 +5355,58 @@ function pivotTemplateRequiredSourceFields(info) {
|
|
|
5331
5355
|
function uniqueDefined(values) {
|
|
5332
5356
|
return [...new Set(values.filter((value) => typeof value === "string" && value.length > 0))];
|
|
5333
5357
|
}
|
|
5358
|
+
function validateTableColumnOrder(info, columnOrder) {
|
|
5359
|
+
const issues = [];
|
|
5360
|
+
if (columnOrder.length !== info.columns.length) {
|
|
5361
|
+
issues.push({
|
|
5362
|
+
code: "TABLE_COLUMN_ORDER_LENGTH_MISMATCH",
|
|
5363
|
+
message: `Column order must include exactly ${info.columns.length} column(s).`,
|
|
5364
|
+
details: { expectedCount: info.columns.length, actualCount: columnOrder.length }
|
|
5365
|
+
});
|
|
5366
|
+
}
|
|
5367
|
+
const seen = new Set();
|
|
5368
|
+
for (const requested of columnOrder) {
|
|
5369
|
+
const column = typeof requested === "number"
|
|
5370
|
+
? info.columns.find((candidate) => candidate.index === requested)
|
|
5371
|
+
: info.columns.find((candidate) => candidate.name === requested);
|
|
5372
|
+
if (!column) {
|
|
5373
|
+
issues.push({
|
|
5374
|
+
code: "TABLE_COLUMN_NOT_FOUND",
|
|
5375
|
+
message: `Column ${String(requested)} is not present in table ${info.tableName}.`,
|
|
5376
|
+
details: { requested, availableColumns: info.columns.map((candidate) => candidate.name) }
|
|
5377
|
+
});
|
|
5378
|
+
continue;
|
|
5379
|
+
}
|
|
5380
|
+
if (seen.has(column.index)) {
|
|
5381
|
+
issues.push({
|
|
5382
|
+
code: "TABLE_COLUMN_ORDER_DUPLICATE",
|
|
5383
|
+
message: `Column ${column.name} appears more than once in the requested order.`,
|
|
5384
|
+
details: { requested, column }
|
|
5385
|
+
});
|
|
5386
|
+
}
|
|
5387
|
+
seen.add(column.index);
|
|
5388
|
+
}
|
|
5389
|
+
for (const column of info.columns) {
|
|
5390
|
+
if (!seen.has(column.index)) {
|
|
5391
|
+
issues.push({
|
|
5392
|
+
code: "TABLE_COLUMN_ORDER_MISSING_COLUMN",
|
|
5393
|
+
message: `Column ${column.name} is missing from the requested order.`,
|
|
5394
|
+
details: { column }
|
|
5395
|
+
});
|
|
5396
|
+
}
|
|
5397
|
+
}
|
|
5398
|
+
if (issues.length > 0) {
|
|
5399
|
+
return {
|
|
5400
|
+
ok: false,
|
|
5401
|
+
warnings: issues,
|
|
5402
|
+
error: runtimeError("INVALID_ARGUMENT", "Table column reorder requires a complete, unique column order.", {
|
|
5403
|
+
retryable: false,
|
|
5404
|
+
details: { issues }
|
|
5405
|
+
})
|
|
5406
|
+
};
|
|
5407
|
+
}
|
|
5408
|
+
return { ok: true };
|
|
5409
|
+
}
|
|
5334
5410
|
function addExpectedPivotAxisIssues(issues, axis, expectedFields, actualFields) {
|
|
5335
5411
|
if (!expectedFields?.length) {
|
|
5336
5412
|
return;
|
|
@@ -5542,6 +5618,14 @@ function targetFromCleanInput(input) {
|
|
|
5542
5618
|
address: input.address
|
|
5543
5619
|
};
|
|
5544
5620
|
}
|
|
5621
|
+
function headerRowTarget(target, headerRowIndex) {
|
|
5622
|
+
const parsed = parseA1Address(stripSheetName(target.address));
|
|
5623
|
+
const row = parsed.startRow + headerRowIndex;
|
|
5624
|
+
return {
|
|
5625
|
+
...target,
|
|
5626
|
+
address: formatA1Address({ startColumn: parsed.startColumn, endColumn: parsed.endColumn, startRow: row, endRow: row })
|
|
5627
|
+
};
|
|
5628
|
+
}
|
|
5545
5629
|
function cleaningReport(workbookId, action, target, changedCells, data, result) {
|
|
5546
5630
|
const report = {
|
|
5547
5631
|
ok: result ? result.ok : true,
|
|
@@ -5886,7 +5970,7 @@ function disconnectedRuntimeCapabilities() {
|
|
|
5886
5970
|
return {
|
|
5887
5971
|
engine: {
|
|
5888
5972
|
name: "open-workbook-daemon",
|
|
5889
|
-
version:
|
|
5973
|
+
version: runtimeVersion,
|
|
5890
5974
|
platform: "unknown"
|
|
5891
5975
|
},
|
|
5892
5976
|
apiSets: [],
|