weifuwu 0.18.0 → 0.18.1
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 +106 -62
- package/dist/agent/types.d.ts +2 -2
- package/dist/ai.d.ts +1 -3
- package/dist/analytics.d.ts +1 -2
- package/dist/graphql.d.ts +1 -3
- package/dist/iii/types.d.ts +1 -2
- package/dist/index.js +255 -242
- package/dist/logdb/types.d.ts +1 -2
- package/dist/messager/types.d.ts +2 -2
- package/dist/opencode/types.d.ts +1 -2
- package/dist/tenant/types.d.ts +2 -2
- package/dist/user/types.d.ts +1 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -88,26 +88,49 @@ app.get('/admin', mw, handler) // route-level
|
|
|
88
88
|
|
|
89
89
|
## Module Patterns
|
|
90
90
|
|
|
91
|
-
All modules follow one of
|
|
91
|
+
All modules follow one of **2 patterns** — learn these and you know every module.
|
|
92
92
|
|
|
93
93
|
| Pattern | How to mount | Example |
|
|
94
94
|
|---------|-------------|---------|
|
|
95
|
-
| `[
|
|
96
|
-
| `[
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
95
|
+
| `[α]` | `app.use(mod())` | `compress()`, `preferences()`, `postgres()` |
|
|
96
|
+
| `[β]` | `app.use('/path', mod())` | `health()`, `graphql(handler)`, `user()` |
|
|
97
|
+
|
|
98
|
+
### Pattern α — Middleware
|
|
99
|
+
|
|
100
|
+
```ts
|
|
101
|
+
app.use(compress()) // basic
|
|
102
|
+
const pg = postgres() // with extras: .sql, .table, .migrate(), .close()
|
|
103
|
+
app.use(pg)
|
|
104
|
+
app.use(rateLimit({ max: 100 })) // with .stop()
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Pattern β — Router
|
|
108
|
+
|
|
109
|
+
```ts
|
|
110
|
+
app.use('/health', health()) // no extras
|
|
111
|
+
app.use('/graphql', graphql(handler))
|
|
112
|
+
app.use('/logs', logdb({ pg })) // with .log(), .migrate()
|
|
113
|
+
app.use('/auth', user({ pg, jwtSecret })) // with .middleware(), .register()
|
|
114
|
+
app.ws('/ws', messager({ pg }).wsHandler())
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
β modules that need **separate middleware** use `.middleware()`:
|
|
118
|
+
```ts
|
|
119
|
+
const a = analytics()
|
|
120
|
+
app.use(a.middleware()) // tracking
|
|
121
|
+
app.use('/', a) // dashboard
|
|
122
|
+
```
|
|
100
123
|
|
|
101
124
|
---
|
|
102
125
|
|
|
103
126
|
## Module Reference
|
|
104
127
|
|
|
105
|
-
### agent [
|
|
128
|
+
### agent [β]
|
|
106
129
|
|
|
107
130
|
```ts
|
|
108
131
|
const a = agent({ pg, model: openai('gpt-4o'), embeddingModel: openai.embedding('text-embedding-3-small') })
|
|
109
132
|
await a.migrate()
|
|
110
|
-
app.use('/api', a
|
|
133
|
+
app.use('/api', a)
|
|
111
134
|
await a.addKnowledge(agentId, 'Title', 'some knowledge content')
|
|
112
135
|
a.run(agentId, { input: 'summarize the data', stream: true })
|
|
113
136
|
```
|
|
@@ -124,24 +147,30 @@ a.run(agentId, { input: 'summarize the data', stream: true })
|
|
|
124
147
|
|--------|-------------|
|
|
125
148
|
| `.run(agentId, { input, stream?, messages? })` | Execute agent with input |
|
|
126
149
|
| `.addKnowledge(agentId, title, content)` | Add knowledge document |
|
|
127
|
-
| `.
|
|
150
|
+
| `.migrate()` | DB setup |
|
|
128
151
|
| `.close()` | Cleanup |
|
|
129
152
|
|
|
130
|
-
### aiStream [
|
|
153
|
+
### aiStream [β]
|
|
154
|
+
|
|
155
|
+
Creates an AI streaming chat endpoint using the Vercel AI SDK.
|
|
131
156
|
|
|
132
157
|
```ts
|
|
133
158
|
const chat = await aiStream(async (req) => ({ model: openai('gpt-4o'), messages: (await req.json()).messages }))
|
|
134
|
-
app.use('/chat', chat
|
|
159
|
+
app.use('/chat', chat)
|
|
135
160
|
```
|
|
136
161
|
|
|
137
|
-
|
|
162
|
+
| Param | Type | Description |
|
|
163
|
+
|-------|------|-------------|
|
|
164
|
+
| `handler` | `(req, ctx) => AIStreamOptions \| Promise<AIStreamOptions>` | Returns AI SDK options (model, messages, schema, etc.) |
|
|
165
|
+
|
|
166
|
+
### analytics [β]
|
|
138
167
|
|
|
139
168
|
In-memory or PostgreSQL page view tracking with built-in dashboard.
|
|
140
169
|
|
|
141
170
|
```ts
|
|
142
171
|
const a = analytics()
|
|
143
172
|
app.use(a.middleware())
|
|
144
|
-
app.use('/', a
|
|
173
|
+
app.use('/', a) // GET /__analytics (dashboard), GET /__analytics/data?days=7 (JSON)
|
|
145
174
|
```
|
|
146
175
|
|
|
147
176
|
| Option | Type | Default | Description |
|
|
@@ -154,10 +183,10 @@ app.use('/', a.router()) // GET /__analytics (dashboard), GET /__analytics
|
|
|
154
183
|
const a = analytics({ pg })
|
|
155
184
|
await a.migrate()
|
|
156
185
|
app.use(a.middleware())
|
|
157
|
-
app.use('/', a
|
|
186
|
+
app.use('/', a) // dashboard routes
|
|
158
187
|
```
|
|
159
188
|
|
|
160
|
-
### auth [
|
|
189
|
+
### auth [α]
|
|
161
190
|
|
|
162
191
|
```ts
|
|
163
192
|
app.use(auth({ token: 'sk-123' })) // static token
|
|
@@ -173,7 +202,7 @@ app.get('/protected', auth({ proxy: 'http://auth:3000/validate' }), handler)
|
|
|
173
202
|
| `verify` | `(token, req) => object\|null` | — | Verify function, return value sets `ctx.user` |
|
|
174
203
|
| `proxy` | `string` | — | Auth service URL to proxy requests to |
|
|
175
204
|
|
|
176
|
-
### compress [
|
|
205
|
+
### compress [α]
|
|
177
206
|
|
|
178
207
|
```ts
|
|
179
208
|
app.use(compress()) // brotli > gzip > deflate (min 1KB)
|
|
@@ -185,7 +214,7 @@ app.use(compress({ threshold: 2048, level: 4 })) // custom threshold and le
|
|
|
185
214
|
| `threshold` | `number` | `1024` | Minimum byte size to compress |
|
|
186
215
|
| `level` | `number` | `6` | Compression level (zlib) |
|
|
187
216
|
|
|
188
|
-
### cors [
|
|
217
|
+
### cors [α]
|
|
189
218
|
|
|
190
219
|
```ts
|
|
191
220
|
app.use(cors()) // allow all
|
|
@@ -203,7 +232,7 @@ app.use(cors({ credentials: true, maxAge: 3600 }))
|
|
|
203
232
|
| `credentials` | `boolean` | `false` | Allow cookies/credentials |
|
|
204
233
|
| `maxAge` | `number` | — | Preflight cache duration (seconds) |
|
|
205
234
|
|
|
206
|
-
### csrf [
|
|
235
|
+
### csrf [α]
|
|
207
236
|
|
|
208
237
|
```ts
|
|
209
238
|
app.use(csrf())
|
|
@@ -234,10 +263,10 @@ const server = await deploy(config)
|
|
|
234
263
|
// server.apps.list(), server.apps.status(name), server.apps.deploy(name)
|
|
235
264
|
```
|
|
236
265
|
|
|
237
|
-
### health [
|
|
266
|
+
### health [β]
|
|
238
267
|
|
|
239
268
|
```ts
|
|
240
|
-
app.use(
|
|
269
|
+
app.use('/health', health())
|
|
241
270
|
// Returns 200 on success, 503 when check throws
|
|
242
271
|
```
|
|
243
272
|
|
|
@@ -246,7 +275,7 @@ app.use(health({ path: '/health' }))
|
|
|
246
275
|
| `path` | `string` | `'/health'` | Health check endpoint |
|
|
247
276
|
| `check` | `() => Promise<void>` | — | Async function; throws → 503 |
|
|
248
277
|
|
|
249
|
-
### helmet [
|
|
278
|
+
### helmet [α]
|
|
250
279
|
|
|
251
280
|
15 security headers: CSP, HSTS, X-Frame-Options, X-Content-Type-Options, etc.
|
|
252
281
|
|
|
@@ -267,12 +296,14 @@ app.use(helmet({ contentSecurityPolicy: "default-src 'self'", xFrameOptions: 'DE
|
|
|
267
296
|
| `crossOriginOpenerPolicy` | — | COOP header |
|
|
268
297
|
| `crossOriginResourcePolicy` | — | CORP header |
|
|
269
298
|
|
|
270
|
-
### iii [
|
|
299
|
+
### iii [β] — Worker / Function / Trigger
|
|
300
|
+
|
|
301
|
+
Distributed function execution with WebSocket workers, triggers, and Redis streams.
|
|
271
302
|
|
|
272
303
|
```ts
|
|
273
304
|
import { createWorker } from 'weifuwu'
|
|
274
305
|
const engine = iii({ pg, redis })
|
|
275
|
-
app.use('/iii', engine
|
|
306
|
+
app.use('/iii', engine)
|
|
276
307
|
app.ws('/iii', engine.wsHandler())
|
|
277
308
|
|
|
278
309
|
const w = createWorker('orders')
|
|
@@ -281,6 +312,12 @@ engine.addWorker(w)
|
|
|
281
312
|
await engine.trigger({ function_id: 'orders::create', payload: { items: ['apple'] } })
|
|
282
313
|
```
|
|
283
314
|
|
|
315
|
+
| Option | Type | Default | Description |
|
|
316
|
+
|--------|------|---------|-------------|
|
|
317
|
+
| `pg` | `object` | — | PostgreSQL client for persistent triggers |
|
|
318
|
+
| `redis` | `object` | — | Redis client for streams |
|
|
319
|
+
| `streamTTL` | `number` | `3600` | Redis stream key TTL (seconds, 0 = no expiry) |
|
|
320
|
+
|
|
284
321
|
| Method | Description |
|
|
285
322
|
|--------|-------------|
|
|
286
323
|
| `.addWorker(w)` | Register a worker |
|
|
@@ -289,19 +326,18 @@ await engine.trigger({ function_id: 'orders::create', payload: { items: ['apple'
|
|
|
289
326
|
| `.listWorkers()` | List registered workers |
|
|
290
327
|
| `.listFunctions()` | List registered functions |
|
|
291
328
|
| `.listTriggers()` | List registered triggers |
|
|
292
|
-
| `.router()` | REST + WS API |
|
|
293
329
|
| `.wsHandler()` | WebSocket handler |
|
|
294
330
|
| `.migrate()` | DB setup |
|
|
295
331
|
| `.shutdown()` | Clean shutdown |
|
|
296
332
|
|
|
297
|
-
### logdb [
|
|
333
|
+
### logdb [β]
|
|
298
334
|
|
|
299
335
|
PostgreSQL structured event logging with monthly partitioning.
|
|
300
336
|
|
|
301
337
|
```ts
|
|
302
338
|
const logger = logdb({ pg })
|
|
303
339
|
await logger.migrate()
|
|
304
|
-
app.use('/logs', logger
|
|
340
|
+
app.use('/logs', logger)
|
|
305
341
|
await logger.clean(12) // drop partitions older than 12 months
|
|
306
342
|
await logger.log({ level: 'info', source: 'app', message: 'hello', metadata: { userId: 1 } })
|
|
307
343
|
```
|
|
@@ -317,13 +353,17 @@ await logger.log({ level: 'info', source: 'app', message: 'hello', metadata: { u
|
|
|
317
353
|
| GET | `/` | Query (`?level=`, `?source=`, `?after=`, `?before=`, `?meta.*=`) |
|
|
318
354
|
| GET | `/:id` | Get single entry |
|
|
319
355
|
|
|
320
|
-
### logger [
|
|
356
|
+
### logger [α]
|
|
321
357
|
|
|
322
358
|
```ts
|
|
323
359
|
app.use(logger()) // GET /hello 200 5ms
|
|
324
360
|
app.use(logger({ format: 'combined' })) // with query params
|
|
325
361
|
```
|
|
326
362
|
|
|
363
|
+
| Option | Type | Default | Description |
|
|
364
|
+
|--------|------|---------|-------------|
|
|
365
|
+
| `format` | `'short' \| 'combined'` | `'short'` | Log format: path only, or path + query params |
|
|
366
|
+
|
|
327
367
|
### mailer
|
|
328
368
|
|
|
329
369
|
```ts
|
|
@@ -337,25 +377,32 @@ await mail.send({ to: 'user@test.com', subject: 'Hello', text: 'Body', html: '<p
|
|
|
337
377
|
| `from` | `string` | — | Default sender address |
|
|
338
378
|
| `send` | `function` | — | Custom send function (alternative to transport) |
|
|
339
379
|
|
|
340
|
-
### messager [
|
|
380
|
+
### messager [β]
|
|
341
381
|
|
|
342
382
|
Real-time chat with channels, WebSocket, agent routing.
|
|
343
383
|
|
|
344
384
|
```ts
|
|
345
385
|
const msg = messager({ pg, agents, redis: redis() })
|
|
346
386
|
await msg.migrate()
|
|
387
|
+
app.use('/api', msg)
|
|
347
388
|
app.ws('/ws', msg.wsHandler())
|
|
348
389
|
await msg.send(channelId, 'System message', { sender_type: 'system', sender_id: 'bot' })
|
|
349
390
|
```
|
|
350
391
|
|
|
392
|
+
| Option | Type | Default | Description |
|
|
393
|
+
|--------|------|---------|-------------|
|
|
394
|
+
| `pg` | `object` | — | PostgreSQL client |
|
|
395
|
+
| `agents` | `AgentModule` | — | Agent module for routing |
|
|
396
|
+
| `webhookTimeout` | `number` | — | Webhook timeout |
|
|
397
|
+
| `redis` | `object` | — | Redis client |
|
|
398
|
+
|
|
351
399
|
| Method | Description |
|
|
352
400
|
|--------|-------------|
|
|
353
401
|
| `.wsHandler()` | WebSocket handler (channels, typing, read receipts) |
|
|
354
402
|
| `.send(channel, content, opts?)` | Send message to channel |
|
|
355
|
-
| `.router()` | REST API |
|
|
356
403
|
| `.close()` | Cleanup |
|
|
357
404
|
|
|
358
|
-
### opencode [
|
|
405
|
+
### opencode [β]
|
|
359
406
|
|
|
360
407
|
AI programming assistant.
|
|
361
408
|
|
|
@@ -367,14 +414,14 @@ const oc = await opencode({
|
|
|
367
414
|
permissions: { bash: { allow: true }, write: { allow: false } },
|
|
368
415
|
})
|
|
369
416
|
await oc.migrate()
|
|
370
|
-
app.use('/opencode',
|
|
417
|
+
app.use('/opencode', oc)
|
|
371
418
|
app.ws('/opencode', oc.wsHandler())
|
|
372
419
|
```
|
|
373
420
|
|
|
374
421
|
| Option | Type | Default | Description |
|
|
375
422
|
|--------|------|---------|-------------|
|
|
376
423
|
| `pg` | `object` | — | PostgreSQL client |
|
|
377
|
-
| `model` | `
|
|
424
|
+
| `model` | `string` | — | AI model name (e.g. `'gpt-4o'`, `'deepseek-v4-flash'`) |
|
|
378
425
|
| `baseURL` | `string` | — | OpenAI-compatible API base URL |
|
|
379
426
|
| `apiKey` | `string` | — | API key for the model |
|
|
380
427
|
| `workspace` | `string` | — | Project directory |
|
|
@@ -382,7 +429,7 @@ app.ws('/opencode', oc.wsHandler())
|
|
|
382
429
|
| `skills` | `object[]` | — | Custom skill definitions |
|
|
383
430
|
| `permissions` | `object` | — | Tool permission rules |
|
|
384
431
|
|
|
385
|
-
### postgres [
|
|
432
|
+
### postgres [α]
|
|
386
433
|
|
|
387
434
|
```ts
|
|
388
435
|
const pg = postgres() // reads DATABASE_URL
|
|
@@ -413,7 +460,7 @@ await pg.transaction(async (tx) => { const users = pg.table('_users', { ... }).w
|
|
|
413
460
|
|
|
414
461
|
Where helpers: `eq`, `ne`, `gt`, `gte`, `lt`, `lte`, `isNull`, `isNotNull`, `like`, `contains`, `in_`, `and`, `or`, `not`.
|
|
415
462
|
|
|
416
|
-
### preferences [
|
|
463
|
+
### preferences [α]
|
|
417
464
|
|
|
418
465
|
Locale detection + theme + translations. `/__lang/:locale` and `/__theme/:theme` auto-routed.
|
|
419
466
|
|
|
@@ -444,7 +491,7 @@ const { theme, resolvedTheme, setTheme } = useTheme()
|
|
|
444
491
|
// resolvedTheme resolves 'system' → 'dark'|'light' based on prefers-color-scheme
|
|
445
492
|
```
|
|
446
493
|
|
|
447
|
-
### queue [
|
|
494
|
+
### queue [α]
|
|
448
495
|
|
|
449
496
|
```ts
|
|
450
497
|
const q = queue({ redis })
|
|
@@ -467,7 +514,7 @@ await q.add('send-email', { to: 'user@test.com' }, { cron: '0 8 * * *' })
|
|
|
467
514
|
| `.stop()` | Stop processing |
|
|
468
515
|
| `.close()` | Cleanup |
|
|
469
516
|
|
|
470
|
-
### rateLimit [
|
|
517
|
+
### rateLimit [α]
|
|
471
518
|
|
|
472
519
|
```ts
|
|
473
520
|
app.use(rateLimit({ max: 100, window: 60_000 })) // 100 req/min
|
|
@@ -484,7 +531,7 @@ app.use(rateLimit({ key: (req) => req.headers.get('x-api-key') ?? 'anonymous' })
|
|
|
484
531
|
| `key` | `(req) => string` | IP-based | Key function |
|
|
485
532
|
| `message` | `string` | `'Too Many Requests'` | 429 response body |
|
|
486
533
|
|
|
487
|
-
### redis [
|
|
534
|
+
### redis [α]
|
|
488
535
|
|
|
489
536
|
```ts
|
|
490
537
|
const r = redis() // reads REDIS_URL
|
|
@@ -498,7 +545,7 @@ await ctx.redis.set('key', 'value')
|
|
|
498
545
|
| `url` | `string` | `REDIS_URL` env | Redis connection string |
|
|
499
546
|
| (all ioredis options) | — | — | Passed directly to ioredis |
|
|
500
547
|
|
|
501
|
-
### requestId [
|
|
548
|
+
### requestId [α]
|
|
502
549
|
|
|
503
550
|
```ts
|
|
504
551
|
app.use(requestId())
|
|
@@ -511,10 +558,10 @@ app.use(requestId({ header: 'X-Request-Id', generator: () => crypto.randomUUID()
|
|
|
511
558
|
| `header` | `string` | `'X-Request-ID'` | Header name to read/write |
|
|
512
559
|
| `generator` | `() => string` | `crypto.randomUUID()` | ID generator |
|
|
513
560
|
|
|
514
|
-
### seo [
|
|
561
|
+
### seo [β] + seoMiddleware [α]
|
|
515
562
|
|
|
516
563
|
```ts
|
|
517
|
-
app.use(seo({ baseUrl: 'https://example.com', robots: [{ userAgent: '*', allow: '/' }], sitemap: { urls: [{ loc: '/' }] } }))
|
|
564
|
+
app.use('/', seo({ baseUrl: 'https://example.com', robots: [{ userAgent: '*', allow: '/' }], sitemap: { urls: [{ loc: '/' }] } }))
|
|
518
565
|
// GET /robots.txt, GET /sitemap.xml
|
|
519
566
|
|
|
520
567
|
app.use(seoMiddleware({ headers: { 'X-Robots-Tag': (path) => path.startsWith('/admin') ? 'noindex' : undefined } }))
|
|
@@ -522,7 +569,14 @@ app.use(seoMiddleware({ headers: { 'X-Robots-Tag': (path) => path.startsWith('/a
|
|
|
522
569
|
|
|
523
570
|
Also exports `seoTags(config)` for generating meta/og/twitter tags as an HTML string.
|
|
524
571
|
|
|
525
|
-
|
|
572
|
+
| Option | Type | Default | Description |
|
|
573
|
+
|--------|------|---------|-------------|
|
|
574
|
+
| `baseUrl` | `string` | — | Base URL for sitemap URLs |
|
|
575
|
+
| `robots` | `RobotsRule[]` | `[{ userAgent: '*', allow: '/' }]` | Robots.txt rules |
|
|
576
|
+
| `sitemap` | `SitemapConfig` | — | Sitemap configuration (urls, resolve, cacheTTL) |
|
|
577
|
+
| `headers` | `SeoHeadersConfig` | — | Response headers (e.g. `X-Robots-Tag`) |
|
|
578
|
+
|
|
579
|
+
### tenant [β]
|
|
526
580
|
|
|
527
581
|
Multi-tenant BaaS with dynamic table API and GraphQL.
|
|
528
582
|
|
|
@@ -530,11 +584,16 @@ Multi-tenant BaaS with dynamic table API and GraphQL.
|
|
|
530
584
|
const t = tenant({ pg, usersTable: '_users' })
|
|
531
585
|
await t.migrate()
|
|
532
586
|
app.use('/api', t.middleware()) // → ctx.tenant
|
|
533
|
-
app.use('/api', t
|
|
587
|
+
app.use('/api', t) // dynamic CRUD
|
|
534
588
|
app.use('/graphql', t.graphql()) // dynamic GraphQL
|
|
535
589
|
```
|
|
536
590
|
|
|
537
|
-
|
|
591
|
+
| Option | Type | Default | Description |
|
|
592
|
+
|--------|------|---------|-------------|
|
|
593
|
+
| `pg` | `object` | — | PostgreSQL client |
|
|
594
|
+
| `usersTable` | `string` | — | Users table name for tenant membership lookup |
|
|
595
|
+
|
|
596
|
+
### upload [α]
|
|
538
597
|
|
|
539
598
|
```ts
|
|
540
599
|
app.post('/upload', upload({ dir: './uploads', maxFileSize: 10_485_760, allowedTypes: ['image/jpeg', 'image/png'] }), (req, ctx) => {
|
|
@@ -550,14 +609,14 @@ app.post('/upload', upload({ dir: './uploads', maxFileSize: 10_485_760, allowedT
|
|
|
550
609
|
| `maxFileSize` | `number` | — | Max bytes per file |
|
|
551
610
|
| `allowedTypes` | `string[]` | — | Allowed MIME types |
|
|
552
611
|
|
|
553
|
-
### user [
|
|
612
|
+
### user [β]
|
|
554
613
|
|
|
555
614
|
Authentication: register, login, JWT, OAuth2.
|
|
556
615
|
|
|
557
616
|
```ts
|
|
558
617
|
const auth = user({ pg, jwtSecret: process.env.JWT_SECRET! })
|
|
559
618
|
await auth.migrate()
|
|
560
|
-
app.use('/auth', auth
|
|
619
|
+
app.use('/auth', auth) // POST /register, POST /login, OAuth2 routes
|
|
561
620
|
app.get('/me', auth.middleware(), (req, ctx) => Response.json(ctx.user))
|
|
562
621
|
```
|
|
563
622
|
|
|
@@ -574,10 +633,9 @@ app.get('/me', auth.middleware(), (req, ctx) => Response.json(ctx.user))
|
|
|
574
633
|
| `.register(data)` | Register a new user programmatically |
|
|
575
634
|
| `.login(data)` | Log in programmatically |
|
|
576
635
|
| `.verify(token)` | Verify JWT token |
|
|
577
|
-
| `.router()` | REST routes (register, login, OAuth2) |
|
|
578
636
|
| `.middleware()` | JWT verify middleware — sets `ctx.user` |
|
|
579
637
|
|
|
580
|
-
### validate [
|
|
638
|
+
### validate [α]
|
|
581
639
|
|
|
582
640
|
```ts
|
|
583
641
|
import { z } from 'zod'
|
|
@@ -789,21 +847,7 @@ import { openai, streamText, generateText, streamObject, generateObject, tool, e
|
|
|
789
847
|
import { runWorkflow } from 'weifuwu'
|
|
790
848
|
```
|
|
791
849
|
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
```ts
|
|
795
|
-
const chat = await aiStream(async (req) => ({ model: openai('gpt-4o'), messages: (await req.json()).messages }))
|
|
796
|
-
app.use('/chat', chat.router().handler())
|
|
797
|
-
```
|
|
798
|
-
|
|
799
|
-
### Agents
|
|
800
|
-
|
|
801
|
-
```ts
|
|
802
|
-
const agents = agent({ pg })
|
|
803
|
-
await agents.migrate()
|
|
804
|
-
app.use('/api', agents.router())
|
|
805
|
-
await agents.addKnowledge(agentId, 'Title', 'content')
|
|
806
|
-
```
|
|
850
|
+
For AI streaming endpoints see [`aiStream`](#aistream-β). For AI agent APIs see [`agent`](#agent-β).
|
|
807
851
|
|
|
808
852
|
### DAG Workflow
|
|
809
853
|
|
package/dist/agent/types.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Router } from '../router.ts';
|
|
1
2
|
import type { LanguageModel, EmbeddingModel, Tool } from 'ai';
|
|
2
3
|
export interface AgentConfig {
|
|
3
4
|
id: number;
|
|
@@ -42,9 +43,8 @@ export interface AgentOptions {
|
|
|
42
43
|
embeddingDimension?: number;
|
|
43
44
|
tools?: Record<string, Tool>;
|
|
44
45
|
}
|
|
45
|
-
export interface AgentModule {
|
|
46
|
+
export interface AgentModule extends Router {
|
|
46
47
|
migrate: () => Promise<void>;
|
|
47
|
-
router: () => any;
|
|
48
48
|
run: (agentId: number, params: RunParams) => Promise<RunResult>;
|
|
49
49
|
addKnowledge: (agentId: number, title: string, content: string) => Promise<KnowledgeDoc>;
|
|
50
50
|
close: () => Promise<void>;
|
package/dist/ai.d.ts
CHANGED
|
@@ -2,6 +2,4 @@ import type { Context } from './types.ts';
|
|
|
2
2
|
import { Router } from './router.ts';
|
|
3
3
|
export type AIHandler = (req: Request, ctx: Context) => Record<string, unknown> | Promise<Record<string, unknown>>;
|
|
4
4
|
export declare const _ai: Record<string, any>;
|
|
5
|
-
export declare function aiStream(handler: AIHandler): Promise<
|
|
6
|
-
router(): Router;
|
|
7
|
-
}>;
|
|
5
|
+
export declare function aiStream(handler: AIHandler): Promise<Router>;
|
package/dist/analytics.d.ts
CHANGED
|
@@ -7,9 +7,8 @@ export interface AnalyticsOptions {
|
|
|
7
7
|
table: (name: string, cols: any) => any;
|
|
8
8
|
};
|
|
9
9
|
}
|
|
10
|
-
export interface AnalyticsModule {
|
|
10
|
+
export interface AnalyticsModule extends Router {
|
|
11
11
|
middleware: () => Middleware;
|
|
12
|
-
router: () => Router;
|
|
13
12
|
migrate: () => Promise<void>;
|
|
14
13
|
close: () => Promise<void>;
|
|
15
14
|
}
|
package/dist/graphql.d.ts
CHANGED
|
@@ -9,6 +9,4 @@ export interface GraphQLOptions {
|
|
|
9
9
|
graphiql?: boolean;
|
|
10
10
|
}
|
|
11
11
|
export type GraphQLHandler = (req: Request, ctx: Context) => GraphQLOptions | Promise<GraphQLOptions>;
|
|
12
|
-
export declare function graphql(handler: GraphQLHandler):
|
|
13
|
-
router(): Router;
|
|
14
|
-
};
|
|
12
|
+
export declare function graphql(handler: GraphQLHandler): Router;
|
package/dist/iii/types.d.ts
CHANGED
|
@@ -30,8 +30,7 @@ export interface TriggerOptions {
|
|
|
30
30
|
action?: 'sync' | 'void';
|
|
31
31
|
timeout_ms?: number;
|
|
32
32
|
}
|
|
33
|
-
export interface IIIModule {
|
|
34
|
-
router: () => Router;
|
|
33
|
+
export interface IIIModule extends Router {
|
|
35
34
|
wsHandler: () => any;
|
|
36
35
|
addWorker: (worker: Worker) => void;
|
|
37
36
|
trigger: (request: TriggerRequest) => Promise<unknown>;
|
package/dist/index.js
CHANGED
|
@@ -2292,7 +2292,7 @@ function graphql(handler) {
|
|
|
2292
2292
|
}
|
|
2293
2293
|
return executeQuery(schema, params, options, req, ctx);
|
|
2294
2294
|
});
|
|
2295
|
-
return
|
|
2295
|
+
return r;
|
|
2296
2296
|
}
|
|
2297
2297
|
|
|
2298
2298
|
// ai.ts
|
|
@@ -2319,7 +2319,7 @@ async function aiStream(handler) {
|
|
|
2319
2319
|
const result = streamText4(options);
|
|
2320
2320
|
return result.toTextStreamResponse();
|
|
2321
2321
|
});
|
|
2322
|
-
return
|
|
2322
|
+
return r;
|
|
2323
2323
|
}
|
|
2324
2324
|
|
|
2325
2325
|
// ai/workflow.ts
|
|
@@ -3592,8 +3592,8 @@ function user(options) {
|
|
|
3592
3592
|
};
|
|
3593
3593
|
}
|
|
3594
3594
|
function router() {
|
|
3595
|
-
const
|
|
3596
|
-
|
|
3595
|
+
const r2 = new Router();
|
|
3596
|
+
r2.post("/register", async (req) => {
|
|
3597
3597
|
try {
|
|
3598
3598
|
const body = await req.json();
|
|
3599
3599
|
const result = await register(body);
|
|
@@ -3606,7 +3606,7 @@ function user(options) {
|
|
|
3606
3606
|
return Response.json({ error: err.message }, { status });
|
|
3607
3607
|
}
|
|
3608
3608
|
});
|
|
3609
|
-
|
|
3609
|
+
r2.post("/login", async (req) => {
|
|
3610
3610
|
try {
|
|
3611
3611
|
const body = await req.json();
|
|
3612
3612
|
const result = await login(body);
|
|
@@ -3622,30 +3622,29 @@ function user(options) {
|
|
|
3622
3622
|
}
|
|
3623
3623
|
});
|
|
3624
3624
|
if (oauth2) {
|
|
3625
|
-
|
|
3626
|
-
|
|
3627
|
-
|
|
3628
|
-
}
|
|
3629
|
-
return
|
|
3630
|
-
}
|
|
3631
|
-
const
|
|
3632
|
-
|
|
3633
|
-
|
|
3634
|
-
|
|
3635
|
-
|
|
3636
|
-
|
|
3637
|
-
|
|
3638
|
-
|
|
3639
|
-
|
|
3640
|
-
|
|
3641
|
-
|
|
3642
|
-
|
|
3643
|
-
},
|
|
3644
|
-
revokeClient: oauth2 ? (clientId) => oauth2.revokeClient(clientId) : async () => {
|
|
3645
|
-
throw new Error("OAuth2 server is not enabled");
|
|
3646
|
-
},
|
|
3647
|
-
close: () => base.close()
|
|
3625
|
+
r2.get("/oauth/authorize", (req, ctx) => oauth2.authorizeHandler(req, ctx));
|
|
3626
|
+
r2.post("/oauth/consent", (req) => oauth2.consentHandler(req));
|
|
3627
|
+
r2.post("/oauth/token", (req) => oauth2.tokenHandler(req));
|
|
3628
|
+
}
|
|
3629
|
+
return r2;
|
|
3630
|
+
}
|
|
3631
|
+
const r = router();
|
|
3632
|
+
const mod = r;
|
|
3633
|
+
mod.middleware = middleware;
|
|
3634
|
+
mod.migrate = migrate;
|
|
3635
|
+
mod.register = register;
|
|
3636
|
+
mod.login = login;
|
|
3637
|
+
mod.verify = verify;
|
|
3638
|
+
mod.registerClient = oauth2 ? (data) => oauth2.registerClient(data) : async () => {
|
|
3639
|
+
throw new Error("OAuth2 server is not enabled");
|
|
3640
|
+
};
|
|
3641
|
+
mod.getClient = oauth2 ? (clientId) => oauth2.getClient(clientId) : async () => {
|
|
3642
|
+
throw new Error("OAuth2 server is not enabled");
|
|
3648
3643
|
};
|
|
3644
|
+
mod.revokeClient = oauth2 ? (clientId) => oauth2.revokeClient(clientId) : async () => {
|
|
3645
|
+
throw new Error("OAuth2 server is not enabled");
|
|
3646
|
+
};
|
|
3647
|
+
mod.close = () => base.close();
|
|
3649
3648
|
return mod;
|
|
3650
3649
|
}
|
|
3651
3650
|
|
|
@@ -4724,76 +4723,78 @@ function tenant(options) {
|
|
|
4724
4723
|
const sql2 = pg.sql;
|
|
4725
4724
|
const usersTable = options.usersTable;
|
|
4726
4725
|
const base = new PgModule(pg);
|
|
4727
|
-
|
|
4728
|
-
|
|
4729
|
-
|
|
4730
|
-
|
|
4731
|
-
|
|
4732
|
-
|
|
4733
|
-
|
|
4734
|
-
|
|
4735
|
-
|
|
4736
|
-
|
|
4737
|
-
|
|
4738
|
-
|
|
4739
|
-
|
|
4740
|
-
|
|
4741
|
-
|
|
4742
|
-
|
|
4743
|
-
|
|
4744
|
-
|
|
4745
|
-
|
|
4746
|
-
|
|
4747
|
-
|
|
4748
|
-
|
|
4749
|
-
|
|
4750
|
-
|
|
4751
|
-
|
|
4752
|
-
|
|
4753
|
-
|
|
4754
|
-
|
|
4755
|
-
|
|
4756
|
-
|
|
4757
|
-
|
|
4758
|
-
|
|
4759
|
-
|
|
4760
|
-
|
|
4761
|
-
|
|
4762
|
-
|
|
4763
|
-
|
|
4764
|
-
|
|
4765
|
-
|
|
4766
|
-
|
|
4767
|
-
|
|
4768
|
-
|
|
4769
|
-
|
|
4770
|
-
|
|
4771
|
-
|
|
4772
|
-
|
|
4773
|
-
|
|
4774
|
-
|
|
4775
|
-
ctx.tenant = { id: m.id, name: m.name, role: m.role };
|
|
4776
|
-
return next(req, ctx);
|
|
4777
|
-
}
|
|
4778
|
-
const headerId = req.headers.get("X-Tenant-ID");
|
|
4779
|
-
if (!headerId) {
|
|
4780
|
-
return Response.json({
|
|
4781
|
-
error: "Multiple tenants. Set X-Tenant-ID header.",
|
|
4782
|
-
tenants: members.map((m) => ({ id: m.id, name: m.name, role: m.role }))
|
|
4783
|
-
}, { status: 300 });
|
|
4784
|
-
}
|
|
4785
|
-
const member = members.find((m) => m.id === headerId);
|
|
4786
|
-
if (!member) {
|
|
4787
|
-
return new Response("Tenant not found", { status: 403 });
|
|
4788
|
-
}
|
|
4789
|
-
ctx.tenant = { id: member.id, name: member.name, role: member.role };
|
|
4726
|
+
async function migrate() {
|
|
4727
|
+
await sql2.unsafe(`CREATE EXTENSION IF NOT EXISTS "vector"`);
|
|
4728
|
+
const tenants = pgTable("_tenants", {
|
|
4729
|
+
id: text("id").primaryKey().default(sql`gen_random_uuid()`),
|
|
4730
|
+
name: text("name").notNull(),
|
|
4731
|
+
created_at: timestamptz("created_at").notNull().default(sql`NOW()`)
|
|
4732
|
+
});
|
|
4733
|
+
await tenants.create(sql2);
|
|
4734
|
+
const members = pgTable("_tenant_members", {
|
|
4735
|
+
id: serial("id").primaryKey(),
|
|
4736
|
+
tenant_id: text("tenant_id").notNull().references("_tenants", "id", "cascade"),
|
|
4737
|
+
user_id: integer("user_id").notNull(),
|
|
4738
|
+
role: text("role").notNull().default("member"),
|
|
4739
|
+
created_at: timestamptz("created_at").notNull().default(sql`NOW()`)
|
|
4740
|
+
});
|
|
4741
|
+
await members.create(sql2);
|
|
4742
|
+
await members.createIndex(sql2, "user_id");
|
|
4743
|
+
await sql2.unsafe(`CREATE UNIQUE INDEX IF NOT EXISTS "_tenant_members_unique_idx" ON "_tenant_members" ("tenant_id", "user_id")`);
|
|
4744
|
+
const tables = pgTable("_user_tables", {
|
|
4745
|
+
id: serial("id").primaryKey(),
|
|
4746
|
+
tenant_id: text("tenant_id").notNull().references("_tenants", "id", "cascade"),
|
|
4747
|
+
slug: text("slug").notNull(),
|
|
4748
|
+
label: text("label").notNull().default(""),
|
|
4749
|
+
fields: jsonb("fields").notNull().default(sql`'[]'::jsonb`),
|
|
4750
|
+
created_at: timestamptz("created_at").notNull().default(sql`NOW()`)
|
|
4751
|
+
});
|
|
4752
|
+
await tables.create(sql2);
|
|
4753
|
+
await tables.createIndex(sql2, "tenant_id");
|
|
4754
|
+
await sql2.unsafe(`CREATE UNIQUE INDEX IF NOT EXISTS "_user_tables_unique_idx" ON "_user_tables" ("tenant_id", "slug")`);
|
|
4755
|
+
}
|
|
4756
|
+
function middleware() {
|
|
4757
|
+
return async (req, ctx, next) => {
|
|
4758
|
+
const user2 = ctx.user;
|
|
4759
|
+
if (!user2) {
|
|
4760
|
+
return new Response("Unauthorized", { status: 401 });
|
|
4761
|
+
}
|
|
4762
|
+
const members = await sql2`
|
|
4763
|
+
SELECT tm.role, t.id, t.name
|
|
4764
|
+
FROM "_tenant_members" tm
|
|
4765
|
+
JOIN "_tenants" t ON t.id = tm.tenant_id
|
|
4766
|
+
WHERE tm.user_id = ${user2.id}
|
|
4767
|
+
`;
|
|
4768
|
+
if (members.length === 0) {
|
|
4769
|
+
return new Response("No tenant found. Create one via POST /sys/tenants.", { status: 403 });
|
|
4770
|
+
}
|
|
4771
|
+
if (members.length === 1) {
|
|
4772
|
+
const m = members[0];
|
|
4773
|
+
ctx.tenant = { id: m.id, name: m.name, role: m.role };
|
|
4790
4774
|
return next(req, ctx);
|
|
4791
|
-
}
|
|
4792
|
-
|
|
4793
|
-
|
|
4794
|
-
|
|
4795
|
-
|
|
4796
|
-
|
|
4775
|
+
}
|
|
4776
|
+
const headerId = req.headers.get("X-Tenant-ID");
|
|
4777
|
+
if (!headerId) {
|
|
4778
|
+
return Response.json({
|
|
4779
|
+
error: "Multiple tenants. Set X-Tenant-ID header.",
|
|
4780
|
+
tenants: members.map((m) => ({ id: m.id, name: m.name, role: m.role }))
|
|
4781
|
+
}, { status: 300 });
|
|
4782
|
+
}
|
|
4783
|
+
const member = members.find((m) => m.id === headerId);
|
|
4784
|
+
if (!member) {
|
|
4785
|
+
return new Response("Tenant not found", { status: 403 });
|
|
4786
|
+
}
|
|
4787
|
+
ctx.tenant = { id: member.id, name: member.name, role: member.role };
|
|
4788
|
+
return next(req, ctx);
|
|
4789
|
+
};
|
|
4790
|
+
}
|
|
4791
|
+
const r = buildRouter(sql2, usersTable);
|
|
4792
|
+
const mod = r;
|
|
4793
|
+
mod.migrate = migrate;
|
|
4794
|
+
mod.middleware = middleware;
|
|
4795
|
+
mod.graphql = () => buildGraphQLHandler(sql2);
|
|
4796
|
+
mod.close = () => base.close();
|
|
4797
|
+
return mod;
|
|
4797
4798
|
}
|
|
4798
4799
|
|
|
4799
4800
|
// agent/client.ts
|
|
@@ -5070,18 +5071,18 @@ function agent(options) {
|
|
|
5070
5071
|
});
|
|
5071
5072
|
const runner = createRunner({ sql: sql2, agents: agentsTable, knowledge: knowledgeTable, getModel, getEmbeddingModel, userTools: options.tools });
|
|
5072
5073
|
const base = new PgModule(pg);
|
|
5073
|
-
|
|
5074
|
-
|
|
5075
|
-
|
|
5076
|
-
|
|
5077
|
-
|
|
5078
|
-
|
|
5079
|
-
|
|
5080
|
-
router: () => buildRouter2({ agents: agentsTable, knowledge: knowledgeTable, runner }),
|
|
5081
|
-
run: (agentId, params) => runner.run(agentId, params),
|
|
5082
|
-
addKnowledge: (agentId, title, content) => runner.addKnowledge(agentId, title, content),
|
|
5083
|
-
close: () => base.close()
|
|
5074
|
+
const r = buildRouter2({ agents: agentsTable, knowledge: knowledgeTable, runner });
|
|
5075
|
+
const mod = r;
|
|
5076
|
+
mod.migrate = async () => {
|
|
5077
|
+
await agentsTable.create();
|
|
5078
|
+
await agentsTable.createIndex("tenant_id");
|
|
5079
|
+
await knowledgeTable.create();
|
|
5080
|
+
await knowledgeTable.createIndex("agent_id");
|
|
5084
5081
|
};
|
|
5082
|
+
mod.run = (agentId, params) => runner.run(agentId, params);
|
|
5083
|
+
mod.addKnowledge = (agentId, title, content) => runner.addKnowledge(agentId, title, content);
|
|
5084
|
+
mod.close = () => base.close();
|
|
5085
|
+
return mod;
|
|
5085
5086
|
}
|
|
5086
5087
|
|
|
5087
5088
|
// messager/agent.ts
|
|
@@ -5390,31 +5391,32 @@ function messager(options) {
|
|
|
5390
5391
|
mime_type: text("mime_type"),
|
|
5391
5392
|
created_at: timestamptz("created_at").notNull().default(sql`NOW()`)
|
|
5392
5393
|
});
|
|
5393
|
-
|
|
5394
|
-
|
|
5395
|
-
|
|
5396
|
-
|
|
5397
|
-
|
|
5398
|
-
|
|
5399
|
-
|
|
5400
|
-
|
|
5401
|
-
|
|
5402
|
-
}
|
|
5403
|
-
|
|
5404
|
-
|
|
5405
|
-
|
|
5406
|
-
|
|
5407
|
-
|
|
5408
|
-
|
|
5409
|
-
|
|
5410
|
-
|
|
5411
|
-
|
|
5412
|
-
|
|
5413
|
-
|
|
5414
|
-
return msg;
|
|
5415
|
-
},
|
|
5416
|
-
close: () => base.close()
|
|
5394
|
+
const r = buildRouter3({ sql: sql2, channels, members, messages: messages2, agents, hub });
|
|
5395
|
+
async function send(channelId, content, opts) {
|
|
5396
|
+
const msg = await messages2.insert({
|
|
5397
|
+
channel_id: channelId,
|
|
5398
|
+
sender_id: opts?.sender_id ?? 0,
|
|
5399
|
+
sender_type: opts?.sender_type ?? "system",
|
|
5400
|
+
type: opts?.type ?? "text",
|
|
5401
|
+
content
|
|
5402
|
+
});
|
|
5403
|
+
broadcastToChannel(hub, channelId, { type: "message", data: msg });
|
|
5404
|
+
return msg;
|
|
5405
|
+
}
|
|
5406
|
+
const mod = r;
|
|
5407
|
+
mod.migrate = async () => {
|
|
5408
|
+
await channels.create();
|
|
5409
|
+
await channels.createIndex("tenant_id");
|
|
5410
|
+
await members.create();
|
|
5411
|
+
await members.createIndex("member_id");
|
|
5412
|
+
await members.createIndex(["channel_id", "member_id", "member_type"], { unique: true });
|
|
5413
|
+
await messages2.create();
|
|
5414
|
+
await messages2.createIndex(["channel_id", "created_at"], { desc: true });
|
|
5417
5415
|
};
|
|
5416
|
+
mod.wsHandler = () => wsResult.handler;
|
|
5417
|
+
mod.send = send;
|
|
5418
|
+
mod.close = () => base.close();
|
|
5419
|
+
return mod;
|
|
5418
5420
|
}
|
|
5419
5421
|
|
|
5420
5422
|
// deploy/index.ts
|
|
@@ -6838,47 +6840,47 @@ async function opencode(options) {
|
|
|
6838
6840
|
const model = provider.chat(modelName);
|
|
6839
6841
|
const pendingQuestions = /* @__PURE__ */ new Map();
|
|
6840
6842
|
const base = new PgModule(pg);
|
|
6841
|
-
|
|
6842
|
-
|
|
6843
|
-
|
|
6844
|
-
|
|
6845
|
-
|
|
6846
|
-
|
|
6847
|
-
|
|
6848
|
-
|
|
6849
|
-
|
|
6850
|
-
|
|
6851
|
-
|
|
6852
|
-
|
|
6853
|
-
|
|
6854
|
-
|
|
6855
|
-
|
|
6856
|
-
|
|
6857
|
-
|
|
6858
|
-
|
|
6859
|
-
|
|
6860
|
-
|
|
6861
|
-
|
|
6862
|
-
|
|
6863
|
-
|
|
6864
|
-
|
|
6865
|
-
|
|
6866
|
-
|
|
6867
|
-
|
|
6868
|
-
|
|
6869
|
-
|
|
6870
|
-
|
|
6871
|
-
|
|
6872
|
-
|
|
6873
|
-
router: () => buildRouter4({ sql: sql2, model, workspace, systemPrompt, skills: manualSkills, skillsRegistry, permissions, pendingQuestions }),
|
|
6874
|
-
wsHandler: () => createWSHandler2({ sql: sql2, model, workspace, systemPrompt, skills: manualSkills, skillsRegistry, permissions, pendingQuestions }),
|
|
6875
|
-
close: () => base.close()
|
|
6843
|
+
const r = await buildRouter4({ sql: sql2, model, workspace, systemPrompt, skills: manualSkills, skillsRegistry, permissions, pendingQuestions });
|
|
6844
|
+
const mod = r;
|
|
6845
|
+
mod.migrate = async () => {
|
|
6846
|
+
const sessions2 = pgTable("_opencode_sessions", {
|
|
6847
|
+
id: uuid("id").default(sql`gen_random_uuid()`).primaryKey(),
|
|
6848
|
+
tenant_id: text("tenant_id"),
|
|
6849
|
+
user_id: integer("user_id").default(0),
|
|
6850
|
+
title: text("title"),
|
|
6851
|
+
agent_type: text("agent_type").default("build"),
|
|
6852
|
+
model: text("model").default("deepseek-v4-flash"),
|
|
6853
|
+
system_prompt: text("system_prompt"),
|
|
6854
|
+
workspace: text("workspace"),
|
|
6855
|
+
metadata: jsonb("metadata").default(sql`'{}'::jsonb`),
|
|
6856
|
+
active: boolean_("active").default(true),
|
|
6857
|
+
created_at: timestamptz("created_at").default(sql`NOW()`),
|
|
6858
|
+
updated_at: timestamptz("updated_at").default(sql`NOW()`)
|
|
6859
|
+
});
|
|
6860
|
+
await sessions2.create(sql2);
|
|
6861
|
+
await sessions2.createIndex(sql2, "user_id");
|
|
6862
|
+
const messages2 = pgTable("_opencode_messages", {
|
|
6863
|
+
id: serial("id").primaryKey(),
|
|
6864
|
+
session_id: uuid("session_id").notNull().references("_opencode_sessions", "id", "cascade"),
|
|
6865
|
+
role: text("role").notNull(),
|
|
6866
|
+
content: text("content"),
|
|
6867
|
+
tool_calls: jsonb("tool_calls"),
|
|
6868
|
+
tool_results: jsonb("tool_results"),
|
|
6869
|
+
tokens_in: integer("tokens_in").default(0),
|
|
6870
|
+
tokens_out: integer("tokens_out").default(0),
|
|
6871
|
+
created_at: timestamptz("created_at").default(sql`NOW()`)
|
|
6872
|
+
});
|
|
6873
|
+
await messages2.create(sql2);
|
|
6874
|
+
await messages2.createIndex(sql2, ["session_id", "created_at"]);
|
|
6876
6875
|
};
|
|
6876
|
+
mod.wsHandler = () => createWSHandler2({ sql: sql2, model, workspace, systemPrompt, skills: manualSkills, skillsRegistry, permissions, pendingQuestions });
|
|
6877
|
+
mod.close = () => base.close();
|
|
6878
|
+
return mod;
|
|
6877
6879
|
}
|
|
6878
6880
|
|
|
6879
6881
|
// health.ts
|
|
6880
6882
|
function health(options) {
|
|
6881
|
-
const path2 = options?.path ?? "/
|
|
6883
|
+
const path2 = options?.path ?? "/";
|
|
6882
6884
|
const r = new Router();
|
|
6883
6885
|
const handler = async () => {
|
|
6884
6886
|
try {
|
|
@@ -7099,18 +7101,19 @@ function analytics(options) {
|
|
|
7099
7101
|
headers: { "content-type": "text/html; charset=utf-8" }
|
|
7100
7102
|
});
|
|
7101
7103
|
};
|
|
7102
|
-
const
|
|
7103
|
-
|
|
7104
|
-
|
|
7105
|
-
r.get("/__analytics", handler);
|
|
7106
|
-
return r;
|
|
7107
|
-
};
|
|
7104
|
+
const r = new Router();
|
|
7105
|
+
r.get("/__analytics/data", handler);
|
|
7106
|
+
r.get("/__analytics", handler);
|
|
7108
7107
|
const migrate = async () => {
|
|
7109
7108
|
if (pg) await migratePg(pg.sql, pg.table);
|
|
7110
7109
|
};
|
|
7111
7110
|
const close = async () => {
|
|
7112
7111
|
};
|
|
7113
|
-
|
|
7112
|
+
const mod = r;
|
|
7113
|
+
mod.middleware = middleware;
|
|
7114
|
+
mod.migrate = migrate;
|
|
7115
|
+
mod.close = close;
|
|
7116
|
+
return mod;
|
|
7114
7117
|
}
|
|
7115
7118
|
|
|
7116
7119
|
// preferences.ts
|
|
@@ -7585,11 +7588,11 @@ function logdb(options) {
|
|
|
7585
7588
|
return row;
|
|
7586
7589
|
}
|
|
7587
7590
|
function router() {
|
|
7588
|
-
const
|
|
7589
|
-
|
|
7590
|
-
|
|
7591
|
-
|
|
7592
|
-
return
|
|
7591
|
+
const r2 = new Router();
|
|
7592
|
+
r2.post("/", createHandler(entries));
|
|
7593
|
+
r2.get("/", listHandler(entries));
|
|
7594
|
+
r2.get("/:id", getHandler(entries));
|
|
7595
|
+
return r2;
|
|
7593
7596
|
}
|
|
7594
7597
|
async function clean(retentionMonths) {
|
|
7595
7598
|
const cutoff = /* @__PURE__ */ new Date();
|
|
@@ -7611,21 +7614,22 @@ function logdb(options) {
|
|
|
7611
7614
|
}
|
|
7612
7615
|
return dropped;
|
|
7613
7616
|
}
|
|
7614
|
-
|
|
7615
|
-
|
|
7616
|
-
|
|
7617
|
-
|
|
7618
|
-
|
|
7619
|
-
|
|
7620
|
-
|
|
7621
|
-
|
|
7622
|
-
|
|
7623
|
-
|
|
7624
|
-
|
|
7625
|
-
|
|
7626
|
-
|
|
7627
|
-
|
|
7617
|
+
async function migrate() {
|
|
7618
|
+
await entries.create({ partitionBy: partitionBy("range", "created_at") });
|
|
7619
|
+
await entries.createIndex(["created_at", "id"]);
|
|
7620
|
+
await entries.createIndex(["level"]);
|
|
7621
|
+
await entries.createIndex(["source"]);
|
|
7622
|
+
await entries.createIndex(["level", "created_at"]);
|
|
7623
|
+
await ensurePartitions(sql2, tableName);
|
|
7624
|
+
}
|
|
7625
|
+
const r = router();
|
|
7626
|
+
const mod = r;
|
|
7627
|
+
mod.log = log;
|
|
7628
|
+
mod.migrate = migrate;
|
|
7629
|
+
mod.clean = clean;
|
|
7630
|
+
mod.close = async () => {
|
|
7628
7631
|
};
|
|
7632
|
+
return mod;
|
|
7629
7633
|
}
|
|
7630
7634
|
|
|
7631
7635
|
// iii/client.ts
|
|
@@ -8234,6 +8238,7 @@ function iii(opts = {}) {
|
|
|
8234
8238
|
for (const t of reg.triggers) triggers.delete(t.id);
|
|
8235
8239
|
workers.delete(workerId);
|
|
8236
8240
|
}
|
|
8241
|
+
let engineRef = null;
|
|
8237
8242
|
const wsHandler = createWsHandler({
|
|
8238
8243
|
registerRemoteWorker(ws, name) {
|
|
8239
8244
|
const id2 = crypto6.randomUUID();
|
|
@@ -8304,7 +8309,7 @@ function iii(opts = {}) {
|
|
|
8304
8309
|
}));
|
|
8305
8310
|
return;
|
|
8306
8311
|
}
|
|
8307
|
-
const ctx = { engine:
|
|
8312
|
+
const ctx = { engine: engineRef, functionId, workerName: fn.workerName };
|
|
8308
8313
|
Promise.resolve(fn.handler(payload, ctx)).then((result) => {
|
|
8309
8314
|
ws.send(JSON.stringify({ type: "invoke_result", invocation_id: invocationId, result }));
|
|
8310
8315
|
}).catch((err) => {
|
|
@@ -8312,70 +8317,78 @@ function iii(opts = {}) {
|
|
|
8312
8317
|
});
|
|
8313
8318
|
}
|
|
8314
8319
|
});
|
|
8315
|
-
|
|
8316
|
-
|
|
8317
|
-
|
|
8318
|
-
|
|
8319
|
-
|
|
8320
|
-
},
|
|
8321
|
-
wsHandler: () => wsHandler,
|
|
8322
|
-
addWorker: addLocalWorker,
|
|
8323
|
-
removeWorker: (worker) => {
|
|
8324
|
-
for (const [wid, reg] of workers) {
|
|
8325
|
-
if (reg.name === worker.name) {
|
|
8326
|
-
removeWorker(wid);
|
|
8327
|
-
return;
|
|
8328
|
-
}
|
|
8320
|
+
function removeWorkerByName(worker) {
|
|
8321
|
+
for (const [wid, reg] of workers) {
|
|
8322
|
+
if (reg.name === worker.name) {
|
|
8323
|
+
removeWorker(wid);
|
|
8324
|
+
return;
|
|
8329
8325
|
}
|
|
8330
|
-
}
|
|
8331
|
-
|
|
8332
|
-
|
|
8333
|
-
|
|
8334
|
-
|
|
8335
|
-
|
|
8336
|
-
|
|
8337
|
-
|
|
8338
|
-
|
|
8339
|
-
|
|
8340
|
-
|
|
8341
|
-
|
|
8326
|
+
}
|
|
8327
|
+
}
|
|
8328
|
+
function trigger(request) {
|
|
8329
|
+
const fn = functions.get(request.function_id);
|
|
8330
|
+
if (!fn) throw new Error(`Function "${request.function_id}" not found`);
|
|
8331
|
+
const ctx = { engine: engineRef, functionId: request.function_id, workerName: fn.workerName };
|
|
8332
|
+
if (request.action === "void") {
|
|
8333
|
+
queueMicrotask(() => fn.handler(request.payload, ctx));
|
|
8334
|
+
return Promise.resolve(void 0);
|
|
8335
|
+
}
|
|
8336
|
+
return Promise.resolve(fn.handler(request.payload, ctx));
|
|
8337
|
+
}
|
|
8338
|
+
function listWorkers() {
|
|
8339
|
+
return Array.from(workers.values()).map((w) => ({
|
|
8342
8340
|
id: w.id,
|
|
8343
8341
|
name: w.name,
|
|
8344
8342
|
status: "connected",
|
|
8345
8343
|
connectedAt: Date.now(),
|
|
8346
8344
|
functionCount: w.functions.length,
|
|
8347
8345
|
triggerCount: w.triggers.length
|
|
8348
|
-
}))
|
|
8349
|
-
|
|
8346
|
+
}));
|
|
8347
|
+
}
|
|
8348
|
+
function listFunctions() {
|
|
8349
|
+
return Array.from(functions.values()).map((f) => ({
|
|
8350
8350
|
id: f.id,
|
|
8351
8351
|
workerId: f.workerId,
|
|
8352
8352
|
workerName: f.workerName,
|
|
8353
8353
|
triggers: f.triggers
|
|
8354
|
-
}))
|
|
8355
|
-
|
|
8354
|
+
}));
|
|
8355
|
+
}
|
|
8356
|
+
function listTriggers() {
|
|
8357
|
+
return Array.from(triggers.values()).map((t) => ({
|
|
8356
8358
|
id: t.id,
|
|
8357
8359
|
type: t.type,
|
|
8358
8360
|
function_id: t.function_id,
|
|
8359
8361
|
config: t.config,
|
|
8360
8362
|
workerId: t.workerId
|
|
8361
|
-
}))
|
|
8362
|
-
|
|
8363
|
-
|
|
8364
|
-
|
|
8365
|
-
|
|
8366
|
-
|
|
8367
|
-
|
|
8368
|
-
|
|
8369
|
-
|
|
8370
|
-
|
|
8371
|
-
|
|
8372
|
-
|
|
8373
|
-
|
|
8374
|
-
|
|
8375
|
-
|
|
8376
|
-
}
|
|
8363
|
+
}));
|
|
8364
|
+
}
|
|
8365
|
+
const routerMethods = { listWorkers, listFunctions, listTriggers, trigger };
|
|
8366
|
+
const r = buildRouter5(routerMethods, wsHandler);
|
|
8367
|
+
engineRef = r;
|
|
8368
|
+
const mod = r;
|
|
8369
|
+
mod.wsHandler = () => wsHandler;
|
|
8370
|
+
mod.addWorker = addLocalWorker;
|
|
8371
|
+
mod.removeWorker = removeWorkerByName;
|
|
8372
|
+
mod.trigger = trigger;
|
|
8373
|
+
mod.listWorkers = listWorkers;
|
|
8374
|
+
mod.listFunctions = listFunctions;
|
|
8375
|
+
mod.listTriggers = listTriggers;
|
|
8376
|
+
mod.migrate = async () => {
|
|
8377
|
+
await stream.migrate();
|
|
8377
8378
|
};
|
|
8378
|
-
|
|
8379
|
+
mod.shutdown = async () => {
|
|
8380
|
+
for (const [, p] of pending) {
|
|
8381
|
+
clearTimeout(p.timer);
|
|
8382
|
+
p.reject(new Error("Engine shutting down"));
|
|
8383
|
+
}
|
|
8384
|
+
pending.clear();
|
|
8385
|
+
for (const [, reg] of workers) reg.ws?.close();
|
|
8386
|
+
workers.clear();
|
|
8387
|
+
functions.clear();
|
|
8388
|
+
triggers.clear();
|
|
8389
|
+
await stream.close();
|
|
8390
|
+
};
|
|
8391
|
+
return mod;
|
|
8379
8392
|
}
|
|
8380
8393
|
|
|
8381
8394
|
// iii/worker.ts
|
package/dist/logdb/types.d.ts
CHANGED
|
@@ -18,9 +18,8 @@ export interface LogEntryInput {
|
|
|
18
18
|
message: string;
|
|
19
19
|
metadata?: Record<string, unknown>;
|
|
20
20
|
}
|
|
21
|
-
export interface LogdbModule {
|
|
21
|
+
export interface LogdbModule extends Router {
|
|
22
22
|
log(input: LogEntryInput): Promise<LogEntry>;
|
|
23
|
-
router(): Router;
|
|
24
23
|
migrate(): Promise<void>;
|
|
25
24
|
clean(retentionMonths: number): Promise<number>;
|
|
26
25
|
close(): Promise<void>;
|
package/dist/messager/types.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Router } from '../router.ts';
|
|
1
2
|
import type { AgentModule } from '../agent/types.ts';
|
|
2
3
|
import type { PostgresClient } from '../postgres/types.ts';
|
|
3
4
|
import type { Redis } from '../vendor.ts';
|
|
@@ -36,9 +37,8 @@ export interface Message {
|
|
|
36
37
|
mime_type: string | null;
|
|
37
38
|
created_at: string;
|
|
38
39
|
}
|
|
39
|
-
export interface MessagerModule {
|
|
40
|
+
export interface MessagerModule extends Router {
|
|
40
41
|
migrate: () => Promise<void>;
|
|
41
|
-
router: () => any;
|
|
42
42
|
wsHandler: () => any;
|
|
43
43
|
send: (channelId: number, content: string, opts?: {
|
|
44
44
|
sender_type?: string;
|
package/dist/opencode/types.d.ts
CHANGED
|
@@ -74,9 +74,8 @@ export interface OpencodeOptions {
|
|
|
74
74
|
skills?: SkillDef[];
|
|
75
75
|
permissions?: OpencodePermissions;
|
|
76
76
|
}
|
|
77
|
-
export interface OpencodeModule {
|
|
77
|
+
export interface OpencodeModule extends Router {
|
|
78
78
|
migrate: () => Promise<void>;
|
|
79
|
-
router: () => Router | Promise<Router>;
|
|
80
79
|
wsHandler: () => any;
|
|
81
80
|
close: () => Promise<void>;
|
|
82
81
|
}
|
package/dist/tenant/types.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Context } from '../types.ts';
|
|
2
|
+
import type { Router } from '../router.ts';
|
|
2
3
|
import type { PostgresClient } from '../postgres/types.ts';
|
|
3
4
|
declare module '../types.ts' {
|
|
4
5
|
interface Context {
|
|
@@ -39,10 +40,9 @@ export interface TenantOptions {
|
|
|
39
40
|
pg: PostgresClient;
|
|
40
41
|
usersTable: string;
|
|
41
42
|
}
|
|
42
|
-
export interface TenantModule {
|
|
43
|
+
export interface TenantModule extends Router {
|
|
43
44
|
migrate: () => Promise<void>;
|
|
44
45
|
middleware: () => (req: Request, ctx: Context, next: any) => Promise<Response>;
|
|
45
|
-
router: () => any;
|
|
46
46
|
graphql: () => any;
|
|
47
47
|
close: () => Promise<void>;
|
|
48
48
|
}
|
package/dist/user/types.d.ts
CHANGED
|
@@ -31,8 +31,7 @@ export interface UserOptions {
|
|
|
31
31
|
expiresIn?: string | number;
|
|
32
32
|
oauth2?: OAuth2ServerOptions;
|
|
33
33
|
}
|
|
34
|
-
export interface UserModule {
|
|
35
|
-
router: () => Router;
|
|
34
|
+
export interface UserModule extends Router {
|
|
36
35
|
middleware: () => Middleware;
|
|
37
36
|
migrate: () => Promise<void>;
|
|
38
37
|
register: (data: {
|