feique 1.1.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 (227) hide show
  1. package/LICENSE +21 -0
  2. package/README.en.md +220 -0
  3. package/README.md +265 -0
  4. package/dist/backend/claude.d.ts +36 -0
  5. package/dist/backend/claude.js +358 -0
  6. package/dist/backend/claude.js.map +1 -0
  7. package/dist/backend/codex.d.ts +31 -0
  8. package/dist/backend/codex.js +100 -0
  9. package/dist/backend/codex.js.map +1 -0
  10. package/dist/backend/factory.d.ts +9 -0
  11. package/dist/backend/factory.js +56 -0
  12. package/dist/backend/factory.js.map +1 -0
  13. package/dist/backend/types.d.ts +54 -0
  14. package/dist/backend/types.js +2 -0
  15. package/dist/backend/types.js.map +1 -0
  16. package/dist/bridge/commands.d.ts +135 -0
  17. package/dist/bridge/commands.js +860 -0
  18. package/dist/bridge/commands.js.map +1 -0
  19. package/dist/bridge/service.d.ts +160 -0
  20. package/dist/bridge/service.js +3785 -0
  21. package/dist/bridge/service.js.map +1 -0
  22. package/dist/bridge/task-queue.d.ts +14 -0
  23. package/dist/bridge/task-queue.js +81 -0
  24. package/dist/bridge/task-queue.js.map +1 -0
  25. package/dist/bridge/types.d.ts +39 -0
  26. package/dist/bridge/types.js +2 -0
  27. package/dist/bridge/types.js.map +1 -0
  28. package/dist/cli.d.ts +2 -0
  29. package/dist/cli.js +1199 -0
  30. package/dist/cli.js.map +1 -0
  31. package/dist/codex/capabilities.d.ts +20 -0
  32. package/dist/codex/capabilities.js +41 -0
  33. package/dist/codex/capabilities.js.map +1 -0
  34. package/dist/codex/runner.d.ts +47 -0
  35. package/dist/codex/runner.js +294 -0
  36. package/dist/codex/runner.js.map +1 -0
  37. package/dist/codex/session-index.d.ts +22 -0
  38. package/dist/codex/session-index.js +205 -0
  39. package/dist/codex/session-index.js.map +1 -0
  40. package/dist/collaboration/awareness.d.ts +36 -0
  41. package/dist/collaboration/awareness.js +107 -0
  42. package/dist/collaboration/awareness.js.map +1 -0
  43. package/dist/collaboration/digest.d.ts +65 -0
  44. package/dist/collaboration/digest.js +178 -0
  45. package/dist/collaboration/digest.js.map +1 -0
  46. package/dist/collaboration/handoff.d.ts +66 -0
  47. package/dist/collaboration/handoff.js +94 -0
  48. package/dist/collaboration/handoff.js.map +1 -0
  49. package/dist/collaboration/insights.d.ts +24 -0
  50. package/dist/collaboration/insights.js +243 -0
  51. package/dist/collaboration/insights.js.map +1 -0
  52. package/dist/collaboration/knowledge.d.ts +26 -0
  53. package/dist/collaboration/knowledge.js +105 -0
  54. package/dist/collaboration/knowledge.js.map +1 -0
  55. package/dist/collaboration/timeline.d.ts +31 -0
  56. package/dist/collaboration/timeline.js +150 -0
  57. package/dist/collaboration/timeline.js.map +1 -0
  58. package/dist/collaboration/trust.d.ts +49 -0
  59. package/dist/collaboration/trust.js +176 -0
  60. package/dist/collaboration/trust.js.map +1 -0
  61. package/dist/config/codex-skill.d.ts +7 -0
  62. package/dist/config/codex-skill.js +44 -0
  63. package/dist/config/codex-skill.js.map +1 -0
  64. package/dist/config/doctor.d.ts +12 -0
  65. package/dist/config/doctor.js +314 -0
  66. package/dist/config/doctor.js.map +1 -0
  67. package/dist/config/init.d.ts +3 -0
  68. package/dist/config/init.js +123 -0
  69. package/dist/config/init.js.map +1 -0
  70. package/dist/config/load.d.ts +33 -0
  71. package/dist/config/load.js +252 -0
  72. package/dist/config/load.js.map +1 -0
  73. package/dist/config/mutate.d.ts +21 -0
  74. package/dist/config/mutate.js +86 -0
  75. package/dist/config/mutate.js.map +1 -0
  76. package/dist/config/paths.d.ts +3 -0
  77. package/dist/config/paths.js +33 -0
  78. package/dist/config/paths.js.map +1 -0
  79. package/dist/config/schema.d.ts +308 -0
  80. package/dist/config/schema.js +250 -0
  81. package/dist/config/schema.js.map +1 -0
  82. package/dist/control-plane/project-session.d.ts +67 -0
  83. package/dist/control-plane/project-session.js +234 -0
  84. package/dist/control-plane/project-session.js.map +1 -0
  85. package/dist/feishu/base.d.ts +19 -0
  86. package/dist/feishu/base.js +93 -0
  87. package/dist/feishu/base.js.map +1 -0
  88. package/dist/feishu/cards.d.ts +22 -0
  89. package/dist/feishu/cards.js +144 -0
  90. package/dist/feishu/cards.js.map +1 -0
  91. package/dist/feishu/client.d.ts +61 -0
  92. package/dist/feishu/client.js +315 -0
  93. package/dist/feishu/client.js.map +1 -0
  94. package/dist/feishu/diagnostics.d.ts +42 -0
  95. package/dist/feishu/diagnostics.js +194 -0
  96. package/dist/feishu/diagnostics.js.map +1 -0
  97. package/dist/feishu/doc.d.ts +13 -0
  98. package/dist/feishu/doc.js +59 -0
  99. package/dist/feishu/doc.js.map +1 -0
  100. package/dist/feishu/extractors.d.ts +7 -0
  101. package/dist/feishu/extractors.js +215 -0
  102. package/dist/feishu/extractors.js.map +1 -0
  103. package/dist/feishu/long-connection.d.ts +12 -0
  104. package/dist/feishu/long-connection.js +41 -0
  105. package/dist/feishu/long-connection.js.map +1 -0
  106. package/dist/feishu/message-resource.d.ts +14 -0
  107. package/dist/feishu/message-resource.js +309 -0
  108. package/dist/feishu/message-resource.js.map +1 -0
  109. package/dist/feishu/replay.d.ts +37 -0
  110. package/dist/feishu/replay.js +114 -0
  111. package/dist/feishu/replay.js.map +1 -0
  112. package/dist/feishu/task.d.ts +18 -0
  113. package/dist/feishu/task.js +86 -0
  114. package/dist/feishu/task.js.map +1 -0
  115. package/dist/feishu/text.d.ts +23 -0
  116. package/dist/feishu/text.js +155 -0
  117. package/dist/feishu/text.js.map +1 -0
  118. package/dist/feishu/webhook.d.ts +23 -0
  119. package/dist/feishu/webhook.js +130 -0
  120. package/dist/feishu/webhook.js.map +1 -0
  121. package/dist/feishu/wiki.d.ts +52 -0
  122. package/dist/feishu/wiki.js +300 -0
  123. package/dist/feishu/wiki.js.map +1 -0
  124. package/dist/index.d.ts +9 -0
  125. package/dist/index.js +9 -0
  126. package/dist/index.js.map +1 -0
  127. package/dist/knowledge/search.d.ts +11 -0
  128. package/dist/knowledge/search.js +83 -0
  129. package/dist/knowledge/search.js.map +1 -0
  130. package/dist/logging.d.ts +3 -0
  131. package/dist/logging.js +40 -0
  132. package/dist/logging.js.map +1 -0
  133. package/dist/mcp/server.d.ts +34 -0
  134. package/dist/mcp/server.js +1196 -0
  135. package/dist/mcp/server.js.map +1 -0
  136. package/dist/memory/embedding-factory.d.ts +6 -0
  137. package/dist/memory/embedding-factory.js +20 -0
  138. package/dist/memory/embedding-factory.js.map +1 -0
  139. package/dist/memory/embeddings.d.ts +40 -0
  140. package/dist/memory/embeddings.js +150 -0
  141. package/dist/memory/embeddings.js.map +1 -0
  142. package/dist/memory/ollama-embeddings.d.ts +63 -0
  143. package/dist/memory/ollama-embeddings.js +215 -0
  144. package/dist/memory/ollama-embeddings.js.map +1 -0
  145. package/dist/memory/retrieve.d.ts +17 -0
  146. package/dist/memory/retrieve.js +29 -0
  147. package/dist/memory/retrieve.js.map +1 -0
  148. package/dist/memory/summarize.d.ts +13 -0
  149. package/dist/memory/summarize.js +58 -0
  150. package/dist/memory/summarize.js.map +1 -0
  151. package/dist/observability/cost.d.ts +12 -0
  152. package/dist/observability/cost.js +22 -0
  153. package/dist/observability/cost.js.map +1 -0
  154. package/dist/observability/dashboard-html.d.ts +5 -0
  155. package/dist/observability/dashboard-html.js +304 -0
  156. package/dist/observability/dashboard-html.js.map +1 -0
  157. package/dist/observability/metrics.d.ts +36 -0
  158. package/dist/observability/metrics.js +230 -0
  159. package/dist/observability/metrics.js.map +1 -0
  160. package/dist/observability/readiness.d.ts +31 -0
  161. package/dist/observability/readiness.js +57 -0
  162. package/dist/observability/readiness.js.map +1 -0
  163. package/dist/observability/server.d.ts +84 -0
  164. package/dist/observability/server.js +181 -0
  165. package/dist/observability/server.js.map +1 -0
  166. package/dist/projects/paths.d.ts +9 -0
  167. package/dist/projects/paths.js +30 -0
  168. package/dist/projects/paths.js.map +1 -0
  169. package/dist/runtime/instance-lock.d.ts +12 -0
  170. package/dist/runtime/instance-lock.js +99 -0
  171. package/dist/runtime/instance-lock.js.map +1 -0
  172. package/dist/runtime/process.d.ts +2 -0
  173. package/dist/runtime/process.js +43 -0
  174. package/dist/runtime/process.js.map +1 -0
  175. package/dist/runtime/shutdown.d.ts +11 -0
  176. package/dist/runtime/shutdown.js +38 -0
  177. package/dist/runtime/shutdown.js.map +1 -0
  178. package/dist/security/access.d.ts +13 -0
  179. package/dist/security/access.js +160 -0
  180. package/dist/security/access.js.map +1 -0
  181. package/dist/service/install.d.ts +19 -0
  182. package/dist/service/install.js +35 -0
  183. package/dist/service/install.js.map +1 -0
  184. package/dist/service/templates.d.ts +22 -0
  185. package/dist/service/templates.js +118 -0
  186. package/dist/service/templates.js.map +1 -0
  187. package/dist/state/audit-log.d.ts +33 -0
  188. package/dist/state/audit-log.js +116 -0
  189. package/dist/state/audit-log.js.map +1 -0
  190. package/dist/state/config-history-store.d.ts +27 -0
  191. package/dist/state/config-history-store.js +65 -0
  192. package/dist/state/config-history-store.js.map +1 -0
  193. package/dist/state/handoff-store.d.ts +20 -0
  194. package/dist/state/handoff-store.js +97 -0
  195. package/dist/state/handoff-store.js.map +1 -0
  196. package/dist/state/idempotency-store.d.ts +19 -0
  197. package/dist/state/idempotency-store.js +84 -0
  198. package/dist/state/idempotency-store.js.map +1 -0
  199. package/dist/state/memory-store.d.ts +137 -0
  200. package/dist/state/memory-store.js +713 -0
  201. package/dist/state/memory-store.js.map +1 -0
  202. package/dist/state/pending-command-store.d.ts +30 -0
  203. package/dist/state/pending-command-store.js +108 -0
  204. package/dist/state/pending-command-store.js.map +1 -0
  205. package/dist/state/run-state-store.d.ts +58 -0
  206. package/dist/state/run-state-store.js +269 -0
  207. package/dist/state/run-state-store.js.map +1 -0
  208. package/dist/state/session-store.d.ts +56 -0
  209. package/dist/state/session-store.js +275 -0
  210. package/dist/state/session-store.js.map +1 -0
  211. package/dist/state/trust-store.d.ts +15 -0
  212. package/dist/state/trust-store.js +53 -0
  213. package/dist/state/trust-store.js.map +1 -0
  214. package/dist/utils/fs.d.ts +4 -0
  215. package/dist/utils/fs.js +26 -0
  216. package/dist/utils/fs.js.map +1 -0
  217. package/dist/utils/json.d.ts +1 -0
  218. package/dist/utils/json.js +9 -0
  219. package/dist/utils/json.js.map +1 -0
  220. package/dist/utils/path.d.ts +3 -0
  221. package/dist/utils/path.js +22 -0
  222. package/dist/utils/path.js.map +1 -0
  223. package/dist/utils/serial-executor.d.ts +5 -0
  224. package/dist/utils/serial-executor.js +12 -0
  225. package/dist/utils/serial-executor.js.map +1 -0
  226. package/package.json +71 -0
  227. package/skills/feique-session/SKILL.md +27 -0
