refactor(pipelines-audio): better token processing pipeline, ACT, DELAY, CALL, unified
This commit is contained in:
+1
@@ -110,6 +110,7 @@ const { context: iframeContext, iframeLoadError, onIframeError, onIframeLoad } =
|
||||
|
||||
const handled = await publishWidgetSparkNotifyReaction(event, {
|
||||
dispatchSparkNotifyReaction: options => contextBridgeStore.dispatchSparkNotifyReaction(options),
|
||||
dispatchSparkNotifyPerformance: options => contextBridgeStore.dispatchSparkNotifyPerformance(options),
|
||||
emit: (eventDefinition, payload) => iframeContext.emit(eventDefinition, payload),
|
||||
})
|
||||
if (handled) {
|
||||
|
||||
+76
@@ -129,4 +129,80 @@ describe('publishWidgetSparkNotifyReaction', () => {
|
||||
headline: 'Quick move',
|
||||
}))
|
||||
})
|
||||
|
||||
/**
|
||||
* @example
|
||||
* await publishWidgetSparkNotifyReaction(eventWithCalls, options)
|
||||
* expect(options.dispatchSparkNotifyPerformance).toHaveBeenCalledWith(expect.objectContaining({ timeoutMs: 15000 }))
|
||||
*/
|
||||
it('uses awaitable performance notify when the widget declares calls', async () => {
|
||||
const dispatchSparkNotifyReaction = vi.fn(async () => 'unused')
|
||||
const dispatchSparkNotifyPerformance = vi.fn(async () => ({
|
||||
type: 'called' as const,
|
||||
name: 'chess.play',
|
||||
reaction: 'Played.',
|
||||
}))
|
||||
const emit = vi.fn()
|
||||
|
||||
const result = await publishWidgetSparkNotifyReaction({
|
||||
route: {
|
||||
namespace: 'airi.plugin.game.chess.commentary',
|
||||
name: 'request',
|
||||
},
|
||||
payload: {
|
||||
requestId: 'req-call',
|
||||
fallbackResponseText: 'fallback',
|
||||
calls: [
|
||||
{
|
||||
name: 'chess.play',
|
||||
prompt: 'Play the prepared chess reply.',
|
||||
examples: [
|
||||
'<|CALL ["chess.play", {"move":"Nf3"}]|>',
|
||||
],
|
||||
},
|
||||
],
|
||||
timeoutMs: 15000,
|
||||
sparkNotify: {
|
||||
kind: 'ping',
|
||||
urgency: 'immediate',
|
||||
headline: 'A move is ready',
|
||||
destinations: ['character'],
|
||||
},
|
||||
},
|
||||
}, {
|
||||
dispatchSparkNotifyReaction,
|
||||
dispatchSparkNotifyPerformance,
|
||||
emit,
|
||||
})
|
||||
|
||||
expect(result).toBe(true)
|
||||
expect(dispatchSparkNotifyReaction).not.toHaveBeenCalled()
|
||||
expect(dispatchSparkNotifyPerformance).toHaveBeenCalledWith(expect.objectContaining({
|
||||
headline: 'A move is ready',
|
||||
fallbackResponseText: 'fallback',
|
||||
timeoutMs: 15000,
|
||||
calls: [
|
||||
{
|
||||
manifest: {
|
||||
name: 'chess.play',
|
||||
prompt: 'Play the prepared chess reply.',
|
||||
examples: [
|
||||
'<|CALL ["chess.play", {"move":"Nf3"}]|>',
|
||||
],
|
||||
},
|
||||
handler: expect.any(Function),
|
||||
},
|
||||
],
|
||||
}))
|
||||
expect(emit).toHaveBeenCalledWith(widgetsIframeBroadcastEvent, expect.objectContaining({
|
||||
payload: expect.objectContaining({
|
||||
requestId: 'req-call',
|
||||
text: 'Played.',
|
||||
performance: {
|
||||
type: 'called',
|
||||
name: 'chess.play',
|
||||
},
|
||||
}),
|
||||
}))
|
||||
})
|
||||
})
|
||||
|
||||
+34
-3
@@ -1,11 +1,12 @@
|
||||
import type { SparkNotifyReactionOptions } from '@proj-airi/stage-ui/stores/mods/api/spark-notify-reaction'
|
||||
import type { SparkNotifyPerformanceResult, SparkNotifyReactionOptions } from '@proj-airi/stage-ui/stores/mods/api/spark-notify-reaction'
|
||||
|
||||
import { widgetsIframeBroadcastEvent } from '@proj-airi/plugin-sdk-tamagotchi/widgets'
|
||||
import { sparkNotifyReactionOptionsSchema } from '@proj-airi/stage-ui/stores/mods/api/spark-notify-reaction'
|
||||
import { looseObject, nonEmpty, optional, pipe, record, safeParse, string, trim, unknown } from 'valibot'
|
||||
import { array, finite, looseObject, nonEmpty, number, optional, pipe, record, safeParse, string, trim, unknown } from 'valibot'
|
||||
|
||||
interface PublishWidgetSparkNotifyReactionOptions {
|
||||
dispatchSparkNotifyReaction: (options: SparkNotifyReactionOptions) => Promise<string>
|
||||
dispatchSparkNotifyPerformance?: (options: SparkNotifyReactionOptions) => Promise<SparkNotifyPerformanceResult>
|
||||
emit: (event: typeof widgetsIframeBroadcastEvent, payload: Record<string, unknown>) => void
|
||||
}
|
||||
|
||||
@@ -29,6 +30,12 @@ const widgetSparkNotifyEventSchema = looseObject({
|
||||
// because it owns the user-facing fallback for its current UI state.
|
||||
fallbackResponseText: string(),
|
||||
responseRoute: optional(record(string(), unknown())),
|
||||
calls: optional(array(looseObject({
|
||||
name: pipe(string(), trim(), nonEmpty()),
|
||||
prompt: pipe(string(), trim(), nonEmpty()),
|
||||
examples: optional(array(string())),
|
||||
}))),
|
||||
timeoutMs: optional(pipe(number(), finite())),
|
||||
sparkNotify: looseObject({}),
|
||||
}),
|
||||
})
|
||||
@@ -60,6 +67,8 @@ function createSparkNotifyReactionOptions(event: Record<string, unknown>) {
|
||||
return {
|
||||
requestId: payload.requestId,
|
||||
responseRoute,
|
||||
calls: payload.calls,
|
||||
timeoutMs: payload.timeoutMs,
|
||||
reactionOptions: reactionOptionsResult.output satisfies SparkNotifyReactionOptions,
|
||||
}
|
||||
}
|
||||
@@ -89,13 +98,35 @@ export async function publishWidgetSparkNotifyReaction(
|
||||
return false
|
||||
}
|
||||
|
||||
const text = await options.dispatchSparkNotifyReaction(request.reactionOptions)
|
||||
const widgetCallManifests = request.calls ?? []
|
||||
const performance = widgetCallManifests.length > 0 && options.dispatchSparkNotifyPerformance
|
||||
? await options.dispatchSparkNotifyPerformance({
|
||||
...request.reactionOptions,
|
||||
timeoutMs: request.timeoutMs,
|
||||
calls: widgetCallManifests.map(manifest => ({
|
||||
manifest,
|
||||
handler: async () => undefined,
|
||||
})),
|
||||
})
|
||||
: undefined
|
||||
|
||||
const text = performance
|
||||
? performance.reaction
|
||||
: await options.dispatchSparkNotifyReaction(request.reactionOptions)
|
||||
|
||||
options.emit(widgetsIframeBroadcastEvent, {
|
||||
route: request.responseRoute,
|
||||
payload: {
|
||||
...(request.requestId ? { requestId: request.requestId } : {}),
|
||||
text,
|
||||
...(performance
|
||||
? {
|
||||
performance: {
|
||||
type: performance.type,
|
||||
name: performance.name,
|
||||
},
|
||||
}
|
||||
: {}),
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
import { cwd } from 'node:process'
|
||||
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
|
||||
import { loadEnv } from 'vite'
|
||||
import { defineConfig } from 'vitest/config'
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [
|
||||
vue(),
|
||||
],
|
||||
test: {
|
||||
env: loadEnv('test', cwd(), ''),
|
||||
include: ['src/**/*.test.ts', 'scripts/**/*.test.ts'],
|
||||
|
||||
Reference in New Issue
Block a user