@tita-agent/dsh-data-table 0.0.0-stage → 0.2.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 (267) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +172 -2
  3. package/cordis.patch.yml +7 -0
  4. package/lib/client.js +16766 -0
  5. package/lib/contract-envelope.d.ts +91 -0
  6. package/lib/contract-envelope.js +106 -0
  7. package/lib/contract-layout.d.ts +130 -0
  8. package/lib/contract-layout.js +138 -0
  9. package/lib/contract-refs.d.ts +39 -0
  10. package/lib/contract-refs.js +9 -0
  11. package/lib/contract-version.d.ts +311 -0
  12. package/lib/contract-version.js +270 -0
  13. package/lib/contract-wire.d.ts +147 -0
  14. package/lib/contract-wire.js +99 -0
  15. package/lib/contracts.d.ts +12 -0
  16. package/lib/contracts.js +12 -0
  17. package/lib/types/audit.d.ts +42 -0
  18. package/lib/types/audit.js +39 -0
  19. package/lib/types/client/ProjectImportMenu.d.ts +30 -0
  20. package/lib/types/client/ProjectImportMenu.js +70 -0
  21. package/lib/types/client/SheetPanel.d.ts +33 -0
  22. package/lib/types/client/SheetPanel.js +1766 -0
  23. package/lib/types/client/SheetToggle.d.ts +18 -0
  24. package/lib/types/client/SheetToggle.js +26 -0
  25. package/lib/types/client/index.d.ts +15 -0
  26. package/lib/types/client/index.js +110 -0
  27. package/lib/types/client/persistence/changes.d.ts +15 -0
  28. package/lib/types/client/persistence/changes.js +51 -0
  29. package/lib/types/client/persistence/ids.d.ts +34 -0
  30. package/lib/types/client/persistence/ids.js +48 -0
  31. package/lib/types/client/persistence/merge.d.ts +35 -0
  32. package/lib/types/client/persistence/merge.js +362 -0
  33. package/lib/types/client/store.d.ts +61 -0
  34. package/lib/types/client/store.js +152 -0
  35. package/lib/types/client/surface-context.d.ts +27 -0
  36. package/lib/types/client/surface-context.js +104 -0
  37. package/lib/types/client/surface-control.d.ts +2 -0
  38. package/lib/types/client/surface-control.js +12 -0
  39. package/lib/types/client/transport/workbookApi.d.ts +159 -0
  40. package/lib/types/client/transport/workbookApi.js +246 -0
  41. package/lib/types/client/univer/StandaloneWorkbookPage.d.ts +5 -0
  42. package/lib/types/client/univer/StandaloneWorkbookPage.js +7 -0
  43. package/lib/types/client/univer/WorkbookCanvas.d.ts +40 -0
  44. package/lib/types/client/univer/WorkbookCanvas.js +87 -0
  45. package/lib/types/client/univer/WorkbookView.d.ts +3 -0
  46. package/lib/types/client/univer/WorkbookView.js +2 -0
  47. package/lib/types/client/univer/loader.d.ts +18 -0
  48. package/lib/types/client/univer/loader.js +81 -0
  49. package/lib/types/client/univer/standalone-entry.d.ts +1 -0
  50. package/lib/types/client/univer/standalone-entry.js +19 -0
  51. package/lib/types/client/versions/VersionChrome.d.ts +33 -0
  52. package/lib/types/client/versions/VersionChrome.js +21 -0
  53. package/lib/types/client/versions/inspect.d.ts +70 -0
  54. package/lib/types/client/versions/inspect.js +88 -0
  55. package/lib/types/client/versions/preview-decoration.d.ts +11 -0
  56. package/lib/types/client/versions/preview-decoration.js +54 -0
  57. package/lib/types/client/versions/records.d.ts +19 -0
  58. package/lib/types/client/versions/records.js +70 -0
  59. package/lib/types/client/workspace-host.d.ts +61 -0
  60. package/lib/types/client/workspace-host.js +124 -0
  61. package/lib/types/collaboration-hub.d.ts +31 -0
  62. package/lib/types/collaboration-hub.js +69 -0
  63. package/lib/types/contract/ids.d.ts +24 -0
  64. package/lib/types/contract/ids.js +46 -0
  65. package/lib/types/contract/mutations.d.ts +25 -0
  66. package/lib/types/contract/mutations.js +782 -0
  67. package/lib/types/contract/operations.d.ts +54 -0
  68. package/lib/types/contract/operations.js +203 -0
  69. package/lib/types/contract/snapshots.d.ts +176 -0
  70. package/lib/types/contract/snapshots.js +351 -0
  71. package/lib/types/contract/univer-api-catalog.d.ts +29 -0
  72. package/lib/types/contract/univer-api-catalog.js +264 -0
  73. package/lib/types/errors.d.ts +8 -0
  74. package/lib/types/errors.js +12 -0
  75. package/lib/types/http/assets-routes.d.ts +3 -0
  76. package/lib/types/http/assets-routes.js +169 -0
  77. package/lib/types/http/collaboration.d.ts +10 -0
  78. package/lib/types/http/collaboration.js +154 -0
  79. package/lib/types/http/history.d.ts +15 -0
  80. package/lib/types/http/history.js +134 -0
  81. package/lib/types/http/project-files.d.ts +79 -0
  82. package/lib/types/http/project-files.js +206 -0
  83. package/lib/types/http/project-scope.d.ts +50 -0
  84. package/lib/types/http/project-scope.js +52 -0
  85. package/lib/types/http/routes.d.ts +98 -0
  86. package/lib/types/http/routes.js +323 -0
  87. package/lib/types/http/standalone.d.ts +9 -0
  88. package/lib/types/http/standalone.js +31 -0
  89. package/lib/types/http/trunk.d.ts +10 -0
  90. package/lib/types/http/trunk.js +322 -0
  91. package/lib/types/http/worktree.d.ts +9 -0
  92. package/lib/types/http/worktree.js +145 -0
  93. package/lib/types/index.d.ts +18 -0
  94. package/lib/types/index.js +156 -0
  95. package/lib/types/invariant.d.ts +15 -0
  96. package/lib/types/invariant.js +15 -0
  97. package/lib/types/request-params.d.ts +21 -0
  98. package/lib/types/request-params.js +76 -0
  99. package/lib/types/store/paths.d.ts +68 -0
  100. package/lib/types/store/paths.js +148 -0
  101. package/lib/types/store/project.d.ts +88 -0
  102. package/lib/types/store/project.js +120 -0
  103. package/lib/types/store/read.d.ts +110 -0
  104. package/lib/types/store/read.js +404 -0
  105. package/lib/types/store/retention.d.ts +27 -0
  106. package/lib/types/store/retention.js +111 -0
  107. package/lib/types/store/write.d.ts +22 -0
  108. package/lib/types/store/write.js +210 -0
  109. package/lib/types/tools/arguments.d.ts +40 -0
  110. package/lib/types/tools/arguments.js +130 -0
  111. package/lib/types/tools/cells.d.ts +50 -0
  112. package/lib/types/tools/cells.js +298 -0
  113. package/lib/types/tools/index.d.ts +2 -0
  114. package/lib/types/tools/index.js +250 -0
  115. package/lib/types/tools/render.d.ts +47 -0
  116. package/lib/types/tools/render.js +290 -0
  117. package/lib/types/tools/univer-api.d.ts +18 -0
  118. package/lib/types/tools/univer-api.js +198 -0
  119. package/lib/types/tools/workbook-catalog.d.ts +3 -0
  120. package/lib/types/tools/workbook-catalog.js +83 -0
  121. package/lib/types/tools/workbook-edit.d.ts +192 -0
  122. package/lib/types/tools/workbook-edit.js +912 -0
  123. package/lib/types/tools/workbook-find.d.ts +11 -0
  124. package/lib/types/tools/workbook-find.js +89 -0
  125. package/lib/types/tools/workbook-history.d.ts +2 -0
  126. package/lib/types/tools/workbook-history.js +59 -0
  127. package/lib/types/tools/workbook-read.d.ts +21 -0
  128. package/lib/types/tools/workbook-read.js +204 -0
  129. package/lib/types/types.d.ts +377 -0
  130. package/lib/types/types.js +34 -0
  131. package/lib/types/univer/apply-operation.d.ts +14 -0
  132. package/lib/types/univer/apply-operation.js +398 -0
  133. package/lib/types/univer/chunk.d.ts +68 -0
  134. package/lib/types/univer/chunk.js +16 -0
  135. package/lib/types/univer/decoration.d.ts +34 -0
  136. package/lib/types/univer/decoration.js +88 -0
  137. package/lib/types/univer/diagnostics.d.ts +31 -0
  138. package/lib/types/univer/diagnostics.js +141 -0
  139. package/lib/types/univer/engine.d.ts +33 -0
  140. package/lib/types/univer/engine.js +338 -0
  141. package/lib/types/univer/entry.d.ts +8 -0
  142. package/lib/types/univer/entry.js +11 -0
  143. package/lib/types/univer/facade.d.ts +107 -0
  144. package/lib/types/univer/facade.js +1 -0
  145. package/lib/types/univer/fonts.d.ts +202 -0
  146. package/lib/types/univer/fonts.js +140 -0
  147. package/lib/types/univer/plugins/collaboration.d.ts +23 -0
  148. package/lib/types/univer/plugins/collaboration.js +47 -0
  149. package/lib/types/univer/plugins/export.d.ts +39 -0
  150. package/lib/types/univer/plugins/export.js +246 -0
  151. package/lib/types/univer/plugins/history.d.ts +24 -0
  152. package/lib/types/univer/plugins/history.js +50 -0
  153. package/lib/types/univer/plugins/version.d.ts +13 -0
  154. package/lib/types/univer/plugins/version.js +13 -0
  155. package/lib/types/version/diff.d.ts +36 -0
  156. package/lib/types/version/diff.js +156 -0
  157. package/lib/types/version/grouping.d.ts +7 -0
  158. package/lib/types/version/grouping.js +94 -0
  159. package/lib/types/version/records.d.ts +17 -0
  160. package/lib/types/version/records.js +102 -0
  161. package/lib/types/version/session.d.ts +36 -0
  162. package/lib/types/version/session.js +89 -0
  163. package/lib/types/version/summary.d.ts +24 -0
  164. package/lib/types/version/summary.js +111 -0
  165. package/lib/types/workbook-manager.d.ts +191 -0
  166. package/lib/types/workbook-manager.js +935 -0
  167. package/lib/types/xlsx-export-worker.d.ts +5 -0
  168. package/lib/types/xlsx-export-worker.js +24 -0
  169. package/lib/types/xlsx-export.d.ts +21 -0
  170. package/lib/types/xlsx-export.js +371 -0
  171. package/lib/types/xlsx-import-worker.d.ts +1 -0
  172. package/lib/types/xlsx-import-worker.js +19 -0
  173. package/lib/univer-client.js +690 -0
  174. package/lib/workbook-page.js +23826 -0
  175. package/lib/xlsx-export-worker.js +104 -0
  176. package/lib/xlsx-import-worker.js +46 -0
  177. package/package.json +106 -3
  178. package/src/audit.ts +58 -0
  179. package/src/client/ProjectImportMenu.tsx +100 -0
  180. package/src/client/SheetPanel.module.css +1578 -0
  181. package/src/client/SheetPanel.tsx +1934 -0
  182. package/src/client/SheetToggle.module.css +73 -0
  183. package/src/client/SheetToggle.tsx +65 -0
  184. package/src/client/contract.d.ts +19 -0
  185. package/src/client/index.ts +131 -0
  186. package/src/client/persistence/changes.ts +58 -0
  187. package/src/client/persistence/ids.ts +60 -0
  188. package/src/client/persistence/merge.ts +392 -0
  189. package/src/client/store.ts +188 -0
  190. package/src/client/surface-context.ts +123 -0
  191. package/src/client/surface-control.ts +13 -0
  192. package/src/client/transport/workbookApi.ts +355 -0
  193. package/src/client/univer/SheetView.module.css +110 -0
  194. package/src/client/univer/StandaloneWorkbookPage.module.css +8 -0
  195. package/src/client/univer/StandaloneWorkbookPage.tsx +15 -0
  196. package/src/client/univer/WorkbookCanvas.tsx +128 -0
  197. package/src/client/univer/WorkbookView.module.css +30 -0
  198. package/src/client/univer/WorkbookView.tsx +3 -0
  199. package/src/client/univer/loader.ts +90 -0
  200. package/src/client/univer/react-dom-client.d.ts +10 -0
  201. package/src/client/univer/standalone-entry.tsx +19 -0
  202. package/src/client/univer/standalone.css +12 -0
  203. package/src/client/univer/univer-locales.d.ts +89 -0
  204. package/src/client/univer/univer-modules.d.ts +26 -0
  205. package/src/client/versions/VersionChrome.tsx +114 -0
  206. package/src/client/versions/inspect.ts +138 -0
  207. package/src/client/versions/preview-decoration.ts +54 -0
  208. package/src/client/versions/records.ts +78 -0
  209. package/src/client/workspace-host.ts +147 -0
  210. package/src/collaboration-hub.ts +83 -0
  211. package/src/contract/ids.ts +50 -0
  212. package/src/contract/mutations.ts +791 -0
  213. package/src/contract/operations.ts +221 -0
  214. package/src/contract/snapshots.ts +383 -0
  215. package/src/contract/univer-api-catalog.ts +289 -0
  216. package/src/css-modules.d.ts +6 -0
  217. package/src/errors.ts +25 -0
  218. package/src/http/assets-routes.ts +177 -0
  219. package/src/http/collaboration.ts +144 -0
  220. package/src/http/history.ts +151 -0
  221. package/src/http/project-files.ts +227 -0
  222. package/src/http/project-scope.ts +77 -0
  223. package/src/http/routes.ts +364 -0
  224. package/src/http/standalone.ts +32 -0
  225. package/src/http/trunk.ts +322 -0
  226. package/src/http/worktree.ts +119 -0
  227. package/src/index.ts +165 -0
  228. package/src/invariant.ts +17 -0
  229. package/src/request-params.ts +92 -0
  230. package/src/store/paths.ts +165 -0
  231. package/src/store/project.ts +137 -0
  232. package/src/store/read.ts +454 -0
  233. package/src/store/retention.ts +106 -0
  234. package/src/store/write.ts +230 -0
  235. package/src/tools/arguments.ts +128 -0
  236. package/src/tools/cells.ts +298 -0
  237. package/src/tools/index.ts +274 -0
  238. package/src/tools/render.ts +301 -0
  239. package/src/tools/univer-api.ts +243 -0
  240. package/src/tools/workbook-catalog.ts +94 -0
  241. package/src/tools/workbook-edit.ts +987 -0
  242. package/src/tools/workbook-find.ts +80 -0
  243. package/src/tools/workbook-history.ts +63 -0
  244. package/src/tools/workbook-read.ts +210 -0
  245. package/src/types.ts +432 -0
  246. package/src/univer/apply-operation.ts +369 -0
  247. package/src/univer/chunk.ts +77 -0
  248. package/src/univer/decoration.ts +111 -0
  249. package/src/univer/diagnostics.ts +136 -0
  250. package/src/univer/engine.ts +370 -0
  251. package/src/univer/entry.ts +14 -0
  252. package/src/univer/facade.ts +91 -0
  253. package/src/univer/fonts.ts +148 -0
  254. package/src/univer/overrides.css +33 -0
  255. package/src/univer/plugins/collaboration.ts +47 -0
  256. package/src/univer/plugins/export.ts +236 -0
  257. package/src/univer/plugins/history.ts +49 -0
  258. package/src/univer/plugins/version.ts +13 -0
  259. package/src/version/diff.ts +169 -0
  260. package/src/version/grouping.ts +96 -0
  261. package/src/version/records.ts +113 -0
  262. package/src/version/session.ts +90 -0
  263. package/src/version/summary.ts +117 -0
  264. package/src/workbook-manager.ts +1111 -0
  265. package/src/xlsx-export-worker.ts +34 -0
  266. package/src/xlsx-export.ts +373 -0
  267. package/src/xlsx-import-worker.ts +30 -0
