feishu-docs-cli 0.1.0-beta.8 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. package/README.md +70 -13
  2. package/README.zh.md +53 -13
  3. package/dist/auth.js +31 -17
  4. package/dist/auth.js.map +1 -1
  5. package/dist/cli.js +16 -4
  6. package/dist/cli.js.map +1 -1
  7. package/dist/client.d.ts +4 -2
  8. package/dist/client.js +177 -61
  9. package/dist/client.js.map +1 -1
  10. package/dist/commands/authorize.d.ts +3 -0
  11. package/dist/commands/authorize.js +16 -34
  12. package/dist/commands/authorize.js.map +1 -1
  13. package/dist/commands/cp.d.ts +9 -0
  14. package/dist/commands/cp.js +70 -0
  15. package/dist/commands/cp.js.map +1 -0
  16. package/dist/commands/create.js +21 -7
  17. package/dist/commands/create.js.map +1 -1
  18. package/dist/commands/delete.js +53 -54
  19. package/dist/commands/delete.js.map +1 -1
  20. package/dist/commands/login.js +6 -2
  21. package/dist/commands/login.js.map +1 -1
  22. package/dist/commands/ls.js +38 -38
  23. package/dist/commands/ls.js.map +1 -1
  24. package/dist/commands/mkdir.d.ts +6 -0
  25. package/dist/commands/mkdir.js +49 -0
  26. package/dist/commands/mkdir.js.map +1 -0
  27. package/dist/commands/mv.d.ts +9 -0
  28. package/dist/commands/mv.js +72 -0
  29. package/dist/commands/mv.js.map +1 -0
  30. package/dist/commands/read.d.ts +1 -1
  31. package/dist/commands/read.js +17 -354
  32. package/dist/commands/read.js.map +1 -1
  33. package/dist/commands/search.js +57 -55
  34. package/dist/commands/search.js.map +1 -1
  35. package/dist/commands/share.d.ts +1 -1
  36. package/dist/commands/share.js +164 -91
  37. package/dist/commands/share.js.map +1 -1
  38. package/dist/commands/update.js +43 -60
  39. package/dist/commands/update.js.map +1 -1
  40. package/dist/commands/wiki.js +8 -20
  41. package/dist/commands/wiki.js.map +1 -1
  42. package/dist/parser/block-types.d.ts +0 -1
  43. package/dist/parser/block-types.js +0 -22
  44. package/dist/parser/block-types.js.map +1 -1
  45. package/dist/parser/blocks-to-md.d.ts +10 -18
  46. package/dist/parser/blocks-to-md.js +341 -450
  47. package/dist/parser/blocks-to-md.js.map +1 -1
  48. package/dist/scopes.d.ts +5 -47
  49. package/dist/scopes.js +9 -54
  50. package/dist/scopes.js.map +1 -1
  51. package/dist/services/block-writer.d.ts +3 -2
  52. package/dist/services/block-writer.js +29 -13
  53. package/dist/services/block-writer.js.map +1 -1
  54. package/dist/services/doc-blocks.d.ts +1 -1
  55. package/dist/services/doc-blocks.js +1 -1
  56. package/dist/services/doc-blocks.js.map +1 -1
  57. package/dist/services/doc-enrichment.d.ts +64 -0
  58. package/dist/services/doc-enrichment.js +397 -0
  59. package/dist/services/doc-enrichment.js.map +1 -0
  60. package/dist/services/image-download.d.ts +31 -0
  61. package/dist/services/image-download.js +127 -0
  62. package/dist/services/image-download.js.map +1 -0
  63. package/dist/services/markdown-convert.d.ts +20 -0
  64. package/dist/services/markdown-convert.js +55 -1
  65. package/dist/services/markdown-convert.js.map +1 -1
  66. package/dist/services/wiki-nodes.d.ts +1 -1
  67. package/dist/services/wiki-nodes.js +2 -3
  68. package/dist/services/wiki-nodes.js.map +1 -1
  69. package/dist/types/api-responses.d.ts +34 -0
  70. package/dist/types/api-responses.js +8 -0
  71. package/dist/types/api-responses.js.map +1 -0
  72. package/dist/types/index.d.ts +9 -17
  73. package/dist/utils/concurrency.d.ts +12 -0
  74. package/dist/utils/concurrency.js +37 -0
  75. package/dist/utils/concurrency.js.map +1 -0
  76. package/dist/utils/errors.d.ts +3 -1
  77. package/dist/utils/errors.js +11 -7
  78. package/dist/utils/errors.js.map +1 -1
  79. package/dist/utils/retry.d.ts +49 -0
  80. package/dist/utils/retry.js +70 -0
  81. package/dist/utils/retry.js.map +1 -0
  82. package/dist/utils/scope-prompt.d.ts +23 -18
  83. package/dist/utils/scope-prompt.js +62 -51
  84. package/dist/utils/scope-prompt.js.map +1 -1
  85. package/package.json +3 -1
  86. package/skills/feishu-docs/SKILL.md +37 -2
