@zhin.js/service-activity-feedback 1.0.1 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -6
- package/lib/ai-event-binder.d.ts +15 -1
- package/lib/ai-event-binder.d.ts.map +1 -1
- package/lib/ai-event-binder.js +24 -5
- package/lib/ai-event-binder.js.map +1 -1
- package/lib/executor.d.ts +14 -0
- package/lib/executor.d.ts.map +1 -1
- package/lib/executor.js +116 -0
- package/lib/executor.js.map +1 -1
- package/lib/index.d.ts +7 -3
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +4 -16
- package/lib/index.js.map +1 -1
- package/package.json +29 -8
- package/plugin.ts +51 -0
- package/schema.json +12 -0
- package/src/ai-event-binder.ts +52 -7
- package/src/executor.ts +132 -0
- package/src/index.ts +10 -24
- package/plugin.yml +0 -2
package/README.md
CHANGED
|
@@ -5,18 +5,24 @@
|
|
|
5
5
|
## 模块结构
|
|
6
6
|
|
|
7
7
|
```
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
8
|
+
ZhinAgentEventEmitter.emit
|
|
9
|
+
│
|
|
10
|
+
▼
|
|
11
|
+
activityFeedbackAiBus ──► ai-event-binder(薄) ──► ActivityFeedbackOrchestrator
|
|
12
|
+
│
|
|
13
|
+
┌────────────────────┼────────────────────┐
|
|
14
|
+
▼ ▼ ▼
|
|
15
|
+
context.ts policy.ts executor.ts
|
|
16
|
+
payload → 上下文 根级 YAML → phase 配置 platform/generic 统一执行
|
|
14
17
|
```
|
|
15
18
|
|
|
16
19
|
- **Orchestrator**:对外 `startPhase` / `stopPhase` / `updateThinkingText`
|
|
17
20
|
- **Policy**:根级 `activityFeedback` 合并与 phase 解析
|
|
18
21
|
- **Executor**:隐藏 platform 自管 manager 与 generic manager 双路径
|
|
19
22
|
- **Adapter**:仅提供 `$activityFeedback` IO 能力
|
|
23
|
+
- **Runtime slice-2**:`plugin.ts` setup 经 `activityFeedbackAiBus` 订阅(无 `usePlugin`);
|
|
24
|
+
endpoint access 暂为 noop(phase 在 resolve 失败时静默跳过)。
|
|
25
|
+
**TODO**:注入真实 Adapter/endpoint access,使 typing/reaction 真正出站。
|
|
20
26
|
|
|
21
27
|
## 安装
|
|
22
28
|
|
package/lib/ai-event-binder.d.ts
CHANGED
|
@@ -1,14 +1,28 @@
|
|
|
1
1
|
import type { Plugin } from 'zhin.js';
|
|
2
|
+
import { type AIEventHandlers } from '@zhin.js/agent';
|
|
2
3
|
import { type ActivityFeedbackServiceConfig } from './config.js';
|
|
3
4
|
import { type ActivityFeedbackEndpointAccess } from './executor.js';
|
|
4
5
|
import { ActivityFeedbackOrchestrator } from './orchestrator.js';
|
|
6
|
+
export declare function createActivityFeedbackAIEventHandlers(orchestrator: ActivityFeedbackOrchestrator): AIEventHandlers;
|
|
7
|
+
/** Legacy host Plugin path (ALS-aware subscribeAIEvents). */
|
|
5
8
|
export declare function bindActivityFeedbackToAIEvents(root: Plugin['root'], orchestrator: ActivityFeedbackOrchestrator): () => void;
|
|
9
|
+
/**
|
|
10
|
+
* Plugin Runtime path: subscribe on module-level `activityFeedbackAiBus`
|
|
11
|
+
* (fed by ZhinAgentEventEmitter.emit). No usePlugin / Adapter inject.
|
|
12
|
+
*/
|
|
13
|
+
export declare function bindActivityFeedbackToAIEventBus(orchestrator: ActivityFeedbackOrchestrator): () => void;
|
|
6
14
|
export declare function mountActivityFeedbackService(plugin: Plugin, orchestrator: ActivityFeedbackOrchestrator): void;
|
|
15
|
+
export type ActivityFeedbackLogger = {
|
|
16
|
+
debug: (msg: string, ...args: unknown[]) => void;
|
|
17
|
+
error: (msg: string, ...args: unknown[]) => void;
|
|
18
|
+
};
|
|
7
19
|
export interface CreateActivityFeedbackOrchestratorOptions {
|
|
8
20
|
serviceConfig: ActivityFeedbackServiceConfig;
|
|
9
21
|
access: ActivityFeedbackEndpointAccess;
|
|
10
|
-
logger:
|
|
22
|
+
logger: ActivityFeedbackLogger;
|
|
11
23
|
}
|
|
12
24
|
export declare function createActivityFeedbackOrchestrator(options: CreateActivityFeedbackOrchestratorOptions): ActivityFeedbackOrchestrator;
|
|
13
25
|
export declare function createActivityFeedbackOrchestratorFromPlugin(plugin: Plugin, serviceConfig: ActivityFeedbackServiceConfig): ActivityFeedbackOrchestrator;
|
|
26
|
+
/** Runtime: prefer OutboundHost-backed access; else noop until Host wires outbound. */
|
|
27
|
+
export declare function createActivityFeedbackOrchestratorForRuntime(serviceConfig: ActivityFeedbackServiceConfig, logger: ActivityFeedbackLogger, access?: ActivityFeedbackEndpointAccess): ActivityFeedbackOrchestrator;
|
|
14
28
|
//# sourceMappingURL=ai-event-binder.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai-event-binder.d.ts","sourceRoot":"","sources":["../src/ai-event-binder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"ai-event-binder.d.ts","sourceRoot":"","sources":["../src/ai-event-binder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACtC,OAAO,EAKL,KAAK,eAAe,EACrB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAqC,KAAK,6BAA6B,EAAE,MAAM,aAAa,CAAC;AACpG,OAAO,EAIL,KAAK,8BAA8B,EACpC,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,4BAA4B,EAAE,MAAM,mBAAmB,CAAC;AAGjE,wBAAgB,qCAAqC,CACnD,YAAY,EAAE,4BAA4B,GACzC,eAAe,CAoEjB;AAED,6DAA6D;AAC7D,wBAAgB,8BAA8B,CAC5C,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,EACpB,YAAY,EAAE,4BAA4B,GACzC,MAAM,IAAI,CAEZ;AAED;;;GAGG;AACH,wBAAgB,gCAAgC,CAC9C,YAAY,EAAE,4BAA4B,GACzC,MAAM,IAAI,CAKZ;AAED,wBAAgB,4BAA4B,CAC1C,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,4BAA4B,GACzC,IAAI,CAMN;AAED,MAAM,MAAM,sBAAsB,GAAG;IACnC,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IACjD,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;CAClD,CAAC;AAEF,MAAM,WAAW,yCAAyC;IACxD,aAAa,EAAE,6BAA6B,CAAC;IAC7C,MAAM,EAAE,8BAA8B,CAAC;IACvC,MAAM,EAAE,sBAAsB,CAAC;CAChC;AAED,wBAAgB,kCAAkC,CAChD,OAAO,EAAE,yCAAyC,GACjD,4BAA4B,CAI9B;AAED,wBAAgB,4CAA4C,CAC1D,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,6BAA6B,GAC3C,4BAA4B,CAM9B;AAED,uFAAuF;AACvF,wBAAgB,4CAA4C,CAC1D,aAAa,EAAE,6BAA6B,EAC5C,MAAM,EAAE,sBAAsB,EAC9B,MAAM,GAAE,8BAA2D,GAClE,4BAA4B,CAM9B"}
|
package/lib/ai-event-binder.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { subscribeAIEvents, isActivityFeedbackEnabled } from '@zhin.js/agent';
|
|
1
|
+
import { subscribeAIEvents, subscribeAIEventsOnTarget, activityFeedbackAiBus, isActivityFeedbackEnabled, } from '@zhin.js/agent';
|
|
2
2
|
import { loadActivityFeedbackServiceConfig } from './config.js';
|
|
3
|
-
import { ActivityFeedbackExecutor, createRootEndpointAccess, } from './executor.js';
|
|
3
|
+
import { ActivityFeedbackExecutor, createNoopEndpointAccess, createRootEndpointAccess, } from './executor.js';
|
|
4
4
|
import { ActivityFeedbackOrchestrator } from './orchestrator.js';
|
|
5
5
|
import { ActivityFeedbackPolicy } from './policy.js';
|
|
6
|
-
export function
|
|
7
|
-
return
|
|
6
|
+
export function createActivityFeedbackAIEventHandlers(orchestrator) {
|
|
7
|
+
return {
|
|
8
8
|
onQueuedStart: (payload) => {
|
|
9
9
|
if (!isActivityFeedbackEnabled(payload, 'queued'))
|
|
10
10
|
return;
|
|
@@ -72,7 +72,18 @@ export function bindActivityFeedbackToAIEvents(root, orchestrator) {
|
|
|
72
72
|
await orchestrator.stopPhase(payload, 'schedule_start', 'schedule.error');
|
|
73
73
|
await orchestrator.startPhase(payload, 'schedule_error', 'schedule.error');
|
|
74
74
|
},
|
|
75
|
-
}
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
/** Legacy host Plugin path (ALS-aware subscribeAIEvents). */
|
|
78
|
+
export function bindActivityFeedbackToAIEvents(root, orchestrator) {
|
|
79
|
+
return subscribeAIEvents(root, createActivityFeedbackAIEventHandlers(orchestrator));
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Plugin Runtime path: subscribe on module-level `activityFeedbackAiBus`
|
|
83
|
+
* (fed by ZhinAgentEventEmitter.emit). No usePlugin / Adapter inject.
|
|
84
|
+
*/
|
|
85
|
+
export function bindActivityFeedbackToAIEventBus(orchestrator) {
|
|
86
|
+
return subscribeAIEventsOnTarget(activityFeedbackAiBus, createActivityFeedbackAIEventHandlers(orchestrator));
|
|
76
87
|
}
|
|
77
88
|
export function mountActivityFeedbackService(plugin, orchestrator) {
|
|
78
89
|
const dispose = bindActivityFeedbackToAIEvents(plugin.root, orchestrator);
|
|
@@ -93,4 +104,12 @@ export function createActivityFeedbackOrchestratorFromPlugin(plugin, serviceConf
|
|
|
93
104
|
logger: plugin.logger,
|
|
94
105
|
});
|
|
95
106
|
}
|
|
107
|
+
/** Runtime: prefer OutboundHost-backed access; else noop until Host wires outbound. */
|
|
108
|
+
export function createActivityFeedbackOrchestratorForRuntime(serviceConfig, logger, access = createNoopEndpointAccess()) {
|
|
109
|
+
return createActivityFeedbackOrchestrator({
|
|
110
|
+
serviceConfig,
|
|
111
|
+
access,
|
|
112
|
+
logger,
|
|
113
|
+
});
|
|
114
|
+
}
|
|
96
115
|
//# sourceMappingURL=ai-event-binder.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai-event-binder.js","sourceRoot":"","sources":["../src/ai-event-binder.ts"],"names":[],"mappings":"AACA,OAAO,
|
|
1
|
+
{"version":3,"file":"ai-event-binder.js","sourceRoot":"","sources":["../src/ai-event-binder.ts"],"names":[],"mappings":"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"}
|
package/lib/executor.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Adapter } from 'zhin.js';
|
|
2
2
|
import { type ActivityFeedbackPhase, type EndpointWithActivityFeedback, type ResolvedActivityFeedbackPhaseConfig, type ActivityFeedbackEventContext } from '@zhin.js/agent';
|
|
3
|
+
import type { OutboundHost } from '@zhin.js/plugin-runtime';
|
|
3
4
|
/** IM 侧 endpoint 访问 seam(便于测试注入 fake) */
|
|
4
5
|
export interface ActivityFeedbackEndpointAccess {
|
|
5
6
|
resolve(platform: string, endpointId: string): {
|
|
@@ -10,6 +11,19 @@ export interface ActivityFeedbackEndpointAccess {
|
|
|
10
11
|
export declare function createRootEndpointAccess(root: {
|
|
11
12
|
injectAdapter(platform: string): Adapter | undefined;
|
|
12
13
|
}): ActivityFeedbackEndpointAccess;
|
|
14
|
+
/** Slice-2: no Adapter inject — executor start/stop no-op when resolve returns undefined. */
|
|
15
|
+
export declare function createNoopEndpointAccess(): ActivityFeedbackEndpointAccess;
|
|
16
|
+
/**
|
|
17
|
+
* Plugin Runtime: resolve endpoints via OutboundHost → ImRuntime.sendEndpointMessage.
|
|
18
|
+
* Typing/reaction text goes through the unified outbound chain (no legacy Adapter.inject).
|
|
19
|
+
*
|
|
20
|
+
* 按 platform:endpointId 缓存 { endpoint, adapter }:activity manager 挂在
|
|
21
|
+
* endpoint.$activityFeedback 上,start/stop 必须解析到同一个对象,否则
|
|
22
|
+
* stop 时拿不到 manager,typing 指示器永远无法停止。
|
|
23
|
+
*/
|
|
24
|
+
export declare function createOutboundEndpointAccess(outbound: OutboundHost, logger?: {
|
|
25
|
+
debug: (msg: string, ...args: unknown[]) => void;
|
|
26
|
+
}): ActivityFeedbackEndpointAccess;
|
|
13
27
|
export declare class ActivityFeedbackExecutor {
|
|
14
28
|
private readonly access;
|
|
15
29
|
constructor(access: ActivityFeedbackEndpointAccess);
|
package/lib/executor.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../src/executor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAgG,KAAK,qBAAqB,EAAE,KAAK,4BAA4B,EAAwC,KAAK,mCAAmC,EAAE,KAAK,4BAA4B,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../src/executor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAgG,KAAK,qBAAqB,EAAE,KAAK,4BAA4B,EAAwC,KAAK,mCAAmC,EAAE,KAAK,4BAA4B,EAAE,MAAM,gBAAgB,CAAC;AAChT,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAE5D,yCAAyC;AACzC,MAAM,WAAW,8BAA8B;IAC7C,OAAO,CACL,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,GACjB;QAAE,QAAQ,EAAE,4BAA4B,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,GAAG,SAAS,CAAC;CAC7E;AAED,wBAAgB,wBAAwB,CAAC,IAAI,EAAE;IAC7C,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC;CACtD,GAAG,8BAA8B,CASjC;AAED,6FAA6F;AAC7F,wBAAgB,wBAAwB,IAAI,8BAA8B,CAMzE;AAqBD;;;;;;;GAOG;AACH,wBAAgB,4BAA4B,CAC1C,QAAQ,EAAE,YAAY,EACtB,MAAM,CAAC,EAAE;IAAE,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAA;CAAE,GAC5D,8BAA8B,CA0FhC;AA2GD,qBAAa,wBAAwB;IACvB,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,EAAE,8BAA8B;IAE7D,KAAK,CACT,GAAG,EAAE,4BAA4B,EACjC,KAAK,EAAE,qBAAqB,EAC5B,WAAW,EAAE,mCAAmC,GAC/C,OAAO,CAAC,IAAI,CAAC;IAOV,IAAI,CAAC,GAAG,EAAE,4BAA4B,EAAE,KAAK,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC;IAOpF,kBAAkB,CAAC,GAAG,EAAE,4BAA4B,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAMzF"}
|
package/lib/executor.js
CHANGED
|
@@ -10,6 +10,122 @@ export function createRootEndpointAccess(root) {
|
|
|
10
10
|
},
|
|
11
11
|
};
|
|
12
12
|
}
|
|
13
|
+
/** Slice-2: no Adapter inject — executor start/stop no-op when resolve returns undefined. */
|
|
14
|
+
export function createNoopEndpointAccess() {
|
|
15
|
+
return {
|
|
16
|
+
resolve() {
|
|
17
|
+
return undefined;
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
function stringifySendContent(content) {
|
|
22
|
+
if (typeof content === 'string')
|
|
23
|
+
return content;
|
|
24
|
+
if (!Array.isArray(content))
|
|
25
|
+
return content == null ? '' : String(content);
|
|
26
|
+
return content.map((segment) => {
|
|
27
|
+
if (typeof segment === 'string')
|
|
28
|
+
return segment;
|
|
29
|
+
if (segment && typeof segment === 'object') {
|
|
30
|
+
const data = segment.data
|
|
31
|
+
?? segment;
|
|
32
|
+
if (typeof data === 'object' && data && 'text' in data && typeof data.text === 'string') {
|
|
33
|
+
return data.text;
|
|
34
|
+
}
|
|
35
|
+
if (typeof segment.text === 'string') {
|
|
36
|
+
return segment.text;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return '';
|
|
40
|
+
}).join('');
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Plugin Runtime: resolve endpoints via OutboundHost → ImRuntime.sendEndpointMessage.
|
|
44
|
+
* Typing/reaction text goes through the unified outbound chain (no legacy Adapter.inject).
|
|
45
|
+
*
|
|
46
|
+
* 按 platform:endpointId 缓存 { endpoint, adapter }:activity manager 挂在
|
|
47
|
+
* endpoint.$activityFeedback 上,start/stop 必须解析到同一个对象,否则
|
|
48
|
+
* stop 时拿不到 manager,typing 指示器永远无法停止。
|
|
49
|
+
*/
|
|
50
|
+
export function createOutboundEndpointAccess(outbound, logger) {
|
|
51
|
+
const cache = new Map();
|
|
52
|
+
return {
|
|
53
|
+
resolve(platform, endpointId) {
|
|
54
|
+
const key = `${platform}:${endpointId}`;
|
|
55
|
+
const cached = cache.get(key);
|
|
56
|
+
if (cached)
|
|
57
|
+
return cached;
|
|
58
|
+
const addReaction = outbound.addReaction;
|
|
59
|
+
const removeReaction = outbound.removeReaction;
|
|
60
|
+
const endpoint = {
|
|
61
|
+
$id: endpointId,
|
|
62
|
+
// Prefer real OutboundHost.recall when available (icqq RECALL_MSG).
|
|
63
|
+
$recallMessage: async (messageId) => {
|
|
64
|
+
if (outbound.recall) {
|
|
65
|
+
try {
|
|
66
|
+
await outbound.recall({ adapter: platform, endpointId, messageId });
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
logger?.debug(`[ActivityFeedback] outbound recall failed (${key}):`, error instanceof Error ? error.message : String(error));
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
logger?.debug(`[ActivityFeedback] recall not supported via OutboundHost (${key}, messageId=${messageId})`);
|
|
75
|
+
},
|
|
76
|
+
$addReaction: addReaction
|
|
77
|
+
? async (messageId, emoji, hint) => addReaction({
|
|
78
|
+
adapter: platform,
|
|
79
|
+
endpointId,
|
|
80
|
+
messageId,
|
|
81
|
+
emoji,
|
|
82
|
+
sceneType: hint?.sceneType,
|
|
83
|
+
channelId: hint?.channelId,
|
|
84
|
+
})
|
|
85
|
+
: undefined,
|
|
86
|
+
$removeReaction: removeReaction
|
|
87
|
+
? async (messageId, reactionId) => {
|
|
88
|
+
await removeReaction({
|
|
89
|
+
adapter: platform,
|
|
90
|
+
endpointId,
|
|
91
|
+
messageId,
|
|
92
|
+
reactionId,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
: undefined,
|
|
96
|
+
};
|
|
97
|
+
const adapter = {
|
|
98
|
+
sendMessage: async (options) => {
|
|
99
|
+
const text = stringifySendContent(options.content);
|
|
100
|
+
if (!text || !options.id)
|
|
101
|
+
return null;
|
|
102
|
+
try {
|
|
103
|
+
const messageId = await outbound.send({
|
|
104
|
+
adapter: platform,
|
|
105
|
+
endpointId,
|
|
106
|
+
channelType: options.type || 'private',
|
|
107
|
+
channelId: options.id,
|
|
108
|
+
content: text,
|
|
109
|
+
});
|
|
110
|
+
// Prefer real id; fall back to a sentinel so MessageTypingIndicator
|
|
111
|
+
// keeps the phase active until stop (recall is a no-op here).
|
|
112
|
+
return messageId || `outbound:${Date.now()}`;
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
logger?.debug(`[ActivityFeedback] outbound send failed (${key}):`, error instanceof Error ? error.message : String(error));
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
endpoints: {
|
|
120
|
+
get: (id) => (id === endpointId ? endpoint : undefined),
|
|
121
|
+
},
|
|
122
|
+
};
|
|
123
|
+
const resolved = { endpoint, adapter: adapter };
|
|
124
|
+
cache.set(key, resolved);
|
|
125
|
+
return resolved;
|
|
126
|
+
},
|
|
127
|
+
};
|
|
128
|
+
}
|
|
13
129
|
class PlatformPhaseDriver {
|
|
14
130
|
manager;
|
|
15
131
|
constructor(manager) {
|
package/lib/executor.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"executor.js","sourceRoot":"","sources":["../src/executor.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,4BAA4B,EAAE,gCAAgC,EAAkN,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"executor.js","sourceRoot":"","sources":["../src/executor.ts"],"names":[],"mappings":"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"}
|
package/lib/index.d.ts
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/**
|
|
2
|
+
* @zhin.js/service-activity-feedback
|
|
3
|
+
*
|
|
4
|
+
* Pure module exports. Plugin Runtime entry is `plugin.ts`.
|
|
5
|
+
*/
|
|
6
|
+
export { bindActivityFeedbackToAIEvents, bindActivityFeedbackToAIEventBus, createActivityFeedbackAIEventHandlers, createActivityFeedbackOrchestrator, createActivityFeedbackOrchestratorFromPlugin, createActivityFeedbackOrchestratorForRuntime, mountActivityFeedbackService, } from './ai-event-binder.js';
|
|
3
7
|
export { ActivityFeedbackOrchestrator } from './orchestrator.js';
|
|
4
8
|
export { ActivityFeedbackPolicy } from './policy.js';
|
|
5
9
|
export { loadActivityFeedbackServiceConfig, resolveActivityFeedbackForTarget, type ActivityFeedbackServiceConfig, } from './config.js';
|
|
6
10
|
export type { ActivityFeedbackEndpointAccess } from './executor.js';
|
|
7
|
-
export
|
|
11
|
+
export { createNoopEndpointAccess, createOutboundEndpointAccess, createRootEndpointAccess, } from './executor.js';
|
|
8
12
|
//# sourceMappingURL=index.d.ts.map
|
package/lib/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EACL,8BAA8B,EAC9B,gCAAgC,EAChC,qCAAqC,EACrC,kCAAkC,EAClC,4CAA4C,EAC5C,4CAA4C,EAC5C,4BAA4B,GAC7B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,4BAA4B,EAAE,MAAM,mBAAmB,CAAC;AACjE,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EACL,iCAAiC,EACjC,gCAAgC,EAChC,KAAK,6BAA6B,GACnC,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,8BAA8B,EAAE,MAAM,eAAe,CAAC;AACpE,OAAO,EACL,wBAAwB,EACxB,4BAA4B,EAC5B,wBAAwB,GACzB,MAAM,eAAe,CAAC"}
|
package/lib/index.js
CHANGED
|
@@ -1,23 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @zhin.js/service-activity-feedback
|
|
3
|
+
*
|
|
4
|
+
* Pure module exports. Plugin Runtime entry is `plugin.ts`.
|
|
3
5
|
*/
|
|
4
|
-
|
|
5
|
-
import { createActivityFeedbackOrchestratorFromPlugin, mountActivityFeedbackService, } from './ai-event-binder.js';
|
|
6
|
-
import { loadActivityFeedbackServiceConfig } from './config.js';
|
|
7
|
-
const plugin = usePlugin();
|
|
8
|
-
const { root, logger } = plugin;
|
|
9
|
-
const configService = root.inject('config');
|
|
10
|
-
const appConfig = configService?.getPrimary() || {};
|
|
11
|
-
const serviceConfig = loadActivityFeedbackServiceConfig(appConfig.activityFeedback);
|
|
12
|
-
if (serviceConfig.enabled !== false) {
|
|
13
|
-
mountActivityFeedbackService(plugin, createActivityFeedbackOrchestratorFromPlugin(plugin, serviceConfig));
|
|
14
|
-
}
|
|
15
|
-
else {
|
|
16
|
-
logger.debug('[ActivityFeedback] disabled by activityFeedback.enabled=false');
|
|
17
|
-
}
|
|
18
|
-
export { bindActivityFeedbackToAIEvents, createActivityFeedbackOrchestrator, createActivityFeedbackOrchestratorFromPlugin, mountActivityFeedbackService, } from './ai-event-binder.js';
|
|
6
|
+
export { bindActivityFeedbackToAIEvents, bindActivityFeedbackToAIEventBus, createActivityFeedbackAIEventHandlers, createActivityFeedbackOrchestrator, createActivityFeedbackOrchestratorFromPlugin, createActivityFeedbackOrchestratorForRuntime, mountActivityFeedbackService, } from './ai-event-binder.js';
|
|
19
7
|
export { ActivityFeedbackOrchestrator } from './orchestrator.js';
|
|
20
8
|
export { ActivityFeedbackPolicy } from './policy.js';
|
|
21
9
|
export { loadActivityFeedbackServiceConfig, resolveActivityFeedbackForTarget, } from './config.js';
|
|
22
|
-
export
|
|
10
|
+
export { createNoopEndpointAccess, createOutboundEndpointAccess, createRootEndpointAccess, } from './executor.js';
|
|
23
11
|
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EACL,8BAA8B,EAC9B,gCAAgC,EAChC,qCAAqC,EACrC,kCAAkC,EAClC,4CAA4C,EAC5C,4CAA4C,EAC5C,4BAA4B,GAC7B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,4BAA4B,EAAE,MAAM,mBAAmB,CAAC;AACjE,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EACL,iCAAiC,EACjC,gCAAgC,GAEjC,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,wBAAwB,EACxB,4BAA4B,EAC5B,wBAAwB,GACzB,MAAM,eAAe,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zhin.js/service-activity-feedback",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "Activity Feedback
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"description": "Activity Feedback 服务插件(Plugin Runtime)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.js",
|
|
7
7
|
"types": "./lib/index.d.ts",
|
|
@@ -14,9 +14,10 @@
|
|
|
14
14
|
"./package.json": "./package.json"
|
|
15
15
|
},
|
|
16
16
|
"files": [
|
|
17
|
+
"plugin.ts",
|
|
18
|
+
"schema.json",
|
|
17
19
|
"src",
|
|
18
20
|
"lib",
|
|
19
|
-
"plugin.yml",
|
|
20
21
|
"README.md"
|
|
21
22
|
],
|
|
22
23
|
"keywords": [
|
|
@@ -35,20 +36,40 @@
|
|
|
35
36
|
"directory": "plugins/services/activity-feedback"
|
|
36
37
|
},
|
|
37
38
|
"dependencies": {
|
|
38
|
-
"@zhin.js/agent": "1.0.
|
|
39
|
+
"@zhin.js/agent": "1.0.5",
|
|
40
|
+
"@zhin.js/logger": "1.0.75",
|
|
41
|
+
"@zhin.js/plugin-runtime": "1.1.0"
|
|
39
42
|
},
|
|
40
43
|
"devDependencies": {
|
|
41
44
|
"@types/node": "^26.1.0",
|
|
42
45
|
"typescript": "^6.0.3",
|
|
43
|
-
"
|
|
46
|
+
"vitest": "^4.1.10",
|
|
47
|
+
"zhin.js": "5.0.0"
|
|
44
48
|
},
|
|
45
49
|
"peerDependencies": {
|
|
46
|
-
"@zhin.js/agent": "1.0.
|
|
47
|
-
"zhin.js": "
|
|
50
|
+
"@zhin.js/agent": "1.0.5",
|
|
51
|
+
"zhin.js": "5.0.0"
|
|
52
|
+
},
|
|
53
|
+
"peerDependenciesMeta": {
|
|
54
|
+
"zhin.js": {
|
|
55
|
+
"optional": true
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
"engines": {
|
|
59
|
+
"node": "^20.19.0 || >=22.12.0"
|
|
60
|
+
},
|
|
61
|
+
"zhin": {
|
|
62
|
+
"protocol": 1,
|
|
63
|
+
"type": "plugin",
|
|
64
|
+
"entry": "./plugin.ts",
|
|
65
|
+
"engine": "^1.0.0",
|
|
66
|
+
"runtime": "trusted",
|
|
67
|
+
"features": [],
|
|
68
|
+
"plugins": []
|
|
48
69
|
},
|
|
49
70
|
"scripts": {
|
|
50
71
|
"build": "tsc",
|
|
51
72
|
"clean": "rimraf lib",
|
|
52
|
-
"test": "vitest run --
|
|
73
|
+
"test": "vitest run --root ../../.. plugins/services/activity-feedback/tests"
|
|
53
74
|
}
|
|
54
75
|
}
|
package/plugin.ts
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { definePlugin, outboundHostToken } from '@zhin.js/plugin-runtime';
|
|
2
|
+
import { getLogger } from '@zhin.js/logger';
|
|
3
|
+
import {
|
|
4
|
+
loadActivityFeedbackServiceConfig,
|
|
5
|
+
type ActivityFeedbackServiceConfig,
|
|
6
|
+
} from './src/config.js';
|
|
7
|
+
import {
|
|
8
|
+
bindActivityFeedbackToAIEventBus,
|
|
9
|
+
createActivityFeedbackOrchestratorForRuntime,
|
|
10
|
+
} from './src/ai-event-binder.js';
|
|
11
|
+
import {
|
|
12
|
+
createNoopEndpointAccess,
|
|
13
|
+
createOutboundEndpointAccess,
|
|
14
|
+
} from './src/executor.js';
|
|
15
|
+
|
|
16
|
+
const logger = getLogger('activity-feedback');
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Activity Feedback service — Plugin Runtime entry.
|
|
20
|
+
*
|
|
21
|
+
* Subscribes AI lifecycle events via `activityFeedbackAiBus`.
|
|
22
|
+
* When Root provides `outboundHostToken`, typing/status text uses
|
|
23
|
+
* ImRuntime.sendEndpointMessage; otherwise phases no-op.
|
|
24
|
+
*/
|
|
25
|
+
export default definePlugin<ActivityFeedbackServiceConfig>({
|
|
26
|
+
name: 'activity-feedback',
|
|
27
|
+
metadata: {
|
|
28
|
+
displayName: 'Activity Feedback',
|
|
29
|
+
},
|
|
30
|
+
setup(context) {
|
|
31
|
+
const serviceConfig = loadActivityFeedbackServiceConfig(context.config.get());
|
|
32
|
+
if (serviceConfig.enabled === false) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const access = context.resources.has(outboundHostToken)
|
|
37
|
+
? createOutboundEndpointAccess(context.resources.use(outboundHostToken), logger)
|
|
38
|
+
: createNoopEndpointAccess();
|
|
39
|
+
|
|
40
|
+
const orchestrator = createActivityFeedbackOrchestratorForRuntime(
|
|
41
|
+
serviceConfig,
|
|
42
|
+
logger,
|
|
43
|
+
access,
|
|
44
|
+
);
|
|
45
|
+
const dispose = bindActivityFeedbackToAIEventBus(orchestrator);
|
|
46
|
+
context.lifecycle.add(() => {
|
|
47
|
+
logger.debug('[ActivityFeedback] Disposing Runtime AI event binder');
|
|
48
|
+
dispose();
|
|
49
|
+
});
|
|
50
|
+
},
|
|
51
|
+
});
|
package/schema.json
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"type": "object",
|
|
4
|
+
"additionalProperties": false,
|
|
5
|
+
"properties": {
|
|
6
|
+
"enabled": { "type": "boolean", "default": true },
|
|
7
|
+
"defaults": { "type": "object", "additionalProperties": true },
|
|
8
|
+
"platforms": { "type": "object", "additionalProperties": true },
|
|
9
|
+
"endpoints": { "type": "object", "additionalProperties": true },
|
|
10
|
+
"schedule": { "type": "object", "additionalProperties": true }
|
|
11
|
+
}
|
|
12
|
+
}
|
package/src/ai-event-binder.ts
CHANGED
|
@@ -1,19 +1,25 @@
|
|
|
1
1
|
import type { Plugin } from 'zhin.js';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
subscribeAIEvents,
|
|
4
|
+
subscribeAIEventsOnTarget,
|
|
5
|
+
activityFeedbackAiBus,
|
|
6
|
+
isActivityFeedbackEnabled,
|
|
7
|
+
type AIEventHandlers,
|
|
8
|
+
} from '@zhin.js/agent';
|
|
3
9
|
import { loadActivityFeedbackServiceConfig, type ActivityFeedbackServiceConfig } from './config.js';
|
|
4
10
|
import {
|
|
5
11
|
ActivityFeedbackExecutor,
|
|
12
|
+
createNoopEndpointAccess,
|
|
6
13
|
createRootEndpointAccess,
|
|
7
14
|
type ActivityFeedbackEndpointAccess,
|
|
8
15
|
} from './executor.js';
|
|
9
16
|
import { ActivityFeedbackOrchestrator } from './orchestrator.js';
|
|
10
17
|
import { ActivityFeedbackPolicy } from './policy.js';
|
|
11
18
|
|
|
12
|
-
export function
|
|
13
|
-
root: Plugin['root'],
|
|
19
|
+
export function createActivityFeedbackAIEventHandlers(
|
|
14
20
|
orchestrator: ActivityFeedbackOrchestrator,
|
|
15
|
-
):
|
|
16
|
-
return
|
|
21
|
+
): AIEventHandlers {
|
|
22
|
+
return {
|
|
17
23
|
onQueuedStart: (payload) => {
|
|
18
24
|
if (!isActivityFeedbackEnabled(payload, 'queued')) return;
|
|
19
25
|
return orchestrator.startPhase(payload, 'queued', 'activity.queued.start');
|
|
@@ -79,7 +85,28 @@ export function bindActivityFeedbackToAIEvents(
|
|
|
79
85
|
await orchestrator.stopPhase(payload, 'schedule_start', 'schedule.error');
|
|
80
86
|
await orchestrator.startPhase(payload, 'schedule_error', 'schedule.error');
|
|
81
87
|
},
|
|
82
|
-
}
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/** Legacy host Plugin path (ALS-aware subscribeAIEvents). */
|
|
92
|
+
export function bindActivityFeedbackToAIEvents(
|
|
93
|
+
root: Plugin['root'],
|
|
94
|
+
orchestrator: ActivityFeedbackOrchestrator,
|
|
95
|
+
): () => void {
|
|
96
|
+
return subscribeAIEvents(root, createActivityFeedbackAIEventHandlers(orchestrator));
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Plugin Runtime path: subscribe on module-level `activityFeedbackAiBus`
|
|
101
|
+
* (fed by ZhinAgentEventEmitter.emit). No usePlugin / Adapter inject.
|
|
102
|
+
*/
|
|
103
|
+
export function bindActivityFeedbackToAIEventBus(
|
|
104
|
+
orchestrator: ActivityFeedbackOrchestrator,
|
|
105
|
+
): () => void {
|
|
106
|
+
return subscribeAIEventsOnTarget(
|
|
107
|
+
activityFeedbackAiBus,
|
|
108
|
+
createActivityFeedbackAIEventHandlers(orchestrator),
|
|
109
|
+
);
|
|
83
110
|
}
|
|
84
111
|
|
|
85
112
|
export function mountActivityFeedbackService(
|
|
@@ -93,10 +120,15 @@ export function mountActivityFeedbackService(
|
|
|
93
120
|
});
|
|
94
121
|
}
|
|
95
122
|
|
|
123
|
+
export type ActivityFeedbackLogger = {
|
|
124
|
+
debug: (msg: string, ...args: unknown[]) => void;
|
|
125
|
+
error: (msg: string, ...args: unknown[]) => void;
|
|
126
|
+
};
|
|
127
|
+
|
|
96
128
|
export interface CreateActivityFeedbackOrchestratorOptions {
|
|
97
129
|
serviceConfig: ActivityFeedbackServiceConfig;
|
|
98
130
|
access: ActivityFeedbackEndpointAccess;
|
|
99
|
-
logger:
|
|
131
|
+
logger: ActivityFeedbackLogger;
|
|
100
132
|
}
|
|
101
133
|
|
|
102
134
|
export function createActivityFeedbackOrchestrator(
|
|
@@ -117,3 +149,16 @@ export function createActivityFeedbackOrchestratorFromPlugin(
|
|
|
117
149
|
logger: plugin.logger,
|
|
118
150
|
});
|
|
119
151
|
}
|
|
152
|
+
|
|
153
|
+
/** Runtime: prefer OutboundHost-backed access; else noop until Host wires outbound. */
|
|
154
|
+
export function createActivityFeedbackOrchestratorForRuntime(
|
|
155
|
+
serviceConfig: ActivityFeedbackServiceConfig,
|
|
156
|
+
logger: ActivityFeedbackLogger,
|
|
157
|
+
access: ActivityFeedbackEndpointAccess = createNoopEndpointAccess(),
|
|
158
|
+
): ActivityFeedbackOrchestrator {
|
|
159
|
+
return createActivityFeedbackOrchestrator({
|
|
160
|
+
serviceConfig,
|
|
161
|
+
access,
|
|
162
|
+
logger,
|
|
163
|
+
});
|
|
164
|
+
}
|
package/src/executor.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Adapter } from 'zhin.js';
|
|
2
2
|
import { enableActivityFeedbackForBot, isGenericActivityFeedbackManager, type ActivityFeedbackManager, type ActivityFeedbackPhase, type EndpointWithActivityFeedback, type PlatformActivityFeedbackManager, type ResolvedActivityFeedbackPhaseConfig, type ActivityFeedbackEventContext } from '@zhin.js/agent';
|
|
3
|
+
import type { OutboundHost } from '@zhin.js/plugin-runtime';
|
|
3
4
|
|
|
4
5
|
/** IM 侧 endpoint 访问 seam(便于测试注入 fake) */
|
|
5
6
|
export interface ActivityFeedbackEndpointAccess {
|
|
@@ -22,6 +23,137 @@ export function createRootEndpointAccess(root: {
|
|
|
22
23
|
};
|
|
23
24
|
}
|
|
24
25
|
|
|
26
|
+
/** Slice-2: no Adapter inject — executor start/stop no-op when resolve returns undefined. */
|
|
27
|
+
export function createNoopEndpointAccess(): ActivityFeedbackEndpointAccess {
|
|
28
|
+
return {
|
|
29
|
+
resolve() {
|
|
30
|
+
return undefined;
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function stringifySendContent(content: unknown): string {
|
|
36
|
+
if (typeof content === 'string') return content;
|
|
37
|
+
if (!Array.isArray(content)) return content == null ? '' : String(content);
|
|
38
|
+
return content.map((segment) => {
|
|
39
|
+
if (typeof segment === 'string') return segment;
|
|
40
|
+
if (segment && typeof segment === 'object') {
|
|
41
|
+
const data = (segment as { data?: { text?: string }; text?: string }).data
|
|
42
|
+
?? (segment as { text?: string });
|
|
43
|
+
if (typeof data === 'object' && data && 'text' in data && typeof data.text === 'string') {
|
|
44
|
+
return data.text;
|
|
45
|
+
}
|
|
46
|
+
if (typeof (segment as { text?: string }).text === 'string') {
|
|
47
|
+
return (segment as { text: string }).text;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return '';
|
|
51
|
+
}).join('');
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Plugin Runtime: resolve endpoints via OutboundHost → ImRuntime.sendEndpointMessage.
|
|
56
|
+
* Typing/reaction text goes through the unified outbound chain (no legacy Adapter.inject).
|
|
57
|
+
*
|
|
58
|
+
* 按 platform:endpointId 缓存 { endpoint, adapter }:activity manager 挂在
|
|
59
|
+
* endpoint.$activityFeedback 上,start/stop 必须解析到同一个对象,否则
|
|
60
|
+
* stop 时拿不到 manager,typing 指示器永远无法停止。
|
|
61
|
+
*/
|
|
62
|
+
export function createOutboundEndpointAccess(
|
|
63
|
+
outbound: OutboundHost,
|
|
64
|
+
logger?: { debug: (msg: string, ...args: unknown[]) => void },
|
|
65
|
+
): ActivityFeedbackEndpointAccess {
|
|
66
|
+
const cache = new Map<string, { endpoint: EndpointWithActivityFeedback; adapter: Adapter }>();
|
|
67
|
+
return {
|
|
68
|
+
resolve(platform, endpointId) {
|
|
69
|
+
const key = `${platform}:${endpointId}`;
|
|
70
|
+
const cached = cache.get(key);
|
|
71
|
+
if (cached) return cached;
|
|
72
|
+
const addReaction = outbound.addReaction;
|
|
73
|
+
const removeReaction = outbound.removeReaction;
|
|
74
|
+
const endpoint = {
|
|
75
|
+
$id: endpointId,
|
|
76
|
+
// Prefer real OutboundHost.recall when available (icqq RECALL_MSG).
|
|
77
|
+
$recallMessage: async (messageId: string) => {
|
|
78
|
+
if (outbound.recall) {
|
|
79
|
+
try {
|
|
80
|
+
await outbound.recall({ adapter: platform, endpointId, messageId });
|
|
81
|
+
return;
|
|
82
|
+
} catch (error) {
|
|
83
|
+
logger?.debug(
|
|
84
|
+
`[ActivityFeedback] outbound recall failed (${key}):`,
|
|
85
|
+
error instanceof Error ? error.message : String(error),
|
|
86
|
+
);
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
logger?.debug(
|
|
91
|
+
`[ActivityFeedback] recall not supported via OutboundHost (${key}, messageId=${messageId})`,
|
|
92
|
+
);
|
|
93
|
+
},
|
|
94
|
+
$addReaction: addReaction
|
|
95
|
+
? async (
|
|
96
|
+
messageId: string,
|
|
97
|
+
emoji: string,
|
|
98
|
+
hint?: { sceneType?: 'private' | 'group' | 'channel'; channelId?: string },
|
|
99
|
+
) => addReaction({
|
|
100
|
+
adapter: platform,
|
|
101
|
+
endpointId,
|
|
102
|
+
messageId,
|
|
103
|
+
emoji,
|
|
104
|
+
sceneType: hint?.sceneType,
|
|
105
|
+
channelId: hint?.channelId,
|
|
106
|
+
})
|
|
107
|
+
: undefined,
|
|
108
|
+
$removeReaction: removeReaction
|
|
109
|
+
? async (messageId: string, reactionId: string) => {
|
|
110
|
+
await removeReaction({
|
|
111
|
+
adapter: platform,
|
|
112
|
+
endpointId,
|
|
113
|
+
messageId,
|
|
114
|
+
reactionId,
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
: undefined,
|
|
118
|
+
} as EndpointWithActivityFeedback;
|
|
119
|
+
const adapter = {
|
|
120
|
+
sendMessage: async (options: {
|
|
121
|
+
type?: string;
|
|
122
|
+
id?: string;
|
|
123
|
+
content?: unknown;
|
|
124
|
+
}) => {
|
|
125
|
+
const text = stringifySendContent(options.content);
|
|
126
|
+
if (!text || !options.id) return null;
|
|
127
|
+
try {
|
|
128
|
+
const messageId = await outbound.send({
|
|
129
|
+
adapter: platform,
|
|
130
|
+
endpointId,
|
|
131
|
+
channelType: options.type || 'private',
|
|
132
|
+
channelId: options.id,
|
|
133
|
+
content: text,
|
|
134
|
+
});
|
|
135
|
+
// Prefer real id; fall back to a sentinel so MessageTypingIndicator
|
|
136
|
+
// keeps the phase active until stop (recall is a no-op here).
|
|
137
|
+
return messageId || `outbound:${Date.now()}`;
|
|
138
|
+
} catch (error) {
|
|
139
|
+
logger?.debug(
|
|
140
|
+
`[ActivityFeedback] outbound send failed (${key}):`,
|
|
141
|
+
error instanceof Error ? error.message : String(error),
|
|
142
|
+
);
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
},
|
|
146
|
+
endpoints: {
|
|
147
|
+
get: (id: string) => (id === endpointId ? endpoint : undefined),
|
|
148
|
+
},
|
|
149
|
+
};
|
|
150
|
+
const resolved = { endpoint, adapter: adapter as unknown as Adapter };
|
|
151
|
+
cache.set(key, resolved);
|
|
152
|
+
return resolved;
|
|
153
|
+
},
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
|
|
25
157
|
interface PhaseDriver {
|
|
26
158
|
start(
|
|
27
159
|
ctx: ActivityFeedbackEventContext,
|
package/src/index.ts
CHANGED
|
@@ -1,33 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @zhin.js/service-activity-feedback
|
|
3
|
+
*
|
|
4
|
+
* Pure module exports. Plugin Runtime entry is `plugin.ts`.
|
|
3
5
|
*/
|
|
4
|
-
import { usePlugin } from 'zhin.js';
|
|
5
|
-
import {
|
|
6
|
-
createActivityFeedbackOrchestratorFromPlugin,
|
|
7
|
-
mountActivityFeedbackService,
|
|
8
|
-
} from './ai-event-binder.js';
|
|
9
|
-
import { loadActivityFeedbackServiceConfig, type ActivityFeedbackServiceConfig } from './config.js';
|
|
10
|
-
|
|
11
|
-
const plugin = usePlugin();
|
|
12
|
-
const { root, logger } = plugin;
|
|
13
|
-
|
|
14
|
-
const configService = root.inject('config');
|
|
15
|
-
const appConfig = configService?.getPrimary<{ activityFeedback?: ActivityFeedbackServiceConfig }>() || {};
|
|
16
|
-
const serviceConfig = loadActivityFeedbackServiceConfig(appConfig.activityFeedback);
|
|
17
|
-
|
|
18
|
-
if (serviceConfig.enabled !== false) {
|
|
19
|
-
mountActivityFeedbackService(
|
|
20
|
-
plugin,
|
|
21
|
-
createActivityFeedbackOrchestratorFromPlugin(plugin, serviceConfig),
|
|
22
|
-
);
|
|
23
|
-
} else {
|
|
24
|
-
logger.debug('[ActivityFeedback] disabled by activityFeedback.enabled=false');
|
|
25
|
-
}
|
|
26
|
-
|
|
27
6
|
export {
|
|
28
7
|
bindActivityFeedbackToAIEvents,
|
|
8
|
+
bindActivityFeedbackToAIEventBus,
|
|
9
|
+
createActivityFeedbackAIEventHandlers,
|
|
29
10
|
createActivityFeedbackOrchestrator,
|
|
30
11
|
createActivityFeedbackOrchestratorFromPlugin,
|
|
12
|
+
createActivityFeedbackOrchestratorForRuntime,
|
|
31
13
|
mountActivityFeedbackService,
|
|
32
14
|
} from './ai-event-binder.js';
|
|
33
15
|
export { ActivityFeedbackOrchestrator } from './orchestrator.js';
|
|
@@ -38,4 +20,8 @@ export {
|
|
|
38
20
|
type ActivityFeedbackServiceConfig,
|
|
39
21
|
} from './config.js';
|
|
40
22
|
export type { ActivityFeedbackEndpointAccess } from './executor.js';
|
|
41
|
-
export
|
|
23
|
+
export {
|
|
24
|
+
createNoopEndpointAccess,
|
|
25
|
+
createOutboundEndpointAccess,
|
|
26
|
+
createRootEndpointAccess,
|
|
27
|
+
} from './executor.js';
|
package/plugin.yml
DELETED