weifuwu 0.25.2 → 0.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (208) hide show
  1. package/README.md +291 -2489
  2. package/ai/provider.ts +129 -0
  3. package/ai/stream.ts +63 -0
  4. package/cli.ts +55 -257
  5. package/core/cookie.ts +114 -0
  6. package/core/env.ts +142 -0
  7. package/core/logger.ts +72 -0
  8. package/core/router.ts +795 -0
  9. package/core/serve.ts +294 -0
  10. package/core/sse.ts +85 -0
  11. package/core/trace.ts +146 -0
  12. package/graphql.ts +267 -0
  13. package/hub.ts +133 -0
  14. package/index.ts +71 -0
  15. package/mailer.ts +81 -0
  16. package/middleware/compress.ts +103 -0
  17. package/middleware/cors.ts +81 -0
  18. package/middleware/csrf.ts +112 -0
  19. package/middleware/flash.ts +144 -0
  20. package/middleware/health.ts +44 -0
  21. package/middleware/helmet.ts +98 -0
  22. package/middleware/i18n.ts +175 -0
  23. package/middleware/rate-limit.ts +167 -0
  24. package/middleware/request-id.ts +60 -0
  25. package/middleware/static.ts +149 -0
  26. package/middleware/theme.ts +84 -0
  27. package/middleware/upload.ts +168 -0
  28. package/middleware/validate.ts +186 -0
  29. package/package.json +14 -36
  30. package/postgres/client.ts +132 -0
  31. package/postgres/index.ts +4 -0
  32. package/postgres/module.ts +37 -0
  33. package/postgres/schema/columns.ts +186 -0
  34. package/postgres/schema/index.ts +36 -0
  35. package/postgres/schema/sql.ts +39 -0
  36. package/postgres/schema/table.ts +548 -0
  37. package/postgres/schema/where.ts +99 -0
  38. package/postgres/types.ts +48 -0
  39. package/queue/cron.ts +90 -0
  40. package/queue/index.ts +654 -0
  41. package/queue/types.ts +60 -0
  42. package/redis/client.ts +24 -0
  43. package/{dist/redis/index.d.ts → redis/index.ts} +2 -2
  44. package/redis/types.ts +28 -0
  45. package/types.ts +78 -0
  46. package/cli/template/app.ts +0 -22
  47. package/cli/template/index.ts +0 -10
  48. package/cli/template/locales/en.json +0 -13
  49. package/cli/template/locales/zh-CN.json +0 -13
  50. package/cli/template/locales/zh-TW.json +0 -13
  51. package/cli/template/locales/zh.json +0 -13
  52. package/cli/template/ui/app/globals.css +0 -2
  53. package/cli/template/ui/app/layout.tsx +0 -15
  54. package/cli/template/ui/app/page.tsx +0 -124
  55. package/cli/template/ui/components/Greeting.tsx +0 -3
  56. package/dist/agent/client.d.ts +0 -2
  57. package/dist/agent/index.d.ts +0 -2
  58. package/dist/agent/rest.d.ts +0 -14
  59. package/dist/agent/run.d.ts +0 -19
  60. package/dist/agent/types.d.ts +0 -55
  61. package/dist/ai/provider.d.ts +0 -45
  62. package/dist/ai/utils.d.ts +0 -5
  63. package/dist/ai/workflow.d.ts +0 -17
  64. package/dist/ai-sdk.d.ts +0 -2
  65. package/dist/ai.d.ts +0 -13
  66. package/dist/analytics.d.ts +0 -45
  67. package/dist/auth.d.ts +0 -22
  68. package/dist/cache.d.ts +0 -74
  69. package/dist/cli.d.ts +0 -2
  70. package/dist/cli.js +0 -302
  71. package/dist/client-locale.d.ts +0 -25
  72. package/dist/client-pref.d.ts +0 -3
  73. package/dist/client-router.d.ts +0 -300
  74. package/dist/client-state.d.ts +0 -22
  75. package/dist/client-theme.d.ts +0 -36
  76. package/dist/compile.d.ts +0 -15
  77. package/dist/compress.d.ts +0 -20
  78. package/dist/cookie.d.ts +0 -36
  79. package/dist/cors.d.ts +0 -25
  80. package/dist/cron-utils.d.ts +0 -73
  81. package/dist/csrf.d.ts +0 -47
  82. package/dist/deploy/config.d.ts +0 -2
  83. package/dist/deploy/gateway.d.ts +0 -2
  84. package/dist/deploy/index.d.ts +0 -4
  85. package/dist/deploy/manager.d.ts +0 -16
  86. package/dist/deploy/process.d.ts +0 -14
  87. package/dist/deploy/types.d.ts +0 -53
  88. package/dist/env.d.ts +0 -69
  89. package/dist/error-boundary.d.ts +0 -2
  90. package/dist/flash.d.ts +0 -90
  91. package/dist/fts.d.ts +0 -36
  92. package/dist/graphql.d.ts +0 -16
  93. package/dist/head.d.ts +0 -6
  94. package/dist/health.d.ts +0 -24
  95. package/dist/helmet.d.ts +0 -33
  96. package/dist/html-shell.d.ts +0 -1
  97. package/dist/hub.d.ts +0 -37
  98. package/dist/i18n.d.ts +0 -39
  99. package/dist/iii/client.d.ts +0 -2
  100. package/dist/iii/index.d.ts +0 -4
  101. package/dist/iii/register-worker.d.ts +0 -9
  102. package/dist/iii/rest.d.ts +0 -3
  103. package/dist/iii/stream.d.ts +0 -82
  104. package/dist/iii/types.d.ts +0 -121
  105. package/dist/iii/worker.d.ts +0 -2
  106. package/dist/iii/ws.d.ts +0 -22
  107. package/dist/index.d.ts +0 -101
  108. package/dist/index.js +0 -12752
  109. package/dist/kb/index.d.ts +0 -3
  110. package/dist/kb/types.d.ts +0 -72
  111. package/dist/layout.d.ts +0 -2
  112. package/dist/live.d.ts +0 -7
  113. package/dist/logdb/client.d.ts +0 -2
  114. package/dist/logdb/index.d.ts +0 -2
  115. package/dist/logdb/rest.d.ts +0 -5
  116. package/dist/logdb/types.d.ts +0 -27
  117. package/dist/logger.d.ts +0 -16
  118. package/dist/mailer.d.ts +0 -51
  119. package/dist/mcp.d.ts +0 -34
  120. package/dist/messager/agent.d.ts +0 -11
  121. package/dist/messager/client.d.ts +0 -2
  122. package/dist/messager/index.d.ts +0 -2
  123. package/dist/messager/rest.d.ts +0 -15
  124. package/dist/messager/types.d.ts +0 -57
  125. package/dist/messager/ws.d.ts +0 -14
  126. package/dist/module-server.d.ts +0 -9
  127. package/dist/not-found.d.ts +0 -2
  128. package/dist/notifier/client.d.ts +0 -2
  129. package/dist/notifier/index.d.ts +0 -2
  130. package/dist/notifier/types.d.ts +0 -105
  131. package/dist/opencode/client.d.ts +0 -2
  132. package/dist/opencode/index.d.ts +0 -2
  133. package/dist/opencode/permissions.d.ts +0 -5
  134. package/dist/opencode/prompt.d.ts +0 -8
  135. package/dist/opencode/rest.d.ts +0 -16
  136. package/dist/opencode/run.d.ts +0 -13
  137. package/dist/opencode/session.d.ts +0 -26
  138. package/dist/opencode/skills.d.ts +0 -4
  139. package/dist/opencode/tools/bash.d.ts +0 -6
  140. package/dist/opencode/tools/edit.d.ts +0 -19
  141. package/dist/opencode/tools/glob.d.ts +0 -9
  142. package/dist/opencode/tools/grep.d.ts +0 -17
  143. package/dist/opencode/tools/index.d.ts +0 -12
  144. package/dist/opencode/tools/question.d.ts +0 -5
  145. package/dist/opencode/tools/read.d.ts +0 -16
  146. package/dist/opencode/tools/skill.d.ts +0 -18
  147. package/dist/opencode/tools/web.d.ts +0 -18
  148. package/dist/opencode/tools/write.d.ts +0 -13
  149. package/dist/opencode/types.d.ts +0 -90
  150. package/dist/opencode/ws.d.ts +0 -21
  151. package/dist/permissions.d.ts +0 -51
  152. package/dist/postgres/client.d.ts +0 -4
  153. package/dist/postgres/index.d.ts +0 -4
  154. package/dist/postgres/module.d.ts +0 -17
  155. package/dist/postgres/schema/columns.d.ts +0 -99
  156. package/dist/postgres/schema/index.d.ts +0 -6
  157. package/dist/postgres/schema/sql.d.ts +0 -22
  158. package/dist/postgres/schema/table.d.ts +0 -141
  159. package/dist/postgres/schema/where.d.ts +0 -29
  160. package/dist/postgres/types.d.ts +0 -50
  161. package/dist/queue/index.d.ts +0 -2
  162. package/dist/queue/types.d.ts +0 -62
  163. package/dist/rate-limit.d.ts +0 -45
  164. package/dist/react.d.ts +0 -14
  165. package/dist/react.js +0 -751
  166. package/dist/redis/client.d.ts +0 -2
  167. package/dist/redis/types.d.ts +0 -18
  168. package/dist/request-id.d.ts +0 -40
  169. package/dist/router.d.ts +0 -73
  170. package/dist/s3.d.ts +0 -68
  171. package/dist/seo.d.ts +0 -104
  172. package/dist/serve.d.ts +0 -38
  173. package/dist/server-registry.d.ts +0 -10
  174. package/dist/session.d.ts +0 -117
  175. package/dist/sse.d.ts +0 -47
  176. package/dist/ssr-entries.d.ts +0 -4
  177. package/dist/ssr.d.ts +0 -11
  178. package/dist/static.d.ts +0 -23
  179. package/dist/stream.d.ts +0 -24
  180. package/dist/tailwind.d.ts +0 -15
  181. package/dist/tenant/client.d.ts +0 -2
  182. package/dist/tenant/graphql.d.ts +0 -3
  183. package/dist/tenant/index.d.ts +0 -2
  184. package/dist/tenant/rest.d.ts +0 -3
  185. package/dist/tenant/schema.d.ts +0 -5
  186. package/dist/tenant/types.d.ts +0 -48
  187. package/dist/tenant/utils.d.ts +0 -9
  188. package/dist/test-utils.d.ts +0 -194
  189. package/dist/theme.d.ts +0 -31
  190. package/dist/trace.d.ts +0 -95
  191. package/dist/tsx-context.d.ts +0 -32
  192. package/dist/types.d.ts +0 -47
  193. package/dist/upload.d.ts +0 -55
  194. package/dist/use-action.d.ts +0 -42
  195. package/dist/use-agent-stream.d.ts +0 -49
  196. package/dist/use-flash-message.d.ts +0 -17
  197. package/dist/use-websocket.d.ts +0 -42
  198. package/dist/user/client.d.ts +0 -30
  199. package/dist/user/index.d.ts +0 -2
  200. package/dist/user/oauth-login.d.ts +0 -21
  201. package/dist/user/oauth2.d.ts +0 -31
  202. package/dist/user/types.d.ts +0 -178
  203. package/dist/validate.d.ts +0 -32
  204. package/dist/vendor.d.ts +0 -7
  205. package/dist/webhook.d.ts +0 -79
  206. package/opencode/ui/app/globals.css +0 -1
  207. package/opencode/ui/app/layout.tsx +0 -13
  208. package/opencode/ui/app/page.tsx +0 -523