@@ -35,6 +35,57 @@ export function normalizeLangNames(markdown) {
35
35
  return alias ? fence + alias : match;
36
36
  });
37
37
  }
38
+ /**
39
+ * Extract the first top-level heading (# title) from markdown.
40
+ *
41
+ * Returns the title text and the remaining body with the heading line removed.
42
+ * Only matches `# heading` (H1), not `## heading` (H2+).
43
+ * Ignores leading blank lines before the heading.
44
+ * If no H1 heading is found, returns null title and the original markdown.
45
+ */
46
+ export function extractMarkdownTitle(markdown) {
47
+ const lines = markdown.split("\n");
48
+ let headingIndex = -1;
49
+ for (let i = 0; i < lines.length; i++) {
50
+ const trimmed = lines[i].trim();
51
+ if (trimmed === "")
52
+ continue;
53
+ // Match exactly one # followed by space (H1 only, not ##)
54
+ const match = trimmed.match(/^#\s+(.+)$/);
55
+ if (match) {
56
+ headingIndex = i;
57
+ }
58
+ break; // Only check the first non-empty line
59
+ }
60
+ if (headingIndex === -1) {
61
+ return { title: null, body: markdown };
62
+ }
63
+ const title = lines[headingIndex].trim().replace(/^#\s+/, "");
64
+ const remaining = [
65
+ ...lines.slice(0, headingIndex),
66
+ ...lines.slice(headingIndex + 1),
67
+ ];
68
+ // Remove leading blank lines left after title extraction
69
+ let startIdx = 0;
70
+ while (startIdx < remaining.length && remaining[startIdx].trim() === "") {
71
+ startIdx++;
72
+ }
73
+ const body = remaining.slice(startIdx).join("\n");
74
+ return { title, body };
75
+ }
76
+ /**
77
+ * Replace literal `\n` with `<br>` inside mermaid code blocks.
78
+ *
79
+ * Claude and other AI tools generate mermaid node labels with `\n` for
80
+ * line breaks (e.g. `A[Line 1\nLine 2]`), but standard mermaid syntax
81
+ * requires `<br>` (e.g. `A[Line 1<br>Line 2]`).
82
+ */
83
+ export function normalizeMermaidLineBreaks(markdown) {
84
+ return markdown.replace(/^```mermaid\s*\n([\s\S]*?)^```/gm, (_match, block) => {
85
+ const fixed = block.replace(/\\n/g, "<br>");
86
+ return "```mermaid\n" + fixed + "```";
87
+ });
88
+ }
38
89
  /**
39
90
  * Convert markdown string to Feishu block array via Convert API.
40
91
  * Requires scope: docx:document.block:convert
@@ -44,7 +95,10 @@ export function normalizeLangNames(markdown) {
44
95
  export async function convertMarkdown(authInfo, markdown) {
45
96
  const res = await fetchWithAuth(authInfo, "/open-apis/docx/v1/documents/blocks/convert", {
46
97
  method: "POST",
47
- body: { content: normalizeLangNames(markdown), content_type: "markdown" },
98
+ body: {
99
+ content: normalizeMermaidLineBreaks(normalizeLangNames(markdown)),
100
+ content_type: "markdown",
101
+ },
48
102
  });
49
103
  const data = res?.data;
50
104
  if (!data?.blocks || !data?.first_level_block_ids) {
@@ -1 +1 @@
1
- {"version":3,"file":"markdown-convert.js","sourceRoot":"","sources":["../../src/services/markdown-convert.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"markdown-convert.js","sourceRoot":"","sources":["../../src/services/markdown-convert.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Shared wiki node helpers.
3
3
  */
4
- import { AuthInfo, WikiNode } from "../types/index.js";
4
+ import type { AuthInfo, WikiNode } from "../types/index.js";
5
5
  export interface ResolvedWikiNode {
6
6
  objToken: string;
7
7
  objType: string;
@@ -16,7 +16,7 @@ export async function fetchChildren(authInfo, spaceId, parentNodeToken) {
16
16
  ...(parentNodeToken && { parent_node_token: parentNodeToken }),
17
17
  };
18
18
  const res = await fetchWithAuth(authInfo, `/open-apis/wiki/v2/spaces/${encodeURIComponent(spaceId)}/nodes`, { params });
19
- const data = res?.data;
19
+ const data = res.data;
20
20
  if (data?.items) {
21
21
  nodes.push(...data.items);
22
22
  }
@@ -29,8 +29,7 @@ export async function fetchChildren(authInfo, spaceId, parentNodeToken) {
29
29
  */
30
30
  export async function resolveWikiToken(authInfo, wikiToken) {
31
31
  const res = await fetchWithAuth(authInfo, "/open-apis/wiki/v2/spaces/get_node", { params: { token: wikiToken, obj_type: "wiki" } });
32
- const data = res?.data;
33
- const node = data?.node;
32
+ const node = res.data?.node;
34
33
  if (!node) {
35
34
  throw new CliError("NOT_FOUND", `知识库节点不存在: ${wikiToken}`);
36
35
  }
@@ -1 +1 @@
1
- {"version":3,"file":"wiki-nodes.js","sourceRoot":"","sources":["../../src/services/wiki-nodes.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAY9C;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,QAAkB,EAClB,OAAe,EACf,eAAwB;IAExB,MAAM,KAAK,GAAe,EAAE,CAAC;IAC7B,IAAI,SAA6B,CAAC;IAElC,GAAG,CAAC;QACF,MAAM,MAAM,GAAgD;YAC1D,SAAS,EAAE,EAAE;YACb,GAAG,CAAC,SAAS,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,CAAC;YAC3C,GAAG,CAAC,eAAe,IAAI,EAAE,iBAAiB,EAAE,eAAe,EAAE,CAAC;SAC/D,CAAC;QAEF,MAAM,GAAG,GAAG,MAAM,aAAa,CAC7B,QAAQ,EACR,6BAA6B,kBAAkB,CAAC,OAAO,CAAC,QAAQ,EAChE,EAAE,MAAM,EAAE,CACX,CAAC;QAEF,MAAM,IAAI,GAAG,GAAG,EAAE,IAA2C,CAAC;QAC9D,IAAI,IAAI,EAAE,KAAK,EAAE,CAAC;YAChB,KAAK,CAAC,IAAI,CAAC,GAAI,IAAI,CAAC,KAAoB,CAAC,CAAC;QAC5C,CAAC;QACD,SAAS,GAAG,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAE,IAAI,CAAC,UAAqB,CAAC,CAAC,CAAC,SAAS,CAAC;IACvE,CAAC,QAAQ,SAAS,EAAE;IAEpB,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,QAAkB,EAClB,SAAiB;IAEjB,MAAM,GAAG,GAAG,MAAM,aAAa,CAC7B,QAAQ,EACR,oCAAoC,EACpC,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,CACnD,CAAC;IAEF,MAAM,IAAI,GAAG,GAAG,EAAE,IAA2C,CAAC;IAC9D,MAAM,IAAI,GAAG,IAAI,EAAE,IAA2C,CAAC;IAC/D,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,IAAI,QAAQ,CAAC,WAAW,EAAE,aAAa,SAAS,EAAE,CAAC,CAAC;IAC5D,CAAC;IAED,OAAO;QACL,QAAQ,EAAG,IAAI,CAAC,SAAoB,IAAI,EAAE;QAC1C,OAAO,EAAG,IAAI,CAAC,QAAmB,IAAI,EAAE;QACxC,KAAK,EAAG,IAAI,CAAC,KAAgB,IAAI,EAAE;QACnC,SAAS,EAAG,IAAI,CAAC,UAAqB,IAAI,EAAE;QAC5C,OAAO,EAAG,IAAI,CAAC,QAAmB,IAAI,EAAE;QACxC,QAAQ,EAAG,IAAI,CAAC,SAAqB,IAAI,KAAK;KAC/C,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"wiki-nodes.js","sourceRoot":"","sources":["../../src/services/wiki-nodes.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAgB9C;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,QAAkB,EAClB,OAAe,EACf,eAAwB;IAExB,MAAM,KAAK,GAAe,EAAE,CAAC;IAC7B,IAAI,SAA6B,CAAC;IAElC,GAAG,CAAC;QACF,MAAM,MAAM,GAAgD;YAC1D,SAAS,EAAE,EAAE;YACb,GAAG,CAAC,SAAS,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,CAAC;YAC3C,GAAG,CAAC,eAAe,IAAI,EAAE,iBAAiB,EAAE,eAAe,EAAE,CAAC;SAC/D,CAAC;QAEF,MAAM,GAAG,GAAG,MAAM,aAAa,CAC7B,QAAQ,EACR,6BAA6B,kBAAkB,CAAC,OAAO,CAAC,QAAQ,EAChE,EAAE,MAAM,EAAE,CACX,CAAC;QAEF,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC;QACtB,IAAI,IAAI,EAAE,KAAK,EAAE,CAAC;YAChB,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;QAC5B,CAAC;QACD,SAAS,GAAG,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC;IAC3D,CAAC,QAAQ,SAAS,EAAE;IAEpB,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,QAAkB,EAClB,SAAiB;IAEjB,MAAM,GAAG,GAAG,MAAM,aAAa,CAC7B,QAAQ,EACR,oCAAoC,EACpC,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,CACnD,CAAC;IAEF,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC;IAC5B,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,IAAI,QAAQ,CAAC,WAAW,EAAE,aAAa,SAAS,EAAE,CAAC,CAAC;IAC5D,CAAC;IAED,OAAO;QACL,QAAQ,EAAE,IAAI,CAAC,SAAS,IAAI,EAAE;QAC9B,OAAO,EAAE,IAAI,CAAC,QAAQ,IAAI,EAAE;QAC5B,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,EAAE;QACvB,SAAS,EAAE,IAAI,CAAC,UAAU,IAAI,EAAE;QAChC,OAAO,EAAE,IAAI,CAAC,QAAQ,IAAI,EAAE;QAC5B,QAAQ,EAAE,IAAI,CAAC,SAAS,IAAI,KAAK;KAClC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Typed API response data interfaces for Feishu Open API endpoints.
3
+ *
4
+ * Each interface describes the shape of the `data` field in ApiResponse<T>.
5
+ * Used with fetchWithAuth<T>() for compile-time type safety.
6
+ */
7
+ import type { Block, WikiNode } from "./index.js";
8
+ /** GET /open-apis/docx/v1/documents/{document_id}/blocks */
9
+ export interface DocxBlocksResponse {
10
+ items?: Block[];
11
+ has_more?: boolean;
12
+ page_token?: string;
13
+ }
14
+ /** GET /open-apis/wiki/v2/spaces/{space_id}/nodes */
15
+ export interface WikiChildrenResponse {
16
+ items?: WikiNode[];
17
+ has_more?: boolean;
18
+ page_token?: string;
19
+ }
20
+ /** GET /open-apis/wiki/v2/spaces/get_node */
21
+ export interface WikiGetNodeResponse {
22
+ node?: {
23
+ obj_token: string;
24
+ obj_type: string;
25
+ title: string;
26
+ node_token: string;
27
+ space_id: string;
28
+ has_child: boolean;
29
+ parent_node_token?: string;
30
+ node_type?: string;
31
+ origin_node_token?: string;
32
+ origin_space_id?: string;
33
+ };
34
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Typed API response data interfaces for Feishu Open API endpoints.
3
+ *
4
+ * Each interface describes the shape of the `data` field in ApiResponse<T>.
5
+ * Used with fetchWithAuth<T>() for compile-time type safety.
6
+ */
7
+ export {};
8
+ //# sourceMappingURL=api-responses.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-responses.js","sourceRoot":"","sources":["../../src/types/api-responses.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
@@ -1,11 +1,13 @@
1
1
  /**
2
2
  * Shared type definitions for feishu-docs CLI.
3
3
  */
4
- export type ErrorType = "INVALID_ARGS" | "FILE_NOT_FOUND" | "AUTH_REQUIRED" | "TOKEN_EXPIRED" | "PERMISSION_DENIED" | "NOT_FOUND" | "NOT_SUPPORTED" | "RATE_LIMITED" | "API_ERROR";
4
+ export type ErrorType = "INVALID_ARGS" | "FILE_NOT_FOUND" | "AUTH_REQUIRED" | "TOKEN_EXPIRED" | "PERMISSION_DENIED" | "SCOPE_MISSING" | "NOT_FOUND" | "NOT_SUPPORTED" | "RATE_LIMITED" | "API_ERROR";
5
5
  export interface CliErrorOptions {
6
6
  apiCode?: number;
7
7
  retryable?: boolean;
8
8
  recovery?: string;
9
+ /** Scope names extracted from API permission_violations (for SCOPE_MISSING errors). */
10
+ missingScopes?: string[];
9
11
  }
10
12
  export type AuthMode = "user" | "tenant" | "auto";
11
13
  export interface AuthInfo {
@@ -51,26 +53,22 @@ export interface ParsedDoc {
51
53
  type: DocType;
52
54
  token: string;
53
55
  }
54
- export interface DocumentInfo {
55
- documentId: string;
56
- objToken: string;
57
- objType: string;
58
- title: string;
59
- url?: string;
60
- revisionId?: number;
61
- nodeToken?: string;
62
- spaceId?: string;
63
- }
64
56
  export interface ApiResponse<T = unknown> {
65
57
  code?: number;
66
58
  msg?: string;
67
59
  data?: T;
68
60
  }
61
+ export interface RetryConfig {
62
+ maxRetries?: number;
63
+ initialDelay?: number;
64
+ maxDelay?: number;
65
+ }
69
66
  export interface FetchOptions {
70
67
  method?: string;
71
68
  params?: Record<string, string | number | string[] | undefined>;
72
69
  body?: unknown;
73
70
  headers?: Record<string, string>;
71
+ retry?: RetryConfig | false;
74
72
  }
75
73
  export interface TextElement {
76
74
  text_run?: {
@@ -221,12 +219,6 @@ export interface WikiNode {
221
219
  origin_node_token?: string;
222
220
  origin_space_id?: string;
223
221
  }
224
- export interface WikiSpace {
225
- space_id: string;
226
- name: string;
227
- description?: string;
228
- visibility?: string;
229
- }
230
222
  export interface ConvertedBlocks {
231
223
  blocks: Block[];
232
224
  firstLevelBlockIds: string[];
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Zero-dependency concurrency limiter (pLimit-style).
3
+ * Limits the number of concurrently executing async functions.
4
+ */
5
+ /**
6
+ * Create a concurrency limiter that allows at most `concurrency`
7
+ * async functions to execute simultaneously.
8
+ *
9
+ * @param concurrency Maximum number of concurrent executions (positive integer)
10
+ * @returns A limit function that wraps async functions with concurrency control
11
+ */
12
+ export declare function pLimit(concurrency: number): <T>(fn: () => Promise<T>) => Promise<T>;
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Zero-dependency concurrency limiter (pLimit-style).
3
+ * Limits the number of concurrently executing async functions.
4
+ */
5
+ /**
6
+ * Create a concurrency limiter that allows at most `concurrency`
7
+ * async functions to execute simultaneously.
8
+ *
9
+ * @param concurrency Maximum number of concurrent executions (positive integer)
10
+ * @returns A limit function that wraps async functions with concurrency control
11
+ */
12
+ export function pLimit(concurrency) {
13
+ if (!Number.isInteger(concurrency) || concurrency < 1) {
14
+ throw new TypeError("Expected concurrency to be a positive integer");
15
+ }
16
+ let active = 0;
17
+ const queue = [];
18
+ function next() {
19
+ if (queue.length > 0 && active < concurrency) {
20
+ active++;
21
+ const run = queue.shift();
22
+ run();
23
+ }
24
+ }
25
+ return (fn) => {
26
+ return new Promise((resolve, reject) => {
27
+ queue.push(() => {
28
+ fn().then(resolve, reject).finally(() => {
29
+ active--;
30
+ next();
31
+ });
32
+ });
33
+ next();
34
+ });
35
+ };
36
+ }
37
+ //# sourceMappingURL=concurrency.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"concurrency.js","sourceRoot":"","sources":["../../src/utils/concurrency.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;;GAMG;AACH,MAAM,UAAU,MAAM,CAAC,WAAmB;IACxC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,WAAW,CAAC,IAAI,WAAW,GAAG,CAAC,EAAE,CAAC;QACtD,MAAM,IAAI,SAAS,CAAC,+CAA+C,CAAC,CAAC;IACvE,CAAC;IAED,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,MAAM,KAAK,GAAsB,EAAE,CAAC;IAEpC,SAAS,IAAI;QACX,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,MAAM,GAAG,WAAW,EAAE,CAAC;YAC7C,MAAM,EAAE,CAAC;YACT,MAAM,GAAG,GAAG,KAAK,CAAC,KAAK,EAAG,CAAC;YAC3B,GAAG,EAAE,CAAC;QACR,CAAC;IACH,CAAC;IAED,OAAO,CAAI,EAAoB,EAAc,EAAE;QAC7C,OAAO,IAAI,OAAO,CAAI,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACxC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE;gBACd,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE;oBACtC,MAAM,EAAE,CAAC;oBACT,IAAI,EAAE,CAAC;gBACT,CAAC,CAAC,CAAC;YACL,CAAC,CAAC,CAAC;YACH,IAAI,EAAE,CAAC;QACT,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC"}
@@ -14,7 +14,9 @@ export declare class CliError extends Error {
14
14
  apiCode?: number;
15
15
  retryable: boolean;
16
16
  recovery?: string;
17
- constructor(type: ErrorType, message: string, { apiCode, retryable, recovery }?: CliErrorOptions);
17
+ /** Scope names from API permission_violations (only for SCOPE_MISSING). */
18
+ missingScopes?: string[];
19
+ constructor(type: ErrorType, message: string, { apiCode, retryable, recovery, missingScopes, }?: CliErrorOptions);
18
20
  }
19
21
  export declare function formatError(err: unknown, json?: boolean): string;
20
22
  export declare function handleError(err: unknown, json?: boolean): never;
@@ -13,6 +13,7 @@ const ERROR_MAP = {
13
13
  AUTH_REQUIRED: { exit: 2, type: "AUTH_REQUIRED" },
14
14
  TOKEN_EXPIRED: { exit: 2, type: "TOKEN_EXPIRED" },
15
15
  PERMISSION_DENIED: { exit: 2, type: "PERMISSION_DENIED" },
16
+ SCOPE_MISSING: { exit: 2, type: "SCOPE_MISSING" },
16
17
  NOT_FOUND: { exit: 3, type: "NOT_FOUND" },
17
18
  NOT_SUPPORTED: { exit: 3, type: "NOT_SUPPORTED" },
18
19
  RATE_LIMITED: { exit: 3, type: "RATE_LIMITED" },
@@ -24,7 +25,9 @@ export class CliError extends Error {
24
25
  apiCode;
25
26
  retryable;
26
27
  recovery;
27
- constructor(type, message, { apiCode, retryable = false, recovery } = {}) {
28
+ /** Scope names from API permission_violations (only for SCOPE_MISSING). */
29
+ missingScopes;
30
+ constructor(type, message, { apiCode, retryable = false, recovery, missingScopes, } = {}) {
28
31
  super(message);
29
32
  this.name = "CliError";
30
33
  const info = ERROR_MAP[type] || ERROR_MAP.API_ERROR;
@@ -33,6 +36,7 @@ export class CliError extends Error {
33
36
  this.apiCode = apiCode;
34
37
  this.retryable = retryable;
35
38
  this.recovery = recovery;
39
+ this.missingScopes = missingScopes;
36
40
  }
37
41
  }
38
42
  export function formatError(err, json = false) {
@@ -46,6 +50,10 @@ export function formatError(err, json = false) {
46
50
  api_code: err.apiCode,
47
51
  retryable: err.retryable,
48
52
  recovery: err.recovery,
53
+ ...(err.missingScopes &&
54
+ err.missingScopes.length > 0 && {
55
+ missing_scopes: err.missingScopes,
56
+ }),
49
57
  },
50
58
  });
51
59
  }
@@ -99,12 +107,8 @@ export function mapApiError(err) {
99
107
  recovery: "运行 feishu-docs login 重新认证",
100
108
  });
101
109
  }
102
- if (code === 99991672) {
103
- return new CliError("RATE_LIMITED", `API 请求频率超限,请稍后重试`, {
104
- apiCode: code,
105
- retryable: true,
106
- });
107
- }
110
+ // 99991672 / 99991679 are scope errors — handled directly in fetchWithAuth
111
+ // before mapApiError is called. If they reach here, treat as generic API error.
108
112
  return new CliError("API_ERROR", msg || "未知 API 错误", { apiCode: code });
109
113
  }
110
114
  //# sourceMappingURL=errors.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/utils/errors.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/utils/errors.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,49 @@
1
+ /** Zero-dependency retry utilities for transient error handling. */
2
+ /** Configuration options for retry behavior. */
3
+ export interface RetryOptions {
4
+ maxRetries: number;
5
+ initialDelay: number;
6
+ maxDelay: number;
7
+ }
8
+ /** Default retry configuration: 2 retries, 1s initial, 10s max. */
9
+ export declare const DEFAULT_RETRY: RetryOptions;
10
+ /**
11
+ * Calculate delay for a retry attempt using exponential backoff with jitter.
12
+ *
13
+ * Computes base = min(initialDelay * 2^attempt, maxDelay), then applies
14
+ * +/-25% random jitter. Result is clamped to >= 0.
15
+ *
16
+ * @param attempt - Zero-based retry attempt number
17
+ * @param initialDelay - Base delay in milliseconds
18
+ * @param maxDelay - Maximum delay cap in milliseconds
19
+ * @returns Delay in milliseconds with jitter applied
20
+ */
21
+ export declare function calculateDelay(attempt: number, initialDelay: number, maxDelay: number): number;
22
+ /**
23
+ * Parse the Retry-After HTTP header value (seconds format only).
24
+ *
25
+ * Returns the value in milliseconds, capped at 30 seconds.
26
+ * Returns null for null, empty, non-numeric, or non-positive values.
27
+ * Does NOT handle HTTP date format.
28
+ *
29
+ * @param headerValue - The Retry-After header value (string of seconds)
30
+ * @returns Delay in milliseconds, or null if unparseable
31
+ */
32
+ export declare function parseRetryAfter(headerValue: string | null): number | null;
33
+ /**
34
+ * Check whether a status code or error name indicates a retryable condition.
35
+ *
36
+ * Retryable statuses: 429 (rate limit), 502 (bad gateway), 503 (service unavailable).
37
+ * Retryable errors: AbortError (timeout).
38
+ *
39
+ * @param statusOrErrorName - HTTP status code or error name string
40
+ * @returns true if the condition is retryable
41
+ */
42
+ export declare function isRetryable(statusOrErrorName: number | string): boolean;
43
+ /**
44
+ * Sleep for the specified number of milliseconds.
45
+ *
46
+ * @param ms - Duration to sleep in milliseconds
47
+ * @returns Promise that resolves after the delay
48
+ */
49
+ export declare function sleep(ms: number): Promise<void>;
@@ -0,0 +1,70 @@
1
+ /** Zero-dependency retry utilities for transient error handling. */
2
+ /** Default retry configuration: 2 retries, 1s initial, 10s max. */
3
+ export const DEFAULT_RETRY = {
4
+ maxRetries: 2,
5
+ initialDelay: 1000,
6
+ maxDelay: 10_000,
7
+ };
8
+ /** Retryable HTTP status codes. */
9
+ const RETRYABLE_STATUSES = new Set([429, 502, 503]);
10
+ /** Maximum Retry-After value in milliseconds (30 seconds). */
11
+ const MAX_RETRY_AFTER_MS = 30_000;
12
+ /**
13
+ * Calculate delay for a retry attempt using exponential backoff with jitter.
14
+ *
15
+ * Computes base = min(initialDelay * 2^attempt, maxDelay), then applies
16
+ * +/-25% random jitter. Result is clamped to >= 0.
17
+ *
18
+ * @param attempt - Zero-based retry attempt number
19
+ * @param initialDelay - Base delay in milliseconds
20
+ * @param maxDelay - Maximum delay cap in milliseconds
21
+ * @returns Delay in milliseconds with jitter applied
22
+ */
23
+ export function calculateDelay(attempt, initialDelay, maxDelay) {
24
+ const base = Math.min(initialDelay * Math.pow(2, attempt), maxDelay);
25
+ const jitter = base * 0.25 * (2 * Math.random() - 1);
26
+ return Math.max(0, base + jitter);
27
+ }
28
+ /**
29
+ * Parse the Retry-After HTTP header value (seconds format only).
30
+ *
31
+ * Returns the value in milliseconds, capped at 30 seconds.
32
+ * Returns null for null, empty, non-numeric, or non-positive values.
33
+ * Does NOT handle HTTP date format.
34
+ *
35
+ * @param headerValue - The Retry-After header value (string of seconds)
36
+ * @returns Delay in milliseconds, or null if unparseable
37
+ */
38
+ export function parseRetryAfter(headerValue) {
39
+ if (headerValue === null || headerValue === "")
40
+ return null;
41
+ const seconds = Number(headerValue);
42
+ if (!Number.isFinite(seconds) || seconds <= 0)
43
+ return null;
44
+ return Math.min(seconds * 1000, MAX_RETRY_AFTER_MS);
45
+ }
46
+ /**
47
+ * Check whether a status code or error name indicates a retryable condition.
48
+ *
49
+ * Retryable statuses: 429 (rate limit), 502 (bad gateway), 503 (service unavailable).
50
+ * Retryable errors: AbortError (timeout).
51
+ *
52
+ * @param statusOrErrorName - HTTP status code or error name string
53
+ * @returns true if the condition is retryable
54
+ */
55
+ export function isRetryable(statusOrErrorName) {
56
+ if (typeof statusOrErrorName === "number") {
57
+ return RETRYABLE_STATUSES.has(statusOrErrorName);
58
+ }
59
+ return statusOrErrorName === "AbortError";
60
+ }
61
+ /**
62
+ * Sleep for the specified number of milliseconds.
63
+ *
64
+ * @param ms - Duration to sleep in milliseconds
65
+ * @returns Promise that resolves after the delay
66
+ */
67
+ export function sleep(ms) {
68
+ return new Promise((r) => setTimeout(r, ms));
69
+ }
70
+ //# sourceMappingURL=retry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retry.js","sourceRoot":"","sources":["../../src/utils/retry.ts"],"names":[],"mappings":"AAAA,oEAAoE;AASpE,mEAAmE;AACnE,MAAM,CAAC,MAAM,aAAa,GAAiB;IACzC,UAAU,EAAE,CAAC;IACb,YAAY,EAAE,IAAI;IAClB,QAAQ,EAAE,MAAM;CACjB,CAAC;AAEF,mCAAmC;AACnC,MAAM,kBAAkB,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;AAEpD,8DAA8D;AAC9D,MAAM,kBAAkB,GAAG,MAAM,CAAC;AAElC;;;;;;;;;;GAUG;AACH,MAAM,UAAU,cAAc,CAC5B,OAAe,EACf,YAAoB,EACpB,QAAgB;IAEhB,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,QAAQ,CAAC,CAAC;IACrE,MAAM,MAAM,GAAG,IAAI,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;IACrD,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC,CAAC;AACpC,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,eAAe,CAAC,WAA0B;IACxD,IAAI,WAAW,KAAK,IAAI,IAAI,WAAW,KAAK,EAAE;QAAE,OAAO,IAAI,CAAC;IAC5D,MAAM,OAAO,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC;IACpC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,OAAO,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAC3D,OAAO,IAAI,CAAC,GAAG,CAAC,OAAO,GAAG,IAAI,EAAE,kBAAkB,CAAC,CAAC;AACtD,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,WAAW,CAAC,iBAAkC;IAC5D,IAAI,OAAO,iBAAiB,KAAK,QAAQ,EAAE,CAAC;QAC1C,OAAO,kBAAkB,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;IACnD,CAAC;IACD,OAAO,iBAAiB,KAAK,YAAY,CAAC;AAC5C,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,KAAK,CAAC,EAAU;IAC9B,OAAO,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;AAC/C,CAAC"}
@@ -1,15 +1,18 @@
1
1
  /**
2
- * Interactive scope authorization prompt and recovery utilities.
2
+ * Reactive scope authorization: prompt and recovery utilities.
3
3
  *
4
- * When a command discovers missing OAuth scopes, these helpers guide
5
- * the user through authorizing them — or gracefully skipping if the
6
- * user declines (or the session is non-interactive).
7
- */
8
- import type { AuthInfo, GlobalOpts } from "../types/index.js";
9
- /**
10
- * Check whether an error is a permission / scope error.
4
+ * Instead of pre-flight scope checks, this module provides:
5
+ *
6
+ * - `promptScopeAuth()` Interactive OAuth prompt for missing scopes.
7
+ * - `withScopeRecovery()` — Wrapper that catches SCOPE_MISSING errors,
8
+ * prompts the user (if interactive), and retries the operation once.
9
+ *
10
+ * The Feishu API is the source of truth for required scopes. When an API
11
+ * call fails with 99991672 (app scope) or 99991679 (user scope), `fetchWithAuth`
12
+ * throws `CliError("SCOPE_MISSING", { missingScopes })`. This module handles
13
+ * the recovery.
11
14
  */
12
- export declare function isPermissionError(err: unknown): boolean;
15
+ import type { GlobalOpts } from "../types/index.js";
13
16
  /**
14
17
  * Prompt the user to authorize missing scopes interactively.
15
18
  *
@@ -19,16 +22,18 @@ export declare function isPermissionError(err: unknown): boolean;
19
22
  *
20
23
  * Returns `true` if authorization succeeded, `false` otherwise.
21
24
  * Always returns `false` in non-interactive contexts (JSON mode, non-TTY).
22
- *
23
- * @param storedScopeStr Pre-loaded stored scope string (avoids duplicate
24
- * loadTokens call when called from ensureScopes).
25
25
  */
26
- export declare function promptScopeAuth(missingScopes: string[], globalOpts: GlobalOpts, storedScopeStr?: string): Promise<boolean>;
26
+ export declare function promptScopeAuth(missingScopes: string[], globalOpts: GlobalOpts): Promise<boolean>;
27
27
  /**
28
- * Pre-flight scope check with interactive recovery.
28
+ * Wrap an async operation with reactive scope error recovery.
29
+ *
30
+ * When the operation throws `CliError("SCOPE_MISSING")`:
31
+ * - If interactive (TTY + non-JSON) and scopes are known: prompt → retry once.
32
+ * - Otherwise: re-throw with a clear recovery hint.
29
33
  *
30
- * If scopes are missing and the user authorizes them, returns a fresh
31
- * `AuthInfo` with the new token. If no recovery is needed, returns the
32
- * original `authInfo` unchanged. If the user declines, throws.
34
+ * @param fallbackScopes Scope names to use when the API doesn't include
35
+ * `permission_violations` (older APIs like search). When the error has
36
+ * empty `missingScopes` but `fallbackScopes` is provided, these are used
37
+ * for the authorization prompt.
33
38
  */
34
- export declare function ensureScopes(authInfo: AuthInfo, requiredScopes: readonly string[], globalOpts: GlobalOpts): Promise<AuthInfo>;
39
+ export declare function withScopeRecovery<T>(fn: () => Promise<T>, globalOpts: GlobalOpts, fallbackScopes?: string[]): Promise<T>;