Skip to content

feat(server): basic implementation of server runtime and SDK #13

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jan 15, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions cspell.config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ words:
- bumpp
- cientos
- composables
- crossws
- csmmap
- csmvector
- cubismbreath
Expand Down Expand Up @@ -50,6 +51,7 @@ words:
- Kawaii
- kwaa
- libsodium
- listhen
- live2dcubismcore
- live2dcubismframework
- Llmmarker
Expand Down
13 changes: 10 additions & 3 deletions packages/server-runtime/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"type": "module",
"version": "0.1.1",
"private": false,
"description": "Server runtime and utility implementation for Airi running in different environments",
"description": "Server runtime implementation for Airi running in different environments",
"author": {
"name": "Neko Ayaka",
"email": "neko@ayaka.moe",
Expand All @@ -30,9 +30,16 @@
"dist",
"package.json"
],
"scripts": {},
"scripts": {
"dev": "listhen -w --ws --port 6121 ./src/index.ts",
"start": "listhen --ws --port 6121 ./src/index.ts"
},
"dependencies": {
"@guiiai/logg": "^1.0.6",
"@proj-airi/server-shared": "workspace:^",
"crossws": "^0.3.1",
"defu": "^6.1.4",
"h3": "^1.13.1"
"h3": "^1.13.1",
"listhen": "^1.9.0"
}
}
45 changes: 33 additions & 12 deletions packages/server-runtime/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,38 @@
// Import h3 as npm dependency
import { createApp, createRouter, defineEventHandler } from 'h3'
import type { WebSocketEvent } from '@proj-airi/server-shared/types'
import { Format, LogLevel, setGlobalFormat, setGlobalLogLevel, useLogg } from '@guiiai/logg'
import { createApp, createRouter, defineWebSocketHandler } from 'h3'

// Create an app instance
export const app = createApp()
setGlobalFormat(Format.Pretty)
setGlobalLogLevel(LogLevel.Log)

const appLogger = useLogg('App').useGlobalConfig()
const websocketLogger = useLogg('WebSocket').useGlobalConfig()

export const app = createApp({
onError: error => appLogger.withError(error).error('an error occurred'),
})

// Create a new router and register it in app
const router = createRouter()
app.use(router)

// Add a new route that matches GET requests to / path
router.get(
'/',
defineEventHandler(() => {
return { message: '⚡️ Tadaa!' }
}),
)
router.get('/ws', defineWebSocketHandler({
open: (peer) => {
websocketLogger.withFields({ peer: peer.id }).log('connected')
},
message: (peer, message) => {
const event = message.json() as WebSocketEvent

websocketLogger.withFields({ peer: peer.id, message: event }).log('received message')
switch (event.type) {
case 'input:voice:discord:transcription':
websocketLogger.withFields({ message: event }).log('transcribed')
break
}
},
error: (peer, error) => {
websocketLogger.withFields({ peer: peer.id }).withError(error).error('an error occurred')
},
close: (peer, details) => {
websocketLogger.withFields({ peer: peer.id, details }).log('closed')
},
}))
43 changes: 43 additions & 0 deletions packages/server-sdk/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{
"name": "@proj-airi/server-sdk",
"type": "module",
"version": "0.1.1",
"private": false,
"description": "Client-side SDK implementation for connecting to Airi server components and runtimes",
"author": {
"name": "Neko Ayaka",
"email": "neko@ayaka.moe",
"url": "https://github.com/nekomeowww"
},
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/moeru-ai/airi.git",
"directory": "packages/server-sdk"
},
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.mjs",
"require": "./dist/index.cjs"
}
},
"main": "./dist/index.cjs",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"files": [
"README.md",
"dist",
"package.json"
],
"scripts": {
"dev": "pnpm run stub",
"stub": "unbuild --stub",
"build": "unbuild",
"package:publish": "pnpm build && pnpm publish --access public --no-git-checks"
},
"dependencies": {
"@proj-airi/server-shared": "workspace:^",
"crossws": "^0.3.1"
}
}
19 changes: 19 additions & 0 deletions packages/server-sdk/src/client.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import type { WebSocketEvent } from '@proj-airi/server-shared/types'
import type { Blob } from 'node:buffer'
import WebSocket from 'crossws/websocket'

export class Client {
private websocket: WebSocket

constructor(url: string) {
this.websocket = new WebSocket(url)
}

send(data: WebSocketEvent): void {
this.websocket.send(JSON.stringify(data))
}

sendRaw(data: string | ArrayBufferLike | Blob | ArrayBufferView): void {
this.websocket.send(data)
}
}
1 change: 1 addition & 0 deletions packages/server-sdk/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './client'
18 changes: 18 additions & 0 deletions packages/server-sdk/tsconfig.json
Original file line number Diff line number Diff line change
@@ -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"
]
}
42 changes: 42 additions & 0 deletions packages/server-shared/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"name": "@proj-airi/server-shared",
"type": "module",
"version": "0.1.1",
"private": false,
"description": "Server shared types, utilities for Airi server components and runtimes",
"author": {
"name": "Neko Ayaka",
"email": "neko@ayaka.moe",
"url": "https://github.com/nekomeowww"
},
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/moeru-ai/airi.git",
"directory": "packages/server-shared"
},
"exports": {
"./types": {
"types": "./dist/types/index.d.ts",
"import": "./dist/types/index.mjs",
"require": "./dist/types/index.cjs"
}
},
"main": "./dist/types/index.cjs",
"module": "./dist/types/index.mjs",
"types": "./dist/types/index.d.ts",
"files": [
"README.md",
"dist",
"package.json"
],
"scripts": {
"dev": "pnpm run stub",
"stub": "unbuild --stub",
"build": "unbuild",
"package:publish": "pnpm build && pnpm publish --access public --no-git-checks"
},
"dependencies": {
"crossws": "^0.3.1"
}
}
Empty file.
1 change: 1 addition & 0 deletions packages/server-shared/src/types/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './websocket'
24 changes: 24 additions & 0 deletions packages/server-shared/src/types/websocket/events.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
export interface WebSocketBaseEvent<T, D> {
type: T
data: D
}

// Thanks to:
//
// A little hack for creating extensible discriminated unions : r/typescript
// https://www.reddit.com/r/typescript/comments/1064ibt/a_little_hack_for_creating_extensible/
export interface WebSocketEvents {
'module:announce': {
name: string
}
'input:voice:discord:transcription': {
text: string
username: string
userDisplayName: string
userId: string
}
}

export type WebSocketEvent = {
[K in keyof WebSocketEvents]: WebSocketBaseEvent<K, WebSocketEvents[K]>;
}[keyof WebSocketEvents]
1 change: 1 addition & 0 deletions packages/server-shared/src/types/websocket/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './events'
18 changes: 18 additions & 0 deletions packages/server-shared/tsconfig.json
Original file line number Diff line number Diff line change
@@ -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"
]
}
Loading
Loading