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,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ChannelManager — manages registered channel plugins and their lifecycles.
|
|
3
|
+
* Provides register, startAll, stopAll, getChannel, listChannels.
|
|
4
|
+
*/
|
|
5
|
+
import type { ChannelPlugin, ChannelId } from "./types.js";
|
|
6
|
+
import type { Logger } from "../utils/logger.js";
|
|
7
|
+
export interface ChannelManagerOptions {
|
|
8
|
+
logger: Logger;
|
|
9
|
+
}
|
|
10
|
+
export declare class ChannelManager {
|
|
11
|
+
private readonly channels;
|
|
12
|
+
private readonly logger;
|
|
13
|
+
constructor(options: ChannelManagerOptions);
|
|
14
|
+
/**
|
|
15
|
+
* Register a channel plugin by its id.
|
|
16
|
+
*/
|
|
17
|
+
register(plugin: ChannelPlugin): void;
|
|
18
|
+
/**
|
|
19
|
+
* Start all registered channels that have a gateway adapter.
|
|
20
|
+
* Error isolation: one channel failing does not prevent others from starting.
|
|
21
|
+
*/
|
|
22
|
+
startAll(signal: AbortSignal): Promise<void>;
|
|
23
|
+
/**
|
|
24
|
+
* Stop all registered channels that have a gateway adapter.
|
|
25
|
+
* Error isolation: one channel failing does not prevent others from stopping.
|
|
26
|
+
*/
|
|
27
|
+
stopAll(): Promise<void>;
|
|
28
|
+
/**
|
|
29
|
+
* Get a channel plugin by id.
|
|
30
|
+
*/
|
|
31
|
+
getChannel(id: ChannelId): ChannelPlugin | undefined;
|
|
32
|
+
/**
|
|
33
|
+
* List all registered channel plugins.
|
|
34
|
+
*/
|
|
35
|
+
listChannels(): ChannelPlugin[];
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/channel/manager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAC1D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAA;AAEhD,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,MAAM,CAAA;CACf;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAsC;IAC/D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAQ;gBAEnB,OAAO,EAAE,qBAAqB;IAI1C;;OAEG;IACH,QAAQ,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI;IAKrC;;;OAGG;IACG,QAAQ,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAelD;;;OAGG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAc9B;;OAEG;IACH,UAAU,CAAC,EAAE,EAAE,SAAS,GAAG,aAAa,GAAG,SAAS;IAIpD;;OAEG;IACH,YAAY,IAAI,aAAa,EAAE;CAGhC"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ChannelManager — manages registered channel plugins and their lifecycles.
|
|
3
|
+
* Provides register, startAll, stopAll, getChannel, listChannels.
|
|
4
|
+
*/
|
|
5
|
+
export class ChannelManager {
|
|
6
|
+
channels = new Map();
|
|
7
|
+
logger;
|
|
8
|
+
constructor(options) {
|
|
9
|
+
this.logger = options.logger;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Register a channel plugin by its id.
|
|
13
|
+
*/
|
|
14
|
+
register(plugin) {
|
|
15
|
+
this.channels.set(plugin.id, plugin);
|
|
16
|
+
this.logger.info(`Channel registered: ${plugin.id}`);
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Start all registered channels that have a gateway adapter.
|
|
20
|
+
* Error isolation: one channel failing does not prevent others from starting.
|
|
21
|
+
*/
|
|
22
|
+
async startAll(signal) {
|
|
23
|
+
for (const plugin of this.channels.values()) {
|
|
24
|
+
if (!plugin.gateway) {
|
|
25
|
+
this.logger.info(`Channel ${plugin.id} has no gateway, skipping start`);
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
try {
|
|
29
|
+
await plugin.gateway.startAccount("default", signal);
|
|
30
|
+
this.logger.info(`Channel ${plugin.id} started`);
|
|
31
|
+
}
|
|
32
|
+
catch (err) {
|
|
33
|
+
this.logger.error(`Channel ${plugin.id} failed to start`, err);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Stop all registered channels that have a gateway adapter.
|
|
39
|
+
* Error isolation: one channel failing does not prevent others from stopping.
|
|
40
|
+
*/
|
|
41
|
+
async stopAll() {
|
|
42
|
+
for (const plugin of this.channels.values()) {
|
|
43
|
+
if (!plugin.gateway?.stopAccount) {
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
await plugin.gateway.stopAccount("default");
|
|
48
|
+
this.logger.info(`Channel ${plugin.id} stopped`);
|
|
49
|
+
}
|
|
50
|
+
catch (err) {
|
|
51
|
+
this.logger.error(`Channel ${plugin.id} failed to stop`, err);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Get a channel plugin by id.
|
|
57
|
+
*/
|
|
58
|
+
getChannel(id) {
|
|
59
|
+
return this.channels.get(id);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* List all registered channel plugins.
|
|
63
|
+
*/
|
|
64
|
+
listChannels() {
|
|
65
|
+
return [...this.channels.values()];
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manager.js","sourceRoot":"","sources":["../../src/channel/manager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AASH,MAAM,OAAO,cAAc;IACR,QAAQ,GAAG,IAAI,GAAG,EAA4B,CAAA;IAC9C,MAAM,CAAQ;IAE/B,YAAY,OAA8B;QACxC,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAA;IAC9B,CAAC;IAED;;OAEG;IACH,QAAQ,CAAC,MAAqB;QAC5B,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,CAAC,CAAA;QACpC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,uBAAuB,MAAM,CAAC,EAAE,EAAE,CAAC,CAAA;IACtD,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,QAAQ,CAAC,MAAmB;QAChC,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC;YAC5C,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;gBACpB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,MAAM,CAAC,EAAE,iCAAiC,CAAC,CAAA;gBACvE,SAAQ;YACV,CAAC;YACD,IAAI,CAAC;gBACH,MAAM,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,SAAS,EAAE,MAAM,CAAC,CAAA;gBACpD,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,MAAM,CAAC,EAAE,UAAU,CAAC,CAAA;YAClD,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,MAAM,CAAC,EAAE,kBAAkB,EAAE,GAAG,CAAC,CAAA;YAChE,CAAC;QACH,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,OAAO;QACX,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC;YAC5C,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,WAAW,EAAE,CAAC;gBACjC,SAAQ;YACV,CAAC;YACD,IAAI,CAAC;gBACH,MAAM,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,SAAS,CAAC,CAAA;gBAC3C,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,MAAM,CAAC,EAAE,UAAU,CAAC,CAAA;YAClD,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,MAAM,CAAC,EAAE,iBAAiB,EAAE,GAAG,CAAC,CAAA;YAC/D,CAAC;QACH,CAAC;IACH,CAAC;IAED;;OAEG;IACH,UAAU,CAAC,EAAa;QACtB,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;IAC9B,CAAC;IAED;;OAEG;IACH,YAAY;QACV,OAAO,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAA;IACpC,CAAC;CACF"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MockPlugin — minimal channel plugin for testing the ChannelPlugin abstraction.
|
|
3
|
+
* Uses an in-memory message queue to record sent messages.
|
|
4
|
+
* NOT for production use.
|
|
5
|
+
*/
|
|
6
|
+
import { BaseChannelPlugin } from "../base-plugin.js";
|
|
7
|
+
import type { ChannelId, ChannelMeta, ChannelConfigAdapter, ChannelGatewayAdapter, ChannelOutboundAdapter, OutboundTarget } from "../types.js";
|
|
8
|
+
export interface MockSentMessage {
|
|
9
|
+
target: OutboundTarget;
|
|
10
|
+
text: string;
|
|
11
|
+
}
|
|
12
|
+
export declare class MockPlugin extends BaseChannelPlugin {
|
|
13
|
+
id: ChannelId;
|
|
14
|
+
meta: ChannelMeta;
|
|
15
|
+
/** Public record of all messages sent through outbound */
|
|
16
|
+
readonly sentMessages: MockSentMessage[];
|
|
17
|
+
/** Track gateway startAccount calls */
|
|
18
|
+
readonly startedAccounts: string[];
|
|
19
|
+
config: ChannelConfigAdapter;
|
|
20
|
+
gateway: ChannelGatewayAdapter;
|
|
21
|
+
outbound: ChannelOutboundAdapter;
|
|
22
|
+
constructor();
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=mock-plugin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mock-plugin.d.ts","sourceRoot":"","sources":["../../../src/channel/mock/mock-plugin.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AACrD,OAAO,KAAK,EACV,SAAS,EACT,WAAW,EACX,oBAAoB,EACpB,qBAAqB,EACrB,sBAAsB,EACtB,cAAc,EACf,MAAM,aAAa,CAAA;AAEpB,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,cAAc,CAAA;IACtB,IAAI,EAAE,MAAM,CAAA;CACb;AAED,qBAAa,UAAW,SAAQ,iBAAiB;IACtC,EAAE,EAAa,SAAS,CAAA;IACxB,IAAI,EAAE,WAAW,CAIzB;IAED,0DAA0D;IAC1D,QAAQ,CAAC,YAAY,EAAE,eAAe,EAAE,CAAK;IAE7C,uCAAuC;IACvC,QAAQ,CAAC,eAAe,EAAE,MAAM,EAAE,CAAK;IAE9B,MAAM,EAAE,oBAAoB,CAAA;IAC5B,OAAO,EAAE,qBAAqB,CAAA;IAC9B,QAAQ,EAAE,sBAAsB,CAAA;;CAyB1C"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MockPlugin — minimal channel plugin for testing the ChannelPlugin abstraction.
|
|
3
|
+
* Uses an in-memory message queue to record sent messages.
|
|
4
|
+
* NOT for production use.
|
|
5
|
+
*/
|
|
6
|
+
import { BaseChannelPlugin } from "../base-plugin.js";
|
|
7
|
+
export class MockPlugin extends BaseChannelPlugin {
|
|
8
|
+
id = "mock";
|
|
9
|
+
meta = {
|
|
10
|
+
id: "mock",
|
|
11
|
+
label: "Mock Channel",
|
|
12
|
+
description: "In-memory mock channel for testing",
|
|
13
|
+
};
|
|
14
|
+
/** Public record of all messages sent through outbound */
|
|
15
|
+
sentMessages = [];
|
|
16
|
+
/** Track gateway startAccount calls */
|
|
17
|
+
startedAccounts = [];
|
|
18
|
+
config;
|
|
19
|
+
gateway;
|
|
20
|
+
outbound;
|
|
21
|
+
constructor() {
|
|
22
|
+
super();
|
|
23
|
+
this.config = {
|
|
24
|
+
listAccountIds: () => ["test-acct"],
|
|
25
|
+
resolveAccount: (id) => ({ id, type: "mock" }),
|
|
26
|
+
};
|
|
27
|
+
this.gateway = {
|
|
28
|
+
startAccount: async (accountId, _signal) => {
|
|
29
|
+
this.startedAccounts.push(accountId);
|
|
30
|
+
},
|
|
31
|
+
stopAccount: async (accountId) => {
|
|
32
|
+
// no-op for mock
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
this.outbound = {
|
|
36
|
+
sendText: async (target, text) => {
|
|
37
|
+
this.sentMessages.push({ target, text });
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=mock-plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mock-plugin.js","sourceRoot":"","sources":["../../../src/channel/mock/mock-plugin.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAerD,MAAM,OAAO,UAAW,SAAQ,iBAAiB;IACtC,EAAE,GAAG,MAAmB,CAAA;IACxB,IAAI,GAAgB;QAC3B,EAAE,EAAE,MAAmB;QACvB,KAAK,EAAE,cAAc;QACrB,WAAW,EAAE,oCAAoC;KAClD,CAAA;IAED,0DAA0D;IACjD,YAAY,GAAsB,EAAE,CAAA;IAE7C,uCAAuC;IAC9B,eAAe,GAAa,EAAE,CAAA;IAE9B,MAAM,CAAsB;IAC5B,OAAO,CAAuB;IAC9B,QAAQ,CAAwB;IAEzC;QACE,KAAK,EAAE,CAAA;QAEP,IAAI,CAAC,MAAM,GAAG;YACZ,cAAc,EAAE,GAAG,EAAE,CAAC,CAAC,WAAW,CAAC;YACnC,cAAc,EAAE,CAAC,EAAU,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;SACvD,CAAA;QAED,IAAI,CAAC,OAAO,GAAG;YACb,YAAY,EAAE,KAAK,EAAE,SAAiB,EAAE,OAAoB,EAAiB,EAAE;gBAC7E,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;YACtC,CAAC;YACD,WAAW,EAAE,KAAK,EAAE,SAAiB,EAAiB,EAAE;gBACtD,iBAAiB;YACnB,CAAC;SACF,CAAA;QAED,IAAI,CAAC,QAAQ,GAAG;YACd,QAAQ,EAAE,KAAK,EAAE,MAAsB,EAAE,IAAY,EAAiB,EAAE;gBACtE,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAA;YAC1C,CAAC;SACF,CAAA;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ChannelPlugin type definitions for opencode-lark
|
|
3
|
+
* Defines the core plugin contract for channel integrations.
|
|
4
|
+
* Inspired by openclaw but independently defined.
|
|
5
|
+
*/
|
|
6
|
+
/** Unique identifier for a channel provider (e.g., "feishu", "slack", "discord") */
|
|
7
|
+
export type ChannelId = string & {
|
|
8
|
+
readonly __brand: "ChannelId";
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Metadata describing a channel plugin
|
|
12
|
+
*/
|
|
13
|
+
export interface ChannelMeta {
|
|
14
|
+
/** Unique channel identifier */
|
|
15
|
+
id: ChannelId;
|
|
16
|
+
/** Human-readable label (e.g., "Feishu") */
|
|
17
|
+
label: string;
|
|
18
|
+
/** Long-form description of the channel */
|
|
19
|
+
description: string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Normalized representation of an inbound message from a channel
|
|
23
|
+
*/
|
|
24
|
+
export interface NormalizedMessage {
|
|
25
|
+
/** Unique message ID in the channel */
|
|
26
|
+
messageId: string;
|
|
27
|
+
/** Sender's unique identifier */
|
|
28
|
+
senderId: string;
|
|
29
|
+
/** Human-readable sender name */
|
|
30
|
+
senderName?: string;
|
|
31
|
+
/** Message text content */
|
|
32
|
+
text: string;
|
|
33
|
+
/** Chat/thread/group identifier */
|
|
34
|
+
chatId: string;
|
|
35
|
+
/** Optional: unique identifier for a thread this message belongs to */
|
|
36
|
+
threadId?: string;
|
|
37
|
+
/** Unix timestamp when message was sent */
|
|
38
|
+
timestamp: number;
|
|
39
|
+
/** Optional: ID of a message this one replies to */
|
|
40
|
+
replyToId?: string;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Message prepared for sending to a channel
|
|
44
|
+
*/
|
|
45
|
+
export interface OutboundMessage {
|
|
46
|
+
/** Target recipient/channel ID */
|
|
47
|
+
target: string;
|
|
48
|
+
/** Message text content */
|
|
49
|
+
text: string;
|
|
50
|
+
/** Optional: formatted card/rich content (channel-specific format) */
|
|
51
|
+
card?: unknown;
|
|
52
|
+
/** Optional: reply-to message ID */
|
|
53
|
+
replyToId?: string;
|
|
54
|
+
/** Optional: thread ID for threaded channels */
|
|
55
|
+
threadId?: string;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Destination specification for an outbound message
|
|
59
|
+
*/
|
|
60
|
+
export interface OutboundTarget {
|
|
61
|
+
/** Target address (user ID, channel ID, etc.) */
|
|
62
|
+
address: string;
|
|
63
|
+
/** Optional: channel/group ID if different from address */
|
|
64
|
+
channelId?: string;
|
|
65
|
+
/** Optional: thread ID for threaded messaging */
|
|
66
|
+
threadId?: string;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Destination for streaming operations
|
|
70
|
+
*/
|
|
71
|
+
export interface StreamTarget {
|
|
72
|
+
/** Target address for streaming updates */
|
|
73
|
+
address: string;
|
|
74
|
+
/** Optional: context metadata */
|
|
75
|
+
context?: Record<string, unknown>;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Active streaming session for coalesced updates
|
|
79
|
+
*/
|
|
80
|
+
export interface StreamingSession {
|
|
81
|
+
/** Unique session identifier */
|
|
82
|
+
sessionId: string;
|
|
83
|
+
/** Target for this streaming session */
|
|
84
|
+
target: StreamTarget;
|
|
85
|
+
/** Accumulated updates pending send */
|
|
86
|
+
pendingUpdates: string[];
|
|
87
|
+
/** Timestamp when session was created */
|
|
88
|
+
createdAt: number;
|
|
89
|
+
/** Function to flush accumulated updates */
|
|
90
|
+
flush: () => Promise<void>;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Key identifying a thread for message threading operations
|
|
94
|
+
*/
|
|
95
|
+
export type ThreadKey = string & {
|
|
96
|
+
readonly __brand: "ThreadKey";
|
|
97
|
+
};
|
|
98
|
+
/**
|
|
99
|
+
* Adapter for configuring channel accounts and resolving credentials
|
|
100
|
+
*/
|
|
101
|
+
export interface ChannelConfigAdapter {
|
|
102
|
+
/**
|
|
103
|
+
* List all configured account IDs for this channel
|
|
104
|
+
*/
|
|
105
|
+
listAccountIds(): string[];
|
|
106
|
+
/**
|
|
107
|
+
* Resolve a channel account to its full configuration/credentials
|
|
108
|
+
* @param id Account ID to resolve
|
|
109
|
+
* @returns Resolved account object (channel-specific structure)
|
|
110
|
+
*/
|
|
111
|
+
resolveAccount(id: string): unknown;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Adapter for channel gateway connection lifecycle
|
|
115
|
+
*/
|
|
116
|
+
export interface ChannelGatewayAdapter {
|
|
117
|
+
/**
|
|
118
|
+
* Start a channel account connection
|
|
119
|
+
* @param accountId Account ID to start
|
|
120
|
+
* @param signal Abort signal to stop the operation
|
|
121
|
+
*/
|
|
122
|
+
startAccount(accountId: string, signal: AbortSignal): Promise<void>;
|
|
123
|
+
/**
|
|
124
|
+
* Optional: Stop a channel account connection
|
|
125
|
+
* @param accountId Account ID to stop
|
|
126
|
+
*/
|
|
127
|
+
stopAccount?(accountId: string): Promise<void>;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Adapter for message normalization and formatting between inbound/outbound
|
|
131
|
+
*/
|
|
132
|
+
export interface ChannelMessagingAdapter {
|
|
133
|
+
/**
|
|
134
|
+
* Normalize a raw channel message to standard format
|
|
135
|
+
* @param raw Raw message object from channel provider
|
|
136
|
+
* @returns Normalized message
|
|
137
|
+
*/
|
|
138
|
+
normalizeInbound(raw: unknown): NormalizedMessage;
|
|
139
|
+
/**
|
|
140
|
+
* Format an outbound message to channel-specific format
|
|
141
|
+
* @param msg Message to format
|
|
142
|
+
* @returns Channel-specific message object
|
|
143
|
+
*/
|
|
144
|
+
formatOutbound(msg: OutboundMessage): unknown;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Adapter for sending messages to a channel
|
|
148
|
+
*/
|
|
149
|
+
export interface ChannelOutboundAdapter {
|
|
150
|
+
/**
|
|
151
|
+
* Send text message to a target
|
|
152
|
+
* @param target Destination specification
|
|
153
|
+
* @param text Message text to send
|
|
154
|
+
*/
|
|
155
|
+
sendText(target: OutboundTarget, text: string): Promise<void>;
|
|
156
|
+
/**
|
|
157
|
+
* Optional: Send rich card/formatted message
|
|
158
|
+
* @param target Destination specification
|
|
159
|
+
* @param card Card object (channel-specific format)
|
|
160
|
+
*/
|
|
161
|
+
sendCard?(target: OutboundTarget, card: unknown): Promise<void>;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Adapter for streaming message updates with optional coalescing
|
|
165
|
+
*/
|
|
166
|
+
export interface ChannelStreamingAdapter {
|
|
167
|
+
/**
|
|
168
|
+
* Create a new streaming session for a target
|
|
169
|
+
* @param target Target to stream to
|
|
170
|
+
* @returns Active streaming session
|
|
171
|
+
*/
|
|
172
|
+
createStreamingSession(target: StreamTarget): StreamingSession;
|
|
173
|
+
/**
|
|
174
|
+
* Optional: Coalesce multiple updates into a single message
|
|
175
|
+
* @param updates Array of update strings
|
|
176
|
+
* @param intervalMs Time window for coalescing
|
|
177
|
+
* @returns Coalesced update string
|
|
178
|
+
*/
|
|
179
|
+
coalesceUpdates?(updates: string[], intervalMs: number): string;
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Adapter for thread/conversation tracking
|
|
183
|
+
*/
|
|
184
|
+
export interface ChannelThreadingAdapter {
|
|
185
|
+
/**
|
|
186
|
+
* Resolve a thread key from an inbound message
|
|
187
|
+
* @param inbound Normalized inbound message
|
|
188
|
+
* @returns Unique thread key
|
|
189
|
+
*/
|
|
190
|
+
resolveThread(inbound: NormalizedMessage): ThreadKey;
|
|
191
|
+
/**
|
|
192
|
+
* Map a thread key to a session ID
|
|
193
|
+
* @param threadKey Thread key to map
|
|
194
|
+
* @param sessionId Agent session ID
|
|
195
|
+
*/
|
|
196
|
+
mapSession(threadKey: ThreadKey, sessionId: string): void;
|
|
197
|
+
/**
|
|
198
|
+
* Get the session ID for a thread
|
|
199
|
+
* @param threadKey Thread key to look up
|
|
200
|
+
* @returns Session ID if mapped, null otherwise
|
|
201
|
+
*/
|
|
202
|
+
getSession(threadKey: ThreadKey): string | null;
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Main ChannelPlugin contract
|
|
206
|
+
* Defines required and optional adapters for a channel integration
|
|
207
|
+
*/
|
|
208
|
+
export interface ChannelPlugin {
|
|
209
|
+
/** Unique channel identifier */
|
|
210
|
+
id: ChannelId;
|
|
211
|
+
/** Channel metadata */
|
|
212
|
+
meta: ChannelMeta;
|
|
213
|
+
/** Configuration adapter (REQUIRED) */
|
|
214
|
+
config: ChannelConfigAdapter;
|
|
215
|
+
/** Gateway adapter for connection lifecycle (OPTIONAL) */
|
|
216
|
+
gateway?: ChannelGatewayAdapter;
|
|
217
|
+
/** Message normalization and formatting (OPTIONAL) */
|
|
218
|
+
messaging?: ChannelMessagingAdapter;
|
|
219
|
+
/** Outbound message sending (OPTIONAL) */
|
|
220
|
+
outbound?: ChannelOutboundAdapter;
|
|
221
|
+
/** Streaming update delivery (OPTIONAL) */
|
|
222
|
+
streaming?: ChannelStreamingAdapter;
|
|
223
|
+
/** Thread/conversation tracking (OPTIONAL) */
|
|
224
|
+
threading?: ChannelThreadingAdapter;
|
|
225
|
+
}
|
|
226
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/channel/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/channel/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { CronConfig } from "../utils/config.js";
|
|
2
|
+
import type { SessionManager } from "../session/session-manager.js";
|
|
3
|
+
import type { FeishuApiClient } from "../feishu/api-client.js";
|
|
4
|
+
import type { Logger } from "../utils/logger.js";
|
|
5
|
+
export interface CronServiceOptions {
|
|
6
|
+
config: CronConfig;
|
|
7
|
+
sessionManager: SessionManager;
|
|
8
|
+
feishuClient: FeishuApiClient;
|
|
9
|
+
serverUrl: string;
|
|
10
|
+
logger: Logger;
|
|
11
|
+
}
|
|
12
|
+
interface ParsedSchedule {
|
|
13
|
+
type: "interval" | "daily";
|
|
14
|
+
intervalMs?: number;
|
|
15
|
+
hour?: number;
|
|
16
|
+
minute?: number;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Supported formats:
|
|
20
|
+
* "every Nm" → interval of N minutes
|
|
21
|
+
* "every Nh" → interval of N hours
|
|
22
|
+
* "daily HH:MM" → execute once per day at HH:MM
|
|
23
|
+
*
|
|
24
|
+
* @throws Error on invalid format
|
|
25
|
+
*/
|
|
26
|
+
export declare function parseSchedule(schedule: string): ParsedSchedule;
|
|
27
|
+
export declare class CronService {
|
|
28
|
+
private readonly options;
|
|
29
|
+
private readonly intervals;
|
|
30
|
+
private running;
|
|
31
|
+
private lastDailyRun;
|
|
32
|
+
constructor(options: CronServiceOptions);
|
|
33
|
+
/** @throws Error if any job has an invalid schedule */
|
|
34
|
+
start(): void;
|
|
35
|
+
stop(): void;
|
|
36
|
+
private executeJob;
|
|
37
|
+
private waitForResponse;
|
|
38
|
+
}
|
|
39
|
+
export {};
|
|
40
|
+
//# sourceMappingURL=cron-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cron-service.d.ts","sourceRoot":"","sources":["../../src/cron/cron-service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAiB,MAAM,oBAAoB,CAAA;AACnE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAA;AACnE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AAC9D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAA;AAEhD,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,UAAU,CAAA;IAClB,cAAc,EAAE,cAAc,CAAA;IAC9B,YAAY,EAAE,eAAe,CAAA;IAC7B,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,MAAM,CAAA;CACf;AAED,UAAU,cAAc;IACtB,IAAI,EAAE,UAAU,GAAG,OAAO,CAAA;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,cAAc,CA6B9D;AAED,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAoB;IAC5C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAuC;IACjE,OAAO,CAAC,OAAO,CAAQ;IACvB,OAAO,CAAC,YAAY,CAA4B;gBAEpC,OAAO,EAAE,kBAAkB;IAIvC,uDAAuD;IACvD,KAAK,IAAI,IAAI;IAsCb,IAAI,IAAI,IAAI;YAYE,UAAU;YAmCV,eAAe;CAyB9B"}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Supported formats:
|
|
3
|
+
* "every Nm" → interval of N minutes
|
|
4
|
+
* "every Nh" → interval of N hours
|
|
5
|
+
* "daily HH:MM" → execute once per day at HH:MM
|
|
6
|
+
*
|
|
7
|
+
* @throws Error on invalid format
|
|
8
|
+
*/
|
|
9
|
+
export function parseSchedule(schedule) {
|
|
10
|
+
const trimmed = schedule.trim();
|
|
11
|
+
// "every Nm" or "every Nh" → regex: digit(s) + unit letter
|
|
12
|
+
const intervalMatch = trimmed.match(/^every\s+(\d+)\s*([mh])$/i);
|
|
13
|
+
if (intervalMatch) {
|
|
14
|
+
const value = Number(intervalMatch[1]);
|
|
15
|
+
const unit = intervalMatch[2].toLowerCase();
|
|
16
|
+
if (value <= 0) {
|
|
17
|
+
throw new Error(`Invalid schedule "${schedule}": interval must be positive`);
|
|
18
|
+
}
|
|
19
|
+
const multiplier = unit === "m" ? 60_000 : 3_600_000;
|
|
20
|
+
return { type: "interval", intervalMs: value * multiplier };
|
|
21
|
+
}
|
|
22
|
+
// "daily HH:MM" → regex: 1-2 digit hour + 2 digit minute
|
|
23
|
+
const dailyMatch = trimmed.match(/^daily\s+(\d{1,2}):(\d{2})$/i);
|
|
24
|
+
if (dailyMatch) {
|
|
25
|
+
const hour = Number(dailyMatch[1]);
|
|
26
|
+
const minute = Number(dailyMatch[2]);
|
|
27
|
+
if (hour < 0 || hour > 23 || minute < 0 || minute > 59) {
|
|
28
|
+
throw new Error(`Invalid schedule "${schedule}": invalid time (expected HH:MM with 0-23:0-59)`);
|
|
29
|
+
}
|
|
30
|
+
return { type: "daily", hour, minute };
|
|
31
|
+
}
|
|
32
|
+
throw new Error(`Invalid schedule format "${schedule}". Supported: "every Nm", "every Nh", "daily HH:MM"`);
|
|
33
|
+
}
|
|
34
|
+
export class CronService {
|
|
35
|
+
options;
|
|
36
|
+
intervals = [];
|
|
37
|
+
running = false;
|
|
38
|
+
lastDailyRun = new Map();
|
|
39
|
+
constructor(options) {
|
|
40
|
+
this.options = options;
|
|
41
|
+
}
|
|
42
|
+
/** @throws Error if any job has an invalid schedule */
|
|
43
|
+
start() {
|
|
44
|
+
if (this.running)
|
|
45
|
+
return;
|
|
46
|
+
const { config, logger } = this.options;
|
|
47
|
+
const jobs = config.jobs;
|
|
48
|
+
const parsed = jobs.map((job) => ({
|
|
49
|
+
job,
|
|
50
|
+
schedule: parseSchedule(job.schedule),
|
|
51
|
+
}));
|
|
52
|
+
for (const { job, schedule } of parsed) {
|
|
53
|
+
if (schedule.type === "interval") {
|
|
54
|
+
logger.info(`Cron job "${job.name}": every ${schedule.intervalMs}ms`);
|
|
55
|
+
const id = setInterval(() => {
|
|
56
|
+
void this.executeJob(job);
|
|
57
|
+
}, schedule.intervalMs);
|
|
58
|
+
this.intervals.push(id);
|
|
59
|
+
}
|
|
60
|
+
else if (schedule.type === "daily") {
|
|
61
|
+
logger.info(`Cron job "${job.name}": daily at ${String(schedule.hour).padStart(2, "0")}:${String(schedule.minute).padStart(2, "0")}`);
|
|
62
|
+
const id = setInterval(() => {
|
|
63
|
+
const now = new Date();
|
|
64
|
+
if (now.getHours() === schedule.hour && now.getMinutes() === schedule.minute) {
|
|
65
|
+
const dateKey = `${job.name}:${now.toISOString().slice(0, 10)}`;
|
|
66
|
+
if (!this.lastDailyRun.has(dateKey)) {
|
|
67
|
+
this.lastDailyRun.set(dateKey, now.toISOString());
|
|
68
|
+
void this.executeJob(job);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}, 60_000);
|
|
72
|
+
this.intervals.push(id);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
this.running = true;
|
|
76
|
+
logger.info(`Cron service started with ${jobs.length} job(s)`);
|
|
77
|
+
}
|
|
78
|
+
stop() {
|
|
79
|
+
if (!this.running)
|
|
80
|
+
return;
|
|
81
|
+
for (const id of this.intervals) {
|
|
82
|
+
clearInterval(id);
|
|
83
|
+
}
|
|
84
|
+
this.intervals.length = 0;
|
|
85
|
+
this.lastDailyRun.clear();
|
|
86
|
+
this.running = false;
|
|
87
|
+
this.options.logger.info("Cron service stopped");
|
|
88
|
+
}
|
|
89
|
+
async executeJob(job) {
|
|
90
|
+
const { sessionManager, feishuClient, serverUrl, logger } = this.options;
|
|
91
|
+
const cronKey = `cron:${job.name}`;
|
|
92
|
+
try {
|
|
93
|
+
logger.info(`Executing cron job "${job.name}"...`);
|
|
94
|
+
const sessionId = await sessionManager.getOrCreate(cronKey);
|
|
95
|
+
const resp = await fetch(`${serverUrl}/session/${sessionId}/message`, {
|
|
96
|
+
method: "POST",
|
|
97
|
+
headers: { "Content-Type": "application/json" },
|
|
98
|
+
body: JSON.stringify({
|
|
99
|
+
parts: [{ type: "text", text: job.prompt }],
|
|
100
|
+
}),
|
|
101
|
+
});
|
|
102
|
+
if (!resp.ok) {
|
|
103
|
+
logger.error(`Cron job "${job.name}": POST failed with HTTP ${resp.status}`);
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
const result = await this.waitForResponse(sessionId);
|
|
107
|
+
await feishuClient.sendMessage(job.chatId, {
|
|
108
|
+
msg_type: "text",
|
|
109
|
+
content: JSON.stringify({ text: result }),
|
|
110
|
+
});
|
|
111
|
+
logger.info(`Cron job "${job.name}" completed`);
|
|
112
|
+
}
|
|
113
|
+
catch (err) {
|
|
114
|
+
logger.error(`Cron job "${job.name}" failed:`, err);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
async waitForResponse(sessionId, maxWaitMs = 300_000) {
|
|
118
|
+
const { serverUrl } = this.options;
|
|
119
|
+
const start = Date.now();
|
|
120
|
+
const pollInterval = 2_000;
|
|
121
|
+
while (Date.now() - start < maxWaitMs) {
|
|
122
|
+
await new Promise((r) => setTimeout(r, pollInterval));
|
|
123
|
+
const statusResp = await fetch(`${serverUrl}/session/${sessionId}`);
|
|
124
|
+
if (!statusResp.ok)
|
|
125
|
+
continue;
|
|
126
|
+
const session = (await statusResp.json());
|
|
127
|
+
if (session.status?.type === "idle") {
|
|
128
|
+
const msgResp = await fetch(`${serverUrl}/session/${sessionId}/message?limit=1`);
|
|
129
|
+
if (msgResp.ok) {
|
|
130
|
+
const messages = (await msgResp.json());
|
|
131
|
+
const last = messages.find((m) => m.role === "assistant");
|
|
132
|
+
return last?.text ?? "(no response)";
|
|
133
|
+
}
|
|
134
|
+
return "(failed to retrieve response)";
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return "(timed out waiting for response)";
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
//# sourceMappingURL=cron-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cron-service.js","sourceRoot":"","sources":["../../src/cron/cron-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { Logger } from "../utils/logger.js";
|
|
2
|
+
import type { FeishuApiClient } from "../feishu/api-client.js";
|
|
3
|
+
export interface HeartbeatOptions {
|
|
4
|
+
intervalMs: number;
|
|
5
|
+
serverUrl: string;
|
|
6
|
+
feishuClient?: FeishuApiClient;
|
|
7
|
+
statusChatId?: string;
|
|
8
|
+
logger: Logger;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Periodic health check service.
|
|
12
|
+
* Pings server at intervals and reports status via Feishu on failure.
|
|
13
|
+
*/
|
|
14
|
+
export declare class HeartbeatService {
|
|
15
|
+
private readonly options;
|
|
16
|
+
private intervalId;
|
|
17
|
+
private running;
|
|
18
|
+
private successCount;
|
|
19
|
+
private failCount;
|
|
20
|
+
constructor(options: HeartbeatOptions);
|
|
21
|
+
start(): void;
|
|
22
|
+
stop(): void;
|
|
23
|
+
private tick;
|
|
24
|
+
private sendAlert;
|
|
25
|
+
getStats(): {
|
|
26
|
+
successCount: number;
|
|
27
|
+
failCount: number;
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=heartbeat.d.ts.map
|