weifuwu 0.15.0 → 0.16.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 +191 -9
- package/cli.ts +13 -16
- package/dist/ai-sdk.d.ts +2 -0
- package/dist/cli.js +12 -13
- package/dist/helmet.d.ts +18 -0
- package/dist/iii/stream.d.ts +1 -0
- package/dist/iii/types.d.ts +2 -0
- package/dist/index.d.ts +18 -9
- package/dist/index.js +361 -106
- package/dist/request-id.d.ts +6 -0
- package/dist/seo.d.ts +39 -0
- package/dist/types.d.ts +1 -0
- package/package.json +1 -2
- package/README.zh.md +0 -158
package/README.md
CHANGED
|
@@ -24,10 +24,12 @@ Everything follows the same `(req, ctx) => Response` contract. The Router handle
|
|
|
24
24
|
- **PostgreSQL** — schema builder with type-safe DDL, CRUD (`read`/`readMany`, `insertMany`, `update`/`updateMany`, `delete`/`deleteMany`), WHERE helpers (`eq`, `gte`, `contains`, `and`, `or`), transactions, vector search
|
|
25
25
|
- **Auth** — password + JWT + OAuth2 Server (authorization code / PKCE / client_credentials)
|
|
26
26
|
- **Real-time** — WebSocket, messaging channels with agent routing
|
|
27
|
-
- **AI** — streaming endpoint, DAG workflow tool, AI agents with RAG and tool-use
|
|
27
|
+
- **AI** — streaming endpoint, DAG workflow tool, AI agents with RAG and tool-use — re-exports `streamText`, `tool`, `openai` and more from AI SDK
|
|
28
28
|
- **Data** — Redis client, job queue with cron scheduling
|
|
29
29
|
- **Multi-tenant BaaS** — dynamic tables, auto REST + GraphQL, row-level isolation
|
|
30
30
|
- **Deploy** — self-hosted PaaS: multi-app proxy, zero-downtime updates, auto SSL
|
|
31
|
+
- **Security** — `helmet()` security headers, request ID tracing, rate limiting, CORS, auth
|
|
32
|
+
- **SEO** — `robots.txt`, `sitemap.xml`, `X-Robots-Tag` middleware, `seoTags()` for meta / OG / Twitter Card
|
|
31
33
|
- **i18n** — locale detection, JSON translations, `ctx.t()`
|
|
32
34
|
- **Email** — SMTP or custom transport
|
|
33
35
|
- **Health check** — configurable `/health` endpoint
|
|
@@ -47,8 +49,7 @@ serve((req, ctx) => new Response('Hello, World!'), { port: 3000 })
|
|
|
47
49
|
### Full app
|
|
48
50
|
|
|
49
51
|
```ts
|
|
50
|
-
import { serve, Router, postgres, user, aiStream, graphql } from 'weifuwu'
|
|
51
|
-
import { openai } from '@ai-sdk/openai'
|
|
52
|
+
import { serve, Router, postgres, user, aiStream, graphql, openai } from 'weifuwu'
|
|
52
53
|
|
|
53
54
|
const app = new Router()
|
|
54
55
|
const pg = postgres()
|
|
@@ -106,6 +107,7 @@ All use the same pattern — `const m = module(options)` → `app.use('/path', m
|
|
|
106
107
|
| `graphql(handler)` | GraphQL endpoint | — |
|
|
107
108
|
| `logdb(options)` | Structured event logging | `log()`, `migrate()`, `clean()`, `close()` |
|
|
108
109
|
| `health(options?)` | Health check | — |
|
|
110
|
+
| `seo(options?)` | `robots.txt`, `sitemap.xml`, indexing control | `seoMiddleware()`, `seoTags()` |
|
|
109
111
|
| `iii(options?)` | Worker/Function/Trigger service paradigm | `migrate()`, `trigger()`, `addWorker()`, `listWorkers()`, `listFunctions()`, `listTriggers()`, `shutdown()` |
|
|
110
112
|
| `registerWorker(url)` | Pure WebSocket SDK (browser/Node) | `registerFunction()`, `registerTrigger()`, `trigger()`, `shutdown()` |
|
|
111
113
|
|
|
@@ -121,6 +123,9 @@ All use the same pattern — `const m = module(options)` → `app.use('/path', m
|
|
|
121
123
|
| `validate(schemas)` | Zod validation (body, query, params) |
|
|
122
124
|
| `upload(options?)` | Multipart file upload |
|
|
123
125
|
| `i18n(options)` | Internationalization — `ctx.t()`, locale detection |
|
|
126
|
+
| `seoMiddleware(options?)` | `X-Robots-Tag` header — string or path-based function |
|
|
127
|
+
| `helmet(options?)` | Security headers — CSP, HSTS, X-Frame-Options, etc. |
|
|
128
|
+
| `requestId(options?)` | `X-Request-ID` header + `ctx.requestId` |
|
|
124
129
|
|
|
125
130
|
## Utility functions
|
|
126
131
|
|
|
@@ -131,12 +136,21 @@ All use the same pattern — `const m = module(options)` → `app.use('/path', m
|
|
|
131
136
|
| `getCookies(req)` / `setCookie(res, ...)` / `deleteCookie(res, ...)` | Cookie helpers |
|
|
132
137
|
| `mailer(options)` | Email sender (SMTP or custom) |
|
|
133
138
|
| `createTestServer(handler)` | Start test server → `{ server, url }` |
|
|
139
|
+
| `seoTags(config)` | Generate `<title>`, `<meta>`, Open Graph, Twitter Card, canonical tags |
|
|
140
|
+
| `createSSEStream(iterable, opts?)` | SSE response from `AsyncIterable` |
|
|
141
|
+
| `formatSSE(event, data)` | Format SSE event string |
|
|
142
|
+
| `formatSSEData(data)` | Format SSE data string |
|
|
134
143
|
| `runWorkflow(options)` | DAG execution engine as AI SDK `Tool` |
|
|
135
144
|
| `pgTable(name, columns)` | Type-safe table schema builder |
|
|
136
145
|
| `pg.table(name, columns)` | Pre-bound table (no `sql` param needed) |
|
|
137
146
|
| `serial()`, `uuid()`, `text()`, ... | Column type builders |
|
|
138
147
|
| `eq()`, `gte()`, `contains()`, `and()` ... | WHERE clause helpers — same API as Drizzle |
|
|
139
148
|
| `PgModule` | Base class for DB-backed modules |
|
|
149
|
+
| `streamText()` / `generateText()` / `streamObject()` / `generateObject()` | AI SDK — text/structured generation |
|
|
150
|
+
| `tool()` | AI SDK — tool definition |
|
|
151
|
+
| `embed()` / `embedMany()` | AI SDK — text embeddings |
|
|
152
|
+
| `smoothStream()` | AI SDK — smooth streaming middleware |
|
|
153
|
+
| `openai` / `createOpenAI()` | OpenAI provider for AI SDK |
|
|
140
154
|
|
|
141
155
|
---
|
|
142
156
|
|
|
@@ -145,7 +159,7 @@ All use the same pattern — `const m = module(options)` → `app.use('/path', m
|
|
|
145
159
|
Optional module that organizes service logic as **Worker + Function + Trigger**, plus a pure WebSocket SDK for connecting remote workers. Built-in `stream::*` functions for hierarchical real-time data.
|
|
146
160
|
|
|
147
161
|
```ts
|
|
148
|
-
import { serve, Router, iii, createWorker
|
|
162
|
+
import { serve, Router, iii, createWorker, registerWorker } from 'weifuwu'
|
|
149
163
|
|
|
150
164
|
// Engine
|
|
151
165
|
const engine = iii({ pg, redis })
|
|
@@ -154,7 +168,7 @@ app.use('/iii', engine.router())
|
|
|
154
168
|
serve(app.handler(), { port: 3000, websocket: app.websocketHandler() })
|
|
155
169
|
|
|
156
170
|
// Local worker
|
|
157
|
-
const w =
|
|
171
|
+
const w = createWorker('orders')
|
|
158
172
|
w.registerFunction('orders::create', async (payload) => {
|
|
159
173
|
return db.query('INSERT INTO orders ...', [payload.items])
|
|
160
174
|
})
|
|
@@ -1086,8 +1100,7 @@ export default function NotFound() {
|
|
|
1086
1100
|
Server-sent event streaming via the Vercel AI SDK:
|
|
1087
1101
|
|
|
1088
1102
|
```ts
|
|
1089
|
-
import { serve, Router, aiStream } from 'weifuwu'
|
|
1090
|
-
import { openai } from '@ai-sdk/openai'
|
|
1103
|
+
import { serve, Router, aiStream, openai } from 'weifuwu'
|
|
1091
1104
|
|
|
1092
1105
|
const app = new Router()
|
|
1093
1106
|
const chat = await aiStream(async (req, ctx) => {
|
|
@@ -1104,8 +1117,7 @@ serve(app.handler(), { port: 3000 })
|
|
|
1104
1117
|
Multi-step DAG execution engine — packaged as a single AI SDK `Tool`. Use it with `streamText()` or `generateText()` when the LLM needs conditional logic, loops, or multi-step tool orchestration.
|
|
1105
1118
|
|
|
1106
1119
|
```ts
|
|
1107
|
-
import { tool, streamText } from '
|
|
1108
|
-
import { runWorkflow } from 'weifuwu'
|
|
1120
|
+
import { tool, streamText, runWorkflow } from 'weifuwu'
|
|
1109
1121
|
import { z } from 'zod'
|
|
1110
1122
|
|
|
1111
1123
|
const tools = {
|
|
@@ -1485,6 +1497,176 @@ const oc = await opencode({
|
|
|
1485
1497
|
|
|
1486
1498
|
---
|
|
1487
1499
|
|
|
1500
|
+
# SEO
|
|
1501
|
+
|
|
1502
|
+
Built-in SEO module — `robots.txt`, `sitemap.xml`, indexing headers, and meta tag utilities.
|
|
1503
|
+
|
|
1504
|
+
```ts
|
|
1505
|
+
import { seo, seoMiddleware, seoTags } from 'weifuwu'
|
|
1506
|
+
|
|
1507
|
+
const app = new Router()
|
|
1508
|
+
|
|
1509
|
+
// robots.txt + sitemap.xml
|
|
1510
|
+
app.use(seo({
|
|
1511
|
+
baseUrl: 'https://example.com',
|
|
1512
|
+
robots: [
|
|
1513
|
+
{ userAgent: '*', allow: '/', disallow: ['/admin', '/api'] },
|
|
1514
|
+
],
|
|
1515
|
+
sitemap: {
|
|
1516
|
+
urls: [
|
|
1517
|
+
{ loc: '/', changefreq: 'daily', priority: 1.0 },
|
|
1518
|
+
{ loc: '/about', changefreq: 'monthly', priority: 0.8 },
|
|
1519
|
+
],
|
|
1520
|
+
// Dynamic URLs from database
|
|
1521
|
+
async resolve() {
|
|
1522
|
+
const articles = await db.query('SELECT slug, updated_at FROM articles')
|
|
1523
|
+
return articles.map(a => ({
|
|
1524
|
+
loc: `/blog/${a.slug}`,
|
|
1525
|
+
lastmod: a.updated_at,
|
|
1526
|
+
}))
|
|
1527
|
+
},
|
|
1528
|
+
cacheTTL: 3_600_000, // re-generate every hour (default)
|
|
1529
|
+
},
|
|
1530
|
+
}))
|
|
1531
|
+
```
|
|
1532
|
+
|
|
1533
|
+
### Endpoints
|
|
1534
|
+
|
|
1535
|
+
| Path | Description |
|
|
1536
|
+
|------|-------------|
|
|
1537
|
+
| `GET /robots.txt` | Generated robots.txt with optional Sitemap reference |
|
|
1538
|
+
| `GET /sitemap.xml` | Generated XML sitemap with caching |
|
|
1539
|
+
|
|
1540
|
+
### seoMiddleware — Indexing control
|
|
1541
|
+
|
|
1542
|
+
```ts
|
|
1543
|
+
// Global — block all paths
|
|
1544
|
+
app.use(seoMiddleware({ headers: { 'X-Robots-Tag': 'noindex' } }))
|
|
1545
|
+
|
|
1546
|
+
// Per-path via function
|
|
1547
|
+
app.use(seoMiddleware({
|
|
1548
|
+
headers: {
|
|
1549
|
+
'X-Robots-Tag': (path) => path.startsWith('/admin') ? 'noindex' : undefined,
|
|
1550
|
+
},
|
|
1551
|
+
}))
|
|
1552
|
+
```
|
|
1553
|
+
|
|
1554
|
+
### seoTags — Meta / OG / Twitter Card
|
|
1555
|
+
|
|
1556
|
+
Generate SEO meta tags for SSR pages:
|
|
1557
|
+
|
|
1558
|
+
```ts
|
|
1559
|
+
const tags = seoTags({
|
|
1560
|
+
title: 'My Page',
|
|
1561
|
+
description: 'A great page about things',
|
|
1562
|
+
ogImage: 'https://example.com/og.png',
|
|
1563
|
+
twitterCard: 'summary_large_image',
|
|
1564
|
+
canonical: 'https://example.com/page',
|
|
1565
|
+
})
|
|
1566
|
+
// → <title>My Page</title>
|
|
1567
|
+
// → <meta property="og:title" content="My Page">
|
|
1568
|
+
// → <meta name="twitter:card" content="summary_large_image">
|
|
1569
|
+
// → <link rel="canonical" href="https://example.com/page">
|
|
1570
|
+
// ...
|
|
1571
|
+
```
|
|
1572
|
+
|
|
1573
|
+
Use in `layout.tsx` or `page.tsx` with `tsx()`:
|
|
1574
|
+
|
|
1575
|
+
```tsx
|
|
1576
|
+
export default function RootLayout({ children }) {
|
|
1577
|
+
return (
|
|
1578
|
+
<html>
|
|
1579
|
+
<head>{seoTags({ title: 'My App' })}</head>
|
|
1580
|
+
<body>{children}</body>
|
|
1581
|
+
</html>
|
|
1582
|
+
)
|
|
1583
|
+
}
|
|
1584
|
+
```
|
|
1585
|
+
|
|
1586
|
+
# Security
|
|
1587
|
+
|
|
1588
|
+
## Helmet — Security headers
|
|
1589
|
+
|
|
1590
|
+
```ts
|
|
1591
|
+
import { helmet } from 'weifuwu'
|
|
1592
|
+
|
|
1593
|
+
// Apply all security headers with safe defaults
|
|
1594
|
+
app.use(helmet())
|
|
1595
|
+
|
|
1596
|
+
// Customize individual headers (any can be set to false to remove)
|
|
1597
|
+
app.use(helmet({
|
|
1598
|
+
contentSecurityPolicy: "default-src 'self'",
|
|
1599
|
+
xFrameOptions: 'DENY',
|
|
1600
|
+
strictTransportSecurity: 'max-age=63072000; includeSubDomains; preload',
|
|
1601
|
+
}))
|
|
1602
|
+
|
|
1603
|
+
// Middleware-order: set after helmet to override
|
|
1604
|
+
app.use(helmet({ xFrameOptions: false })) // remove a header
|
|
1605
|
+
```
|
|
1606
|
+
|
|
1607
|
+
13 security headers set by default:
|
|
1608
|
+
|
|
1609
|
+
| Header | Default |
|
|
1610
|
+
|--------|---------|
|
|
1611
|
+
| `Content-Security-Policy` | `default-src 'self'; ...` |
|
|
1612
|
+
| `X-Content-Type-Options` | `nosniff` |
|
|
1613
|
+
| `X-Frame-Options` | `SAMEORIGIN` |
|
|
1614
|
+
| `Strict-Transport-Security` | `max-age=15552000; includeSubDomains` |
|
|
1615
|
+
| `X-XSS-Protection` | `0` |
|
|
1616
|
+
| `Referrer-Policy` | `no-referrer` |
|
|
1617
|
+
| `Permissions-Policy` | `camera=(),geolocation=(),...` |
|
|
1618
|
+
| `Cross-Origin-Embedder-Policy` | `require-corp` |
|
|
1619
|
+
| `Cross-Origin-Opener-Policy` | `same-origin` |
|
|
1620
|
+
| `Cross-Origin-Resource-Policy` | `same-origin` |
|
|
1621
|
+
| `Origin-Agent-Cluster` | `?1` |
|
|
1622
|
+
| `X-DNS-Prefetch-Control` | `off` |
|
|
1623
|
+
| `X-Download-Options` | `noopen` |
|
|
1624
|
+
| `X-Permitted-Cross-Domain-Policies` | `none` |
|
|
1625
|
+
|
|
1626
|
+
Does not override response headers already set by the application — your explicit headers take precedence.
|
|
1627
|
+
|
|
1628
|
+
## Request ID
|
|
1629
|
+
|
|
1630
|
+
```ts
|
|
1631
|
+
import { requestId } from 'weifuwu'
|
|
1632
|
+
|
|
1633
|
+
// Every response gets X-Request-ID
|
|
1634
|
+
app.use(requestId())
|
|
1635
|
+
|
|
1636
|
+
// Custom header name
|
|
1637
|
+
app.use(requestId({ header: 'X-Trace-Id' }))
|
|
1638
|
+
|
|
1639
|
+
// Custom ID generator
|
|
1640
|
+
app.use(requestId({ generator: () => crypto.randomUUID() }))
|
|
1641
|
+
|
|
1642
|
+
// Access the ID in handlers via ctx.requestId
|
|
1643
|
+
app.get('/log', (req, ctx) => {
|
|
1644
|
+
console.log(`Handling request ${ctx.requestId}`)
|
|
1645
|
+
return Response.json({ id: ctx.requestId })
|
|
1646
|
+
})
|
|
1647
|
+
```
|
|
1648
|
+
|
|
1649
|
+
Preserves incoming `X-Request-ID` for distributed tracing — if the upstream service already set it, the value is reused and propagated.
|
|
1650
|
+
|
|
1651
|
+
## Server-Sent Events
|
|
1652
|
+
|
|
1653
|
+
```ts
|
|
1654
|
+
import { createSSEStream, formatSSE } from 'weifuwu'
|
|
1655
|
+
|
|
1656
|
+
async function* eventStream() {
|
|
1657
|
+
yield { type: 'ping', data: { time: Date.now() } }
|
|
1658
|
+
yield { type: 'message', data: { text: 'hello' } }
|
|
1659
|
+
}
|
|
1660
|
+
|
|
1661
|
+
app.get('/events', () => createSSEStream(eventStream()))
|
|
1662
|
+
```
|
|
1663
|
+
|
|
1664
|
+
| Function | Description |
|
|
1665
|
+
|----------|-------------|
|
|
1666
|
+
| `createSSEStream(iterable, opts?)` | Returns a `Response` with `Content-Type: text/event-stream` |
|
|
1667
|
+
| `formatSSE(event, data)` | Formats an SSE event string (`event: ...\ndata: ...\n\n`) |
|
|
1668
|
+
| `formatSSEData(data)` | Formats SSE data-only string (`data: ...\n\n`) |
|
|
1669
|
+
|
|
1488
1670
|
# Health, i18n, Email & Testing
|
|
1489
1671
|
|
|
1490
1672
|
## Health check
|
package/cli.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { mkdir, writeFile, copyFile,
|
|
2
|
+
import { mkdir, writeFile, copyFile, readFile } from 'node:fs/promises'
|
|
3
|
+
import { existsSync } from 'node:fs'
|
|
3
4
|
import { homedir } from 'node:os'
|
|
4
5
|
import { join, dirname, resolve } from 'node:path'
|
|
5
6
|
import { fileURLToPath } from 'node:url'
|
|
@@ -7,26 +8,20 @@ import { fileURLToPath } from 'node:url'
|
|
|
7
8
|
const __filename = fileURLToPath(import.meta.url)
|
|
8
9
|
const __dirname = dirname(__filename)
|
|
9
10
|
|
|
10
|
-
const pkgRoot = resolve(__dirname, '..')
|
|
11
|
+
const pkgRoot = existsSync(join(__dirname, 'package.json')) ? __dirname : resolve(__dirname, '..')
|
|
11
12
|
|
|
12
13
|
async function cmdSkill() {
|
|
13
14
|
const targetDir = join(homedir(), '.agents', 'skills', 'weifuwu')
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
await mkdir(docsTarget, { recursive: true })
|
|
15
|
+
await mkdir(targetDir, { recursive: true })
|
|
17
16
|
await copyFile(join(pkgRoot, 'README.md'), join(targetDir, 'SKILL.md'))
|
|
18
|
-
|
|
19
|
-
const docDir = join(pkgRoot, 'docs')
|
|
20
|
-
const entries = await readdir(docDir)
|
|
21
|
-
for (const entry of entries) {
|
|
22
|
-
if (entry.endsWith('.md')) {
|
|
23
|
-
await copyFile(join(docDir, entry), join(docsTarget, entry))
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
17
|
console.log('✅ Installed weifuwu skill to ~/.agents/skills/weifuwu/')
|
|
28
18
|
}
|
|
29
19
|
|
|
20
|
+
async function cmdVersion() {
|
|
21
|
+
const pkg = JSON.parse(await readFile(join(pkgRoot, 'package.json'), 'utf-8'))
|
|
22
|
+
console.log(pkg.version)
|
|
23
|
+
}
|
|
24
|
+
|
|
30
25
|
async function cmdInit(name: string) {
|
|
31
26
|
const targetDir = resolve(process.cwd(), name)
|
|
32
27
|
await mkdir(targetDir, { recursive: true })
|
|
@@ -78,7 +73,9 @@ async function cmdInit(name: string) {
|
|
|
78
73
|
|
|
79
74
|
const cmd = process.argv[2]
|
|
80
75
|
|
|
81
|
-
if (cmd === '
|
|
76
|
+
if (cmd === 'version' || cmd === '-v' || cmd === '--version') {
|
|
77
|
+
cmdVersion().catch(console.error)
|
|
78
|
+
} else if (cmd === 'skill') {
|
|
82
79
|
cmdSkill().catch(console.error)
|
|
83
80
|
} else if (cmd === 'init') {
|
|
84
81
|
const name = process.argv[3]
|
|
@@ -88,5 +85,5 @@ if (cmd === 'skill') {
|
|
|
88
85
|
}
|
|
89
86
|
cmdInit(name).catch(console.error)
|
|
90
87
|
} else {
|
|
91
|
-
console.log('\nUsage:\n npx weifuwu init <name> Create a new weifuwu project\n npx weifuwu skill Install weifuwu skill to ~/.agents/skills/\n')
|
|
88
|
+
console.log('\nUsage:\n npx weifuwu version Print version\n npx weifuwu init <name> Create a new weifuwu project\n npx weifuwu skill Install weifuwu skill to ~/.agents/skills/\n')
|
|
92
89
|
}
|
package/dist/ai-sdk.d.ts
ADDED
package/dist/cli.js
CHANGED
|
@@ -1,27 +1,24 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// cli.ts
|
|
4
|
-
import { mkdir, writeFile, copyFile,
|
|
4
|
+
import { mkdir, writeFile, copyFile, readFile } from "node:fs/promises";
|
|
5
|
+
import { existsSync } from "node:fs";
|
|
5
6
|
import { homedir } from "node:os";
|
|
6
7
|
import { join, dirname, resolve } from "node:path";
|
|
7
8
|
import { fileURLToPath } from "node:url";
|
|
8
9
|
var __filename = fileURLToPath(import.meta.url);
|
|
9
10
|
var __dirname = dirname(__filename);
|
|
10
|
-
var pkgRoot = resolve(__dirname, "..");
|
|
11
|
+
var pkgRoot = existsSync(join(__dirname, "package.json")) ? __dirname : resolve(__dirname, "..");
|
|
11
12
|
async function cmdSkill() {
|
|
12
13
|
const targetDir = join(homedir(), ".agents", "skills", "weifuwu");
|
|
13
|
-
|
|
14
|
-
await mkdir(docsTarget, { recursive: true });
|
|
14
|
+
await mkdir(targetDir, { recursive: true });
|
|
15
15
|
await copyFile(join(pkgRoot, "README.md"), join(targetDir, "SKILL.md"));
|
|
16
|
-
const docDir = join(pkgRoot, "docs");
|
|
17
|
-
const entries = await readdir(docDir);
|
|
18
|
-
for (const entry of entries) {
|
|
19
|
-
if (entry.endsWith(".md")) {
|
|
20
|
-
await copyFile(join(docDir, entry), join(docsTarget, entry));
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
16
|
console.log("\u2705 Installed weifuwu skill to ~/.agents/skills/weifuwu/");
|
|
24
17
|
}
|
|
18
|
+
async function cmdVersion() {
|
|
19
|
+
const pkg = JSON.parse(await readFile(join(pkgRoot, "package.json"), "utf-8"));
|
|
20
|
+
console.log(pkg.version);
|
|
21
|
+
}
|
|
25
22
|
async function cmdInit(name) {
|
|
26
23
|
const targetDir = resolve(process.cwd(), name);
|
|
27
24
|
await mkdir(targetDir, { recursive: true });
|
|
@@ -65,7 +62,9 @@ async function cmdInit(name) {
|
|
|
65
62
|
console.log(`\u2705 Created ${name}/ \u2014 cd ${name} && npm install && npm run dev`);
|
|
66
63
|
}
|
|
67
64
|
var cmd = process.argv[2];
|
|
68
|
-
if (cmd === "
|
|
65
|
+
if (cmd === "version" || cmd === "-v" || cmd === "--version") {
|
|
66
|
+
cmdVersion().catch(console.error);
|
|
67
|
+
} else if (cmd === "skill") {
|
|
69
68
|
cmdSkill().catch(console.error);
|
|
70
69
|
} else if (cmd === "init") {
|
|
71
70
|
const name = process.argv[3];
|
|
@@ -75,5 +74,5 @@ if (cmd === "skill") {
|
|
|
75
74
|
}
|
|
76
75
|
cmdInit(name).catch(console.error);
|
|
77
76
|
} else {
|
|
78
|
-
console.log("\nUsage:\n npx weifuwu init <name> Create a new weifuwu project\n npx weifuwu skill Install weifuwu skill to ~/.agents/skills/\n");
|
|
77
|
+
console.log("\nUsage:\n npx weifuwu version Print version\n npx weifuwu init <name> Create a new weifuwu project\n npx weifuwu skill Install weifuwu skill to ~/.agents/skills/\n");
|
|
79
78
|
}
|
package/dist/helmet.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Middleware } from './types.ts';
|
|
2
|
+
export interface HelmetOptions {
|
|
3
|
+
contentSecurityPolicy?: string | false;
|
|
4
|
+
crossOriginEmbedderPolicy?: string | false;
|
|
5
|
+
crossOriginOpenerPolicy?: string | false;
|
|
6
|
+
crossOriginResourcePolicy?: string | false;
|
|
7
|
+
originAgentCluster?: string | false;
|
|
8
|
+
referrerPolicy?: string | false;
|
|
9
|
+
strictTransportSecurity?: string | false;
|
|
10
|
+
xContentTypeOptions?: string | false;
|
|
11
|
+
xDnsPrefetchControl?: string | false;
|
|
12
|
+
xDownloadOptions?: string | false;
|
|
13
|
+
xFrameOptions?: string | false;
|
|
14
|
+
xPermittedCrossDomainPolicies?: string | false;
|
|
15
|
+
xXssProtection?: string | false;
|
|
16
|
+
permissionsPolicy?: string | false;
|
|
17
|
+
}
|
|
18
|
+
export declare function helmet(options?: HelmetOptions): Middleware;
|
package/dist/iii/stream.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ import type { StreamUpdateOp, StreamSubscription } from './types.ts';
|
|
|
4
4
|
export declare function createStream(opts?: {
|
|
5
5
|
pg?: PostgresClient;
|
|
6
6
|
redis?: Redis;
|
|
7
|
+
streamTTL?: number;
|
|
7
8
|
}): {
|
|
8
9
|
subscribe(ws: WebSocket, sub: StreamSubscription): void;
|
|
9
10
|
unsubscribe(ws: WebSocket): void;
|
package/dist/iii/types.d.ts
CHANGED
|
@@ -17,6 +17,8 @@ export interface TriggerInput {
|
|
|
17
17
|
export interface IIIOptions {
|
|
18
18
|
pg?: PostgresClient;
|
|
19
19
|
redis?: Redis;
|
|
20
|
+
/** TTL in seconds for Redis stream keys. Default: 3600 (1 hour). Set to 0 for no expiration. */
|
|
21
|
+
streamTTL?: number;
|
|
20
22
|
}
|
|
21
23
|
export interface TriggerRequest {
|
|
22
24
|
function_id: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -20,36 +20,45 @@ export { rateLimit } from './rate-limit.ts';
|
|
|
20
20
|
export type { RateLimitOptions } from './rate-limit.ts';
|
|
21
21
|
export { compress } from './compress.ts';
|
|
22
22
|
export type { CompressOptions } from './compress.ts';
|
|
23
|
+
export { helmet } from './helmet.ts';
|
|
24
|
+
export type { HelmetOptions } from './helmet.ts';
|
|
25
|
+
export { requestId } from './request-id.ts';
|
|
26
|
+
export type { RequestIdOptions } from './request-id.ts';
|
|
27
|
+
export { createSSEStream, formatSSE, formatSSEData } from './sse.ts';
|
|
28
|
+
export type { SSEEvent } from './sse.ts';
|
|
23
29
|
export { graphql } from './graphql.ts';
|
|
24
30
|
export type { GraphQLOptions, GraphQLHandler } from './graphql.ts';
|
|
25
31
|
export { aiStream } from './ai.ts';
|
|
26
32
|
export type { AIHandler } from './ai.ts';
|
|
27
33
|
export { runWorkflow } from './ai/workflow.ts';
|
|
34
|
+
export { streamText, generateText, generateObject, streamObject, tool, embed, embedMany, smoothStream, openai, createOpenAI, } from './ai-sdk.ts';
|
|
28
35
|
export { postgres } from './postgres/index.ts';
|
|
29
36
|
export type { PostgresOptions, PostgresClient } from './postgres/types.ts';
|
|
30
37
|
export { user } from './user/index.ts';
|
|
31
|
-
export type { UserOptions, UserData, UserModule, OAuth2Client } from './user/types.ts';
|
|
38
|
+
export type { UserOptions, UserData, UserModule, OAuth2Client, } from './user/types.ts';
|
|
32
39
|
export { redis } from './redis/index.ts';
|
|
33
40
|
export type { RedisOptions, RedisClient } from './redis/types.ts';
|
|
34
41
|
export { queue } from './queue/index.ts';
|
|
35
42
|
export type { QueueOptions, QueueJob, Queue } from './queue/types.ts';
|
|
36
43
|
export { tenant } from './tenant/index.ts';
|
|
37
|
-
export type { TenantOptions, TenantModule, TenantContext, FieldDef, FieldType, RelationDef, UserTableRow } from './tenant/types.ts';
|
|
44
|
+
export type { TenantOptions, TenantModule, TenantContext, FieldDef, FieldType, RelationDef, UserTableRow, } from './tenant/types.ts';
|
|
38
45
|
export { agent } from './agent/index.ts';
|
|
39
|
-
export type { AgentOptions, AgentModule, AgentConfig, RunParams, RunResult, KnowledgeDoc } from './agent/types.ts';
|
|
46
|
+
export type { AgentOptions, AgentModule, AgentConfig, RunParams, RunResult, KnowledgeDoc, } from './agent/types.ts';
|
|
40
47
|
export { messager } from './messager/index.ts';
|
|
41
|
-
export type { MessagerOptions, MessagerModule, Channel, ChannelMember, Message } from './messager/types.ts';
|
|
48
|
+
export type { MessagerOptions, MessagerModule, Channel, ChannelMember, Message, } from './messager/types.ts';
|
|
42
49
|
export { deploy, defineConfig } from './deploy/index.ts';
|
|
43
|
-
export type { DeployConfig, AppConfig, DeployServer, AppStatus } from './deploy/types.ts';
|
|
50
|
+
export type { DeployConfig, AppConfig, DeployServer, AppStatus, } from './deploy/types.ts';
|
|
44
51
|
export { opencode } from './opencode/index.ts';
|
|
45
|
-
export type { OpencodeOptions, OpencodeModule, SkillDef, OpencodePermissions, Session as OpencodeSession } from './opencode/types.ts';
|
|
52
|
+
export type { OpencodeOptions, OpencodeModule, SkillDef, OpencodePermissions, Session as OpencodeSession, } from './opencode/types.ts';
|
|
46
53
|
export { health } from './health.ts';
|
|
47
54
|
export type { HealthOptions } from './health.ts';
|
|
48
55
|
export { i18n } from './i18n.ts';
|
|
49
56
|
export type { I18nOptions } from './i18n.ts';
|
|
57
|
+
export { seo, seoMiddleware, seoTags } from './seo.ts';
|
|
58
|
+
export type { SeoOptions, RobotsRule, SitemapUrl, SitemapConfig, SeoHeadersConfig, SeoTagsConfig, } from './seo.ts';
|
|
50
59
|
export { mailer } from './mailer.ts';
|
|
51
60
|
export type { MailerOptions, MailOptions, Mailer } from './mailer.ts';
|
|
52
61
|
export { logdb } from './logdb/index.ts';
|
|
53
|
-
export type { LogdbOptions, LogdbModule, LogEntry, LogEntryInput } from './logdb/types.ts';
|
|
54
|
-
export { iii, createWorker
|
|
55
|
-
export type { IIIModule, IIIOptions, WorkerInfo, FunctionInfo, TriggerInfo, FunctionHandler, FunctionContext, TriggerInput, RemoteWorker, TriggerRequest } from './iii/types.ts';
|
|
62
|
+
export type { LogdbOptions, LogdbModule, LogEntry, LogEntryInput, } from './logdb/types.ts';
|
|
63
|
+
export { iii, createWorker, registerWorker } from './iii/index.ts';
|
|
64
|
+
export type { IIIModule, IIIOptions, WorkerInfo, FunctionInfo, TriggerInfo, FunctionHandler, FunctionContext, TriggerInput, RemoteWorker, TriggerRequest, } from './iii/types.ts';
|