weifuwu 0.10.0 → 0.11.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 +86 -125
- package/dist/agent/run.d.ts +1 -1
- package/dist/agent/types.d.ts +2 -2
- package/dist/ai/workflow.d.ts +14 -0
- package/dist/index.d.ts +1 -2
- package/dist/index.js +801 -819
- package/dist/opencode/rest.d.ts +1 -1
- package/dist/opencode/run.d.ts +1 -1
- package/dist/opencode/tools/index.d.ts +1 -1
- package/dist/opencode/ws.d.ts +1 -1
- package/dist/postgres/schema/columns.d.ts +1 -0
- package/dist/postgres/schema/index.d.ts +2 -2
- package/dist/postgres/schema/table.d.ts +27 -0
- package/dist/postgres/types.d.ts +4 -0
- package/dist/user/oauth2.d.ts +2 -1
- package/dist/vendor.d.ts +0 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
weifuwu doesn't invent its own request/response abstraction. `Request` and `Response` are the same objects you use in `fetch()` — what you learn in the browser applies directly on the server. `ctx` is the only framework object, and it only carries what the router parsed for you (`params`, `query`).
|
|
8
8
|
|
|
9
|
-
Everything follows the same `(req, ctx) => Response` contract. The Router handles HTTP routing and WebSocket. All other features — auth, validation, database, GraphQL, AI
|
|
9
|
+
Everything follows the same `(req, ctx) => Response` contract. The Router handles HTTP routing and WebSocket. All other features — auth, validation, database, GraphQL, AI — are standalone modules you import and mount with `app.use()`.
|
|
10
10
|
|
|
11
11
|
## Features
|
|
12
12
|
|
|
@@ -18,8 +18,8 @@ Everything follows the same `(req, ctx) => Response` contract. The Router handle
|
|
|
18
18
|
- **WebSocket** — `router.ws()` with upgrade middleware (auth before connect)
|
|
19
19
|
- **GraphQL** — `graphql(handler)` sub-Router with GraphiQL IDE
|
|
20
20
|
- **AI streaming** — `ai(handler)` sub-Router via Vercel AI SDK
|
|
21
|
-
- **
|
|
22
|
-
- **AI Agent** — `agent()` — server-side AI agents with chat/
|
|
21
|
+
- **DAG workflow tool** — `runWorkflow()` — multi-step execution engine as a single AI SDK `Tool`
|
|
22
|
+
- **AI Agent** — `agent()` — server-side AI agents with chat/tool-use/knowledge types, OpenAI-compatible, Ollama-ready
|
|
23
23
|
- **Messaging** — `messager()` — real-time chat with channels, WebSocket, agent routing, webhook support
|
|
24
24
|
- **Tenant BaaS** — `tenant()` — multi-tenant dynamic tables, auto REST + GraphQL, row-level isolation, pgvector/HNSW
|
|
25
25
|
- **Redis** — `redis()` — ioredis client, `ctx.redis`, middleware
|
|
@@ -278,6 +278,50 @@ await users.createIndex('embedding', { // pgvector HNSW
|
|
|
278
278
|
await users.drop({ cascade: true })
|
|
279
279
|
```
|
|
280
280
|
|
|
281
|
+
### Type-safe CRUD with BoundTable
|
|
282
|
+
|
|
283
|
+
Two usage paths — use `pg.table()` when you have a `pg` handle, or `pgTable()` with explicit `sql`:
|
|
284
|
+
|
|
285
|
+
```ts
|
|
286
|
+
// pg.table() — auto-binds sql, no need to pass it
|
|
287
|
+
const users = pg.table('_users', {
|
|
288
|
+
id: serial('id').primaryKey(),
|
|
289
|
+
name: text('name').notNull(),
|
|
290
|
+
email: text('email').unique(),
|
|
291
|
+
active: boolean('active').default(true),
|
|
292
|
+
createdAt: timestamptz('created_at').default(sql`NOW()`),
|
|
293
|
+
})
|
|
294
|
+
|
|
295
|
+
// INSERT ... RETURNING * — auto-strips serial id
|
|
296
|
+
const user = await users.insert({ name: 'Alice', email: 'alice@test.com' })
|
|
297
|
+
// → { id: 1, name: 'Alice', email: 'alice@test.com', active: true, ... }
|
|
298
|
+
|
|
299
|
+
// SELECT ... WHERE id = ? LIMIT 1
|
|
300
|
+
const found = await users.findById(1)
|
|
301
|
+
|
|
302
|
+
// SELECT ... WHERE ... [ORDER BY ...] [LIMIT ...] [OFFSET ...]
|
|
303
|
+
const admins = await users.find({ role: 'admin' })
|
|
304
|
+
const sorted = await users.find({ active: true }, { orderBy: { name: 'asc' } })
|
|
305
|
+
const page = await users.find(undefined, { limit: 10, offset: 0 })
|
|
306
|
+
const filtered = await users.find({ role: 'admin' }, { orderBy: { name: 'desc' }, limit: 5 })
|
|
307
|
+
|
|
308
|
+
// UPDATE ... SET ... WHERE ... RETURNING *
|
|
309
|
+
const updated = await users.update({ id: 1 }, { name: 'Bob' })
|
|
310
|
+
// With SQL expressions:
|
|
311
|
+
await users.update({ id: 1 }, { name: 'Bob', updated_at: sql`NOW()` })
|
|
312
|
+
|
|
313
|
+
// DELETE ... WHERE ... RETURNING 1
|
|
314
|
+
const ok = await users.delete({ id: 1 })
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
When using `pgTable()` directly (without `pg`), pass `sql` as the first argument:
|
|
318
|
+
|
|
319
|
+
```ts
|
|
320
|
+
const t = pgTable('_users', { ... })
|
|
321
|
+
await t.insert(ctx.sql, { name: 'Alice' })
|
|
322
|
+
await t.find(ctx.sql, { role: 'admin' }, { orderBy: { name: 'asc' } })
|
|
323
|
+
```
|
|
324
|
+
|
|
281
325
|
### Complex queries use raw SQL
|
|
282
326
|
|
|
283
327
|
```ts
|
|
@@ -690,7 +734,7 @@ await fetch('http://localhost/api/sys/tenants/invite', {
|
|
|
690
734
|
|
|
691
735
|
## AI Agent
|
|
692
736
|
|
|
693
|
-
Server-side AI agents with OpenAI-compatible API. Built-in chat,
|
|
737
|
+
Server-side AI agents with OpenAI-compatible API. Built-in chat, tool-use (tool-calling), and knowledge (RAG) types. Works out of the box with Ollama or any OpenAI-compatible provider.
|
|
694
738
|
|
|
695
739
|
```ts
|
|
696
740
|
import { agent } from 'weifuwu'
|
|
@@ -704,7 +748,7 @@ app.use('/api', agents.router())
|
|
|
704
748
|
| Type | Description | Execution |
|
|
705
749
|
|------|-------------|-----------|
|
|
706
750
|
| `chat` | Pure conversation | `streamText()` / `generateText()` |
|
|
707
|
-
| `
|
|
751
|
+
| `tool-use` | Tool-calling agent | `streamText({ tools })` |
|
|
708
752
|
|
|
709
753
|
### Knowledge (RAG)
|
|
710
754
|
|
|
@@ -841,18 +885,18 @@ app.use('/chat', ai(async (req, ctx) => {
|
|
|
841
885
|
serve(app.handler(), { port: 3000 })
|
|
842
886
|
```
|
|
843
887
|
|
|
844
|
-
##
|
|
888
|
+
## runWorkflow
|
|
845
889
|
|
|
846
|
-
|
|
890
|
+
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.
|
|
847
891
|
|
|
848
892
|
```ts
|
|
849
|
-
import {
|
|
893
|
+
import { tool, streamText } from 'ai'
|
|
894
|
+
import { runWorkflow } from 'weifuwu'
|
|
850
895
|
import { z } from 'zod'
|
|
851
896
|
|
|
852
|
-
// 1. Define tools (business capabilities)
|
|
853
897
|
const tools = {
|
|
854
898
|
queryUser: tool({
|
|
855
|
-
description: 'Query user info
|
|
899
|
+
description: 'Query user info',
|
|
856
900
|
inputSchema: z.object({ userId: z.string() }),
|
|
857
901
|
execute: async ({ userId }) => ({ id: userId, email: 'user@test.com', name: 'Test' }),
|
|
858
902
|
}),
|
|
@@ -861,139 +905,57 @@ const tools = {
|
|
|
861
905
|
inputSchema: z.object({ to: z.string(), subject: z.string() }),
|
|
862
906
|
execute: async ({ to, subject }) => ({ sent: true }),
|
|
863
907
|
}),
|
|
908
|
+
runWF: runWorkflow({ tools: { queryUser, sendEmail } }),
|
|
864
909
|
}
|
|
865
910
|
|
|
866
|
-
//
|
|
867
|
-
const
|
|
868
|
-
|
|
869
|
-
// POST /agent { nodes: [...] } → 200 { workflow: {...}, result: ... }
|
|
870
|
-
|
|
871
|
-
// With SSE streaming:
|
|
872
|
-
app.use('/agent-stream', workflow(() => ({ tools, stream: true })))
|
|
873
|
-
// POST /agent-stream { nodes: [...] }
|
|
874
|
-
// → 200 { workflowId: "xxx", eventsUrl: "/xxx/events" }
|
|
875
|
-
// GET /agent-stream/:workflowId/events
|
|
876
|
-
// → SSE: workflow-start → node-start → node-end → complete
|
|
877
|
-
|
|
878
|
-
// With LLM model (generates workflow from goal):
|
|
879
|
-
app.use('/agent-llm', workflow(() => ({
|
|
911
|
+
// Use in any streamText call — the LLM can decide when to trigger a workflow
|
|
912
|
+
const result = await streamText({
|
|
913
|
+
model,
|
|
880
914
|
tools,
|
|
881
|
-
|
|
882
|
-
})))
|
|
883
|
-
// POST /agent-llm { goal: "给用户123发欢迎邮件" }
|
|
884
|
-
// ← LLM generates → executes → returns result
|
|
885
|
-
```
|
|
886
|
-
|
|
887
|
-
### Tool
|
|
888
|
-
|
|
889
|
-
```ts
|
|
890
|
-
import { tool } from 'weifuwu'
|
|
891
|
-
import { z } from 'zod'
|
|
892
|
-
|
|
893
|
-
const myTool = tool({
|
|
894
|
-
description: '做什么的,返回什么',
|
|
895
|
-
inputSchema: z.object({ key: z.string() }),
|
|
896
|
-
execute: async (input, ctx) => {
|
|
897
|
-
return { result: input.key }
|
|
898
|
-
},
|
|
899
|
-
})
|
|
900
|
-
```
|
|
901
|
-
|
|
902
|
-
`ctx.onStream` 用于流式推送(如 LLM token 输出):
|
|
903
|
-
|
|
904
|
-
```ts
|
|
905
|
-
const llmTool = tool({
|
|
906
|
-
description: '生成文本',
|
|
907
|
-
inputSchema: z.object({ prompt: z.string() }),
|
|
908
|
-
execute: async (input, ctx) => {
|
|
909
|
-
const stream = await openai.chat.completions.create({ ... })
|
|
910
|
-
let full = ''
|
|
911
|
-
for await (const chunk of stream) {
|
|
912
|
-
full += chunk.choices[0]?.delta?.content || ''
|
|
913
|
-
ctx.onStream?.({ type: 'llm-stream', chunk, accumulated: full })
|
|
914
|
-
}
|
|
915
|
-
return { text: full }
|
|
916
|
-
},
|
|
915
|
+
messages: [{ role: 'user', content: '查询用户123,如果存在则发送欢迎邮件' }],
|
|
917
916
|
})
|
|
918
917
|
```
|
|
919
918
|
|
|
920
|
-
###
|
|
919
|
+
### Node types
|
|
921
920
|
|
|
922
|
-
7 built-in node types:
|
|
921
|
+
7 built-in node types for defining the execution graph:
|
|
923
922
|
|
|
924
923
|
| Node | Purpose | Input |
|
|
925
924
|
|------|---------|-------|
|
|
926
|
-
| `call` | Call a
|
|
927
|
-
| `set` |
|
|
925
|
+
| `call` | Call a registered AI SDK Tool | `{ tool: "name", args: {...} }` |
|
|
926
|
+
| `set` | Assign a variable | `{ name: "x", value: 42 }` |
|
|
928
927
|
| `get` | Read a variable | `{ name: "x" }` |
|
|
929
928
|
| `eval` | Evaluate an expression | `{ expression: "$var.x + 1" }` |
|
|
930
929
|
| `if` | Conditional branch | `{ conditions: [{ test: ..., body: [nodes] }] }` |
|
|
931
930
|
| `while` | Loop | `{ condition: "$var.i < 5" }, body: [nodes]` |
|
|
932
931
|
| `http` | HTTP request | `{ url: "https://...", method: "GET" }` |
|
|
933
932
|
|
|
934
|
-
###
|
|
933
|
+
### Reference syntax
|
|
935
934
|
|
|
936
935
|
| Pattern | Meaning | Example |
|
|
937
936
|
|---------|---------|---------|
|
|
938
937
|
| `$var.x` | Variable `x` | `$var.counter` |
|
|
939
938
|
| `$nodes.u.output` | Full output of node `u` | `$nodes.u.output` |
|
|
940
939
|
| `$nodes.u.output.field` | Specific field | `$nodes.u.output.email` |
|
|
941
|
-
| `$input.userId` |
|
|
942
|
-
| `42`, `true`, `"hello"` | Literal values | Passed as-is |
|
|
943
|
-
|
|
944
|
-
### Engine API
|
|
945
|
-
|
|
946
|
-
For programmatic use outside of Router:
|
|
947
|
-
|
|
948
|
-
```ts
|
|
949
|
-
import { createWorkflowEngine, createSSEManager } from 'weifuwu'
|
|
950
|
-
|
|
951
|
-
const sse = createSSEManager()
|
|
952
|
-
const engine = createWorkflowEngine({ tools, sseManager: sse })
|
|
953
|
-
|
|
954
|
-
// Sync execution
|
|
955
|
-
const result = await engine.execute({ nodes: [...] })
|
|
940
|
+
| `$input.userId` | Input param | `$input.userId` |
|
|
956
941
|
|
|
957
|
-
|
|
958
|
-
engine.runAsync('wf-1', { nodes: [...] })
|
|
959
|
-
```
|
|
942
|
+
### LLM generation
|
|
960
943
|
|
|
961
|
-
|
|
944
|
+
Pass a `model` to `runWorkflow` — the LLM generates the workflow JSON from a goal:
|
|
962
945
|
|
|
963
946
|
```ts
|
|
964
|
-
const
|
|
965
|
-
|
|
947
|
+
const runWF = runWorkflow({
|
|
948
|
+
tools: { queryUser, sendEmail },
|
|
949
|
+
model: openai('gpt-4o'),
|
|
950
|
+
})
|
|
966
951
|
|
|
967
|
-
const
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
// event: llm-stream — { nodeId, chunk, accumulated }
|
|
972
|
-
// event: complete — { result, duration }
|
|
973
|
-
// event: error — { error }
|
|
952
|
+
const result = await streamText({
|
|
953
|
+
model,
|
|
954
|
+
tools: { runWF },
|
|
955
|
+
})
|
|
974
956
|
```
|
|
975
957
|
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
Define reusable sub-workflows in the `functions` field:
|
|
979
|
-
|
|
980
|
-
```json
|
|
981
|
-
{
|
|
982
|
-
"functions": {
|
|
983
|
-
"double": {
|
|
984
|
-
"inputSchema": { "type": "object", "properties": { "x": { "type": "number" } } },
|
|
985
|
-
"workflow": {
|
|
986
|
-
"nodes": [
|
|
987
|
-
{ "id": "calc", "tool": "eval", "input": { "expression": "$input.x * 2" } }
|
|
988
|
-
]
|
|
989
|
-
}
|
|
990
|
-
}
|
|
991
|
-
},
|
|
992
|
-
"nodes": [
|
|
993
|
-
{ "id": "call_double", "tool": "call", "input": { "function": "double", "args": { "x": 21 } } }
|
|
994
|
-
]
|
|
995
|
-
}
|
|
996
|
-
```
|
|
958
|
+
The LLM calls `runWF` with a goal, and `runWorkflow` internally calls `generateText` to produce the workflow nodes, then executes them.
|
|
997
959
|
|
|
998
960
|
## React pages with tsx()
|
|
999
961
|
|
|
@@ -1194,14 +1156,12 @@ export default function NotFound() {
|
|
|
1194
1156
|
## Usage within a full app
|
|
1195
1157
|
|
|
1196
1158
|
```ts
|
|
1197
|
-
import { serve, Router, ai, graphql
|
|
1198
|
-
import { tsx } from 'weifuwu/tsx'
|
|
1159
|
+
import { serve, Router, ai, graphql } from 'weifuwu'
|
|
1199
1160
|
|
|
1200
1161
|
const app = new Router()
|
|
1201
1162
|
app.use('/', await tsx({ dir: './pages/' }))
|
|
1202
1163
|
app.use('/chat', ai(async (req) => ({ model: openai('gpt-4o'), messages: (await req.json()).messages })))
|
|
1203
1164
|
app.use('/graphql', graphql(() => ({ schema: `type Query { hello: String }`, resolvers: { Query: { hello: () => 'world' } } })))
|
|
1204
|
-
app.use('/agent', workflow(() => ({ tools: myTools, stream: true })))
|
|
1205
1165
|
app.ws('/chat', { message(ws, _, data) { ws.send(data) } })
|
|
1206
1166
|
|
|
1207
1167
|
serve(app.handler(), { websocket: app.websocketHandler() })
|
|
@@ -1334,7 +1294,7 @@ Returns `TenantModule` — `{ migrate, middleware, router, graphql, close }`.
|
|
|
1334
1294
|
| `model` | env `OPENAI_MODEL` → Ollama | `LanguageModel` from ai SDK |
|
|
1335
1295
|
| `embeddingModel` | env `OPENAI_EMBEDDING_MODEL` → Ollama | `EmbeddingModel` for knowledge RAG |
|
|
1336
1296
|
| `embeddingDimension` | `1024` | Vector dimension for pgvector |
|
|
1337
|
-
| `tools` | — | Tools for
|
|
1297
|
+
| `tools` | — | Tools for tool-use agents (ai SDK `Tool` objects) |
|
|
1338
1298
|
|
|
1339
1299
|
Returns `AgentModule` — `{ migrate, router, run, addKnowledge, close }`.
|
|
1340
1300
|
|
|
@@ -1418,12 +1378,12 @@ serve(app.handler(), { websocket: app.websocketHandler() })
|
|
|
1418
1378
|
| `queue(options?)` | Redis-backed job queue — immediate, delayed, cron scheduling |
|
|
1419
1379
|
| `user(options)` | Built-in authentication (password + OAuth2 Server + JWT, middleware) |
|
|
1420
1380
|
| `tenant(options)` | Multi-tenant BaaS — dynamic tables, REST + GraphQL auto-generation, row-level isolation |
|
|
1421
|
-
| `agent(options)` | AI Agent — chat/
|
|
1381
|
+
| `agent(options)` | AI Agent — chat/tool-use/knowledge, Ollama-ready, programmatic API |
|
|
1422
1382
|
| `messager(options)` | Real-time messaging — channels, WebSocket, agent routing, webhooks |
|
|
1423
1383
|
| `opencode(options)` | AI programming assistant — chat agents with tools, skills, permissions, isolated workspaces |
|
|
1424
1384
|
| `graphql(handler)` | GraphQL endpoint (GET/POST + GraphiQL) |
|
|
1425
1385
|
| `ai(handler)` | AI streaming endpoint (POST) |
|
|
1426
|
-
| `
|
|
1386
|
+
| `runWorkflow(options)` | DAG execution engine as an AI SDK `Tool` — use with `streamText()` |
|
|
1427
1387
|
|
|
1428
1388
|
### Deploy
|
|
1429
1389
|
|
|
@@ -1441,13 +1401,14 @@ serve(app.handler(), { websocket: app.websocketHandler() })
|
|
|
1441
1401
|
| `setCookie(res, name, value, options?)` | Set cookie (returns new Response) |
|
|
1442
1402
|
| `deleteCookie(res, name)` | Delete cookie (returns new Response) |
|
|
1443
1403
|
| `useTsx()` | Hook returning `{ params, query, user, parsed }` from `TsxContext` |
|
|
1444
|
-
| `
|
|
1445
|
-
| `
|
|
1446
|
-
| `
|
|
1447
|
-
| `pgTable(name, columns)` | Type-safe table schema definition with DDL generation |
|
|
1404
|
+
| `runWorkflow(options)` | Create a DAG execution AI SDK `Tool` — `{ tools?, model?, maxSteps? }` |
|
|
1405
|
+
| `pgTable(name, columns)` | Type-safe table schema definition with DDL + CRUD |
|
|
1406
|
+
| `pg.table(name, columns)` | Pre-bound table (no `sql` parameter needed for CRUD) |
|
|
1448
1407
|
| `serial()`, `uuid()`, `text()`, `integer()`, `boolean()`, `timestamptz()`, `jsonb()`, `textArray()`, `vector()` | Column type builders |
|
|
1449
|
-
| `sql(strings, ...)` | SQL expression literal for
|
|
1408
|
+
| `sql(strings, ...)` | SQL expression literal for defaults and SET values (e.g. `sql\`NOW()\``) |
|
|
1450
1409
|
| `PgModule` | Base class for database-backed modules (provides `sql`, `close()`) |
|
|
1410
|
+
| `BoundTable` | Table with pre-bound `sql` — returned by `pg.table()` |
|
|
1411
|
+
| `FindOptions` | Query options: `{ orderBy?, limit?, offset? }` for `find()` |
|
|
1451
1412
|
|
|
1452
1413
|
Import `useTsx` and `TsxContext` from `'weifuwu'`.
|
|
1453
1414
|
|
package/dist/agent/run.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type LanguageModel, type EmbeddingModel, type Tool } from 'ai';
|
|
2
2
|
import type { Sql } from '../vendor.ts';
|
|
3
3
|
import type { RunParams, RunResult, KnowledgeDoc } from './types.ts';
|
|
4
4
|
interface RunnerDeps {
|
package/dist/agent/types.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import type { LanguageModel, EmbeddingModel, Tool } from '
|
|
1
|
+
import type { LanguageModel, EmbeddingModel, Tool } from 'ai';
|
|
2
2
|
export interface AgentConfig {
|
|
3
3
|
id: number;
|
|
4
4
|
tenant_id: string | null;
|
|
5
5
|
name: string;
|
|
6
6
|
description: string;
|
|
7
|
-
type: 'chat' | '
|
|
7
|
+
type: 'chat' | 'tool-use';
|
|
8
8
|
model: string;
|
|
9
9
|
system_prompt: string;
|
|
10
10
|
owner_id: number;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { LanguageModel } from 'ai';
|
|
2
|
+
export declare function runWorkflow(opts?: {
|
|
3
|
+
tools?: Record<string, any>;
|
|
4
|
+
model?: LanguageModel;
|
|
5
|
+
maxSteps?: number;
|
|
6
|
+
}): import("ai").Tool<{
|
|
7
|
+
goal: string;
|
|
8
|
+
nodes?: any[];
|
|
9
|
+
}, {
|
|
10
|
+
result: unknown;
|
|
11
|
+
nodeOutputs: {
|
|
12
|
+
[k: string]: unknown;
|
|
13
|
+
};
|
|
14
|
+
}>;
|
package/dist/index.d.ts
CHANGED
|
@@ -23,8 +23,7 @@ export { graphql } from './graphql.ts';
|
|
|
23
23
|
export type { GraphQLOptions, GraphQLHandler } from './graphql.ts';
|
|
24
24
|
export { ai } from './ai.ts';
|
|
25
25
|
export type { AIHandler } from './ai.ts';
|
|
26
|
-
export {
|
|
27
|
-
export type { Tool, Workflow, WorkflowEngine, WorkflowState, SSEEvent, WorkflowOptions, WorkflowHandler } from './workflow/index.ts';
|
|
26
|
+
export { runWorkflow } from './ai/workflow.ts';
|
|
28
27
|
export { postgres } from './postgres/index.ts';
|
|
29
28
|
export type { PostgresOptions, PostgresClient } from './postgres/types.ts';
|
|
30
29
|
export { user } from './user/index.ts';
|