package/queue/types.ts ADDED
@@ -0,0 +1,60 @@
1
+ import type { Redis, Context, Middleware, Closeable } from '../types.ts'
2
+
3
+ declare module '../types.ts' {
4
+ interface Context {
5
+ queue: Queue
6
+ }
7
+ }
8
+
9
+ export interface QueueJob<T = unknown> {
10
+ id: string
11
+ type: string
12
+ payload: T
13
+ createdAt: number
14
+ runAt: number
15
+ schedule?: string
16
+ }
17
+
18
+ export interface QueueOptions {
19
+ /** Backend store. Default: 'memory'. */
20
+ store?: 'memory' | 'pg' | 'redis'
21
+ redis?: Redis
22
+ url?: string
23
+ prefix?: string
24
+ pollInterval?: number
25
+ /** PostgreSQL client (required when store: 'pg'). */
26
+ pg?: { sql: import('../types.ts').SqlClient }
27
+ }
28
+
29
+ export interface QueueInjected {
30
+ queue: Queue
31
+ }
32
+
33
+ export interface QueueJobWithError<T = unknown> extends QueueJob<T> {
34
+ error: string
35
+ failedAt: number
36
+ }
37
+
38
+ export interface Queue extends Middleware<Context, Context & QueueInjected>, Closeable {
39
+ /** Register a cron job. Uses queue's backend (memory/pg/redis) for execution. */
40
+ cron(pattern: string, handler: () => void | Promise<void>): { stop: () => void }
41
+ add<T>(type: string, payload: T, opts?: { delay?: number; schedule?: string }): Promise<string>
42
+ process<T>(type: string, handler: (job: QueueJob<T>) => Promise<void>): void
43
+ run(): Promise<void>
44
+ stats(): {
45
+ running: boolean
46
+ inflight: number
47
+ processed: number
48
+ failed: number
49
+ handlers: number
50
+ maxConcurrent: number
51
+ }
52
+ jobs(limit?: number): Promise<QueueJob[]>
53
+ failedJobs(limit?: number): Promise<QueueJobWithError[]>
54
+ retryFailed(jobId: string): Promise<boolean>
55
+ retryAllFailed(type?: string): Promise<number>
56
+ dashboard(): import('../core/router.ts').Router
57
+ /** Create the jobs table (PG mode only; safe to call multiple times). */
58
+ migrate?(): Promise<void>
59
+ close(): Promise<void>
60
+ }
@@ -0,0 +1,24 @@
1
+ /* eslint-disable no-console */
2
+ import { Redis as IORedis } from 'ioredis'
3
+ import type { Context, Handler } from '../types.ts'
4
+ import type { RedisOptions, RedisClient } from './types.ts'
5
+
6
+ export function redis(opts?: string | RedisOptions): RedisClient {
7
+ const options: RedisOptions = typeof opts === 'string' ? { url: opts } : (opts ?? {})
8
+
9
+ const url = options.url ?? process.env.REDIS_URL ?? 'redis://localhost:6379'
10
+ const client = new IORedis(url, options)
11
+
12
+ client.on('error', (err: Error) => console.error('[redis]', err.message))
13
+
14
+ const mw = ((req: Request, ctx: Context, next: Handler) => {
15
+ ctx.redis = client
16
+ return next(req, ctx)
17
+ }) as unknown as RedisClient
18
+
19
+ mw.__meta = { injects: ['redis'], depends: [] }
20
+ mw.redis = client
21
+ mw.close = () => client.quit() as unknown as Promise<void>
22
+
23
+ return mw
24
+ }
@@ -1,2 +1,2 @@
1
- export { redis } from './client.ts';
2
- export type { RedisOptions, RedisClient, RedisInjected } from './types.ts';
1
+ export { redis } from './client.ts'
2
+ export type { RedisOptions, RedisClient, RedisInjected } from './types.ts'
package/redis/types.ts ADDED
@@ -0,0 +1,28 @@
1
+ import type {
2
+ Redis,
3
+ RedisOptions as IORedisOptions,
4
+ Context,
5
+ Middleware,
6
+ Closeable,
7
+ } from '../types.ts'
8
+
9
+ declare module '../types.ts' {
10
+ interface Context {
11
+ redis: Redis
12
+ }
13
+ }
14
+
15
+ export type { Redis }
16
+
17
+ export type RedisOptions = IORedisOptions & {
18
+ url?: string
19
+ }
20
+
21
+ export interface RedisInjected {
22
+ redis: Redis
23
+ }
24
+
25
+ export interface RedisClient extends Middleware<Context, Context & RedisInjected>, Closeable {
26
+ redis: Redis
27
+ close: () => Promise<void>
28
+ }
package/types.ts ADDED
@@ -0,0 +1,78 @@
1
+ import type postgres from 'postgres'
2
+
3
+ /** Untyped postgres.js SQL client. Use typed `Sql<{ table: { col: type } }>` for schemas. */
4
+ export type SqlClient = postgres.Sql<Record<string, unknown>>
5
+
6
+ /** Re-export for downstream usage. */
7
+ export type { Sql } from 'postgres'
8
+ export type { WebSocket } from 'ws'
9
+ export type { Redis, RedisOptions } from 'ioredis'
10
+
11
+ // Context — extensible via module augmentation.
12
+ // Built-in middleware modules declare additional properties here.
13
+ // e.g. postgres/types.ts → `declare module '../types.ts' { interface Context { sql: SqlClient } }`
14
+ export interface Context {
15
+ params: Record<string, string>
16
+ query: Record<string, string>
17
+ mountPath?: string
18
+ [key: string]: unknown // allow arbitrary middleware-injected data
19
+ }
20
+
21
+ // Generic handler — T extends Context so middleware-injected properties are visible.
22
+ // Default T = Context means no generics needed for simple cases.
23
+ export type Handler<T extends Context = Context> = (
24
+ req: Request,
25
+ ctx: T,
26
+ ) => Response | Promise<Response>
27
+
28
+ /**
29
+ * Metadata for middleware dependency checking.
30
+ * Middleware factories attach this for runtime validation.
31
+ */
32
+ export interface MiddlewareMeta {
33
+ /** Fields this middleware injects into ctx. */
34
+ injects: string[]
35
+ /** Fields this middleware depends on (must be injected earlier). */
36
+ depends: string[]
37
+ }
38
+
39
+ // Generic middleware — In receives accumulated context from previous middlewares,
40
+ // Out adds new properties. next receives the enriched Out type.
41
+ // Default In = Out = Context means backward-compatible.
42
+ export type Middleware<In extends Context = Context, Out extends In = In> = {
43
+ (req: Request, ctx: In, next: Handler<Out>): Response | Promise<Response>
44
+ __meta?: MiddlewareMeta
45
+ }
46
+
47
+ export type ErrorHandler<T extends Context = Context> = (
48
+ error: Error,
49
+ req: Request,
50
+ ctx: T,
51
+ ) => Response | Promise<Response>
52
+
53
+ /**
54
+ * Interface for resources that require explicit cleanup (connections, pools, timers).
55
+ * All stateful modules implement this.
56
+ */
57
+ export interface Closeable {
58
+ /** Release all resources. Call once when shutting down. */
59
+ close(): Promise<void>
60
+ }
61
+
62
+ /**
63
+ * HTTP error with an explicit status code.
64
+ * Throw from a handler or middleware to return a non-200 response.
65
+ *
66
+ * ```ts
67
+ * if (!resource) throw new HttpError('Not found', 404)
68
+ * serve() catches it and returns the status code.
69
+ * ```
70
+ */
71
+ export class HttpError extends Error {
72
+ status: number
73
+ constructor(message: string, status: number) {
74
+ super(message)
75
+ this.name = 'HttpError'
76
+ this.status = status
77
+ }
78
+ }
@@ -1,22 +0,0 @@
1
- import { Router, ssr, theme, i18n } from '../../index.ts'
2
-
3
- export const app = new Router()
4
- app.use(theme())
5
- app.use(i18n({ dir: './locales' }))
6
- app.use('/', ssr({ dir: './ui' }))
7
- app.use(async (req, ctx, next) => {
8
- ctx.loaderData = {
9
- features: [
10
- { title: 'SSR + HMR', desc: 'State-preserving hot reload' },
11
- { title: 'i18n', desc: 'Built-in internationalization' },
12
- { title: 'Theme', desc: 'Light/dark mode toggle' },
13
- ],
14
- }
15
- return next(req, ctx)
16
- })
17
- app.get('/api/ping', () => Response.json({ pong: true, time: new Date().toISOString() }))
18
- app.ws('/ws/echo', {
19
- message(ws, _ctx, data) {
20
- ws.send(`echo: ${data}`)
21
- },
22
- })
@@ -1,10 +0,0 @@
1
- import { loadEnv, serve } from '../../index.ts'
2
- import { app } from './app.ts'
3
-
4
- loadEnv()
5
- const port = Number(process.env.PORT) || 3000
6
- const srv = serve(app.handler(), { port, websocket: app.websocketHandler(), shutdown: false })
7
- process.on('SIGINT', () => {
8
- srv.close()
9
- process.exit(0)
10
- })
@@ -1,13 +0,0 @@
1
- {
2
- "nav": { "home": "Home", "docs": "Docs", "api": "API" },
3
- "hero": { "title": "Build Faster", "subtitle": "A modern web framework for Node.js" },
4
- "cta": { "start": "Get Started", "learn": "Learn More" },
5
- "demo": {
6
- "title": "WebSocket Demo",
7
- "placeholder": "Type a message...",
8
- "send": "Send",
9
- "echo": "Echo"
10
- },
11
- "ws": { "connected": "Connected", "connecting": "Connecting...", "disconnected": "Disconnected" },
12
- "footer": { "privacy": "Privacy", "terms": "Terms" }
13
- }
@@ -1,13 +0,0 @@
1
- {
2
- "nav": { "home": "首页", "docs": "文档", "api": "API" },
3
- "hero": { "title": "更快地构建", "subtitle": "一个现代的 Node.js Web 框架" },
4
- "cta": { "start": "开始使用", "learn": "了解更多" },
5
- "demo": {
6
- "title": "WebSocket 演示",
7
- "placeholder": "输入消息...",
8
- "send": "发送",
9
- "echo": "回声"
10
- },
11
- "ws": { "connected": "已连接", "connecting": "连接中...", "disconnected": "未连接" },
12
- "footer": { "privacy": "隐私", "terms": "条款" }
13
- }
@@ -1,13 +0,0 @@
1
- {
2
- "nav": { "home": "首頁", "docs": "文件", "api": "API" },
3
- "hero": { "title": "更快構建", "subtitle": "一個現代的 Node.js Web 框架" },
4
- "cta": { "start": "開始使用", "learn": "了解更多" },
5
- "demo": {
6
- "title": "WebSocket 演示",
7
- "placeholder": "輸入訊息...",
8
- "send": "發送",
9
- "echo": "回聲"
10
- },
11
- "ws": { "connected": "已連線", "connecting": "連線中...", "disconnected": "未連線" },
12
- "footer": { "privacy": "隱私", "terms": "條款" }
13
- }
@@ -1,13 +0,0 @@
1
- {
2
- "nav": { "home": "首页", "docs": "文档", "api": "API" },
3
- "hero": { "title": "更快地构建", "subtitle": "一个现代的 Node.js Web 框架" },
4
- "cta": { "start": "开始使用", "learn": "了解更多" },
5
- "demo": {
6
- "title": "WebSocket 演示",
7
- "placeholder": "输入消息...",
8
- "send": "发送",
9
- "echo": "回声"
10
- },
11
- "ws": { "connected": "已连接", "connecting": "连接中...", "disconnected": "未连接" },
12
- "footer": { "privacy": "隐私", "terms": "条款" }
13
- }
@@ -1,2 +0,0 @@
1
- @import 'tailwindcss';
2
- @variant dark (&:where([data-theme="dark"] *));
@@ -1,15 +0,0 @@
1
- import { ReactNode } from 'react'
2
-
3
- export default function RootLayout({ children }: { children: ReactNode }) {
4
- return (
5
- <html lang="en">
6
- <head>
7
- <meta charSet="utf-8" />
8
- <meta name="viewport" content="width=device-width, initial-scale=1" />
9
- </head>
10
- <body>
11
- <main>{children}</main>
12
- </body>
13
- </html>
14
- )
15
- }
@@ -1,124 +0,0 @@
1
- import { useState } from 'react'
2
- import { useWebsocket, useLoaderData, useLocale, useTheme } from '../../../../react.ts'
3
- import Greeting from '../components/Greeting.tsx'
4
-
5
- export default function Home() {
6
- const [input, setInput] = useState('')
7
- const { send, lastMessage, readyState } = useWebsocket('/ws/echo')
8
- const { locale, t, setLocale } = useLocale()
9
- const { resolvedTheme, setTheme } = useTheme()
10
- const ld = useLoaderData<{ features?: { title: string; desc: string }[] }>()
11
-
12
- return (
13
- <div className="min-h-screen bg-white dark:bg-gray-950 text-gray-900 dark:text-gray-100">
14
- {/* Navbar */}
15
- <header className="border-b dark:border-gray-800">
16
- <div className="max-w-5xl mx-auto flex items-center justify-between h-14 px-4">
17
- <span className="font-bold text-lg">weifuwu</span>
18
- <nav className="hidden sm:flex gap-6 text-sm">
19
- <span className="hover:text-blue-600 transition cursor-pointer">{t('nav.home')}</span>
20
- <span className="hover:text-blue-600 transition cursor-pointer">{t('nav.docs')}</span>
21
- <span className="hover:text-blue-600 transition cursor-pointer">{t('nav.api')}</span>
22
- </nav>
23
- <div className="flex items-center gap-2 text-sm">
24
- <button
25
- onClick={() => setLocale(locale === 'en' ? 'zh-CN' : 'en')}
26
- className="px-2 py-1 rounded border dark:border-gray-700 hover:bg-gray-100 dark:hover:bg-gray-800 transition"
27
- >
28
- {locale === 'en' ? '中文' : 'EN'}
29
- </button>
30
- <button
31
- onClick={() => setTheme(resolvedTheme === 'light' ? 'dark' : 'light')}
32
- className="px-2 py-1 rounded border dark:border-gray-700 hover:bg-gray-100 dark:hover:bg-gray-800 transition"
33
- >
34
- {resolvedTheme === 'light' ? '🌙' : '☀️'}
35
- </button>
36
- </div>
37
- </div>
38
- </header>
39
-
40
- {/* Hero */}
41
- <section className="text-center py-20 px-4">
42
- <h1 className="text-5xl font-bold mb-4">{t('hero.title')}</h1>
43
- <p className="text-xl text-gray-500 dark:text-gray-400 mb-8">{t('hero.subtitle')}</p>
44
- <Greeting name="Weifuwu" />
45
- <div className="flex justify-center gap-4 mt-8">
46
- <a
47
- href="#"
48
- className="px-6 py-2.5 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition font-medium"
49
- >
50
- {t('cta.start')}
51
- </a>
52
- <a
53
- href="#"
54
- className="px-6 py-2.5 border dark:border-gray-700 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-800 transition font-medium"
55
- >
56
- {t('cta.learn')}
57
- </a>
58
- </div>
59
- </section>
60
-
61
- {/* Features */}
62
- {ld.features && (
63
- <section className="max-w-4xl mx-auto grid grid-cols-1 md:grid-cols-3 gap-6 px-4 pb-20">
64
- {ld.features.map((f, i) => (
65
- <div
66
- key={i}
67
- className="p-6 rounded-xl border dark:border-gray-800 bg-gray-50 dark:bg-gray-900"
68
- >
69
- <h3 className="font-semibold mb-2">{f.title}</h3>
70
- <p className="text-sm text-gray-500 dark:text-gray-400">{f.desc}</p>
71
- </div>
72
- ))}
73
- </section>
74
- )}
75
-
76
- {/* WebSocket demo */}
77
- <section className="max-w-xl mx-auto px-4 pb-20">
78
- <div className="border dark:border-gray-800 rounded-xl p-6 bg-gray-50 dark:bg-gray-900 space-y-4">
79
- <h2 className="font-semibold">{t('demo.title')}</h2>
80
- <p className="text-sm text-gray-500 dark:text-gray-400">
81
- {readyState === 1
82
- ? t('ws.connected')
83
- : readyState === 0
84
- ? t('ws.connecting')
85
- : t('ws.disconnected')}
86
- </p>
87
- <div className="flex gap-2">
88
- <input
89
- value={input}
90
- onChange={(e) => setInput(e.target.value)}
91
- onKeyDown={(e) => {
92
- if (e.key === 'Enter') {
93
- send(input)
94
- setInput('')
95
- }
96
- }}
97
- placeholder={t('demo.placeholder')}
98
- className="flex-1 border dark:border-gray-700 rounded px-3 py-2 text-sm bg-white dark:bg-gray-950 outline-none focus:border-blue-500 transition"
99
- />
100
- <button
101
- onClick={() => {
102
- send(input)
103
- setInput('')
104
- }}
105
- className="px-4 py-2 bg-blue-600 text-white rounded text-sm hover:bg-blue-700 transition font-medium"
106
- >
107
- {t('demo.send')}
108
- </button>
109
- </div>
110
- {lastMessage && (
111
- <p className="text-sm text-gray-600 dark:text-gray-400">
112
- <span className="font-medium">{t('demo.echo')}:</span> {lastMessage}
113
- </p>
114
- )}
115
- </div>
116
- </section>
117
-
118
- {/* Footer */}
119
- <footer className="border-t dark:border-gray-800 py-8 text-center text-sm text-gray-500">
120
- © 2026 MyApp · {t('footer.privacy')} · {t('footer.terms')}
121
- </footer>
122
- </div>
123
- )
124
- }
@@ -1,3 +0,0 @@
1
- export default function Greeting({ name }: { name: string }) {
2
- return <span className="text-red-500 font-bold">{name}!</span>
3
- }
@@ -1,2 +0,0 @@
1
- import type { AgentOptions, AgentModule } from './types.ts';
2
- export declare function agent(options: AgentOptions): AgentModule;
@@ -1,2 +0,0 @@
1
- export { agent } from './client.ts';
2
- export type { AgentOptions, AgentModule, AgentConfig, RunParams, RunResult } from './types.ts';
@@ -1,14 +0,0 @@
1
- import { Router } from '../router.ts';
2
- import { type BoundTable } from '../postgres/schema/index.ts';
3
- import type { RunParams } from './types.ts';
4
- interface RestDeps {
5
- agents: BoundTable<any>;
6
- runs: BoundTable<any>;
7
- knowledge: BoundTable<any>;
8
- runner: {
9
- run: (agentId: number, params: RunParams) => Promise<any>;
10
- addKnowledge: (agentId: number, title: string, content: string) => Promise<any>;
11
- };
12
- }
13
- export declare function buildRouter(deps: RestDeps): Router;
14
- export {};
@@ -1,19 +0,0 @@
1
- import { type Tool } from 'ai';
2
- import type { SqlClient } from '../vendor.ts';
3
- import type { BoundTable } from '../postgres/schema/index.ts';
4
- import type { AIProvider } from '../ai/provider.ts';
5
- import type { RunParams, RunResult, KnowledgeDoc } from './types.ts';
6
- interface RunnerDeps {
7
- sql: SqlClient;
8
- agents: BoundTable<Record<string, unknown>>;
9
- runs: BoundTable<Record<string, unknown>>;
10
- knowledge: BoundTable<Record<string, unknown>>;
11
- provider: AIProvider;
12
- modelName?: string;
13
- userTools?: Record<string, Tool>;
14
- }
15
- export declare function createRunner(deps: RunnerDeps): {
16
- run: (agentId: number, params: RunParams) => Promise<RunResult>;
17
- addKnowledge: (agentId: number, title: string, content: string) => Promise<KnowledgeDoc>;
18
- };
19
- export {};
@@ -1,55 +0,0 @@
1
- import type { Router } from '../router.ts';
2
- import type { LanguageModel, EmbeddingModel, Tool } from 'ai';
3
- import type { AIProvider } from '../ai/provider.ts';
4
- import type { Closeable } from '../types.ts';
5
- export interface AgentConfig {
6
- id: number;
7
- tenant_id: string | null;
8
- name: string;
9
- description: string;
10
- type: 'chat' | 'tool-use';
11
- model: string;
12
- system_prompt: string;
13
- owner_id: number;
14
- active: boolean;
15
- created_at: string;
16
- updated_at: string;
17
- }
18
- export interface KnowledgeDoc {
19
- id: number;
20
- agent_id: number;
21
- title: string;
22
- content: string;
23
- embedding?: number[];
24
- metadata: Record<string, unknown>;
25
- created_at: string;
26
- }
27
- export interface RunParams {
28
- input: string;
29
- stream?: boolean;
30
- messages?: Array<{
31
- role: string;
32
- content: string;
33
- }>;
34
- }
35
- export type RunResult = {
36
- output: string;
37
- elapsed: number;
38
- } | {
39
- stream: ReadableStream<Uint8Array>;
40
- };
41
- export interface AgentOptions {
42
- pg: import('../postgres/types.ts').PostgresClient;
43
- /** AI provider for model and embedding resolution. Overridden by explicit model/embeddingModel. */
44
- provider?: AIProvider;
45
- model?: LanguageModel;
46
- embeddingModel?: EmbeddingModel;
47
- embeddingDimension?: number;
48
- tools?: Record<string, Tool>;
49
- }
50
- export interface AgentModule extends Router, Closeable {
51
- migrate: () => Promise<void>;
52
- run: (agentId: number, params: RunParams) => Promise<RunResult>;
53
- addKnowledge: (agentId: number, title: string, content: string) => Promise<KnowledgeDoc>;
54
- close: () => Promise<void>;
55
- }
@@ -1,45 +0,0 @@
1
- import type { Context, Middleware } from '../types.ts';
2
- import { generateText as aiGenerateText, streamText as aiStreamText, type LanguageModel, type EmbeddingModel } from 'ai';
3
- declare module '../types.ts' {
4
- interface Context {
5
- ai: AIProvider;
6
- }
7
- }
8
- export interface AIProviderInjected {
9
- ai: AIProvider;
10
- }
11
- export interface AIProviderOptions {
12
- /** API base URL (default: OPENAI_BASE_URL env or http://localhost:11434/v1). */
13
- baseURL?: string;
14
- /** API key (default: OPENAI_API_KEY env or 'ollama'). */
15
- apiKey?: string;
16
- /** Chat model name (default: OPENAI_MODEL env or 'qwen3:0.6b'). */
17
- model?: string;
18
- /** Embedding model name (default: OPENAI_EMBEDDING_MODEL env or 'qwen3-embedding:0.6b'). */
19
- embeddingModel?: string;
20
- /** Vector dimension (default: EMBEDDING_DIMENSION env or 1024). */
21
- embeddingDimension?: number;
22
- }
23
- export interface AIProvider {
24
- /** Get the language model. Caches by default; pass a name to override. */
25
- model(name?: string): LanguageModel;
26
- /** Get the embedding model. Caches by default; pass a name to override. */
27
- embeddingModel(name?: string): EmbeddingModel;
28
- /** Embed a single text string into a vector. */
29
- embed(text: string): Promise<number[]>;
30
- /** Embed multiple text strings in batch. */
31
- embedMany(texts: string[]): Promise<number[][]>;
32
- /** The configured vector dimension. */
33
- readonly dimension: number;
34
- /**
35
- * Generate text using the configured model.
36
- * All options are passed through to the AI SDK's `generateText`, with `model` auto-injected.
37
- */
38
- generateText(params: Omit<Parameters<typeof aiGenerateText>[0], 'model'>): ReturnType<typeof aiGenerateText>;
39
- /**
40
- * Stream text using the configured model.
41
- * All options are passed through to the AI SDK's `streamText`, with `model` auto-injected.
42
- */
43
- streamText(params: Omit<Parameters<typeof aiStreamText>[0], 'model'>): ReturnType<typeof aiStreamText>;
44
- }
45
- export declare function aiProvider(options?: AIProviderOptions): Middleware<Context, Context & AIProviderInjected> & AIProvider;
@@ -1,5 +0,0 @@
1
- /**
2
- * Split text into chunks by paragraphs, respecting a max chunk size with overlap.
3
- * Used by both knowledge base and agent modules.
4
- */
5
- export declare function chunkContent(content: string, chunkSize: number, overlap: number): string[];
@@ -1,17 +0,0 @@
1
- import { type LanguageModel } from 'ai';
2
- import type { AIProvider } from './provider.ts';
3
- export declare function runWorkflow(opts?: {
4
- tools?: Record<string, any>;
5
- model?: LanguageModel;
6
- /** AI provider — `provider.model()` is used as fallback if no explicit `model` is set. */
7
- provider?: AIProvider;
8
- maxSteps?: number;
9
- }): import("ai").Tool<{
10
- goal: string;
11
- nodes?: any[];
12
- }, {
13
- result: unknown;
14
- nodeOutputs: {
15
- [k: string]: unknown;
16
- };
17
- }>;
package/dist/ai-sdk.d.ts DELETED
@@ -1,2 +0,0 @@
1
- export { streamText, generateText, generateObject, streamObject, tool, embed, embedMany, smoothStream, } from 'ai';
2
- export { openai, createOpenAI } from '@ai-sdk/openai';
package/dist/ai.d.ts DELETED
@@ -1,13 +0,0 @@
1
- import type { Context } from './types.ts';
2
- import { Router } from './router.ts';
3
- import type { AIProvider } from './ai/provider.ts';
4
- export type AIHandler = (req: Request, ctx: Context) => Record<string, unknown> | Promise<Record<string, unknown>>;
5
- export declare const _ai: Record<string, any>;
6
- /**
7
- * Create a streaming AI endpoint.
8
- *
9
- * @param handler - Returns options for `streamText` or `streamObject` (if `schema` is present).
10
- * @param provider - Optional AI provider. If provided and the handler does not return a `model`,
11
- * `provider.model()` is used as the default.
12
- */
13
- export declare function aiStream(handler: AIHandler, provider?: AIProvider): Promise<Router>;