@zhin.js/service-activity-feedback 1.0.0 → 1.0.2

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/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
+ }
@@ -1,24 +1,36 @@
1
1
  import type { Plugin } from 'zhin.js';
2
- import { subscribeAIEvents } from '@zhin.js/agent';
3
- import type { ActivityFeedbackServiceConfig } from './config.js';
2
+ import {
3
+ subscribeAIEvents,
4
+ subscribeAIEventsOnTarget,
5
+ activityFeedbackAiBus,
6
+ isActivityFeedbackEnabled,
7
+ type AIEventHandlers,
8
+ } from '@zhin.js/agent';
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
- import { loadActivityFeedbackServiceConfig } from './config.js';
12
18
 
13
- export function bindActivityFeedbackToAIEvents(
14
- root: Plugin['root'],
19
+ export function createActivityFeedbackAIEventHandlers(
15
20
  orchestrator: ActivityFeedbackOrchestrator,
16
- ): () => void {
17
- return subscribeAIEvents(root, {
18
- onQueuedStart: (payload) => orchestrator.startPhase(payload, 'queued', 'activity.queued.start'),
19
- onQueuedClear: (payload) => orchestrator.stopPhase(payload, 'queued', 'activity.queued.clear'),
21
+ ): AIEventHandlers {
22
+ return {
23
+ onQueuedStart: (payload) => {
24
+ if (!isActivityFeedbackEnabled(payload, 'queued')) return;
25
+ return orchestrator.startPhase(payload, 'queued', 'activity.queued.start');
26
+ },
27
+ onQueuedClear: (payload) => {
28
+ if (!isActivityFeedbackEnabled(payload, 'queued')) return;
29
+ return orchestrator.stopPhase(payload, 'queued', 'activity.queued.clear');
30
+ },
20
31
 
21
32
  onProcessingStart: async (payload) => {
33
+ if (!isActivityFeedbackEnabled(payload, 'active')) return;
22
34
  await orchestrator.stopPhase(payload, 'queued', 'processing.start');
23
35
  await orchestrator.startPhase(payload, 'active', 'processing.start');
24
36
  },
@@ -26,19 +38,25 @@ export function bindActivityFeedbackToAIEvents(
26
38
  onTypingStart: async () => {},
27
39
 
28
40
  onProcessingFinish: async (payload) => {
41
+ if (!isActivityFeedbackEnabled(payload, 'active')) return;
29
42
  if (payload.keepTyping) return;
30
43
  await orchestrator.stopPhase(payload, 'thinking', 'processing.finish');
31
44
  await orchestrator.stopPhase(payload, 'active', 'processing.finish');
32
45
  },
33
46
 
34
47
  onProcessingError: async (payload) => {
48
+ if (!isActivityFeedbackEnabled(payload, 'active')) return;
35
49
  await orchestrator.stopPhase(payload, 'thinking', 'processing.error');
36
50
  await orchestrator.stopPhase(payload, 'active', 'processing.error');
37
51
  },
38
52
 
39
- onTypingStop: (payload) => orchestrator.stopPhase(payload, 'active', 'typing.stop'),
53
+ onTypingStop: (payload) => {
54
+ if (!isActivityFeedbackEnabled(payload, 'active')) return;
55
+ return orchestrator.stopPhase(payload, 'active', 'typing.stop');
56
+ },
40
57
 
41
58
  onThinking: async (payload) => {
59
+ if (!isActivityFeedbackEnabled(payload, 'thinking')) return;
42
60
  if (!payload.thinking) return;
43
61
  await orchestrator.stopPhase(payload, 'active', 'thinking');
44
62
  await orchestrator.startPhase(payload, 'thinking', 'thinking');
@@ -46,6 +64,7 @@ export function bindActivityFeedbackToAIEvents(
46
64
  },
47
65
 
48
66
  onSubagentStart: async (payload) => {
67
+ if (!isActivityFeedbackEnabled(payload, 'thinking')) return;
49
68
  await orchestrator.stopPhase(payload, 'active', 'subagent.start');
50
69
  await orchestrator.startPhase(payload, 'thinking', 'subagent.start');
51
70
  const label = payload.label
@@ -55,10 +74,39 @@ export function bindActivityFeedbackToAIEvents(
55
74
  },
56
75
 
57
76
  onSubagentFinish: async (payload) => {
77
+ if (!isActivityFeedbackEnabled(payload, 'active')) return;
58
78
  await orchestrator.stopPhase(payload, 'thinking', 'subagent.finish');
59
79
  await orchestrator.startPhase(payload, 'active', 'subagent.finish');
60
80
  },
61
- });
81
+
82
+ onScheduleStart: (payload) => orchestrator.startPhase(payload, 'schedule_start', 'schedule.start'),
83
+ onScheduleFinish: (payload) => orchestrator.stopPhase(payload, 'schedule_start', 'schedule.finish'),
84
+ onScheduleError: async (payload) => {
85
+ await orchestrator.stopPhase(payload, 'schedule_start', 'schedule.error');
86
+ await orchestrator.startPhase(payload, 'schedule_error', 'schedule.error');
87
+ },
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
+ );
62
110
  }
63
111
 
64
112
  export function mountActivityFeedbackService(
@@ -72,10 +120,15 @@ export function mountActivityFeedbackService(
72
120
  });
73
121
  }
74
122
 
123
+ export type ActivityFeedbackLogger = {
124
+ debug: (msg: string, ...args: unknown[]) => void;
125
+ error: (msg: string, ...args: unknown[]) => void;
126
+ };
127
+
75
128
  export interface CreateActivityFeedbackOrchestratorOptions {
76
129
  serviceConfig: ActivityFeedbackServiceConfig;
77
130
  access: ActivityFeedbackEndpointAccess;
78
- logger: Plugin['logger'];
131
+ logger: ActivityFeedbackLogger;
79
132
  }
80
133
 
81
134
  export function createActivityFeedbackOrchestrator(
@@ -96,3 +149,16 @@ export function createActivityFeedbackOrchestratorFromPlugin(
96
149
  logger: plugin.logger,
97
150
  });
98
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/config.ts CHANGED
@@ -6,6 +6,10 @@ export interface ActivityFeedbackServiceConfig {
6
6
  defaults?: ActivityFeedbackConfig;
7
7
  platforms?: Record<string, ActivityFeedbackConfig>;
8
8
  endpoints?: Record<string, ActivityFeedbackConfig>;
9
+ /** Schedule turn 专用相位配置 */
10
+ schedule?: {
11
+ phases?: Partial<Record<'start' | 'error' | 'finish', import('@zhin.js/agent').ActivityFeedbackScenePhases>>;
12
+ };
9
13
  }
10
14
 
11
15
  function mergePhaseScene(
package/src/executor.ts CHANGED
@@ -1,14 +1,6 @@
1
1
  import type { Adapter } from 'zhin.js';
2
- import {
3
- enableActivityFeedbackForBot,
4
- isGenericActivityFeedbackManager,
5
- type ActivityFeedbackManager,
6
- type ActivityFeedbackPhase,
7
- type EndpointWithActivityFeedback,
8
- type PlatformActivityFeedbackManager,
9
- type ResolvedActivityFeedbackPhaseConfig,
10
- } from '@zhin.js/agent';
11
- import type { ActivityFeedbackEventContext } from '@zhin.js/agent';
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';
12
4
 
13
5
  /** IM 侧 endpoint 访问 seam(便于测试注入 fake) */
14
6
  export interface ActivityFeedbackEndpointAccess {
@@ -31,6 +23,135 @@ export function createRootEndpointAccess(root: {
31
23
  };
32
24
  }
33
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 endpoint = {
73
+ $id: endpointId,
74
+ // Prefer real OutboundHost.recall when available (icqq RECALL_MSG).
75
+ $recallMessage: async (messageId: string) => {
76
+ if (outbound.recall) {
77
+ try {
78
+ await outbound.recall({ adapter: platform, endpointId, messageId });
79
+ return;
80
+ } catch (error) {
81
+ logger?.debug(
82
+ `[ActivityFeedback] outbound recall failed (${key}):`,
83
+ error instanceof Error ? error.message : String(error),
84
+ );
85
+ return;
86
+ }
87
+ }
88
+ logger?.debug(
89
+ `[ActivityFeedback] recall not supported via OutboundHost (${key}, messageId=${messageId})`,
90
+ );
91
+ },
92
+ $addReaction: outbound.addReaction
93
+ ? async (
94
+ messageId: string,
95
+ emoji: string,
96
+ hint?: { sceneType?: 'private' | 'group' | 'channel'; channelId?: string },
97
+ ) => outbound.addReaction!({
98
+ adapter: platform,
99
+ endpointId,
100
+ messageId,
101
+ emoji,
102
+ sceneType: hint?.sceneType,
103
+ channelId: hint?.channelId,
104
+ })
105
+ : undefined,
106
+ $removeReaction: outbound.removeReaction
107
+ ? async (messageId: string, reactionId: string) => {
108
+ await outbound.removeReaction!({
109
+ adapter: platform,
110
+ endpointId,
111
+ messageId,
112
+ reactionId,
113
+ });
114
+ }
115
+ : undefined,
116
+ } as EndpointWithActivityFeedback;
117
+ const adapter = {
118
+ sendMessage: async (options: {
119
+ type?: string;
120
+ id?: string;
121
+ content?: unknown;
122
+ }) => {
123
+ const text = stringifySendContent(options.content);
124
+ if (!text || !options.id) return null;
125
+ try {
126
+ const messageId = await outbound.send({
127
+ adapter: platform,
128
+ endpointId,
129
+ channelType: options.type || 'private',
130
+ channelId: options.id,
131
+ content: text,
132
+ });
133
+ // Prefer real id; fall back to a sentinel so MessageTypingIndicator
134
+ // keeps the phase active until stop (recall is a no-op here).
135
+ return messageId || `outbound:${Date.now()}`;
136
+ } catch (error) {
137
+ logger?.debug(
138
+ `[ActivityFeedback] outbound send failed (${key}):`,
139
+ error instanceof Error ? error.message : String(error),
140
+ );
141
+ return null;
142
+ }
143
+ },
144
+ endpoints: {
145
+ get: (id: string) => (id === endpointId ? endpoint : undefined),
146
+ },
147
+ };
148
+ const resolved = { endpoint, adapter: adapter as unknown as Adapter };
149
+ cache.set(key, resolved);
150
+ return resolved;
151
+ },
152
+ };
153
+ }
154
+
34
155
  interface PhaseDriver {
35
156
  start(
36
157
  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.info('[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 default plugin;
23
+ export {
24
+ createNoopEndpointAccess,
25
+ createOutboundEndpointAccess,
26
+ createRootEndpointAccess,
27
+ } from './executor.js';
@@ -1,5 +1,6 @@
1
1
  import {
2
2
  toActivityFeedbackEventContext,
3
+ isActivityFeedbackEnabled,
3
4
  type AIEventPayload,
4
5
  type ActivityFeedbackPhase,
5
6
  } from '@zhin.js/agent';
@@ -16,6 +17,8 @@ export class ActivityFeedbackOrchestrator {
16
17
  ) {}
17
18
 
18
19
  async startPhase(payload: AIEventPayload, phase: ActivityFeedbackPhase, reason: string): Promise<void> {
20
+ const gatePhase = phase as import('@zhin.js/agent').ActivityFeedbackGatePhase;
21
+ if (!isActivityFeedbackEnabled(payload, gatePhase)) return;
19
22
  const ctx = toActivityFeedbackEventContext(payload);
20
23
  if (!ctx) return;
21
24
 
package/lib/context.d.ts DELETED
@@ -1,21 +0,0 @@
1
- import type { AIEventPayload, TypingIndicatorOptions } from '@zhin.js/agent';
2
- export type ActivitySceneType = 'private' | 'group' | 'channel';
3
- /** 单次 phase 操作的归一化上下文(由 AI 事件 payload 解析而来) */
4
- export interface ActivityFeedbackContext {
5
- platform: string;
6
- endpointId: string;
7
- sessionId: string;
8
- messageId?: string;
9
- sceneType: ActivitySceneType;
10
- userId?: string;
11
- groupId?: string;
12
- options: TypingIndicatorOptions;
13
- }
14
- export declare function resolveSceneType(payload: AIEventPayload): ActivitySceneType;
15
- export declare function resolveTargets(payload: AIEventPayload, sceneType: ActivitySceneType): {
16
- userId?: string;
17
- groupId?: string;
18
- };
19
- /** 将 AI 事件转为可执行的 activity 上下文;缺少定位信息时返回 null */
20
- export declare function toActivityContext(payload: AIEventPayload): ActivityFeedbackContext | null;
21
- //# sourceMappingURL=context.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAE7E,MAAM,MAAM,iBAAiB,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,CAAC;AAEhE,+CAA+C;AAC/C,MAAM,WAAW,uBAAuB;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,iBAAiB,CAAC;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,sBAAsB,CAAC;CACjC;AAID,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,cAAc,GAAG,iBAAiB,CAO3E;AAED,wBAAgB,cAAc,CAC5B,OAAO,EAAE,cAAc,EACvB,SAAS,EAAE,iBAAiB,GAC3B;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAwBvC;AAED,gDAAgD;AAChD,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,cAAc,GAAG,uBAAuB,GAAG,IAAI,CAyBzF"}
package/lib/context.js DELETED
@@ -1,65 +0,0 @@
1
- const SYNTHETIC_SENDER_IDS = new Set(['system', 'cron', 'assistant']);
2
- export function resolveSceneType(payload) {
3
- const scope = payload.scope;
4
- if (scope === 'group' || scope === 'channel' || scope === 'private')
5
- return scope;
6
- const sceneId = payload.sceneId ?? '';
7
- if (sceneId.startsWith('group:'))
8
- return 'group';
9
- if (sceneId.startsWith('channel:'))
10
- return 'channel';
11
- return 'private';
12
- }
13
- export function resolveTargets(payload, sceneType) {
14
- const { sceneId, userId, sessionId } = payload;
15
- const parts = sessionId.split(':').filter((p) => p.length > 0);
16
- let resolvedUserId = userId;
17
- let groupId;
18
- if (sceneType === 'group' || sceneType === 'channel') {
19
- groupId = sceneId?.replace(/^(group|channel):/, '') || sceneId;
20
- if (!groupId && parts.length >= 3)
21
- groupId = parts[1];
22
- if (!resolvedUserId && parts.length >= 3)
23
- resolvedUserId = parts[parts.length - 1];
24
- }
25
- else {
26
- if (sceneId?.startsWith('private:'))
27
- resolvedUserId = sceneId.slice('private:'.length);
28
- else if ((!resolvedUserId || SYNTHETIC_SENDER_IDS.has(resolvedUserId))
29
- && sceneId
30
- && !SYNTHETIC_SENDER_IDS.has(sceneId)) {
31
- resolvedUserId = sceneId;
32
- }
33
- else if (!resolvedUserId && parts.length >= 2) {
34
- resolvedUserId = parts.length >= 3 ? parts[parts.length - 1] : parts[1];
35
- }
36
- }
37
- return { userId: resolvedUserId, groupId };
38
- }
39
- /** 将 AI 事件转为可执行的 activity 上下文;缺少定位信息时返回 null */
40
- export function toActivityContext(payload) {
41
- const { platform, endpointId, sessionId } = payload;
42
- if (!platform || !endpointId)
43
- return null;
44
- const sceneType = resolveSceneType(payload);
45
- const targets = resolveTargets(payload, sceneType);
46
- return {
47
- platform,
48
- endpointId,
49
- sessionId,
50
- messageId: payload.messageId,
51
- sceneType,
52
- userId: targets.userId,
53
- groupId: targets.groupId,
54
- options: {
55
- platform,
56
- endpointId,
57
- sessionId,
58
- messageId: payload.messageId,
59
- sceneType,
60
- userId: targets.userId,
61
- groupId: targets.groupId,
62
- },
63
- };
64
- }
65
- //# sourceMappingURL=context.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"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"}
@@ -1,7 +0,0 @@
1
- /**
2
- * Activity Feedback — AI 生命周期事件绑定(服务插件)
3
- */
4
- import type { Plugin } from 'zhin.js';
5
- import { type ActivityFeedbackServiceConfig } from './config.js';
6
- export declare function mountActivityFeedbackBinder(plugin: Plugin, serviceConfig: ActivityFeedbackServiceConfig): void;
7
- //# sourceMappingURL=register-binder.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"register-binder.d.ts","sourceRoot":"","sources":["../src/register-binder.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAW,MAAM,EAAE,MAAM,SAAS,CAAC;AAc/C,OAAO,EACL,KAAK,6BAA6B,EAEnC,MAAM,aAAa,CAAC;AA6MrB,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,6BAA6B,GAC3C,IAAI,CA4DN"}