@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,243 @@
1
+ /**
2
+ * `univer_api`: the safe Univer adapter registry (docs/issue/0022 P3b).
3
+ *
4
+ * `catalog` and `search` describe what may be called; `invoke` turns one adapter
5
+ * call into a normal workbook operation, so it lands in version history like any
6
+ * other edit. It is not an escape hatch to arbitrary JavaScript or a raw
7
+ * Injector: the catalogue is the whole surface.
8
+ */
9
+ import {
10
+ type SheetColumnType,
11
+ type WorkbookOperationPayload,
12
+ } from '../types.ts'
13
+ import type { LineageContext } from '#contracts'
14
+
15
+ import { findUniverApi } from '../contract/univer-api-catalog.ts'
16
+ import { mutateWorkbook, readWorkbook, readWorkbookRange, summarize } from '../workbook-manager.ts'
17
+ import { normalizeValueMatrix, parseIndex, parseRange } from '../request-params.ts'
18
+ import {
19
+ parseCellDeleteShift,
20
+ parseCount,
21
+ parseNonEmptyString,
22
+ sheetRefFromArguments,
23
+ sheetRefForSnapshot,
24
+ } from './arguments.ts'
25
+ import {
26
+ dimensionRange,
27
+ parseApiValues,
28
+ parseFiniteNumber,
29
+ parseFreeze,
30
+ parseHyperlink,
31
+ parseHyperlinkLabel,
32
+ parseSort,
33
+ parseValueRange,
34
+ } from './cells.ts'
35
+
36
+
37
+ /** Sheet column types a modelled table may declare. */
38
+ const COLUMN_TYPES: readonly SheetColumnType[] = ['string', 'number', 'boolean', 'date', 'currency']
39
+
40
+ /** Sheet column types a modelled table may declare. */
41
+ export function parseUniverApiAction(value: unknown): 'catalog' | 'search' | 'invoke' {
42
+ if (value === 'catalog' || value === 'search' || value === 'invoke') return value
43
+ throw new Error('action 必须是 catalog、search 或 invoke')
44
+ }
45
+
46
+
47
+
48
+
49
+
50
+ export type ApiArguments = Record<string, unknown>
51
+
52
+ export function asApiArguments(value: unknown): ApiArguments {
53
+ if (value === undefined || value === null) return {}
54
+ if (typeof value !== 'object' || Array.isArray(value)) throw new Error('arguments 必须是对象')
55
+ return value as ApiArguments
56
+ }
57
+
58
+ /** Execute one cataloged Facade method through the durable DSH adapter. */
59
+ export async function executeUniverApi(args: {
60
+ workbookId: string
61
+ api: string
62
+ arguments: ApiArguments
63
+ expectedRevision?: number
64
+ opId?: string
65
+ lineage?: LineageContext
66
+ }): Promise<unknown> {
67
+ const definition = findUniverApi(args.api)
68
+ if (definition === undefined) throw new Error(`未知 Univer API:${args.api};请先调用 univer_api(action=catalog)`)
69
+ if (definition.availability !== 'implemented') {
70
+ throw new Error(`${args.api} 仅作为浏览器 Facade 元数据提供;持久化 workbook 请使用 workbook_edit 或已注册的 Adapter`)
71
+ }
72
+ const meta = await readWorkbook(args.workbookId)
73
+ if (meta === null) throw new Error(`工作簿不存在:${args.workbookId}`)
74
+ const input = args.arguments
75
+
76
+ if (definition.mode === 'read') {
77
+ switch (args.api) {
78
+ case 'workbook.getSnapshot':
79
+ return { ok: true, workbookId: args.workbookId, revision: meta.revision ?? 0, snapshot: meta.snapshot }
80
+ case 'workbook.getWorksheets': {
81
+ const sheets = summarize(meta).sheets
82
+ return { ok: true, workbookId: args.workbookId, revision: meta.revision ?? 0, sheets, worksheets: sheets, sheetCount: sheets.length }
83
+ }
84
+ case 'worksheet.getRangeValues': {
85
+ const range = parseRange(input.range)
86
+ const sheet = sheetRefForSnapshot(meta.snapshot, input, 'arguments.sheet')
87
+ return { ok: true, workbookId: args.workbookId, revision: meta.revision ?? 0, ...readWorkbookRange(meta.snapshot, sheet, range) }
88
+ }
89
+ default:
90
+ throw new Error(`读取 API 尚未实现:${args.api}`)
91
+ }
92
+ }
93
+
94
+ let type = definition.operation
95
+ let payload: WorkbookOperationPayload
96
+ const sheet = args.api === 'workbook.createSheet'
97
+ ? sheetRefFromArguments(input, 'arguments.sheet')
98
+ : sheetRefForSnapshot(meta.snapshot, input, 'arguments.sheet')
99
+ switch (args.api) {
100
+ case 'worksheet.setValues': {
101
+ const matrix = input.values ?? input.data ?? input.matrix
102
+ const valueMatrix = normalizeValueMatrix(matrix)
103
+ const range = parseValueRange(input.range, valueMatrix, 'arguments')
104
+ payload = { sheetId: sheet, cells: parseApiValues(valueMatrix, range) }
105
+ break
106
+ }
107
+ case 'worksheet.clearContent':
108
+ payload = { sheetId: sheet, range: parseRange(input.range) }
109
+ break
110
+ case 'worksheet.setBackgroundColor':
111
+ payload = { sheetId: sheet, range: parseRange(input.range), style: { bg: parseColor(input.color, 'color') } }
112
+ break
113
+ case 'worksheet.setFontColor':
114
+ payload = { sheetId: sheet, range: parseRange(input.range), style: { cl: parseColor(input.color, 'color') } }
115
+ break
116
+ case 'worksheet.setFontFamily':
117
+ payload = { sheetId: sheet, range: parseRange(input.range), style: { ff: parseNonEmptyString(input.family, 'family') } }
118
+ break
119
+ case 'worksheet.setFontSize': {
120
+ const size = parseFiniteNumber(input.size, 'size')
121
+ if (size <= 0) throw new Error('size 必须大于 0')
122
+ payload = { sheetId: sheet, range: parseRange(input.range), style: { fs: size } }
123
+ break
124
+ }
125
+ case 'worksheet.setFontWeight':
126
+ payload = { sheetId: sheet, range: parseRange(input.range), style: { bl: parseBoolean(input.bold, 'bold') } }
127
+ break
128
+ case 'worksheet.setFontStyle':
129
+ payload = { sheetId: sheet, range: parseRange(input.range), style: { it: parseBoolean(input.italic, 'italic') } }
130
+ break
131
+ case 'worksheet.setHorizontalAlignment':
132
+ payload = { sheetId: sheet, range: parseRange(input.range), style: { ht: parseHorizontalAlignment(input.alignment) } }
133
+ break
134
+ case 'worksheet.setVerticalAlignment':
135
+ payload = { sheetId: sheet, range: parseRange(input.range), style: { vt: parseVerticalAlignment(input.alignment) } }
136
+ break
137
+ case 'worksheet.merge':
138
+ payload = { sheetId: sheet, range: parseRange(input.range) }
139
+ break
140
+ case 'worksheet.breakApart':
141
+ payload = { sheetId: sheet, range: parseRange(input.range) }
142
+ break
143
+ case 'worksheet.deleteCells':
144
+ payload = { sheetId: sheet, range: parseRange(input.range), shift: parseCellDeleteShift(input.shift) }
145
+ break
146
+ case 'worksheet.insertRows':
147
+ payload = { sheetId: sheet, range: dimensionRange(parseIndex(input.index, 'index'), 'row'), count: input.count === undefined ? 1 : parseCount(input.count) }
148
+ break
149
+ case 'worksheet.deleteRows':
150
+ payload = { sheetId: sheet, range: dimensionRange(parseIndex(input.index, 'index'), 'row'), count: input.count === undefined ? 1 : parseCount(input.count) }
151
+ break
152
+ case 'worksheet.insertColumns':
153
+ payload = { sheetId: sheet, range: dimensionRange(parseIndex(input.index, 'index'), 'column'), count: input.count === undefined ? 1 : parseCount(input.count) }
154
+ break
155
+ case 'worksheet.deleteColumns':
156
+ payload = { sheetId: sheet, range: dimensionRange(parseIndex(input.index, 'index'), 'column'), count: input.count === undefined ? 1 : parseCount(input.count) }
157
+ break
158
+ case 'worksheet.setTextRotation':
159
+ payload = { sheetId: sheet, range: parseRange(input.range), style: { tr: parseFiniteNumber(input.rotation, 'rotation') } }
160
+ break
161
+ case 'worksheet.setNumberFormat':
162
+ payload = { sheetId: sheet, range: parseRange(input.range), style: { n: parseNonEmptyString(input.format, 'format') } }
163
+ break
164
+ case 'worksheet.setName':
165
+ payload = { sheetId: sheet, name: parseNonEmptyString(input.name, 'name') }
166
+ break
167
+ case 'workbook.createSheet':
168
+ payload = { sheetId: sheet, name: parseNonEmptyString(input.name, 'name') }
169
+ break
170
+ case 'workbook.deleteSheet':
171
+ payload = { sheetId: sheet }
172
+ break
173
+ case 'worksheet.sort':
174
+ payload = { sheetId: sheet, range: parseRange(input.range), sort: parseSort({ column: input.column, direction: input.direction }) }
175
+ break
176
+ case 'worksheet.setColumnWidth':
177
+ payload = { sheetId: sheet, range: dimensionRange(parseIndex(input.index, 'index'), 'column'), size: parseFiniteNumber(input.size, 'size') }
178
+ break
179
+ case 'worksheet.setRowHeight':
180
+ payload = { sheetId: sheet, range: dimensionRange(parseIndex(input.index, 'index'), 'row'), size: parseFiniteNumber(input.size, 'size') }
181
+ break
182
+ case 'worksheet.setHyperLink':
183
+ payload = { sheetId: sheet, range: parseRange(input.range), url: parseHyperlink(input.url), label: input.label === undefined ? undefined : parseHyperlinkLabel(input.label) }
184
+ break
185
+ case 'worksheet.cancelHyperLink':
186
+ payload = { sheetId: sheet, range: parseRange(input.range) }
187
+ break
188
+ case 'worksheet.setFreeze':
189
+ payload = { sheetId: sheet, freeze: parseFreeze({ rows: input.rows, columns: input.columns }) }
190
+ break
191
+ default:
192
+ type = undefined
193
+ throw new Error(`写入 API 尚未实现:${args.api}`)
194
+ }
195
+ if (type === undefined) throw new Error(`API ${args.api} 没有持久化 operation 映射`)
196
+ const result = await mutateWorkbook({
197
+ workbookId: args.workbookId,
198
+ actor: 'agent',
199
+ type,
200
+ payload,
201
+ expectedRevision: args.expectedRevision,
202
+ opId: args.opId,
203
+ versionKind: 'named',
204
+ lineage: args.lineage,
205
+ })
206
+ return {
207
+ ok: true,
208
+ workbookId: args.workbookId,
209
+ revision: result.meta.revision ?? 0,
210
+ operation: result.operation,
211
+ ...(args.lineage === undefined ? {} : { lineage: args.lineage }),
212
+ ...(result.rebasedOperations === undefined ? {} : { rebasedOperations: result.rebasedOperations }),
213
+ }
214
+ }
215
+
216
+
217
+
218
+ export function parseBoolean(value: unknown, label: string): boolean {
219
+ if (typeof value !== 'boolean') throw new Error(`${label} 必须是 boolean`)
220
+ return value
221
+ }
222
+
223
+ export function parseColor(value: unknown, label: string): string {
224
+ return parseNonEmptyString(value, label)
225
+ }
226
+
227
+ export function parseHorizontalAlignment(value: unknown): number {
228
+ if (value === 'left') return 1
229
+ if (value === 'center') return 2
230
+ if (value === 'normal') return 0
231
+ throw new Error('alignment 必须是 left、center 或 normal')
232
+ }
233
+
234
+ export function parseVerticalAlignment(value: unknown): number {
235
+ if (value === 'top') return 1
236
+ if (value === 'middle') return 2
237
+ if (value === 'bottom') return 0
238
+ throw new Error('alignment 必须是 top、middle 或 bottom')
239
+ }
240
+
241
+
242
+
243
+
@@ -0,0 +1,94 @@
1
+ /**
2
+ * `workbook_catalog`: the directory and lifecycle of workbooks (docs/issue/0022 P3b).
3
+ *
4
+ * Creation also names the file. A workbook's id *is* its file name under
5
+ * `<project>/storages/data-table/`, so the naming rule lives at this one entry
6
+ * point: `yyyymmdd-中文名含义` (see `storageNameOf`). Before it, a Chinese display
7
+ * name was slugged by an ASCII-only rule and became `_wb` — a directory nobody
8
+ * could read.
9
+ */
10
+ import {
11
+ blankSnapshot,
12
+ deleteWorkbook,
13
+ listWorkbookSummaries,
14
+ readWorkbook,
15
+ renameWorkbook,
16
+ summarize,
17
+ workbookExists,
18
+ writeWorkbook,
19
+ } from '../workbook-manager.ts'
20
+ import { storageNameOf } from '#contracts'
21
+ import { normalizeWorkbookId } from '../contract/ids.ts'
22
+ import { now, parseNonEmptyString, workbookIdOf, type ToolArguments } from './arguments.ts'
23
+ import type { WorkbookCatalogResponse } from '#contracts'
24
+
25
+ export function parseCatalogAction(value: unknown): 'list' | 'create' | 'rename' | 'delete' {
26
+ if (value === 'list' || value === 'create' || value === 'rename' || value === 'delete') return value
27
+ throw new Error('action 必须是 list、create、rename 或 delete')
28
+ }
29
+
30
+ export async function executeWorkbookCatalog(args: ToolArguments): Promise<unknown> {
31
+ const action = parseCatalogAction(args.action)
32
+ if (action === 'list') {
33
+ const summaries = await listWorkbookSummaries()
34
+ // 响应按 wire 契约标注,字段变化会在编译期被发现。
35
+ const response: WorkbookCatalogResponse = {
36
+ ok: true,
37
+ workbooks: summaries.map(summary => ({
38
+ id: summary.id,
39
+ name: summary.name,
40
+ revision: summary.revision ?? 0,
41
+ sheets: summary.sheets,
42
+ sheetCount: summary.sheets.length,
43
+ updatedAt: summary.updatedAt,
44
+ })),
45
+ }
46
+ return response
47
+ }
48
+
49
+ if (action === 'create') {
50
+ const name = parseNonEmptyString(args.name, 'name')
51
+ const requestedId = typeof args.workbookId === 'string' && args.workbookId.trim().length > 0 ? args.workbookId : undefined
52
+ if (args.workbookId !== undefined && requestedId === undefined) {
53
+ throw new Error('workbookId 必须是非空字符串')
54
+ }
55
+ // Both halves of the name rule meet here:
56
+ //
57
+ // · no id given — the display name *becomes* the file name's meaning, so the
58
+ // directory says what each workbook is: `20261002-销售汇总.json`;
59
+ // · an id given — it is the caller's own name for this workbook, and it is
60
+ // used as written (character set aside). It is deliberately **not**
61
+ // re-dated: a workbook named `20261001-销售汇总` yesterday must still be
62
+ // addressable by the id its creator used, today.
63
+ const baseId = requestedId === undefined
64
+ ? storageNameOf(name, { fallback: '未命名工作簿' })
65
+ : normalizeWorkbookId(requestedId)
66
+ let workbookId = baseId
67
+ if (requestedId !== undefined && await workbookExists(workbookId)) {
68
+ throw new Error('工作簿 id 已存在:' + workbookId)
69
+ }
70
+ for (let suffix = 2; requestedId === undefined && await workbookExists(workbookId); suffix += 1) {
71
+ workbookId = baseId + '-' + suffix
72
+ }
73
+ await writeWorkbook({
74
+ id: workbookId,
75
+ name,
76
+ sheetOrder: ['sheet1'],
77
+ updatedAt: now(),
78
+ revision: 0,
79
+ operations: [],
80
+ snapshot: blankSnapshot(name),
81
+ } as never)
82
+ return { ok: true, action, workbook: { id: workbookId, name, sheets: summarize((await readWorkbook(workbookId)) as never).sheets, revision: 0 } }
83
+ }
84
+
85
+ const workbookId = workbookIdOf(args.workbookId)
86
+ if (action === 'rename') {
87
+ const meta = await renameWorkbook(workbookId, parseNonEmptyString(args.name, 'name'))
88
+ return { ok: true, action, workbook: { id: meta.id, name: meta.name, sheets: summarize(meta).sheets, revision: meta.revision ?? 0 } }
89
+ }
90
+ if (args.confirm !== true) throw new Error('删除工作簿必须显式传 confirm: true')
91
+ if (!await workbookExists(workbookId)) throw new Error('工作簿不存在:' + workbookId)
92
+ await deleteWorkbook(workbookId)
93
+ return { ok: true, action, workbookId }
94
+ }