opencode-lark 0.1.1

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 (138) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/LICENSE +21 -0
  3. package/README.md +322 -0
  4. package/README.zh-CN.md +324 -0
  5. package/bin/opencode-lark.js +2 -0
  6. package/dist/channel/base-plugin.d.ts +31 -0
  7. package/dist/channel/base-plugin.d.ts.map +1 -0
  8. package/dist/channel/base-plugin.js +42 -0
  9. package/dist/channel/base-plugin.js.map +1 -0
  10. package/dist/channel/feishu/feishu-plugin.d.ts +36 -0
  11. package/dist/channel/feishu/feishu-plugin.d.ts.map +1 -0
  12. package/dist/channel/feishu/feishu-plugin.js +149 -0
  13. package/dist/channel/feishu/feishu-plugin.js.map +1 -0
  14. package/dist/channel/feishu/index.d.ts +2 -0
  15. package/dist/channel/feishu/index.d.ts.map +1 -0
  16. package/dist/channel/feishu/index.js +2 -0
  17. package/dist/channel/feishu/index.js.map +1 -0
  18. package/dist/channel/index.d.ts +4 -0
  19. package/dist/channel/index.d.ts.map +1 -0
  20. package/dist/channel/index.js +4 -0
  21. package/dist/channel/index.js.map +1 -0
  22. package/dist/channel/manager.d.ts +37 -0
  23. package/dist/channel/manager.d.ts.map +1 -0
  24. package/dist/channel/manager.js +68 -0
  25. package/dist/channel/manager.js.map +1 -0
  26. package/dist/channel/mock/mock-plugin.d.ts +24 -0
  27. package/dist/channel/mock/mock-plugin.d.ts.map +1 -0
  28. package/dist/channel/mock/mock-plugin.js +42 -0
  29. package/dist/channel/mock/mock-plugin.js.map +1 -0
  30. package/dist/channel/types.d.ts +226 -0
  31. package/dist/channel/types.d.ts.map +1 -0
  32. package/dist/channel/types.js +7 -0
  33. package/dist/channel/types.js.map +1 -0
  34. package/dist/cron/cron-service.d.ts +40 -0
  35. package/dist/cron/cron-service.d.ts.map +1 -0
  36. package/dist/cron/cron-service.js +140 -0
  37. package/dist/cron/cron-service.js.map +1 -0
  38. package/dist/cron/heartbeat.d.ts +30 -0
  39. package/dist/cron/heartbeat.d.ts.map +1 -0
  40. package/dist/cron/heartbeat.js +76 -0
  41. package/dist/cron/heartbeat.js.map +1 -0
  42. package/dist/feishu/api-client.d.ts +19 -0
  43. package/dist/feishu/api-client.d.ts.map +1 -0
  44. package/dist/feishu/api-client.js +98 -0
  45. package/dist/feishu/api-client.js.map +1 -0
  46. package/dist/feishu/card-builder.d.ts +10 -0
  47. package/dist/feishu/card-builder.d.ts.map +1 -0
  48. package/dist/feishu/card-builder.js +74 -0
  49. package/dist/feishu/card-builder.js.map +1 -0
  50. package/dist/feishu/cardkit-client.d.ts +48 -0
  51. package/dist/feishu/cardkit-client.d.ts.map +1 -0
  52. package/dist/feishu/cardkit-client.js +97 -0
  53. package/dist/feishu/cardkit-client.js.map +1 -0
  54. package/dist/feishu/message-dedup.d.ts +28 -0
  55. package/dist/feishu/message-dedup.d.ts.map +1 -0
  56. package/dist/feishu/message-dedup.js +58 -0
  57. package/dist/feishu/message-dedup.js.map +1 -0
  58. package/dist/feishu/webhook-server.d.ts +20 -0
  59. package/dist/feishu/webhook-server.d.ts.map +1 -0
  60. package/dist/feishu/webhook-server.js +111 -0
  61. package/dist/feishu/webhook-server.js.map +1 -0
  62. package/dist/feishu/ws-client.d.ts +17 -0
  63. package/dist/feishu/ws-client.d.ts.map +1 -0
  64. package/dist/feishu/ws-client.js +158 -0
  65. package/dist/feishu/ws-client.js.map +1 -0
  66. package/dist/handler/interactive-handler.d.ts +16 -0
  67. package/dist/handler/interactive-handler.d.ts.map +1 -0
  68. package/dist/handler/interactive-handler.js +86 -0
  69. package/dist/handler/interactive-handler.js.map +1 -0
  70. package/dist/handler/interactive-poller.d.ts +16 -0
  71. package/dist/handler/interactive-poller.d.ts.map +1 -0
  72. package/dist/handler/interactive-poller.js +147 -0
  73. package/dist/handler/interactive-poller.js.map +1 -0
  74. package/dist/handler/message-handler.d.ts +34 -0
  75. package/dist/handler/message-handler.d.ts.map +1 -0
  76. package/dist/handler/message-handler.js +305 -0
  77. package/dist/handler/message-handler.js.map +1 -0
  78. package/dist/handler/streaming-integration.d.ts +21 -0
  79. package/dist/handler/streaming-integration.d.ts.map +1 -0
  80. package/dist/handler/streaming-integration.js +325 -0
  81. package/dist/handler/streaming-integration.js.map +1 -0
  82. package/dist/index.d.ts +16 -0
  83. package/dist/index.d.ts.map +1 -0
  84. package/dist/index.js +281 -0
  85. package/dist/index.js.map +1 -0
  86. package/dist/memory/memory-manager.d.ts +16 -0
  87. package/dist/memory/memory-manager.d.ts.map +1 -0
  88. package/dist/memory/memory-manager.js +58 -0
  89. package/dist/memory/memory-manager.js.map +1 -0
  90. package/dist/session/progress-tracker.d.ts +12 -0
  91. package/dist/session/progress-tracker.d.ts.map +1 -0
  92. package/dist/session/progress-tracker.js +46 -0
  93. package/dist/session/progress-tracker.js.map +1 -0
  94. package/dist/session/session-manager.d.ts +15 -0
  95. package/dist/session/session-manager.d.ts.map +1 -0
  96. package/dist/session/session-manager.js +91 -0
  97. package/dist/session/session-manager.js.map +1 -0
  98. package/dist/streaming/event-processor.d.ts +74 -0
  99. package/dist/streaming/event-processor.d.ts.map +1 -0
  100. package/dist/streaming/event-processor.js +240 -0
  101. package/dist/streaming/event-processor.js.map +1 -0
  102. package/dist/streaming/session-observer.d.ts +19 -0
  103. package/dist/streaming/session-observer.d.ts.map +1 -0
  104. package/dist/streaming/session-observer.js +140 -0
  105. package/dist/streaming/session-observer.js.map +1 -0
  106. package/dist/streaming/streaming-card.d.ts +37 -0
  107. package/dist/streaming/streaming-card.d.ts.map +1 -0
  108. package/dist/streaming/streaming-card.js +139 -0
  109. package/dist/streaming/streaming-card.js.map +1 -0
  110. package/dist/streaming/subagent-card.d.ts +32 -0
  111. package/dist/streaming/subagent-card.d.ts.map +1 -0
  112. package/dist/streaming/subagent-card.js +103 -0
  113. package/dist/streaming/subagent-card.js.map +1 -0
  114. package/dist/streaming/subagent-tracker.d.ts +45 -0
  115. package/dist/streaming/subagent-tracker.d.ts.map +1 -0
  116. package/dist/streaming/subagent-tracker.js +118 -0
  117. package/dist/streaming/subagent-tracker.js.map +1 -0
  118. package/dist/types.d.ts +55 -0
  119. package/dist/types.d.ts.map +1 -0
  120. package/dist/types.js +5 -0
  121. package/dist/types.js.map +1 -0
  122. package/dist/utils/config.d.ts +197 -0
  123. package/dist/utils/config.d.ts.map +1 -0
  124. package/dist/utils/config.js +87 -0
  125. package/dist/utils/config.js.map +1 -0
  126. package/dist/utils/db.d.ts +12 -0
  127. package/dist/utils/db.d.ts.map +1 -0
  128. package/dist/utils/db.js +35 -0
  129. package/dist/utils/db.js.map +1 -0
  130. package/dist/utils/event-listeners.d.ts +12 -0
  131. package/dist/utils/event-listeners.d.ts.map +1 -0
  132. package/dist/utils/event-listeners.js +21 -0
  133. package/dist/utils/event-listeners.js.map +1 -0
  134. package/dist/utils/logger.d.ts +11 -0
  135. package/dist/utils/logger.d.ts.map +1 -0
  136. package/dist/utils/logger.js +38 -0
  137. package/dist/utils/logger.js.map +1 -0
  138. package/package.json +41 -0
