Skip to content

Commit

Permalink
feat!: new package xsschema (#40)
Browse files Browse the repository at this point in the history
* feat: new package `xsschema`

* chore: clean cspell config

* fix(tsconfig): add reference

* fix(xsschema): add json-schema types to dev deps

* chore(xsschema): export schema type

* fix(xsschema): export schema type

* refactor!: use xsschema instead of typeschema

* fix(generate-object): direct return

* fix(tool): drop tool result generic type

* fix(xsschema): mark return type, handle unknown vendor

* feat(xsschema): export json schema type

* chore(generate-text): update test snapshot

* fix(generate-text): check content length

* chore(tool): update test snapshot
  • Loading branch information
kwaa authored Feb 5, 2025
1 parent 13180a2 commit 29e4d21
Show file tree
Hide file tree
Showing 22 changed files with 204 additions and 211 deletions.
2 changes: 1 addition & 1 deletion cspell.config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ words:
- elevenlabs
- eslintcache
- fumadocs
- gcornut
- importantimport
- koemotion
- masknet
Expand All @@ -30,5 +29,6 @@ words:
- valibot
- vitest
- xsai
- xsschema
ignoreWords: []
import: []
6 changes: 3 additions & 3 deletions packages/generate-object/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,11 @@
"test:watch": "vitest"
},
"dependencies": {
"@typeschema/main": "catalog:",
"@xsai/generate-text": "workspace:"
"@xsai/generate-text": "workspace:",
"xsschema": "workspace:"
},
"devDependencies": {
"@gcornut/valibot-json-schema": "catalog:",
"@valibot/to-json-schema": "catalog:",
"@xsai/providers": "workspace:",
"valibot": "catalog:"
}
Expand Down
30 changes: 11 additions & 19 deletions packages/generate-object/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import type { Infer, Schema } from '@typeschema/main'
import type { GenerateTextOptions, GenerateTextResult } from '@xsai/generate-text'
import type { Infer, InferIn, Schema } from 'xsschema'

import { toJSONSchema, validate } from '@typeschema/main'
import { generateText } from '@xsai/generate-text'
import { toJSONSchema, validate } from 'xsschema'

