weifuwu 0.9.6 → 0.10.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.
- package/README.md +183 -43
- package/dist/agent/migrate.d.ts +1 -1
- package/dist/agent/rest.d.ts +1 -1
- package/dist/agent/run.d.ts +2 -2
- package/dist/agent/types.d.ts +2 -2
- package/dist/index.d.ts +3 -1
- package/dist/index.js +1890 -10615
- package/dist/messager/migrate.d.ts +1 -1
- package/dist/messager/rest.d.ts +1 -1
- package/dist/messager/types.d.ts +2 -1
- package/dist/messager/ws.d.ts +1 -1
- package/dist/opencode/client.d.ts +2 -0
- package/dist/opencode/index.d.ts +2 -0
- package/dist/opencode/migrate.d.ts +2 -0
- package/dist/opencode/permissions.d.ts +5 -0
- package/dist/opencode/prompt.d.ts +8 -0
- package/dist/opencode/rest.d.ts +15 -0
- package/dist/opencode/run.d.ts +13 -0
- package/dist/opencode/session.d.ts +26 -0
- package/dist/opencode/skills.d.ts +4 -0
- package/dist/opencode/tools/bash.d.ts +6 -0
- package/dist/opencode/tools/edit.d.ts +19 -0
- package/dist/opencode/tools/glob.d.ts +9 -0
- package/dist/opencode/tools/grep.d.ts +17 -0
- package/dist/opencode/tools/index.d.ts +12 -0
- package/dist/opencode/tools/question.d.ts +5 -0
- package/dist/opencode/tools/read.d.ts +16 -0
- package/dist/opencode/tools/skill.d.ts +18 -0
- package/dist/opencode/tools/web.d.ts +18 -0
- package/dist/opencode/tools/write.d.ts +13 -0
- package/dist/opencode/types.d.ts +90 -0
- package/dist/opencode/ws.d.ts +22 -0
- package/dist/postgres/index.d.ts +3 -1
- package/dist/postgres/module.d.ts +9 -0
- package/dist/postgres/schema/columns.d.ts +33 -0
- package/dist/postgres/schema/index.d.ts +4 -0
- package/dist/postgres/schema/sql.d.ts +7 -0
- package/dist/postgres/schema/table.d.ts +22 -0
- package/dist/postgres/types.d.ts +7 -35
- package/dist/queue/types.d.ts +1 -1
- package/dist/redis/types.d.ts +1 -1
- package/dist/router.d.ts +1 -1
- package/dist/sse.d.ts +10 -0
- package/dist/tenant/graphql.d.ts +1 -1
- package/dist/tenant/migrate.d.ts +1 -1
- package/dist/tenant/rest.d.ts +1 -1
- package/dist/tenant/types.d.ts +2 -1
- package/dist/tsx-context.d.ts +12 -0
- package/dist/tsx-instance.d.ts +32 -0
- package/dist/tsx.d.ts +5 -16
- package/dist/user/types.d.ts +2 -1
- package/dist/vendor.d.ts +4 -0
- package/dist/workflow/engine.d.ts +1 -1
- package/dist/workflow/route.d.ts +1 -1
- package/package.json +5 -4
package/README.md
CHANGED
|
@@ -221,83 +221,203 @@ Features: MIME type detection (20+ types), ETag + If-None-Match (304), directory
|
|
|
221
221
|
|
|
222
222
|
## PostgreSQL
|
|
223
223
|
|
|
224
|
-
Built-in PostgreSQL —
|
|
224
|
+
Built-in PostgreSQL client — connection management, type-safe DDL, transactions, and module lifecycle.
|
|
225
225
|
|
|
226
226
|
```ts
|
|
227
227
|
import { serve, Router, postgres } from 'weifuwu'
|
|
228
|
-
import { z } from 'zod'
|
|
229
228
|
|
|
230
229
|
const app = new Router()
|
|
231
|
-
const pg = postgres()
|
|
230
|
+
const pg = postgres() // reads DATABASE_URL
|
|
231
|
+
app.use(pg) // injects ctx.sql into handlers
|
|
232
|
+
```
|
|
232
233
|
|
|
233
|
-
|
|
234
|
-
id: z.number().optional(), // → SERIAL PRIMARY KEY
|
|
235
|
-
name: z.string().min(1), // → TEXT NOT NULL
|
|
236
|
-
email: z.string().email(), // → TEXT NOT NULL
|
|
237
|
-
age: z.number().optional(), // → INTEGER
|
|
238
|
-
})
|
|
234
|
+
### Type-safe DDL with schema builder
|
|
239
235
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
236
|
+
Define tables declaratively with type inference — no raw SQL for common operations, no Zod needed:
|
|
237
|
+
|
|
238
|
+
```ts
|
|
239
|
+
import { pgTable, serial, uuid, text, integer, boolean, timestamptz, jsonb, sql } from 'weifuwu'
|
|
240
|
+
|
|
241
|
+
const users = pgTable('_users', {
|
|
242
|
+
id: serial('id').primaryKey(),
|
|
243
|
+
name: text('name').notNull(),
|
|
244
|
+
email: text('email').unique().notNull(),
|
|
245
|
+
age: integer('age'),
|
|
246
|
+
active: boolean('active').default(true),
|
|
247
|
+
createdAt: timestamptz('created_at').default(sql`NOW()`),
|
|
248
|
+
metadata: jsonb<{ role: string }>('metadata'),
|
|
249
|
+
})
|
|
243
250
|
```
|
|
244
251
|
|
|
245
|
-
|
|
252
|
+
Supports 10 column types:
|
|
253
|
+
| Builder | DDL | TS Type |
|
|
254
|
+
|---------|-----|---------|
|
|
255
|
+
| `serial()` | `SERIAL` | `number` |
|
|
256
|
+
| `uuid()` | `UUID` | `string` |
|
|
257
|
+
| `text()` | `TEXT` | `string` |
|
|
258
|
+
| `integer()` | `INTEGER` | `number` |
|
|
259
|
+
| `boolean()` | `BOOLEAN` | `boolean` |
|
|
260
|
+
| `timestamptz()` | `TIMESTAMPTZ` | `string` |
|
|
261
|
+
| `jsonb<T>()` | `JSONB` | `T` |
|
|
262
|
+
| `textArray()` | `TEXT[]` | `string[]` |
|
|
263
|
+
| `vector(name, dims)` | `vector(N)` | `number[]` |
|
|
246
264
|
|
|
247
|
-
|
|
248
|
-
User.get(1) // GET /users/:id
|
|
249
|
-
User.list({ name: 'a' }, // GET /users?name=a
|
|
250
|
-
{ limit: 10, offset: 0, sort: { id: 'desc' } })
|
|
251
|
-
// → { rows: User[], count: number }
|
|
265
|
+
Column constraints chainable: `.primaryKey()`, `.notNull()`, `.nullable()`, `.default(value | sql\`...\`)`, `.unique()`, `.references(table, column?, onDelete?)`.
|
|
252
266
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
267
|
+
### DDL execution
|
|
268
|
+
|
|
269
|
+
```ts
|
|
270
|
+
await users.create() // CREATE TABLE IF NOT EXISTS
|
|
271
|
+
await users.createIndex('email') // CREATE INDEX
|
|
272
|
+
await users.createUniqueIndex('slug') // CREATE UNIQUE INDEX
|
|
273
|
+
await users.createIndex('created_at', { desc: true })
|
|
274
|
+
await users.createIndex(['a', 'b']) // multi-column
|
|
275
|
+
await users.createIndex('embedding', { // pgvector HNSW
|
|
276
|
+
type: 'hnsw', operator: 'vector_cosine_ops',
|
|
277
|
+
})
|
|
278
|
+
await users.drop({ cascade: true })
|
|
256
279
|
```
|
|
257
280
|
|
|
258
|
-
|
|
281
|
+
### Complex queries use raw SQL
|
|
259
282
|
|
|
260
283
|
```ts
|
|
261
284
|
app.get('/users/stats', async (req, ctx) => {
|
|
262
285
|
const rows = await ctx.sql`
|
|
263
286
|
SELECT u.*, count(p.id) as posts
|
|
264
|
-
FROM users u LEFT JOIN posts p ON p.user_id = u.id
|
|
287
|
+
FROM ${users} u LEFT JOIN posts p ON p.user_id = u.id
|
|
265
288
|
GROUP BY u.id
|
|
266
289
|
`
|
|
267
290
|
return Response.json(rows)
|
|
268
291
|
})
|
|
269
292
|
```
|
|
270
293
|
|
|
271
|
-
###
|
|
294
|
+
### Transactions
|
|
272
295
|
|
|
273
|
-
|
|
296
|
+
```ts
|
|
297
|
+
const result = await pg.transaction(async (tx) => {
|
|
298
|
+
const [user] = await tx`INSERT INTO "_users" (...) VALUES (...) RETURNING *`
|
|
299
|
+
const [wallet] = await tx`INSERT INTO "_wallets" ("user_id") VALUES (${user.id}) RETURNING *`
|
|
300
|
+
return { user, wallet }
|
|
301
|
+
})
|
|
302
|
+
```
|
|
274
303
|
|
|
275
|
-
|
|
276
|
-
- **Column missing** → `ALTER TABLE ADD COLUMN IF NOT EXISTS`
|
|
277
|
-
- **Existing** → no-op
|
|
304
|
+
### Connection lifecycle
|
|
278
305
|
|
|
279
|
-
|
|
306
|
+
```ts
|
|
307
|
+
const pg = postgres() // reads DATABASE_URL
|
|
308
|
+
const pg = postgres('postgres://...') // explicit connection
|
|
309
|
+
const pg = postgres({
|
|
310
|
+
connection: 'postgres://...',
|
|
311
|
+
max: 10, // pool size
|
|
312
|
+
ssl: { rejectUnauthorized: false }, // SSL options
|
|
313
|
+
idle_timeout: 30, // idle timeout (s)
|
|
314
|
+
connect_timeout: 10, // connection timeout (s)
|
|
315
|
+
closeTimeout: 5, // close grace period (s)
|
|
316
|
+
signal: ac.signal, // abort → sql.end()
|
|
317
|
+
})
|
|
318
|
+
await pg.close()
|
|
319
|
+
```
|
|
280
320
|
|
|
281
|
-
###
|
|
321
|
+
### Module base class
|
|
322
|
+
|
|
323
|
+
Every database module (`opencode`, `messager`, `tenant`, `agent`, `user`) extends `PgModule`:
|
|
282
324
|
|
|
283
325
|
```ts
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
326
|
+
import { PgModule } from 'weifuwu'
|
|
327
|
+
|
|
328
|
+
class MyModule extends PgModule {
|
|
329
|
+
constructor(pg: PostgresClient) {
|
|
330
|
+
super(pg) // sets this.sql = pg.sql
|
|
331
|
+
}
|
|
332
|
+
async migrate() { /* override */ }
|
|
333
|
+
// close() inherited — calls pg.close() automatically
|
|
334
|
+
}
|
|
288
335
|
```
|
|
289
336
|
|
|
290
|
-
|
|
337
|
+
## Opencode
|
|
338
|
+
|
|
339
|
+
AI programming assistant — chat with LLM agents that have access to filesystem tools, skills, and isolated session workspaces.
|
|
291
340
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
341
|
+
```ts
|
|
342
|
+
import { serve, Router, postgres, opencode } from 'weifuwu'
|
|
343
|
+
|
|
344
|
+
const app = new Router()
|
|
345
|
+
const pg = postgres()
|
|
346
|
+
const oc = await opencode({ pg, permissions: { ... } })
|
|
347
|
+
|
|
348
|
+
await oc.migrate()
|
|
349
|
+
app.use('/opencode', await oc.router())
|
|
350
|
+
app.ws('/opencode', oc.wsHandler())
|
|
351
|
+
|
|
352
|
+
serve(app.handler(), { port: 3000, websocket: app.websocketHandler() })
|
|
353
|
+
```
|
|
297
354
|
|
|
298
|
-
|
|
355
|
+
### Session-isolated workspaces
|
|
299
356
|
|
|
300
|
-
|
|
357
|
+
Each session gets its own sandbox directory — tools operate within it, files cannot escape:
|
|
358
|
+
|
|
359
|
+
```
|
|
360
|
+
cwd/.sessions/opencode/1/ ← session 1's workspace
|
|
361
|
+
cwd/.sessions/opencode/2/ ← session 2's workspace
|
|
362
|
+
cwd/.sessions/chat/3/ ← different mount point
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
Workspaces are computed from `cwd { ctx.mountPath } { sessionId }`. The system prompt shows the session's workspace so the LLM knows where it is.
|
|
366
|
+
|
|
367
|
+
### Tools
|
|
368
|
+
|
|
369
|
+
| Tool | Description |
|
|
370
|
+
|------|-------------|
|
|
371
|
+
| `bash` | Execute shell commands in the workspace |
|
|
372
|
+
| `read` | Read files with offset/limit |
|
|
373
|
+
| `write` | Create or overwrite files |
|
|
374
|
+
| `edit` | Exact string replacements |
|
|
375
|
+
| `grep` | Regex content search |
|
|
376
|
+
| `glob` | Glob pattern file search |
|
|
377
|
+
| `web` | Fetch URL content |
|
|
378
|
+
| `question` | Ask the user for input |
|
|
379
|
+
| `skill` | Load a skill on demand |
|
|
380
|
+
|
|
381
|
+
### Skills
|
|
382
|
+
|
|
383
|
+
Skills are discovered from filesystem and loaded on demand via the `skill` tool — no system prompt bloat:
|
|
384
|
+
|
|
385
|
+
- Project: `.opencode/skills/{name}/SKILL.md`
|
|
386
|
+
- Global: `~/.config/opencode/skills/{name}/SKILL.md`
|
|
387
|
+
- Also reads: `.claude/skills/`, `.agents/skills/` (project + global)
|
|
388
|
+
|
|
389
|
+
```ts
|
|
390
|
+
const oc = await opencode({
|
|
391
|
+
pg,
|
|
392
|
+
skills: [{ name: 'git', description: 'Git workflow', content: '...' }],
|
|
393
|
+
})
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
### Permissions
|
|
397
|
+
|
|
398
|
+
Control tool access per conversation:
|
|
399
|
+
|
|
400
|
+
```ts
|
|
401
|
+
const oc = await opencode({
|
|
402
|
+
pg,
|
|
403
|
+
permissions: {
|
|
404
|
+
bash: { allow: true },
|
|
405
|
+
read: { allow: true },
|
|
406
|
+
write: { allow: false },
|
|
407
|
+
edit: { allow: false },
|
|
408
|
+
skill: { '*': { allow: true }, 'internal-*': { allow: false } },
|
|
409
|
+
},
|
|
410
|
+
})
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
### Workspace isolation
|
|
414
|
+
|
|
415
|
+
```ts
|
|
416
|
+
const oc = await opencode({ pg, permissions })
|
|
417
|
+
// All sessions inherit the instance's workspace (default: process.cwd())
|
|
418
|
+
// Sessions cannot override their workspace
|
|
419
|
+
// Different mount points = different opencode() instances = isolated workspaces
|
|
420
|
+
```
|
|
301
421
|
|
|
302
422
|
```ts
|
|
303
423
|
import { serve, Router, postgres, user } from 'weifuwu'
|
|
@@ -1218,6 +1338,21 @@ Returns `TenantModule` — `{ migrate, middleware, router, graphql, close }`.
|
|
|
1218
1338
|
|
|
1219
1339
|
Returns `AgentModule` — `{ migrate, router, run, addKnowledge, close }`.
|
|
1220
1340
|
|
|
1341
|
+
### `opencode(options)`
|
|
1342
|
+
|
|
1343
|
+
| Option | Default | Description |
|
|
1344
|
+
|--------|---------|-------------|
|
|
1345
|
+
| `pg` | — | PostgreSQL client from `postgres()` |
|
|
1346
|
+
| `workspace` | `process.cwd()` | Base directory for `.sessions` |
|
|
1347
|
+
| `model` | `'deepseek-v4-flash'` | LLM model name |
|
|
1348
|
+
| `baseURL` | env `DEEPSEEK_BASE_URL` | API base URL |
|
|
1349
|
+
| `apiKey` | env `DEEPSEEK_API_KEY` | API key |
|
|
1350
|
+
| `systemPrompt` | — | Custom system prompt |
|
|
1351
|
+
| `skills` | `[]` | Static skill definitions |
|
|
1352
|
+
| `permissions` | — | Tool permission config |
|
|
1353
|
+
|
|
1354
|
+
Returns `OpencodeModule` — `{ migrate, router, wsHandler, close }`.
|
|
1355
|
+
|
|
1221
1356
|
### `messager(options)`
|
|
1222
1357
|
|
|
1223
1358
|
| Option | Default | Description |
|
|
@@ -1278,13 +1413,14 @@ serve(app.handler(), { websocket: app.websocketHandler() })
|
|
|
1278
1413
|
|
|
1279
1414
|
| Import | Description |
|
|
1280
1415
|
|--------|-------------|
|
|
1281
|
-
| `postgres(options?)` | PostgreSQL connection +
|
|
1416
|
+
| `postgres(options?)` | PostgreSQL connection + DDL schema builder + transactions + module lifecycle |
|
|
1282
1417
|
| `redis(options?)` | Redis client (ioredis) — injects `ctx.redis` |
|
|
1283
1418
|
| `queue(options?)` | Redis-backed job queue — immediate, delayed, cron scheduling |
|
|
1284
1419
|
| `user(options)` | Built-in authentication (password + OAuth2 Server + JWT, middleware) |
|
|
1285
1420
|
| `tenant(options)` | Multi-tenant BaaS — dynamic tables, REST + GraphQL auto-generation, row-level isolation |
|
|
1286
1421
|
| `agent(options)` | AI Agent — chat/workflow/knowledge, Ollama-ready, programmatic API |
|
|
1287
1422
|
| `messager(options)` | Real-time messaging — channels, WebSocket, agent routing, webhooks |
|
|
1423
|
+
| `opencode(options)` | AI programming assistant — chat agents with tools, skills, permissions, isolated workspaces |
|
|
1288
1424
|
| `graphql(handler)` | GraphQL endpoint (GET/POST + GraphiQL) |
|
|
1289
1425
|
| `ai(handler)` | AI streaming endpoint (POST) |
|
|
1290
1426
|
| `workflow(handler)` | Workflow engine (POST + SSE) |
|
|
@@ -1308,6 +1444,10 @@ serve(app.handler(), { websocket: app.websocketHandler() })
|
|
|
1308
1444
|
| `createWorkflowEngine(options)` | Programmatic workflow engine |
|
|
1309
1445
|
| `createSSEManager()` | SSE event manager for workflows |
|
|
1310
1446
|
| `tool(def)` | Define a workflow tool |
|
|
1447
|
+
| `pgTable(name, columns)` | Type-safe table schema definition with DDL generation |
|
|
1448
|
+
| `serial()`, `uuid()`, `text()`, `integer()`, `boolean()`, `timestamptz()`, `jsonb()`, `textArray()`, `vector()` | Column type builders |
|
|
1449
|
+
| `sql(strings, ...)` | SQL expression literal for table defaults (e.g. `sql\`NOW()\``) |
|
|
1450
|
+
| `PgModule` | Base class for database-backed modules (provides `sql`, `close()`) |
|
|
1311
1451
|
|
|
1312
1452
|
Import `useTsx` and `TsxContext` from `'weifuwu'`.
|
|
1313
1453
|
|
package/dist/agent/migrate.d.ts
CHANGED
package/dist/agent/rest.d.ts
CHANGED
package/dist/agent/run.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { LanguageModel, EmbeddingModel, Tool } from '
|
|
2
|
-
import type { Sql } from '
|
|
1
|
+
import type { LanguageModel, EmbeddingModel, Tool } from '../vendor.ts';
|
|
2
|
+
import type { Sql } from '../vendor.ts';
|
|
3
3
|
import type { RunParams, RunResult, KnowledgeDoc } from './types.ts';
|
|
4
4
|
interface RunnerDeps {
|
|
5
5
|
sql: Sql<{}>;
|
package/dist/agent/types.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { LanguageModel, EmbeddingModel, Tool } from '
|
|
1
|
+
import type { LanguageModel, EmbeddingModel, Tool } from '../vendor.ts';
|
|
2
2
|
export interface AgentConfig {
|
|
3
3
|
id: number;
|
|
4
4
|
tenant_id: string | null;
|
|
@@ -36,7 +36,7 @@ export type RunResult = {
|
|
|
36
36
|
stream: ReadableStream<Uint8Array>;
|
|
37
37
|
};
|
|
38
38
|
export interface AgentOptions {
|
|
39
|
-
pg:
|
|
39
|
+
pg: import('../postgres/types.ts').PostgresClient;
|
|
40
40
|
model?: LanguageModel;
|
|
41
41
|
embeddingModel?: EmbeddingModel;
|
|
42
42
|
embeddingDimension?: number;
|
package/dist/index.d.ts
CHANGED
|
@@ -26,7 +26,7 @@ export type { AIHandler } from './ai.ts';
|
|
|
26
26
|
export { tool, createWorkflowEngine, createSSEManager, generateWorkflow, workflow } from './workflow/index.ts';
|
|
27
27
|
export type { Tool, Workflow, WorkflowEngine, WorkflowState, SSEEvent, WorkflowOptions, WorkflowHandler } from './workflow/index.ts';
|
|
28
28
|
export { postgres } from './postgres/index.ts';
|
|
29
|
-
export type { PostgresOptions, PostgresClient
|
|
29
|
+
export type { PostgresOptions, PostgresClient } from './postgres/types.ts';
|
|
30
30
|
export { user } from './user/index.ts';
|
|
31
31
|
export type { UserOptions, UserData, UserModule, OAuth2Client } from './user/types.ts';
|
|
32
32
|
export { redis } from './redis/index.ts';
|
|
@@ -41,3 +41,5 @@ export { messager } from './messager/index.ts';
|
|
|
41
41
|
export type { MessagerOptions, MessagerModule, Channel, ChannelMember, Message } from './messager/types.ts';
|
|
42
42
|
export { deploy, defineConfig } from './deploy/index.ts';
|
|
43
43
|
export type { DeployConfig, AppConfig, DeployServer, AppStatus } from './deploy/types.ts';
|
|
44
|
+
export { opencode } from './opencode/index.ts';
|
|
45
|
+
export type { OpencodeOptions, OpencodeModule, SkillDef, OpencodePermissions, Session as OpencodeSession } from './opencode/types.ts';
|