From ec01c6fd5e69a8acdd111d65d07bc727a2c0b87d Mon Sep 17 00:00:00 2001 From: Acbox Date: Sat, 10 Jan 2026 00:47:42 +0800 Subject: [PATCH] feat: long-memory --- .env.example | 2 - packages/agent/package.json | 9 +- packages/agent/src/agent.ts | 3 + packages/agent/src/prompts/index.ts | 1 + packages/agent/src/prompts/system.ts | 21 ++ packages/db/src/index.ts | 5 +- packages/db/src/memory.ts | 16 ++ packages/db/src/model.ts | 10 - packages/db/src/schema.ts | 2 +- packages/memory/README.md | 1 + packages/memory/package.json | 21 ++ packages/memory/src/add.ts | 34 +++ packages/memory/src/filter.ts | 58 +++++ packages/memory/src/index.ts | 6 + packages/memory/src/memory-unit.ts | 8 + packages/memory/src/raw.ts | 33 +++ packages/memory/src/search.ts | 23 ++ packages/memory/src/types.ts | 5 + pnpm-lock.yaml | 323 +++++++++++++++++---------- 19 files changed, 443 insertions(+), 138 deletions(-) create mode 100644 packages/agent/src/agent.ts create mode 100644 packages/agent/src/prompts/index.ts create mode 100644 packages/agent/src/prompts/system.ts create mode 100644 packages/db/src/memory.ts delete mode 100644 packages/db/src/model.ts create mode 100644 packages/memory/README.md create mode 100644 packages/memory/package.json create mode 100644 packages/memory/src/add.ts create mode 100644 packages/memory/src/filter.ts create mode 100644 packages/memory/src/index.ts create mode 100644 packages/memory/src/memory-unit.ts create mode 100644 packages/memory/src/raw.ts create mode 100644 packages/memory/src/search.ts create mode 100644 packages/memory/src/types.ts diff --git a/.env.example b/.env.example index 2e0eb385..f5d94b9f 100644 --- a/.env.example +++ b/.env.example @@ -1,10 +1,8 @@ # Server API_SERVER_PORT=7002 -DEVICE_API_SERVER_PORT=7001 WEB_PORT=7003 API_BASE_URL=http://localhost:7002 -DEVICE_API_BASE_URL=http://localhost:7001 WEB_URL=http://localhost:7003 # Database (PostgreSQL) diff --git a/packages/agent/package.json b/packages/agent/package.json index 01ae29e5..186d0b86 100644 --- a/packages/agent/package.json +++ b/packages/agent/package.json @@ -3,20 +3,15 @@ "version": "1.0.0", "description": "Agent package for the phonetutor monorepo", "scripts": { - "test": "vitest", - "start": "bun run src/client/index.ts" + "test": "vitest" }, "keywords": [], "author": "Phonetutor", "license": "ISC", "packageManager": "pnpm@10.27.0", "dependencies": { - "@ai-sdk/anthropic": "^3.0.7", - "@ai-sdk/google": "^3.0.6", - "@ai-sdk/openai": "^3.0.7", - "@byteagent/shared": "workspace:*", - "ai": "^6.0.14", "dotenv": "^17.2.3", + "xsai": "^0.4.1", "zod": "^4.3.5" } } diff --git a/packages/agent/src/agent.ts b/packages/agent/src/agent.ts new file mode 100644 index 00000000..32fcb87d --- /dev/null +++ b/packages/agent/src/agent.ts @@ -0,0 +1,3 @@ +import { streamText } from 'xsai' + +streamText({}) \ No newline at end of file diff --git a/packages/agent/src/prompts/index.ts b/packages/agent/src/prompts/index.ts new file mode 100644 index 00000000..44c0319e --- /dev/null +++ b/packages/agent/src/prompts/index.ts @@ -0,0 +1 @@ +export * from './system' \ No newline at end of file diff --git a/packages/agent/src/prompts/system.ts b/packages/agent/src/prompts/system.ts new file mode 100644 index 00000000..1c10d456 --- /dev/null +++ b/packages/agent/src/prompts/system.ts @@ -0,0 +1,21 @@ +export interface SystemParams { + date: Date + locale: Intl.LocalesArgument +} + +export const system = ({ date, locale }: SystemParams) => { + return ` + --- + date: ${date.toLocaleDateString(locale)} + time: ${date.toLocaleTimeString(locale)} + language: ${locale} + timezone: ${date.getTimezoneOffset()} + --- + You are a personal housekeeper assistant, which able to manage the master's daily affairs. + + Your abilities: + - Long memory: You possess long-term memory; conversations from the last 24 hours will be directly loaded into your context. Additionally, you can use tools to search for past memories. + - Scheduled tasks: You can create scheduled tasks to automatically remind you to do something. + - Messaging: You may allowed to use message software to send messages to the master. + `.trim() +} \ No newline at end of file diff --git a/packages/db/src/index.ts b/packages/db/src/index.ts index d884a390..dda4888c 100644 --- a/packages/db/src/index.ts +++ b/packages/db/src/index.ts @@ -1,3 +1,6 @@ import { drizzle } from 'drizzle-orm/node-postgres' +import { config } from 'dotenv' -export const db = drizzle(process.env.DATABASE_URL!) \ No newline at end of file +config({ path: '../../' }) + +export const db = drizzle(process.env.DATABASE_URL!) diff --git a/packages/db/src/memory.ts b/packages/db/src/memory.ts new file mode 100644 index 00000000..e8f7ab68 --- /dev/null +++ b/packages/db/src/memory.ts @@ -0,0 +1,16 @@ +import { pgTable, timestamp, uuid, jsonb, text, vector, index } from 'drizzle-orm/pg-core' + +export const memory = pgTable( + 'memory', + { + id: uuid('id').primaryKey().defaultRandom(), + messages: jsonb('messages').notNull(), + timestamp: timestamp('timestamp').notNull(), + user: text('user').notNull(), + rawContent: text('raw_content').notNull(), + embedding: vector('embedding', { dimensions: 1536 }).notNull(), + }, + (table) => [ + index('embedding_index').using('hnsw', table.embedding.op('vector_cosine_ops')), + ] +) \ No newline at end of file diff --git a/packages/db/src/model.ts b/packages/db/src/model.ts deleted file mode 100644 index 64d5abcf..00000000 --- a/packages/db/src/model.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { pgTable, text, uuid } from 'drizzle-orm/pg-core' - -export const model = pgTable('model', { - id: uuid('id').primaryKey(), - modelId: text('model_id').notNull(), - name: text('name'), - baseUrl: text('base_url').notNull(), - apiKey: text('api_key').notNull(), - clientType: text('client_type').notNull() -}) \ No newline at end of file diff --git a/packages/db/src/schema.ts b/packages/db/src/schema.ts index bc4e2a78..3c69b644 100644 --- a/packages/db/src/schema.ts +++ b/packages/db/src/schema.ts @@ -1 +1 @@ -export * from './model' \ No newline at end of file +export * from './memory' \ No newline at end of file diff --git a/packages/memory/README.md b/packages/memory/README.md new file mode 100644 index 00000000..c704086f --- /dev/null +++ b/packages/memory/README.md @@ -0,0 +1 @@ +# @byteagent/memory diff --git a/packages/memory/package.json b/packages/memory/package.json new file mode 100644 index 00000000..92ab02b5 --- /dev/null +++ b/packages/memory/package.json @@ -0,0 +1,21 @@ +{ + "name": "@byteagent/memory", + "version": "1.0.0", + "description": "", + "exports": { + ".": "./src/index.ts" + }, + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "packageManager": "pnpm@10.27.0", + "dependencies": { + "@byteagent/db": "workspace:*", + "drizzle-orm": "^0.45.1", + "xsai": "^0.4.1" + } +} diff --git a/packages/memory/src/add.ts b/packages/memory/src/add.ts new file mode 100644 index 00000000..4644e34e --- /dev/null +++ b/packages/memory/src/add.ts @@ -0,0 +1,34 @@ +import { embed } from 'xsai' +import { EmbedParams } from './types' +import { MemoryUnit } from './memory-unit' +import { rawMemory } from './raw' +import { db } from '@byteagent/db' +import { memory } from '@byteagent/db/schema' + +export interface AddMemoryParams extends EmbedParams { + locale: Intl.LocalesArgument +} + +export interface AddMemoryInput { + memory: MemoryUnit +} + +export const createAddMemory = (params: AddMemoryParams) => + async ({ memory: memoryUnit }: AddMemoryInput) => { + const rawContent = rawMemory(memoryUnit, params.locale) + const { embedding } = await embed({ + model: params.model, + input: rawContent, + apiKey: params.apiKey, + baseURL: params.baseURL, + }) + await db.insert(memory) + .values({ + timestamp: memoryUnit.timestamp, + user: memoryUnit.user, + rawContent, + embedding, + messages: memoryUnit.messages, + }) + .onConflictDoNothing() + } \ No newline at end of file diff --git a/packages/memory/src/filter.ts b/packages/memory/src/filter.ts new file mode 100644 index 00000000..2a2a54b8 --- /dev/null +++ b/packages/memory/src/filter.ts @@ -0,0 +1,58 @@ +import { db } from '@byteagent/db' +import { memory } from '@byteagent/db/schema' +import { and, gte, lte, asc, sql, cosineDistance, gt, desc, eq } from 'drizzle-orm' +import { MemoryUnit } from './memory-unit' + +export const filterByTimestamp = async ( + from: Date, + to: Date, + user: string, +) => { + const results = await db + .select() + .from(memory) + .where(and( + gte(memory.timestamp, from), + lte(memory.timestamp, to), + eq(memory.user, user), + )) + .orderBy(asc(memory.timestamp)) + + return results.map((result) => ({ + messages: result.messages, + timestamp: new Date(result.timestamp), + user: result.user, + raw: result.rawContent, + })) as MemoryUnit[] +} + +export const filterByEmbedding = async ( + embedding: number[], + user: string, + limit: number = 10, +) => { + const similarity = sql`1 - (${cosineDistance(memory.embedding, embedding)})` + const results = await db + .select({ + similarity, + messages: memory.messages, + timestamp: memory.timestamp, + user: memory.user, + rawContent: memory.rawContent, + embedding: memory.embedding, + id: memory.id, + }) + .from(memory) + .where(and( + gt(similarity, 0.5), + eq(memory.user, user), + )) + .orderBy((t) => desc(t.similarity)) + .limit(limit) + return results.map((result) => ({ + messages: result.messages, + timestamp: new Date(result.timestamp), + user: result.user, + raw: result.rawContent, + })) as MemoryUnit[] +} \ No newline at end of file diff --git a/packages/memory/src/index.ts b/packages/memory/src/index.ts new file mode 100644 index 00000000..fa209bbc --- /dev/null +++ b/packages/memory/src/index.ts @@ -0,0 +1,6 @@ +export * from './memory-unit' +export * from './filter' +export * from './add' +export * from './search' +export * from './types' +export * from './raw' \ No newline at end of file diff --git a/packages/memory/src/memory-unit.ts b/packages/memory/src/memory-unit.ts new file mode 100644 index 00000000..4eaf50e3 --- /dev/null +++ b/packages/memory/src/memory-unit.ts @@ -0,0 +1,8 @@ +import { Message } from 'xsai' + +export interface MemoryUnit { + messages: Message[] + timestamp: Date + user: string + raw: string +} \ No newline at end of file diff --git a/packages/memory/src/raw.ts b/packages/memory/src/raw.ts new file mode 100644 index 00000000..0fbbcdee --- /dev/null +++ b/packages/memory/src/raw.ts @@ -0,0 +1,33 @@ +import { Message } from 'xsai' +import { MemoryUnit } from './memory-unit' + +export const rawMessages = (messages: Message[]) => { + return messages.map((message) => { + if (message.role === 'user') { + return `User: ${message.content}` + } else if (message.role === 'assistant') { + let toolCalls = '' + if (message.tool_calls && message.tool_calls.length !== 0) { + toolCalls = `Tool Calls: ${message.tool_calls.map(t => t.function.name).join(', ')}` + } + return `You: ${message.content} \n${toolCalls}` + } else if (message.role === 'tool') { + return `Tool Result: ${message.content}` + } else { + return null + } + }) + .filter((message) => message !== null) + .join('\n\n') +} + +export const rawMemory = (memory: MemoryUnit, locale: Intl.LocalesArgument) => { + return ` + --- + date: ${memory.timestamp.toLocaleDateString(locale)} + time: ${memory.timestamp.toLocaleTimeString(locale)} + timezone: ${memory.timestamp.getTimezoneOffset()} + --- + ${rawMessages(memory.messages)} + `.trim() +} diff --git a/packages/memory/src/search.ts b/packages/memory/src/search.ts new file mode 100644 index 00000000..84b69401 --- /dev/null +++ b/packages/memory/src/search.ts @@ -0,0 +1,23 @@ +import { embed } from 'xsai' +import { filterByEmbedding } from './filter' +import { EmbedParams } from './types' + +// eslint-disable-next-line @typescript-eslint/no-empty-object-type +export interface MemorySearchParams extends EmbedParams { } + +export interface MemorySearchInput { + user: string + query: string + maxResults?: number +} + +export const createMemorySearch = (params: MemorySearchParams) => + async ({ user, query, maxResults = 10 }: MemorySearchInput) => { + const { embedding } = await embed({ + model: params.model, + input: query, + apiKey: params.apiKey, + baseURL: params.baseURL, + }) + return await filterByEmbedding(embedding, user, maxResults) + } \ No newline at end of file diff --git a/packages/memory/src/types.ts b/packages/memory/src/types.ts new file mode 100644 index 00000000..85ce92f4 --- /dev/null +++ b/packages/memory/src/types.ts @@ -0,0 +1,5 @@ +export interface EmbedParams { + baseURL: string + apiKey: string + model: string +} \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 81a0560b..c3078be1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -36,24 +36,12 @@ importers: packages/agent: dependencies: - '@ai-sdk/anthropic': - specifier: ^3.0.7 - version: 3.0.7(zod@4.3.5) - '@ai-sdk/google': - specifier: ^3.0.6 - version: 3.0.6(zod@4.3.5) - '@ai-sdk/openai': - specifier: ^3.0.7 - version: 3.0.7(zod@4.3.5) - '@byteagent/shared': - specifier: workspace:* - version: link:../shared - ai: - specifier: ^6.0.14 - version: 6.0.14(zod@4.3.5) dotenv: specifier: ^17.2.3 version: 17.2.3 + xsai: + specifier: ^0.4.1 + version: 0.4.1(zod@4.3.5) zod: specifier: ^4.3.5 version: 4.3.5 @@ -90,6 +78,18 @@ importers: specifier: ^4.21.0 version: 4.21.0 + packages/memory: + dependencies: + '@byteagent/db': + specifier: workspace:* + version: link:../db + drizzle-orm: + specifier: ^0.45.1 + version: 0.45.1(@opentelemetry/api@1.9.0)(@types/pg@8.16.0)(bun-types@1.3.5)(pg@8.16.3) + xsai: + specifier: ^0.4.1 + version: 0.4.1(zod@4.3.5) + packages/shared: {} packages/ui: @@ -222,40 +222,6 @@ importers: packages: - '@ai-sdk/anthropic@3.0.7': - resolution: {integrity: sha512-WFE56yxgjecd77f8pNj1TkusfCKh34E4h+0J0qVOKDNFXuOsZiAb6dIG9Q3PUrwY1MuiMQLD/9ir0s+dVcVfeA==} - engines: {node: '>=18'} - peerDependencies: - zod: ^3.25.76 || ^4.1.8 - - '@ai-sdk/gateway@3.0.9': - resolution: {integrity: sha512-EA5dZIukimwoJ9HIPuuREotAqaTItpdc/yImzVF0XGNg7B0YRJmYI8Uq3aCMr87vjr1YB1cWUfnrTt6OJ9eHiQ==} - engines: {node: '>=18'} - peerDependencies: - zod: ^3.25.76 || ^4.1.8 - - '@ai-sdk/google@3.0.6': - resolution: {integrity: sha512-Nr7E+ouWd/bKO9SFlgLnJJ1+fiGHC07KAeFr08faT+lvkECWlxVox3aL0dec8uCgBDUghYbq7f4S5teUrCc+QQ==} - engines: {node: '>=18'} - peerDependencies: - zod: ^3.25.76 || ^4.1.8 - - '@ai-sdk/openai@3.0.7': - resolution: {integrity: sha512-CBoYn1U59Lop8yBL9KuVjHCKc/B06q9Qo0SasRwHoyMEq+X4I8LQZu3a8Ck1jwwcZTTxfyiExB70LtIRSynBDA==} - engines: {node: '>=18'} - peerDependencies: - zod: ^3.25.76 || ^4.1.8 - - '@ai-sdk/provider-utils@4.0.4': - resolution: {integrity: sha512-VxhX0B/dWGbpNHxrKCWUAJKXIXV015J4e7qYjdIU9lLWeptk0KMLGcqkB4wFxff5Njqur8dt8wRi1MN9lZtDqg==} - engines: {node: '>=18'} - peerDependencies: - zod: ^3.25.76 || ^4.1.8 - - '@ai-sdk/provider@3.0.2': - resolution: {integrity: sha512-HrEmNt/BH/hkQ7zpi2o6N3k1ZR1QTb7z85WYhYygiTxOQuaml4CMtHCWRbric5WPU+RNsYI7r1EpyVQMKO1pYw==} - engines: {node: '>=18'} - '@babel/code-frame@7.27.1': resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} engines: {node: '>=6.9.0'} @@ -1352,10 +1318,6 @@ packages: resolution: {integrity: sha512-ink3/Zofus34nmBsPjow63FP5M7IGff0RKAgqR6+CFpdk22M7aLwC9gOcLGYqr7MczLPzZVERW9hRog3O4n1sQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@vercel/oidc@3.1.0': - resolution: {integrity: sha512-Fw28YZpRnA3cAHHDlkt7xQHiJ0fcL+NRcIqsocZQUSmbzeIKRpwttJjik5ZGanXP+vlA4SbTg+AbA3bP363l+w==} - engines: {node: '>= 20'} - '@vitejs/plugin-vue@6.0.3': resolution: {integrity: sha512-TlGPkLFLVOY3T7fZrwdvKpjprR3s4fxRln0ORDo1VQ7HHyxJwTlrjKU3kpVWTlaAjIEuCTokmjkZnr8Tpc925w==} engines: {node: ^20.19.0 || >=22.12.0} @@ -1505,6 +1467,54 @@ packages: peerDependencies: vue: ^3.5.0 + '@xsai/embed@0.4.1': + resolution: {integrity: sha512-Ta/qk7Hzbzp6L0KUkyqWv4OXBaptP+F8vBpnNvLxmgJPS+EUlUOddNWBTo1rpLON8bLCt3d5nZzEEwx53PauUw==} + + '@xsai/generate-image@0.4.1': + resolution: {integrity: sha512-PmXRCdRWFJRh6U+sCpxKK03w9hUdIfO2XYow3I/BGGrcZm3oZ36bLLnIqW63I93pF1wzDu0qZ/3uLGqd11dwOg==} + + '@xsai/generate-object@0.4.1': + resolution: {integrity: sha512-0nJw8RVutGyzV4Iqz/42qHKr75KTw2QBximo1Ku1H4FL0zZxvFgR6rfJjutcKgeL1ktsFDObRuCKBJl2KFiq5g==} + + '@xsai/generate-speech@0.4.1': + resolution: {integrity: sha512-eea0K1oyCd0RBHbtX6iTIvQpIsqwmX23B93B20okT1ut8/b79KLogn+3CAl2ESDj217bmPJch+S+cZfp3u5eFw==} + + '@xsai/generate-text@0.4.1': + resolution: {integrity: sha512-FGqo19K0aNxn3hOW+zW43xvVq/ukg353PhcQowNt/AGa1snsjNTsbw+9aBXLSdFLINH3sjd/q4rsyg2Ld7GoxQ==} + + '@xsai/generate-transcription@0.4.1': + resolution: {integrity: sha512-VoWe1zm1d8i7d+HImRvoTnrBUHVmNIjlbNibrcXbvA7olQect65Wh5CEMpnThfQcaVa+L8/5wMh8oV5KlCuCAw==} + + '@xsai/model@0.4.1': + resolution: {integrity: sha512-rhXcKQnJWFWPfvo3UUw1eRXeNWD8IEu/EFw01FZ/MGiQ3TEMppXIiQSLkQFiWylfx5TrucQIzEbE/QBKjdWfkg==} + + '@xsai/shared-chat@0.4.1': + resolution: {integrity: sha512-6pyjFs9oKi2jSjtZBk4QNF5RM5b63aUrSJ8e46xvaeMIpsK6hec3ay7X4r81annhb/HpMNOQrfbxCQsTcWalhA==} + + '@xsai/shared@0.4.1': + resolution: {integrity: sha512-WptfJwv0ajc22UNvMgSbM2wCtJDWok6x3svljETMc3ycknHE3w5XQ6whbASdbeDJomb/MtGhFhaHYVQZQnqHIw==} + + '@xsai/stream-object@0.4.1': + resolution: {integrity: sha512-3k2ulDTRkWfW/Y76YBmohmigl0CNQBTI7oEmXpU8LBqETty7wEZgfiXNqq7cfbhPk9iAA2DPsS7NPA9H+aP2Yw==} + + '@xsai/stream-text@0.4.1': + resolution: {integrity: sha512-Eq+b3knPB0YEpL6lnW08RZETEgCm07Q1XaP6YUO4Y81FF0q8dztyLXxtmAck1t7GV5eI7fTBRMxP6iQzwabomA==} + + '@xsai/stream-transcription@0.4.1': + resolution: {integrity: sha512-kJe7CLbiNd2151ZGbVKVoirATQbmzn/qH786MhtpYOpMAN4SEnoREbc/TOeggoJ30k0+Q9j1CdwpKYr54zhoug==} + + '@xsai/tool@0.4.1': + resolution: {integrity: sha512-SnPMRPUUbhK1MdOZZoN+nY3jR/ntsfQ1//HnUvHWXdGWo47cmYuiVN7wwlsGACkG8VHJkR3BSxL6wfNQ/toozA==} + + '@xsai/utils-chat@0.4.1': + resolution: {integrity: sha512-nSDbBI5mdLR21l44a1cJQPKO/OGqT3qmVMI2y/XIJTU+opG/z/0RRIRE/RwOfisWGYZu3IvNTAvUdOZS6aOTXQ==} + + '@xsai/utils-reasoning@0.4.1': + resolution: {integrity: sha512-365G0/ccfNYqXz7Gnt+bZSZFxtChjanXAn5MPiDGxhP2h22qYmw5zUM6ihUdqaVHke7Ons5ooV+SayVuls2Kiw==} + + '@xsai/utils-stream@0.4.1': + resolution: {integrity: sha512-u3kgR0XuFs5NWf6etuZu7dhJTFQmT9cjBsxpllo5ZhJEjrknVttuVGfs45xHRjz6q/SBtyPDjzAG6JdrtUAl3Q==} + acorn-jsx@5.3.2: resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: @@ -1515,12 +1525,6 @@ packages: engines: {node: '>=0.4.0'} hasBin: true - ai@6.0.14: - resolution: {integrity: sha512-OaEJFeQ3gb45eZtC/lSNKqAxmsrqWxC8wLmIVXFYAMvPXE3lb96zIdS3swYArR4uXOVt6N7H/XZSyQz/Dl+HTw==} - engines: {node: '>=18'} - peerDependencies: - zod: ^3.25.76 || ^4.1.8 - ajv-draft-04@1.0.0: resolution: {integrity: sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==} peerDependencies: @@ -1930,10 +1934,6 @@ packages: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} - eventsource-parser@3.0.6: - resolution: {integrity: sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg==} - engines: {node: '>=18.0.0'} - exact-mirror@0.2.6: resolution: {integrity: sha512-7s059UIx9/tnOKSySzUk5cPGkoILhTE4p6ncf6uIPaQ+9aRBQzQjc9+q85l51+oZ+P6aBxh084pD0CzBQPcFUA==} peerDependencies: @@ -2122,9 +2122,6 @@ packages: json-schema-traverse@1.0.0: resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} - json-schema@0.4.0: - resolution: {integrity: sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==} - json-stable-stringify-without-jsonify@1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} @@ -2914,6 +2911,32 @@ packages: resolution: {integrity: sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==} engines: {node: '>=12'} + xsai@0.4.1: + resolution: {integrity: sha512-HvhJYWyaQz+t/8Jntt0SsZAH6Ty7+EjDDdH2BVz7ftaEF9t6Cxr0Cb+17prsCPQnI99my/vS4T70OyPrxUbiew==} + + xsschema@0.4.1: + resolution: {integrity: sha512-v4kWVUoqF73IFDxONxb9cvl6EXolas1zUnS1ajR8d8RZdM897ByxHaTqw3QOPspuiLl3ML86Mk0ccVfwURHEBw==} + peerDependencies: + '@valibot/to-json-schema': ^1.0.0 + arktype: ^2.1.20 + effect: ^3.16.0 + sury: ^10.0.0 + zod: ^3.25.0 || ^4.0.0 + zod-to-json-schema: ^3.25.0 + peerDependenciesMeta: + '@valibot/to-json-schema': + optional: true + arktype: + optional: true + effect: + optional: true + sury: + optional: true + zod: + optional: true + zod-to-json-schema: + optional: true + xtend@4.0.2: resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} engines: {node: '>=0.4'} @@ -2933,42 +2956,6 @@ packages: snapshots: - '@ai-sdk/anthropic@3.0.7(zod@4.3.5)': - dependencies: - '@ai-sdk/provider': 3.0.2 - '@ai-sdk/provider-utils': 4.0.4(zod@4.3.5) - zod: 4.3.5 - - '@ai-sdk/gateway@3.0.9(zod@4.3.5)': - dependencies: - '@ai-sdk/provider': 3.0.2 - '@ai-sdk/provider-utils': 4.0.4(zod@4.3.5) - '@vercel/oidc': 3.1.0 - zod: 4.3.5 - - '@ai-sdk/google@3.0.6(zod@4.3.5)': - dependencies: - '@ai-sdk/provider': 3.0.2 - '@ai-sdk/provider-utils': 4.0.4(zod@4.3.5) - zod: 4.3.5 - - '@ai-sdk/openai@3.0.7(zod@4.3.5)': - dependencies: - '@ai-sdk/provider': 3.0.2 - '@ai-sdk/provider-utils': 4.0.4(zod@4.3.5) - zod: 4.3.5 - - '@ai-sdk/provider-utils@4.0.4(zod@4.3.5)': - dependencies: - '@ai-sdk/provider': 3.0.2 - '@standard-schema/spec': 1.1.0 - eventsource-parser: 3.0.6 - zod: 4.3.5 - - '@ai-sdk/provider@3.0.2': - dependencies: - json-schema: 0.4.0 - '@babel/code-frame@7.27.1': dependencies: '@babel/helper-validator-identifier': 7.28.5 @@ -3554,7 +3541,8 @@ snapshots: '@microsoft/tsdoc@0.16.0': {} - '@opentelemetry/api@1.9.0': {} + '@opentelemetry/api@1.9.0': + optional: true '@polka/url@1.0.0-next.29': {} @@ -3887,8 +3875,6 @@ snapshots: '@typescript-eslint/types': 8.52.0 eslint-visitor-keys: 4.2.1 - '@vercel/oidc@3.1.0': {} - '@vitejs/plugin-vue@6.0.3(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0))(vue@3.5.26(typescript@5.9.3))': dependencies: '@rolldown/pluginutils': 1.0.0-beta.53 @@ -4120,20 +4106,97 @@ snapshots: dependencies: vue: 3.5.26(typescript@5.9.3) + '@xsai/embed@0.4.1': + dependencies: + '@xsai/shared': 0.4.1 + + '@xsai/generate-image@0.4.1': + dependencies: + '@xsai/shared': 0.4.1 + + '@xsai/generate-object@0.4.1(zod@4.3.5)': + dependencies: + '@xsai/generate-text': 0.4.1 + xsschema: 0.4.1(zod@4.3.5) + transitivePeerDependencies: + - '@valibot/to-json-schema' + - arktype + - effect + - sury + - zod + - zod-to-json-schema + + '@xsai/generate-speech@0.4.1': + dependencies: + '@xsai/shared': 0.4.1 + + '@xsai/generate-text@0.4.1': + dependencies: + '@xsai/shared': 0.4.1 + '@xsai/shared-chat': 0.4.1 + + '@xsai/generate-transcription@0.4.1': + dependencies: + '@xsai/shared': 0.4.1 + + '@xsai/model@0.4.1': + dependencies: + '@xsai/shared': 0.4.1 + + '@xsai/shared-chat@0.4.1': + dependencies: + '@xsai/shared': 0.4.1 + + '@xsai/shared@0.4.1': {} + + '@xsai/stream-object@0.4.1(zod@4.3.5)': + dependencies: + '@xsai/stream-text': 0.4.1 + xsschema: 0.4.1(zod@4.3.5) + transitivePeerDependencies: + - '@valibot/to-json-schema' + - arktype + - effect + - sury + - zod + - zod-to-json-schema + + '@xsai/stream-text@0.4.1': + dependencies: + '@xsai/shared': 0.4.1 + '@xsai/shared-chat': 0.4.1 + + '@xsai/stream-transcription@0.4.1': + dependencies: + '@xsai/shared': 0.4.1 + + '@xsai/tool@0.4.1(zod@4.3.5)': + dependencies: + '@xsai/shared': 0.4.1 + '@xsai/shared-chat': 0.4.1 + xsschema: 0.4.1(zod@4.3.5) + transitivePeerDependencies: + - '@valibot/to-json-schema' + - arktype + - effect + - sury + - zod + - zod-to-json-schema + + '@xsai/utils-chat@0.4.1': + dependencies: + '@xsai/shared-chat': 0.4.1 + + '@xsai/utils-reasoning@0.4.1': {} + + '@xsai/utils-stream@0.4.1': {} + acorn-jsx@5.3.2(acorn@8.15.0): dependencies: acorn: 8.15.0 acorn@8.15.0: {} - ai@6.0.14(zod@4.3.5): - dependencies: - '@ai-sdk/gateway': 3.0.9(zod@4.3.5) - '@ai-sdk/provider': 3.0.2 - '@ai-sdk/provider-utils': 4.0.4(zod@4.3.5) - '@opentelemetry/api': 1.9.0 - zod: 4.3.5 - ajv-draft-04@1.0.0(ajv@8.13.0): optionalDependencies: ajv: 8.13.0 @@ -4514,8 +4577,6 @@ snapshots: esutils@2.0.3: {} - eventsource-parser@3.0.6: {} - exact-mirror@0.2.6(@sinclair/typebox@0.34.47): optionalDependencies: '@sinclair/typebox': 0.34.47 @@ -4655,8 +4716,6 @@ snapshots: json-schema-traverse@1.0.0: {} - json-schema@0.4.0: {} - json-stable-stringify-without-jsonify@1.0.1: {} json5@2.2.3: {} @@ -5383,6 +5442,36 @@ snapshots: xml-name-validator@4.0.0: {} + xsai@0.4.1(zod@4.3.5): + dependencies: + '@xsai/embed': 0.4.1 + '@xsai/generate-image': 0.4.1 + '@xsai/generate-object': 0.4.1(zod@4.3.5) + '@xsai/generate-speech': 0.4.1 + '@xsai/generate-text': 0.4.1 + '@xsai/generate-transcription': 0.4.1 + '@xsai/model': 0.4.1 + '@xsai/shared': 0.4.1 + '@xsai/shared-chat': 0.4.1 + '@xsai/stream-object': 0.4.1(zod@4.3.5) + '@xsai/stream-text': 0.4.1 + '@xsai/stream-transcription': 0.4.1 + '@xsai/tool': 0.4.1(zod@4.3.5) + '@xsai/utils-chat': 0.4.1 + '@xsai/utils-reasoning': 0.4.1 + '@xsai/utils-stream': 0.4.1 + transitivePeerDependencies: + - '@valibot/to-json-schema' + - arktype + - effect + - sury + - zod + - zod-to-json-schema + + xsschema@0.4.1(zod@4.3.5): + optionalDependencies: + zod: 4.3.5 + xtend@4.0.2: {} yallist@3.1.1: {}