File size: 1,527 Bytes
e1bb50d | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | import type { VRMSceneHandle } from './components/VRMScene'
/** VersperClaw server base URL */
export const SERVER_URL = 'http://127.0.0.1:3456'
/** Base path for the Friend VRM plugin API */
export const FRIEND_API = `${SERVER_URL}/plugins/friend`
let sceneHandle: VRMSceneHandle | null = null
export function bindScene(handle: VRMSceneHandle | null) {
sceneHandle = handle
}
/**
* POST to a server API. If the request body contains an `emotion` field,
* the VRM expression will automatically change to match.
*
* Body example:
* { emotion: "happy", message: "hello", ... }
*
* Supported emotions: happy, sad, angry, surprised, think, neutral
*
* Optional fields:
* emotionDuration — ms, auto-reset to neutral after this time
* emotionIntensity — 0~1, defaults to 1
*/
export async function postApi<T = any>(url: string, body: Record<string, any>): Promise<T> {
// Trigger emotion from the request body
if (body.emotion && sceneHandle) {
const duration = body.emotionDuration as number | undefined
const intensity = body.emotionIntensity as number | undefined
if (duration) {
sceneHandle.setEmotionWithReset(body.emotion, duration, intensity)
} else {
sceneHandle.setEmotion(body.emotion, intensity)
}
}
const res = await fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body),
})
if (!res.ok) {
throw new Error(`API error: ${res.status} ${res.statusText}`)
}
return res.json()
}
|