@@ -0,0 +1,11 @@
1
+ /**
2
+ * `workbook_find`: locate a value across sheets, cells or formulas
3
+ * (docs/issue/0022 P3b).
4
+ */
5
+ import type { WorkbookRange } from '../types.ts';
6
+ import { type ToolArguments } from './arguments.ts';
7
+ export declare function parseFindScope(value: unknown): 'sheets' | 'cells' | 'formulas';
8
+ export declare function parseFindMatch(value: unknown): 'contains' | 'exact' | 'regex';
9
+ export declare function textMatcher(query: string, match: 'contains' | 'exact' | 'regex'): (value: unknown) => boolean;
10
+ export declare function inRange(row: number, column: number, range: WorkbookRange | undefined): boolean;
11
+ export declare function findWorkbookContent(workbookId: string, args: ToolArguments): Promise<unknown>;
@@ -0,0 +1,89 @@
1
+ import { readWorkbook } from "../workbook-manager.js";
2
+ import { parseRange } from "../request-params.js";
3
+ import { asToolArguments, parseCount, parseNonEmptyString, sheetRefFromArguments } from "./arguments.js";
4
+ export function parseFindScope(value) {
5
+ if (value === undefined || value === null)
6
+ return 'cells';
7
+ if (value === 'sheets' || value === 'cells' || value === 'formulas')
8
+ return value;
9
+ throw new Error('scope 必须是 sheets、cells 或 formulas');
10
+ }
11
+ export function parseFindMatch(value) {
12
+ if (value === undefined || value === null)
13
+ return 'contains';
14
+ if (value === 'contains' || value === 'exact' || value === 'regex')
15
+ return value;
16
+ throw new Error('match 必须是 contains、exact 或 regex');
17
+ }
18
+ export function textMatcher(query, match) {
19
+ if (match === 'regex') {
20
+ let expression;
21
+ try {
22
+ expression = new RegExp(query, 'i');
23
+ }
24
+ catch {
25
+ throw new Error('query 不是有效的正则表达式');
26
+ }
27
+ return value => expression.test(String(value ?? ''));
28
+ }
29
+ const needle = query.toLocaleLowerCase();
30
+ return value => {
31
+ const text = String(value ?? '').toLocaleLowerCase();
32
+ return match === 'exact' ? text === needle : text.includes(needle);
33
+ };
34
+ }
35
+ export function inRange(row, column, range) {
36
+ return range === undefined || row >= range.startRow && row <= range.endRow && column >= range.startColumn && column <= range.endColumn;
37
+ }
38
+ export async function findWorkbookContent(workbookId, args) {
39
+ const meta = await readWorkbook(workbookId);
40
+ if (meta === null)
41
+ throw new Error('工作簿不存在:' + workbookId);
42
+ const query = parseNonEmptyString(args.query, 'query');
43
+ const scope = parseFindScope(args.scope);
44
+ const match = parseFindMatch(args.match);
45
+ const matches = textMatcher(query, match);
46
+ const limit = args.limit === undefined ? 100 : Math.min(500, parseCount(args.limit));
47
+ const selectedSheet = sheetRefFromArguments(args, 'sheet');
48
+ const range = args.range === undefined ? undefined : parseRange(args.range);
49
+ const root = asToolArguments(meta.snapshot, 'workbook snapshot');
50
+ const sheets = asToolArguments(root.sheets, 'workbook snapshot.sheets');
51
+ const results = [];
52
+ for (const [sheetId, sheet] of Object.entries(sheets)) {
53
+ const sheetName = typeof sheet.name === 'string' ? sheet.name : sheetId;
54
+ if (selectedSheet !== undefined && selectedSheet !== sheetId && selectedSheet !== sheetName)
55
+ continue;
56
+ if (scope === 'sheets') {
57
+ if (matches(sheetName))
58
+ results.push({ sheetId, sheetName });
59
+ if (results.length >= limit)
60
+ break;
61
+ continue;
62
+ }
63
+ const cellData = sheet.cellData;
64
+ if (typeof cellData !== 'object' || cellData === null || Array.isArray(cellData))
65
+ continue;
66
+ for (const [rowKey, line] of Object.entries(cellData)) {
67
+ const row = Number(rowKey);
68
+ if (!Number.isInteger(row) || typeof line !== 'object' || line === null || Array.isArray(line))
69
+ continue;
70
+ for (const [columnKey, rawCell] of Object.entries(line)) {
71
+ const column = Number(columnKey);
72
+ if (!Number.isInteger(column) || !inRange(row, column, range))
73
+ continue;
74
+ const cell = typeof rawCell === 'object' && rawCell !== null && !Array.isArray(rawCell) ? rawCell : {};
75
+ const candidate = scope === 'formulas' ? cell.f : cell.v;
76
+ if (!matches(candidate))
77
+ continue;
78
+ results.push({ sheetId, sheetName, row, column, value: cell.v ?? null, formula: typeof cell.f === 'string' ? cell.f : null });
79
+ if (results.length >= limit)
80
+ break;
81
+ }
82
+ if (results.length >= limit)
83
+ break;
84
+ }
85
+ if (results.length >= limit)
86
+ break;
87
+ }
88
+ return { ok: true, workbookId, revision: meta.revision ?? 0, query, scope, match, results, truncated: results.length >= limit };
89
+ }
@@ -0,0 +1,2 @@
1
+ import { type ToolArguments } from './arguments.ts';
2
+ export declare function executeHistoryQuery(workbookId: string, args: ToolArguments): Promise<unknown>;
@@ -0,0 +1,59 @@
1
+ import { readWorkbook, readWorkbookAtRevision, readWorkbookAtStep } from "../workbook-manager.js";
2
+ import { diffWorkbookSnapshots } from "../version/diff.js";
3
+ import { historyVersionsFromOperations } from "../version/grouping.js";
4
+ import { activeHistoryRevisions, canReplayHistoryRevision, checkpointHasher, toVersionRecords } from "../version/records.js";
5
+ import { parseIndex } from "../request-params.js";
6
+ import { parseCount } from "./arguments.js";
7
+ export async function executeHistoryQuery(workbookId, args) {
8
+ const action = args.action === undefined || args.action === null ? 'list' : args.action;
9
+ if (action !== 'list' && action !== 'diff' && action !== 'replay')
10
+ throw new Error('action 必须是 list、diff 或 replay');
11
+ if (action === 'diff') {
12
+ const fromRevision = parseIndex(args.fromRevision, 'fromRevision');
13
+ const toRevision = parseIndex(args.toRevision, 'toRevision');
14
+ if (fromRevision > toRevision)
15
+ throw new Error('fromRevision 不得大于 toRevision');
16
+ const left = await readWorkbookAtRevision(workbookId, fromRevision);
17
+ const right = await readWorkbookAtRevision(workbookId, toRevision);
18
+ if (left === null || right === null)
19
+ throw new Error('指定 revision 已被压缩或无法重放');
20
+ return { ok: true, action, workbookId, fromRevision, toRevision, changes: diffWorkbookSnapshots(left.snapshot, right.snapshot) };
21
+ }
22
+ if (action === 'replay') {
23
+ const rawRevision = args.revision ?? args.toRevision;
24
+ const revision = parseIndex(rawRevision, 'revision');
25
+ if (args.step !== undefined && args.step !== null) {
26
+ const step = parseIndex(args.step, 'step');
27
+ const replay = await readWorkbookAtStep(workbookId, revision, step);
28
+ if (replay === null)
29
+ throw new Error('指定 revision/step 已被压缩或无法重放');
30
+ return { ok: true, action, workbookId, ...replay };
31
+ }
32
+ const replay = await readWorkbookAtRevision(workbookId, revision);
33
+ if (replay === null)
34
+ throw new Error('指定 revision 已被压缩或无法重放');
35
+ return { ok: true, action, workbookId, ...replay };
36
+ }
37
+ const meta = await readWorkbook(workbookId, { includeCheckpoints: true });
38
+ if (meta === null)
39
+ throw new Error('工作簿不存在:' + workbookId);
40
+ const limit = args.limit === undefined ? 20 : Math.min(100, Math.max(1, parseCount(args.limit)));
41
+ const allOperations = (meta.operations ?? []).slice().sort((left, right) => left.revision - right.revision);
42
+ const currentRevision = meta.revision ?? 0;
43
+ const byRevision = new Map(allOperations.map(operation => [operation.revision, operation]));
44
+ const active = activeHistoryRevisions(currentRevision, byRevision);
45
+ const checkpoints = (meta.checkpoints ?? []).map(checkpoint => checkpoint.revision).sort((left, right) => left - right);
46
+ const canReplay = (revision) => canReplayHistoryRevision(revision, currentRevision, checkpoints, byRevision);
47
+ const fullVersions = historyVersionsFromOperations(allOperations, canReplay, active).slice(-limit);
48
+ const versions = fullVersions.map(({ steps: _steps, ...version }) => version);
49
+ return {
50
+ ok: true,
51
+ action,
52
+ workbookId,
53
+ revision: currentRevision,
54
+ versions,
55
+ // Unified cross-plugin model (PRD §7.1). `versions` stays for compatibility.
56
+ versionRecords: toVersionRecords(fullVersions, workbookId, checkpointHasher(meta.checkpoints ?? [])),
57
+ checkpoints,
58
+ };
59
+ }
@@ -0,0 +1,21 @@
1
+ /**
2
+ * `workbook_read`: one bounded look at a sheet, a range or a single cell
3
+ * (docs/issue/0022 P3b).
4
+ */
5
+ import type { WorkbookRange } from '../types.ts';
6
+ export declare function parseReadIncludes(value: unknown): Set<string>;
7
+ export declare function snapshotSheet(snapshot: unknown, sheetRef: string): Record<string, unknown>;
8
+ export declare function snapshotCell(snapshot: unknown, sheetRef: string, row: number, column: number): Record<string, unknown> | undefined;
9
+ export declare function styleMatrix(snapshot: unknown, sheetRef: string, range: WorkbookRange): unknown[][];
10
+ /**
11
+ * Per-sheet backfill status for `workbook_read(kind: 'workbook')`
12
+ * (docs/issue/0011 I5 / T7).
13
+ *
14
+ * The agent kept a prose table of "which sheet still needs what" because the
15
+ * read surface could only show scale. This reports the four things that table
16
+ * tracked — data area, run provenance, run time and a conclusion block — so a
17
+ * workbook's completeness is visible without opening every sheet. `complete` is
18
+ * deliberately conservative: it is a hint, not a gate.
19
+ */
20
+ export declare function sheetBackfillStatus(sheet: Record<string, unknown>): Record<string, unknown>;
21
+ export declare function readWorkbookTarget(workbookId: string, rawTarget: unknown, rawInclude: unknown): Promise<unknown>;
@@ -0,0 +1,204 @@
1
+ import { readWorkbook, readWorkbookRange, summarize } from "../workbook-manager.js";
2
+ import { parseIndex, parseRange } from "../request-params.js";
3
+ import { asToolArguments, sheetRefForSnapshot } from "./arguments.js";
4
+ import { sheetOverviews } from "./render.js";
5
+ export function parseReadIncludes(value) {
6
+ if (value === undefined || value === null)
7
+ return new Set();
8
+ if (!Array.isArray(value))
9
+ throw new Error('include 必须是字符串数组');
10
+ const allowed = new Set(['values', 'formulas', 'cells', 'styles', 'snapshot', 'backfill']);
11
+ const result = new Set();
12
+ for (const item of value) {
13
+ if (typeof item !== 'string' || !allowed.has(item))
14
+ throw new Error('include 仅支持 values、formulas、cells、styles、snapshot、backfill');
15
+ result.add(item);
16
+ }
17
+ return result;
18
+ }
19
+ export function snapshotSheet(snapshot, sheetRef) {
20
+ const root = asToolArguments(snapshot, 'workbook snapshot');
21
+ const sheets = asToolArguments(root.sheets, 'workbook snapshot.sheets');
22
+ const direct = sheets[sheetRef];
23
+ if (direct !== undefined)
24
+ return direct;
25
+ const byName = Object.values(sheets).find(sheet => sheet.name === sheetRef);
26
+ if (byName === undefined)
27
+ throw new Error('sheet 不存在:' + sheetRef);
28
+ return byName;
29
+ }
30
+ export function snapshotCell(snapshot, sheetRef, row, column) {
31
+ const sheet = snapshotSheet(snapshot, sheetRef);
32
+ const cellData = sheet.cellData;
33
+ if (typeof cellData !== 'object' || cellData === null || Array.isArray(cellData))
34
+ return undefined;
35
+ const line = cellData[String(row)];
36
+ if (typeof line !== 'object' || line === null || Array.isArray(line))
37
+ return undefined;
38
+ const cell = line[String(column)];
39
+ return typeof cell === 'object' && cell !== null && !Array.isArray(cell) ? cell : undefined;
40
+ }
41
+ export function styleMatrix(snapshot, sheetRef, range) {
42
+ const result = [];
43
+ for (let row = range.startRow; row <= range.endRow; row += 1) {
44
+ const line = [];
45
+ for (let column = range.startColumn; column <= range.endColumn; column += 1) {
46
+ line.push(snapshotCell(snapshot, sheetRef, row, column)?.s ?? null);
47
+ }
48
+ result.push(line);
49
+ }
50
+ return result;
51
+ }
52
+ /**
53
+ * Per-sheet backfill status for `workbook_read(kind: 'workbook')`
54
+ * (docs/issue/0011 I5 / T7).
55
+ *
56
+ * The agent kept a prose table of "which sheet still needs what" because the
57
+ * read surface could only show scale. This reports the four things that table
58
+ * tracked — data area, run provenance, run time and a conclusion block — so a
59
+ * workbook's completeness is visible without opening every sheet. `complete` is
60
+ * deliberately conservative: it is a hint, not a gate.
61
+ */
62
+ export function sheetBackfillStatus(sheet) {
63
+ const asRecord = (value) => typeof value === 'object' && value !== null && !Array.isArray(value) ? value : undefined;
64
+ const stats = asRecord(sheet.dataSheetStats);
65
+ const meta = asRecord(sheet.dataSheetMeta);
66
+ const schema = asRecord(sheet.dataSheetSchema);
67
+ const dataRows = typeof stats?.rowCount === 'number' && stats.rowCount >= 0 ? stats.rowCount : 0;
68
+ const cellData = asRecord(sheet.cellData) ?? {};
69
+ // A conclusion block is not tracked anywhere in the snapshot: any write
70
+ // recomputes the row counts, so the counter cannot separate data from prose.
71
+ // What it can do is spot rows that do not span the data schema, which is the
72
+ // shape a conclusion row takes in these report sheets (row 0 is the header).
73
+ const schemaColumns = Array.isArray(schema?.columns) ? schema.columns.length : 0;
74
+ let conclusionRows = 0;
75
+ for (const [key, line] of Object.entries(cellData)) {
76
+ const row = Number(key);
77
+ if (!Number.isInteger(row) || row <= 0)
78
+ continue;
79
+ const cells = asRecord(line);
80
+ if (cells === undefined)
81
+ continue;
82
+ const filled = Object.values(cells).filter(cell => {
83
+ const value = asRecord(cell)?.v;
84
+ return value !== undefined && value !== null && String(value).length > 0;
85
+ }).length;
86
+ if (filled === 0)
87
+ continue;
88
+ if (schemaColumns > 0 && filled >= schemaColumns)
89
+ continue;
90
+ conclusionRows += 1;
91
+ }
92
+ const provenance = meta === undefined
93
+ ? null
94
+ : { source: meta.source ?? null, query: meta.query ?? null, notes: meta.notes ?? null };
95
+ return {
96
+ /** Highest row index holding content. Every write recomputes it, so it
97
+ * covers a conclusion block as well as the data — it is a bound, not a
98
+ * count of data rows. */
99
+ lastOccupiedRow: typeof stats?.rowCount === 'number' && stats.rowCount >= 0 ? stats.rowCount : 0,
100
+ columnCount: typeof stats?.columnCount === 'number' ? stats.columnCount : 0,
101
+ conclusionRows,
102
+ runAt: typeof meta?.generatedAt === 'string' ? meta.generatedAt : null,
103
+ provenance,
104
+ schemaUpdatedAt: typeof schema?.updatedAt === 'string' ? schema.updatedAt : null,
105
+ complete: (typeof stats?.rowCount === 'number' ? stats.rowCount : 0) > 0 && provenance !== null,
106
+ };
107
+ }
108
+ export async function readWorkbookTarget(workbookId, rawTarget, rawInclude) {
109
+ const meta = await readWorkbook(workbookId);
110
+ if (meta === null)
111
+ throw new Error('工作簿不存在:' + workbookId);
112
+ const target = asToolArguments(rawTarget, 'target');
113
+ const kind = target.kind;
114
+ if (kind !== 'workbook' && kind !== 'sheet' && kind !== 'range' && kind !== 'cells') {
115
+ throw new Error('target.kind 必须是 workbook、sheet、range 或 cells');
116
+ }
117
+ const include = parseReadIncludes(rawInclude);
118
+ const summary = summarize(meta);
119
+ const base = { ok: true, workbookId, revision: meta.revision ?? 0 };
120
+ if (kind === 'workbook') {
121
+ const sheets = sheetOverviews(meta.snapshot);
122
+ return {
123
+ ...base,
124
+ workbook: { id: summary.id, name: summary.name, sheets, sheetCount: sheets.length, updatedAt: summary.updatedAt },
125
+ ...(include.has('snapshot') ? { snapshot: meta.snapshot } : {}),
126
+ ...(include.has('backfill')
127
+ ? {
128
+ backfill: sheets.map(overview => ({
129
+ sheetId: overview.id,
130
+ name: overview.name,
131
+ ...sheetBackfillStatus(snapshotSheet(meta.snapshot, overview.id)),
132
+ })),
133
+ }
134
+ : {}),
135
+ };
136
+ }
137
+ const sheetRef = sheetRefForSnapshot(meta.snapshot, target, 'target.sheet');
138
+ const sheet = snapshotSheet(meta.snapshot, sheetRef);
139
+ const sheetSummary = summary.sheets.find(candidate => candidate.id === sheetRef || candidate.name === sheetRef);
140
+ const resolvedSheetRef = {
141
+ workbookId,
142
+ sheetId: sheetSummary?.id ?? String(sheet.id ?? sheetRef),
143
+ sheetName: sheetSummary?.name ?? String(sheet.name ?? sheetRef),
144
+ };
145
+ if (kind === 'sheet') {
146
+ const overview = sheetOverviews(meta.snapshot).find(candidate => candidate.id === resolvedSheetRef.sheetId);
147
+ return {
148
+ ...base,
149
+ sheetRef: resolvedSheetRef,
150
+ sheet: {
151
+ id: resolvedSheetRef.sheetId,
152
+ name: resolvedSheetRef.sheetName,
153
+ rowCount: overview?.rowCount ?? sheet.rowCount ?? 0,
154
+ columnCount: overview?.columnCount ?? sheet.columnCount ?? 0,
155
+ maxRow: overview?.maxRow ?? null,
156
+ maxColumn: overview?.maxColumn ?? null,
157
+ nonEmptyCells: overview?.nonEmptyCells ?? 0,
158
+ },
159
+ ...(include.has('snapshot') ? { snapshot: sheet } : {}),
160
+ };
161
+ }
162
+ if (kind === 'range') {
163
+ const range = parseRange(target.range);
164
+ const result = readWorkbookRange(meta.snapshot, sheetRef, range);
165
+ // `readWorkbookRange` materializes values, formulas and cells together, but
166
+ // returning all three inline spent the result budget three times over
167
+ // (docs/issue/0011 I1 / T5). Only `values` is unconditional; the heavier views
168
+ // have to be asked for.
169
+ return {
170
+ ...base,
171
+ sheetRef: { ...resolvedSheetRef, range: `${range.startRow}:${range.startColumn}-${range.endRow}:${range.endColumn}` },
172
+ sheetId: result.sheetId,
173
+ sheetName: result.sheetName,
174
+ range: result.range,
175
+ values: result.values,
176
+ ...(include.has('formulas') ? { formulas: result.formulas } : {}),
177
+ ...(include.has('cells') ? { cells: result.cells } : {}),
178
+ ...(include.has('styles') ? { styles: styleMatrix(meta.snapshot, result.sheetId, range) } : {}),
179
+ };
180
+ }
181
+ if (!Array.isArray(target.cells) || target.cells.length === 0 || target.cells.length > 500) {
182
+ throw new Error('target.cells 必须是 1 到 500 项的单元格坐标数组');
183
+ }
184
+ const cells = target.cells.map((rawCell, index) => {
185
+ const coordinate = asToolArguments(rawCell, 'target.cells[' + index + ']');
186
+ const row = parseIndex(coordinate.row, 'target.cells[' + index + '].row');
187
+ const column = parseIndex(coordinate.column, 'target.cells[' + index + '].column');
188
+ const cell = snapshotCell(meta.snapshot, sheetRef, row, column);
189
+ const value = cell?.v;
190
+ return {
191
+ row,
192
+ column,
193
+ value: value === undefined ? null : value,
194
+ formula: typeof cell?.f === 'string' ? cell.f : null,
195
+ ...(include.has('styles') ? { style: cell?.s ?? null } : {}),
196
+ };
197
+ });
198
+ return {
199
+ ...base,
200
+ sheetRef: resolvedSheetRef,
201
+ sheet: { id: resolvedSheetRef.sheetId, name: resolvedSheetRef.sheetName },
202
+ cells,
203
+ };
204
+ }