docz-cli 0.8.1 → 0.9.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 CHANGED
@@ -79,6 +79,7 @@ export DOCSYNC_API_TOKEN=<your-token>
79
79
  | `ls <space>[:<path>]` | List files and folders |
80
80
  | `cat <space>:<path>` | Read file content |
81
81
  | `upload <file> <space>[:<dir>]` | Upload local file |
82
+ | `image upload <file>` | Upload image to OSS, get permanent public URL for Markdown |
82
83
  | `write <space>:<path> <content>` | Write content to file (`-` for stdin) |
83
84
  | `mkdir <space>:<path>` | Create folder |
84
85
  | `rm <space>:<path>` | Delete file/folder (30-day trash) |
@@ -141,6 +142,16 @@ docz-cli upload ./report.pdf G160-研发:reports # Uploa
141
142
  docz-cli mkdir G160-研发:new-project # Create folder
142
143
  ```
143
144
 
145
+ ### Images
146
+
147
+ Upload images to OSS for embedding in Markdown documents. Returns a permanent public URL — visible in share links and blogs without login, and doesn't consume Space quota. Supports png/jpg/webp, max 5MB.
148
+
149
+ ```bash
150
+ docz-cli image upload ./screenshot.png
151
+ # URL: https://<bucket>.oss-cn-beijing.aliyuncs.com/docz-markdown/2026/06/.../image.png
152
+ # Markdown: ![screenshot](https://...)
153
+ ```
154
+
144
155
  ### Manage
145
156
 
146
157
  ```bash
@@ -254,6 +265,7 @@ Add to your MCP settings:
254
265
  | `docz_list_files` | List files in a directory |
255
266
  | `docz_read_file` | Read file content |
256
267
  | `docz_upload_file` | Upload/create a file |
268
+ | `docz_upload_image` | Upload image to OSS, returns public URL for Markdown |
257
269
  | `docz_mkdir` | Create a folder |
258
270
  | `docz_delete` | Delete file/folder |
259
271
  | `docz_file_history` | View change history |
@@ -285,6 +297,7 @@ docz-cli wraps the DocSync REST API:
285
297
  | `ls` | `GET /api/spaces/{id}/tree?path=` |
286
298
  | `cat` | `GET /api/spaces/{id}/blob/{path}` |
287
299
  | `upload` / `write` | `POST /api/spaces/{id}/files/upload` or `POST /api/spaces/{id}/files/save` |
300
+ | `image upload` | `POST /api/assets/images` |
288
301
  | `mkdir` | `POST /api/spaces/{id}/files/mkdir` |
289
302
  | `rm` | `POST /api/spaces/{id}/files/delete` |
290
303
  | `mv` | `POST /api/spaces/{id}/files/rename` |
@@ -32,6 +32,20 @@ var DocSyncClient = class {
32
32
  if (ct.includes("application/json")) return res.json();
33
33
  return res.text();
34
34
  }
35
+ async requestText(path, init) {
36
+ const res = await fetch(`${this.baseUrl}${path}`, {
37
+ ...init,
38
+ headers: {
39
+ Authorization: `Bearer ${this.token}`,
40
+ ...init?.headers
41
+ }
42
+ });
43
+ if (!res.ok) {
44
+ const body = await res.text().catch(() => "");
45
+ throw new Error(`${res.status} ${res.statusText}: ${body}`.trim());
46
+ }
47
+ return res.text();
48
+ }
35
49
  // --- Auth ---
36
50
  async me() {
37
51
  return this.request("/api/auth/me");
@@ -73,7 +87,7 @@ var DocSyncClient = class {
73
87
  }
74
88
  // --- Blob ---
75
89
  async cat(spaceId, filepath) {
76
- return this.request(
90
+ return this.requestText(
77
91
  `/api/spaces/${spaceId}/blob/${encodeURIComponent(filepath)}`
78
92
  );
79
93
  }
@@ -101,6 +115,20 @@ var DocSyncClient = class {
101
115
  body: form
102
116
  });
103
117
  }
118
+ /**
119
+ * Upload an image to the server's OSS asset storage.
120
+ * Returns a permanent public URL that can be embedded in Markdown.
121
+ * Server limits: png/jpg/webp only, max 5MB.
122
+ */
123
+ async uploadImage(content, filename) {
124
+ const blob = new Blob([content], { type: "application/octet-stream" });
125
+ const form = new FormData();
126
+ form.append("file", blob, filename);
127
+ return this.request("/api/assets/images", {
128
+ method: "POST",
129
+ body: form
130
+ });
131
+ }
104
132
  async save(spaceId, path, content, opts) {
105
133
  const body = { path, content };
106
134
  if (opts?.baseRef) body.base_ref = opts.baseRef;
@@ -251,7 +279,7 @@ var DocSyncClient = class {
251
279
  });
252
280
  }
253
281
  async getSharedFile(token) {
254
- return this.request(`/api/share/${token}`);
282
+ return this.requestText(`/api/share/${token}`);
255
283
  }
