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.
- package/CHANGELOG.md +50 -0
- package/LICENSE +21 -0
- package/README.md +322 -0
- package/README.zh-CN.md +324 -0
- package/bin/opencode-lark.js +2 -0
- package/dist/channel/base-plugin.d.ts +31 -0
- package/dist/channel/base-plugin.d.ts.map +1 -0
- package/dist/channel/base-plugin.js +42 -0
- package/dist/channel/base-plugin.js.map +1 -0
- package/dist/channel/feishu/feishu-plugin.d.ts +36 -0
- package/dist/channel/feishu/feishu-plugin.d.ts.map +1 -0
- package/dist/channel/feishu/feishu-plugin.js +149 -0
- package/dist/channel/feishu/feishu-plugin.js.map +1 -0
- package/dist/channel/feishu/index.d.ts +2 -0
- package/dist/channel/feishu/index.d.ts.map +1 -0
- package/dist/channel/feishu/index.js +2 -0
- package/dist/channel/feishu/index.js.map +1 -0
- package/dist/channel/index.d.ts +4 -0
- package/dist/channel/index.d.ts.map +1 -0
- package/dist/channel/index.js +4 -0
- package/dist/channel/index.js.map +1 -0
- package/dist/channel/manager.d.ts +37 -0
- package/dist/channel/manager.d.ts.map +1 -0
- package/dist/channel/manager.js +68 -0
- package/dist/channel/manager.js.map +1 -0
- package/dist/channel/mock/mock-plugin.d.ts +24 -0
- package/dist/channel/mock/mock-plugin.d.ts.map +1 -0
- package/dist/channel/mock/mock-plugin.js +42 -0
- package/dist/channel/mock/mock-plugin.js.map +1 -0
- package/dist/channel/types.d.ts +226 -0
- package/dist/channel/types.d.ts.map +1 -0
- package/dist/channel/types.js +7 -0
- package/dist/channel/types.js.map +1 -0
- package/dist/cron/cron-service.d.ts +40 -0
- package/dist/cron/cron-service.d.ts.map +1 -0
- package/dist/cron/cron-service.js +140 -0
- package/dist/cron/cron-service.js.map +1 -0
- package/dist/cron/heartbeat.d.ts +30 -0
- package/dist/cron/heartbeat.d.ts.map +1 -0
- package/dist/cron/heartbeat.js +76 -0
- package/dist/cron/heartbeat.js.map +1 -0
- package/dist/feishu/api-client.d.ts +19 -0
- package/dist/feishu/api-client.d.ts.map +1 -0
- package/dist/feishu/api-client.js +98 -0
- package/dist/feishu/api-client.js.map +1 -0
- package/dist/feishu/card-builder.d.ts +10 -0
- package/dist/feishu/card-builder.d.ts.map +1 -0
- package/dist/feishu/card-builder.js +74 -0
- package/dist/feishu/card-builder.js.map +1 -0
- package/dist/feishu/cardkit-client.d.ts +48 -0
- package/dist/feishu/cardkit-client.d.ts.map +1 -0
- package/dist/feishu/cardkit-client.js +97 -0
- package/dist/feishu/cardkit-client.js.map +1 -0
- package/dist/feishu/message-dedup.d.ts +28 -0
- package/dist/feishu/message-dedup.d.ts.map +1 -0
- package/dist/feishu/message-dedup.js +58 -0
- package/dist/feishu/message-dedup.js.map +1 -0
- package/dist/feishu/webhook-server.d.ts +20 -0
- package/dist/feishu/webhook-server.d.ts.map +1 -0
- package/dist/feishu/webhook-server.js +111 -0
- package/dist/feishu/webhook-server.js.map +1 -0
- package/dist/feishu/ws-client.d.ts +17 -0
- package/dist/feishu/ws-client.d.ts.map +1 -0
- package/dist/feishu/ws-client.js +158 -0
- package/dist/feishu/ws-client.js.map +1 -0
- package/dist/handler/interactive-handler.d.ts +16 -0
- package/dist/handler/interactive-handler.d.ts.map +1 -0
- package/dist/handler/interactive-handler.js +86 -0
- package/dist/handler/interactive-handler.js.map +1 -0
- package/dist/handler/interactive-poller.d.ts +16 -0
- package/dist/handler/interactive-poller.d.ts.map +1 -0
- package/dist/handler/interactive-poller.js +147 -0
- package/dist/handler/interactive-poller.js.map +1 -0
- package/dist/handler/message-handler.d.ts +34 -0
- package/dist/handler/message-handler.d.ts.map +1 -0
- package/dist/handler/message-handler.js +305 -0
- package/dist/handler/message-handler.js.map +1 -0
- package/dist/handler/streaming-integration.d.ts +21 -0
- package/dist/handler/streaming-integration.d.ts.map +1 -0
- package/dist/handler/streaming-integration.js +325 -0
- package/dist/handler/streaming-integration.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +281 -0
- package/dist/index.js.map +1 -0
- package/dist/memory/memory-manager.d.ts +16 -0
- package/dist/memory/memory-manager.d.ts.map +1 -0
- package/dist/memory/memory-manager.js +58 -0
- package/dist/memory/memory-manager.js.map +1 -0
- package/dist/session/progress-tracker.d.ts +12 -0
- package/dist/session/progress-tracker.d.ts.map +1 -0
- package/dist/session/progress-tracker.js +46 -0
- package/dist/session/progress-tracker.js.map +1 -0
- package/dist/session/session-manager.d.ts +15 -0
- package/dist/session/session-manager.d.ts.map +1 -0
- package/dist/session/session-manager.js +91 -0
- package/dist/session/session-manager.js.map +1 -0
- package/dist/streaming/event-processor.d.ts +74 -0
- package/dist/streaming/event-processor.d.ts.map +1 -0
- package/dist/streaming/event-processor.js +240 -0
- package/dist/streaming/event-processor.js.map +1 -0
- package/dist/streaming/session-observer.d.ts +19 -0
- package/dist/streaming/session-observer.d.ts.map +1 -0
- package/dist/streaming/session-observer.js +140 -0
- package/dist/streaming/session-observer.js.map +1 -0
- package/dist/streaming/streaming-card.d.ts +37 -0
- package/dist/streaming/streaming-card.d.ts.map +1 -0
- package/dist/streaming/streaming-card.js +139 -0
- package/dist/streaming/streaming-card.js.map +1 -0
- package/dist/streaming/subagent-card.d.ts +32 -0
- package/dist/streaming/subagent-card.d.ts.map +1 -0
- package/dist/streaming/subagent-card.js +103 -0
- package/dist/streaming/subagent-card.js.map +1 -0
- package/dist/streaming/subagent-tracker.d.ts +45 -0
- package/dist/streaming/subagent-tracker.d.ts.map +1 -0
- package/dist/streaming/subagent-tracker.js +118 -0
- package/dist/streaming/subagent-tracker.js.map +1 -0
- package/dist/types.d.ts +55 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/config.d.ts +197 -0
- package/dist/utils/config.d.ts.map +1 -0
- package/dist/utils/config.js +87 -0
- package/dist/utils/config.js.map +1 -0
- package/dist/utils/db.d.ts +12 -0
- package/dist/utils/db.d.ts.map +1 -0
- package/dist/utils/db.js +35 -0
- package/dist/utils/db.js.map +1 -0
- package/dist/utils/event-listeners.d.ts +12 -0
- package/dist/utils/event-listeners.d.ts.map +1 -0
- package/dist/utils/event-listeners.js +21 -0
- package/dist/utils/event-listeners.js.map +1 -0
- package/dist/utils/logger.d.ts +11 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +38 -0
- package/dist/utils/logger.js.map +1 -0
- package/package.json +41 -0
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
// ═══════════════════════════════════════════
|
|
2
|
+
// Session Observer
|
|
3
|
+
// Observes opencode sessions and forwards TUI-initiated
|
|
4
|
+
// messages to Feishu chats.
|
|
5
|
+
// ═══════════════════════════════════════════
|
|
6
|
+
import { buildQuestionCard, buildPermissionCard } from "../handler/streaming-integration.js";
|
|
7
|
+
// ---------------------------------------------------------------------------
|
|
8
|
+
// Helpers
|
|
9
|
+
// ---------------------------------------------------------------------------
|
|
10
|
+
function extractMessageId(rawEvent) {
|
|
11
|
+
if (rawEvent === null || typeof rawEvent !== "object")
|
|
12
|
+
return undefined;
|
|
13
|
+
const props = rawEvent.properties;
|
|
14
|
+
if (!props || typeof props !== "object")
|
|
15
|
+
return undefined;
|
|
16
|
+
const p = props;
|
|
17
|
+
// message.part.updated → properties.part.messageID
|
|
18
|
+
// message.part.delta → properties.messageID
|
|
19
|
+
const part = p.part;
|
|
20
|
+
if (part && typeof part === "object") {
|
|
21
|
+
const mid = part.messageID;
|
|
22
|
+
if (typeof mid === "string")
|
|
23
|
+
return mid;
|
|
24
|
+
}
|
|
25
|
+
const mid = p.messageID;
|
|
26
|
+
if (typeof mid === "string")
|
|
27
|
+
return mid;
|
|
28
|
+
return undefined;
|
|
29
|
+
}
|
|
30
|
+
// ---------------------------------------------------------------------------
|
|
31
|
+
// Factory
|
|
32
|
+
// ---------------------------------------------------------------------------
|
|
33
|
+
export function createSessionObserver(deps) {
|
|
34
|
+
const { feishuClient, eventProcessor, addListener, removeListener, logger, seenInteractiveIds } = deps;
|
|
35
|
+
// Feishu-initiated message IDs — skip these in forwarding
|
|
36
|
+
const knownMessageIds = new Set();
|
|
37
|
+
// Per-messageId text accumulation
|
|
38
|
+
const textBuffers = new Map();
|
|
39
|
+
// Active observation state per session
|
|
40
|
+
const observedSessions = new Map();
|
|
41
|
+
function flushBuffers(chatId) {
|
|
42
|
+
for (const [messageId, text] of textBuffers) {
|
|
43
|
+
if (text.trim().length === 0)
|
|
44
|
+
continue;
|
|
45
|
+
feishuClient
|
|
46
|
+
.sendMessage(chatId, {
|
|
47
|
+
msg_type: "text",
|
|
48
|
+
content: JSON.stringify({ text }),
|
|
49
|
+
})
|
|
50
|
+
.catch((err) => {
|
|
51
|
+
logger.error(`Failed to send TUI message for ${messageId}: ${err}`);
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
textBuffers.clear();
|
|
55
|
+
}
|
|
56
|
+
return {
|
|
57
|
+
observe(sessionId, chatId) {
|
|
58
|
+
if (observedSessions.has(sessionId))
|
|
59
|
+
return;
|
|
60
|
+
const listener = (rawEvent) => {
|
|
61
|
+
const action = eventProcessor.processEvent(rawEvent);
|
|
62
|
+
if (!action)
|
|
63
|
+
return;
|
|
64
|
+
const messageId = extractMessageId(rawEvent);
|
|
65
|
+
// Skip events belonging to Feishu-initiated messages
|
|
66
|
+
if (messageId && knownMessageIds.has(messageId))
|
|
67
|
+
return;
|
|
68
|
+
switch (action.type) {
|
|
69
|
+
case "TextDelta": {
|
|
70
|
+
if (!messageId)
|
|
71
|
+
break;
|
|
72
|
+
const current = textBuffers.get(messageId) ?? "";
|
|
73
|
+
textBuffers.set(messageId, current + action.text);
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
case "SessionIdle": {
|
|
77
|
+
flushBuffers(chatId);
|
|
78
|
+
break;
|
|
79
|
+
}
|
|
80
|
+
case "QuestionAsked": {
|
|
81
|
+
if (seenInteractiveIds.has(action.requestId))
|
|
82
|
+
break;
|
|
83
|
+
seenInteractiveIds.add(action.requestId);
|
|
84
|
+
logger.info(`Question event received in observer for chat ${chatId}, requestId=${action.requestId}`);
|
|
85
|
+
const questionCard = buildQuestionCard(action);
|
|
86
|
+
feishuClient
|
|
87
|
+
.sendMessage(chatId, {
|
|
88
|
+
msg_type: "interactive",
|
|
89
|
+
content: JSON.stringify(questionCard),
|
|
90
|
+
})
|
|
91
|
+
.catch((err) => {
|
|
92
|
+
logger.warn(`Question card send failed (observer): ${err}`);
|
|
93
|
+
});
|
|
94
|
+
break;
|
|
95
|
+
}
|
|
96
|
+
case "PermissionRequested": {
|
|
97
|
+
if (seenInteractiveIds.has(action.requestId))
|
|
98
|
+
break;
|
|
99
|
+
seenInteractiveIds.add(action.requestId);
|
|
100
|
+
logger.info(`Permission event received in observer for chat ${chatId}, requestId=${action.requestId}`);
|
|
101
|
+
const permissionCard = buildPermissionCard(action);
|
|
102
|
+
feishuClient
|
|
103
|
+
.sendMessage(chatId, {
|
|
104
|
+
msg_type: "interactive",
|
|
105
|
+
content: JSON.stringify(permissionCard),
|
|
106
|
+
})
|
|
107
|
+
.catch((err) => {
|
|
108
|
+
logger.warn(`Permission card send failed (observer): ${err}`);
|
|
109
|
+
});
|
|
110
|
+
break;
|
|
111
|
+
}
|
|
112
|
+
default:
|
|
113
|
+
// ToolStateChange, SubtaskDiscovered — ignored
|
|
114
|
+
break;
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
addListener(sessionId, listener);
|
|
118
|
+
observedSessions.set(sessionId, { chatId, listener });
|
|
119
|
+
logger.info(`Observing session ${sessionId} for chat ${chatId}`);
|
|
120
|
+
},
|
|
121
|
+
markOwned(messageId) {
|
|
122
|
+
knownMessageIds.add(messageId);
|
|
123
|
+
// Drop any buffered text for this message
|
|
124
|
+
textBuffers.delete(messageId);
|
|
125
|
+
},
|
|
126
|
+
getChatForSession(sessionId) {
|
|
127
|
+
return observedSessions.get(sessionId)?.chatId;
|
|
128
|
+
},
|
|
129
|
+
stop() {
|
|
130
|
+
for (const [sessionId, { listener }] of observedSessions) {
|
|
131
|
+
removeListener(sessionId, listener);
|
|
132
|
+
}
|
|
133
|
+
observedSessions.clear();
|
|
134
|
+
textBuffers.clear();
|
|
135
|
+
knownMessageIds.clear();
|
|
136
|
+
logger.info("Session observer stopped");
|
|
137
|
+
},
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
//# sourceMappingURL=session-observer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-observer.js","sourceRoot":"","sources":["../../src/streaming/session-observer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* High-level streaming card session manager.
|
|
3
|
+
* Wraps CardKitClient with throttling, tool status, sub-agent buttons,
|
|
4
|
+
* and full lifecycle management.
|
|
5
|
+
*/
|
|
6
|
+
import type { CardKitClient } from "../feishu/cardkit-client.js";
|
|
7
|
+
import type { FeishuApiClient } from "../feishu/api-client.js";
|
|
8
|
+
export interface StreamingCardOptions {
|
|
9
|
+
cardkitClient: CardKitClient;
|
|
10
|
+
feishuClient: FeishuApiClient;
|
|
11
|
+
chatId: string;
|
|
12
|
+
}
|
|
13
|
+
export declare class StreamingCardSession {
|
|
14
|
+
private readonly cardkitClient;
|
|
15
|
+
private readonly feishuClient;
|
|
16
|
+
private readonly chatId;
|
|
17
|
+
private state;
|
|
18
|
+
private closed;
|
|
19
|
+
private queue;
|
|
20
|
+
private lastUpdateTime;
|
|
21
|
+
private pendingText;
|
|
22
|
+
private lastSentContent;
|
|
23
|
+
private readonly updateThrottleMs;
|
|
24
|
+
private toolStatuses;
|
|
25
|
+
private subtaskButtons;
|
|
26
|
+
constructor(options: StreamingCardOptions);
|
|
27
|
+
get isActive(): boolean;
|
|
28
|
+
start(): Promise<void>;
|
|
29
|
+
setToolStatus(name: string, state: "running" | "completed" | "error", title?: string): Promise<void>;
|
|
30
|
+
addSubtaskButton(label: string, actionValue: string): Promise<void>;
|
|
31
|
+
close(finalText?: string): Promise<void>;
|
|
32
|
+
private enqueueUpdate;
|
|
33
|
+
private buildToolStatusText;
|
|
34
|
+
private buildButtonsText;
|
|
35
|
+
private buildFullContent;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=streaming-card.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"streaming-card.d.ts","sourceRoot":"","sources":["../../src/streaming/streaming-card.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAiB,MAAM,6BAA6B,CAAA;AAC/E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AAE9D,MAAM,WAAW,oBAAoB;IACnC,aAAa,EAAE,aAAa,CAAA;IAC5B,YAAY,EAAE,eAAe,CAAA;IAC7B,MAAM,EAAE,MAAM,CAAA;CACf;AAoBD,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAe;IAC7C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAiB;IAC9C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAQ;IAE/B,OAAO,CAAC,KAAK,CAAyB;IACtC,OAAO,CAAC,MAAM,CAAQ;IACtB,OAAO,CAAC,KAAK,CAAmC;IAChD,OAAO,CAAC,cAAc,CAAI;IAC1B,OAAO,CAAC,WAAW,CAAsB;IACzC,OAAO,CAAC,eAAe,CAAK;IAC5B,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAM;IAEvC,OAAO,CAAC,YAAY,CAAmB;IACvC,OAAO,CAAC,cAAc,CAAsB;gBAEhC,OAAO,EAAE,oBAAoB;IAMzC,IAAI,QAAQ,IAAI,OAAO,CAEtB;IAEK,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAsCtB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,GAAG,WAAW,GAAG,OAAO,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAkBpG,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAYnE,KAAK,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;YA8BhC,aAAa;IAiB3B,OAAO,CAAC,mBAAmB;IAe3B,OAAO,CAAC,gBAAgB;IAUxB,OAAO,CAAC,gBAAgB;CAKzB"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* High-level streaming card session manager.
|
|
3
|
+
* Wraps CardKitClient with throttling, tool status, sub-agent buttons,
|
|
4
|
+
* and full lifecycle management.
|
|
5
|
+
*/
|
|
6
|
+
export class StreamingCardSession {
|
|
7
|
+
cardkitClient;
|
|
8
|
+
feishuClient;
|
|
9
|
+
chatId;
|
|
10
|
+
state = null;
|
|
11
|
+
closed = false;
|
|
12
|
+
queue = Promise.resolve();
|
|
13
|
+
lastUpdateTime = 0;
|
|
14
|
+
pendingText = null;
|
|
15
|
+
lastSentContent = "";
|
|
16
|
+
updateThrottleMs = 100;
|
|
17
|
+
toolStatuses = [];
|
|
18
|
+
subtaskButtons = [];
|
|
19
|
+
constructor(options) {
|
|
20
|
+
this.cardkitClient = options.cardkitClient;
|
|
21
|
+
this.feishuClient = options.feishuClient;
|
|
22
|
+
this.chatId = options.chatId;
|
|
23
|
+
}
|
|
24
|
+
get isActive() {
|
|
25
|
+
return this.state !== null && !this.closed;
|
|
26
|
+
}
|
|
27
|
+
async start() {
|
|
28
|
+
if (this.state) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
const cardJson = {
|
|
32
|
+
schema: "2.0",
|
|
33
|
+
config: {
|
|
34
|
+
streaming_mode: true,
|
|
35
|
+
summary: { content: "[Generating...]" },
|
|
36
|
+
streaming_config: {
|
|
37
|
+
print_frequency_ms: { default: 200 },
|
|
38
|
+
print_step: { default: 10 },
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
body: {
|
|
42
|
+
elements: [
|
|
43
|
+
{ tag: "markdown", content: "🛠️ Processing...", element_id: "content" },
|
|
44
|
+
],
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
const cardId = await this.cardkitClient.createCard(cardJson);
|
|
48
|
+
const result = await this.feishuClient.sendMessage(this.chatId, {
|
|
49
|
+
msg_type: "interactive",
|
|
50
|
+
content: JSON.stringify({ type: "card", data: { card_id: cardId } }),
|
|
51
|
+
});
|
|
52
|
+
const messageId = result.data?.["message_id"];
|
|
53
|
+
if (!messageId) {
|
|
54
|
+
throw new Error("sendMessage returned no message_id");
|
|
55
|
+
}
|
|
56
|
+
this.state = { cardId, messageId, sequence: 1, currentText: "" };
|
|
57
|
+
}
|
|
58
|
+
async setToolStatus(name, state, title) {
|
|
59
|
+
if (!this.state || this.closed) {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
const existing = this.toolStatuses.find((t) => t.name === name);
|
|
63
|
+
if (existing) {
|
|
64
|
+
existing.state = state;
|
|
65
|
+
if (title !== undefined)
|
|
66
|
+
existing.title = title;
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
this.toolStatuses.push({ name, state, title });
|
|
70
|
+
}
|
|
71
|
+
// Build tool status text and update the content element
|
|
72
|
+
const fullContent = this.buildFullContent();
|
|
73
|
+
await this.enqueueUpdate(fullContent);
|
|
74
|
+
}
|
|
75
|
+
async addSubtaskButton(label, actionValue) {
|
|
76
|
+
if (!this.state || this.closed) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
this.subtaskButtons.push({ label, actionValue });
|
|
80
|
+
// Rebuild full content with buttons section
|
|
81
|
+
const fullContent = this.buildFullContent();
|
|
82
|
+
await this.enqueueUpdate(fullContent);
|
|
83
|
+
}
|
|
84
|
+
async close(finalText) {
|
|
85
|
+
if (!this.state || this.closed) {
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
this.closed = true;
|
|
89
|
+
await this.queue;
|
|
90
|
+
// Final content: use finalText override, tool status content, or "Done" fallback
|
|
91
|
+
const text = finalText ?? (this.toolStatuses.length > 0 ? this.buildFullContent() : "✅ Done");
|
|
92
|
+
// Only send final update if content differs from what was last sent
|
|
93
|
+
if (text && text !== this.lastSentContent) {
|
|
94
|
+
this.state.sequence += 1;
|
|
95
|
+
await this.cardkitClient.updateElement(this.state.cardId, "content", text, this.state.sequence);
|
|
96
|
+
}
|
|
97
|
+
// Close streaming mode with tool-focused summary
|
|
98
|
+
const completed = this.toolStatuses.filter(t => t.state === "completed").length;
|
|
99
|
+
const summary = completed > 0 ? `✅ ${completed} tool(s) used` : "Done";
|
|
100
|
+
this.state.sequence += 1;
|
|
101
|
+
await this.cardkitClient.closeStreaming(this.state.cardId, summary, this.state.sequence);
|
|
102
|
+
}
|
|
103
|
+
async enqueueUpdate(content) {
|
|
104
|
+
this.queue = this.queue.then(async () => {
|
|
105
|
+
if (!this.state || this.closed) {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
this.state.sequence += 1;
|
|
109
|
+
await this.cardkitClient.updateElement(this.state.cardId, "content", content, this.state.sequence);
|
|
110
|
+
this.lastSentContent = content;
|
|
111
|
+
});
|
|
112
|
+
await this.queue;
|
|
113
|
+
}
|
|
114
|
+
buildToolStatusText() {
|
|
115
|
+
if (this.toolStatuses.length === 0) {
|
|
116
|
+
return "";
|
|
117
|
+
}
|
|
118
|
+
const icons = {
|
|
119
|
+
running: "🔄",
|
|
120
|
+
completed: "✅",
|
|
121
|
+
error: "❌",
|
|
122
|
+
};
|
|
123
|
+
const lines = this.toolStatuses.map((t) => t.title ? `${icons[t.state]} ${t.name} · ${t.title}` : `${icons[t.state]} ${t.name}`);
|
|
124
|
+
return "\n\n---\n" + lines.join("\n");
|
|
125
|
+
}
|
|
126
|
+
buildButtonsText() {
|
|
127
|
+
if (this.subtaskButtons.length === 0) {
|
|
128
|
+
return "";
|
|
129
|
+
}
|
|
130
|
+
const lines = this.subtaskButtons.map((b) => `🔗 [${b.label}](${b.actionValue})`);
|
|
131
|
+
return "\n\n---\n" + lines.join("\n");
|
|
132
|
+
}
|
|
133
|
+
buildFullContent() {
|
|
134
|
+
const toolText = this.buildToolStatusText();
|
|
135
|
+
const buttonText = this.buildButtonsText();
|
|
136
|
+
return toolText + buttonText || "🛠️ Processing...";
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=streaming-card.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"streaming-card.js","sourceRoot":"","sources":["../../src/streaming/streaming-card.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sub-agent card handler for Feishu.
|
|
3
|
+
* Handles button clicks to view sub-agent session conversations.
|
|
4
|
+
* Formats messages and sends as interactive cards.
|
|
5
|
+
*/
|
|
6
|
+
import type { Logger } from "../utils/logger.js";
|
|
7
|
+
import type { FeishuApiClient } from "../feishu/api-client.js";
|
|
8
|
+
import type { FeishuCardAction } from "../types.js";
|
|
9
|
+
import type { SubAgentTracker, MessageSummary } from "./subagent-tracker.js";
|
|
10
|
+
export interface SubAgentCardDeps {
|
|
11
|
+
subAgentTracker: SubAgentTracker;
|
|
12
|
+
feishuClient: FeishuApiClient;
|
|
13
|
+
logger: Logger;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Creates a handler for sub-agent card button clicks.
|
|
17
|
+
* Fetches child session messages and sends as Feishu card.
|
|
18
|
+
*/
|
|
19
|
+
export declare function createSubAgentCardHandler(deps: SubAgentCardDeps): (action: FeishuCardAction) => Promise<void>;
|
|
20
|
+
/**
|
|
21
|
+
* Formats messages with role indicators and truncation.
|
|
22
|
+
* Role indicators: 👤 user / 🤖 assistant / 🛠 tool
|
|
23
|
+
* Truncates at 4000 chars with "...(内容过长,已截断)"
|
|
24
|
+
*/
|
|
25
|
+
export declare function formatSubAgentMessages(messages: MessageSummary[]): string;
|
|
26
|
+
/**
|
|
27
|
+
* Builds a Feishu card for sub-agent messages.
|
|
28
|
+
* Header: "🔍 子任务详情" with blue template
|
|
29
|
+
* Body: div with lark_md content
|
|
30
|
+
*/
|
|
31
|
+
export declare function buildSubAgentCard(description: string, content: string): Record<string, unknown>;
|
|
32
|
+
//# sourceMappingURL=subagent-card.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subagent-card.d.ts","sourceRoot":"","sources":["../../src/streaming/subagent-card.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAA;AAChD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AAC9D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AACnD,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAM5E,MAAM,WAAW,gBAAgB;IAC/B,eAAe,EAAE,eAAe,CAAA;IAChC,YAAY,EAAE,eAAe,CAAA;IAC7B,MAAM,EAAE,MAAM,CAAA;CACf;AAMD;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,gBAAgB,IAGhD,QAAQ,gBAAgB,KAAG,OAAO,CAAC,IAAI,CAAC,CAkCvD;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,cAAc,EAAE,GAAG,MAAM,CAkCzE;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,GACd,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAoBzB"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sub-agent card handler for Feishu.
|
|
3
|
+
* Handles button clicks to view sub-agent session conversations.
|
|
4
|
+
* Formats messages and sends as interactive cards.
|
|
5
|
+
*/
|
|
6
|
+
// ─────────────────────────────────────────────────────────
|
|
7
|
+
// Exports
|
|
8
|
+
// ─────────────────────────────────────────────────────────
|
|
9
|
+
/**
|
|
10
|
+
* Creates a handler for sub-agent card button clicks.
|
|
11
|
+
* Fetches child session messages and sends as Feishu card.
|
|
12
|
+
*/
|
|
13
|
+
export function createSubAgentCardHandler(deps) {
|
|
14
|
+
const { subAgentTracker, feishuClient, logger } = deps;
|
|
15
|
+
return async (action) => {
|
|
16
|
+
// Check action type early
|
|
17
|
+
const actionType = action.action?.value?.action;
|
|
18
|
+
if (actionType !== "view_subagent") {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
const childSessionId = action.action?.value?.childSessionId;
|
|
22
|
+
const messageId = action.open_message_id;
|
|
23
|
+
if (!childSessionId || !messageId) {
|
|
24
|
+
logger.warn("Missing childSessionId or messageId in subagent card action");
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
try {
|
|
28
|
+
// Fetch child messages
|
|
29
|
+
const messages = await subAgentTracker.getChildMessages(childSessionId, 50);
|
|
30
|
+
// Format messages for display
|
|
31
|
+
const content = formatSubAgentMessages(messages);
|
|
32
|
+
// Build and send card
|
|
33
|
+
const card = buildSubAgentCard("子任务进展", content);
|
|
34
|
+
await feishuClient.replyMessage(messageId, {
|
|
35
|
+
msg_type: "interactive",
|
|
36
|
+
content: JSON.stringify(card),
|
|
37
|
+
});
|
|
38
|
+
logger.info(`Sent subagent card for session ${childSessionId}`);
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
logger.error(`Failed to send subagent card: ${String(error)}`);
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Formats messages with role indicators and truncation.
|
|
47
|
+
* Role indicators: 👤 user / 🤖 assistant / 🛠 tool
|
|
48
|
+
* Truncates at 4000 chars with "...(内容过长,已截断)"
|
|
49
|
+
*/
|
|
50
|
+
export function formatSubAgentMessages(messages) {
|
|
51
|
+
if (messages.length === 0) {
|
|
52
|
+
return "暂无对话内容";
|
|
53
|
+
}
|
|
54
|
+
const roleIcons = {
|
|
55
|
+
user: "👤",
|
|
56
|
+
assistant: "🤖",
|
|
57
|
+
tool: "🛠",
|
|
58
|
+
};
|
|
59
|
+
const lines = [];
|
|
60
|
+
for (const msg of messages) {
|
|
61
|
+
const icon = roleIcons[msg.role] ?? "❓";
|
|
62
|
+
const roleLabel = msg.role.charAt(0).toUpperCase() + msg.role.slice(1);
|
|
63
|
+
lines.push(`${icon} **${roleLabel}**`);
|
|
64
|
+
lines.push(msg.text);
|
|
65
|
+
if (msg.toolCalls && msg.toolCalls.length > 0) {
|
|
66
|
+
lines.push(` _工具调用: ${msg.toolCalls.join(", ")}_`);
|
|
67
|
+
}
|
|
68
|
+
lines.push("");
|
|
69
|
+
}
|
|
70
|
+
let content = lines.join("\n");
|
|
71
|
+
// Truncate at 4000 chars
|
|
72
|
+
if (content.length > 4000) {
|
|
73
|
+
content = content.slice(0, 4000) + "\n\n...(内容过长,已截断)";
|
|
74
|
+
}
|
|
75
|
+
return content;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Builds a Feishu card for sub-agent messages.
|
|
79
|
+
* Header: "🔍 子任务详情" with blue template
|
|
80
|
+
* Body: div with lark_md content
|
|
81
|
+
*/
|
|
82
|
+
export function buildSubAgentCard(description, content) {
|
|
83
|
+
return {
|
|
84
|
+
config: { wide_screen_mode: true },
|
|
85
|
+
header: {
|
|
86
|
+
title: {
|
|
87
|
+
tag: "plain_text",
|
|
88
|
+
content: `🔍 ${description}`,
|
|
89
|
+
},
|
|
90
|
+
template: "blue",
|
|
91
|
+
},
|
|
92
|
+
elements: [
|
|
93
|
+
{
|
|
94
|
+
tag: "div",
|
|
95
|
+
text: {
|
|
96
|
+
tag: "lark_md",
|
|
97
|
+
content,
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
],
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=subagent-card.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subagent-card.js","sourceRoot":"","sources":["../../src/streaming/subagent-card.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { SubtaskDiscovered } from "./event-processor.js";
|
|
2
|
+
export interface TrackedSubAgent {
|
|
3
|
+
parentSessionId: string;
|
|
4
|
+
childSessionId?: string;
|
|
5
|
+
prompt: string;
|
|
6
|
+
description: string;
|
|
7
|
+
agent: string;
|
|
8
|
+
status: "discovering" | "active" | "completed" | "failed";
|
|
9
|
+
}
|
|
10
|
+
export interface MessageSummary {
|
|
11
|
+
role: string;
|
|
12
|
+
text: string;
|
|
13
|
+
toolCalls?: string[];
|
|
14
|
+
}
|
|
15
|
+
export interface SubAgentTrackerOptions {
|
|
16
|
+
serverUrl: string;
|
|
17
|
+
maxDepth?: number;
|
|
18
|
+
}
|
|
19
|
+
export declare class SubAgentTracker {
|
|
20
|
+
private readonly serverUrl;
|
|
21
|
+
private readonly maxDepth;
|
|
22
|
+
private readonly tracked;
|
|
23
|
+
constructor(options: SubAgentTrackerOptions);
|
|
24
|
+
/**
|
|
25
|
+
* Register a newly-discovered sub-agent and start polling for its child session.
|
|
26
|
+
* Returns the TrackedSubAgent immediately; status updates asynchronously.
|
|
27
|
+
*/
|
|
28
|
+
onSubtaskDiscovered(action: SubtaskDiscovered, depth?: number): Promise<TrackedSubAgent>;
|
|
29
|
+
/**
|
|
30
|
+
* Poll `GET /session/{parentSessionId}/children` to find the child session.
|
|
31
|
+
* Retries up to 5 times with exponential backoff: 500ms, 1s, 2s, 4s, 8s.
|
|
32
|
+
*/
|
|
33
|
+
pollChildSession(parentSessionId: string, retries?: number): Promise<string | null>;
|
|
34
|
+
/**
|
|
35
|
+
* Fetch messages from a child session.
|
|
36
|
+
* GET /session/{childSessionId}/message?limit=N
|
|
37
|
+
*/
|
|
38
|
+
getChildMessages(childSessionId: string, limit?: number): Promise<MessageSummary[]>;
|
|
39
|
+
/**
|
|
40
|
+
* Return all tracked sub-agents with current status.
|
|
41
|
+
*/
|
|
42
|
+
getTrackedSubAgents(): TrackedSubAgent[];
|
|
43
|
+
private sleep;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=subagent-tracker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subagent-tracker.d.ts","sourceRoot":"","sources":["../../src/streaming/subagent-tracker.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAA;AAM7D,MAAM,WAAW,eAAe;IAC9B,eAAe,EAAE,MAAM,CAAA;IACvB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,MAAM,EAAE,MAAM,CAAA;IACd,WAAW,EAAE,MAAM,CAAA;IACnB,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,aAAa,GAAG,QAAQ,GAAG,WAAW,GAAG,QAAQ,CAAA;CAC1D;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,CAAC,EAAE,MAAM,EAAE,CAAA;CACrB;AAED,MAAM,WAAW,sBAAsB;IACrC,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAaD,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAQ;IAClC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAQ;IACjC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAwB;gBAEpC,OAAO,EAAE,sBAAsB;IAK3C;;;OAGG;IACG,mBAAmB,CACvB,MAAM,EAAE,iBAAiB,EACzB,KAAK,GAAE,MAAU,GAChB,OAAO,CAAC,eAAe,CAAC;IAkC3B;;;OAGG;IACG,gBAAgB,CACpB,eAAe,EAAE,MAAM,EACvB,OAAO,GAAE,MAAoB,GAC5B,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IA8BzB;;;OAGG;IACG,gBAAgB,CACpB,cAAc,EAAE,MAAM,EACtB,KAAK,GAAE,MAAW,GACjB,OAAO,CAAC,cAAc,EAAE,CAAC;IA4B5B;;OAEG;IACH,mBAAmB,IAAI,eAAe,EAAE;IAQxC,OAAO,CAAC,KAAK;CAGd"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
// ═══════════════════════════════════════════
|
|
2
|
+
// Sub-Agent Tracker
|
|
3
|
+
// Tracks sub-agent lifecycle and fetches child session details via REST API polling.
|
|
4
|
+
// ═══════════════════════════════════════════
|
|
5
|
+
// ---------------------------------------------------------------------------
|
|
6
|
+
// Constants
|
|
7
|
+
// ---------------------------------------------------------------------------
|
|
8
|
+
const MAX_RETRIES = 5;
|
|
9
|
+
const BACKOFF_BASE_MS = 500;
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
// SubAgentTracker
|
|
12
|
+
// ---------------------------------------------------------------------------
|
|
13
|
+
export class SubAgentTracker {
|
|
14
|
+
serverUrl;
|
|
15
|
+
maxDepth;
|
|
16
|
+
tracked = [];
|
|
17
|
+
constructor(options) {
|
|
18
|
+
this.serverUrl = options.serverUrl;
|
|
19
|
+
this.maxDepth = Math.min(options.maxDepth ?? 1, 1);
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Register a newly-discovered sub-agent and start polling for its child session.
|
|
23
|
+
* Returns the TrackedSubAgent immediately; status updates asynchronously.
|
|
24
|
+
*/
|
|
25
|
+
async onSubtaskDiscovered(action, depth = 1) {
|
|
26
|
+
if (depth > this.maxDepth) {
|
|
27
|
+
throw new Error(`Max sub-agent depth is ${this.maxDepth}; requested depth ${depth}`);
|
|
28
|
+
}
|
|
29
|
+
const agent = {
|
|
30
|
+
parentSessionId: action.sessionId,
|
|
31
|
+
prompt: action.prompt,
|
|
32
|
+
description: action.description,
|
|
33
|
+
agent: action.agent,
|
|
34
|
+
status: "discovering",
|
|
35
|
+
};
|
|
36
|
+
this.tracked.push(agent);
|
|
37
|
+
// Fire-and-forget: poll for child session in background
|
|
38
|
+
this.pollChildSession(action.sessionId)
|
|
39
|
+
.then((childSessionId) => {
|
|
40
|
+
if (childSessionId) {
|
|
41
|
+
agent.childSessionId = childSessionId;
|
|
42
|
+
agent.status = "active";
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
agent.status = "failed";
|
|
46
|
+
}
|
|
47
|
+
})
|
|
48
|
+
.catch(() => {
|
|
49
|
+
agent.status = "failed";
|
|
50
|
+
});
|
|
51
|
+
return agent;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Poll `GET /session/{parentSessionId}/children` to find the child session.
|
|
55
|
+
* Retries up to 5 times with exponential backoff: 500ms, 1s, 2s, 4s, 8s.
|
|
56
|
+
*/
|
|
57
|
+
async pollChildSession(parentSessionId, retries = MAX_RETRIES) {
|
|
58
|
+
for (let attempt = 0; attempt < retries; attempt++) {
|
|
59
|
+
try {
|
|
60
|
+
const response = await fetch(`${this.serverUrl}/session/${parentSessionId}/children`);
|
|
61
|
+
if (response.ok) {
|
|
62
|
+
const children = (await response.json());
|
|
63
|
+
if (children.length > 0) {
|
|
64
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
65
|
+
return children[children.length - 1].id;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
// Network error — will retry
|
|
71
|
+
}
|
|
72
|
+
// Don't sleep after the last attempt
|
|
73
|
+
if (attempt < retries - 1) {
|
|
74
|
+
const delay = BACKOFF_BASE_MS * Math.pow(2, attempt);
|
|
75
|
+
await this.sleep(delay);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Fetch messages from a child session.
|
|
82
|
+
* GET /session/{childSessionId}/message?limit=N
|
|
83
|
+
*/
|
|
84
|
+
async getChildMessages(childSessionId, limit = 20) {
|
|
85
|
+
try {
|
|
86
|
+
const response = await fetch(`${this.serverUrl}/session/${childSessionId}/message?limit=${limit}`);
|
|
87
|
+
if (!response.ok)
|
|
88
|
+
return [];
|
|
89
|
+
const messages = (await response.json());
|
|
90
|
+
return messages.map((msg) => {
|
|
91
|
+
const summary = {
|
|
92
|
+
role: msg.role ?? "unknown",
|
|
93
|
+
text: msg.text ?? "",
|
|
94
|
+
};
|
|
95
|
+
if (msg.toolCalls && msg.toolCalls.length > 0) {
|
|
96
|
+
summary.toolCalls = msg.toolCalls.map((tc) => tc.name ?? "unknown");
|
|
97
|
+
}
|
|
98
|
+
return summary;
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
return [];
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Return all tracked sub-agents with current status.
|
|
107
|
+
*/
|
|
108
|
+
getTrackedSubAgents() {
|
|
109
|
+
return [...this.tracked];
|
|
110
|
+
}
|
|
111
|
+
// -------------------------------------------------------------------------
|
|
112
|
+
// Private helpers
|
|
113
|
+
// -------------------------------------------------------------------------
|
|
114
|
+
sleep(ms) {
|
|
115
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=subagent-tracker.js.map
|