@@ -0,0 +1,16 @@
1
+ import type { Database } from "bun:sqlite";
2
+ interface MemoryManagerOptions {
3
+ db: Database;
4
+ }
5
+ export interface MemorySearchResult {
6
+ session_id: string;
7
+ snippet: string;
8
+ rank: number;
9
+ }
10
+ export interface MemoryManager {
11
+ saveMemory(sessionId: string, content: string): void;
12
+ searchMemory(query: string, limit?: number): MemorySearchResult[];
13
+ }
14
+ export declare function createMemoryManager(options: MemoryManagerOptions): MemoryManager;
15
+ export {};
16
+ //# sourceMappingURL=memory-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory-manager.d.ts","sourceRoot":"","sources":["../../src/memory/memory-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAK1C,UAAU,oBAAoB;IAC5B,EAAE,EAAE,QAAQ,CAAA;CACb;AAED,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;CACb;AAED,MAAM,WAAW,aAAa;IAC5B,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACpD,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,kBAAkB,EAAE,CAAA;CAClE;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,oBAAoB,GAAG,aAAa,CAgEhF"}
@@ -0,0 +1,58 @@
1
+ import { createLogger } from "../utils/logger.js";
2
+ const logger = createLogger("memory-manager");
3
+ export function createMemoryManager(options) {
4
+ const { db } = options;
5
+ db.exec(`
6
+ CREATE VIRTUAL TABLE IF NOT EXISTS memory_fts USING fts5(
7
+ session_id,
8
+ content,
9
+ tokenize='unicode61'
10
+ )
11
+ `);
12
+ db.exec(`
13
+ CREATE TABLE IF NOT EXISTS memory_entries (
14
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
15
+ session_id TEXT NOT NULL,
16
+ content TEXT NOT NULL,
17
+ created_at INTEGER NOT NULL
18
+ )
19
+ `);
20
+ const insertEntryStmt = db.prepare("INSERT INTO memory_entries (session_id, content, created_at) VALUES (?, ?, ?)");
21
+ const insertFtsStmt = db.prepare("INSERT INTO memory_fts (session_id, content) VALUES (?, ?)");
22
+ const searchStmt = db.prepare(`
23
+ SELECT session_id, snippet(memory_fts, 1, '<b>', '</b>', '...', 64) as snippet, rank
24
+ FROM memory_fts
25
+ WHERE memory_fts MATCH ?
26
+ ORDER BY rank
27
+ LIMIT ?
28
+ `);
29
+ return {
30
+ saveMemory(sessionId, content) {
31
+ try {
32
+ insertEntryStmt.run(sessionId, content, Date.now());
33
+ insertFtsStmt.run(sessionId, content);
34
+ logger.debug(`Saved memory for session ${sessionId} (${content.length} chars)`);
35
+ }
36
+ catch (error) {
37
+ logger.error(`Failed to save memory: ${error}`);
38
+ }
39
+ },
40
+ searchMemory(query, limit = 5) {
41
+ try {
42
+ const ftsQuery = query
43
+ .replace(/[^\w\u4e00-\u9fff\s]/g, "")
44
+ .split(/\s+/)
45
+ .filter(Boolean)
46
+ .join(" OR ");
47
+ if (!ftsQuery)
48
+ return [];
49
+ return searchStmt.all(ftsQuery, limit);
50
+ }
51
+ catch (error) {
52
+ logger.error(`Memory search failed: ${error}`);
53
+ return [];
54
+ }
55
+ },
56
+ };
57
+ }
58
+ //# sourceMappingURL=memory-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory-manager.js","sourceRoot":"","sources":["../../src/memory/memory-manager.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAEjD,MAAM,MAAM,GAAG,YAAY,CAAC,gBAAgB,CAAC,CAAA;AAiB7C,MAAM,UAAU,mBAAmB,CAAC,OAA6B;IAC/D,MAAM,EAAE,EAAE,EAAE,GAAG,OAAO,CAAA;IAEtB,EAAE,CAAC,IAAI,CAAC;;;;;;GAMP,CAAC,CAAA;IAEF,EAAE,CAAC,IAAI,CAAC;;;;;;;GAOP,CAAC,CAAA;IAEF,MAAM,eAAe,GAAG,EAAE,CAAC,OAAO,CAChC,+EAA+E,CAChF,CAAA;IAED,MAAM,aAAa,GAAG,EAAE,CAAC,OAAO,CAC9B,4DAA4D,CAC7D,CAAA;IAED,MAAM,UAAU,GAAG,EAAE,CAAC,OAAO,CAAC;;;;;;GAM7B,CAAC,CAAA;IAEF,OAAO;QACL,UAAU,CAAC,SAAS,EAAE,OAAO;YAC3B,IAAI,CAAC;gBACH,eAAe,CAAC,GAAG,CAAC,SAAS,EAAE,OAAO,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAA;gBACnD,aAAa,CAAC,GAAG,CAAC,SAAS,EAAE,OAAO,CAAC,CAAA;gBACrC,MAAM,CAAC,KAAK,CAAC,4BAA4B,SAAS,KAAK,OAAO,CAAC,MAAM,SAAS,CAAC,CAAA;YACjF,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,CAAC,KAAK,CAAC,0BAA0B,KAAK,EAAE,CAAC,CAAA;YACjD,CAAC;QACH,CAAC;QAED,YAAY,CAAC,KAAK,EAAE,KAAK,GAAG,CAAC;YAC3B,IAAI,CAAC;gBACH,MAAM,QAAQ,GAAG,KAAK;qBACnB,OAAO,CAAC,uBAAuB,EAAE,EAAE,CAAC;qBACpC,KAAK,CAAC,KAAK,CAAC;qBACZ,MAAM,CAAC,OAAO,CAAC;qBACf,IAAI,CAAC,MAAM,CAAC,CAAA;gBAEf,IAAI,CAAC,QAAQ;oBAAE,OAAO,EAAE,CAAA;gBAExB,OAAO,UAAU,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAyB,CAAA;YAChE,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,CAAC,KAAK,CAAC,yBAAyB,KAAK,EAAE,CAAC,CAAA;gBAC9C,OAAO,EAAE,CAAA;YACX,CAAC;QACH,CAAC;KACF,CAAA;AACH,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { FeishuApiClient } from "../feishu/api-client.js";
2
+ interface ProgressTrackerOptions {
3
+ feishuClient: FeishuApiClient;
4
+ }
5
+ export interface ProgressTracker {
6
+ sendThinking(chatId: string): Promise<string | null>;
7
+ updateWithResponse(messageId: string, text: string): Promise<void>;
8
+ updateWithError(messageId: string, msg: string): Promise<void>;
9
+ }
10
+ export declare function createProgressTracker(options: ProgressTrackerOptions): ProgressTracker;
11
+ export {};
12
+ //# sourceMappingURL=progress-tracker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"progress-tracker.d.ts","sourceRoot":"","sources":["../../src/session/progress-tracker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AAM9D,UAAU,sBAAsB;IAC9B,YAAY,EAAE,eAAe,CAAA;CAC9B;AAED,MAAM,WAAW,eAAe;IAC9B,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAA;IACpD,kBAAkB,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAClE,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAC/D;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,sBAAsB,GAAG,eAAe,CAyCtF"}
@@ -0,0 +1,46 @@
1
+ import { buildThinkingCard, buildResponseCard, buildErrorCard } from "../feishu/card-builder.js";
2
+ import { createLogger } from "../utils/logger.js";
3
+ const logger = createLogger("progress-tracker");
4
+ export function createProgressTracker(options) {
5
+ const { feishuClient } = options;
6
+ return {
7
+ async sendThinking(chatId) {
8
+ try {
9
+ const card = buildThinkingCard();
10
+ const result = await feishuClient.sendMessage(chatId, {
11
+ msg_type: "interactive",
12
+ content: JSON.stringify(card),
13
+ });
14
+ const messageId = result.data?.["message_id"];
15
+ if (!messageId) {
16
+ logger.error("sendThinking: no message_id in response");
17
+ return null;
18
+ }
19
+ return messageId;
20
+ }
21
+ catch (error) {
22
+ logger.error(`Failed to send thinking card: ${error}`);
23
+ return null;
24
+ }
25
+ },
26
+ async updateWithResponse(messageId, text) {
27
+ try {
28
+ const card = buildResponseCard(text);
29
+ await feishuClient.updateMessage(messageId, JSON.stringify(card));
30
+ }
31
+ catch (error) {
32
+ logger.error(`Failed to update response card: ${error}`);
33
+ }
34
+ },
35
+ async updateWithError(messageId, msg) {
36
+ try {
37
+ const card = buildErrorCard(msg);
38
+ await feishuClient.updateMessage(messageId, JSON.stringify(card));
39
+ }
40
+ catch (error) {
41
+ logger.error(`Failed to update error card: ${error}`);
42
+ }
43
+ },
44
+ };
45
+ }
46
+ //# sourceMappingURL=progress-tracker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"progress-tracker.js","sourceRoot":"","sources":["../../src/session/progress-tracker.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAA;AAChG,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAEjD,MAAM,MAAM,GAAG,YAAY,CAAC,kBAAkB,CAAC,CAAA;AAY/C,MAAM,UAAU,qBAAqB,CAAC,OAA+B;IACnE,MAAM,EAAE,YAAY,EAAE,GAAG,OAAO,CAAA;IAEhC,OAAO;QACL,KAAK,CAAC,YAAY,CAAC,MAAM;YACvB,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,iBAAiB,EAAE,CAAA;gBAChC,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,WAAW,CAAC,MAAM,EAAE;oBACpD,QAAQ,EAAE,aAAa;oBACvB,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;iBAC9B,CAAC,CAAA;gBACF,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,YAAY,CAAuB,CAAA;gBACnE,IAAI,CAAC,SAAS,EAAE,CAAC;oBACf,MAAM,CAAC,KAAK,CAAC,yCAAyC,CAAC,CAAA;oBACvD,OAAO,IAAI,CAAA;gBACb,CAAC;gBACD,OAAO,SAAS,CAAA;YAClB,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,CAAC,KAAK,CAAC,iCAAiC,KAAK,EAAE,CAAC,CAAA;gBACtD,OAAO,IAAI,CAAA;YACb,CAAC;QACH,CAAC;QAED,KAAK,CAAC,kBAAkB,CAAC,SAAS,EAAE,IAAI;YACtC,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAA;gBACpC,MAAM,YAAY,CAAC,aAAa,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAA;YACnE,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,CAAC,KAAK,CAAC,mCAAmC,KAAK,EAAE,CAAC,CAAA;YAC1D,CAAC;QACH,CAAC;QAED,KAAK,CAAC,eAAe,CAAC,SAAS,EAAE,GAAG;YAClC,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,cAAc,CAAC,GAAG,CAAC,CAAA;gBAChC,MAAM,YAAY,CAAC,aAAa,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAA;YACnE,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,CAAC,KAAK,CAAC,gCAAgC,KAAK,EAAE,CAAC,CAAA;YACvD,CAAC;QACH,CAAC;KACF,CAAA;AACH,CAAC"}
@@ -0,0 +1,15 @@
1
+ import { type Database } from "bun:sqlite";
2
+ import type { SessionMapping } from "../types.js";
3
+ interface SessionManagerOptions {
4
+ serverUrl: string;
5
+ db: Database;
6
+ defaultAgent: string;
7
+ }
8
+ export interface SessionManager {
9
+ getOrCreate(feishuKey: string, agent?: string): Promise<string>;
10
+ getSession(feishuKey: string): SessionMapping | null;
11
+ cleanup(maxAgeMs?: number): number;
12
+ }
13
+ export declare function createSessionManager(options: SessionManagerOptions): SessionManager;
14
+ export {};
15
+ //# sourceMappingURL=session-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-manager.d.ts","sourceRoot":"","sources":["../../src/session/session-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,QAAQ,EAAkB,MAAM,YAAY,CAAA;AAE1D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAIjD,UAAU,qBAAqB;IAC7B,SAAS,EAAE,MAAM,CAAA;IACjB,EAAE,EAAE,QAAQ,CAAA;IACZ,YAAY,EAAE,MAAM,CAAA;CACrB;AAED,MAAM,WAAW,cAAc;IAC7B,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;IAC/D,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI,CAAA;IACpD,OAAO,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;CACnC;AAaD,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,qBAAqB,GAC7B,cAAc,CA6GhB"}
@@ -0,0 +1,91 @@
1
+ import { createLogger } from "../utils/logger.js";
2
+ const logger = createLogger("session-manager");
3
+ function getWorkingDirectory() {
4
+ return process.env.OPENCODE_CWD || process.cwd();
5
+ }
6
+ export function createSessionManager(options) {
7
+ const { serverUrl, db, defaultAgent } = options;
8
+ db.exec(`
9
+ CREATE TABLE IF NOT EXISTS feishu_sessions (
10
+ feishu_key TEXT PRIMARY KEY,
11
+ session_id TEXT NOT NULL,
12
+ agent TEXT NOT NULL,
13
+ created_at INTEGER NOT NULL,
14
+ last_active INTEGER NOT NULL,
15
+ is_bound INTEGER DEFAULT 0
16
+ )
17
+ `);
18
+ try {
19
+ db.exec("ALTER TABLE feishu_sessions ADD COLUMN is_bound INTEGER DEFAULT 0");
20
+ }
21
+ catch {
22
+ // Column already exists — safe to ignore
23
+ }
24
+ const getStmt = db.prepare("SELECT * FROM feishu_sessions WHERE feishu_key = ?");
25
+ const upsertStmt = db.prepare(`INSERT OR REPLACE INTO feishu_sessions
26
+ (feishu_key, session_id, agent, created_at, last_active, is_bound)
27
+ VALUES (?, ?, ?, ?, ?, ?)`);
28
+ const updateActiveStmt = db.prepare("UPDATE feishu_sessions SET last_active = ? WHERE feishu_key = ?");
29
+ const cleanupStmt = db.prepare("DELETE FROM feishu_sessions WHERE last_active < ?");
30
+ async function discoverTuiSession() {
31
+ const cwd = getWorkingDirectory();
32
+ const url = `${serverUrl}/session?roots=true&limit=1&directory=${encodeURIComponent(cwd)}`;
33
+ try {
34
+ const resp = await fetch(url);
35
+ if (!resp.ok)
36
+ return null;
37
+ const sessions = (await resp.json());
38
+ return sessions[0] ?? null;
39
+ }
40
+ catch {
41
+ return null;
42
+ }
43
+ }
44
+ async function createNewSession(feishuKey) {
45
+ const resp = await fetch(`${serverUrl}/session`, {
46
+ method: "POST",
47
+ headers: { "Content-Type": "application/json" },
48
+ body: JSON.stringify({ title: `Feishu chat ${feishuKey}` }),
49
+ });
50
+ if (!resp.ok) {
51
+ throw new Error(`Failed to create session: HTTP ${resp.status}`);
52
+ }
53
+ const data = (await resp.json());
54
+ return data.id;
55
+ }
56
+ return {
57
+ async getOrCreate(feishuKey, agent) {
58
+ const existing = getStmt.get(feishuKey);
59
+ if (existing) {
60
+ updateActiveStmt.run(Date.now(), feishuKey);
61
+ return existing.session_id;
62
+ }
63
+ const agentName = agent ?? defaultAgent;
64
+ logger.info(`Resolving session for ${feishuKey} (agent: ${agentName})`);
65
+ const discovered = await discoverTuiSession();
66
+ if (discovered) {
67
+ const now = Date.now();
68
+ upsertStmt.run(feishuKey, discovered.id, agentName, now, now, 1);
69
+ logger.info(`Bound to TUI session: ${feishuKey} → ${discovered.id}`);
70
+ return discovered.id;
71
+ }
72
+ const sessionId = await createNewSession(feishuKey);
73
+ const now = Date.now();
74
+ upsertStmt.run(feishuKey, sessionId, agentName, now, now, 0);
75
+ logger.info(`Session created: ${feishuKey} → ${sessionId}`);
76
+ return sessionId;
77
+ },
78
+ getSession(feishuKey) {
79
+ return getStmt.get(feishuKey) ?? null;
80
+ },
81
+ cleanup(maxAgeMs = 30 * 60 * 1000) {
82
+ const cutoff = Date.now() - maxAgeMs;
83
+ const result = cleanupStmt.run(cutoff);
84
+ if (result.changes > 0) {
85
+ logger.info(`Cleaned up ${result.changes} expired session mappings`);
86
+ }
87
+ return result.changes;
88
+ },
89
+ };
90
+ }
91
+ //# sourceMappingURL=session-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-manager.js","sourceRoot":"","sources":["../../src/session/session-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,74 @@
1
+ export interface TextDelta {
2
+ readonly type: "TextDelta";
3
+ readonly sessionId: string;
4
+ readonly text: string;
5
+ }
6
+ export interface ToolStateChange {
7
+ readonly type: "ToolStateChange";
8
+ readonly sessionId: string;
9
+ readonly toolName: string;
10
+ readonly state: string;
11
+ readonly input?: Record<string, unknown>;
12
+ readonly output?: string;
13
+ readonly error?: string;
14
+ readonly title?: string;
15
+ }
16
+ export interface SubtaskDiscovered {
17
+ readonly type: "SubtaskDiscovered";
18
+ readonly sessionId: string;
19
+ readonly prompt: string;
20
+ readonly description: string;
21
+ readonly agent: string;
22
+ }
23
+ export interface SessionIdle {
24
+ readonly type: "SessionIdle";
25
+ readonly sessionId: string;
26
+ }
27
+ export interface QuestionAsked {
28
+ readonly type: "QuestionAsked";
29
+ readonly sessionId: string;
30
+ readonly requestId: string;
31
+ readonly questions: ReadonlyArray<{
32
+ question: string;
33
+ header: string;
34
+ options: ReadonlyArray<{
35
+ label: string;
36
+ description: string;
37
+ }>;
38
+ multiple?: boolean;
39
+ custom?: boolean;
40
+ }>;
41
+ }
42
+ export interface PermissionRequested {
43
+ readonly type: "PermissionRequested";
44
+ readonly sessionId: string;
45
+ readonly requestId: string;
46
+ readonly permissionType: string;
47
+ readonly title: string;
48
+ readonly metadata: Record<string, unknown>;
49
+ }
50
+ export type ProcessedAction = TextDelta | ToolStateChange | SubtaskDiscovered | SessionIdle | QuestionAsked | PermissionRequested;
51
+ export interface EventProcessorOptions {
52
+ ownedSessions: Set<string>;
53
+ logger?: {
54
+ warn(msg: string, ...args: unknown[]): void;
55
+ };
56
+ }
57
+ export declare class EventProcessor {
58
+ private readonly ownedSessions;
59
+ private readonly reasoningPartIds;
60
+ private readonly logger?;
61
+ constructor(options: EventProcessorOptions);
62
+ processEvent(raw: unknown): ProcessedAction | null;
63
+ private processMessagePartUpdated;
64
+ private processMessagePartDelta;
65
+ private processTextPart;
66
+ private processReasoningPart;
67
+ private processToolPart;
68
+ private processSubtaskPart;
69
+ private processSessionStatus;
70
+ private processSessionIdle;
71
+ private processQuestionAsked;
72
+ private processPermissionAsked;
73
+ }
74
+ //# sourceMappingURL=event-processor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-processor.d.ts","sourceRoot":"","sources":["../../src/streaming/event-processor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,240 @@
1
+ // ═══════════════════════════════════════════
2
+ // SSE Event Processor
3
+ // Parses raw opencode SSE events into typed actions.
4
+ // ═══════════════════════════════════════════
5
+ // ---------------------------------------------------------------------------
6
+ // Type guards
7
+ // ---------------------------------------------------------------------------
8
+ function isObject(v) {
9
+ return v !== null && typeof v === "object";
10
+ }
11
+ function hasType(v) {
12
+ return isObject(v) && typeof v.type === "string";
13
+ }
14
+ const KNOWN_TYPES = new Set([
15
+ "message.part.updated",
16
+ "message.part.delta",
17
+ "session.status",
18
+ "session.idle",
19
+ "question.asked",
20
+ "permission.asked",
21
+ ]);
22
+ function isKnownEvent(v) {
23
+ if (!hasType(v))
24
+ return false;
25
+ return KNOWN_TYPES.has(v.type);
26
+ }
27
+ export class EventProcessor {
28
+ ownedSessions;
29
+ reasoningPartIds = new Set();
30
+ logger;
31
+ constructor(options) {
32
+ this.ownedSessions = options.ownedSessions;
33
+ this.logger = options.logger;
34
+ }
35
+ processEvent(raw) {
36
+ try {
37
+ if (!isKnownEvent(raw))
38
+ return null;
39
+ switch (raw.type) {
40
+ case "message.part.updated":
41
+ return this.processMessagePartUpdated(raw);
42
+ case "message.part.delta":
43
+ return this.processMessagePartDelta(raw);
44
+ case "session.status":
45
+ return this.processSessionStatus(raw);
46
+ case "session.idle":
47
+ return this.processSessionIdle(raw);
48
+ case "question.asked":
49
+ return this.processQuestionAsked(raw);
50
+ case "permission.asked":
51
+ return this.processPermissionAsked(raw);
52
+ default:
53
+ return null;
54
+ }
55
+ }
56
+ catch (err) {
57
+ const eventType = raw?.type ?? "unknown";
58
+ this.logger?.warn(`Error processing ${eventType} event: ${err}`);
59
+ return null;
60
+ }
61
+ }
62
+ // -------------------------------------------------------------------------
63
+ // Private handlers
64
+ // -------------------------------------------------------------------------
65
+ processMessagePartUpdated(event) {
66
+ const { part, delta } = event.properties;
67
+ if (!part || !isObject(part))
68
+ return null;
69
+ const sessionId = part.sessionID;
70
+ if (typeof sessionId !== "string")
71
+ return null;
72
+ if (!this.ownedSessions.has(sessionId))
73
+ return null;
74
+ const partType = part.type;
75
+ if (typeof partType !== "string")
76
+ return null;
77
+ // Track reasoning part IDs so message.part.delta events can be filtered
78
+ const partId = part.id;
79
+ if (partType === "reasoning" && typeof partId === "string") {
80
+ this.reasoningPartIds.add(partId);
81
+ }
82
+ switch (partType) {
83
+ case "text":
84
+ return this.processTextPart(sessionId, delta);
85
+ case "reasoning":
86
+ return this.processReasoningPart(sessionId, delta);
87
+ case "tool":
88
+ return this.processToolPart(sessionId, part);
89
+ case "subtask":
90
+ return this.processSubtaskPart(sessionId, part);
91
+ default:
92
+ return null;
93
+ }
94
+ }
95
+ processMessagePartDelta(event) {
96
+ const props = event.properties;
97
+ if (!isObject(props))
98
+ return null;
99
+ const sessionId = props.sessionID;
100
+ if (typeof sessionId !== "string")
101
+ return null;
102
+ if (!this.ownedSessions.has(sessionId))
103
+ return null;
104
+ const field = props.field;
105
+ if (field !== "text")
106
+ return null;
107
+ const delta = props.delta;
108
+ if (typeof delta !== "string" || delta.length === 0)
109
+ return null;
110
+ // Check if this delta belongs to a reasoning part
111
+ const partID = props.partID;
112
+ if (typeof partID === "string" && this.reasoningPartIds.has(partID)) {
113
+ return null;
114
+ }
115
+ return { type: "TextDelta", sessionId, text: delta };
116
+ }
117
+ processTextPart(sessionId, delta) {
118
+ if (typeof delta !== "string" || delta.length === 0)
119
+ return null;
120
+ return { type: "TextDelta", sessionId, text: delta };
121
+ }
122
+ processReasoningPart(_sessionId, _delta) {
123
+ return null;
124
+ }
125
+ processToolPart(sessionId, part) {
126
+ const toolName = part.tool;
127
+ const state = part.state;
128
+ if (typeof toolName !== "string" || !isObject(state))
129
+ return null;
130
+ const status = state.status;
131
+ if (typeof status !== "string")
132
+ return null;
133
+ const error = state.error;
134
+ const title = state.title;
135
+ const input = state.input;
136
+ const output = state.output;
137
+ const result = {
138
+ type: "ToolStateChange",
139
+ sessionId,
140
+ toolName,
141
+ state: status,
142
+ ...(isObject(input) ? { input: input } : {}),
143
+ ...(typeof output === "string" ? { output } : {}),
144
+ ...(typeof error === "string" ? { error } : {}),
145
+ ...(typeof title === "string" ? { title } : {}),
146
+ };
147
+ return result;
148
+ }
149
+ processSubtaskPart(sessionId, part) {
150
+ const { prompt, description, agent } = part;
151
+ if (typeof prompt !== "string" ||
152
+ typeof description !== "string" ||
153
+ typeof agent !== "string") {
154
+ return null;
155
+ }
156
+ return { type: "SubtaskDiscovered", sessionId, prompt, description, agent };
157
+ }
158
+ processSessionStatus(event) {
159
+ const props = event.properties;
160
+ if (!isObject(props))
161
+ return null;
162
+ const sessionId = props.sessionID;
163
+ if (typeof sessionId !== "string")
164
+ return null;
165
+ if (!this.ownedSessions.has(sessionId))
166
+ return null;
167
+ const status = props.status;
168
+ if (!isObject(status))
169
+ return null;
170
+ const statusType = status.type;
171
+ if (typeof statusType !== "string")
172
+ return null;
173
+ switch (statusType) {
174
+ case "busy":
175
+ return null;
176
+ case "idle":
177
+ return { type: "SessionIdle", sessionId };
178
+ default:
179
+ return null;
180
+ }
181
+ }
182
+ processSessionIdle(event) {
183
+ const props = event.properties;
184
+ if (!isObject(props))
185
+ return null;
186
+ const sessionId = props.sessionID;
187
+ if (typeof sessionId !== "string")
188
+ return null;
189
+ if (!this.ownedSessions.has(sessionId))
190
+ return null;
191
+ return { type: "SessionIdle", sessionId };
192
+ }
193
+ processQuestionAsked(event) {
194
+ const props = event.properties;
195
+ if (!isObject(props))
196
+ return null;
197
+ const requestId = props.id;
198
+ if (typeof requestId !== "string")
199
+ return null;
200
+ const sessionId = props.sessionID;
201
+ if (typeof sessionId !== "string")
202
+ return null;
203
+ const questions = props.questions;
204
+ if (!Array.isArray(questions) || questions.length === 0)
205
+ return null;
206
+ return {
207
+ type: "QuestionAsked",
208
+ sessionId,
209
+ requestId,
210
+ questions: questions,
211
+ };
212
+ }
213
+ processPermissionAsked(event) {
214
+ const props = event.properties;
215
+ if (!isObject(props))
216
+ return null;
217
+ const requestId = props.id;
218
+ if (typeof requestId !== "string")
219
+ return null;
220
+ const sessionId = props.sessionID;
221
+ if (typeof sessionId !== "string")
222
+ return null;
223
+ const permissionType = props.permission;
224
+ if (typeof permissionType !== "string")
225
+ return null;
226
+ const patterns = props.patterns;
227
+ const patternList = Array.isArray(patterns) ? patterns.filter((p) => typeof p === "string") : [];
228
+ const title = patternList.length > 0 ? patternList.join(", ") : permissionType;
229
+ const metadata = props.metadata;
230
+ return {
231
+ type: "PermissionRequested",
232
+ sessionId,
233
+ requestId,
234
+ permissionType,
235
+ title,
236
+ metadata: isObject(metadata) ? metadata : {},
237
+ };
238
+ }
239
+ }
240
+ //# sourceMappingURL=event-processor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-processor.js","sourceRoot":"","sources":["../../src/streaming/event-processor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import type { EventProcessor } from "./event-processor.js";
2
+ import type { FeishuApiClient } from "../feishu/api-client.js";
3
+ import type { Logger } from "../utils/logger.js";
4
+ export interface SessionObserverDeps {
5
+ feishuClient: Pick<FeishuApiClient, "sendMessage">;
6
+ eventProcessor: EventProcessor;
7
+ addListener: (sessionId: string, fn: (event: unknown) => void) => void;
8
+ removeListener: (sessionId: string, fn: (event: unknown) => void) => void;
9
+ logger: Logger;
10
+ seenInteractiveIds: Set<string>;
11
+ }
12
+ export interface SessionObserver {
13
+ observe(sessionId: string, chatId: string): void;
14
+ markOwned(messageId: string): void;
15
+ getChatForSession(sessionId: string): string | undefined;
16
+ stop(): void;
17
+ }
18
+ export declare function createSessionObserver(deps: SessionObserverDeps): SessionObserver;
19
+ //# sourceMappingURL=session-observer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-observer.d.ts","sourceRoot":"","sources":["../../src/streaming/session-observer.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAC1D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AAC9D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAA;AAOhD,MAAM,WAAW,mBAAmB;IAClC,YAAY,EAAE,IAAI,CAAC,eAAe,EAAE,aAAa,CAAC,CAAA;IAClD,cAAc,EAAE,cAAc,CAAA;IAC9B,WAAW,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,KAAK,IAAI,CAAA;IACtE,cAAc,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,KAAK,IAAI,CAAA;IACzE,MAAM,EAAE,MAAM,CAAA;IACd,kBAAkB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;CAChC;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IAChD,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IAClC,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAA;IACxD,IAAI,IAAI,IAAI,CAAA;CACb;AA2BD,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,mBAAmB,GACxB,eAAe,CAkHjB"}