256
284
  async getSharedFileInfo(token) {
257
285
  return this.request(`/api/share/${token}/info`);
@@ -317,7 +345,7 @@ function getConfigPath() {
317
345
  }
318
346
 
319
347
  // src/commands.ts
320
- import { readFileSync as readFileSync2 } from "fs";
348
+ import { existsSync as existsSync2, readFileSync as readFileSync2, statSync } from "fs";
321
349
  import { basename } from "path";
322
350
  function getClient() {
323
351
  const token = getToken();
@@ -435,6 +463,31 @@ async function readStdin() {
435
463
  return Buffer.concat(chunks).toString("utf-8");
436
464
  }
437
465
  var MAX_SAVE_SIZE = 2 * 1024 * 1024;
466
+ var IMAGE_EXTS = ["png", "jpg", "jpeg", "webp"];
467
+ var IMAGE_MAX_SIZE = 5 * 1024 * 1024;
468
+ function readImageFile(filePath) {
469
+ if (!existsSync2(filePath)) {
470
+ return { error: `File not found: ${filePath}` };
471
+ }
472
+ const filename = basename(filePath);
473
+ const ext = filename.split(".").pop()?.toLowerCase() ?? "";
474
+ if (!IMAGE_EXTS.includes(ext)) {
475
+ return {
476
+ error: `Unsupported image type ".${ext}". Supported: ${IMAGE_EXTS.join(", ")}`
477
+ };
478
+ }
479
+ const size = statSync(filePath).size;
480
+ if (size > IMAGE_MAX_SIZE) {
481
+ return {
482
+ error: `Image too large (${formatSize(size)}). Max size: 5 MB`
483
+ };
484
+ }
485
+ return { content: readFileSync2(filePath), filename };
486
+ }
487
+ function markdownImageRef(filename, url) {
488
+ const alt = filename.replace(/\.[^.]+$/, "");
489
+ return `![${alt}](${url})`;
490
+ }
438
491
  function registerCommands(program) {
439
492
  program.command("login").description("Configure DocSync credentials").option("-u, --url <url>", "DocSync server URL").option("-t, --token <token>", "API token").action(async (opts) => {
440
493
  const url = opts.url ?? getBaseUrl();
@@ -518,6 +571,20 @@ function registerCommands(program) {
518
571
  const result = await client.upload(spaceId, targetDir, filename, content);
519
572
  console.log(`Uploaded: ${result.path}`);
520
573
  });
574
+ const image = program.command("image").description("Image asset operations");
575
+ image.command("upload").description(
576
+ "Upload image to OSS, returns a permanent public URL for Markdown embedding"
577
+ ).argument("<file>", "Local image file (png/jpg/webp, max 5MB)").action(async (file) => {
578
+ const read = readImageFile(file);
579
+ if ("error" in read) {
580
+ console.error(`Error: ${read.error}`);
581
+ process.exit(1);
582
+ }
583
+ const client = getClient();
584
+ const result = await client.uploadImage(read.content, read.filename);
585
+ console.log(`URL: ${result.url}`);
586
+ console.log(`Markdown: ${markdownImageRef(read.filename, result.url)}`);
587
+ });
521
588
  program.command("write").description(
522
589
  "Write content to file \u2014 docz write <space>:<path> <content> or <url> <content>"
523
590
  ).argument("<target>", "space:dir/filename.md or short URL").argument("<content>", "File content (or - for stdin)").option("--force", "Skip conflict detection").option("-m, --message <msg>", "Custom commit message").action(
@@ -851,6 +918,8 @@ export {
851
918
  getBaseUrl,
852
919
  getToken,
853
920
  parseExpires,
921
+ readImageFile,
922
+ markdownImageRef,
854
923
  registerCommands
855
924
  };
856
- //# sourceMappingURL=chunk-GDCH6MWB.js.map
925
+ //# sourceMappingURL=chunk-K3JRXIEV.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/client.ts","../src/config.ts","../src/commands.ts"],"sourcesContent":["/**\n * DocSync API Client\n *\n * DocSync 底层是 Git 仓库,每个 Space = 一个 Git repo。\n * 认证:Authorization: Bearer {token}(支持 JWT 和永久 API Token)。\n */\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface Space {\n id: string;\n name: string;\n slug?: string;\n owner_id: string;\n is_private: boolean;\n created_at: string;\n member_count: number;\n}\n\nexport interface TreeEntry {\n name: string;\n type: 'blob' | 'tree';\n size: number;\n}\n\nexport interface LogEntry {\n hash: string;\n author: string;\n message: string;\n date: string;\n num_files: number;\n}\n\nexport interface TrashEntry {\n path: string;\n deleted_by: string;\n deleted_at: string;\n commit: string;\n}\n\nexport interface User {\n id: string;\n email: string;\n name: string;\n is_admin: boolean;\n is_active: boolean;\n created_at: string;\n}\n\nexport interface ShareLink {\n id: string;\n token: string;\n space_id: string;\n file_path: string;\n created_by: string;\n created_by_name?: string;\n created_by_email?: string;\n expires_at: string | null;\n created_at: string;\n user_ids?: string[];\n group_ids?: string[];\n}\n\nexport interface ShareFileInfo {\n file_path: string;\n file_name: string;\n space_name: string;\n created_by_name: string;\n expires_at: string | null;\n}\n\nexport interface DiffResponse {\n from: string;\n to: string;\n path: string;\n diff: string;\n old_body: string;\n new_body: string;\n}\n\nexport interface DiffFileEntry {\n path: string;\n status: string;\n}\n\nexport interface DiffSummary {\n from: string;\n to: string;\n files: DiffFileEntry[];\n}\n\nexport interface FileRef {\n id: string;\n space_id: string;\n path: string;\n}\n\nexport interface CatResult {\n content: string;\n ref: string;\n}\n\nexport interface UploadImageResult {\n url: string;\n object_key: string;\n content_type: string;\n size: number;\n}\n\nexport interface SaveResult {\n path: string;\n ref: string;\n}\n\nexport interface SaveConflict {\n error: 'conflict';\n current_ref: string;\n path: string;\n}\n\nexport interface Comment {\n id: number;\n space_id: string;\n file_path: string;\n comment_type: string;\n target_type: string;\n target_selector: string;\n target_content: string;\n content: string;\n user_id: string;\n user_name: string;\n user_email: string;\n is_closed: boolean;\n created_at: string;\n updated_at: string;\n replies: CommentReply[];\n}\n\nexport interface CommentReply {\n id: number;\n comment_id: number;\n content: string;\n user_id: string;\n user_name: string;\n user_email: string;\n created_at: string;\n updated_at: string;\n}\n\n// ---------------------------------------------------------------------------\n// Errors\n// ---------------------------------------------------------------------------\n\nexport class ConflictError extends Error {\n constructor(public readonly detail: SaveConflict) {\n super(\n 'Conflict: file has been modified by others. Please re-read the latest content and re-apply your changes.'\n );\n this.name = 'ConflictError';\n }\n}\n\n// ---------------------------------------------------------------------------\n// Client\n// ---------------------------------------------------------------------------\n\nexport class DocSyncClient {\n constructor(\n private baseUrl: string,\n private token: string\n ) {\n this.baseUrl = baseUrl.replace(/\\/$/, '');\n }\n\n private async request<T>(path: string, init?: RequestInit): Promise<T> {\n const res = await fetch(`${this.baseUrl}${path}`, {\n ...init,\n headers: {\n Authorization: `Bearer ${this.token}`,\n ...init?.headers,\n },\n });\n\n if (!res.ok) {\n const body = await res.text().catch(() => '');\n throw new Error(`${res.status} ${res.statusText}: ${body}`.trim());\n }\n\n const ct = res.headers.get('content-type') ?? '';\n if (ct.includes('application/json')) return res.json() as Promise<T>;\n return res.text() as unknown as T;\n }\n\n private async requestText(path: string, init?: RequestInit): Promise<string> {\n const res = await fetch(`${this.baseUrl}${path}`, {\n ...init,\n headers: {\n Authorization: `Bearer ${this.token}`,\n ...init?.headers,\n },\n });\n\n if (!res.ok) {\n const body = await res.text().catch(() => '');\n throw new Error(`${res.status} ${res.statusText}: ${body}`.trim());\n }\n\n return res.text();\n }\n\n // --- Auth ---\n async me(): Promise<User> {\n return this.request('/api/auth/me');\n }\n\n // --- Spaces ---\n async listSpaces(): Promise<Space[]> {\n return this.request('/api/spaces');\n }\n\n async resolveSpace(nameOrId: string): Promise<Space> {\n const spaces = await this.listSpaces();\n const input = nameOrId.toLowerCase();\n\n // 1-3: exact id / exact name / case-insensitive name\n const exact = spaces.find(\n (s) =>\n s.id === nameOrId ||\n s.name === nameOrId ||\n s.name.toLowerCase() === input\n );\n if (exact) return exact;\n\n // 4: slug exact match\n const bySlug = spaces.find((s) => s.slug === nameOrId);\n if (bySlug) return bySlug;\n\n // 5: name suffix match (e.g. \"研发\" matches \"G160-研发\")\n const suffixMatches = spaces.filter(\n (s) =>\n s.name.length > nameOrId.length && s.name.toLowerCase().endsWith(input)\n );\n if (suffixMatches.length === 1) return suffixMatches[0];\n if (suffixMatches.length > 1) {\n const candidates = suffixMatches.map((s) => s.name).join(', ');\n throw new Error(\n `Space \"${nameOrId}\" is ambiguous, matches: ${candidates}. Use the full name or UUID.`\n );\n }\n\n const available = spaces\n .map((s) => (s.slug ? `${s.name} (${s.slug})` : s.name))\n .join(', ');\n throw new Error(`Space \"${nameOrId}\" not found. Available: ${available}`);\n }\n\n // --- Tree ---\n async ls(spaceId: string, path = ''): Promise<TreeEntry[]> {\n return this.request(\n `/api/spaces/${spaceId}/tree?path=${encodeURIComponent(path)}`\n );\n }\n\n async treeFull(spaceId: string): Promise<TreeEntry[]> {\n return this.request(`/api/spaces/${spaceId}/tree/full`);\n }\n\n // --- Blob ---\n async cat(spaceId: string, filepath: string): Promise<string> {\n return this.requestText(\n `/api/spaces/${spaceId}/blob/${encodeURIComponent(filepath)}`\n );\n }\n\n async catWithRef(spaceId: string, filepath: string): Promise<CatResult> {\n const res = await fetch(\n `${this.baseUrl}/api/spaces/${spaceId}/blob/${encodeURIComponent(filepath)}`,\n { headers: { Authorization: `Bearer ${this.token}` } }\n );\n if (!res.ok) {\n const body = await res.text().catch(() => '');\n throw new Error(`${res.status} ${res.statusText}: ${body}`.trim());\n }\n const content = await res.text();\n const ref = res.headers.get('X-Git-Ref') ?? '';\n return { content, ref };\n }\n\n // --- Write ---\n async upload(\n spaceId: string,\n dir: string,\n filename: string,\n content: string | Buffer\n ): Promise<{ path: string }> {\n const blob =\n typeof content === 'string'\n ? new Blob([content], { type: 'application/octet-stream' })\n : new Blob([content], { type: 'application/octet-stream' });\n const form = new FormData();\n form.append('file', blob, filename);\n form.append('path', dir);\n return this.request(`/api/spaces/${spaceId}/files/upload`, {\n method: 'POST',\n body: form,\n });\n }\n\n /**\n * Upload an image to the server's OSS asset storage.\n * Returns a permanent public URL that can be embedded in Markdown.\n * Server limits: png/jpg/webp only, max 5MB.\n */\n async uploadImage(\n content: Buffer,\n filename: string\n ): Promise<UploadImageResult> {\n const blob = new Blob([content], { type: 'application/octet-stream' });\n const form = new FormData();\n form.append('file', blob, filename);\n return this.request('/api/assets/images', {\n method: 'POST',\n body: form,\n });\n }\n\n async save(\n spaceId: string,\n path: string,\n content: string,\n opts?: { baseRef?: string; message?: string }\n ): Promise<SaveResult> {\n const body: Record<string, string> = { path, content };\n if (opts?.baseRef) body.base_ref = opts.baseRef;\n if (opts?.message) body.message = opts.message;\n\n const res = await fetch(\n `${this.baseUrl}/api/spaces/${spaceId}/files/save`,\n {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${this.token}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(body),\n }\n );\n\n if (res.status === 409) {\n const data = (await res.json()) as SaveConflict;\n throw new ConflictError(data);\n }\n\n if (!res.ok) {\n const text = await res.text().catch(() => '');\n throw new Error(`${res.status} ${res.statusText}: ${text}`.trim());\n }\n\n return res.json() as Promise<SaveResult>;\n }\n\n async mkdir(spaceId: string, path: string): Promise<void> {\n await this.request(`/api/spaces/${spaceId}/files/mkdir`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ path }),\n });\n }\n\n async rm(spaceId: string, path: string): Promise<void> {\n await this.request(`/api/spaces/${spaceId}/files/delete`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ path }),\n });\n }\n\n async mv(spaceId: string, from: string, to: string): Promise<void> {\n await this.request(`/api/spaces/${spaceId}/files/rename`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ old_path: from, new_path: to }),\n });\n }\n\n async rollback(\n spaceId: string,\n filePath: string,\n commitHash: string\n ): Promise<void> {\n await this.request(`/api/spaces/${spaceId}/files/rollback`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ file_path: filePath, commit_hash: commitHash }),\n });\n }\n\n // --- History ---\n async log(spaceId: string, filepath?: string): Promise<LogEntry[]> {\n const path = filepath\n ? `/api/spaces/${spaceId}/log/${encodeURIComponent(filepath)}`\n : `/api/spaces/${spaceId}/log/`;\n return this.request(path);\n }\n\n // --- Trash ---\n async trash(spaceId: string): Promise<TrashEntry[]> {\n return this.request(`/api/spaces/${spaceId}/trash`);\n }\n\n async restore(spaceId: string, path: string, commit: string): Promise<void> {\n await this.request(`/api/spaces/${spaceId}/trash/restore`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ path, commit }),\n });\n }\n\n // --- Comments ---\n async listComments(spaceId: string, filePath: string): Promise<Comment[]> {\n return this.request(\n `/api/spaces/${spaceId}/comments?path=${encodeURIComponent(filePath)}`\n );\n }\n\n async createComment(\n spaceId: string,\n filePath: string,\n content: string,\n opts?: { quote?: string }\n ): Promise<Comment> {\n const body: Record<string, string> = { file_path: filePath, content };\n if (opts?.quote) {\n body.comment_type = 'text';\n body.target_type = 'selection';\n body.target_content = opts.quote;\n body.target_selector = JSON.stringify({\n startOffset: 0,\n endOffset: 0,\n text: opts.quote,\n prefix: '',\n suffix: '',\n });\n }\n return this.request(`/api/spaces/${spaceId}/comments`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n });\n }\n\n async replyComment(\n spaceId: string,\n commentId: number,\n content: string\n ): Promise<CommentReply> {\n return this.request(\n `/api/spaces/${spaceId}/comments/${commentId}/replies`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ content }),\n }\n );\n }\n\n async closeComment(spaceId: string, commentId: number): Promise<Comment> {\n return this.request(`/api/spaces/${spaceId}/comments/${commentId}`, {\n method: 'PUT',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ is_closed: true }),\n });\n }\n\n async deleteComment(spaceId: string, commentId: number): Promise<void> {\n await this.request(`/api/spaces/${spaceId}/comments/${commentId}`, {\n method: 'DELETE',\n });\n }\n\n // --- Share Links ---\n async createShareLink(\n spaceId: string,\n filePath: string,\n opts?: { expiresAt?: string; userIds?: string[]; groupIds?: string[] }\n ): Promise<ShareLink> {\n const body: Record<string, unknown> = { file_path: filePath };\n if (opts?.expiresAt) body.expires_at = opts.expiresAt;\n if (opts?.userIds?.length) body.user_ids = opts.userIds;\n if (opts?.groupIds?.length) body.group_ids = opts.groupIds;\n return this.request(`/api/spaces/${spaceId}/share-links`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n });\n }\n\n async listShareLinks(\n spaceId: string,\n filePath?: string\n ): Promise<ShareLink[]> {\n const q = filePath ? `?file_path=${encodeURIComponent(filePath)}` : '';\n return this.request(`/api/spaces/${spaceId}/share-links${q}`);\n }\n\n async updateShareLink(\n spaceId: string,\n linkId: string,\n opts: { expiresAt?: string; userIds?: string[]; groupIds?: string[] }\n ): Promise<ShareLink> {\n const body: Record<string, unknown> = {};\n if (opts.expiresAt !== undefined) body.expires_at = opts.expiresAt;\n if (opts.userIds) body.user_ids = opts.userIds;\n if (opts.groupIds) body.group_ids = opts.groupIds;\n return this.request(`/api/spaces/${spaceId}/share-links/${linkId}`, {\n method: 'PUT',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n });\n }\n\n async deleteShareLink(spaceId: string, linkId: string): Promise<void> {\n await this.request(`/api/spaces/${spaceId}/share-links/${linkId}`, {\n method: 'DELETE',\n });\n }\n\n async getSharedFile(token: string): Promise<string> {\n return this.requestText(`/api/share/${token}`);\n }\n\n async getSharedFileInfo(token: string): Promise<ShareFileInfo> {\n return this.request(`/api/share/${token}/info`);\n }\n\n // --- Diff ---\n async diffFile(\n spaceId: string,\n filePath: string,\n to: string,\n from?: string\n ): Promise<DiffResponse> {\n const params = new URLSearchParams({ to });\n if (from) params.set('from', from);\n return this.request(\n `/api/spaces/${spaceId}/diff/${encodeURIComponent(filePath)}?${params}`\n );\n }\n\n async diffSummary(\n spaceId: string,\n to: string,\n from?: string\n ): Promise<DiffSummary> {\n const params = new URLSearchParams({ to });\n if (from) params.set('from', from);\n return this.request(`/api/spaces/${spaceId}/diff?${params}`);\n }\n\n // --- File Ref ---\n async getFileRef(\n spaceId: string,\n path: string\n ): Promise<{\n id: string;\n space_id: string;\n slug: string;\n path: string;\n is_dir: boolean;\n url: string;\n }> {\n return this.request(\n `/api/spaces/${spaceId}/file-ref?path=${encodeURIComponent(path)}`\n );\n }\n\n // --- Resolve short URLs ---\n async resolveBySlug(slug: string): Promise<Space> {\n return this.request(`/api/spaces/by-slug/${encodeURIComponent(slug)}`);\n }\n\n async resolveFileRef(fileId: string): Promise<FileRef> {\n return this.request(`/api/file-refs/${encodeURIComponent(fileId)}`);\n }\n}\n","/**\n * 配置管理\n *\n * 优先级:环境变量 > ~/.docz/config.json\n */\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\n\nconst CONFIG_DIR = join(homedir(), '.docz');\nconst CONFIG_FILE = join(CONFIG_DIR, 'config.json');\n\ninterface Config {\n base_url?: string;\n token?: string;\n}\n\nfunction readConfig(): Config {\n if (!existsSync(CONFIG_FILE)) return {};\n try {\n return JSON.parse(readFileSync(CONFIG_FILE, 'utf-8'));\n } catch {\n return {};\n }\n}\n\nfunction writeConfig(config: Config): void {\n mkdirSync(CONFIG_DIR, { recursive: true });\n writeFileSync(CONFIG_FILE, `${JSON.stringify(config, null, 2)}\\n`);\n}\n\nexport function getBaseUrl(): string {\n return (\n process.env.DOCSYNC_BASE_URL ??\n readConfig().base_url ??\n 'https://docz.zhenguanyu.com'\n );\n}\n\nexport function getToken(): string | undefined {\n return process.env.DOCSYNC_API_TOKEN ?? readConfig().token;\n}\n\nexport function saveConfig(baseUrl: string, token: string): void {\n writeConfig({ base_url: baseUrl, token });\n}\n\nexport function getConfigPath(): string {\n return CONFIG_FILE;\n}\n","/**\n * CLI Commands\n */\n\nimport { existsSync, readFileSync, statSync } from 'node:fs';\nimport { basename } from 'node:path';\nimport type { Command } from 'commander';\nimport { ConflictError, DocSyncClient } from './client.js';\nimport { getBaseUrl, getConfigPath, getToken, saveConfig } from './config.js';\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction getClient(): DocSyncClient {\n const token = getToken();\n if (!token) {\n console.error(\n 'Error: No token configured.\\n' +\n 'Run `docz login` or set DOCSYNC_API_TOKEN environment variable.'\n );\n process.exit(1);\n }\n return new DocSyncClient(getBaseUrl(), token);\n}\n\n/** Parse \"space:path\" or \"space path\" format */\nexport function parseTarget(args: string[]): { space: string; path: string } {\n if (args.length === 0) {\n console.error(\n 'Error: space is required. Usage: docz <cmd> <space>[:<path>]'\n );\n process.exit(1);\n }\n const first = args[0];\n if (first.includes(':')) {\n const [space, ...rest] = first.split(':');\n return { space, path: rest.join(':') };\n }\n return { space: first, path: args.slice(1).join(' ') };\n}\n\nfunction formatSize(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n}\n\n// Share URL: /share/{token}\nconst SHARE_URL_RE = /\\/share\\/([^/?\\s]+)/;\n\n/** Resolve slug: try local spaces cache first, then API */\nasync function resolveSlug(\n client: DocSyncClient,\n slug: string\n): Promise<{ id: string }> {\n try {\n const spaces = await client.listSpaces();\n const found = spaces.find((s) => s.slug === slug);\n if (found) return found;\n } catch {\n // fall through to by-slug API\n }\n return client.resolveBySlug(slug);\n}\n\n/**\n * Detect if input is a URL and resolve it to { spaceId, path }.\n * Supports:\n * /s/{slug}/f/{fileId} — short URL with fileId\n * /s/{slug}[/path/to/file] — slug URL with optional path\n * /spaces/{spaceId}[/path/...] — legacy URL\n * Returns null if not a recognized DocSync URL.\n */\nasync function resolveUrl(\n client: DocSyncClient,\n input: string\n): Promise<{ spaceId: string; path: string } | null> {\n let pathname: string;\n try {\n pathname = new URL(input).pathname;\n } catch {\n return null;\n }\n\n // /s/{slug}/f/{fileId}\n const fileMatch = pathname.match(/^\\/s\\/([^/]+)\\/f\\/([^/]+)$/);\n if (fileMatch) {\n const [, slug, fileId] = fileMatch;\n const space = await resolveSlug(client, slug);\n const ref = await client.resolveFileRef(fileId);\n return { spaceId: space.id, path: ref.path };\n }\n\n // /s/{slug}[/path/to/file]\n const slugMatch = pathname.match(/^\\/s\\/([^/]+)(\\/.*)?$/);\n if (slugMatch) {\n const [, slug, rest] = slugMatch;\n const space = await resolveSlug(client, slug);\n const filePath = rest ? decodeURIComponent(rest.slice(1)) : '';\n return { spaceId: space.id, path: filePath };\n }\n\n // /spaces/{spaceId}[/path/to/file] (legacy)\n const legacyMatch = pathname.match(/^\\/spaces\\/([^/]+)(\\/.*)?$/);\n if (legacyMatch) {\n const [, spaceId, rest] = legacyMatch;\n const filePath = rest ? decodeURIComponent(rest.slice(1)) : '';\n return { spaceId, path: filePath };\n }\n\n return null;\n}\n\n/**\n * Resolve target: if it's a URL, resolve it; otherwise use parseTarget + resolveSpace.\n */\nexport async function resolveTarget(\n client: DocSyncClient,\n args: string[]\n): Promise<{ spaceId: string; path: string }> {\n const first = args[0];\n if (first && (first.startsWith('http://') || first.startsWith('https://'))) {\n const result = await resolveUrl(client, first);\n if (result) return result;\n throw new Error(\n `Unrecognized DocSync URL: ${first}\\nExpected: /s/{slug}[/f/{fileId}], /s/{slug}[/path], or /spaces/{id}[/path]`\n );\n }\n const { space, path } = parseTarget(args);\n const s = await client.resolveSpace(space);\n return { spaceId: s.id, path };\n}\n\n/**\n * Resolve a space argument that may be a name, UUID, or URL.\n * For URLs, delegates to resolveUrl and extracts the spaceId.\n */\nexport async function resolveSpaceArg(\n client: DocSyncClient,\n input: string\n): Promise<{ id: string }> {\n if (input.startsWith('http://') || input.startsWith('https://')) {\n const result = await resolveUrl(client, input);\n if (result) return { id: result.spaceId };\n throw new Error(\n `Unrecognized DocSync URL: ${input}\\nExpected: /s/{slug}[/f/{fileId}], /s/{slug}[/path], or /spaces/{id}[/path]`\n );\n }\n return client.resolveSpace(input);\n}\n\n/** Parse relative duration (7d, 24h, 30d) to RFC3339 */\nexport function parseExpires(value: string): string {\n const match = value.match(/^(\\d+)([dh])$/);\n if (!match)\n throw new Error(\n `Invalid expires format: \"${value}\". Use e.g. 7d, 24h, 30d`\n );\n const [, num, unit] = match;\n const ms = unit === 'd' ? Number(num) * 86400000 : Number(num) * 3600000;\n return new Date(Date.now() + ms).toISOString();\n}\n\n/** Extract share token from URL or return as-is */\nfunction extractShareToken(input: string): string {\n const m = input.match(SHARE_URL_RE);\n if (m) return m[1];\n return input;\n}\n\n/** Read all of stdin into a string */\nasync function readStdin(): Promise<string> {\n const chunks: Buffer[] = [];\n for await (const chunk of process.stdin) {\n chunks.push(chunk as Buffer);\n }\n return Buffer.concat(chunks).toString('utf-8');\n}\n\nconst MAX_SAVE_SIZE = 2 * 1024 * 1024; // 2MB\n\n// --- Image upload (shared by CLI command and MCP tool) ---\n\nexport const IMAGE_EXTS = ['png', 'jpg', 'jpeg', 'webp'];\nexport const IMAGE_MAX_SIZE = 5 * 1024 * 1024; // 5MB, same as server limit\n\n/**\n * Validate and read a local image file for upload.\n * Returns { content, filename } on success, or { error } describing\n * why the file was rejected (no request is sent in that case).\n */\nexport function readImageFile(\n filePath: string\n): { content: Buffer; filename: string } | { error: string } {\n if (!existsSync(filePath)) {\n return { error: `File not found: ${filePath}` };\n }\n const filename = basename(filePath);\n const ext = filename.split('.').pop()?.toLowerCase() ?? '';\n if (!IMAGE_EXTS.includes(ext)) {\n return {\n error: `Unsupported image type \".${ext}\". Supported: ${IMAGE_EXTS.join(', ')}`,\n };\n }\n const size = statSync(filePath).size;\n if (size > IMAGE_MAX_SIZE) {\n return {\n error: `Image too large (${formatSize(size)}). Max size: 5 MB`,\n };\n }\n return { content: readFileSync(filePath), filename };\n}\n\n/** Markdown image reference with the filename (minus extension) as alt text */\nexport function markdownImageRef(filename: string, url: string): string {\n const alt = filename.replace(/\\.[^.]+$/, '');\n return `![${alt}](${url})`;\n}\n\n// ---------------------------------------------------------------------------\n// Commands\n// ---------------------------------------------------------------------------\n\nexport function registerCommands(program: Command): void {\n // --- login ---\n program\n .command('login')\n .description('Configure DocSync credentials')\n .option('-u, --url <url>', 'DocSync server URL')\n .option('-t, --token <token>', 'API token')\n .action(async (opts) => {\n const url = opts.url ?? getBaseUrl();\n const token = opts.token;\n if (!token) {\n console.error(\n 'Error: --token is required.\\n' +\n 'Get one at: ' +\n url +\n ' → Settings → API Tokens'\n );\n process.exit(1);\n }\n const client = new DocSyncClient(url, token);\n try {\n const user = await client.me();\n saveConfig(url, token);\n console.log(`Logged in as ${user.name} (${user.email})`);\n console.log(`Config saved to ${getConfigPath()}`);\n } catch (err) {\n console.error(\n `Error: ${err instanceof Error ? err.message : String(err)}`\n );\n process.exit(1);\n }\n });\n\n // --- whoami ---\n program\n .command('whoami')\n .description('Show current user')\n .action(async () => {\n const client = getClient();\n const user = await client.me();\n console.log(`${user.name} (${user.email})`);\n });\n\n // --- spaces ---\n program\n .command('spaces')\n .description('List all accessible spaces')\n .action(async () => {\n const client = getClient();\n const spaces = await client.listSpaces();\n for (const s of spaces) {\n const tag = s.is_private ? 'private' : 'team';\n console.log(\n `${s.name}\\t${tag}\\t${s.member_count} members\\t${s.id}\\t${s.slug ?? ''}`\n );\n }\n });\n\n // --- ls ---\n program\n .command('ls')\n .description('List files — docz ls <space>[:<path>] or <url>')\n .argument('<target...>')\n .option('-R, --recursive', 'Recursively list all files')\n .action(async (args: string[], opts: { recursive?: boolean }) => {\n const client = getClient();\n const { spaceId, path } = await resolveTarget(client, args);\n const entries = opts.recursive\n ? await client.treeFull(spaceId)\n : await client.ls(spaceId, path);\n if (entries.length === 0) {\n console.log('(empty)');\n return;\n }\n for (const e of entries) {\n if (e.type === 'tree') {\n console.log(`${e.name}/`);\n } else {\n console.log(`${e.name}\\t${formatSize(e.size)}`);\n }\n }\n });\n\n // --- cat ---\n program\n .command('cat')\n .description('Read file content — docz cat <space>:<path> or <url>')\n .argument('<target...>')\n .option('--ref', 'Also output Git ref to stderr')\n .action(async (args: string[], opts: { ref?: boolean }) => {\n const client = getClient();\n const { spaceId, path } = await resolveTarget(client, args);\n if (!path) {\n console.error(\n 'Error: file path is required. Usage: docz cat <space>:<path>'\n );\n process.exit(1);\n }\n if (opts.ref) {\n const result = await client.catWithRef(spaceId, path);\n console.error(`ref: ${result.ref}`);\n process.stdout.write(result.content);\n } else {\n const content = await client.cat(spaceId, path);\n process.stdout.write(content);\n }\n });\n\n // --- upload ---\n program\n .command('upload')\n .description(\n 'Upload file — docz upload <local-file> <space>[:<dir>] or <url>'\n )\n .argument('<file>', 'Local file to upload')\n .argument('<target...>')\n .action(async (file: string, args: string[]) => {\n const client = getClient();\n const { spaceId, path: dir } = await resolveTarget(client, args);\n const content = readFileSync(file);\n const filename = basename(file);\n const targetDir = dir || '';\n const result = await client.upload(spaceId, targetDir, filename, content);\n console.log(`Uploaded: ${result.path}`);\n });\n\n // --- image ---\n const image = program.command('image').description('Image asset operations');\n\n image\n .command('upload')\n .description(\n 'Upload image to OSS, returns a permanent public URL for Markdown embedding'\n )\n .argument('<file>', 'Local image file (png/jpg/webp, max 5MB)')\n .action(async (file: string) => {\n const read = readImageFile(file);\n if ('error' in read) {\n console.error(`Error: ${read.error}`);\n process.exit(1);\n }\n const client = getClient();\n const result = await client.uploadImage(read.content, read.filename);\n console.log(`URL: ${result.url}`);\n console.log(`Markdown: ${markdownImageRef(read.filename, result.url)}`);\n });\n\n // --- write ---\n program\n .command('write')\n .description(\n 'Write content to file — docz write <space>:<path> <content> or <url> <content>'\n )\n .argument('<target>', 'space:dir/filename.md or short URL')\n .argument('<content>', 'File content (or - for stdin)')\n .option('--force', 'Skip conflict detection')\n .option('-m, --message <msg>', 'Custom commit message')\n .action(\n async (\n target: string,\n content: string,\n opts: { force?: boolean; message?: string }\n ) => {\n const client = getClient();\n const { spaceId, path } = await resolveTarget(client, [target]);\n if (!path) {\n console.error(\n 'Error: path is required. Usage: docz write <space>:<dir/filename> <content>'\n );\n process.exit(1);\n }\n const body = content === '-' ? await readStdin() : content;\n\n if (Buffer.byteLength(body, 'utf-8') > MAX_SAVE_SIZE) {\n console.error(\n 'Error: content exceeds 2MB limit. Use `docz upload` for large files.'\n );\n process.exit(1);\n }\n\n let baseRef: string | undefined;\n if (!opts.force) {\n try {\n const existing = await client.catWithRef(spaceId, path);\n baseRef = existing.ref;\n } catch (err) {\n const msg = err instanceof Error ? err.message : '';\n if (!msg.includes('404')) throw err;\n }\n }\n\n try {\n const result = await client.save(spaceId, path, body, {\n baseRef,\n message: opts.message,\n });\n console.log(`Written: ${result.path} (ref: ${result.ref})`);\n } catch (err) {\n if (err instanceof ConflictError) {\n console.error(\n 'Error: file was modified by someone else. Please re-read the latest content and try again.'\n );\n process.exit(1);\n }\n throw err;\n }\n }\n );\n\n // --- mkdir ---\n program\n .command('mkdir')\n .description('Create folder — docz mkdir <space>:<path> or <url>')\n .argument('<target...>')\n .action(async (args: string[]) => {\n const client = getClient();\n const { spaceId, path } = await resolveTarget(client, args);\n if (!path) {\n console.error('Error: path is required.');\n process.exit(1);\n }\n await client.mkdir(spaceId, path);\n console.log(`Created: ${path}`);\n });\n\n // --- rm ---\n program\n .command('rm')\n .description('Delete file/folder — docz rm <space>:<path> or <url>')\n .argument('<target...>')\n .action(async (args: string[]) => {\n const client = getClient();\n const { spaceId, path } = await resolveTarget(client, args);\n if (!path) {\n console.error('Error: path is required.');\n process.exit(1);\n }\n await client.rm(spaceId, path);\n console.log(`Deleted: ${path} (recoverable from trash for 30 days)`);\n });\n\n // --- mv ---\n program\n .command('mv')\n .description('Rename/move — docz mv <space>:<from> <to> or <url> <to>')\n .argument('<target>', 'space:old-path or short URL')\n .argument('<to>', 'new-path')\n .action(async (target: string, to: string) => {\n const client = getClient();\n const { spaceId, path: from } = await resolveTarget(client, [target]);\n if (!from) {\n console.error('Error: source path is required.');\n process.exit(1);\n }\n await client.mv(spaceId, from, to);\n console.log(`Moved: ${from} → ${to}`);\n });\n\n // --- log ---\n program\n .command('log')\n .description('Show change history — docz log <space>[:<path>] or <url>')\n .argument('<target...>')\n .action(async (args: string[]) => {\n const client = getClient();\n const { spaceId, path } = await resolveTarget(client, args);\n const logs = await client.log(spaceId, path || undefined);\n if (logs.length === 0) {\n console.log('No history.');\n return;\n }\n for (const l of logs) {\n console.log(`${l.hash} ${l.date} ${l.message}`);\n }\n });\n\n // --- rollback ---\n program\n .command('rollback')\n .description(\n 'Rollback file to a previous version — docz rollback <space>:<path> <commit> or <url> <commit>'\n )\n .argument('<target>', 'space:path or short URL')\n .argument('<commit>', 'Commit hash to rollback to')\n .action(async (target: string, commit: string) => {\n const client = getClient();\n const { spaceId, path } = await resolveTarget(client, [target]);\n if (!path) {\n console.error('Error: file path is required.');\n process.exit(1);\n }\n await client.rollback(spaceId, path, commit);\n console.log(`Rolled back: ${path} → ${commit.substring(0, 7)}`);\n });\n\n // --- trash ---\n program\n .command('trash')\n .description('Show deleted files — docz trash <space>')\n .argument('<space>')\n .action(async (spaceName: string) => {\n const client = getClient();\n const s = await resolveSpaceArg(client, spaceName);\n const items = await client.trash(s.id);\n if (items.length === 0) {\n console.log('Trash is empty.');\n return;\n }\n for (const t of items) {\n console.log(\n `${t.path}\\tdeleted ${t.deleted_at}\\t${t.commit.substring(0, 7)}`\n );\n }\n });\n\n // --- restore ---\n program\n .command('restore')\n .description(\n 'Restore file from trash — docz restore <space>:<path> <commit> or <url> <commit>'\n )\n .argument('<target>', 'space:path or short URL')\n .argument('<commit>', 'Commit hash from trash listing')\n .action(async (target: string, commit: string) => {\n const client = getClient();\n const { spaceId, path } = await resolveTarget(client, [target]);\n if (!path) {\n console.error('Error: path is required.');\n process.exit(1);\n }\n await client.restore(spaceId, path, commit);\n console.log(`Restored: ${path}`);\n });\n\n // --- comment ---\n const comment = program\n .command('comment')\n .description('Manage file comments');\n\n comment\n .command('list')\n .description('List comments — docz comment list <space>:<path>')\n .argument('<target...>')\n .action(async (args: string[]) => {\n const client = getClient();\n const { spaceId, path } = await resolveTarget(client, args);\n if (!path) {\n console.error('Error: file path is required.');\n process.exit(1);\n }\n const comments = await client.listComments(spaceId, path);\n if (comments.length === 0) {\n console.log('No comments.');\n return;\n }\n for (const c of comments) {\n const status = c.is_closed ? ' [closed]' : '';\n console.log(`#${c.id} ${c.user_name} (${c.created_at})${status}`);\n if (c.target_content) {\n console.log(` > ${c.target_content}`);\n }\n console.log(` ${c.content}`);\n for (const r of c.replies) {\n console.log(` → ${r.user_name}: ${r.content}`);\n }\n }\n });\n\n comment\n .command('add')\n .description(\n 'Add comment — docz comment add <space>:<path> <content> or <url> <content>'\n )\n .argument('<target>', 'space:path or short URL')\n .argument('<content>', 'Comment text (or - for stdin)')\n .option(\n '--quote <text>',\n 'Quote text from the file (selection comment). The quoted text will be highlighted in Web UI'\n )\n .action(\n async (target: string, content: string, opts: { quote?: string }) => {\n const client = getClient();\n const { spaceId, path } = await resolveTarget(client, [target]);\n if (!path) {\n console.error('Error: file path is required.');\n process.exit(1);\n }\n const body = content === '-' ? await readStdin() : content;\n const c = await client.createComment(spaceId, path, body, {\n quote: opts.quote,\n });\n console.log(`Comment #${c.id} created.`);\n }\n );\n\n comment\n .command('reply')\n .description(\n 'Reply to comment — docz comment reply <space> <commentId> <content>'\n )\n .argument('<space>')\n .argument('<commentId>')\n .argument('<content>', 'Reply text (or - for stdin)')\n .action(async (spaceName: string, commentId: string, content: string) => {\n const client = getClient();\n const s = await resolveSpaceArg(client, spaceName);\n const body = content === '-' ? await readStdin() : content;\n const r = await client.replyComment(s.id, Number(commentId), body);\n console.log(`Reply #${r.id} created.`);\n });\n\n comment\n .command('close')\n .description('Close comment — docz comment close <space> <commentId>')\n .argument('<space>')\n .argument('<commentId>')\n .action(async (spaceName: string, commentId: string) => {\n const client = getClient();\n const s = await resolveSpaceArg(client, spaceName);\n await client.closeComment(s.id, Number(commentId));\n console.log(`Comment #${commentId} closed.`);\n });\n\n comment\n .command('rm')\n .description('Delete comment — docz comment rm <space> <commentId>')\n .argument('<space>')\n .argument('<commentId>')\n .action(async (spaceName: string, commentId: string) => {\n const client = getClient();\n const s = await resolveSpaceArg(client, spaceName);\n await client.deleteComment(s.id, Number(commentId));\n console.log(`Comment #${commentId} deleted.`);\n });\n\n // --- share ---\n const share = program.command('share').description('Manage share links');\n\n share\n .command('create')\n .description(\n 'Create share link — docz share create <space>:<path> or <url>'\n )\n .argument('<target>', 'space:path or short URL')\n .option('--expires <duration>', 'Expiry duration (e.g. 7d, 24h)')\n .option('--users <emails>', 'Comma-separated user emails or IDs')\n .option('--groups <ids>', 'Comma-separated group IDs')\n .action(\n async (\n target: string,\n opts: { expires?: string; users?: string; groups?: string }\n ) => {\n const client = getClient();\n const { spaceId, path } = await resolveTarget(client, [target]);\n if (!path) {\n console.error(\n 'Error: file path is required. Usage: docz share create <space>:<path>'\n );\n process.exit(1);\n }\n const apiOpts: {\n expiresAt?: string;\n userIds?: string[];\n groupIds?: string[];\n } = {};\n if (opts.expires) apiOpts.expiresAt = parseExpires(opts.expires);\n if (opts.users)\n apiOpts.userIds = opts.users.split(',').map((s) => s.trim());\n if (opts.groups)\n apiOpts.groupIds = opts.groups.split(',').map((s) => s.trim());\n const link = await client.createShareLink(spaceId, path, apiOpts);\n const baseUrl = getBaseUrl();\n console.log('Created share link:');\n console.log(` id: ${link.id}`);\n console.log(` token: ${link.token}`);\n console.log(` url: ${baseUrl}/share/${link.token}`);\n console.log(` expires: ${link.expires_at ?? 'never'}`);\n if (link.user_ids?.length)\n console.log(` users: ${link.user_ids.join(', ')}`);\n if (link.group_ids?.length)\n console.log(` groups: ${link.group_ids.length}`);\n }\n );\n\n share\n .command('list')\n .description('List share links — docz share list <space>')\n .argument('<space>')\n .option('--file <path>', 'Filter by file path')\n .action(async (spaceName: string, opts: { file?: string }) => {\n const client = getClient();\n const s = await resolveSpaceArg(client, spaceName);\n const links = await client.listShareLinks(s.id, opts.file);\n if (links.length === 0) {\n console.log('No share links.');\n return;\n }\n for (const l of links) {\n const expires = l.expires_at ?? 'never';\n const creator = l.created_by_name ?? l.created_by_email ?? l.created_by;\n console.log(\n `${l.id}\\t${l.token}\\t${l.file_path}\\t${expires}\\t${creator}`\n );\n }\n });\n\n share\n .command('update')\n .description('Update share link — docz share update <space> <link-id>')\n .argument('<space>')\n .argument('<linkId>')\n .option('--expires <duration>', 'New expiry duration (e.g. 30d)')\n .option('--users <emails>', 'Comma-separated user emails or IDs')\n .option('--groups <ids>', 'Comma-separated group IDs')\n .action(\n async (\n spaceName: string,\n linkId: string,\n opts: { expires?: string; users?: string; groups?: string }\n ) => {\n const client = getClient();\n const s = await resolveSpaceArg(client, spaceName);\n const apiOpts: {\n expiresAt?: string;\n userIds?: string[];\n groupIds?: string[];\n } = {};\n if (opts.expires) apiOpts.expiresAt = parseExpires(opts.expires);\n if (opts.users)\n apiOpts.userIds = opts.users.split(',').map((s) => s.trim());\n if (opts.groups)\n apiOpts.groupIds = opts.groups.split(',').map((s) => s.trim());\n await client.updateShareLink(s.id, linkId, apiOpts);\n console.log(`Updated share link: ${linkId}`);\n }\n );\n\n share\n .command('cat')\n .description('Read shared file — docz share cat <token-or-url>')\n .argument('<token>', 'Share token or full URL')\n .option('--raw', 'Output raw content only')\n .action(async (tokenArg: string, opts: { raw?: boolean }) => {\n const client = getClient();\n const token = extractShareToken(tokenArg);\n if (!opts.raw) {\n try {\n const info = await client.getSharedFileInfo(token);\n console.log(`File: ${info.file_path} (${info.space_name})`);\n console.log(\n `Shared by: ${info.created_by_name} | Expires: ${info.expires_at ?? 'never'}`\n );\n console.log('---');\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n if (!msg.includes('404')) {\n console.error(`Warning: failed to fetch share info: ${msg}`);\n }\n }\n }\n const content = await client.getSharedFile(token);\n process.stdout.write(content);\n });\n\n share\n .command('info')\n .description('Show share link info — docz share info <token-or-url>')\n .argument('<token>', 'Share token or full URL')\n .action(async (tokenArg: string) => {\n const client = getClient();\n const token = extractShareToken(tokenArg);\n const info = await client.getSharedFileInfo(token);\n console.log(`File: ${info.file_path}`);\n console.log(`Space: ${info.space_name}`);\n console.log(`Shared by: ${info.created_by_name}`);\n console.log(`Expires: ${info.expires_at ?? 'never'}`);\n });\n\n share\n .command('rm')\n .description('Delete share link — docz share rm <space> <link-id>')\n .argument('<space>')\n .argument('<linkId>')\n .action(async (spaceName: string, linkId: string) => {\n const client = getClient();\n const s = await resolveSpaceArg(client, spaceName);\n await client.deleteShareLink(s.id, linkId);\n console.log(`Deleted share link: ${linkId}`);\n });\n\n // --- shortlink ---\n program\n .command('shortlink')\n .description('Get short URL — docz shortlink <space>:<path> or <url>')\n .argument('<target...>')\n .action(async (args: string[]) => {\n const client = getClient();\n const { spaceId, path } = await resolveTarget(client, args);\n if (!path) {\n console.error(\n 'Error: file path is required. Usage: docz shortlink <space>:<path>'\n );\n process.exit(1);\n }\n const ref = await client.getFileRef(spaceId, path);\n console.log(ref.url);\n });\n\n // --- diff ---\n program\n .command('diff')\n .description(\n 'Show changes — docz diff <space>[:<path>] <commit> [<from>] or <url> <commit> [<from>]'\n )\n .argument('<target>', 'space or space:path or short URL')\n .argument('<to>', 'Commit hash')\n .argument('[from]', 'From commit hash (default: to^)')\n .action(async (target: string, to: string, from?: string) => {\n const client = getClient();\n const { spaceId, path } = await resolveTarget(client, [target]);\n if (path) {\n const result = await client.diffFile(spaceId, path, to, from);\n if (result.diff) {\n process.stdout.write(result.diff);\n } else {\n console.log('No changes.');\n }\n } else {\n const result = await client.diffSummary(spaceId, to, from);\n if (result.files.length === 0) {\n console.log('No changes.');\n return;\n }\n for (const f of result.files) {\n console.log(`${f.status} ${f.path}`);\n }\n }\n });\n}\n"],"mappings":"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","names":["existsSync","readFileSync","existsSync","readFileSync","s"]}
package/dist/index.js CHANGED
@@ -1,15 +1,15 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  registerCommands
4
- } from "./chunk-GDCH6MWB.js";
4
+ } from "./chunk-K3JRXIEV.js";
5
5
 
6
6
  // src/index.ts
7
7
  import { Command } from "commander";
8
8
  var program = new Command();
9
- program.name("docz").description("DocSync CLI \u2014 read and write company documents").version("0.8.1");
9
+ program.name("docz").description("DocSync CLI \u2014 read and write company documents").version("0.9.0");
10
10
  registerCommands(program);
11
11
  program.command("mcp").description("Start MCP stdio server for AI agent integration").action(async () => {
12
- const { startMcpServer } = await import("./mcp-S5OSNTRV.js");
12
+ const { startMcpServer } = await import("./mcp-HXAB75DP.js");
13
13
  await startMcpServer();
14
14
  });
15
15
  program.parse();
@@ -4,8 +4,10 @@ import {
4
4
  DocSyncClient,
5
5
  getBaseUrl,
6
6
  getToken,
7
- parseExpires
8
- } from "./chunk-GDCH6MWB.js";
7
+ markdownImageRef,
8
+ parseExpires,
9
+ readImageFile
10
+ } from "./chunk-K3JRXIEV.js";
9
11
 
10
12
  // src/mcp.ts
11
13
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
@@ -121,6 +123,20 @@ async function startMcpServer() {
121
123
  required: ["space", "path", "content"]
122
124
  }
123
125
  },
126
+ {
127
+ name: "docz_upload_image",
128
+ description: "\u4E3A Docz \u6587\u6863\u914D\u56FE\uFF1A\u4E0A\u4F20\u672C\u5730\u56FE\u7247\u5230\u56FE\u5E8A\uFF08OSS\uFF09\uFF0C\u8FD4\u56DE\u6C38\u4E45\u516C\u7F51 URL\u3002\u5178\u578B\u5DE5\u4F5C\u6D41\uFF1A\u5148\u7528\u672C\u5DE5\u5177\u4E0A\u4F20\u56FE\u7247\u62FF\u5230 URL\uFF0C\u518D\u628A\u8FD4\u56DE\u7684 ![alt](url) \u5199\u5165\u6587\u6863\u5185\u5BB9\uFF0C\u901A\u8FC7 docz_save_file / docz_upload_file \u4FDD\u5B58\u3002\u56FE\u7247\u5B58 OSS \u800C\u975E Space\uFF08\u4E0D\u5360\u914D\u989D\uFF09\uFF0CURL \u65E0\u9700\u767B\u5F55\u5373\u53EF\u8BBF\u95EE\uFF0C\u5206\u4EAB\u94FE\u63A5/\u535A\u5BA2\u4E2D\u5747\u53EF\u663E\u793A\u3002\u6CE8\u610F\uFF1A\u6587\u6863\u914D\u56FE\u8BF7\u7528\u672C\u5DE5\u5177\uFF0C\u4E0D\u8981\u7528 docz_upload_file \u628A\u56FE\u7247\u4F20\u8FDB Space\u3002\u652F\u6301 png/jpg/webp\uFF0C\u6700\u5927 5MB",
129
+ inputSchema: {
130
+ type: "object",
131
+ properties: {
132
+ file_path: {
133
+ type: "string",
134
+ description: "\u672C\u5730\u56FE\u7247\u6587\u4EF6\u7684\u7EDD\u5BF9\u8DEF\u5F84"
135
+ }
136
+ },
137
+ required: ["file_path"]
138
+ }
139
+ },
124
140
  {
125
141
  name: "docz_upload_file",
126
142
  description: "\u4E0A\u4F20/\u521B\u5EFA\u6587\u4EF6\u5230 DocSync Space",
@@ -515,6 +531,17 @@ async function startMcpServer() {
515
531
  throw err;
516
532
  }
517
533
  }
534
+ case "docz_upload_image": {
535
+ const read = readImageFile(String(args.file_path));
536
+ if ("error" in read) {
537
+ return fail(read.error);
538
+ }
539
+ const result = await client.uploadImage(read.content, read.filename);
540
+ return ok(
541
+ `\u5DF2\u4E0A\u4F20: ${result.url}
542
+ Markdown \u5F15\u7528: ${markdownImageRef(read.filename, result.url)}`
543
+ );
544
+ }
518
545
  case "docz_upload_file": {
519
546
  const sid = await resolveSpaceId(client, String(args.space));
520
547
  const result = await client.upload(
@@ -691,4 +718,4 @@ Space: ${info.space_name}
691
718
  export {
692
719
  startMcpServer
693
720
  };
694
- //# sourceMappingURL=mcp-S5OSNTRV.js.map
721
+ //# sourceMappingURL=mcp-HXAB75DP.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/mcp.ts"],"sourcesContent":["/**\n * DocSync MCP Server (stdio transport)\n *\n * Usage:\n * docz mcp\n *\n * 环境变量:\n * DOCSYNC_API_TOKEN — 必须\n * DOCSYNC_BASE_URL — 可选,默认 https://docz.zhenguanyu.com\n */\n\nimport { Server } from '@modelcontextprotocol/sdk/server/index.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport {\n CallToolRequestSchema,\n ListToolsRequestSchema,\n} from '@modelcontextprotocol/sdk/types.js';\nimport { ConflictError, DocSyncClient } from './client.js';\nimport { markdownImageRef, parseExpires, readImageFile } from './commands.js';\nimport { getBaseUrl, getToken } from './config.js';\n\nfunction getClient(): DocSyncClient {\n const token = getToken();\n if (!token) {\n throw new Error(\n 'DOCSYNC_API_TOKEN not set. Run `docz login --token <token>` or set the env var.'\n );\n }\n return new DocSyncClient(getBaseUrl(), token);\n}\n\nasync function resolveSpaceId(\n client: DocSyncClient,\n nameOrId: string\n): Promise<string> {\n const space = await client.resolveSpace(nameOrId);\n return space.id;\n}\n\nfunction formatSize(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n}\n\nfunction ok(text: string) {\n return { content: [{ type: 'text' as const, text }] };\n}\n\nfunction fail(err: unknown) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `Error: ${err instanceof Error ? err.message : String(err)}`,\n },\n ],\n isError: true,\n };\n}\n\nexport async function startMcpServer(): Promise<void> {\n const server = new Server(\n { name: 'docz-mcp', version: '0.5.0' },\n { capabilities: { tools: {} } }\n );\n\n server.setRequestHandler(ListToolsRequestSchema, async () => ({\n tools: [\n {\n name: 'docz_list_spaces',\n description: '列出所有可访问的 DocSync Space(个人空间和团队空间)',\n inputSchema: { type: 'object' as const, properties: {} },\n },\n {\n name: 'docz_list_files',\n description: '列出 DocSync Space 中指定目录的文件和文件夹',\n inputSchema: {\n type: 'object' as const,\n properties: {\n space: {\n type: 'string',\n description: 'Space 名称或 ID',\n },\n path: {\n type: 'string',\n description: '目录路径,空字符串表示根目录',\n default: '',\n },\n recursive: {\n type: 'boolean',\n description: '是否递归列出所有子目录',\n default: false,\n },\n },\n required: ['space'],\n },\n },\n {\n name: 'docz_read_file',\n description:\n '读取 DocSync 文件内容(Markdown、CSV、HTML 等文本文件)。返回格式:第一行 [ref: <commit_hash>],空行后是文件内容。保存时请将 ref 值作为 base_ref 传入 docz_save_file 以检测冲突',\n inputSchema: {\n type: 'object' as const,\n properties: {\n space: {\n type: 'string',\n description: 'Space 名称或 ID',\n },\n path: { type: 'string', description: '文件路径' },\n },\n required: ['space', 'path'],\n },\n },\n {\n name: 'docz_save_file',\n description:\n '保存/编辑文档内容(支持冲突检测)。建议先用 docz_read_file 获取 ref,再传入 base_ref 以检测并发冲突。如果返回冲突错误,请重新用 docz_read_file 获取最新内容,重新修改后再保存',\n inputSchema: {\n type: 'object' as const,\n properties: {\n space: {\n type: 'string',\n description: 'Space 名称或 ID',\n },\n path: { type: 'string', description: '文件路径' },\n content: { type: 'string', description: '文件内容' },\n base_ref: {\n type: 'string',\n description: '读取时获得的 ref,用于冲突检测(可选)',\n },\n message: {\n type: 'string',\n description: '提交消息(可选)',\n },\n },\n required: ['space', 'path', 'content'],\n },\n },\n {\n name: 'docz_upload_image',\n description:\n '为 Docz 文档配图:上传本地图片到图床(OSS),返回永久公网 URL。典型工作流:先用本工具上传图片拿到 URL,再把返回的 ![alt](url) 写入文档内容,通过 docz_save_file / docz_upload_file 保存。图片存 OSS 而非 Space(不占配额),URL 无需登录即可访问,分享链接/博客中均可显示。注意:文档配图请用本工具,不要用 docz_upload_file 把图片传进 Space。支持 png/jpg/webp,最大 5MB',\n inputSchema: {\n type: 'object' as const,\n properties: {\n file_path: {\n type: 'string',\n description: '本地图片文件的绝对路径',\n },\n },\n required: ['file_path'],\n },\n },\n {\n name: 'docz_upload_file',\n description: '上传/创建文件到 DocSync Space',\n inputSchema: {\n type: 'object' as const,\n properties: {\n space: {\n type: 'string',\n description: 'Space 名称或 ID',\n },\n path: {\n type: 'string',\n description: '目标目录路径(如 reports)',\n },\n filename: {\n type: 'string',\n description: '文件名(如 summary.md)',\n },\n content: { type: 'string', description: '文件内容' },\n },\n required: ['space', 'filename', 'content'],\n },\n },\n {\n name: 'docz_mkdir',\n description: '在 DocSync Space 中创建文件夹',\n inputSchema: {\n type: 'object' as const,\n properties: {\n space: {\n type: 'string',\n description: 'Space 名称或 ID',\n },\n path: {\n type: 'string',\n description: '要创建的文件夹路径',\n },\n },\n required: ['space', 'path'],\n },\n },\n {\n name: 'docz_delete',\n description: '删除文件或文件夹(进入回收站,30 天内可恢复)',\n inputSchema: {\n type: 'object' as const,\n properties: {\n space: {\n type: 'string',\n description: 'Space 名称或 ID',\n },\n path: { type: 'string', description: '要删除的路径' },\n },\n required: ['space', 'path'],\n },\n },\n {\n name: 'docz_file_history',\n description: '查看文件的变更历史(基于 Git 版本控制)',\n inputSchema: {\n type: 'object' as const,\n properties: {\n space: {\n type: 'string',\n description: 'Space 名称或 ID',\n },\n path: { type: 'string', description: '文件路径' },\n },\n required: ['space'],\n },\n },\n {\n name: 'docz_rollback',\n description: '将文件回滚到指定的历史版本(通过 commit hash)',\n inputSchema: {\n type: 'object' as const,\n properties: {\n space: {\n type: 'string',\n description: 'Space 名称或 ID',\n },\n path: { type: 'string', description: '文件路径' },\n commit: {\n type: 'string',\n description: '目标 commit hash(通过 docz_file_history 获取)',\n },\n },\n required: ['space', 'path', 'commit'],\n },\n },\n {\n name: 'docz_trash',\n description: '查看回收站中的已删除文件列表',\n inputSchema: {\n type: 'object' as const,\n properties: {\n space: {\n type: 'string',\n description: 'Space 名称或 ID',\n },\n },\n required: ['space'],\n },\n },\n {\n name: 'docz_restore',\n description: '从回收站恢复已删除的文件',\n inputSchema: {\n type: 'object' as const,\n properties: {\n space: {\n type: 'string',\n description: 'Space 名称或 ID',\n },\n path: {\n type: 'string',\n description: '被删除的文件路径',\n },\n commit: {\n type: 'string',\n description: '删除时的 commit hash(通过 docz_trash 获取)',\n },\n },\n required: ['space', 'path', 'commit'],\n },\n },\n {\n name: 'docz_list_comments',\n description: '列出文件的评论和回复',\n inputSchema: {\n type: 'object' as const,\n properties: {\n space: {\n type: 'string',\n description: 'Space 名称或 ID',\n },\n path: { type: 'string', description: '文件路径' },\n },\n required: ['space', 'path'],\n },\n },\n {\n name: 'docz_add_comment',\n description:\n '在文件上添加评论。支持 @email 格式提及其他用户。可通过 quote 引用文件中的原文(划线评论),引用内容会在 Web UI 高亮显示',\n inputSchema: {\n type: 'object' as const,\n properties: {\n space: {\n type: 'string',\n description: 'Space 名称或 ID',\n },\n path: { type: 'string', description: '文件路径' },\n content: {\n type: 'string',\n description: '评论内容',\n },\n quote: {\n type: 'string',\n description:\n '引用的原文内容(划线评论)。从文件中复制要评论的文字片段,建议 10 字以上以避免重复匹配',\n },\n },\n required: ['space', 'path', 'content'],\n },\n },\n {\n name: 'docz_reply_comment',\n description: '回复指定评论',\n inputSchema: {\n type: 'object' as const,\n properties: {\n space: {\n type: 'string',\n description: 'Space 名称或 ID',\n },\n comment_id: {\n type: 'number',\n description: '评论 ID',\n },\n content: {\n type: 'string',\n description: '回复内容',\n },\n },\n required: ['space', 'comment_id', 'content'],\n },\n },\n {\n name: 'docz_close_comment',\n description: '关闭评论(标记为已解决)',\n inputSchema: {\n type: 'object' as const,\n properties: {\n space: {\n type: 'string',\n description: 'Space 名称或 ID',\n },\n comment_id: {\n type: 'number',\n description: '评论 ID',\n },\n },\n required: ['space', 'comment_id'],\n },\n },\n {\n name: 'docz_share_create',\n description: '创建文件分享链接',\n inputSchema: {\n type: 'object' as const,\n properties: {\n space: {\n type: 'string',\n description: 'Space 名称或 ID',\n },\n path: { type: 'string', description: '文件路径' },\n expires: {\n type: 'string',\n description: '过期时间,如 7d, 24h',\n },\n userIds: {\n type: 'array',\n items: { type: 'string' },\n description: '可见用户 ID 列表',\n },\n groupIds: {\n type: 'array',\n items: { type: 'string' },\n description: '可见组 ID 列表',\n },\n },\n required: ['space', 'path'],\n },\n },\n {\n name: 'docz_share_list',\n description: '列出空间的分享链接',\n inputSchema: {\n type: 'object' as const,\n properties: {\n space: {\n type: 'string',\n description: 'Space 名称或 ID',\n },\n filePath: {\n type: 'string',\n description: '按文件路径过滤',\n },\n },\n required: ['space'],\n },\n },\n {\n name: 'docz_share_read',\n description: '通过分享 token 读取文件内容',\n inputSchema: {\n type: 'object' as const,\n properties: {\n token: {\n type: 'string',\n description: '分享链接 token',\n },\n },\n required: ['token'],\n },\n },\n {\n name: 'docz_share_info',\n description: '查看分享链接信息',\n inputSchema: {\n type: 'object' as const,\n properties: {\n token: {\n type: 'string',\n description: '分享链接 token',\n },\n },\n required: ['token'],\n },\n },\n {\n name: 'docz_share_delete',\n description: '删除分享链接',\n inputSchema: {\n type: 'object' as const,\n properties: {\n space: {\n type: 'string',\n description: 'Space 名称或 ID',\n },\n linkId: {\n type: 'string',\n description: '分享链接 ID',\n },\n },\n required: ['space', 'linkId'],\n },\n },\n {\n name: 'docz_shortlink',\n description: '获取文件的短链接 URL,可直接在浏览器打开',\n inputSchema: {\n type: 'object' as const,\n properties: {\n space: {\n type: 'string',\n description: 'Space 名称或 ID',\n },\n path: { type: 'string', description: '文件路径' },\n },\n required: ['space', 'path'],\n },\n },\n {\n name: 'docz_diff',\n description: '查看文件或 Space 的变更 diff',\n inputSchema: {\n type: 'object' as const,\n properties: {\n space: {\n type: 'string',\n description: 'Space 名称或 ID',\n },\n path: {\n type: 'string',\n description: '文件路径(空则返回变更文件列表)',\n },\n to: {\n type: 'string',\n description: '目标 commit hash',\n },\n from: {\n type: 'string',\n description: '起始 commit hash(默认 to^)',\n },\n },\n required: ['space', 'to'],\n },\n },\n ],\n }));\n\n server.setRequestHandler(CallToolRequestSchema, async (request) => {\n const args = (request.params.arguments ?? {}) as Record<string, unknown>;\n\n try {\n const client = getClient();\n\n switch (request.params.name) {\n case 'docz_list_spaces': {\n const spaces = await client.listSpaces();\n const lines = spaces.map(\n (s) =>\n `${s.name} (${s.is_private ? '私有' : '团队'}, ${s.member_count} 人) id=${s.id}`\n );\n return ok(lines.join('\\n'));\n }\n\n case 'docz_list_files': {\n const sid = await resolveSpaceId(client, String(args.space));\n const entries = args.recursive\n ? await client.treeFull(sid)\n : await client.ls(sid, String(args.path ?? ''));\n if (entries.length === 0) return ok('(空目录)');\n const lines = entries.map((e) => {\n const size = e.type === 'blob' ? ` (${formatSize(e.size)})` : '';\n return `${e.type === 'tree' ? '📁' : '📄'} ${e.name}${size}`;\n });\n return ok(lines.join('\\n'));\n }\n\n case 'docz_read_file': {\n const sid = await resolveSpaceId(client, String(args.space));\n const result = await client.catWithRef(sid, String(args.path));\n const header = result.ref ? `[ref: ${result.ref}]\\n\\n` : '';\n return ok(header + result.content);\n }\n\n case 'docz_save_file': {\n const sid = await resolveSpaceId(client, String(args.space));\n const savePath = String(args.path);\n const saveContent = String(args.content);\n const saveMessage = args.message ? String(args.message) : undefined;\n const baseRef = args.base_ref ? String(args.base_ref) : undefined;\n\n if (Buffer.byteLength(saveContent, 'utf-8') > 2 * 1024 * 1024) {\n return fail('内容超过 2MB 限制,请使用 docz_upload_file 上传');\n }\n\n try {\n const result = await client.save(sid, savePath, saveContent, {\n baseRef,\n message: saveMessage,\n });\n return ok(`已保存: ${result.path} (ref: ${result.ref})`);\n } catch (err) {\n if (err instanceof ConflictError) {\n return fail(\n `冲突:文件已被他人修改(当前 ref: ${err.detail.current_ref})。请先用 docz_read_file 获取最新内容,重新修改后再保存。`\n );\n }\n throw err;\n }\n }\n\n case 'docz_upload_image': {\n const read = readImageFile(String(args.file_path));\n if ('error' in read) {\n return fail(read.error);\n }\n const result = await client.uploadImage(read.content, read.filename);\n return ok(\n `已上传: ${result.url}\\nMarkdown 引用: ${markdownImageRef(read.filename, result.url)}`\n );\n }\n\n case 'docz_upload_file': {\n const sid = await resolveSpaceId(client, String(args.space));\n const result = await client.upload(\n sid,\n String(args.path ?? ''),\n String(args.filename),\n String(args.content)\n );\n return ok(`已上传: ${result.path}`);\n }\n\n case 'docz_mkdir': {\n const sid = await resolveSpaceId(client, String(args.space));\n await client.mkdir(sid, String(args.path));\n return ok(`已创建: ${args.path}`);\n }\n\n case 'docz_delete': {\n const sid = await resolveSpaceId(client, String(args.space));\n await client.rm(sid, String(args.path));\n return ok(`已删除: ${args.path}(30 天内可从回收站恢复)`);\n }\n\n case 'docz_file_history': {\n const sid = await resolveSpaceId(client, String(args.space));\n const logs = await client.log(\n sid,\n args.path ? String(args.path) : undefined\n );\n if (logs.length === 0) return ok('没有变更历史。');\n const lines = logs.map((l) => `${l.hash} ${l.date} ${l.message}`);\n return ok(lines.join('\\n'));\n }\n\n case 'docz_rollback': {\n const sid = await resolveSpaceId(client, String(args.space));\n await client.rollback(sid, String(args.path), String(args.commit));\n return ok(\n `已回滚: ${args.path} → ${String(args.commit).substring(0, 7)}`\n );\n }\n\n case 'docz_trash': {\n const sid = await resolveSpaceId(client, String(args.space));\n const items = await client.trash(sid);\n if (items.length === 0) return ok('回收站为空。');\n const lines = items.map(\n (t) =>\n `${t.path} 删除于 ${t.deleted_at} commit: ${t.commit.substring(0, 7)}`\n );\n return ok(lines.join('\\n'));\n }\n\n case 'docz_restore': {\n const sid = await resolveSpaceId(client, String(args.space));\n await client.restore(sid, String(args.path), String(args.commit));\n return ok(`已恢复: ${args.path}`);\n }\n\n case 'docz_list_comments': {\n const sid = await resolveSpaceId(client, String(args.space));\n const comments = await client.listComments(sid, String(args.path));\n if (comments.length === 0) return ok('没有评论。');\n const lines = comments.map((c) => {\n const status = c.is_closed ? ' [已关闭]' : '';\n const quote = c.target_content ? `\\n > ${c.target_content}` : '';\n let text = `#${c.id} ${c.user_name}${status}:${quote}\\n ${c.content}`;\n for (const r of c.replies) {\n text += `\\n ↳ ${r.user_name}: ${r.content}`;\n }\n return text;\n });\n return ok(lines.join('\\n\\n'));\n }\n\n case 'docz_add_comment': {\n const sid = await resolveSpaceId(client, String(args.space));\n const quote = args.quote ? String(args.quote) : undefined;\n const c = await client.createComment(\n sid,\n String(args.path),\n String(args.content),\n { quote }\n );\n return ok(`评论 #${c.id} 已创建`);\n }\n\n case 'docz_reply_comment': {\n const sid = await resolveSpaceId(client, String(args.space));\n const r = await client.replyComment(\n sid,\n Number(args.comment_id),\n String(args.content)\n );\n return ok(`回复 #${r.id} 已创建`);\n }\n\n case 'docz_close_comment': {\n const sid = await resolveSpaceId(client, String(args.space));\n await client.closeComment(sid, Number(args.comment_id));\n return ok(`评论 #${args.comment_id} 已关闭`);\n }\n\n case 'docz_share_create': {\n const sharePath = String(args.path ?? '');\n if (!sharePath) return fail('path is required');\n const sid = await resolveSpaceId(client, String(args.space));\n const opts: {\n expiresAt?: string;\n userIds?: string[];\n groupIds?: string[];\n } = {};\n if (args.expires) opts.expiresAt = parseExpires(String(args.expires));\n if (args.userIds) opts.userIds = args.userIds as string[];\n if (args.groupIds) opts.groupIds = args.groupIds as string[];\n const link = await client.createShareLink(sid, sharePath, opts);\n return ok(\n `已创建分享链接:\\ntoken: ${link.token}\\nurl: ${getBaseUrl()}/share/${link.token}\\n过期: ${link.expires_at ?? '永不'}`\n );\n }\n\n case 'docz_share_list': {\n const sid = await resolveSpaceId(client, String(args.space));\n const links = await client.listShareLinks(\n sid,\n args.filePath ? String(args.filePath) : undefined\n );\n if (links.length === 0) return ok('没有分享链接。');\n const lines = links.map(\n (l) =>\n `${l.token} ${l.file_path} 过期: ${l.expires_at ?? '永不'} 创建者: ${l.created_by_name ?? l.created_by_email ?? l.created_by}`\n );\n return ok(lines.join('\\n'));\n }\n\n case 'docz_share_read': {\n const content = await client.getSharedFile(String(args.token));\n return ok(content);\n }\n\n case 'docz_share_info': {\n const info = await client.getSharedFileInfo(String(args.token));\n return ok(\n `文件: ${info.file_path}\\nSpace: ${info.space_name}\\n分享者: ${info.created_by_name}\\n过期: ${info.expires_at ?? '永不'}`\n );\n }\n\n case 'docz_share_delete': {\n const sid = await resolveSpaceId(client, String(args.space));\n await client.deleteShareLink(sid, String(args.linkId));\n return ok(`已删除分享链接: ${args.linkId}`);\n }\n\n case 'docz_shortlink': {\n const sid = await resolveSpaceId(client, String(args.space));\n const ref = await client.getFileRef(sid, String(args.path));\n return ok(ref.url);\n }\n\n case 'docz_diff': {\n const sid = await resolveSpaceId(client, String(args.space));\n const path = args.path ? String(args.path) : '';\n const from = args.from ? String(args.from) : undefined;\n if (path) {\n const result = await client.diffFile(\n sid,\n path,\n String(args.to),\n from\n );\n return ok(result.diff || '没有变更。');\n }\n const result = await client.diffSummary(sid, String(args.to), from);\n if (result.files.length === 0) return ok('没有变更。');\n const lines = result.files.map((f) => `${f.status} ${f.path}`);\n return ok(lines.join('\\n'));\n }\n\n default:\n return fail(`Unknown tool: ${request.params.name}`);\n }\n } catch (err) {\n return fail(err);\n }\n });\n\n const transport = new StdioServerTransport();\n await server.connect(transport);\n}\n"],"mappings":"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","names":["result"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "docz-cli",
3
- "version": "0.8.1",
3
+ "version": "0.9.0",
4
4
  "description": "DocSync CLI — read and write company documents",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/client.ts","../src/config.ts","../src/commands.ts"],"sourcesContent":["/**\n * DocSync API Client\n *\n * DocSync 底层是 Git 仓库,每个 Space = 一个 Git repo。\n * 认证:Authorization: Bearer {token}(支持 JWT 和永久 API Token)。\n */\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface Space {\n id: string;\n name: string;\n slug?: string;\n owner_id: string;\n is_private: boolean;\n created_at: string;\n member_count: number;\n}\n\nexport interface TreeEntry {\n name: string;\n type: 'blob' | 'tree';\n size: number;\n}\n\nexport interface LogEntry {\n hash: string;\n author: string;\n message: string;\n date: string;\n num_files: number;\n}\n\nexport interface TrashEntry {\n path: string;\n deleted_by: string;\n deleted_at: string;\n commit: string;\n}\n\nexport interface User {\n id: string;\n email: string;\n name: string;\n is_admin: boolean;\n is_active: boolean;\n created_at: string;\n}\n\nexport interface ShareLink {\n id: string;\n token: string;\n space_id: string;\n file_path: string;\n created_by: string;\n created_by_name?: string;\n created_by_email?: string;\n expires_at: string | null;\n created_at: string;\n user_ids?: string[];\n group_ids?: string[];\n}\n\nexport interface ShareFileInfo {\n file_path: string;\n file_name: string;\n space_name: string;\n created_by_name: string;\n expires_at: string | null;\n}\n\nexport interface DiffResponse {\n from: string;\n to: string;\n path: string;\n diff: string;\n old_body: string;\n new_body: string;\n}\n\nexport interface DiffFileEntry {\n path: string;\n status: string;\n}\n\nexport interface DiffSummary {\n from: string;\n to: string;\n files: DiffFileEntry[];\n}\n\nexport interface FileRef {\n id: string;\n space_id: string;\n path: string;\n}\n\nexport interface CatResult {\n content: string;\n ref: string;\n}\n\nexport interface SaveResult {\n path: string;\n ref: string;\n}\n\nexport interface SaveConflict {\n error: 'conflict';\n current_ref: string;\n path: string;\n}\n\nexport interface Comment {\n id: number;\n space_id: string;\n file_path: string;\n comment_type: string;\n target_type: string;\n target_selector: string;\n target_content: string;\n content: string;\n user_id: string;\n user_name: string;\n user_email: string;\n is_closed: boolean;\n created_at: string;\n updated_at: string;\n replies: CommentReply[];\n}\n\nexport interface CommentReply {\n id: number;\n comment_id: number;\n content: string;\n user_id: string;\n user_name: string;\n user_email: string;\n created_at: string;\n updated_at: string;\n}\n\n// ---------------------------------------------------------------------------\n// Errors\n// ---------------------------------------------------------------------------\n\nexport class ConflictError extends Error {\n constructor(public readonly detail: SaveConflict) {\n super(\n 'Conflict: file has been modified by others. Please re-read the latest content and re-apply your changes.'\n );\n this.name = 'ConflictError';\n }\n}\n\n// ---------------------------------------------------------------------------\n// Client\n// ---------------------------------------------------------------------------\n\nexport class DocSyncClient {\n constructor(\n private baseUrl: string,\n private token: string\n ) {\n this.baseUrl = baseUrl.replace(/\\/$/, '');\n }\n\n private async request<T>(path: string, init?: RequestInit): Promise<T> {\n const res = await fetch(`${this.baseUrl}${path}`, {\n ...init,\n headers: {\n Authorization: `Bearer ${this.token}`,\n ...init?.headers,\n },\n });\n\n if (!res.ok) {\n const body = await res.text().catch(() => '');\n throw new Error(`${res.status} ${res.statusText}: ${body}`.trim());\n }\n\n const ct = res.headers.get('content-type') ?? '';\n if (ct.includes('application/json')) return res.json() as Promise<T>;\n return res.text() as unknown as T;\n }\n\n // --- Auth ---\n async me(): Promise<User> {\n return this.request('/api/auth/me');\n }\n\n // --- Spaces ---\n async listSpaces(): Promise<Space[]> {\n return this.request('/api/spaces');\n }\n\n async resolveSpace(nameOrId: string): Promise<Space> {\n const spaces = await this.listSpaces();\n const input = nameOrId.toLowerCase();\n\n // 1-3: exact id / exact name / case-insensitive name\n const exact = spaces.find(\n (s) =>\n s.id === nameOrId ||\n s.name === nameOrId ||\n s.name.toLowerCase() === input\n );\n if (exact) return exact;\n\n // 4: slug exact match\n const bySlug = spaces.find((s) => s.slug === nameOrId);\n if (bySlug) return bySlug;\n\n // 5: name suffix match (e.g. \"研发\" matches \"G160-研发\")\n const suffixMatches = spaces.filter(\n (s) =>\n s.name.length > nameOrId.length && s.name.toLowerCase().endsWith(input)\n );\n if (suffixMatches.length === 1) return suffixMatches[0];\n if (suffixMatches.length > 1) {\n const candidates = suffixMatches.map((s) => s.name).join(', ');\n throw new Error(\n `Space \"${nameOrId}\" is ambiguous, matches: ${candidates}. Use the full name or UUID.`\n );\n }\n\n const available = spaces\n .map((s) => (s.slug ? `${s.name} (${s.slug})` : s.name))\n .join(', ');\n throw new Error(`Space \"${nameOrId}\" not found. Available: ${available}`);\n }\n\n // --- Tree ---\n async ls(spaceId: string, path = ''): Promise<TreeEntry[]> {\n return this.request(\n `/api/spaces/${spaceId}/tree?path=${encodeURIComponent(path)}`\n );\n }\n\n async treeFull(spaceId: string): Promise<TreeEntry[]> {\n return this.request(`/api/spaces/${spaceId}/tree/full`);\n }\n\n // --- Blob ---\n async cat(spaceId: string, filepath: string): Promise<string> {\n return this.request(\n `/api/spaces/${spaceId}/blob/${encodeURIComponent(filepath)}`\n );\n }\n\n async catWithRef(spaceId: string, filepath: string): Promise<CatResult> {\n const res = await fetch(\n `${this.baseUrl}/api/spaces/${spaceId}/blob/${encodeURIComponent(filepath)}`,\n { headers: { Authorization: `Bearer ${this.token}` } }\n );\n if (!res.ok) {\n const body = await res.text().catch(() => '');\n throw new Error(`${res.status} ${res.statusText}: ${body}`.trim());\n }\n const content = await res.text();\n const ref = res.headers.get('X-Git-Ref') ?? '';\n return { content, ref };\n }\n\n // --- Write ---\n async upload(\n spaceId: string,\n dir: string,\n filename: string,\n content: string | Buffer\n ): Promise<{ path: string }> {\n const blob =\n typeof content === 'string'\n ? new Blob([content], { type: 'application/octet-stream' })\n : new Blob([content], { type: 'application/octet-stream' });\n const form = new FormData();\n form.append('file', blob, filename);\n form.append('path', dir);\n return this.request(`/api/spaces/${spaceId}/files/upload`, {\n method: 'POST',\n body: form,\n });\n }\n\n async save(\n spaceId: string,\n path: string,\n content: string,\n opts?: { baseRef?: string; message?: string }\n ): Promise<SaveResult> {\n const body: Record<string, string> = { path, content };\n if (opts?.baseRef) body.base_ref = opts.baseRef;\n if (opts?.message) body.message = opts.message;\n\n const res = await fetch(\n `${this.baseUrl}/api/spaces/${spaceId}/files/save`,\n {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${this.token}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(body),\n }\n );\n\n if (res.status === 409) {\n const data = (await res.json()) as SaveConflict;\n throw new ConflictError(data);\n }\n\n if (!res.ok) {\n const text = await res.text().catch(() => '');\n throw new Error(`${res.status} ${res.statusText}: ${text}`.trim());\n }\n\n return res.json() as Promise<SaveResult>;\n }\n\n async mkdir(spaceId: string, path: string): Promise<void> {\n await this.request(`/api/spaces/${spaceId}/files/mkdir`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ path }),\n });\n }\n\n async rm(spaceId: string, path: string): Promise<void> {\n await this.request(`/api/spaces/${spaceId}/files/delete`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ path }),\n });\n }\n\n async mv(spaceId: string, from: string, to: string): Promise<void> {\n await this.request(`/api/spaces/${spaceId}/files/rename`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ old_path: from, new_path: to }),\n });\n }\n\n async rollback(\n spaceId: string,\n filePath: string,\n commitHash: string\n ): Promise<void> {\n await this.request(`/api/spaces/${spaceId}/files/rollback`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ file_path: filePath, commit_hash: commitHash }),\n });\n }\n\n // --- History ---\n async log(spaceId: string, filepath?: string): Promise<LogEntry[]> {\n const path = filepath\n ? `/api/spaces/${spaceId}/log/${encodeURIComponent(filepath)}`\n : `/api/spaces/${spaceId}/log/`;\n return this.request(path);\n }\n\n // --- Trash ---\n async trash(spaceId: string): Promise<TrashEntry[]> {\n return this.request(`/api/spaces/${spaceId}/trash`);\n }\n\n async restore(spaceId: string, path: string, commit: string): Promise<void> {\n await this.request(`/api/spaces/${spaceId}/trash/restore`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ path, commit }),\n });\n }\n\n // --- Comments ---\n async listComments(spaceId: string, filePath: string): Promise<Comment[]> {\n return this.request(\n `/api/spaces/${spaceId}/comments?path=${encodeURIComponent(filePath)}`\n );\n }\n\n async createComment(\n spaceId: string,\n filePath: string,\n content: string,\n opts?: { quote?: string }\n ): Promise<Comment> {\n const body: Record<string, string> = { file_path: filePath, content };\n if (opts?.quote) {\n body.comment_type = 'text';\n body.target_type = 'selection';\n body.target_content = opts.quote;\n body.target_selector = JSON.stringify({\n startOffset: 0,\n endOffset: 0,\n text: opts.quote,\n prefix: '',\n suffix: '',\n });\n }\n return this.request(`/api/spaces/${spaceId}/comments`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n });\n }\n\n async replyComment(\n spaceId: string,\n commentId: number,\n content: string\n ): Promise<CommentReply> {\n return this.request(\n `/api/spaces/${spaceId}/comments/${commentId}/replies`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ content }),\n }\n );\n }\n\n async closeComment(spaceId: string, commentId: number): Promise<Comment> {\n return this.request(`/api/spaces/${spaceId}/comments/${commentId}`, {\n method: 'PUT',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ is_closed: true }),\n });\n }\n\n async deleteComment(spaceId: string, commentId: number): Promise<void> {\n await this.request(`/api/spaces/${spaceId}/comments/${commentId}`, {\n method: 'DELETE',\n });\n }\n\n // --- Share Links ---\n async createShareLink(\n spaceId: string,\n filePath: string,\n opts?: { expiresAt?: string; userIds?: string[]; groupIds?: string[] }\n ): Promise<ShareLink> {\n const body: Record<string, unknown> = { file_path: filePath };\n if (opts?.expiresAt) body.expires_at = opts.expiresAt;\n if (opts?.userIds?.length) body.user_ids = opts.userIds;\n if (opts?.groupIds?.length) body.group_ids = opts.groupIds;\n return this.request(`/api/spaces/${spaceId}/share-links`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n });\n }\n\n async listShareLinks(\n spaceId: string,\n filePath?: string\n ): Promise<ShareLink[]> {\n const q = filePath ? `?file_path=${encodeURIComponent(filePath)}` : '';\n return this.request(`/api/spaces/${spaceId}/share-links${q}`);\n }\n\n async updateShareLink(\n spaceId: string,\n linkId: string,\n opts: { expiresAt?: string; userIds?: string[]; groupIds?: string[] }\n ): Promise<ShareLink> {\n const body: Record<string, unknown> = {};\n if (opts.expiresAt !== undefined) body.expires_at = opts.expiresAt;\n if (opts.userIds) body.user_ids = opts.userIds;\n if (opts.groupIds) body.group_ids = opts.groupIds;\n return this.request(`/api/spaces/${spaceId}/share-links/${linkId}`, {\n method: 'PUT',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n });\n }\n\n async deleteShareLink(spaceId: string, linkId: string): Promise<void> {\n await this.request(`/api/spaces/${spaceId}/share-links/${linkId}`, {\n method: 'DELETE',\n });\n }\n\n async getSharedFile(token: string): Promise<string> {\n return this.request(`/api/share/${token}`);\n }\n\n async getSharedFileInfo(token: string): Promise<ShareFileInfo> {\n return this.request(`/api/share/${token}/info`);\n }\n\n // --- Diff ---\n async diffFile(\n spaceId: string,\n filePath: string,\n to: string,\n from?: string\n ): Promise<DiffResponse> {\n const params = new URLSearchParams({ to });\n if (from) params.set('from', from);\n return this.request(\n `/api/spaces/${spaceId}/diff/${encodeURIComponent(filePath)}?${params}`\n );\n }\n\n async diffSummary(\n spaceId: string,\n to: string,\n from?: string\n ): Promise<DiffSummary> {\n const params = new URLSearchParams({ to });\n if (from) params.set('from', from);\n return this.request(`/api/spaces/${spaceId}/diff?${params}`);\n }\n\n // --- File Ref ---\n async getFileRef(\n spaceId: string,\n path: string\n ): Promise<{\n id: string;\n space_id: string;\n slug: string;\n path: string;\n is_dir: boolean;\n url: string;\n }> {\n return this.request(\n `/api/spaces/${spaceId}/file-ref?path=${encodeURIComponent(path)}`\n );\n }\n\n // --- Resolve short URLs ---\n async resolveBySlug(slug: string): Promise<Space> {\n return this.request(`/api/spaces/by-slug/${encodeURIComponent(slug)}`);\n }\n\n async resolveFileRef(fileId: string): Promise<FileRef> {\n return this.request(`/api/file-refs/${encodeURIComponent(fileId)}`);\n }\n}\n","/**\n * 配置管理\n *\n * 优先级:环境变量 > ~/.docz/config.json\n */\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\n\nconst CONFIG_DIR = join(homedir(), '.docz');\nconst CONFIG_FILE = join(CONFIG_DIR, 'config.json');\n\ninterface Config {\n base_url?: string;\n token?: string;\n}\n\nfunction readConfig(): Config {\n if (!existsSync(CONFIG_FILE)) return {};\n try {\n return JSON.parse(readFileSync(CONFIG_FILE, 'utf-8'));\n } catch {\n return {};\n }\n}\n\nfunction writeConfig(config: Config): void {\n mkdirSync(CONFIG_DIR, { recursive: true });\n writeFileSync(CONFIG_FILE, `${JSON.stringify(config, null, 2)}\\n`);\n}\n\nexport function getBaseUrl(): string {\n return (\n process.env.DOCSYNC_BASE_URL ??\n readConfig().base_url ??\n 'https://docz.zhenguanyu.com'\n );\n}\n\nexport function getToken(): string | undefined {\n return process.env.DOCSYNC_API_TOKEN ?? readConfig().token;\n}\n\nexport function saveConfig(baseUrl: string, token: string): void {\n writeConfig({ base_url: baseUrl, token });\n}\n\nexport function getConfigPath(): string {\n return CONFIG_FILE;\n}\n","/**\n * CLI Commands\n */\n\nimport { readFileSync } from 'node:fs';\nimport { basename } from 'node:path';\nimport type { Command } from 'commander';\nimport { ConflictError, DocSyncClient } from './client.js';\nimport { getBaseUrl, getConfigPath, getToken, saveConfig } from './config.js';\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction getClient(): DocSyncClient {\n const token = getToken();\n if (!token) {\n console.error(\n 'Error: No token configured.\\n' +\n 'Run `docz login` or set DOCSYNC_API_TOKEN environment variable.'\n );\n process.exit(1);\n }\n return new DocSyncClient(getBaseUrl(), token);\n}\n\n/** Parse \"space:path\" or \"space path\" format */\nexport function parseTarget(args: string[]): { space: string; path: string } {\n if (args.length === 0) {\n console.error(\n 'Error: space is required. Usage: docz <cmd> <space>[:<path>]'\n );\n process.exit(1);\n }\n const first = args[0];\n if (first.includes(':')) {\n const [space, ...rest] = first.split(':');\n return { space, path: rest.join(':') };\n }\n return { space: first, path: args.slice(1).join(' ') };\n}\n\nfunction formatSize(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n}\n\n// Share URL: /share/{token}\nconst SHARE_URL_RE = /\\/share\\/([^/?\\s]+)/;\n\n/** Resolve slug: try local spaces cache first, then API */\nasync function resolveSlug(\n client: DocSyncClient,\n slug: string\n): Promise<{ id: string }> {\n try {\n const spaces = await client.listSpaces();\n const found = spaces.find((s) => s.slug === slug);\n if (found) return found;\n } catch {\n // fall through to by-slug API\n }\n return client.resolveBySlug(slug);\n}\n\n/**\n * Detect if input is a URL and resolve it to { spaceId, path }.\n * Supports:\n * /s/{slug}/f/{fileId} — short URL with fileId\n * /s/{slug}[/path/to/file] — slug URL with optional path\n * /spaces/{spaceId}[/path/...] — legacy URL\n * Returns null if not a recognized DocSync URL.\n */\nasync function resolveUrl(\n client: DocSyncClient,\n input: string\n): Promise<{ spaceId: string; path: string } | null> {\n let pathname: string;\n try {\n pathname = new URL(input).pathname;\n } catch {\n return null;\n }\n\n // /s/{slug}/f/{fileId}\n const fileMatch = pathname.match(/^\\/s\\/([^/]+)\\/f\\/([^/]+)$/);\n if (fileMatch) {\n const [, slug, fileId] = fileMatch;\n const space = await resolveSlug(client, slug);\n const ref = await client.resolveFileRef(fileId);\n return { spaceId: space.id, path: ref.path };\n }\n\n // /s/{slug}[/path/to/file]\n const slugMatch = pathname.match(/^\\/s\\/([^/]+)(\\/.*)?$/);\n if (slugMatch) {\n const [, slug, rest] = slugMatch;\n const space = await resolveSlug(client, slug);\n const filePath = rest ? decodeURIComponent(rest.slice(1)) : '';\n return { spaceId: space.id, path: filePath };\n }\n\n // /spaces/{spaceId}[/path/to/file] (legacy)\n const legacyMatch = pathname.match(/^\\/spaces\\/([^/]+)(\\/.*)?$/);\n if (legacyMatch) {\n const [, spaceId, rest] = legacyMatch;\n const filePath = rest ? decodeURIComponent(rest.slice(1)) : '';\n return { spaceId, path: filePath };\n }\n\n return null;\n}\n\n/**\n * Resolve target: if it's a URL, resolve it; otherwise use parseTarget + resolveSpace.\n */\nexport async function resolveTarget(\n client: DocSyncClient,\n args: string[]\n): Promise<{ spaceId: string; path: string }> {\n const first = args[0];\n if (first && (first.startsWith('http://') || first.startsWith('https://'))) {\n const result = await resolveUrl(client, first);\n if (result) return result;\n throw new Error(\n `Unrecognized DocSync URL: ${first}\\nExpected: /s/{slug}[/f/{fileId}], /s/{slug}[/path], or /spaces/{id}[/path]`\n );\n }\n const { space, path } = parseTarget(args);\n const s = await client.resolveSpace(space);\n return { spaceId: s.id, path };\n}\n\n/**\n * Resolve a space argument that may be a name, UUID, or URL.\n * For URLs, delegates to resolveUrl and extracts the spaceId.\n */\nexport async function resolveSpaceArg(\n client: DocSyncClient,\n input: string\n): Promise<{ id: string }> {\n if (input.startsWith('http://') || input.startsWith('https://')) {\n const result = await resolveUrl(client, input);\n if (result) return { id: result.spaceId };\n throw new Error(\n `Unrecognized DocSync URL: ${input}\\nExpected: /s/{slug}[/f/{fileId}], /s/{slug}[/path], or /spaces/{id}[/path]`\n );\n }\n return client.resolveSpace(input);\n}\n\n/** Parse relative duration (7d, 24h, 30d) to RFC3339 */\nexport function parseExpires(value: string): string {\n const match = value.match(/^(\\d+)([dh])$/);\n if (!match)\n throw new Error(\n `Invalid expires format: \"${value}\". Use e.g. 7d, 24h, 30d`\n );\n const [, num, unit] = match;\n const ms = unit === 'd' ? Number(num) * 86400000 : Number(num) * 3600000;\n return new Date(Date.now() + ms).toISOString();\n}\n\n/** Extract share token from URL or return as-is */\nfunction extractShareToken(input: string): string {\n const m = input.match(SHARE_URL_RE);\n if (m) return m[1];\n return input;\n}\n\n/** Read all of stdin into a string */\nasync function readStdin(): Promise<string> {\n const chunks: Buffer[] = [];\n for await (const chunk of process.stdin) {\n chunks.push(chunk as Buffer);\n }\n return Buffer.concat(chunks).toString('utf-8');\n}\n\nconst MAX_SAVE_SIZE = 2 * 1024 * 1024; // 2MB\n\n// ---------------------------------------------------------------------------\n// Commands\n// ---------------------------------------------------------------------------\n\nexport function registerCommands(program: Command): void {\n // --- login ---\n program\n .command('login')\n .description('Configure DocSync credentials')\n .option('-u, --url <url>', 'DocSync server URL')\n .option('-t, --token <token>', 'API token')\n .action(async (opts) => {\n const url = opts.url ?? getBaseUrl();\n const token = opts.token;\n if (!token) {\n console.error(\n 'Error: --token is required.\\n' +\n 'Get one at: ' +\n url +\n ' → Settings → API Tokens'\n );\n process.exit(1);\n }\n const client = new DocSyncClient(url, token);\n try {\n const user = await client.me();\n saveConfig(url, token);\n console.log(`Logged in as ${user.name} (${user.email})`);\n console.log(`Config saved to ${getConfigPath()}`);\n } catch (err) {\n console.error(\n `Error: ${err instanceof Error ? err.message : String(err)}`\n );\n process.exit(1);\n }\n });\n\n // --- whoami ---\n program\n .command('whoami')\n .description('Show current user')\n .action(async () => {\n const client = getClient();\n const user = await client.me();\n console.log(`${user.name} (${user.email})`);\n });\n\n // --- spaces ---\n program\n .command('spaces')\n .description('List all accessible spaces')\n .action(async () => {\n const client = getClient();\n const spaces = await client.listSpaces();\n for (const s of spaces) {\n const tag = s.is_private ? 'private' : 'team';\n console.log(\n `${s.name}\\t${tag}\\t${s.member_count} members\\t${s.id}\\t${s.slug ?? ''}`\n );\n }\n });\n\n // --- ls ---\n program\n .command('ls')\n .description('List files — docz ls <space>[:<path>] or <url>')\n .argument('<target...>')\n .option('-R, --recursive', 'Recursively list all files')\n .action(async (args: string[], opts: { recursive?: boolean }) => {\n const client = getClient();\n const { spaceId, path } = await resolveTarget(client, args);\n const entries = opts.recursive\n ? await client.treeFull(spaceId)\n : await client.ls(spaceId, path);\n if (entries.length === 0) {\n console.log('(empty)');\n return;\n }\n for (const e of entries) {\n if (e.type === 'tree') {\n console.log(`${e.name}/`);\n } else {\n console.log(`${e.name}\\t${formatSize(e.size)}`);\n }\n }\n });\n\n // --- cat ---\n program\n .command('cat')\n .description('Read file content — docz cat <space>:<path> or <url>')\n .argument('<target...>')\n .option('--ref', 'Also output Git ref to stderr')\n .action(async (args: string[], opts: { ref?: boolean }) => {\n const client = getClient();\n const { spaceId, path } = await resolveTarget(client, args);\n if (!path) {\n console.error(\n 'Error: file path is required. Usage: docz cat <space>:<path>'\n );\n process.exit(1);\n }\n if (opts.ref) {\n const result = await client.catWithRef(spaceId, path);\n console.error(`ref: ${result.ref}`);\n process.stdout.write(result.content);\n } else {\n const content = await client.cat(spaceId, path);\n process.stdout.write(content);\n }\n });\n\n // --- upload ---\n program\n .command('upload')\n .description(\n 'Upload file — docz upload <local-file> <space>[:<dir>] or <url>'\n )\n .argument('<file>', 'Local file to upload')\n .argument('<target...>')\n .action(async (file: string, args: string[]) => {\n const client = getClient();\n const { spaceId, path: dir } = await resolveTarget(client, args);\n const content = readFileSync(file);\n const filename = basename(file);\n const targetDir = dir || '';\n const result = await client.upload(spaceId, targetDir, filename, content);\n console.log(`Uploaded: ${result.path}`);\n });\n\n // --- write ---\n program\n .command('write')\n .description(\n 'Write content to file — docz write <space>:<path> <content> or <url> <content>'\n )\n .argument('<target>', 'space:dir/filename.md or short URL')\n .argument('<content>', 'File content (or - for stdin)')\n .option('--force', 'Skip conflict detection')\n .option('-m, --message <msg>', 'Custom commit message')\n .action(\n async (\n target: string,\n content: string,\n opts: { force?: boolean; message?: string }\n ) => {\n const client = getClient();\n const { spaceId, path } = await resolveTarget(client, [target]);\n if (!path) {\n console.error(\n 'Error: path is required. Usage: docz write <space>:<dir/filename> <content>'\n );\n process.exit(1);\n }\n const body = content === '-' ? await readStdin() : content;\n\n if (Buffer.byteLength(body, 'utf-8') > MAX_SAVE_SIZE) {\n console.error(\n 'Error: content exceeds 2MB limit. Use `docz upload` for large files.'\n );\n process.exit(1);\n }\n\n let baseRef: string | undefined;\n if (!opts.force) {\n try {\n const existing = await client.catWithRef(spaceId, path);\n baseRef = existing.ref;\n } catch (err) {\n const msg = err instanceof Error ? err.message : '';\n if (!msg.includes('404')) throw err;\n }\n }\n\n try {\n const result = await client.save(spaceId, path, body, {\n baseRef,\n message: opts.message,\n });\n console.log(`Written: ${result.path} (ref: ${result.ref})`);\n } catch (err) {\n if (err instanceof ConflictError) {\n console.error(\n 'Error: file was modified by someone else. Please re-read the latest content and try again.'\n );\n process.exit(1);\n }\n throw err;\n }\n }\n );\n\n // --- mkdir ---\n program\n .command('mkdir')\n .description('Create folder — docz mkdir <space>:<path> or <url>')\n .argument('<target...>')\n .action(async (args: string[]) => {\n const client = getClient();\n const { spaceId, path } = await resolveTarget(client, args);\n if (!path) {\n console.error('Error: path is required.');\n process.exit(1);\n }\n await client.mkdir(spaceId, path);\n console.log(`Created: ${path}`);\n });\n\n // --- rm ---\n program\n .command('rm')\n .description('Delete file/folder — docz rm <space>:<path> or <url>')\n .argument('<target...>')\n .action(async (args: string[]) => {\n const client = getClient();\n const { spaceId, path } = await resolveTarget(client, args);\n if (!path) {\n console.error('Error: path is required.');\n process.exit(1);\n }\n await client.rm(spaceId, path);\n console.log(`Deleted: ${path} (recoverable from trash for 30 days)`);\n });\n\n // --- mv ---\n program\n .command('mv')\n .description('Rename/move — docz mv <space>:<from> <to> or <url> <to>')\n .argument('<target>', 'space:old-path or short URL')\n .argument('<to>', 'new-path')\n .action(async (target: string, to: string) => {\n const client = getClient();\n const { spaceId, path: from } = await resolveTarget(client, [target]);\n if (!from) {\n console.error('Error: source path is required.');\n process.exit(1);\n }\n await client.mv(spaceId, from, to);\n console.log(`Moved: ${from} → ${to}`);\n });\n\n // --- log ---\n program\n .command('log')\n .description('Show change history — docz log <space>[:<path>] or <url>')\n .argument('<target...>')\n .action(async (args: string[]) => {\n const client = getClient();\n const { spaceId, path } = await resolveTarget(client, args);\n const logs = await client.log(spaceId, path || undefined);\n if (logs.length === 0) {\n console.log('No history.');\n return;\n }\n for (const l of logs) {\n console.log(`${l.hash} ${l.date} ${l.message}`);\n }\n });\n\n // --- rollback ---\n program\n .command('rollback')\n .description(\n 'Rollback file to a previous version — docz rollback <space>:<path> <commit> or <url> <commit>'\n )\n .argument('<target>', 'space:path or short URL')\n .argument('<commit>', 'Commit hash to rollback to')\n .action(async (target: string, commit: string) => {\n const client = getClient();\n const { spaceId, path } = await resolveTarget(client, [target]);\n if (!path) {\n console.error('Error: file path is required.');\n process.exit(1);\n }\n await client.rollback(spaceId, path, commit);\n console.log(`Rolled back: ${path} → ${commit.substring(0, 7)}`);\n });\n\n // --- trash ---\n program\n .command('trash')\n .description('Show deleted files — docz trash <space>')\n .argument('<space>')\n .action(async (spaceName: string) => {\n const client = getClient();\n const s = await resolveSpaceArg(client, spaceName);\n const items = await client.trash(s.id);\n if (items.length === 0) {\n console.log('Trash is empty.');\n return;\n }\n for (const t of items) {\n console.log(\n `${t.path}\\tdeleted ${t.deleted_at}\\t${t.commit.substring(0, 7)}`\n );\n }\n });\n\n // --- restore ---\n program\n .command('restore')\n .description(\n 'Restore file from trash — docz restore <space>:<path> <commit> or <url> <commit>'\n )\n .argument('<target>', 'space:path or short URL')\n .argument('<commit>', 'Commit hash from trash listing')\n .action(async (target: string, commit: string) => {\n const client = getClient();\n const { spaceId, path } = await resolveTarget(client, [target]);\n if (!path) {\n console.error('Error: path is required.');\n process.exit(1);\n }\n await client.restore(spaceId, path, commit);\n console.log(`Restored: ${path}`);\n });\n\n // --- comment ---\n const comment = program\n .command('comment')\n .description('Manage file comments');\n\n comment\n .command('list')\n .description('List comments — docz comment list <space>:<path>')\n .argument('<target...>')\n .action(async (args: string[]) => {\n const client = getClient();\n const { spaceId, path } = await resolveTarget(client, args);\n if (!path) {\n console.error('Error: file path is required.');\n process.exit(1);\n }\n const comments = await client.listComments(spaceId, path);\n if (comments.length === 0) {\n console.log('No comments.');\n return;\n }\n for (const c of comments) {\n const status = c.is_closed ? ' [closed]' : '';\n console.log(`#${c.id} ${c.user_name} (${c.created_at})${status}`);\n if (c.target_content) {\n console.log(` > ${c.target_content}`);\n }\n console.log(` ${c.content}`);\n for (const r of c.replies) {\n console.log(` → ${r.user_name}: ${r.content}`);\n }\n }\n });\n\n comment\n .command('add')\n .description(\n 'Add comment — docz comment add <space>:<path> <content> or <url> <content>'\n )\n .argument('<target>', 'space:path or short URL')\n .argument('<content>', 'Comment text (or - for stdin)')\n .option(\n '--quote <text>',\n 'Quote text from the file (selection comment). The quoted text will be highlighted in Web UI'\n )\n .action(\n async (target: string, content: string, opts: { quote?: string }) => {\n const client = getClient();\n const { spaceId, path } = await resolveTarget(client, [target]);\n if (!path) {\n console.error('Error: file path is required.');\n process.exit(1);\n }\n const body = content === '-' ? await readStdin() : content;\n const c = await client.createComment(spaceId, path, body, {\n quote: opts.quote,\n });\n console.log(`Comment #${c.id} created.`);\n }\n );\n\n comment\n .command('reply')\n .description(\n 'Reply to comment — docz comment reply <space> <commentId> <content>'\n )\n .argument('<space>')\n .argument('<commentId>')\n .argument('<content>', 'Reply text (or - for stdin)')\n .action(async (spaceName: string, commentId: string, content: string) => {\n const client = getClient();\n const s = await resolveSpaceArg(client, spaceName);\n const body = content === '-' ? await readStdin() : content;\n const r = await client.replyComment(s.id, Number(commentId), body);\n console.log(`Reply #${r.id} created.`);\n });\n\n comment\n .command('close')\n .description('Close comment — docz comment close <space> <commentId>')\n .argument('<space>')\n .argument('<commentId>')\n .action(async (spaceName: string, commentId: string) => {\n const client = getClient();\n const s = await resolveSpaceArg(client, spaceName);\n await client.closeComment(s.id, Number(commentId));\n console.log(`Comment #${commentId} closed.`);\n });\n\n comment\n .command('rm')\n .description('Delete comment — docz comment rm <space> <commentId>')\n .argument('<space>')\n .argument('<commentId>')\n .action(async (spaceName: string, commentId: string) => {\n const client = getClient();\n const s = await resolveSpaceArg(client, spaceName);\n await client.deleteComment(s.id, Number(commentId));\n console.log(`Comment #${commentId} deleted.`);\n });\n\n // --- share ---\n const share = program.command('share').description('Manage share links');\n\n share\n .command('create')\n .description(\n 'Create share link — docz share create <space>:<path> or <url>'\n )\n .argument('<target>', 'space:path or short URL')\n .option('--expires <duration>', 'Expiry duration (e.g. 7d, 24h)')\n .option('--users <emails>', 'Comma-separated user emails or IDs')\n .option('--groups <ids>', 'Comma-separated group IDs')\n .action(\n async (\n target: string,\n opts: { expires?: string; users?: string; groups?: string }\n ) => {\n const client = getClient();\n const { spaceId, path } = await resolveTarget(client, [target]);\n if (!path) {\n console.error(\n 'Error: file path is required. Usage: docz share create <space>:<path>'\n );\n process.exit(1);\n }\n const apiOpts: {\n expiresAt?: string;\n userIds?: string[];\n groupIds?: string[];\n } = {};\n if (opts.expires) apiOpts.expiresAt = parseExpires(opts.expires);\n if (opts.users)\n apiOpts.userIds = opts.users.split(',').map((s) => s.trim());\n if (opts.groups)\n apiOpts.groupIds = opts.groups.split(',').map((s) => s.trim());\n const link = await client.createShareLink(spaceId, path, apiOpts);\n const baseUrl = getBaseUrl();\n console.log('Created share link:');\n console.log(` id: ${link.id}`);\n console.log(` token: ${link.token}`);\n console.log(` url: ${baseUrl}/share/${link.token}`);\n console.log(` expires: ${link.expires_at ?? 'never'}`);\n if (link.user_ids?.length)\n console.log(` users: ${link.user_ids.join(', ')}`);\n if (link.group_ids?.length)\n console.log(` groups: ${link.group_ids.length}`);\n }\n );\n\n share\n .command('list')\n .description('List share links — docz share list <space>')\n .argument('<space>')\n .option('--file <path>', 'Filter by file path')\n .action(async (spaceName: string, opts: { file?: string }) => {\n const client = getClient();\n const s = await resolveSpaceArg(client, spaceName);\n const links = await client.listShareLinks(s.id, opts.file);\n if (links.length === 0) {\n console.log('No share links.');\n return;\n }\n for (const l of links) {\n const expires = l.expires_at ?? 'never';\n const creator = l.created_by_name ?? l.created_by_email ?? l.created_by;\n console.log(\n `${l.id}\\t${l.token}\\t${l.file_path}\\t${expires}\\t${creator}`\n );\n }\n });\n\n share\n .command('update')\n .description('Update share link — docz share update <space> <link-id>')\n .argument('<space>')\n .argument('<linkId>')\n .option('--expires <duration>', 'New expiry duration (e.g. 30d)')\n .option('--users <emails>', 'Comma-separated user emails or IDs')\n .option('--groups <ids>', 'Comma-separated group IDs')\n .action(\n async (\n spaceName: string,\n linkId: string,\n opts: { expires?: string; users?: string; groups?: string }\n ) => {\n const client = getClient();\n const s = await resolveSpaceArg(client, spaceName);\n const apiOpts: {\n expiresAt?: string;\n userIds?: string[];\n groupIds?: string[];\n } = {};\n if (opts.expires) apiOpts.expiresAt = parseExpires(opts.expires);\n if (opts.users)\n apiOpts.userIds = opts.users.split(',').map((s) => s.trim());\n if (opts.groups)\n apiOpts.groupIds = opts.groups.split(',').map((s) => s.trim());\n await client.updateShareLink(s.id, linkId, apiOpts);\n console.log(`Updated share link: ${linkId}`);\n }\n );\n\n share\n .command('cat')\n .description('Read shared file — docz share cat <token-or-url>')\n .argument('<token>', 'Share token or full URL')\n .option('--raw', 'Output raw content only')\n .action(async (tokenArg: string, opts: { raw?: boolean }) => {\n const client = getClient();\n const token = extractShareToken(tokenArg);\n if (!opts.raw) {\n try {\n const info = await client.getSharedFileInfo(token);\n console.log(`File: ${info.file_path} (${info.space_name})`);\n console.log(\n `Shared by: ${info.created_by_name} | Expires: ${info.expires_at ?? 'never'}`\n );\n console.log('---');\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n if (!msg.includes('404')) {\n console.error(`Warning: failed to fetch share info: ${msg}`);\n }\n }\n }\n const content = await client.getSharedFile(token);\n process.stdout.write(content);\n });\n\n share\n .command('info')\n .description('Show share link info — docz share info <token-or-url>')\n .argument('<token>', 'Share token or full URL')\n .action(async (tokenArg: string) => {\n const client = getClient();\n const token = extractShareToken(tokenArg);\n const info = await client.getSharedFileInfo(token);\n console.log(`File: ${info.file_path}`);\n console.log(`Space: ${info.space_name}`);\n console.log(`Shared by: ${info.created_by_name}`);\n console.log(`Expires: ${info.expires_at ?? 'never'}`);\n });\n\n share\n .command('rm')\n .description('Delete share link — docz share rm <space> <link-id>')\n .argument('<space>')\n .argument('<linkId>')\n .action(async (spaceName: string, linkId: string) => {\n const client = getClient();\n const s = await resolveSpaceArg(client, spaceName);\n await client.deleteShareLink(s.id, linkId);\n console.log(`Deleted share link: ${linkId}`);\n });\n\n // --- shortlink ---\n program\n .command('shortlink')\n .description('Get short URL — docz shortlink <space>:<path> or <url>')\n .argument('<target...>')\n .action(async (args: string[]) => {\n const client = getClient();\n const { spaceId, path } = await resolveTarget(client, args);\n if (!path) {\n console.error(\n 'Error: file path is required. Usage: docz shortlink <space>:<path>'\n );\n process.exit(1);\n }\n const ref = await client.getFileRef(spaceId, path);\n console.log(ref.url);\n });\n\n // --- diff ---\n program\n .command('diff')\n .description(\n 'Show changes — docz diff <space>[:<path>] <commit> [<from>] or <url> <commit> [<from>]'\n )\n .argument('<target>', 'space or space:path or short URL')\n .argument('<to>', 'Commit hash')\n .argument('[from]', 'From commit hash (default: to^)')\n .action(async (target: string, to: string, from?: string) => {\n const client = getClient();\n const { spaceId, path } = await resolveTarget(client, [target]);\n if (path) {\n const result = await client.diffFile(spaceId, path, to, from);\n if (result.diff) {\n process.stdout.write(result.diff);\n } else {\n console.log('No changes.');\n }\n } else {\n const result = await client.diffSummary(spaceId, to, from);\n if (result.files.length === 0) {\n console.log('No changes.');\n return;\n }\n for (const f of result.files) {\n console.log(`${f.status} ${f.path}`);\n }\n }\n });\n}\n"],"mappings":";;;AAoJO,IAAM,gBAAN,cAA4B,MAAM;AAAA,EACvC,YAA4B,QAAsB;AAChD;AAAA,MACE;AAAA,IACF;AAH0B;AAI1B,SAAK,OAAO;AAAA,EACd;AACF;AAMO,IAAM,gBAAN,MAAoB;AAAA,EACzB,YACU,SACA,OACR;AAFQ;AACA;AAER,SAAK,UAAU,QAAQ,QAAQ,OAAO,EAAE;AAAA,EAC1C;AAAA,EAEA,MAAc,QAAW,MAAc,MAAgC;AACrE,UAAM,MAAM,MAAM,MAAM,GAAG,KAAK,OAAO,GAAG,IAAI,IAAI;AAAA,MAChD,GAAG;AAAA,MACH,SAAS;AAAA,QACP,eAAe,UAAU,KAAK,KAAK;AAAA,QACnC,GAAG,MAAM;AAAA,MACX;AAAA,IACF,CAAC;AAED,QAAI,CAAC,IAAI,IAAI;AACX,YAAM,OAAO,MAAM,IAAI,KAAK,EAAE,MAAM,MAAM,EAAE;AAC5C,YAAM,IAAI,MAAM,GAAG,IAAI,MAAM,IAAI,IAAI,UAAU,KAAK,IAAI,GAAG,KAAK,CAAC;AAAA,IACnE;AAEA,UAAM,KAAK,IAAI,QAAQ,IAAI,cAAc,KAAK;AAC9C,QAAI,GAAG,SAAS,kBAAkB,EAAG,QAAO,IAAI,KAAK;AACrD,WAAO,IAAI,KAAK;AAAA,EAClB;AAAA;AAAA,EAGA,MAAM,KAAoB;AACxB,WAAO,KAAK,QAAQ,cAAc;AAAA,EACpC;AAAA;AAAA,EAGA,MAAM,aAA+B;AACnC,WAAO,KAAK,QAAQ,aAAa;AAAA,EACnC;AAAA,EAEA,MAAM,aAAa,UAAkC;AACnD,UAAM,SAAS,MAAM,KAAK,WAAW;AACrC,UAAM,QAAQ,SAAS,YAAY;AAGnC,UAAM,QAAQ,OAAO;AAAA,MACnB,CAAC,MACC,EAAE,OAAO,YACT,EAAE,SAAS,YACX,EAAE,KAAK,YAAY,MAAM;AAAA,IAC7B;AACA,QAAI,MAAO,QAAO;AAGlB,UAAM,SAAS,OAAO,KAAK,CAAC,MAAM,EAAE,SAAS,QAAQ;AACrD,QAAI,OAAQ,QAAO;AAGnB,UAAM,gBAAgB,OAAO;AAAA,MAC3B,CAAC,MACC,EAAE,KAAK,SAAS,SAAS,UAAU,EAAE,KAAK,YAAY,EAAE,SAAS,KAAK;AAAA,IAC1E;AACA,QAAI,cAAc,WAAW,EAAG,QAAO,cAAc,CAAC;AACtD,QAAI,cAAc,SAAS,GAAG;AAC5B,YAAM,aAAa,cAAc,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,IAAI;AAC7D,YAAM,IAAI;AAAA,QACR,UAAU,QAAQ,4BAA4B,UAAU;AAAA,MAC1D;AAAA,IACF;AAEA,UAAM,YAAY,OACf,IAAI,CAAC,MAAO,EAAE,OAAO,GAAG,EAAE,IAAI,KAAK,EAAE,IAAI,MAAM,EAAE,IAAK,EACtD,KAAK,IAAI;AACZ,UAAM,IAAI,MAAM,UAAU,QAAQ,2BAA2B,SAAS,EAAE;AAAA,EAC1E;AAAA;AAAA,EAGA,MAAM,GAAG,SAAiB,OAAO,IAA0B;AACzD,WAAO,KAAK;AAAA,MACV,eAAe,OAAO,cAAc,mBAAmB,IAAI,CAAC;AAAA,IAC9D;AAAA,EACF;AAAA,EAEA,MAAM,SAAS,SAAuC;AACpD,WAAO,KAAK,QAAQ,eAAe,OAAO,YAAY;AAAA,EACxD;AAAA;AAAA,EAGA,MAAM,IAAI,SAAiB,UAAmC;AAC5D,WAAO,KAAK;AAAA,MACV,eAAe,OAAO,SAAS,mBAAmB,QAAQ,CAAC;AAAA,IAC7D;AAAA,EACF;AAAA,EAEA,MAAM,WAAW,SAAiB,UAAsC;AACtE,UAAM,MAAM,MAAM;AAAA,MAChB,GAAG,KAAK,OAAO,eAAe,OAAO,SAAS,mBAAmB,QAAQ,CAAC;AAAA,MAC1E,EAAE,SAAS,EAAE,eAAe,UAAU,KAAK,KAAK,GAAG,EAAE;AAAA,IACvD;AACA,QAAI,CAAC,IAAI,IAAI;AACX,YAAM,OAAO,MAAM,IAAI,KAAK,EAAE,MAAM,MAAM,EAAE;AAC5C,YAAM,IAAI,MAAM,GAAG,IAAI,MAAM,IAAI,IAAI,UAAU,KAAK,IAAI,GAAG,KAAK,CAAC;AAAA,IACnE;AACA,UAAM,UAAU,MAAM,IAAI,KAAK;AAC/B,UAAM,MAAM,IAAI,QAAQ,IAAI,WAAW,KAAK;AAC5C,WAAO,EAAE,SAAS,IAAI;AAAA,EACxB;AAAA;AAAA,EAGA,MAAM,OACJ,SACA,KACA,UACA,SAC2B;AAC3B,UAAM,OACJ,OAAO,YAAY,WACf,IAAI,KAAK,CAAC,OAAO,GAAG,EAAE,MAAM,2BAA2B,CAAC,IACxD,IAAI,KAAK,CAAC,OAAO,GAAG,EAAE,MAAM,2BAA2B,CAAC;AAC9D,UAAM,OAAO,IAAI,SAAS;AAC1B,SAAK,OAAO,QAAQ,MAAM,QAAQ;AAClC,SAAK,OAAO,QAAQ,GAAG;AACvB,WAAO,KAAK,QAAQ,eAAe,OAAO,iBAAiB;AAAA,MACzD,QAAQ;AAAA,MACR,MAAM;AAAA,IACR,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,KACJ,SACA,MACA,SACA,MACqB;AACrB,UAAM,OAA+B,EAAE,MAAM,QAAQ;AACrD,QAAI,MAAM,QAAS,MAAK,WAAW,KAAK;AACxC,QAAI,MAAM,QAAS,MAAK,UAAU,KAAK;AAEvC,UAAM,MAAM,MAAM;AAAA,MAChB,GAAG,KAAK,OAAO,eAAe,OAAO;AAAA,MACrC;AAAA,QACE,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,eAAe,UAAU,KAAK,KAAK;AAAA,UACnC,gBAAgB;AAAA,QAClB;AAAA,QACA,MAAM,KAAK,UAAU,IAAI;AAAA,MAC3B;AAAA,IACF;AAEA,QAAI,IAAI,WAAW,KAAK;AACtB,YAAM,OAAQ,MAAM,IAAI,KAAK;AAC7B,YAAM,IAAI,cAAc,IAAI;AAAA,IAC9B;AAEA,QAAI,CAAC,IAAI,IAAI;AACX,YAAM,OAAO,MAAM,IAAI,KAAK,EAAE,MAAM,MAAM,EAAE;AAC5C,YAAM,IAAI,MAAM,GAAG,IAAI,MAAM,IAAI,IAAI,UAAU,KAAK,IAAI,GAAG,KAAK,CAAC;AAAA,IACnE;AAEA,WAAO,IAAI,KAAK;AAAA,EAClB;AAAA,EAEA,MAAM,MAAM,SAAiB,MAA6B;AACxD,UAAM,KAAK,QAAQ,eAAe,OAAO,gBAAgB;AAAA,MACvD,QAAQ;AAAA,MACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,MAC9C,MAAM,KAAK,UAAU,EAAE,KAAK,CAAC;AAAA,IAC/B,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,GAAG,SAAiB,MAA6B;AACrD,UAAM,KAAK,QAAQ,eAAe,OAAO,iBAAiB;AAAA,MACxD,QAAQ;AAAA,MACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,MAC9C,MAAM,KAAK,UAAU,EAAE,KAAK,CAAC;AAAA,IAC/B,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,GAAG,SAAiB,MAAc,IAA2B;AACjE,UAAM,KAAK,QAAQ,eAAe,OAAO,iBAAiB;AAAA,MACxD,QAAQ;AAAA,MACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,MAC9C,MAAM,KAAK,UAAU,EAAE,UAAU,MAAM,UAAU,GAAG,CAAC;AAAA,IACvD,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,SACJ,SACA,UACA,YACe;AACf,UAAM,KAAK,QAAQ,eAAe,OAAO,mBAAmB;AAAA,MAC1D,QAAQ;AAAA,MACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,MAC9C,MAAM,KAAK,UAAU,EAAE,WAAW,UAAU,aAAa,WAAW,CAAC;AAAA,IACvE,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,MAAM,IAAI,SAAiB,UAAwC;AACjE,UAAM,OAAO,WACT,eAAe,OAAO,QAAQ,mBAAmB,QAAQ,CAAC,KAC1D,eAAe,OAAO;AAC1B,WAAO,KAAK,QAAQ,IAAI;AAAA,EAC1B;AAAA;AAAA,EAGA,MAAM,MAAM,SAAwC;AAClD,WAAO,KAAK,QAAQ,eAAe,OAAO,QAAQ;AAAA,EACpD;AAAA,EAEA,MAAM,QAAQ,SAAiB,MAAc,QAA+B;AAC1E,UAAM,KAAK,QAAQ,eAAe,OAAO,kBAAkB;AAAA,MACzD,QAAQ;AAAA,MACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,MAC9C,MAAM,KAAK,UAAU,EAAE,MAAM,OAAO,CAAC;AAAA,IACvC,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,MAAM,aAAa,SAAiB,UAAsC;AACxE,WAAO,KAAK;AAAA,MACV,eAAe,OAAO,kBAAkB,mBAAmB,QAAQ,CAAC;AAAA,IACtE;AAAA,EACF;AAAA,EAEA,MAAM,cACJ,SACA,UACA,SACA,MACkB;AAClB,UAAM,OAA+B,EAAE,WAAW,UAAU,QAAQ;AACpE,QAAI,MAAM,OAAO;AACf,WAAK,eAAe;AACpB,WAAK,cAAc;AACnB,WAAK,iBAAiB,KAAK;AAC3B,WAAK,kBAAkB,KAAK,UAAU;AAAA,QACpC,aAAa;AAAA,QACb,WAAW;AAAA,QACX,MAAM,KAAK;AAAA,QACX,QAAQ;AAAA,QACR,QAAQ;AAAA,MACV,CAAC;AAAA,IACH;AACA,WAAO,KAAK,QAAQ,eAAe,OAAO,aAAa;AAAA,MACrD,QAAQ;AAAA,MACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,MAC9C,MAAM,KAAK,UAAU,IAAI;AAAA,IAC3B,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,aACJ,SACA,WACA,SACuB;AACvB,WAAO,KAAK;AAAA,MACV,eAAe,OAAO,aAAa,SAAS;AAAA,MAC5C;AAAA,QACE,QAAQ;AAAA,QACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,QAC9C,MAAM,KAAK,UAAU,EAAE,QAAQ,CAAC;AAAA,MAClC;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,aAAa,SAAiB,WAAqC;AACvE,WAAO,KAAK,QAAQ,eAAe,OAAO,aAAa,SAAS,IAAI;AAAA,MAClE,QAAQ;AAAA,MACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,MAC9C,MAAM,KAAK,UAAU,EAAE,WAAW,KAAK,CAAC;AAAA,IAC1C,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,cAAc,SAAiB,WAAkC;AACrE,UAAM,KAAK,QAAQ,eAAe,OAAO,aAAa,SAAS,IAAI;AAAA,MACjE,QAAQ;AAAA,IACV,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,MAAM,gBACJ,SACA,UACA,MACoB;AACpB,UAAM,OAAgC,EAAE,WAAW,SAAS;AAC5D,QAAI,MAAM,UAAW,MAAK,aAAa,KAAK;AAC5C,QAAI,MAAM,SAAS,OAAQ,MAAK,WAAW,KAAK;AAChD,QAAI,MAAM,UAAU,OAAQ,MAAK,YAAY,KAAK;AAClD,WAAO,KAAK,QAAQ,eAAe,OAAO,gBAAgB;AAAA,MACxD,QAAQ;AAAA,MACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,MAC9C,MAAM,KAAK,UAAU,IAAI;AAAA,IAC3B,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,eACJ,SACA,UACsB;AACtB,UAAM,IAAI,WAAW,cAAc,mBAAmB,QAAQ,CAAC,KAAK;AACpE,WAAO,KAAK,QAAQ,eAAe,OAAO,eAAe,CAAC,EAAE;AAAA,EAC9D;AAAA,EAEA,MAAM,gBACJ,SACA,QACA,MACoB;AACpB,UAAM,OAAgC,CAAC;AACvC,QAAI,KAAK,cAAc,OAAW,MAAK,aAAa,KAAK;AACzD,QAAI,KAAK,QAAS,MAAK,WAAW,KAAK;AACvC,QAAI,KAAK,SAAU,MAAK,YAAY,KAAK;AACzC,WAAO,KAAK,QAAQ,eAAe,OAAO,gBAAgB,MAAM,IAAI;AAAA,MAClE,QAAQ;AAAA,MACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,MAC9C,MAAM,KAAK,UAAU,IAAI;AAAA,IAC3B,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,gBAAgB,SAAiB,QAA+B;AACpE,UAAM,KAAK,QAAQ,eAAe,OAAO,gBAAgB,MAAM,IAAI;AAAA,MACjE,QAAQ;AAAA,IACV,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,cAAc,OAAgC;AAClD,WAAO,KAAK,QAAQ,cAAc,KAAK,EAAE;AAAA,EAC3C;AAAA,EAEA,MAAM,kBAAkB,OAAuC;AAC7D,WAAO,KAAK,QAAQ,cAAc,KAAK,OAAO;AAAA,EAChD;AAAA;AAAA,EAGA,MAAM,SACJ,SACA,UACA,IACA,MACuB;AACvB,UAAM,SAAS,IAAI,gBAAgB,EAAE,GAAG,CAAC;AACzC,QAAI,KAAM,QAAO,IAAI,QAAQ,IAAI;AACjC,WAAO,KAAK;AAAA,MACV,eAAe,OAAO,SAAS,mBAAmB,QAAQ,CAAC,IAAI,MAAM;AAAA,IACvE;AAAA,EACF;AAAA,EAEA,MAAM,YACJ,SACA,IACA,MACsB;AACtB,UAAM,SAAS,IAAI,gBAAgB,EAAE,GAAG,CAAC;AACzC,QAAI,KAAM,QAAO,IAAI,QAAQ,IAAI;AACjC,WAAO,KAAK,QAAQ,eAAe,OAAO,SAAS,MAAM,EAAE;AAAA,EAC7D;AAAA;AAAA,EAGA,MAAM,WACJ,SACA,MAQC;AACD,WAAO,KAAK;AAAA,MACV,eAAe,OAAO,kBAAkB,mBAAmB,IAAI,CAAC;AAAA,IAClE;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,cAAc,MAA8B;AAChD,WAAO,KAAK,QAAQ,uBAAuB,mBAAmB,IAAI,CAAC,EAAE;AAAA,EACvE;AAAA,EAEA,MAAM,eAAe,QAAkC;AACrD,WAAO,KAAK,QAAQ,kBAAkB,mBAAmB,MAAM,CAAC,EAAE;AAAA,EACpE;AACF;;;AC1hBA,SAAS,YAAY,WAAW,cAAc,qBAAqB;AACnE,SAAS,eAAe;AACxB,SAAS,YAAY;AAErB,IAAM,aAAa,KAAK,QAAQ,GAAG,OAAO;AAC1C,IAAM,cAAc,KAAK,YAAY,aAAa;AAOlD,SAAS,aAAqB;AAC5B,MAAI,CAAC,WAAW,WAAW,EAAG,QAAO,CAAC;AACtC,MAAI;AACF,WAAO,KAAK,MAAM,aAAa,aAAa,OAAO,CAAC;AAAA,EACtD,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACF;AAEA,SAAS,YAAY,QAAsB;AACzC,YAAU,YAAY,EAAE,WAAW,KAAK,CAAC;AACzC,gBAAc,aAAa,GAAG,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AAAA,CAAI;AACnE;AAEO,SAAS,aAAqB;AACnC,SACE,QAAQ,IAAI,oBACZ,WAAW,EAAE,YACb;AAEJ;AAEO,SAAS,WAA+B;AAC7C,SAAO,QAAQ,IAAI,qBAAqB,WAAW,EAAE;AACvD;AAEO,SAAS,WAAW,SAAiB,OAAqB;AAC/D,cAAY,EAAE,UAAU,SAAS,MAAM,CAAC;AAC1C;AAEO,SAAS,gBAAwB;AACtC,SAAO;AACT;;;AC9CA,SAAS,gBAAAA,qBAAoB;AAC7B,SAAS,gBAAgB;AASzB,SAAS,YAA2B;AAClC,QAAM,QAAQ,SAAS;AACvB,MAAI,CAAC,OAAO;AACV,YAAQ;AAAA,MACN;AAAA,IAEF;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AACA,SAAO,IAAI,cAAc,WAAW,GAAG,KAAK;AAC9C;AAGO,SAAS,YAAY,MAAiD;AAC3E,MAAI,KAAK,WAAW,GAAG;AACrB,YAAQ;AAAA,MACN;AAAA,IACF;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AACA,QAAM,QAAQ,KAAK,CAAC;AACpB,MAAI,MAAM,SAAS,GAAG,GAAG;AACvB,UAAM,CAAC,OAAO,GAAG,IAAI,IAAI,MAAM,MAAM,GAAG;AACxC,WAAO,EAAE,OAAO,MAAM,KAAK,KAAK,GAAG,EAAE;AAAA,EACvC;AACA,SAAO,EAAE,OAAO,OAAO,MAAM,KAAK,MAAM,CAAC,EAAE,KAAK,GAAG,EAAE;AACvD;AAEA,SAAS,WAAW,OAAuB;AACzC,MAAI,QAAQ,KAAM,QAAO,GAAG,KAAK;AACjC,MAAI,QAAQ,OAAO,KAAM,QAAO,IAAI,QAAQ,MAAM,QAAQ,CAAC,CAAC;AAC5D,SAAO,IAAI,SAAS,OAAO,OAAO,QAAQ,CAAC,CAAC;AAC9C;AAGA,IAAM,eAAe;AAGrB,eAAe,YACb,QACA,MACyB;AACzB,MAAI;AACF,UAAM,SAAS,MAAM,OAAO,WAAW;AACvC,UAAM,QAAQ,OAAO,KAAK,CAAC,MAAM,EAAE,SAAS,IAAI;AAChD,QAAI,MAAO,QAAO;AAAA,EACpB,QAAQ;AAAA,EAER;AACA,SAAO,OAAO,cAAc,IAAI;AAClC;AAUA,eAAe,WACb,QACA,OACmD;AACnD,MAAI;AACJ,MAAI;AACF,eAAW,IAAI,IAAI,KAAK,EAAE;AAAA,EAC5B,QAAQ;AACN,WAAO;AAAA,EACT;AAGA,QAAM,YAAY,SAAS,MAAM,4BAA4B;AAC7D,MAAI,WAAW;AACb,UAAM,CAAC,EAAE,MAAM,MAAM,IAAI;AACzB,UAAM,QAAQ,MAAM,YAAY,QAAQ,IAAI;AAC5C,UAAM,MAAM,MAAM,OAAO,eAAe,MAAM;AAC9C,WAAO,EAAE,SAAS,MAAM,IAAI,MAAM,IAAI,KAAK;AAAA,EAC7C;AAGA,QAAM,YAAY,SAAS,MAAM,uBAAuB;AACxD,MAAI,WAAW;AACb,UAAM,CAAC,EAAE,MAAM,IAAI,IAAI;AACvB,UAAM,QAAQ,MAAM,YAAY,QAAQ,IAAI;AAC5C,UAAM,WAAW,OAAO,mBAAmB,KAAK,MAAM,CAAC,CAAC,IAAI;AAC5D,WAAO,EAAE,SAAS,MAAM,IAAI,MAAM,SAAS;AAAA,EAC7C;AAGA,QAAM,cAAc,SAAS,MAAM,4BAA4B;AAC/D,MAAI,aAAa;AACf,UAAM,CAAC,EAAE,SAAS,IAAI,IAAI;AAC1B,UAAM,WAAW,OAAO,mBAAmB,KAAK,MAAM,CAAC,CAAC,IAAI;AAC5D,WAAO,EAAE,SAAS,MAAM,SAAS;AAAA,EACnC;AAEA,SAAO;AACT;AAKA,eAAsB,cACpB,QACA,MAC4C;AAC5C,QAAM,QAAQ,KAAK,CAAC;AACpB,MAAI,UAAU,MAAM,WAAW,SAAS,KAAK,MAAM,WAAW,UAAU,IAAI;AAC1E,UAAM,SAAS,MAAM,WAAW,QAAQ,KAAK;AAC7C,QAAI,OAAQ,QAAO;AACnB,UAAM,IAAI;AAAA,MACR,6BAA6B,KAAK;AAAA;AAAA,IACpC;AAAA,EACF;AACA,QAAM,EAAE,OAAO,KAAK,IAAI,YAAY,IAAI;AACxC,QAAM,IAAI,MAAM,OAAO,aAAa,KAAK;AACzC,SAAO,EAAE,SAAS,EAAE,IAAI,KAAK;AAC/B;AAMA,eAAsB,gBACpB,QACA,OACyB;AACzB,MAAI,MAAM,WAAW,SAAS,KAAK,MAAM,WAAW,UAAU,GAAG;AAC/D,UAAM,SAAS,MAAM,WAAW,QAAQ,KAAK;AAC7C,QAAI,OAAQ,QAAO,EAAE,IAAI,OAAO,QAAQ;AACxC,UAAM,IAAI;AAAA,MACR,6BAA6B,KAAK;AAAA;AAAA,IACpC;AAAA,EACF;AACA,SAAO,OAAO,aAAa,KAAK;AAClC;AAGO,SAAS,aAAa,OAAuB;AAClD,QAAM,QAAQ,MAAM,MAAM,eAAe;AACzC,MAAI,CAAC;AACH,UAAM,IAAI;AAAA,MACR,4BAA4B,KAAK;AAAA,IACnC;AACF,QAAM,CAAC,EAAE,KAAK,IAAI,IAAI;AACtB,QAAM,KAAK,SAAS,MAAM,OAAO,GAAG,IAAI,QAAW,OAAO,GAAG,IAAI;AACjE,SAAO,IAAI,KAAK,KAAK,IAAI,IAAI,EAAE,EAAE,YAAY;AAC/C;AAGA,SAAS,kBAAkB,OAAuB;AAChD,QAAM,IAAI,MAAM,MAAM,YAAY;AAClC,MAAI,EAAG,QAAO,EAAE,CAAC;AACjB,SAAO;AACT;AAGA,eAAe,YAA6B;AAC1C,QAAM,SAAmB,CAAC;AAC1B,mBAAiB,SAAS,QAAQ,OAAO;AACvC,WAAO,KAAK,KAAe;AAAA,EAC7B;AACA,SAAO,OAAO,OAAO,MAAM,EAAE,SAAS,OAAO;AAC/C;AAEA,IAAM,gBAAgB,IAAI,OAAO;AAM1B,SAAS,iBAAiB,SAAwB;AAEvD,UACG,QAAQ,OAAO,EACf,YAAY,+BAA+B,EAC3C,OAAO,mBAAmB,oBAAoB,EAC9C,OAAO,uBAAuB,WAAW,EACzC,OAAO,OAAO,SAAS;AACtB,UAAM,MAAM,KAAK,OAAO,WAAW;AACnC,UAAM,QAAQ,KAAK;AACnB,QAAI,CAAC,OAAO;AACV,cAAQ;AAAA,QACN,8CAEE,MACA;AAAA,MACJ;AACA,cAAQ,KAAK,CAAC;AAAA,IAChB;AACA,UAAM,SAAS,IAAI,cAAc,KAAK,KAAK;AAC3C,QAAI;AACF,YAAM,OAAO,MAAM,OAAO,GAAG;AAC7B,iBAAW,KAAK,KAAK;AACrB,cAAQ,IAAI,gBAAgB,KAAK,IAAI,KAAK,KAAK,KAAK,GAAG;AACvD,cAAQ,IAAI,mBAAmB,cAAc,CAAC,EAAE;AAAA,IAClD,SAAS,KAAK;AACZ,cAAQ;AAAA,QACN,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,MAC5D;AACA,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF,CAAC;AAGH,UACG,QAAQ,QAAQ,EAChB,YAAY,mBAAmB,EAC/B,OAAO,YAAY;AAClB,UAAM,SAAS,UAAU;AACzB,UAAM,OAAO,MAAM,OAAO,GAAG;AAC7B,YAAQ,IAAI,GAAG,KAAK,IAAI,KAAK,KAAK,KAAK,GAAG;AAAA,EAC5C,CAAC;AAGH,UACG,QAAQ,QAAQ,EAChB,YAAY,4BAA4B,EACxC,OAAO,YAAY;AAClB,UAAM,SAAS,UAAU;AACzB,UAAM,SAAS,MAAM,OAAO,WAAW;AACvC,eAAW,KAAK,QAAQ;AACtB,YAAM,MAAM,EAAE,aAAa,YAAY;AACvC,cAAQ;AAAA,QACN,GAAG,EAAE,IAAI,IAAK,GAAG,IAAK,EAAE,YAAY,YAAa,EAAE,EAAE,IAAK,EAAE,QAAQ,EAAE;AAAA,MACxE;AAAA,IACF;AAAA,EACF,CAAC;AAGH,UACG,QAAQ,IAAI,EACZ,YAAY,qDAAgD,EAC5D,SAAS,aAAa,EACtB,OAAO,mBAAmB,4BAA4B,EACtD,OAAO,OAAO,MAAgB,SAAkC;AAC/D,UAAM,SAAS,UAAU;AACzB,UAAM,EAAE,SAAS,KAAK,IAAI,MAAM,cAAc,QAAQ,IAAI;AAC1D,UAAM,UAAU,KAAK,YACjB,MAAM,OAAO,SAAS,OAAO,IAC7B,MAAM,OAAO,GAAG,SAAS,IAAI;AACjC,QAAI,QAAQ,WAAW,GAAG;AACxB,cAAQ,IAAI,SAAS;AACrB;AAAA,IACF;AACA,eAAW,KAAK,SAAS;AACvB,UAAI,EAAE,SAAS,QAAQ;AACrB,gBAAQ,IAAI,GAAG,EAAE,IAAI,GAAG;AAAA,MAC1B,OAAO;AACL,gBAAQ,IAAI,GAAG,EAAE,IAAI,IAAK,WAAW,EAAE,IAAI,CAAC,EAAE;AAAA,MAChD;AAAA,IACF;AAAA,EACF,CAAC;AAGH,UACG,QAAQ,KAAK,EACb,YAAY,2DAAsD,EAClE,SAAS,aAAa,EACtB,OAAO,SAAS,+BAA+B,EAC/C,OAAO,OAAO,MAAgB,SAA4B;AACzD,UAAM,SAAS,UAAU;AACzB,UAAM,EAAE,SAAS,KAAK,IAAI,MAAM,cAAc,QAAQ,IAAI;AAC1D,QAAI,CAAC,MAAM;AACT,cAAQ;AAAA,QACN;AAAA,MACF;AACA,cAAQ,KAAK,CAAC;AAAA,IAChB;AACA,QAAI,KAAK,KAAK;AACZ,YAAM,SAAS,MAAM,OAAO,WAAW,SAAS,IAAI;AACpD,cAAQ,MAAM,QAAQ,OAAO,GAAG,EAAE;AAClC,cAAQ,OAAO,MAAM,OAAO,OAAO;AAAA,IACrC,OAAO;AACL,YAAM,UAAU,MAAM,OAAO,IAAI,SAAS,IAAI;AAC9C,cAAQ,OAAO,MAAM,OAAO;AAAA,IAC9B;AAAA,EACF,CAAC;AAGH,UACG,QAAQ,QAAQ,EAChB;AAAA,IACC;AAAA,EACF,EACC,SAAS,UAAU,sBAAsB,EACzC,SAAS,aAAa,EACtB,OAAO,OAAO,MAAc,SAAmB;AAC9C,UAAM,SAAS,UAAU;AACzB,UAAM,EAAE,SAAS,MAAM,IAAI,IAAI,MAAM,cAAc,QAAQ,IAAI;AAC/D,UAAM,UAAUC,cAAa,IAAI;AACjC,UAAM,WAAW,SAAS,IAAI;AAC9B,UAAM,YAAY,OAAO;AACzB,UAAM,SAAS,MAAM,OAAO,OAAO,SAAS,WAAW,UAAU,OAAO;AACxE,YAAQ,IAAI,aAAa,OAAO,IAAI,EAAE;AAAA,EACxC,CAAC;AAGH,UACG,QAAQ,OAAO,EACf;AAAA,IACC;AAAA,EACF,EACC,SAAS,YAAY,oCAAoC,EACzD,SAAS,aAAa,+BAA+B,EACrD,OAAO,WAAW,yBAAyB,EAC3C,OAAO,uBAAuB,uBAAuB,EACrD;AAAA,IACC,OACE,QACA,SACA,SACG;AACH,YAAM,SAAS,UAAU;AACzB,YAAM,EAAE,SAAS,KAAK,IAAI,MAAM,cAAc,QAAQ,CAAC,MAAM,CAAC;AAC9D,UAAI,CAAC,MAAM;AACT,gBAAQ;AAAA,UACN;AAAA,QACF;AACA,gBAAQ,KAAK,CAAC;AAAA,MAChB;AACA,YAAM,OAAO,YAAY,MAAM,MAAM,UAAU,IAAI;AAEnD,UAAI,OAAO,WAAW,MAAM,OAAO,IAAI,eAAe;AACpD,gBAAQ;AAAA,UACN;AAAA,QACF;AACA,gBAAQ,KAAK,CAAC;AAAA,MAChB;AAEA,UAAI;AACJ,UAAI,CAAC,KAAK,OAAO;AACf,YAAI;AACF,gBAAM,WAAW,MAAM,OAAO,WAAW,SAAS,IAAI;AACtD,oBAAU,SAAS;AAAA,QACrB,SAAS,KAAK;AACZ,gBAAM,MAAM,eAAe,QAAQ,IAAI,UAAU;AACjD,cAAI,CAAC,IAAI,SAAS,KAAK,EAAG,OAAM;AAAA,QAClC;AAAA,MACF;AAEA,UAAI;AACF,cAAM,SAAS,MAAM,OAAO,KAAK,SAAS,MAAM,MAAM;AAAA,UACpD;AAAA,UACA,SAAS,KAAK;AAAA,QAChB,CAAC;AACD,gBAAQ,IAAI,YAAY,OAAO,IAAI,UAAU,OAAO,GAAG,GAAG;AAAA,MAC5D,SAAS,KAAK;AACZ,YAAI,eAAe,eAAe;AAChC,kBAAQ;AAAA,YACN;AAAA,UACF;AACA,kBAAQ,KAAK,CAAC;AAAA,QAChB;AACA,cAAM;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAGF,UACG,QAAQ,OAAO,EACf,YAAY,yDAAoD,EAChE,SAAS,aAAa,EACtB,OAAO,OAAO,SAAmB;AAChC,UAAM,SAAS,UAAU;AACzB,UAAM,EAAE,SAAS,KAAK,IAAI,MAAM,cAAc,QAAQ,IAAI;AAC1D,QAAI,CAAC,MAAM;AACT,cAAQ,MAAM,0BAA0B;AACxC,cAAQ,KAAK,CAAC;AAAA,IAChB;AACA,UAAM,OAAO,MAAM,SAAS,IAAI;AAChC,YAAQ,IAAI,YAAY,IAAI,EAAE;AAAA,EAChC,CAAC;AAGH,UACG,QAAQ,IAAI,EACZ,YAAY,2DAAsD,EAClE,SAAS,aAAa,EACtB,OAAO,OAAO,SAAmB;AAChC,UAAM,SAAS,UAAU;AACzB,UAAM,EAAE,SAAS,KAAK,IAAI,MAAM,cAAc,QAAQ,IAAI;AAC1D,QAAI,CAAC,MAAM;AACT,cAAQ,MAAM,0BAA0B;AACxC,cAAQ,KAAK,CAAC;AAAA,IAChB;AACA,UAAM,OAAO,GAAG,SAAS,IAAI;AAC7B,YAAQ,IAAI,YAAY,IAAI,uCAAuC;AAAA,EACrE,CAAC;AAGH,UACG,QAAQ,IAAI,EACZ,YAAY,8DAAyD,EACrE,SAAS,YAAY,6BAA6B,EAClD,SAAS,QAAQ,UAAU,EAC3B,OAAO,OAAO,QAAgB,OAAe;AAC5C,UAAM,SAAS,UAAU;AACzB,UAAM,EAAE,SAAS,MAAM,KAAK,IAAI,MAAM,cAAc,QAAQ,CAAC,MAAM,CAAC;AACpE,QAAI,CAAC,MAAM;AACT,cAAQ,MAAM,iCAAiC;AAC/C,cAAQ,KAAK,CAAC;AAAA,IAChB;AACA,UAAM,OAAO,GAAG,SAAS,MAAM,EAAE;AACjC,YAAQ,IAAI,UAAU,IAAI,WAAM,EAAE,EAAE;AAAA,EACtC,CAAC;AAGH,UACG,QAAQ,KAAK,EACb,YAAY,+DAA0D,EACtE,SAAS,aAAa,EACtB,OAAO,OAAO,SAAmB;AAChC,UAAM,SAAS,UAAU;AACzB,UAAM,EAAE,SAAS,KAAK,IAAI,MAAM,cAAc,QAAQ,IAAI;AAC1D,UAAM,OAAO,MAAM,OAAO,IAAI,SAAS,QAAQ,MAAS;AACxD,QAAI,KAAK,WAAW,GAAG;AACrB,cAAQ,IAAI,aAAa;AACzB;AAAA,IACF;AACA,eAAW,KAAK,MAAM;AACpB,cAAQ,IAAI,GAAG,EAAE,IAAI,KAAK,EAAE,IAAI,KAAK,EAAE,OAAO,EAAE;AAAA,IAClD;AAAA,EACF,CAAC;AAGH,UACG,QAAQ,UAAU,EAClB;AAAA,IACC;AAAA,EACF,EACC,SAAS,YAAY,yBAAyB,EAC9C,SAAS,YAAY,4BAA4B,EACjD,OAAO,OAAO,QAAgB,WAAmB;AAChD,UAAM,SAAS,UAAU;AACzB,UAAM,EAAE,SAAS,KAAK,IAAI,MAAM,cAAc,QAAQ,CAAC,MAAM,CAAC;AAC9D,QAAI,CAAC,MAAM;AACT,cAAQ,MAAM,+BAA+B;AAC7C,cAAQ,KAAK,CAAC;AAAA,IAChB;AACA,UAAM,OAAO,SAAS,SAAS,MAAM,MAAM;AAC3C,YAAQ,IAAI,gBAAgB,IAAI,WAAM,OAAO,UAAU,GAAG,CAAC,CAAC,EAAE;AAAA,EAChE,CAAC;AAGH,UACG,QAAQ,OAAO,EACf,YAAY,8CAAyC,EACrD,SAAS,SAAS,EAClB,OAAO,OAAO,cAAsB;AACnC,UAAM,SAAS,UAAU;AACzB,UAAM,IAAI,MAAM,gBAAgB,QAAQ,SAAS;AACjD,UAAM,QAAQ,MAAM,OAAO,MAAM,EAAE,EAAE;AACrC,QAAI,MAAM,WAAW,GAAG;AACtB,cAAQ,IAAI,iBAAiB;AAC7B;AAAA,IACF;AACA,eAAW,KAAK,OAAO;AACrB,cAAQ;AAAA,QACN,GAAG,EAAE,IAAI,YAAa,EAAE,UAAU,IAAK,EAAE,OAAO,UAAU,GAAG,CAAC,CAAC;AAAA,MACjE;AAAA,IACF;AAAA,EACF,CAAC;AAGH,UACG,QAAQ,SAAS,EACjB;AAAA,IACC;AAAA,EACF,EACC,SAAS,YAAY,yBAAyB,EAC9C,SAAS,YAAY,gCAAgC,EACrD,OAAO,OAAO,QAAgB,WAAmB;AAChD,UAAM,SAAS,UAAU;AACzB,UAAM,EAAE,SAAS,KAAK,IAAI,MAAM,cAAc,QAAQ,CAAC,MAAM,CAAC;AAC9D,QAAI,CAAC,MAAM;AACT,cAAQ,MAAM,0BAA0B;AACxC,cAAQ,KAAK,CAAC;AAAA,IAChB;AACA,UAAM,OAAO,QAAQ,SAAS,MAAM,MAAM;AAC1C,YAAQ,IAAI,aAAa,IAAI,EAAE;AAAA,EACjC,CAAC;AAGH,QAAM,UAAU,QACb,QAAQ,SAAS,EACjB,YAAY,sBAAsB;AAErC,UACG,QAAQ,MAAM,EACd,YAAY,uDAAkD,EAC9D,SAAS,aAAa,EACtB,OAAO,OAAO,SAAmB;AAChC,UAAM,SAAS,UAAU;AACzB,UAAM,EAAE,SAAS,KAAK,IAAI,MAAM,cAAc,QAAQ,IAAI;AAC1D,QAAI,CAAC,MAAM;AACT,cAAQ,MAAM,+BAA+B;AAC7C,cAAQ,KAAK,CAAC;AAAA,IAChB;AACA,UAAM,WAAW,MAAM,OAAO,aAAa,SAAS,IAAI;AACxD,QAAI,SAAS,WAAW,GAAG;AACzB,cAAQ,IAAI,cAAc;AAC1B;AAAA,IACF;AACA,eAAW,KAAK,UAAU;AACxB,YAAM,SAAS,EAAE,YAAY,cAAc;AAC3C,cAAQ,IAAI,IAAI,EAAE,EAAE,IAAI,EAAE,SAAS,KAAK,EAAE,UAAU,IAAI,MAAM,EAAE;AAChE,UAAI,EAAE,gBAAgB;AACpB,gBAAQ,IAAI,OAAO,EAAE,cAAc,EAAE;AAAA,MACvC;AACA,cAAQ,IAAI,KAAK,EAAE,OAAO,EAAE;AAC5B,iBAAW,KAAK,EAAE,SAAS;AACzB,gBAAQ,IAAI,cAAS,EAAE,SAAS,KAAK,EAAE,OAAO,EAAE;AAAA,MAClD;AAAA,IACF;AAAA,EACF,CAAC;AAEH,UACG,QAAQ,KAAK,EACb;AAAA,IACC;AAAA,EACF,EACC,SAAS,YAAY,yBAAyB,EAC9C,SAAS,aAAa,+BAA+B,EACrD;AAAA,IACC;AAAA,IACA;AAAA,EACF,EACC;AAAA,IACC,OAAO,QAAgB,SAAiB,SAA6B;AACnE,YAAM,SAAS,UAAU;AACzB,YAAM,EAAE,SAAS,KAAK,IAAI,MAAM,cAAc,QAAQ,CAAC,MAAM,CAAC;AAC9D,UAAI,CAAC,MAAM;AACT,gBAAQ,MAAM,+BAA+B;AAC7C,gBAAQ,KAAK,CAAC;AAAA,MAChB;AACA,YAAM,OAAO,YAAY,MAAM,MAAM,UAAU,IAAI;AACnD,YAAM,IAAI,MAAM,OAAO,cAAc,SAAS,MAAM,MAAM;AAAA,QACxD,OAAO,KAAK;AAAA,MACd,CAAC;AACD,cAAQ,IAAI,YAAY,EAAE,EAAE,WAAW;AAAA,IACzC;AAAA,EACF;AAEF,UACG,QAAQ,OAAO,EACf;AAAA,IACC;AAAA,EACF,EACC,SAAS,SAAS,EAClB,SAAS,aAAa,EACtB,SAAS,aAAa,6BAA6B,EACnD,OAAO,OAAO,WAAmB,WAAmB,YAAoB;AACvE,UAAM,SAAS,UAAU;AACzB,UAAM,IAAI,MAAM,gBAAgB,QAAQ,SAAS;AACjD,UAAM,OAAO,YAAY,MAAM,MAAM,UAAU,IAAI;AACnD,UAAM,IAAI,MAAM,OAAO,aAAa,EAAE,IAAI,OAAO,SAAS,GAAG,IAAI;AACjE,YAAQ,IAAI,UAAU,EAAE,EAAE,WAAW;AAAA,EACvC,CAAC;AAEH,UACG,QAAQ,OAAO,EACf,YAAY,6DAAwD,EACpE,SAAS,SAAS,EAClB,SAAS,aAAa,EACtB,OAAO,OAAO,WAAmB,cAAsB;AACtD,UAAM,SAAS,UAAU;AACzB,UAAM,IAAI,MAAM,gBAAgB,QAAQ,SAAS;AACjD,UAAM,OAAO,aAAa,EAAE,IAAI,OAAO,SAAS,CAAC;AACjD,YAAQ,IAAI,YAAY,SAAS,UAAU;AAAA,EAC7C,CAAC;AAEH,UACG,QAAQ,IAAI,EACZ,YAAY,2DAAsD,EAClE,SAAS,SAAS,EAClB,SAAS,aAAa,EACtB,OAAO,OAAO,WAAmB,cAAsB;AACtD,UAAM,SAAS,UAAU;AACzB,UAAM,IAAI,MAAM,gBAAgB,QAAQ,SAAS;AACjD,UAAM,OAAO,cAAc,EAAE,IAAI,OAAO,SAAS,CAAC;AAClD,YAAQ,IAAI,YAAY,SAAS,WAAW;AAAA,EAC9C,CAAC;AAGH,QAAM,QAAQ,QAAQ,QAAQ,OAAO,EAAE,YAAY,oBAAoB;AAEvE,QACG,QAAQ,QAAQ,EAChB;AAAA,IACC;AAAA,EACF,EACC,SAAS,YAAY,yBAAyB,EAC9C,OAAO,wBAAwB,gCAAgC,EAC/D,OAAO,oBAAoB,oCAAoC,EAC/D,OAAO,kBAAkB,2BAA2B,EACpD;AAAA,IACC,OACE,QACA,SACG;AACH,YAAM,SAAS,UAAU;AACzB,YAAM,EAAE,SAAS,KAAK,IAAI,MAAM,cAAc,QAAQ,CAAC,MAAM,CAAC;AAC9D,UAAI,CAAC,MAAM;AACT,gBAAQ;AAAA,UACN;AAAA,QACF;AACA,gBAAQ,KAAK,CAAC;AAAA,MAChB;AACA,YAAM,UAIF,CAAC;AACL,UAAI,KAAK,QAAS,SAAQ,YAAY,aAAa,KAAK,OAAO;AAC/D,UAAI,KAAK;AACP,gBAAQ,UAAU,KAAK,MAAM,MAAM,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC;AAC7D,UAAI,KAAK;AACP,gBAAQ,WAAW,KAAK,OAAO,MAAM,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC;AAC/D,YAAM,OAAO,MAAM,OAAO,gBAAgB,SAAS,MAAM,OAAO;AAChE,YAAM,UAAU,WAAW;AAC3B,cAAQ,IAAI,qBAAqB;AACjC,cAAQ,IAAI,cAAc,KAAK,EAAE,EAAE;AACnC,cAAQ,IAAI,cAAc,KAAK,KAAK,EAAE;AACtC,cAAQ,IAAI,cAAc,OAAO,UAAU,KAAK,KAAK,EAAE;AACvD,cAAQ,IAAI,cAAc,KAAK,cAAc,OAAO,EAAE;AACtD,UAAI,KAAK,UAAU;AACjB,gBAAQ,IAAI,cAAc,KAAK,SAAS,KAAK,IAAI,CAAC,EAAE;AACtD,UAAI,KAAK,WAAW;AAClB,gBAAQ,IAAI,cAAc,KAAK,UAAU,MAAM,EAAE;AAAA,IACrD;AAAA,EACF;AAEF,QACG,QAAQ,MAAM,EACd,YAAY,iDAA4C,EACxD,SAAS,SAAS,EAClB,OAAO,iBAAiB,qBAAqB,EAC7C,OAAO,OAAO,WAAmB,SAA4B;AAC5D,UAAM,SAAS,UAAU;AACzB,UAAM,IAAI,MAAM,gBAAgB,QAAQ,SAAS;AACjD,UAAM,QAAQ,MAAM,OAAO,eAAe,EAAE,IAAI,KAAK,IAAI;AACzD,QAAI,MAAM,WAAW,GAAG;AACtB,cAAQ,IAAI,iBAAiB;AAC7B;AAAA,IACF;AACA,eAAW,KAAK,OAAO;AACrB,YAAM,UAAU,EAAE,cAAc;AAChC,YAAM,UAAU,EAAE,mBAAmB,EAAE,oBAAoB,EAAE;AAC7D,cAAQ;AAAA,QACN,GAAG,EAAE,EAAE,IAAK,EAAE,KAAK,IAAK,EAAE,SAAS,IAAK,OAAO,IAAK,OAAO;AAAA,MAC7D;AAAA,IACF;AAAA,EACF,CAAC;AAEH,QACG,QAAQ,QAAQ,EAChB,YAAY,8DAAyD,EACrE,SAAS,SAAS,EAClB,SAAS,UAAU,EACnB,OAAO,wBAAwB,gCAAgC,EAC/D,OAAO,oBAAoB,oCAAoC,EAC/D,OAAO,kBAAkB,2BAA2B,EACpD;AAAA,IACC,OACE,WACA,QACA,SACG;AACH,YAAM,SAAS,UAAU;AACzB,YAAM,IAAI,MAAM,gBAAgB,QAAQ,SAAS;AACjD,YAAM,UAIF,CAAC;AACL,UAAI,KAAK,QAAS,SAAQ,YAAY,aAAa,KAAK,OAAO;AAC/D,UAAI,KAAK;AACP,gBAAQ,UAAU,KAAK,MAAM,MAAM,GAAG,EAAE,IAAI,CAACC,OAAMA,GAAE,KAAK,CAAC;AAC7D,UAAI,KAAK;AACP,gBAAQ,WAAW,KAAK,OAAO,MAAM,GAAG,EAAE,IAAI,CAACA,OAAMA,GAAE,KAAK,CAAC;AAC/D,YAAM,OAAO,gBAAgB,EAAE,IAAI,QAAQ,OAAO;AAClD,cAAQ,IAAI,uBAAuB,MAAM,EAAE;AAAA,IAC7C;AAAA,EACF;AAEF,QACG,QAAQ,KAAK,EACb,YAAY,uDAAkD,EAC9D,SAAS,WAAW,yBAAyB,EAC7C,OAAO,SAAS,yBAAyB,EACzC,OAAO,OAAO,UAAkB,SAA4B;AAC3D,UAAM,SAAS,UAAU;AACzB,UAAM,QAAQ,kBAAkB,QAAQ;AACxC,QAAI,CAAC,KAAK,KAAK;AACb,UAAI;AACF,cAAM,OAAO,MAAM,OAAO,kBAAkB,KAAK;AACjD,gBAAQ,IAAI,SAAS,KAAK,SAAS,KAAK,KAAK,UAAU,GAAG;AAC1D,gBAAQ;AAAA,UACN,cAAc,KAAK,eAAe,eAAe,KAAK,cAAc,OAAO;AAAA,QAC7E;AACA,gBAAQ,IAAI,KAAK;AAAA,MACnB,SAAS,KAAK;AACZ,cAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC3D,YAAI,CAAC,IAAI,SAAS,KAAK,GAAG;AACxB,kBAAQ,MAAM,wCAAwC,GAAG,EAAE;AAAA,QAC7D;AAAA,MACF;AAAA,IACF;AACA,UAAM,UAAU,MAAM,OAAO,cAAc,KAAK;AAChD,YAAQ,OAAO,MAAM,OAAO;AAAA,EAC9B,CAAC;AAEH,QACG,QAAQ,MAAM,EACd,YAAY,4DAAuD,EACnE,SAAS,WAAW,yBAAyB,EAC7C,OAAO,OAAO,aAAqB;AAClC,UAAM,SAAS,UAAU;AACzB,UAAM,QAAQ,kBAAkB,QAAQ;AACxC,UAAM,OAAO,MAAM,OAAO,kBAAkB,KAAK;AACjD,YAAQ,IAAI,eAAe,KAAK,SAAS,EAAE;AAC3C,YAAQ,IAAI,eAAe,KAAK,UAAU,EAAE;AAC5C,YAAQ,IAAI,eAAe,KAAK,eAAe,EAAE;AACjD,YAAQ,IAAI,eAAe,KAAK,cAAc,OAAO,EAAE;AAAA,EACzD,CAAC;AAEH,QACG,QAAQ,IAAI,EACZ,YAAY,0DAAqD,EACjE,SAAS,SAAS,EAClB,SAAS,UAAU,EACnB,OAAO,OAAO,WAAmB,WAAmB;AACnD,UAAM,SAAS,UAAU;AACzB,UAAM,IAAI,MAAM,gBAAgB,QAAQ,SAAS;AACjD,UAAM,OAAO,gBAAgB,EAAE,IAAI,MAAM;AACzC,YAAQ,IAAI,uBAAuB,MAAM,EAAE;AAAA,EAC7C,CAAC;AAGH,UACG,QAAQ,WAAW,EACnB,YAAY,6DAAwD,EACpE,SAAS,aAAa,EACtB,OAAO,OAAO,SAAmB;AAChC,UAAM,SAAS,UAAU;AACzB,UAAM,EAAE,SAAS,KAAK,IAAI,MAAM,cAAc,QAAQ,IAAI;AAC1D,QAAI,CAAC,MAAM;AACT,cAAQ;AAAA,QACN;AAAA,MACF;AACA,cAAQ,KAAK,CAAC;AAAA,IAChB;AACA,UAAM,MAAM,MAAM,OAAO,WAAW,SAAS,IAAI;AACjD,YAAQ,IAAI,IAAI,GAAG;AAAA,EACrB,CAAC;AAGH,UACG,QAAQ,MAAM,EACd;AAAA,IACC;AAAA,EACF,EACC,SAAS,YAAY,kCAAkC,EACvD,SAAS,QAAQ,aAAa,EAC9B,SAAS,UAAU,iCAAiC,EACpD,OAAO,OAAO,QAAgB,IAAY,SAAkB;AAC3D,UAAM,SAAS,UAAU;AACzB,UAAM,EAAE,SAAS,KAAK,IAAI,MAAM,cAAc,QAAQ,CAAC,MAAM,CAAC;AAC9D,QAAI,MAAM;AACR,YAAM,SAAS,MAAM,OAAO,SAAS,SAAS,MAAM,IAAI,IAAI;AAC5D,UAAI,OAAO,MAAM;AACf,gBAAQ,OAAO,MAAM,OAAO,IAAI;AAAA,MAClC,OAAO;AACL,gBAAQ,IAAI,aAAa;AAAA,MAC3B;AAAA,IACF,OAAO;AACL,YAAM,SAAS,MAAM,OAAO,YAAY,SAAS,IAAI,IAAI;AACzD,UAAI,OAAO,MAAM,WAAW,GAAG;AAC7B,gBAAQ,IAAI,aAAa;AACzB;AAAA,MACF;AACA,iBAAW,KAAK,OAAO,OAAO;AAC5B,gBAAQ,IAAI,GAAG,EAAE,MAAM,KAAK,EAAE,IAAI,EAAE;AAAA,MACtC;AAAA,IACF;AAAA,EACF,CAAC;AACL;","names":["readFileSync","readFileSync","s"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/mcp.ts"],"sourcesContent":["/**\n * DocSync MCP Server (stdio transport)\n *\n * Usage:\n * docz mcp\n *\n * 环境变量:\n * DOCSYNC_API_TOKEN — 必须\n * DOCSYNC_BASE_URL — 可选,默认 https://docz.zhenguanyu.com\n */\n\nimport { Server } from '@modelcontextprotocol/sdk/server/index.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport {\n CallToolRequestSchema,\n ListToolsRequestSchema,\n} from '@modelcontextprotocol/sdk/types.js';\nimport { ConflictError, DocSyncClient } from './client.js';\nimport { parseExpires } from './commands.js';\nimport { getBaseUrl, getToken } from './config.js';\n\nfunction getClient(): DocSyncClient {\n const token = getToken();\n if (!token) {\n throw new Error(\n 'DOCSYNC_API_TOKEN not set. Run `docz login --token <token>` or set the env var.'\n );\n }\n return new DocSyncClient(getBaseUrl(), token);\n}\n\nasync function resolveSpaceId(\n client: DocSyncClient,\n nameOrId: string\n): Promise<string> {\n const space = await client.resolveSpace(nameOrId);\n return space.id;\n}\n\nfunction formatSize(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n}\n\nfunction ok(text: string) {\n return { content: [{ type: 'text' as const, text }] };\n}\n\nfunction fail(err: unknown) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `Error: ${err instanceof Error ? err.message : String(err)}`,\n },\n ],\n isError: true,\n };\n}\n\nexport async function startMcpServer(): Promise<void> {\n const server = new Server(\n { name: 'docz-mcp', version: '0.5.0' },\n { capabilities: { tools: {} } }\n );\n\n server.setRequestHandler(ListToolsRequestSchema, async () => ({\n tools: [\n {\n name: 'docz_list_spaces',\n description: '列出所有可访问的 DocSync Space(个人空间和团队空间)',\n inputSchema: { type: 'object' as const, properties: {} },\n },\n {\n name: 'docz_list_files',\n description: '列出 DocSync Space 中指定目录的文件和文件夹',\n inputSchema: {\n type: 'object' as const,\n properties: {\n space: {\n type: 'string',\n description: 'Space 名称或 ID',\n },\n path: {\n type: 'string',\n description: '目录路径,空字符串表示根目录',\n default: '',\n },\n recursive: {\n type: 'boolean',\n description: '是否递归列出所有子目录',\n default: false,\n },\n },\n required: ['space'],\n },\n },\n {\n name: 'docz_read_file',\n description:\n '读取 DocSync 文件内容(Markdown、CSV、HTML 等文本文件)。返回格式:第一行 [ref: <commit_hash>],空行后是文件内容。保存时请将 ref 值作为 base_ref 传入 docz_save_file 以检测冲突',\n inputSchema: {\n type: 'object' as const,\n properties: {\n space: {\n type: 'string',\n description: 'Space 名称或 ID',\n },\n path: { type: 'string', description: '文件路径' },\n },\n required: ['space', 'path'],\n },\n },\n {\n name: 'docz_save_file',\n description:\n '保存/编辑文档内容(支持冲突检测)。建议先用 docz_read_file 获取 ref,再传入 base_ref 以检测并发冲突。如果返回冲突错误,请重新用 docz_read_file 获取最新内容,重新修改后再保存',\n inputSchema: {\n type: 'object' as const,\n properties: {\n space: {\n type: 'string',\n description: 'Space 名称或 ID',\n },\n path: { type: 'string', description: '文件路径' },\n content: { type: 'string', description: '文件内容' },\n base_ref: {\n type: 'string',\n description: '读取时获得的 ref,用于冲突检测(可选)',\n },\n message: {\n type: 'string',\n description: '提交消息(可选)',\n },\n },\n required: ['space', 'path', 'content'],\n },\n },\n {\n name: 'docz_upload_file',\n description: '上传/创建文件到 DocSync Space',\n inputSchema: {\n type: 'object' as const,\n properties: {\n space: {\n type: 'string',\n description: 'Space 名称或 ID',\n },\n path: {\n type: 'string',\n description: '目标目录路径(如 reports)',\n },\n filename: {\n type: 'string',\n description: '文件名(如 summary.md)',\n },\n content: { type: 'string', description: '文件内容' },\n },\n required: ['space', 'filename', 'content'],\n },\n },\n {\n name: 'docz_mkdir',\n description: '在 DocSync Space 中创建文件夹',\n inputSchema: {\n type: 'object' as const,\n properties: {\n space: {\n type: 'string',\n description: 'Space 名称或 ID',\n },\n path: {\n type: 'string',\n description: '要创建的文件夹路径',\n },\n },\n required: ['space', 'path'],\n },\n },\n {\n name: 'docz_delete',\n description: '删除文件或文件夹(进入回收站,30 天内可恢复)',\n inputSchema: {\n type: 'object' as const,\n properties: {\n space: {\n type: 'string',\n description: 'Space 名称或 ID',\n },\n path: { type: 'string', description: '要删除的路径' },\n },\n required: ['space', 'path'],\n },\n },\n {\n name: 'docz_file_history',\n description: '查看文件的变更历史(基于 Git 版本控制)',\n inputSchema: {\n type: 'object' as const,\n properties: {\n space: {\n type: 'string',\n description: 'Space 名称或 ID',\n },\n path: { type: 'string', description: '文件路径' },\n },\n required: ['space'],\n },\n },\n {\n name: 'docz_rollback',\n description: '将文件回滚到指定的历史版本(通过 commit hash)',\n inputSchema: {\n type: 'object' as const,\n properties: {\n space: {\n type: 'string',\n description: 'Space 名称或 ID',\n },\n path: { type: 'string', description: '文件路径' },\n commit: {\n type: 'string',\n description: '目标 commit hash(通过 docz_file_history 获取)',\n },\n },\n required: ['space', 'path', 'commit'],\n },\n },\n {\n name: 'docz_trash',\n description: '查看回收站中的已删除文件列表',\n inputSchema: {\n type: 'object' as const,\n properties: {\n space: {\n type: 'string',\n description: 'Space 名称或 ID',\n },\n },\n required: ['space'],\n },\n },\n {\n name: 'docz_restore',\n description: '从回收站恢复已删除的文件',\n inputSchema: {\n type: 'object' as const,\n properties: {\n space: {\n type: 'string',\n description: 'Space 名称或 ID',\n },\n path: {\n type: 'string',\n description: '被删除的文件路径',\n },\n commit: {\n type: 'string',\n description: '删除时的 commit hash(通过 docz_trash 获取)',\n },\n },\n required: ['space', 'path', 'commit'],\n },\n },\n {\n name: 'docz_list_comments',\n description: '列出文件的评论和回复',\n inputSchema: {\n type: 'object' as const,\n properties: {\n space: {\n type: 'string',\n description: 'Space 名称或 ID',\n },\n path: { type: 'string', description: '文件路径' },\n },\n required: ['space', 'path'],\n },\n },\n {\n name: 'docz_add_comment',\n description:\n '在文件上添加评论。支持 @email 格式提及其他用户。可通过 quote 引用文件中的原文(划线评论),引用内容会在 Web UI 高亮显示',\n inputSchema: {\n type: 'object' as const,\n properties: {\n space: {\n type: 'string',\n description: 'Space 名称或 ID',\n },\n path: { type: 'string', description: '文件路径' },\n content: {\n type: 'string',\n description: '评论内容',\n },\n quote: {\n type: 'string',\n description:\n '引用的原文内容(划线评论)。从文件中复制要评论的文字片段,建议 10 字以上以避免重复匹配',\n },\n },\n required: ['space', 'path', 'content'],\n },\n },\n {\n name: 'docz_reply_comment',\n description: '回复指定评论',\n inputSchema: {\n type: 'object' as const,\n properties: {\n space: {\n type: 'string',\n description: 'Space 名称或 ID',\n },\n comment_id: {\n type: 'number',\n description: '评论 ID',\n },\n content: {\n type: 'string',\n description: '回复内容',\n },\n },\n required: ['space', 'comment_id', 'content'],\n },\n },\n {\n name: 'docz_close_comment',\n description: '关闭评论(标记为已解决)',\n inputSchema: {\n type: 'object' as const,\n properties: {\n space: {\n type: 'string',\n description: 'Space 名称或 ID',\n },\n comment_id: {\n type: 'number',\n description: '评论 ID',\n },\n },\n required: ['space', 'comment_id'],\n },\n },\n {\n name: 'docz_share_create',\n description: '创建文件分享链接',\n inputSchema: {\n type: 'object' as const,\n properties: {\n space: {\n type: 'string',\n description: 'Space 名称或 ID',\n },\n path: { type: 'string', description: '文件路径' },\n expires: {\n type: 'string',\n description: '过期时间,如 7d, 24h',\n },\n userIds: {\n type: 'array',\n items: { type: 'string' },\n description: '可见用户 ID 列表',\n },\n groupIds: {\n type: 'array',\n items: { type: 'string' },\n description: '可见组 ID 列表',\n },\n },\n required: ['space', 'path'],\n },\n },\n {\n name: 'docz_share_list',\n description: '列出空间的分享链接',\n inputSchema: {\n type: 'object' as const,\n properties: {\n space: {\n type: 'string',\n description: 'Space 名称或 ID',\n },\n filePath: {\n type: 'string',\n description: '按文件路径过滤',\n },\n },\n required: ['space'],\n },\n },\n {\n name: 'docz_share_read',\n description: '通过分享 token 读取文件内容',\n inputSchema: {\n type: 'object' as const,\n properties: {\n token: {\n type: 'string',\n description: '分享链接 token',\n },\n },\n required: ['token'],\n },\n },\n {\n name: 'docz_share_info',\n description: '查看分享链接信息',\n inputSchema: {\n type: 'object' as const,\n properties: {\n token: {\n type: 'string',\n description: '分享链接 token',\n },\n },\n required: ['token'],\n },\n },\n {\n name: 'docz_share_delete',\n description: '删除分享链接',\n inputSchema: {\n type: 'object' as const,\n properties: {\n space: {\n type: 'string',\n description: 'Space 名称或 ID',\n },\n linkId: {\n type: 'string',\n description: '分享链接 ID',\n },\n },\n required: ['space', 'linkId'],\n },\n },\n {\n name: 'docz_shortlink',\n description: '获取文件的短链接 URL,可直接在浏览器打开',\n inputSchema: {\n type: 'object' as const,\n properties: {\n space: {\n type: 'string',\n description: 'Space 名称或 ID',\n },\n path: { type: 'string', description: '文件路径' },\n },\n required: ['space', 'path'],\n },\n },\n {\n name: 'docz_diff',\n description: '查看文件或 Space 的变更 diff',\n inputSchema: {\n type: 'object' as const,\n properties: {\n space: {\n type: 'string',\n description: 'Space 名称或 ID',\n },\n path: {\n type: 'string',\n description: '文件路径(空则返回变更文件列表)',\n },\n to: {\n type: 'string',\n description: '目标 commit hash',\n },\n from: {\n type: 'string',\n description: '起始 commit hash(默认 to^)',\n },\n },\n required: ['space', 'to'],\n },\n },\n ],\n }));\n\n server.setRequestHandler(CallToolRequestSchema, async (request) => {\n const args = (request.params.arguments ?? {}) as Record<string, unknown>;\n\n try {\n const client = getClient();\n\n switch (request.params.name) {\n case 'docz_list_spaces': {\n const spaces = await client.listSpaces();\n const lines = spaces.map(\n (s) =>\n `${s.name} (${s.is_private ? '私有' : '团队'}, ${s.member_count} 人) id=${s.id}`\n );\n return ok(lines.join('\\n'));\n }\n\n case 'docz_list_files': {\n const sid = await resolveSpaceId(client, String(args.space));\n const entries = args.recursive\n ? await client.treeFull(sid)\n : await client.ls(sid, String(args.path ?? ''));\n if (entries.length === 0) return ok('(空目录)');\n const lines = entries.map((e) => {\n const size = e.type === 'blob' ? ` (${formatSize(e.size)})` : '';\n return `${e.type === 'tree' ? '📁' : '📄'} ${e.name}${size}`;\n });\n return ok(lines.join('\\n'));\n }\n\n case 'docz_read_file': {\n const sid = await resolveSpaceId(client, String(args.space));\n const result = await client.catWithRef(sid, String(args.path));\n const header = result.ref ? `[ref: ${result.ref}]\\n\\n` : '';\n return ok(header + result.content);\n }\n\n case 'docz_save_file': {\n const sid = await resolveSpaceId(client, String(args.space));\n const savePath = String(args.path);\n const saveContent = String(args.content);\n const saveMessage = args.message ? String(args.message) : undefined;\n const baseRef = args.base_ref ? String(args.base_ref) : undefined;\n\n if (Buffer.byteLength(saveContent, 'utf-8') > 2 * 1024 * 1024) {\n return fail('内容超过 2MB 限制,请使用 docz_upload_file 上传');\n }\n\n try {\n const result = await client.save(sid, savePath, saveContent, {\n baseRef,\n message: saveMessage,\n });\n return ok(`已保存: ${result.path} (ref: ${result.ref})`);\n } catch (err) {\n if (err instanceof ConflictError) {\n return fail(\n `冲突:文件已被他人修改(当前 ref: ${err.detail.current_ref})。请先用 docz_read_file 获取最新内容,重新修改后再保存。`\n );\n }\n throw err;\n }\n }\n\n case 'docz_upload_file': {\n const sid = await resolveSpaceId(client, String(args.space));\n const result = await client.upload(\n sid,\n String(args.path ?? ''),\n String(args.filename),\n String(args.content)\n );\n return ok(`已上传: ${result.path}`);\n }\n\n case 'docz_mkdir': {\n const sid = await resolveSpaceId(client, String(args.space));\n await client.mkdir(sid, String(args.path));\n return ok(`已创建: ${args.path}`);\n }\n\n case 'docz_delete': {\n const sid = await resolveSpaceId(client, String(args.space));\n await client.rm(sid, String(args.path));\n return ok(`已删除: ${args.path}(30 天内可从回收站恢复)`);\n }\n\n case 'docz_file_history': {\n const sid = await resolveSpaceId(client, String(args.space));\n const logs = await client.log(\n sid,\n args.path ? String(args.path) : undefined\n );\n if (logs.length === 0) return ok('没有变更历史。');\n const lines = logs.map((l) => `${l.hash} ${l.date} ${l.message}`);\n return ok(lines.join('\\n'));\n }\n\n case 'docz_rollback': {\n const sid = await resolveSpaceId(client, String(args.space));\n await client.rollback(sid, String(args.path), String(args.commit));\n return ok(\n `已回滚: ${args.path} → ${String(args.commit).substring(0, 7)}`\n );\n }\n\n case 'docz_trash': {\n const sid = await resolveSpaceId(client, String(args.space));\n const items = await client.trash(sid);\n if (items.length === 0) return ok('回收站为空。');\n const lines = items.map(\n (t) =>\n `${t.path} 删除于 ${t.deleted_at} commit: ${t.commit.substring(0, 7)}`\n );\n return ok(lines.join('\\n'));\n }\n\n case 'docz_restore': {\n const sid = await resolveSpaceId(client, String(args.space));\n await client.restore(sid, String(args.path), String(args.commit));\n return ok(`已恢复: ${args.path}`);\n }\n\n case 'docz_list_comments': {\n const sid = await resolveSpaceId(client, String(args.space));\n const comments = await client.listComments(sid, String(args.path));\n if (comments.length === 0) return ok('没有评论。');\n const lines = comments.map((c) => {\n const status = c.is_closed ? ' [已关闭]' : '';\n const quote = c.target_content ? `\\n > ${c.target_content}` : '';\n let text = `#${c.id} ${c.user_name}${status}:${quote}\\n ${c.content}`;\n for (const r of c.replies) {\n text += `\\n ↳ ${r.user_name}: ${r.content}`;\n }\n return text;\n });\n return ok(lines.join('\\n\\n'));\n }\n\n case 'docz_add_comment': {\n const sid = await resolveSpaceId(client, String(args.space));\n const quote = args.quote ? String(args.quote) : undefined;\n const c = await client.createComment(\n sid,\n String(args.path),\n String(args.content),\n { quote }\n );\n return ok(`评论 #${c.id} 已创建`);\n }\n\n case 'docz_reply_comment': {\n const sid = await resolveSpaceId(client, String(args.space));\n const r = await client.replyComment(\n sid,\n Number(args.comment_id),\n String(args.content)\n );\n return ok(`回复 #${r.id} 已创建`);\n }\n\n case 'docz_close_comment': {\n const sid = await resolveSpaceId(client, String(args.space));\n await client.closeComment(sid, Number(args.comment_id));\n return ok(`评论 #${args.comment_id} 已关闭`);\n }\n\n case 'docz_share_create': {\n const sharePath = String(args.path ?? '');\n if (!sharePath) return fail('path is required');\n const sid = await resolveSpaceId(client, String(args.space));\n const opts: {\n expiresAt?: string;\n userIds?: string[];\n groupIds?: string[];\n } = {};\n if (args.expires) opts.expiresAt = parseExpires(String(args.expires));\n if (args.userIds) opts.userIds = args.userIds as string[];\n if (args.groupIds) opts.groupIds = args.groupIds as string[];\n const link = await client.createShareLink(sid, sharePath, opts);\n return ok(\n `已创建分享链接:\\ntoken: ${link.token}\\nurl: ${getBaseUrl()}/share/${link.token}\\n过期: ${link.expires_at ?? '永不'}`\n );\n }\n\n case 'docz_share_list': {\n const sid = await resolveSpaceId(client, String(args.space));\n const links = await client.listShareLinks(\n sid,\n args.filePath ? String(args.filePath) : undefined\n );\n if (links.length === 0) return ok('没有分享链接。');\n const lines = links.map(\n (l) =>\n `${l.token} ${l.file_path} 过期: ${l.expires_at ?? '永不'} 创建者: ${l.created_by_name ?? l.created_by_email ?? l.created_by}`\n );\n return ok(lines.join('\\n'));\n }\n\n case 'docz_share_read': {\n const content = await client.getSharedFile(String(args.token));\n return ok(content);\n }\n\n case 'docz_share_info': {\n const info = await client.getSharedFileInfo(String(args.token));\n return ok(\n `文件: ${info.file_path}\\nSpace: ${info.space_name}\\n分享者: ${info.created_by_name}\\n过期: ${info.expires_at ?? '永不'}`\n );\n }\n\n case 'docz_share_delete': {\n const sid = await resolveSpaceId(client, String(args.space));\n await client.deleteShareLink(sid, String(args.linkId));\n return ok(`已删除分享链接: ${args.linkId}`);\n }\n\n case 'docz_shortlink': {\n const sid = await resolveSpaceId(client, String(args.space));\n const ref = await client.getFileRef(sid, String(args.path));\n return ok(ref.url);\n }\n\n case 'docz_diff': {\n const sid = await resolveSpaceId(client, String(args.space));\n const path = args.path ? String(args.path) : '';\n const from = args.from ? String(args.from) : undefined;\n if (path) {\n const result = await client.diffFile(\n sid,\n path,\n String(args.to),\n from\n );\n return ok(result.diff || '没有变更。');\n }\n const result = await client.diffSummary(sid, String(args.to), from);\n if (result.files.length === 0) return ok('没有变更。');\n const lines = result.files.map((f) => `${f.status} ${f.path}`);\n return ok(lines.join('\\n'));\n }\n\n default:\n return fail(`Unknown tool: ${request.params.name}`);\n }\n } catch (err) {\n return fail(err);\n }\n });\n\n const transport = new StdioServerTransport();\n await server.connect(transport);\n}\n"],"mappings":"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","names":["result"]}