@zhin.js/service-activity-feedback 1.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/src/index.ts ADDED
@@ -0,0 +1,41 @@
1
+ /**
2
+ * @zhin.js/service-activity-feedback
3
+ */
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
+ export {
28
+ bindActivityFeedbackToAIEvents,
29
+ createActivityFeedbackOrchestrator,
30
+ createActivityFeedbackOrchestratorFromPlugin,
31
+ mountActivityFeedbackService,
32
+ } from './ai-event-binder.js';
33
+ export { ActivityFeedbackOrchestrator } from './orchestrator.js';
34
+ export { ActivityFeedbackPolicy } from './policy.js';
35
+ export {
36
+ loadActivityFeedbackServiceConfig,
37
+ resolveActivityFeedbackForTarget,
38
+ type ActivityFeedbackServiceConfig,
39
+ } from './config.js';
40
+ export type { ActivityFeedbackEndpointAccess } from './executor.js';
41
+ export default plugin;
@@ -0,0 +1,55 @@
1
+ import {
2
+ toActivityFeedbackEventContext,
3
+ type AIEventPayload,
4
+ type ActivityFeedbackPhase,
5
+ } from '@zhin.js/agent';
6
+ import { ActivityFeedbackExecutor } from './executor.js';
7
+ import { ActivityFeedbackPolicy } from './policy.js';
8
+
9
+ type Logger = { debug: (msg: string, ...args: unknown[]) => void; error: (msg: string, ...args: unknown[]) => void };
10
+
11
+ export class ActivityFeedbackOrchestrator {
12
+ constructor(
13
+ private readonly policy: ActivityFeedbackPolicy,
14
+ private readonly executor: ActivityFeedbackExecutor,
15
+ private readonly log: Logger,
16
+ ) {}
17
+
18
+ async startPhase(payload: AIEventPayload, phase: ActivityFeedbackPhase, reason: string): Promise<void> {
19
+ const ctx = toActivityFeedbackEventContext(payload);
20
+ if (!ctx) return;
21
+
22
+ try {
23
+ const resolution = this.policy.resolvePhase(ctx.platform, ctx.endpointId, phase, ctx.sceneType);
24
+ if (resolution.kind !== 'active') return;
25
+
26
+ this.log.debug(`[ActivityFeedback] start ${phase} (${reason}) session=${ctx.sessionId}`);
27
+ await this.executor.start(ctx, phase, resolution.config);
28
+ } catch (error) {
29
+ this.log.error(`[ActivityFeedback] start ${phase} failed (${reason}):`, error);
30
+ }
31
+ }
32
+
33
+ async stopPhase(payload: AIEventPayload, phase: ActivityFeedbackPhase, reason: string): Promise<void> {
34
+ const ctx = toActivityFeedbackEventContext(payload);
35
+ if (!ctx) return;
36
+
37
+ try {
38
+ this.log.debug(`[ActivityFeedback] stop ${phase} (${reason}) session=${ctx.sessionId}`);
39
+ await this.executor.stop(ctx, phase);
40
+ } catch (error) {
41
+ this.log.error(`[ActivityFeedback] stop ${phase} failed (${reason}):`, error);
42
+ }
43
+ }
44
+
45
+ async updateThinkingText(payload: AIEventPayload, text: string): Promise<void> {
46
+ const ctx = toActivityFeedbackEventContext(payload);
47
+ if (!ctx || !text) return;
48
+
49
+ try {
50
+ await this.executor.updateThinkingText(ctx, text);
51
+ } catch (error) {
52
+ this.log.error('[ActivityFeedback] thinking update failed:', error);
53
+ }
54
+ }
55
+ }
package/src/policy.ts ADDED
@@ -0,0 +1,51 @@
1
+ import {
2
+ resolveActivityFeedbackPhaseConfig,
3
+ type ActivityFeedbackPhase,
4
+ type ActivitySceneType,
5
+ type ResolvedActivityFeedbackPhaseConfig,
6
+ } from '@zhin.js/agent';
7
+ import {
8
+ type ActivityFeedbackServiceConfig,
9
+ mergeActivityFeedbackLayers,
10
+ loadActivityFeedbackServiceConfig,
11
+ } from './config.js';
12
+
13
+ export type { ActivityFeedbackServiceConfig } from './config.js';
14
+ export { loadActivityFeedbackServiceConfig, resolveActivityFeedbackForTarget } from './config.js';
15
+
16
+ export type PhaseResolution =
17
+ | { kind: 'disabled' }
18
+ | { kind: 'none' }
19
+ | { kind: 'active'; config: ResolvedActivityFeedbackPhaseConfig };
20
+
21
+ export class ActivityFeedbackPolicy {
22
+ constructor(private readonly service: ActivityFeedbackServiceConfig) {}
23
+
24
+ resolvePhase(
25
+ platform: string,
26
+ endpointId: string,
27
+ phase: ActivityFeedbackPhase,
28
+ sceneType: ActivitySceneType,
29
+ ): PhaseResolution {
30
+ if (this.service.enabled === false) {
31
+ return { kind: 'disabled' };
32
+ }
33
+
34
+ const policy = mergeActivityFeedbackLayers(
35
+ this.service.defaults,
36
+ this.service.platforms?.[platform],
37
+ this.service.endpoints?.[`${platform}:${endpointId}`],
38
+ );
39
+
40
+ if (policy?.enabled === false) {
41
+ return { kind: 'disabled' };
42
+ }
43
+
44
+ const config = resolveActivityFeedbackPhaseConfig(platform, policy, phase, sceneType);
45
+ if (config.type === 'none') {
46
+ return { kind: 'none' };
47
+ }
48
+
49
+ return { kind: 'active', config };
50
+ }
51
+ }