feat(server-protocol): introduce shared protocol types for AIRI server clients and frontends

- Added package.json for @proj-airi/server-protocol with necessary configurations.
- Implemented chat event types including WireMessage, SendMessagesRequest, and PullMessagesRequest.
- Defined WebSocket event types and structures for better integration with AIRI components.
- Updated server-runtime and server-sdk to utilize the new server-protocol package.
- Refactored imports across various packages to replace server-shared types with server-protocol types.
- Enhanced type definitions and added TypeScript configurations for better development experience.
This commit is contained in:
RainbowBird
2026-03-28 02:25:44 +08:00
committed by RainbowBird
parent c0d0e22f12
commit ba3d66de86
58 changed files with 329 additions and 195 deletions
+6 -3
View File
@@ -4,17 +4,20 @@ WORKDIR /app
RUN corepack enable
COPY pnpm-lock.yaml pnpm-workspace.yaml package.json ./
COPY pnpm-lock.yaml pnpm-workspace.yaml package.json tsconfig.json ./
COPY patches/ ./patches/
COPY apps/server apps/server
COPY packages/server-protocol packages/server-protocol
COPY packages/server-schema packages/server-schema
COPY packages/server-sdk packages/server-sdk
COPY packages/plugin-protocol packages/plugin-protocol
RUN --mount=type=cache,id=pnpm-store,target=/root/.pnpm-store \
pnpm install --frozen-lockfile --ignore-scripts
RUN pnpm -F @proj-airi/server-schema run build
RUN pnpm -F @proj-airi/server-sdk run build
RUN pnpm -F @proj-airi/server-protocol run build
RUN pnpm -F @proj-airi/plugin-protocol run build
RUN pnpm -F @proj-airi/server run build
EXPOSE 3000
+36 -1
View File
@@ -30,10 +30,11 @@ services:
timeout: 5s
retries: 10
server:
api:
build:
context: ../..
dockerfile: apps/server/Dockerfile
command: ['pnpm', '-F', '@proj-airi/server', 'run', 'server', 'api']
depends_on:
db:
condition: service_healthy
@@ -52,6 +53,40 @@ services:
timeout: 5s
retries: 5
outbox-dispatcher:
build:
context: ../..
dockerfile: apps/server/Dockerfile
command: ['pnpm', '-F', '@proj-airi/server', 'run', 'server', 'outbox-dispatcher']
depends_on:
db:
condition: service_healthy
redis:
condition: service_healthy
env_file:
- path: .env
required: false
- path: .env.local
required: false
restart: unless-stopped
cache-sync-consumer:
build:
context: ../..
dockerfile: apps/server/Dockerfile
command: ['pnpm', '-F', '@proj-airi/server', 'run', 'server', 'cache-sync-consumer']
depends_on:
db:
condition: service_healthy
redis:
condition: service_healthy
env_file:
- path: .env
required: false
- path: .env.local
required: false
restart: unless-stopped
volumes:
db_data:
driver: local
@@ -125,7 +125,7 @@
- WS 广播不具备持久化和重放能力
- 真正补齐消息还是靠 `pullMessages`
- 广播只是加速客户端同步
- 广播只是为了降低拉取延迟,不代表存在旧式 `sync` 端点
## OpenTelemetry
+3 -1
View File
@@ -9,6 +9,7 @@
"dev": "pnpm run apply:env -- tsx --watch src/bin/run.ts api",
"start": "pnpm run apply:env -- tsx src/bin/run.ts api",
"server": "pnpm run apply:env -- tsx src/bin/run.ts",
"build": "tsc -b",
"typecheck": "tsc --noEmit",
"db:generate": "drizzle-kit generate",
"db:push": "pnpm run apply:env -- drizzle-kit push"
@@ -37,9 +38,10 @@
"@opentelemetry/sdk-trace-node": "^2.6.1",
"@opentelemetry/semantic-conventions": "^1.40.0",
"@proj-airi/drizzle-orm-browser-migrator": "^0.1.6",
"@proj-airi/server-protocol": "workspace:*",
"@proj-airi/server-schema": "workspace:*",
"@proj-airi/server-sdk": "workspace:",
"better-auth": "^1.5.6",
"cac": "catalog:",
"drizzle-orm": "^0.45.1",
"drizzle-valibot": "catalog:",
"hono": "catalog:",
+9 -6
View File
@@ -1,6 +1,6 @@
import { describe, expect, it } from 'vitest'
import { getServerCliHelpText, parseServerRole } from '../run'
import { createServerCli, parseServerRole } from '../run'
describe('server cli', () => {
it('parses supported roles', () => {
@@ -14,10 +14,13 @@ describe('server cli', () => {
expect(parseServerRole(['unknown'])).toBeNull()
})
it('returns help text that lists all supported roles', () => {
expect(getServerCliHelpText()).toContain('Usage: server <role>')
expect(getServerCliHelpText()).toContain('api')
expect(getServerCliHelpText()).toContain('cache-sync-consumer')
expect(getServerCliHelpText()).toContain('outbox-dispatcher')
it('registers all supported roles with cac', () => {
const cli = createServerCli()
expect(cli.commands.map(command => command.name)).toEqual(expect.arrayContaining([
'api',
'cache-sync-consumer',
'outbox-dispatcher',
]))
})
})
+40 -24
View File
@@ -5,6 +5,7 @@ import process from 'node:process'
import { pathToFileURL } from 'node:url'
import { errorMessageFrom } from '@moeru/std'
import { cac } from 'cac'
import { runApiServer } from '../app'
import { handleCacheSyncMessage, runBillingEventsConsumer } from './run-billing-events-consumer'
@@ -14,26 +15,6 @@ const serverRoles = ['api', 'cache-sync-consumer', 'outbox-dispatcher'] as const
type ServerRole = typeof serverRoles[number]
export function getServerCliHelpText(): string {
return [
'Usage: server <role>',
'',
'Roles:',
' api Start the HTTP/WebSocket API process',
' cache-sync-consumer Start the cache-sync Redis Streams consumer',
' outbox-dispatcher Publish DB outbox events to Redis Streams',
].join('\n')
}
export function parseServerRole(args: string[]): ServerRole | null {
const role = args[0]
if (!role) {
return null
}
return serverRoles.includes(role as ServerRole) ? role as ServerRole : null
}
async function runServerRole(role: ServerRole): Promise<void> {
switch (role) {
case 'api':
@@ -51,15 +32,50 @@ async function runServerRole(role: ServerRole): Promise<void> {
}
}
async function main(): Promise<void> {
const role = parseServerRole(process.argv.slice(2))
export function createServerCli() {
const cli = cac('server')
cli
.usage('<role>')
.command('api', 'Start the HTTP/WebSocket API process')
.action(() => runServerRole('api'))
cli
.command('cache-sync-consumer', 'Start the cache-sync Redis Streams consumer')
.action(() => runServerRole('cache-sync-consumer'))
cli
.command('outbox-dispatcher', 'Publish DB outbox events to Redis Streams')
.action(() => runServerRole('outbox-dispatcher'))
cli.help()
return cli
}
export function parseServerRole(args: string[]): ServerRole | null {
const cli = createServerCli()
cli.parse(['node', 'server', ...args], { run: false })
const role = cli.matchedCommandName
if (!role) {
process.stdout.write(`${getServerCliHelpText()}\n`)
return null
}
return serverRoles.includes(role as ServerRole) ? role as ServerRole : null
}
async function main(): Promise<void> {
const cli = createServerCli()
cli.parse(process.argv, { run: false })
if (!cli.matchedCommand) {
cli.outputHelp()
process.exitCode = 1
return
}
await runServerRole(role)
await cli.runMatchedCommand()
}
function isExecutedAsMainModule(): boolean {
+1 -5
View File
@@ -38,7 +38,6 @@ export interface AuthMetrics {
}
export interface EngagementMetrics {
chatSync: Counter
chatMessages: Counter
characterCreated: Counter
characterDeleted: Counter
@@ -200,11 +199,8 @@ export function initOtel(env: Env): OtelInstance | undefined {
// Engagement metrics
const engagement: EngagementMetrics = {
chatSync: meter.createCounter('chat.sync', {
description: 'Number of chat sync operations',
}),
chatMessages: meter.createCounter('chat.messages', {
description: 'Number of chat messages synced',
description: 'Number of chat messages written or pulled',
}),
characterCreated: meter.createCounter('character.created', {
description: 'Number of characters created',
+1 -1
View File
@@ -6,7 +6,7 @@ import type { ChatService } from '../services/chats'
import { useLogger } from '@guiiai/logg'
import { defineInvokeHandler } from '@moeru/eventa'
import { newMessages, pullMessages, sendMessages } from '@proj-airi/server-sdk'
import { newMessages, pullMessages, sendMessages } from '@proj-airi/server-protocol'
import { createPeerHooks, wsDisconnectedEvent } from '../libs/eventa-hono-adapter'
+1 -2
View File
@@ -1,4 +1,4 @@
import type { MessageRole, WireMessage } from '@proj-airi/server-sdk'
import type { MessageRole, WireMessage } from '@proj-airi/server-protocol'
import type { Database } from '../libs/db'
import type { EngagementMetrics } from '../libs/otel'
@@ -281,7 +281,6 @@ export function createChatService(db: Database, metrics?: EngagementMetrics | nu
}
})
metrics?.chatSync.add(1)
if (result.totalCount > 0) {
metrics?.chatMessages.add(result.totalCount)
}
+10
View File
@@ -8,8 +8,17 @@
"ESNext"
],
"useDefineForClassFields": true,
"baseUrl": ".",
"module": "ESNext",
"moduleResolution": "Bundler",
"paths": {
"@proj-airi/server-protocol": [
"../../packages/server-protocol/src/index.ts"
],
"@proj-airi/server-protocol/*": [
"../../packages/server-protocol/src/*"
]
},
"resolveJsonModule": true,
"types": [
"vitest",
@@ -20,6 +29,7 @@
"skipLibCheck": true
},
"include": [
"../../packages/server-protocol/src/**/*.ts",
"src/**/*.ts",
"src/**/*.d.ts"
]
-1
View File
@@ -42,7 +42,6 @@
"dependencies": {
"@moeru/eventa": "catalog:",
"@proj-airi/plugin-protocol": "workspace:*",
"@proj-airi/server-shared": "workspace:*",
"nanoid": "catalog:",
"valibot": "^1.3.1",
"xstate": "^5.28.0"
+20
View File
@@ -0,0 +1,20 @@
# @proj-airi/server-protocol
Shared protocol types for AIRI server runtimes, SDKs, and frontend consumers.
## Usage
```shell
ni @proj-airi/server-protocol -D # from @antfu/ni, can be installed via `npm i -g @antfu/ni`
pnpm i @proj-airi/server-protocol -D
yarn i @proj-airi/server-protocol -D
npm i @proj-airi/server-protocol -D
```
```typescript
import type { WebSocketEvents } from '@proj-airi/server-protocol'
```
## License
[MIT](../../LICENSE)
+43
View File
@@ -0,0 +1,43 @@
{
"name": "@proj-airi/server-protocol",
"type": "module",
"version": "0.9.0-alpha.22",
"description": "Shared protocol types for AIRI server clients, frontends, and runtimes",
"author": {
"name": "Moeru AI Project AIRI Team",
"email": "airi@moeru.ai",
"url": "https://github.com/moeru-ai"
},
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/moeru-ai/airi.git",
"directory": "packages/server-protocol"
},
"exports": {
".": {
"types": "./dist/index.d.mts",
"default": "./dist/index.mjs"
},
"./types": {
"types": "./dist/types/index.d.mts",
"default": "./dist/types/index.mjs"
}
},
"main": "./dist/index.mjs",
"types": "./dist/index.d.mts",
"files": [
"README.md",
"dist",
"package.json"
],
"scripts": {
"dev": "pnpm run build",
"build": "tsdown",
"typecheck": "tsc --noEmit"
},
"dependencies": {
"@moeru/eventa": "catalog:",
"@proj-airi/plugin-protocol": "workspace:*"
}
}
@@ -0,0 +1,45 @@
import { defineInvokeEventa, defineOutboundEventa } from '@moeru/eventa'
export interface WireMessage {
id: string
chatId: string
senderId: string | null
role: 'system' | 'user' | 'assistant' | 'tool' | 'error'
content: string
seq: number
createdAt: number
updatedAt: number
}
export type MessageRole = WireMessage['role']
export interface SendMessagesRequest {
chatId: string
messages: { id: string, role: string, content: string }[]
}
export interface SendMessagesResponse {
seq: number
}
export interface PullMessagesRequest {
chatId: string
afterSeq: number
limit?: number
}
export interface PullMessagesResponse {
messages: WireMessage[]
seq: number
}
export interface NewMessagesPayload {
chatId: string
messages: WireMessage[]
fromSeq: number
toSeq: number
}
export const sendMessages = defineInvokeEventa<SendMessagesResponse, SendMessagesRequest>('chat:send-messages')
export const pullMessages = defineInvokeEventa<PullMessagesResponse, PullMessagesRequest>('chat:pull-messages')
export const newMessages = defineOutboundEventa<NewMessagesPayload>('chat:new-messages')
+2
View File
@@ -0,0 +1,2 @@
export * from './events/chat'
export * from './types'
+18
View File
@@ -0,0 +1,18 @@
{
"compilerOptions": {
"target": "ESNext",
"lib": [
"ESNext"
],
"module": "ESNext",
"moduleResolution": "bundler",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"isolatedModules": true,
"verbatimModuleSyntax": true,
"skipLibCheck": true
},
"include": [
"src/**/*.ts"
]
}
+11
View File
@@ -0,0 +1,11 @@
import { defineConfig } from 'tsdown'
export default defineConfig({
entry: {
'index': 'src/index.ts',
'types/index': 'src/types/index.ts',
},
sourcemap: true,
unused: true,
inlineOnly: false,
})
+1
View File
@@ -41,6 +41,7 @@
"dependencies": {
"@guiiai/logg": "catalog:",
"@moeru/std": "catalog:",
"@proj-airi/server-protocol": "workspace:^",
"@proj-airi/server-shared": "workspace:^",
"crossws": "^0.4.4",
"h3": "^2.0.1-rc.19",
+2 -2
View File
@@ -1,4 +1,4 @@
import type { MetadataEventSource, WebSocketEvent } from '@proj-airi/server-shared/types'
import type { MetadataEventSource, WebSocketEvent } from '@proj-airi/server-protocol'
import type {
RouteContext,
@@ -11,11 +11,11 @@ import type { AuthenticatedPeer, Peer } from './types'
import { timingSafeEqual } from 'node:crypto'
import { availableLogLevelStrings, Format, LogLevelString, logLevelStringToLogLevelMap, useLogg } from '@guiiai/logg'
import { MessageHeartbeat, MessageHeartbeatKind, WebSocketEventSource } from '@proj-airi/server-protocol'
import {
createInvalidJsonServerErrorMessage,
ServerErrorMessages,
} from '@proj-airi/server-shared'
import { MessageHeartbeat, MessageHeartbeatKind, WebSocketEventSource } from '@proj-airi/server-shared/types'
import { defineWebSocketHandler, H3 } from 'h3'
import { nanoid } from 'nanoid'
import { parse, stringify } from 'superjson'
@@ -1,4 +1,4 @@
import type { RouteTargetExpression, WebSocketBaseEvent, WebSocketEventOf, WebSocketEvents } from '@proj-airi/server-shared/types'
import type { RouteTargetExpression, WebSocketBaseEvent, WebSocketEventOf, WebSocketEvents } from '@proj-airi/server-protocol'
import type { AuthenticatedPeer } from '../types'
@@ -1,4 +1,4 @@
import type { RouteTargetExpression, WebSocketEvent } from '@proj-airi/server-shared/types'
import type { RouteTargetExpression, WebSocketEvent } from '@proj-airi/server-protocol'
import type { AuthenticatedPeer } from '../types'
@@ -1,4 +1,4 @@
import type { RouteTargetExpression } from '@proj-airi/server-shared/types'
import type { RouteTargetExpression } from '@proj-airi/server-protocol'
import type { AuthenticatedPeer } from '../../types'
+1 -1
View File
@@ -1,4 +1,4 @@
import type { MetadataEventSource } from '@proj-airi/server-shared/types'
import type { MetadataEventSource } from '@proj-airi/server-protocol'
export interface Peer {
/**
+4 -4
View File
@@ -8,11 +8,11 @@
"module": "ESNext",
"moduleResolution": "bundler",
"paths": {
"@proj-airi/server-shared": [
"../server-shared/src/index.ts"
"@proj-airi/server-protocol": [
"../server-protocol/src/index.ts"
],
"@proj-airi/server-shared/*": [
"../server-shared/src/*"
"@proj-airi/server-protocol/*": [
"../server-protocol/src/*"
]
},
"esModuleInterop": true,
+1
View File
@@ -39,6 +39,7 @@
"dependencies": {
"@moeru/eventa": "catalog:",
"@moeru/std": "catalog:",
"@proj-airi/server-protocol": "workspace:^",
"@proj-airi/server-shared": "workspace:^",
"crossws": "^0.4.4",
"superjson": "catalog:"
+2 -2
View File
@@ -6,14 +6,14 @@ import type {
WebSocketEvent,
WebSocketEventOptionalSource,
WebSocketEvents,
} from '@proj-airi/server-shared/types'
} from '@proj-airi/server-protocol'
import WebSocket from 'crossws/websocket'
import superjson from 'superjson'
import { errorMessageFrom, sleep } from '@moeru/std'
import { MessageHeartbeat, MessageHeartbeatKind } from '@proj-airi/server-protocol'
import { isTerminalAuthenticationServerErrorMessage, parseServerErrorMessage } from '@proj-airi/server-shared'
import { MessageHeartbeat, MessageHeartbeatKind } from '@proj-airi/server-shared/types'
export type ClientStatus
= | 'idle'
+1 -45
View File
@@ -1,45 +1 @@
import { defineInvokeEventa, defineOutboundEventa } from '@moeru/eventa'
export interface WireMessage {
id: string
chatId: string
senderId: string | null
role: 'system' | 'user' | 'assistant' | 'tool' | 'error'
content: string
seq: number
createdAt: number
updatedAt: number
}
export type MessageRole = WireMessage['role']
export interface SendMessagesRequest {
chatId: string
messages: { id: string, role: string, content: string }[]
}
export interface SendMessagesResponse {
seq: number
}
export interface PullMessagesRequest {
chatId: string
afterSeq: number
limit?: number
}
export interface PullMessagesResponse {
messages: WireMessage[]
seq: number
}
export interface NewMessagesPayload {
chatId: string
messages: WireMessage[]
fromSeq: number
toSeq: number
}
export const sendMessages = defineInvokeEventa<SendMessagesResponse, SendMessagesRequest>('chat:send-messages')
export const pullMessages = defineInvokeEventa<PullMessagesResponse, PullMessagesRequest>('chat:pull-messages')
export const newMessages = defineOutboundEventa<NewMessagesPayload>('chat:new-messages')
export * from '@proj-airi/server-protocol'
+2 -2
View File
@@ -1,4 +1,4 @@
export * from './client'
export * from './events/chat'
export type * from '@proj-airi/server-shared/types'
export { ContextUpdateStrategy, WebSocketEventSource } from '@proj-airi/server-shared/types'
export type * from '@proj-airi/server-protocol'
export { ContextUpdateStrategy, WebSocketEventSource } from '@proj-airi/server-protocol'
+1 -1
View File
@@ -1,4 +1,4 @@
import type { WebSocketEvent } from '@proj-airi/server-shared/types'
import type { WebSocketEvent } from '@proj-airi/server-protocol'
import superjson from 'superjson'
+2 -43
View File
@@ -1,6 +1,6 @@
# @proj-airi/server-shared
The shared type definitions for all server-side packages of Project AIRI.
Server-side shared utilities for AIRI runtimes.
## Usage
@@ -12,50 +12,9 @@ npm i @proj-airi/server-shared -D
```
```typescript
import type { WebSocketEvents } from '@proj-airi/server-shared'
import { parseServerErrorMessage } from '@proj-airi/server-shared'
```
## How to use the events in distributed use cases?
### Scenarios
#### Minecraft agent
##### 1. Urgent combat (witch attack)
- Minecraft sends `spark:notify` (kind=alarm, urgency=immediate, payload hp/location/gear, destinations=["character"]).
- Character `spark:emit` working ("Seen it").
- Character issues `spark:command` with interrupt=force and options (retreat vs push).
- Minecraft `spark:emit` working ("Pillared up; healing") then done/blocked as it executes.
- Optional `context:update` for summary/memory.
##### 2. Prep plan (Ender Dragon)
- Discord/user intent triggers character `spark:command` to Minecraft (intent=plan, interrupt=soft, steps gather beds/pots/gear, fallback).
- Optional `context:update` with tips (lane='game').
- Minecraft streams `spark:emit` progress.
- If ambushed, Minecraft raises new `spark:notify` (alarm/immediate) to preempt.
- Character revises with another `spark:command`.
- Completion via `spark:emit` done + summary note.
##### 3. Routine nudge
- Minecraft signals low food via `spark:notify` (kind=reminder, urgency=soon, destinations=["character"]).
- Character defers to next tick and sends `spark:command` (interrupt=soft, intent=plan: "gather food nearby").
- Minecraft `spark:emit` queued/working then done.
##### 4. Multi-step command while researching (plan + live control)
> [!NOTE]
> Using `intent=plan` keeps the loop alive even with un-finalized ideas—similar to TODO scaffolding in coding agents—while richer guidance is still being researched.
- Character receives a user goal (e.g., fortify base) and issues an initial `spark:command` to Minecraft (interrupt=soft, intent=plan, steps to gather materials) so the agent keeps working.
- Character simultaneously performs memory/search/design tasks outside the game loop (wiki lookup, prior notes).
- As insights arrive, character sends `context:update` (lane='game', hints/ideas) to enrich the sub-agent without preemption.
- If an urgent event occurs during prep, Minecraft raises `spark:notify` (alarm) → character responds with a short `spark:emit` working and a `spark:command` (interrupt=force) to handle it (e.g., retreat, block up).
- Once design is ready, character sends a refined `spark:command` (`intent=proposal` (or `action`), `interrupt=soft`) with structured options/steps/fallbacks.
- Minecraft streams `spark:emit` progress; when complete, character summarizes via `spark:emit` or `context:update` for memory.
## License
[MIT](../../LICENSE)
+1 -7
View File
@@ -18,10 +18,6 @@
".": {
"types": "./dist/index.d.mts",
"default": "./dist/index.mjs"
},
"./types": {
"types": "./dist/types/index.d.mts",
"default": "./dist/types/index.mjs"
}
},
"main": "./dist/index.mjs",
@@ -36,7 +32,5 @@
"build": "tsdown",
"typecheck": "tsc --noEmit"
},
"dependencies": {
"@proj-airi/plugin-protocol": "workspace:*"
}
"dependencies": {}
}
-1
View File
@@ -1,2 +1 @@
export * from './errors'
export * from './types'
+1 -2
View File
@@ -2,8 +2,7 @@ import { defineConfig } from 'tsdown'
export default defineConfig({
entry: {
'index': 'src/index.ts',
'types/index': 'src/types/index.ts',
index: 'src/index.ts',
},
sourcemap: true,
unused: true,
+1
View File
@@ -26,6 +26,7 @@
"@moeru/std": "catalog:",
"@proj-airi/ccc": "workspace:*",
"@proj-airi/i18n": "workspace:*",
"@proj-airi/server-protocol": "workspace:*",
"@proj-airi/server-sdk": "workspace:*",
"@proj-airi/stage-ui": "workspace:*",
"@proj-airi/stage-ui-live2d": "workspace:*",
@@ -1,5 +1,5 @@
<script setup lang="ts">
import { ContextUpdateStrategy } from '@proj-airi/server-sdk'
import { ContextUpdateStrategy } from '@proj-airi/server-protocol'
import { Section } from '@proj-airi/stage-ui/components'
import { Button, FieldInput, FieldTextArea, SelectTab } from '@proj-airi/ui'
@@ -1,4 +1,4 @@
import type { WebSocketEvents } from '@proj-airi/server-sdk'
import type { WebSocketEvents } from '@proj-airi/server-protocol'
import type { FlowEntry, PreviewItem } from '../context-flow-types'
@@ -1,4 +1,4 @@
import type { WebSocketEvents } from '@proj-airi/server-sdk'
import type { WebSocketEvents } from '@proj-airi/server-protocol'
type Optional<T> = T | undefined
@@ -1,11 +1,11 @@
<script setup lang="ts">
import type { WebSocketBaseEvent, WebSocketEventOf, WebSocketEvents } from '@proj-airi/server-sdk'
import type { WebSocketBaseEvent, WebSocketEventOf, WebSocketEvents } from '@proj-airi/server-protocol'
import type { ChatStreamEvent, ContextMessage } from '@proj-airi/stage-ui/types/chat'
import type { FlowDirection, FlowEntry, SparkNotifyEntryState } from './context-flow-types'
import { errorMessageFrom } from '@moeru/std'
import { ContextUpdateStrategy } from '@proj-airi/server-sdk'
import { ContextUpdateStrategy } from '@proj-airi/server-protocol'
import { useCharacterOrchestratorStore, useCharacterStore } from '@proj-airi/stage-ui/stores/character'
import { useChatOrchestratorStore } from '@proj-airi/stage-ui/stores/chat'
import { CHAT_STREAM_CHANNEL_NAME, CONTEXT_CHANNEL_NAME } from '@proj-airi/stage-ui/stores/chat/constants'
+1
View File
@@ -69,6 +69,7 @@
"@proj-airi/i18n": "workspace:^",
"@proj-airi/model-driver-lipsync": "workspace:^",
"@proj-airi/pipelines-audio": "workspace:^",
"@proj-airi/server-protocol": "workspace:^",
"@proj-airi/server-sdk": "workspace:^",
"@proj-airi/stage-shared": "workspace:^",
"@proj-airi/stage-ui-live2d": "workspace:^",
@@ -1,4 +1,4 @@
import type { WebSocketEventOf, WebSocketEvents } from '@proj-airi/server-sdk'
import type { WebSocketEventOf, WebSocketEvents } from '@proj-airi/server-protocol'
import type { ChatProvider, ChatProviderWithExtraOptions, EmbedProvider, EmbedProviderWithExtraOptions, SpeechProvider, SpeechProviderWithExtraOptions, TranscriptionProvider, TranscriptionProviderWithExtraOptions } from '@xsai-ext/providers/utils'
import type { Message } from '@xsai/shared-chat'
@@ -1,7 +1,7 @@
/* eslint-disable style/indent-binary-ops */
/* eslint-disable style/operator-linebreak */
import type { WebSocketEventOf } from '@proj-airi/server-sdk'
import type { WebSocketEventOf } from '@proj-airi/server-protocol'
import type { Store, StoreDefinition } from 'pinia'
import type { Mock } from 'vitest'
import type { UnwrapRef } from 'vue'
@@ -1,4 +1,4 @@
import type { WebSocketBaseEvent, WebSocketEventOf, WebSocketEvents } from '@proj-airi/server-sdk'
import type { WebSocketBaseEvent, WebSocketEventOf, WebSocketEvents } from '@proj-airi/server-protocol'
import { defineStore, storeToRefs } from 'pinia'
import { ref } from 'vue'
+1 -1
View File
@@ -1,4 +1,4 @@
import type { WebSocketEventInputs } from '@proj-airi/server-sdk'
import type { WebSocketEventInputs } from '@proj-airi/server-protocol'
import type { ChatProvider } from '@xsai-ext/providers/utils'
import type { CommonContentPart, Message, ToolMessage } from '@xsai/shared-chat'
@@ -1,6 +1,6 @@
import type { ContextMessage } from '../../../types/chat'
import { ContextUpdateStrategy } from '@proj-airi/server-sdk'
import { ContextUpdateStrategy } from '@proj-airi/server-protocol'
import { nanoid } from 'nanoid'
const DATETIME_CONTEXT_ID = 'system:datetime'
@@ -1,6 +1,6 @@
import type { ContextMessage } from '../../types/chat'
import { ContextUpdateStrategy } from '@proj-airi/server-sdk'
import { ContextUpdateStrategy } from '@proj-airi/server-protocol'
import { defineStore } from 'pinia'
import { ref, toRaw } from 'vue'
@@ -1,4 +1,4 @@
import type { WebSocketEvent } from '@proj-airi/server-sdk'
import type { WebSocketEvent } from '@proj-airi/server-protocol'
import { nanoid } from 'nanoid'
import { defineStore } from 'pinia'
@@ -1,7 +1,8 @@
import type { ContextUpdate, InputContextUpdate, WebSocketBaseEvent, WebSocketEvent, WebSocketEventOptionalSource, WebSocketEvents } from '@proj-airi/server-sdk'
import type { ContextUpdate, InputContextUpdate, WebSocketBaseEvent, WebSocketEvent, WebSocketEventOptionalSource, WebSocketEvents } from '@proj-airi/server-protocol'
import type { CommonContentPart } from '@xsai/shared-chat'
import { Client, WebSocketEventSource } from '@proj-airi/server-sdk'
import { WebSocketEventSource } from '@proj-airi/server-protocol'
import { Client } from '@proj-airi/server-sdk'
import { isStageTamagotchi, isStageWeb } from '@proj-airi/stage-shared'
import { useLocalStorage } from '@vueuse/core'
import { nanoid } from 'nanoid'
@@ -2,7 +2,7 @@ import type { CommonContentPart } from '@xsai/shared-chat'
import type { VisionWorkloadId } from '../../../composables/vision/use-vision-workloads'
import { ContextUpdateStrategy } from '@proj-airi/server-sdk'
import { ContextUpdateStrategy } from '@proj-airi/server-protocol'
import { defineStore, storeToRefs } from 'pinia'
import { ref } from 'vue'
+1 -1
View File
@@ -1,4 +1,4 @@
import type { ContextUpdate, MetadataEventSource, WebSocketEventInputs } from '@proj-airi/server-sdk'
import type { ContextUpdate, MetadataEventSource, WebSocketEventInputs } from '@proj-airi/server-protocol'
import type { AssistantMessage, CommonContentPart, CompletionToolCall, Message, SystemMessage, ToolMessage, UserMessage } from '@xsai/shared-chat'
export interface ChatSlicesText {
+1 -1
View File
@@ -1,4 +1,4 @@
import type { MetadataEventSource } from '@proj-airi/server-sdk'
import type { MetadataEventSource } from '@proj-airi/server-protocol'
interface EventSourcePayload {
source?: string
+34 -14
View File
@@ -147,6 +147,9 @@ catalogs:
builder-util-runtime:
specifier: ^9.5.1
version: 9.5.1
cac:
specifier: ^7.0.0
version: 7.0.0
capacitor-native-settings:
specifier: ^8.1.0
version: 8.1.0
@@ -569,15 +572,18 @@ importers:
'@proj-airi/drizzle-orm-browser-migrator':
specifier: ^0.1.6
version: 0.1.6(drizzle-orm@0.45.1(@electric-sql/pglite@0.4.1)(@opentelemetry/api@1.9.1)(@prisma/client@5.22.0)(@types/pg@8.20.0)(better-sqlite3@12.5.0)(kysely@0.28.14)(pg@8.20.0)(postgres@3.4.8))
'@proj-airi/server-protocol':
specifier: workspace:*
version: link:../../packages/server-protocol
'@proj-airi/server-schema':
specifier: workspace:*
version: link:../../packages/server-schema
'@proj-airi/server-sdk':
specifier: 'workspace:'
version: link:../../packages/server-sdk
better-auth:
specifier: ^1.5.6
version: 1.5.6(@opentelemetry/api@1.9.1)(@prisma/client@5.22.0)(better-sqlite3@12.5.0)(drizzle-kit@0.31.10)(drizzle-orm@0.45.1(@electric-sql/pglite@0.4.1)(@opentelemetry/api@1.9.1)(@prisma/client@5.22.0)(@types/pg@8.20.0)(better-sqlite3@12.5.0)(kysely@0.28.14)(pg@8.20.0)(postgres@3.4.8))(pg@8.20.0)(react@19.2.3)(vitest@4.1.1)(vue@3.5.30(typescript@5.9.3))
cac:
specifier: 'catalog:'
version: 7.0.0
drizzle-orm:
specifier: ^0.45.1
version: 0.45.1(@electric-sql/pglite@0.4.1)(@opentelemetry/api@1.9.1)(@prisma/client@5.22.0)(@types/pg@8.20.0)(better-sqlite3@12.5.0)(kysely@0.28.14)(pg@8.20.0)(postgres@3.4.8)
@@ -2227,9 +2233,6 @@ importers:
'@proj-airi/plugin-protocol':
specifier: workspace:*
version: link:../plugin-protocol
'@proj-airi/server-shared':
specifier: workspace:*
version: link:../server-shared
nanoid:
specifier: 'catalog:'
version: 5.1.6
@@ -2240,6 +2243,15 @@ importers:
specifier: ^5.28.0
version: 5.28.0
packages/server-protocol:
dependencies:
'@moeru/eventa':
specifier: 'catalog:'
version: 1.0.0-beta.2(electron@41.0.3)(h3@2.0.1-rc.19(crossws@0.4.4(srvx@0.11.13(patch_hash=c761d25a70e22a0925c88fe91a9dd1c3153dd341d8fd4f260166678156c4df2d))))
'@proj-airi/plugin-protocol':
specifier: workspace:*
version: link:../plugin-protocol
packages/server-runtime:
dependencies:
'@guiiai/logg':
@@ -2248,6 +2260,9 @@ importers:
'@moeru/std':
specifier: 'catalog:'
version: 0.1.0-beta.17
'@proj-airi/server-protocol':
specifier: workspace:^
version: link:../server-protocol
'@proj-airi/server-shared':
specifier: workspace:^
version: link:../server-shared
@@ -2281,6 +2296,9 @@ importers:
'@moeru/std':
specifier: 'catalog:'
version: 0.1.0-beta.17
'@proj-airi/server-protocol':
specifier: workspace:^
version: link:../server-protocol
'@proj-airi/server-shared':
specifier: workspace:^
version: link:../server-shared
@@ -2291,11 +2309,7 @@ importers:
specifier: 'catalog:'
version: 2.2.6
packages/server-shared:
dependencies:
'@proj-airi/plugin-protocol':
specifier: workspace:*
version: link:../plugin-protocol
packages/server-shared: {}
packages/stage-layouts:
dependencies:
@@ -2414,6 +2428,9 @@ importers:
'@proj-airi/i18n':
specifier: workspace:*
version: link:../i18n
'@proj-airi/server-protocol':
specifier: workspace:*
version: link:../server-protocol
'@proj-airi/server-sdk':
specifier: workspace:*
version: link:../server-sdk
@@ -2593,6 +2610,9 @@ importers:
'@proj-airi/pipelines-audio':
specifier: workspace:^
version: link:../pipelines-audio
'@proj-airi/server-protocol':
specifier: workspace:^
version: link:../server-protocol
'@proj-airi/server-sdk':
specifier: workspace:^
version: link:../server-sdk
@@ -3333,12 +3353,12 @@ importers:
'@proj-airi/audio':
specifier: workspace:^
version: link:../../packages/audio
'@proj-airi/server-protocol':
specifier: workspace:^
version: link:../../packages/server-protocol
'@proj-airi/server-sdk':
specifier: workspace:^
version: link:../../packages/server-sdk
'@proj-airi/server-shared':
specifier: workspace:^
version: link:../../packages/server-shared
'@snazzah/davey':
specifier: ^0.1.10
version: 0.1.10
+2 -2
View File
@@ -20,14 +20,12 @@ overrides:
safer-buffer: npm:@nolyfill/safer-buffer@^1.0.44
side-channel: npm:@nolyfill/side-channel@^1.0.44
string.prototype.matchall: npm:@nolyfill/string.prototype.matchall@^1.0.44
patchedDependencies:
'@mediapipe/tasks-vision': patches/@mediapipe__tasks-vision.patch
mineflayer-pathfinder: patches/mineflayer-pathfinder.patch
mineflayer@4.33.0: patches/mineflayer@4.33.0.patch
pixi-live2d-display: patches/pixi-live2d-display.patch
srvx: patches/srvx.patch
catalog:
'@better-auth/drizzle-adapter': ^1.5.6
'@capacitor/android': ^8.2.0
@@ -78,6 +76,7 @@ catalog:
async-mutex: 0.5.0
better-auth: ^1.5.6
builder-util-runtime: ^9.5.1
cac: ^7.0.0
capacitor-native-settings: ^8.1.0
crossws: ^0.4.4
d3: 7.9.0
@@ -155,6 +154,7 @@ onlyBuiltDependencies:
- spawn-sync
- utf-8-validate
- vue-demi
packageExtensions:
'@formkit/auto-animate':
peerDependencies:
+1 -1
View File
@@ -23,8 +23,8 @@
"@guiiai/logg": "catalog:",
"@huggingface/transformers": "^3.8.1",
"@proj-airi/audio": "workspace:^",
"@proj-airi/server-protocol": "workspace:^",
"@proj-airi/server-sdk": "workspace:^",
"@proj-airi/server-shared": "workspace:^",
"@snazzah/davey": "^0.1.10",
"@xsai-ext/providers": "catalog:",
"@xsai/generate-speech": "catalog:",
@@ -1,11 +1,11 @@
import type { Discord } from '@proj-airi/server-shared/types'
import type { Discord } from '@proj-airi/server-protocol'
import type { Interaction } from 'discord.js'
import { env } from 'node:process'
import { useLogg } from '@guiiai/logg'
import { ContextUpdateStrategy } from '@proj-airi/server-protocol'
import { Client as ServerChannel } from '@proj-airi/server-sdk'
import { ContextUpdateStrategy } from '@proj-airi/server-shared/types'
import { Client, Events, GatewayIntentBits, Partials } from 'discord.js'
import { handlePing, registerCommands, VoiceManager } from '../bots/discord/commands'
@@ -2,8 +2,8 @@ import type { Readable } from 'node:stream'
import type { AudioPlayer, VoiceConnection, VoiceConnectionState } from '@discordjs/voice'
import type { Logg } from '@guiiai/logg'
import type { Discord } from '@proj-airi/server-protocol'
import type { Client as AiriClient } from '@proj-airi/server-sdk'
import type { Discord } from '@proj-airi/server-shared/types'
import type {
BaseGuildVoiceChannel,
CacheType,