@@ -0,0 +1,37 @@
1
+ export declare function buildReplayMessageEvent(input: {
2
+ appId?: string;
3
+ tenantKey?: string;
4
+ chatId: string;
5
+ chatType: 'p2p' | 'group';
6
+ actorId: string;
7
+ senderType?: string;
8
+ text: string;
9
+ messageId?: string;
10
+ }): Record<string, unknown>;
11
+ export declare function buildReplayCardAction(input: {
12
+ appId?: string;
13
+ tenantKey?: string;
14
+ chatId: string;
15
+ actorId: string;
16
+ openMessageId: string;
17
+ action: string;
18
+ projectAlias?: string;
19
+ conversationKey?: string;
20
+ }): Record<string, unknown>;
21
+ export declare function postWebhookPayload(input: {
22
+ url: string;
23
+ payload: Record<string, unknown>;
24
+ timeoutMs?: number;
25
+ }): Promise<{
26
+ statusCode: number;
27
+ body: string;
28
+ }>;
29
+ export declare function requestWebhookEndpoint(input: {
30
+ url: string;
31
+ method?: 'GET' | 'POST';
32
+ payload?: Record<string, unknown>;
33
+ timeoutMs?: number;
34
+ }): Promise<{
35
+ statusCode: number;
36
+ body: string;
37
+ }>;
@@ -0,0 +1,114 @@
1
+ import http from 'node:http';
2
+ import https from 'node:https';
3
+ import { URL } from 'node:url';
4
+ export function buildReplayMessageEvent(input) {
5
+ const now = Date.now();
6
+ return {
7
+ schema: '2.0',
8
+ header: {
9
+ event_id: `evt_${now}`,
10
+ event_type: 'im.message.receive_v1',
11
+ create_time: String(now),
12
+ token: 'local-replay',
13
+ app_id: input.appId ?? 'local-app',
14
+ tenant_key: input.tenantKey ?? 'tenant-local',
15
+ },
16
+ event: {
17
+ sender: {
18
+ sender_id: {
19
+ open_id: input.actorId,
20
+ },
21
+ sender_type: input.senderType ?? 'user',
22
+ },
23
+ message: {
24
+ message_id: input.messageId ?? `om_${now}`,
25
+ create_time: String(now),
26
+ chat_id: input.chatId,
27
+ chat_type: input.chatType,
28
+ message_type: 'text',
29
+ content: JSON.stringify({ text: input.text }),
30
+ mentions: [],
31
+ },
32
+ },
33
+ };
34
+ }
35
+ export function buildReplayCardAction(input) {
36
+ const now = Date.now();
37
+ return {
38
+ schema: '2.0',
39
+ header: {
40
+ event_id: `evt_${now}`,
41
+ event_type: 'card.action.trigger',
42
+ create_time: String(now),
43
+ token: 'local-replay',
44
+ app_id: input.appId ?? 'local-app',
45
+ tenant_key: input.tenantKey ?? 'tenant-local',
46
+ },
47
+ event: {
48
+ open_message_id: input.openMessageId,
49
+ open_chat_id: input.chatId,
50
+ tenant_key: input.tenantKey ?? 'tenant-local',
51
+ operator: {
52
+ open_id: input.actorId,
53
+ },
54
+ action: {
55
+ value: {
56
+ action: input.action,
57
+ ...(input.projectAlias ? { project_alias: input.projectAlias } : {}),
58
+ ...(input.conversationKey ? { conversation_key: input.conversationKey } : {}),
59
+ chat_id: input.chatId,
60
+ },
61
+ },
62
+ },
63
+ };
64
+ }
65
+ export async function postWebhookPayload(input) {
66
+ return requestWebhookEndpoint({
67
+ url: input.url,
68
+ payload: input.payload,
69
+ timeoutMs: input.timeoutMs,
70
+ });
71
+ }
72
+ export async function requestWebhookEndpoint(input) {
73
+ const target = new URL(input.url);
74
+ const method = input.method ?? (input.payload ? 'POST' : 'GET');
75
+ const body = input.payload ? JSON.stringify(input.payload) : undefined;
76
+ return new Promise((resolve, reject) => {
77
+ const transport = target.protocol === 'https:' ? https : http;
78
+ const request = transport.request({
79
+ protocol: target.protocol,
80
+ hostname: target.hostname,
81
+ port: target.port ? Number(target.port) : target.protocol === 'https:' ? 443 : 80,
82
+ method,
83
+ path: `${target.pathname}${target.search}`,
84
+ ...(body
85
+ ? {
86
+ headers: {
87
+ 'content-type': 'application/json; charset=utf-8',
88
+ 'content-length': Buffer.byteLength(body),
89
+ },
90
+ }
91
+ : {}),
92
+ }, (response) => {
93
+ const chunks = [];
94
+ response.on('data', (chunk) => {
95
+ chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
96
+ });
97
+ response.on('end', () => {
98
+ resolve({
99
+ statusCode: response.statusCode ?? 0,
100
+ body: Buffer.concat(chunks).toString('utf8'),
101
+ });
102
+ });
103
+ });
104
+ request.setTimeout(input.timeoutMs ?? 5000, () => {
105
+ request.destroy(new Error(`Webhook replay timed out after ${input.timeoutMs ?? 5000}ms`));
106
+ });
107
+ request.on('error', reject);
108
+ if (body) {
109
+ request.write(body);
110
+ }
111
+ request.end();
112
+ });
113
+ }
114
+ //# sourceMappingURL=replay.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"replay.js","sourceRoot":"","sources":["../../src/feishu/replay.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import * as lark from '@larksuiteoapi/node-sdk';
2
+ export interface FeishuTaskRecord {
3
+ guid: string;
4
+ taskId?: string;
5
+ summary?: string;
6
+ description?: string;
7
+ status?: string;
8
+ completedAt?: string;
9
+ url?: string;
10
+ }
11
+ export declare class FeishuTaskClient {
12
+ private readonly client;
13
+ constructor(client: lark.Client);
14
+ list(limit?: number): Promise<FeishuTaskRecord[]>;
15
+ get(taskGuid: string): Promise<FeishuTaskRecord>;
16
+ create(summary: string, description?: string): Promise<FeishuTaskRecord>;
17
+ complete(taskGuid: string): Promise<FeishuTaskRecord>;
18
+ }
@@ -0,0 +1,86 @@
1
+ export class FeishuTaskClient {
2
+ client;
3
+ constructor(client) {
4
+ this.client = client;
5
+ }
6
+ async list(limit = 10) {
7
+ const response = await this.client.task.v2.task.list({
8
+ params: {
9
+ page_size: Math.min(limit, 50),
10
+ },
11
+ });
12
+ ensureSuccess(response);
13
+ return (response.data?.items ?? [])
14
+ .filter((item) => item.guid)
15
+ .map((item) => ({
16
+ guid: item.guid,
17
+ taskId: item.task_id,
18
+ summary: item.summary,
19
+ description: item.description,
20
+ status: item.status,
21
+ completedAt: item.completed_at,
22
+ url: item.url,
23
+ }));
24
+ }
25
+ async get(taskGuid) {
26
+ const response = await this.client.task.v2.task.get({
27
+ path: {
28
+ task_guid: taskGuid,
29
+ },
30
+ });
31
+ ensureSuccess(response);
32
+ const task = response.data?.task;
33
+ if (!task?.guid) {
34
+ throw new Error('Feishu Task get returned no task.');
35
+ }
36
+ return {
37
+ guid: task.guid,
38
+ taskId: task.task_id,
39
+ summary: task.summary,
40
+ description: task.description,
41
+ status: task.status,
42
+ completedAt: task.completed_at,
43
+ url: task.url,
44
+ };
45
+ }
46
+ async create(summary, description) {
47
+ const response = await this.client.task.v2.task.create({
48
+ data: {
49
+ summary,
50
+ ...(description ? { description } : {}),
51
+ },
52
+ });
53
+ ensureSuccess(response);
54
+ const task = response.data?.task;
55
+ if (!task?.guid) {
56
+ throw new Error('Feishu Task create returned no task guid.');
57
+ }
58
+ return {
59
+ guid: task.guid,
60
+ taskId: task.task_id,
61
+ summary: task.summary ?? summary,
62
+ description: task.description ?? description,
63
+ status: task.status,
64
+ completedAt: task.completed_at,
65
+ url: task.url,
66
+ };
67
+ }
68
+ async complete(taskGuid) {
69
+ const task = await this.get(taskGuid);
70
+ const taskId = task.taskId ?? taskGuid;
71
+ const response = await this.client.task.v1.task.complete({
72
+ path: {
73
+ task_id: taskId,
74
+ },
75
+ });
76
+ ensureSuccess(response);
77
+ return this.get(taskGuid);
78
+ }
79
+ }
80
+ function ensureSuccess(response) {
81
+ if (response.code === undefined || response.code === 0) {
82
+ return;
83
+ }
84
+ throw new Error(`Feishu API error ${response.code}: ${response.msg ?? 'unknown error'}`);
85
+ }
86
+ //# sourceMappingURL=task.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task.js","sourceRoot":"","sources":["../../src/feishu/task.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ export declare const DEFAULT_FEISHU_TEXT_LIMIT = 1800;
2
+ export declare const DEFAULT_FEISHU_CARD_SUMMARY_LIMIT = 1200;
3
+ export declare const DEFAULT_FEISHU_CARD_MARKDOWN_LIMIT = 2000;
4
+ interface FeishuPostTextSegment {
5
+ tag: 'text';
6
+ text: string;
7
+ }
8
+ interface FeishuPostLinkSegment {
9
+ tag: 'a';
10
+ text: string;
11
+ href: string;
12
+ }
13
+ type FeishuPostSegment = FeishuPostTextSegment | FeishuPostLinkSegment;
14
+ export declare function splitTextForFeishu(input: string, maxChars?: number): string[];
15
+ export declare function truncateForFeishuCard(input: string, maxChars?: number): string;
16
+ export declare function buildFeishuPost(title: string, body: string): {
17
+ zh_cn: {
18
+ title: string;
19
+ content: Array<Array<FeishuPostSegment>>;
20
+ };
21
+ };
22
+ export declare function splitMarkdownForFeishuCard(input: string, maxChars?: number): string[];
23
+ export {};
@@ -0,0 +1,155 @@
1
+ export const DEFAULT_FEISHU_TEXT_LIMIT = 1800;
2
+ export const DEFAULT_FEISHU_CARD_SUMMARY_LIMIT = 1200;
3
+ export const DEFAULT_FEISHU_CARD_MARKDOWN_LIMIT = 2000;
4
+ export function splitTextForFeishu(input, maxChars = DEFAULT_FEISHU_TEXT_LIMIT) {
5
+ const text = input.trim();
6
+ if (!text) {
7
+ return [''];
8
+ }
9
+ if (text.length <= maxChars) {
10
+ return [text];
11
+ }
12
+ const chunks = [];
13
+ let buffer = '';
14
+ const paragraphs = text.split(/\n{2,}/);
15
+ for (const paragraph of paragraphs) {
16
+ const candidate = buffer ? `${buffer}\n\n${paragraph}` : paragraph;
17
+ if (candidate.length <= maxChars) {
18
+ buffer = candidate;
19
+ continue;
20
+ }
21
+ if (buffer) {
22
+ chunks.push(buffer);
23
+ buffer = '';
24
+ }
25
+ if (paragraph.length <= maxChars) {
26
+ buffer = paragraph;
27
+ continue;
28
+ }
29
+ chunks.push(...splitHard(paragraph, maxChars));
30
+ }
31
+ if (buffer) {
32
+ chunks.push(buffer);
33
+ }
34
+ return chunks;
35
+ }
36
+ export function truncateForFeishuCard(input, maxChars = DEFAULT_FEISHU_CARD_SUMMARY_LIMIT) {
37
+ const text = input.trim();
38
+ if (text.length <= maxChars) {
39
+ return text;
40
+ }
41
+ return `${text.slice(0, Math.max(0, maxChars - 1)).trimEnd()}…`;
42
+ }
43
+ export function buildFeishuPost(title, body) {
44
+ const rawLines = body.split(/\r?\n/).map((line) => line.trimEnd());
45
+ const lines = [];
46
+ for (const line of rawLines) {
47
+ if (line.length > 0 || (lines.length > 0 && lines[lines.length - 1] !== '')) {
48
+ lines.push(line);
49
+ }
50
+ }
51
+ const content = lines.length > 0
52
+ ? lines.map((line) => tokenizePostLine(formatPostLine(line)))
53
+ : [[{ tag: 'text', text: body.trim() || ' ' }]];
54
+ return {
55
+ zh_cn: {
56
+ title,
57
+ content,
58
+ },
59
+ };
60
+ }
61
+ export function splitMarkdownForFeishuCard(input, maxChars = DEFAULT_FEISHU_CARD_MARKDOWN_LIMIT) {
62
+ return splitTextForFeishu(input, maxChars);
63
+ }
64
+ function splitHard(input, maxChars) {
65
+ const chunks = [];
66
+ let remaining = input.trim();
67
+ while (remaining.length > maxChars) {
68
+ let cut = remaining.lastIndexOf('\n', maxChars);
69
+ if (cut <= 0) {
70
+ cut = remaining.lastIndexOf(' ', maxChars);
71
+ }
72
+ if (cut <= 0) {
73
+ cut = maxChars;
74
+ }
75
+ chunks.push(remaining.slice(0, cut).trim());
76
+ remaining = remaining.slice(cut).trim();
77
+ }
78
+ if (remaining) {
79
+ chunks.push(remaining);
80
+ }
81
+ return chunks;
82
+ }
83
+ function formatPostLine(line) {
84
+ const trimmed = line.trim();
85
+ if (!trimmed) {
86
+ return ' ';
87
+ }
88
+ if (/^#{1,6}\s+/.test(trimmed)) {
89
+ return `【${trimmed.replace(/^#{1,6}\s+/, '').trim()}】`;
90
+ }
91
+ if (/^>\s+/.test(trimmed)) {
92
+ return `引用|${trimmed.replace(/^>\s+/, '').trim()}`;
93
+ }
94
+ if (/^[-*]\s+/.test(trimmed)) {
95
+ return `• ${trimmed.replace(/^[-*]\s+/, '').trim()}`;
96
+ }
97
+ return trimmed;
98
+ }
99
+ function tokenizePostLine(line) {
100
+ const segments = [];
101
+ const markdownLinkRegex = /\[([^\]]+)\]\((https?:\/\/[^\s)]+)\)/g;
102
+ let cursor = 0;
103
+ let match;
104
+ while ((match = markdownLinkRegex.exec(line)) !== null) {
105
+ const fullMatch = match[0];
106
+ const label = match[1];
107
+ const href = match[2];
108
+ if (!label || !href) {
109
+ continue;
110
+ }
111
+ if (match.index > cursor) {
112
+ segments.push(...tokenizeBareUrls(line.slice(cursor, match.index)));
113
+ }
114
+ segments.push({ tag: 'a', text: label, href });
115
+ cursor = match.index + fullMatch.length;
116
+ }
117
+ if (cursor < line.length) {
118
+ segments.push(...tokenizeBareUrls(line.slice(cursor)));
119
+ }
120
+ return segments.length > 0 ? mergeAdjacentTextSegments(segments) : [{ tag: 'text', text: line || ' ' }];
121
+ }
122
+ function tokenizeBareUrls(input) {
123
+ const segments = [];
124
+ const urlRegex = /https?:\/\/[^\s]+/g;
125
+ let cursor = 0;
126
+ let match;
127
+ while ((match = urlRegex.exec(input)) !== null) {
128
+ const [href] = match;
129
+ if (match.index > cursor) {
130
+ segments.push({ tag: 'text', text: input.slice(cursor, match.index) });
131
+ }
132
+ segments.push({ tag: 'a', text: href, href });
133
+ cursor = match.index + href.length;
134
+ }
135
+ if (cursor < input.length) {
136
+ segments.push({ tag: 'text', text: input.slice(cursor) });
137
+ }
138
+ return segments;
139
+ }
140
+ function mergeAdjacentTextSegments(input) {
141
+ const merged = [];
142
+ for (const segment of input) {
143
+ if (segment.tag === 'text' && segment.text.length === 0) {
144
+ continue;
145
+ }
146
+ const last = merged.at(-1);
147
+ if (last?.tag === 'text' && segment.tag === 'text') {
148
+ last.text += segment.text;
149
+ continue;
150
+ }
151
+ merged.push(segment);
152
+ }
153
+ return merged.length > 0 ? merged : [{ tag: 'text', text: ' ' }];
154
+ }
155
+ //# sourceMappingURL=text.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text.js","sourceRoot":"","sources":["../../src/feishu/text.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import type { Logger } from '../logging.js';
2
+ import type { BridgeConfig } from '../config/schema.js';
3
+ import { FeiqueService } from '../bridge/service.js';
4
+ import type { ServiceReadinessProbe } from '../observability/readiness.js';
5
+ export interface WebhookBridgeHandle {
6
+ address: {
7
+ host: string;
8
+ port: number;
9
+ };
10
+ close(): Promise<void>;
11
+ }
12
+ export declare function createWebhookBridgeServer(input: {
13
+ config: BridgeConfig;
14
+ service: FeiqueService;
15
+ logger: Logger;
16
+ readiness?: ServiceReadinessProbe;
17
+ }): Promise<WebhookBridgeHandle>;
18
+ export declare function startWebhookBridge(input: {
19
+ config: BridgeConfig;
20
+ service: FeiqueService;
21
+ logger: Logger;
22
+ readiness?: ServiceReadinessProbe;
23
+ }): Promise<NodeJS.Signals>;
@@ -0,0 +1,130 @@
1
+ import http from 'node:http';
2
+ import * as lark from '@larksuiteoapi/node-sdk';
3
+ import { extractCardAction, extractIncomingMessage, shouldAllowChat } from './extractors.js';
4
+ import { waitForShutdownSignal } from '../runtime/shutdown.js';
5
+ export async function createWebhookBridgeServer(input) {
6
+ const eventDispatcher = new lark.EventDispatcher({
7
+ encryptKey: input.config.feishu.encrypt_key,
8
+ verificationToken: input.config.feishu.verification_token,
9
+ }).register({
10
+ 'im.message.receive_v1': async (payload) => {
11
+ const message = extractIncomingMessage(payload);
12
+ if (!message) {
13
+ return;
14
+ }
15
+ if (message.sender_type && message.sender_type !== 'user') {
16
+ input.logger.info({ chatId: message.chat_id, senderType: message.sender_type, messageId: message.message_id }, 'Ignoring non-user message');
17
+ return;
18
+ }
19
+ if (!shouldAllowChat(input.config.feishu, message.chat_id, message.chat_type)) {
20
+ input.logger.info({ chatId: message.chat_id }, 'Ignoring message from disallowed chat');
21
+ return;
22
+ }
23
+ await input.service.handleIncomingMessage(message);
24
+ },
25
+ });
26
+ const cardDispatcher = new lark.CardActionHandler({
27
+ encryptKey: input.config.feishu.encrypt_key,
28
+ verificationToken: input.config.feishu.verification_token,
29
+ }, async (payload) => {
30
+ const action = extractCardAction(payload);
31
+ if (!action) {
32
+ return {
33
+ header: {
34
+ title: { tag: 'plain_text', content: '无法处理卡片事件' },
35
+ },
36
+ elements: [],
37
+ };
38
+ }
39
+ return input.service.handleCardAction(action);
40
+ });
41
+ const eventHandler = lark.adaptDefault(input.config.feishu.event_path, eventDispatcher, { autoChallenge: true });
42
+ const cardHandler = lark.adaptDefault(input.config.feishu.card_path, cardDispatcher);
43
+ const server = http.createServer((request, response) => {
44
+ if (!request.url) {
45
+ response.statusCode = 404;
46
+ response.end('Not found');
47
+ return;
48
+ }
49
+ if (request.url === '/healthz' || request.url === '/readyz') {
50
+ const readiness = input.readiness?.snapshot() ?? {
51
+ ok: true,
52
+ ready: true,
53
+ service: input.config.service.name,
54
+ transport: 'webhook',
55
+ stage: 'ready',
56
+ startupWarnings: 0,
57
+ startupErrors: 0,
58
+ timestamp: new Date().toISOString(),
59
+ };
60
+ response.statusCode = request.url === '/readyz' ? (readiness.ready ? 200 : 503) : (readiness.ok ? 200 : 503);
61
+ response.setHeader('content-type', 'application/json; charset=utf-8');
62
+ response.end(JSON.stringify({
63
+ ...readiness,
64
+ event_path: input.config.feishu.event_path,
65
+ card_path: input.config.feishu.card_path,
66
+ }));
67
+ return;
68
+ }
69
+ if (request.url.startsWith(input.config.feishu.event_path)) {
70
+ eventHandler(request, response);
71
+ return;
72
+ }
73
+ if (request.url.startsWith(input.config.feishu.card_path)) {
74
+ cardHandler(request, response);
75
+ return;
76
+ }
77
+ response.statusCode = 404;
78
+ response.end('Not found');
79
+ });
80
+ await new Promise((resolve, reject) => {
81
+ server.once('error', reject);
82
+ server.listen(input.config.feishu.port, input.config.feishu.host, () => {
83
+ resolve();
84
+ });
85
+ });
86
+ const address = server.address();
87
+ const port = typeof address === 'object' && address ? address.port : input.config.feishu.port;
88
+ input.logger.info({
89
+ host: input.config.feishu.host,
90
+ port,
91
+ eventPath: input.config.feishu.event_path,
92
+ cardPath: input.config.feishu.card_path,
93
+ }, 'Feishu webhook bridge started');
94
+ input.readiness?.markReady({
95
+ host: input.config.feishu.host,
96
+ port,
97
+ eventPath: input.config.feishu.event_path,
98
+ cardPath: input.config.feishu.card_path,
99
+ });
100
+ return {
101
+ address: {
102
+ host: input.config.feishu.host,
103
+ port,
104
+ },
105
+ close: async () => {
106
+ await new Promise((resolve, reject) => {
107
+ server.close((error) => {
108
+ if (error) {
109
+ reject(error);
110
+ return;
111
+ }
112
+ resolve();
113
+ });
114
+ });
115
+ },
116
+ };
117
+ }
118
+ export async function startWebhookBridge(input) {
119
+ const server = await createWebhookBridgeServer(input);
120
+ return waitForShutdownSignal({
121
+ logger: input.logger,
122
+ onShutdown: async (signal) => {
123
+ input.readiness?.markStopping({ signal, port: server.address.port });
124
+ await server.close();
125
+ input.readiness?.markStopped({ signal, port: server.address.port });
126
+ input.logger.info({ signal, port: server.address.port }, 'Feishu webhook bridge stopped');
127
+ },
128
+ });
129
+ }
130
+ //# sourceMappingURL=webhook.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webhook.js","sourceRoot":"","sources":["../../src/feishu/webhook.ts"],"names":[],"mappings":"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"}