export interface GenerateObjectOptions<T extends Schema> extends GenerateTextOptions {
schema: T
Expand Down Expand Up @@ -32,24 +32,16 @@ export const generateObject = async <T extends Schema>(options: GenerateObjectOp
schemaName: undefined,
})
.then(async ({ finishReason, messages, steps, text, toolCalls, toolResults, usage }) => {
const result = await validate(options.schema, JSON.parse(text!))
const object = await validate(options.schema, JSON.parse(text!) as InferIn<T>)

if (result.success) {
return {
finishReason,
messages,
object: result.data,
steps,
toolCalls,
toolResults,
usage,
}
}
else {
throw new Error([
'Schema validation failed:',
...result.issues.map(issue => `- ${issue.message}`),
].join('\n'))
return {
finishReason,
messages,
object,
steps,
toolCalls,
toolResults,
usage,
}
})

Expand Down
2 changes: 1 addition & 1 deletion packages/generate-text/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ const rawGenerateText: RawGenerateText = async (options: GenerateTextOptions) =>
? 'tool-result'
: 'continue'

if (message.content !== undefined || !message.tool_calls || steps.length >= (options.maxSteps ?? 1)) {
if ((message.content !== undefined && message.content.length > 0) || !message.tool_calls || steps.length >= (options.maxSteps ?? 1)) {
const step: StepResult = {
finishReason,
stepType,
Expand Down
2 changes: 2 additions & 0 deletions packages/generate-text/test/__snapshots__/index.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
exports[`@xsai/generate-text > basic 1`] = `
[
{
"finishReason": "stop",
"stepType": "initial",
"text": "YES",
"toolCalls": [],
"toolResults": [],
Expand Down
6 changes: 3 additions & 3 deletions packages/stream-object/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,11 @@
"test:watch": "vitest"
},
"dependencies": {
"@typeschema/main": "catalog:",
"@xsai/stream-text": "workspace:"
"@xsai/stream-text": "workspace:",
"xsschema": "workspace:"
},
"devDependencies": {
"@gcornut/valibot-json-schema": "catalog:",
"@valibot/to-json-schema": "catalog:",
"@xsai/providers": "workspace:",
"best-effort-json-parser": "^1.1.2",
"type-fest": "^4.33.0",
Expand Down
4 changes: 2 additions & 2 deletions packages/stream-object/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import type { Infer, Schema } from '@typeschema/main'
import type { StreamTextOptions, StreamTextResult } from '@xsai/stream-text'
import type { PartialDeep } from 'type-fest'
import type { Infer, Schema } from 'xsschema'

import { toJSONSchema } from '@typeschema/main'
import { streamText } from '@xsai/stream-text'
import { parse } from 'best-effort-json-parser'
import { toJSONSchema } from 'xsschema'

export interface StreamObjectOptions<T extends Schema> extends StreamTextOptions {
schema: T
Expand Down
6 changes: 3 additions & 3 deletions packages/tool/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,11 @@
}
},
"dependencies": {
"@typeschema/main": "catalog:",
"@xsai/shared": "workspace:"
"@xsai/shared": "workspace:",
"xsschema": "workspace:"
},
"devDependencies": {
"@gcornut/valibot-json-schema": "catalog:",
"@valibot/to-json-schema": "catalog:",
"@xsai/generate-text": "workspace:",
"@xsai/providers": "workspace:",
"valibot": "catalog:"
Expand Down
4 changes: 1 addition & 3 deletions packages/tool/src/generate-text.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
/// <reference types="@xsai/generate-text" />

import type { Schema } from '@typeschema/main'

import type { ToolResult } from '.'

declare module '@xsai/generate-text' {
export interface GenerateTextOptions {
tools?: ToolResult<Schema>[]
tools?: ToolResult[]
}
}
12 changes: 6 additions & 6 deletions packages/tool/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import type { InferIn, Schema } from '@typeschema/main'
import type { InferIn, Schema } from 'xsschema'

import { toJSONSchema } from '@typeschema/main'
import { clean } from '@xsai/shared'
import { toJSONSchema } from 'xsschema'

export interface ToolOptions<T extends Schema> {
export interface ToolOptions<T extends Schema = Schema> {
description?: string
execute: (input: InferIn<T>) => Promise<string> | string
name: string
parameters: T
strict?: boolean
}

export interface ToolResult<T extends Schema> {
execute: (input: InferIn<T>) => Promise<string> | string
export interface ToolResult {
execute: (input: unknown) => Promise<string> | string
function: {
description?: string
name: string
Expand All @@ -22,7 +22,7 @@ export interface ToolResult<T extends Schema> {
type: 'function'
}

export const tool = async <T extends Schema>(options: ToolOptions<T>): Promise<ToolResult<T>> => ({
export const tool = async <T extends Schema>(options: ToolOptions<T>): Promise<ToolResult> => ({
execute: options.execute,
function: {
description: options.description,
Expand Down
2 changes: 1 addition & 1 deletion packages/tool/test/__snapshots__/index.test.ts.snap
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`@xsai/tool > generateText with tool 1`] = `"In San Francisco, it's currently 42°F."`;
exports[`@xsai/tool > generateText with tool 1`] = `"Right now, it's 42°F (6°C) partly cloudy in San Francisco."`;
57 changes: 57 additions & 0 deletions packages/xsschema/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
{
"name": "xsschema",
"type": "module",
"version": "0.0.31",
"private": true,
"description": "extra-small, Standard Schema-based alternative to typeschema.",
"author": "Moeru AI",
"license": "MIT",
"homepage": "https://xsai.js.org",
"repository": {
"type": "git",
"url": "git+https://github.com/moeru-ai/xsai.git",
"directory": "packages/xsschema"
},
"bugs": "https://github.com/moeru-ai/xsai/issues",
"keywords": [
"xsai",
"standard-schema",
"typeschema"
],
"sideEffects": false,
"exports": {
".": {
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
}
},
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"files": [
"dist"
],
"scripts": {
"build": "pkgroll",
"build:watch": "pkgroll --watch"
},
"peerDependencies": {
"@valibot/to-json-schema": "catalog:",
"zod-to-json-schema": "^3.24.1"
},
"peerDependenciesMeta": {
"@valibot/to-json-schema": {
"optional": true
},
"zod-to-json-schema": {
"optional": true
}
},
"dependencies": {
"@standard-schema/spec": "^1.0.0"
},
"devDependencies": {
"@types/json-schema": "^7.0.15",
"@valibot/to-json-schema": "catalog:",
"zod-to-json-schema": "^3.24.1"
}
}
3 changes: 3 additions & 0 deletions packages/xsschema/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export { toJsonSchema, toJsonSchema as toJSONSchema } from './to-json-schema'
export type { Infer, InferIn, JSONSchema as JsonSchema, JSONSchema, Schema } from './types'
export { validate } from './validate'
15 changes: 15 additions & 0 deletions packages/xsschema/src/to-json-schema/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import type { StandardSchemaV1 } from '@standard-schema/spec'
import type { JSONSchema7 } from 'json-schema'

export const toJsonSchema = async (schema: StandardSchemaV1): Promise<JSONSchema7> => {
switch (schema['~standard'].vendor) {
case 'valibot':
// eslint-disable-next-line ts/no-unsafe-argument
return (await import('./valibot')).toJsonSchema(schema as any)
case 'zod':
// eslint-disable-next-line ts/no-unsafe-argument, @masknet/type-prefer-return-type-annotation
return (await import('./zod')).toJsonSchema(schema as any) as JSONSchema7
default:
throw new Error(`xsschema: Unsupported schema vendor ${schema['~standard'].vendor}`)
}
}
1 change: 1 addition & 0 deletions packages/xsschema/src/to-json-schema/valibot.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { toJsonSchema } from '@valibot/to-json-schema'
1 change: 1 addition & 0 deletions packages/xsschema/src/to-json-schema/zod.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { zodToJsonSchema as toJsonSchema } from 'zod-to-json-schema'
7 changes: 7 additions & 0 deletions packages/xsschema/src/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import type { StandardSchemaV1 } from '@standard-schema/spec'

export type { StandardSchemaV1 as Schema } from '@standard-schema/spec'
export type { JSONSchema7 as JSONSchema } from 'json-schema'

export type Infer<T extends StandardSchemaV1> = StandardSchemaV1.InferOutput<T>
export type InferIn<T extends StandardSchemaV1> = StandardSchemaV1.InferInput<T>
13 changes: 13 additions & 0 deletions packages/xsschema/src/validate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import type { StandardSchemaV1 } from '@standard-schema/spec'

export const validate = async <T extends StandardSchemaV1>(schema: T, input: StandardSchemaV1.InferInput<T>): Promise<StandardSchemaV1.InferOutput<T>> => {
let result = schema['~standard'].validate(input)
if (result instanceof Promise)
result = await result

if (result.issues) {
throw new Error(JSON.stringify(result.issues, null, 2))
}

return result.value
}
4 changes: 4 additions & 0 deletions packages/xsschema/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"extends": "@importantimport/tsconfig/app.json",
"include": ["src"]
}
Loading

0 comments on commit 29e4d21

Please sign in to comment.