@centerseedwu/naru-agent 0.2.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 +392 -0
- package/dist/agent.d.ts +39 -0
- package/dist/agent.d.ts.map +1 -0
- package/dist/agent.js +578 -0
- package/dist/agent.js.map +1 -0
- package/dist/compression/base.d.ts +12 -0
- package/dist/compression/base.d.ts.map +1 -0
- package/dist/compression/base.js +2 -0
- package/dist/compression/base.js.map +1 -0
- package/dist/compression/compressor.d.ts +20 -0
- package/dist/compression/compressor.d.ts.map +1 -0
- package/dist/compression/compressor.js +52 -0
- package/dist/compression/compressor.js.map +1 -0
- package/dist/compression/in-memory-store.d.ts +8 -0
- package/dist/compression/in-memory-store.d.ts.map +1 -0
- package/dist/compression/in-memory-store.js +13 -0
- package/dist/compression/in-memory-store.js.map +1 -0
- package/dist/decision/index.d.ts +7 -0
- package/dist/decision/index.d.ts.map +1 -0
- package/dist/decision/index.js +4 -0
- package/dist/decision/index.js.map +1 -0
- package/dist/decision/llm-structured-classifier.d.ts +18 -0
- package/dist/decision/llm-structured-classifier.d.ts.map +1 -0
- package/dist/decision/llm-structured-classifier.js +44 -0
- package/dist/decision/llm-structured-classifier.js.map +1 -0
- package/dist/decision/tool-planner.d.ts +14 -0
- package/dist/decision/tool-planner.d.ts.map +1 -0
- package/dist/decision/tool-planner.js +35 -0
- package/dist/decision/tool-planner.js.map +1 -0
- package/dist/decision/types.d.ts +53 -0
- package/dist/decision/types.d.ts.map +1 -0
- package/dist/decision/types.js +12 -0
- package/dist/decision/types.js.map +1 -0
- package/dist/event-bus.d.ts +10 -0
- package/dist/event-bus.d.ts.map +1 -0
- package/dist/event-bus.js +34 -0
- package/dist/event-bus.js.map +1 -0
- package/dist/guardrails/base.d.ts +10 -0
- package/dist/guardrails/base.d.ts.map +1 -0
- package/dist/guardrails/base.js +2 -0
- package/dist/guardrails/base.js.map +1 -0
- package/dist/guardrails/keyword.d.ts +15 -0
- package/dist/guardrails/keyword.d.ts.map +1 -0
- package/dist/guardrails/keyword.js +37 -0
- package/dist/guardrails/keyword.js.map +1 -0
- package/dist/index.d.ts +51 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +39 -0
- package/dist/index.js.map +1 -0
- package/dist/intent/base.d.ts +19 -0
- package/dist/intent/base.d.ts.map +1 -0
- package/dist/intent/base.js +2 -0
- package/dist/intent/base.js.map +1 -0
- package/dist/intent/llm-classifier.d.ts +22 -0
- package/dist/intent/llm-classifier.d.ts.map +1 -0
- package/dist/intent/llm-classifier.js +49 -0
- package/dist/intent/llm-classifier.js.map +1 -0
- package/dist/intent/tool-calling-classifier.d.ts +16 -0
- package/dist/intent/tool-calling-classifier.d.ts.map +1 -0
- package/dist/intent/tool-calling-classifier.js +56 -0
- package/dist/intent/tool-calling-classifier.js.map +1 -0
- package/dist/knowledge/base.d.ts +14 -0
- package/dist/knowledge/base.d.ts.map +1 -0
- package/dist/knowledge/base.js +10 -0
- package/dist/knowledge/base.js.map +1 -0
- package/dist/knowledge/chroma-store.d.ts +25 -0
- package/dist/knowledge/chroma-store.d.ts.map +1 -0
- package/dist/knowledge/chroma-store.js +70 -0
- package/dist/knowledge/chroma-store.js.map +1 -0
- package/dist/knowledge/contextualizer.d.ts +17 -0
- package/dist/knowledge/contextualizer.d.ts.map +1 -0
- package/dist/knowledge/contextualizer.js +47 -0
- package/dist/knowledge/contextualizer.js.map +1 -0
- package/dist/knowledge/graph-store.d.ts +22 -0
- package/dist/knowledge/graph-store.d.ts.map +1 -0
- package/dist/knowledge/graph-store.js +116 -0
- package/dist/knowledge/graph-store.js.map +1 -0
- package/dist/knowledge/hybrid-store.d.ts +16 -0
- package/dist/knowledge/hybrid-store.d.ts.map +1 -0
- package/dist/knowledge/hybrid-store.js +39 -0
- package/dist/knowledge/hybrid-store.js.map +1 -0
- package/dist/knowledge/in-memory-store.d.ts +27 -0
- package/dist/knowledge/in-memory-store.d.ts.map +1 -0
- package/dist/knowledge/in-memory-store.js +54 -0
- package/dist/knowledge/in-memory-store.js.map +1 -0
- package/dist/knowledge/pgvector-store.d.ts +27 -0
- package/dist/knowledge/pgvector-store.d.ts.map +1 -0
- package/dist/knowledge/pgvector-store.js +68 -0
- package/dist/knowledge/pgvector-store.js.map +1 -0
- package/dist/memory/base.d.ts +21 -0
- package/dist/memory/base.d.ts.map +1 -0
- package/dist/memory/base.js +9 -0
- package/dist/memory/base.js.map +1 -0
- package/dist/memory/in-memory-store.d.ts +10 -0
- package/dist/memory/in-memory-store.d.ts.map +1 -0
- package/dist/memory/in-memory-store.js +35 -0
- package/dist/memory/in-memory-store.js.map +1 -0
- package/dist/memory/manager.d.ts +29 -0
- package/dist/memory/manager.d.ts.map +1 -0
- package/dist/memory/manager.js +121 -0
- package/dist/memory/manager.js.map +1 -0
- package/dist/memory/mem0-manager.d.ts +32 -0
- package/dist/memory/mem0-manager.d.ts.map +1 -0
- package/dist/memory/mem0-manager.js +77 -0
- package/dist/memory/mem0-manager.js.map +1 -0
- package/dist/memory/pgvector-store.d.ts +22 -0
- package/dist/memory/pgvector-store.d.ts.map +1 -0
- package/dist/memory/pgvector-store.js +89 -0
- package/dist/memory/pgvector-store.js.map +1 -0
- package/dist/orchestration/channel.d.ts +18 -0
- package/dist/orchestration/channel.d.ts.map +1 -0
- package/dist/orchestration/channel.js +2 -0
- package/dist/orchestration/channel.js.map +1 -0
- package/dist/orchestration/executor.d.ts +19 -0
- package/dist/orchestration/executor.d.ts.map +1 -0
- package/dist/orchestration/executor.js +2 -0
- package/dist/orchestration/executor.js.map +1 -0
- package/dist/orchestration/index.d.ts +13 -0
- package/dist/orchestration/index.d.ts.map +1 -0
- package/dist/orchestration/index.js +9 -0
- package/dist/orchestration/index.js.map +1 -0
- package/dist/orchestration/intent.d.ts +49 -0
- package/dist/orchestration/intent.d.ts.map +1 -0
- package/dist/orchestration/intent.js +57 -0
- package/dist/orchestration/intent.js.map +1 -0
- package/dist/orchestration/orchestrator.d.ts +59 -0
- package/dist/orchestration/orchestrator.d.ts.map +1 -0
- package/dist/orchestration/orchestrator.js +216 -0
- package/dist/orchestration/orchestrator.js.map +1 -0
- package/dist/orchestration/pending.d.ts +28 -0
- package/dist/orchestration/pending.d.ts.map +1 -0
- package/dist/orchestration/pending.js +32 -0
- package/dist/orchestration/pending.js.map +1 -0
- package/dist/orchestration/result.d.ts +24 -0
- package/dist/orchestration/result.d.ts.map +1 -0
- package/dist/orchestration/result.js +2 -0
- package/dist/orchestration/result.js.map +1 -0
- package/dist/orchestration/session-state.d.ts +24 -0
- package/dist/orchestration/session-state.d.ts.map +1 -0
- package/dist/orchestration/session-state.js +19 -0
- package/dist/orchestration/session-state.js.map +1 -0
- package/dist/orchestration/trace.d.ts +20 -0
- package/dist/orchestration/trace.d.ts.map +1 -0
- package/dist/orchestration/trace.js +2 -0
- package/dist/orchestration/trace.js.map +1 -0
- package/dist/session/base.d.ts +7 -0
- package/dist/session/base.d.ts.map +1 -0
- package/dist/session/base.js +2 -0
- package/dist/session/base.js.map +1 -0
- package/dist/session/in-memory-store.d.ts +9 -0
- package/dist/session/in-memory-store.d.ts.map +1 -0
- package/dist/session/in-memory-store.js +13 -0
- package/dist/session/in-memory-store.js.map +1 -0
- package/dist/session/redis-store.d.ts +16 -0
- package/dist/session/redis-store.d.ts.map +1 -0
- package/dist/session/redis-store.js +29 -0
- package/dist/session/redis-store.js.map +1 -0
- package/dist/skills/base.d.ts +38 -0
- package/dist/skills/base.d.ts.map +1 -0
- package/dist/skills/base.js +24 -0
- package/dist/skills/base.js.map +1 -0
- package/dist/skills/registry.d.ts +11 -0
- package/dist/skills/registry.d.ts.map +1 -0
- package/dist/skills/registry.js +37 -0
- package/dist/skills/registry.js.map +1 -0
- package/dist/skills/selectors.d.ts +23 -0
- package/dist/skills/selectors.d.ts.map +1 -0
- package/dist/skills/selectors.js +52 -0
- package/dist/skills/selectors.js.map +1 -0
- package/dist/tools/base.d.ts +34 -0
- package/dist/tools/base.d.ts.map +1 -0
- package/dist/tools/base.js +22 -0
- package/dist/tools/base.js.map +1 -0
- package/dist/tools/vercel-adapter.d.ts +17 -0
- package/dist/tools/vercel-adapter.d.ts.map +1 -0
- package/dist/tools/vercel-adapter.js +66 -0
- package/dist/tools/vercel-adapter.js.map +1 -0
- package/dist/tracing/collector.d.ts +16 -0
- package/dist/tracing/collector.d.ts.map +1 -0
- package/dist/tracing/collector.js +92 -0
- package/dist/tracing/collector.js.map +1 -0
- package/dist/tracing/exporters/jsonl.d.ts +13 -0
- package/dist/tracing/exporters/jsonl.d.ts.map +1 -0
- package/dist/tracing/exporters/jsonl.js +14 -0
- package/dist/tracing/exporters/jsonl.js.map +1 -0
- package/dist/tracing/trace.d.ts +34 -0
- package/dist/tracing/trace.d.ts.map +1 -0
- package/dist/tracing/trace.js +28 -0
- package/dist/tracing/trace.js.map +1 -0
- package/dist/types.d.ts +77 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +7 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/math.d.ts +3 -0
- package/dist/utils/math.d.ts.map +1 -0
- package/dist/utils/math.js +14 -0
- package/dist/utils/math.js.map +1 -0
- package/dist-cjs/agent.js +581 -0
- package/dist-cjs/compression/base.js +2 -0
- package/dist-cjs/compression/compressor.js +55 -0
- package/dist-cjs/compression/in-memory-store.js +16 -0
- package/dist-cjs/decision/index.js +9 -0
- package/dist-cjs/decision/llm-structured-classifier.js +47 -0
- package/dist-cjs/decision/tool-planner.js +38 -0
- package/dist-cjs/decision/types.js +15 -0
- package/dist-cjs/event-bus.js +37 -0
- package/dist-cjs/guardrails/base.js +2 -0
- package/dist-cjs/guardrails/keyword.js +40 -0
- package/dist-cjs/index.js +84 -0
- package/dist-cjs/intent/base.js +2 -0
- package/dist-cjs/intent/llm-classifier.js +52 -0
- package/dist-cjs/intent/tool-calling-classifier.js +59 -0
- package/dist-cjs/knowledge/base.js +12 -0
- package/dist-cjs/knowledge/chroma-store.js +106 -0
- package/dist-cjs/knowledge/contextualizer.js +50 -0
- package/dist-cjs/knowledge/graph-store.js +152 -0
- package/dist-cjs/knowledge/hybrid-store.js +42 -0
- package/dist-cjs/knowledge/in-memory-store.js +57 -0
- package/dist-cjs/knowledge/pgvector-store.js +71 -0
- package/dist-cjs/memory/base.js +11 -0
- package/dist-cjs/memory/in-memory-store.js +38 -0
- package/dist-cjs/memory/manager.js +124 -0
- package/dist-cjs/memory/mem0-manager.js +113 -0
- package/dist-cjs/memory/pgvector-store.js +92 -0
- package/dist-cjs/orchestration/channel.js +2 -0
- package/dist-cjs/orchestration/executor.js +2 -0
- package/dist-cjs/orchestration/index.js +17 -0
- package/dist-cjs/orchestration/intent.js +61 -0
- package/dist-cjs/orchestration/orchestrator.js +219 -0
- package/dist-cjs/orchestration/pending.js +36 -0
- package/dist-cjs/orchestration/result.js +2 -0
- package/dist-cjs/orchestration/session-state.js +22 -0
- package/dist-cjs/orchestration/trace.js +2 -0
- package/dist-cjs/session/base.js +2 -0
- package/dist-cjs/session/in-memory-store.js +16 -0
- package/dist-cjs/session/redis-store.js +32 -0
- package/dist-cjs/skills/base.js +27 -0
- package/dist-cjs/skills/registry.js +40 -0
- package/dist-cjs/skills/selectors.js +56 -0
- package/dist-cjs/tools/base.js +24 -0
- package/dist-cjs/tools/vercel-adapter.js +69 -0
- package/dist-cjs/tracing/collector.js +95 -0
- package/dist-cjs/tracing/exporters/jsonl.js +17 -0
- package/dist-cjs/tracing/trace.js +31 -0
- package/dist-cjs/types.js +9 -0
- package/dist-cjs/utils/math.js +17 -0
- package/package.json +70 -0
package/README.md
ADDED
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
# naru-agent-js
|
|
2
|
+
|
|
3
|
+
輕量 TypeScript Agent 框架,支援 orchestration、記憶、RAG、技能、護欄及結構化決策模式。基於 [Vercel AI SDK](https://sdk.vercel.ai/) 建構,支援 100+ LLM 供應商。
|
|
4
|
+
|
|
5
|
+
從單一 agent 到 Swarm 風格的多 agent 路由,同一個框架全部涵蓋。
|
|
6
|
+
|
|
7
|
+
## 安裝
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install naru-agent-js
|
|
11
|
+
# peer deps(選擇你的 LLM 供應商)
|
|
12
|
+
npm install @ai-sdk/anthropic
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## 架構
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
┌─────────────────────────────────────────────────────────┐
|
|
21
|
+
│ AgentOrchestrator(可選的協作層) │
|
|
22
|
+
│ │
|
|
23
|
+
│ Phase 0: Pending Confirmation(待確認攔截) │
|
|
24
|
+
│ Phase 1: Intent Resolution(確定性 + LLM 分類) │
|
|
25
|
+
│ Phase 2: Direct Execution(高信心度跳過 LLM) │
|
|
26
|
+
│ Phase 3: Delegate(路由到對應的 NaruAgent) │
|
|
27
|
+
└─────────────────────────┬───────────────────────────────┘
|
|
28
|
+
│
|
|
29
|
+
┌─────────────────────────▼───────────────────────────────┐
|
|
30
|
+
│ NaruAgent(核心 agent,可獨立使用) │
|
|
31
|
+
│ │
|
|
32
|
+
│ Tools ─ Skills ─ Memory ─ Knowledge(RAG) │
|
|
33
|
+
│ Session ─ Guardrails ─ Compression ─ Tracing │
|
|
34
|
+
└─────────────────────────────────────────────────────────┘
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## 快速開始
|
|
40
|
+
|
|
41
|
+
### 單一 Agent
|
|
42
|
+
|
|
43
|
+
```typescript
|
|
44
|
+
import { NaruAgent } from "naru-agent-js";
|
|
45
|
+
import { anthropic } from "@ai-sdk/anthropic";
|
|
46
|
+
|
|
47
|
+
const agent = new NaruAgent({
|
|
48
|
+
model: anthropic("claude-sonnet-4-5"),
|
|
49
|
+
instructions: ["你是一個實用的助手。"],
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
const result = await agent.chat("你好!", "session-1");
|
|
53
|
+
console.log(result.content);
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### 多 Agent 協作
|
|
57
|
+
|
|
58
|
+
```typescript
|
|
59
|
+
import {
|
|
60
|
+
AgentOrchestrator,
|
|
61
|
+
NaruAgent,
|
|
62
|
+
DeterministicIntentResolver,
|
|
63
|
+
LLMFallbackIntentResolver,
|
|
64
|
+
InMemoryPendingStateManager,
|
|
65
|
+
} from "naru-agent-js";
|
|
66
|
+
|
|
67
|
+
// 各自擁有不同 tools/skills 的專職 agent
|
|
68
|
+
const taskAgent = new NaruAgent({ model, tools: [brainDumpTool], instructions: ["你負責任務記錄。"] });
|
|
69
|
+
const calAgent = new NaruAgent({ model, tools: [calendarTool], instructions: ["你負責行事曆查詢。"] });
|
|
70
|
+
const general = new NaruAgent({ model, instructions: ["你是通用助手。"] });
|
|
71
|
+
|
|
72
|
+
// 基於意圖的路由
|
|
73
|
+
const orchestrator = new AgentOrchestrator({
|
|
74
|
+
delegate: general, // 預設 fallback
|
|
75
|
+
delegates: new Map([
|
|
76
|
+
["task_capture", taskAgent],
|
|
77
|
+
["calendar_query", calAgent],
|
|
78
|
+
]),
|
|
79
|
+
intentResolver: new LLMFallbackIntentResolver({
|
|
80
|
+
primary: new DeterministicIntentResolver([ // 零 LLM 成本
|
|
81
|
+
{ pattern: /記一下|待辦|todo/i, intent: { object: "task_capture", confidence: 1.0 } },
|
|
82
|
+
{ pattern: /行事曆|會議|schedule/i, intent: { object: "calendar_query", confidence: 1.0 } },
|
|
83
|
+
]),
|
|
84
|
+
fallbackAgent: classifierAgent, // 模糊訊息走 LLM fallback
|
|
85
|
+
}),
|
|
86
|
+
pendingStateManager: new InMemoryPendingStateManager(),
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
const result = await orchestrator.chat("記一下明天要買牛奶", { sessionId: "s1" });
|
|
90
|
+
// → taskAgent 處理此訊息
|
|
91
|
+
// result.decisionTrace.delegateUsed === "taskAgent"
|
|
92
|
+
// result.decisionTrace.phaseReached === "delegate"
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### 最小 Orchestrator(零開銷)
|
|
96
|
+
|
|
97
|
+
```typescript
|
|
98
|
+
// 僅包裝現有 agent — 行為與 agent.chat() 完全一致
|
|
99
|
+
const orchestrator = new AgentOrchestrator({ delegate: myAgent });
|
|
100
|
+
const result = await orchestrator.chat("Hello");
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## 核心功能
|
|
106
|
+
|
|
107
|
+
### 對話(`agent.chat`)
|
|
108
|
+
|
|
109
|
+
標準對話模式,完整的上下文管線 — 記憶、知識檢索、技能、工具呼叫、護欄。
|
|
110
|
+
|
|
111
|
+
```typescript
|
|
112
|
+
const result = await agent.chat("天氣如何?", "session-1", {
|
|
113
|
+
userId: "user-123",
|
|
114
|
+
});
|
|
115
|
+
// result.content, result.usage, result.blocked
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### 決策模式(`agent.decide`)
|
|
119
|
+
|
|
120
|
+
回傳型別化的 JSON 決策而非自然語言。使用完整的預取管線但跳過工具執行 — 適合路由、分類和評分。
|
|
121
|
+
|
|
122
|
+
```typescript
|
|
123
|
+
import { LLMStructuredClassifier } from "naru-agent-js";
|
|
124
|
+
import { z } from "zod";
|
|
125
|
+
|
|
126
|
+
const classifier = new LLMStructuredClassifier({
|
|
127
|
+
model: anthropic("claude-haiku-4-5"),
|
|
128
|
+
schema: z.object({
|
|
129
|
+
intent: z.enum(["question", "complaint", "feedback"]),
|
|
130
|
+
urgency: z.number().min(1).max(5),
|
|
131
|
+
}),
|
|
132
|
+
systemPrompt: "分類使用者訊息。",
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
const result = await agent.decide("我的訂單還沒到!", classifier);
|
|
136
|
+
console.log(result.decision);
|
|
137
|
+
// { intent: "complaint", urgency: 4 }
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### 工具規劃器(ToolPlanner)
|
|
141
|
+
|
|
142
|
+
決定要呼叫哪些工具(含參數)但不執行。適合預覽、稽核或非同步派發。
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
import { ToolPlanner } from "naru-agent-js";
|
|
146
|
+
|
|
147
|
+
const planner = new ToolPlanner({ model: anthropic("claude-haiku-4-5") });
|
|
148
|
+
const plan = await planner.plan("訂一張去東京的機票", myTools);
|
|
149
|
+
// [{ tool: "search_flights", args: { destination: "Tokyo" } }]
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### 工具(Tools)
|
|
153
|
+
|
|
154
|
+
```typescript
|
|
155
|
+
import { tool } from "naru-agent-js";
|
|
156
|
+
import { z } from "zod";
|
|
157
|
+
|
|
158
|
+
const weatherTool = tool({
|
|
159
|
+
name: "get_weather",
|
|
160
|
+
description: "查詢城市目前天氣",
|
|
161
|
+
parameters: z.object({ city: z.string() }),
|
|
162
|
+
execute: async ({ city }) => `${city} 天氣:晴天 22°C`,
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
const agent = new NaruAgent({ model, tools: [weatherTool] });
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### 記憶(Memory)
|
|
169
|
+
|
|
170
|
+
```typescript
|
|
171
|
+
import { MemoryManager, InMemoryMemoryStore } from "naru-agent-js";
|
|
172
|
+
|
|
173
|
+
const memory = new MemoryManager({
|
|
174
|
+
store: new InMemoryMemoryStore(),
|
|
175
|
+
model: myModel,
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
const agent = new NaruAgent({ model, memoryManager: memory });
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
### 知識庫(RAG)
|
|
182
|
+
|
|
183
|
+
```typescript
|
|
184
|
+
import { ChromaKnowledgeStore } from "naru-agent-js";
|
|
185
|
+
|
|
186
|
+
const knowledge = new ChromaKnowledgeStore({
|
|
187
|
+
collectionName: "docs",
|
|
188
|
+
embedFn: myEmbedFn,
|
|
189
|
+
contextualRetrieval: true, // Anthropic Contextual Retrieval
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
await knowledge.ingest([{ content: "...", metadata: {} }]);
|
|
193
|
+
const agent = new NaruAgent({ model, knowledgeStore: knowledge });
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### 技能(Skills)
|
|
197
|
+
|
|
198
|
+
```typescript
|
|
199
|
+
import { skill } from "naru-agent-js";
|
|
200
|
+
|
|
201
|
+
const summarySkill = skill({
|
|
202
|
+
name: "summarize",
|
|
203
|
+
description: "摘要內容",
|
|
204
|
+
triggers: ["摘要", "重點", "tldr"],
|
|
205
|
+
priority: 10,
|
|
206
|
+
run: async (message, context) => ({
|
|
207
|
+
promptInjection: "請簡潔地摘要內容。",
|
|
208
|
+
skillName: "summarize",
|
|
209
|
+
}),
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
const agent = new NaruAgent({ model, skills: [summarySkill] });
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
### 護欄(Guardrails)
|
|
216
|
+
|
|
217
|
+
```typescript
|
|
218
|
+
import { KeywordGuardrail } from "naru-agent-js";
|
|
219
|
+
|
|
220
|
+
const agent = new NaruAgent({
|
|
221
|
+
model,
|
|
222
|
+
guardrails: [new KeywordGuardrail({ blockedPatterns: ["spam", "abuse"] })],
|
|
223
|
+
});
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
### Session 管理
|
|
227
|
+
|
|
228
|
+
```typescript
|
|
229
|
+
import { InMemorySessionStore, RedisSessionStore } from "naru-agent-js";
|
|
230
|
+
|
|
231
|
+
// 開發環境
|
|
232
|
+
const agent = new NaruAgent({ model, sessionStore: new InMemorySessionStore() });
|
|
233
|
+
|
|
234
|
+
// 生產環境(多 instance)
|
|
235
|
+
const agent = new NaruAgent({
|
|
236
|
+
model,
|
|
237
|
+
sessionStore: new RedisSessionStore({ url: process.env.REDIS_URL }),
|
|
238
|
+
});
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### 串流(Streaming)
|
|
242
|
+
|
|
243
|
+
```typescript
|
|
244
|
+
for await (const event of agent.stream("你好!", "session-1")) {
|
|
245
|
+
if (event.type === "text_delta") process.stdout.write(event.text);
|
|
246
|
+
if (event.type === "done") console.log("\n完成:", event.result.usage);
|
|
247
|
+
}
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
### 上下文壓縮(Context Compression)
|
|
251
|
+
|
|
252
|
+
```typescript
|
|
253
|
+
import { ContextCompressor, InMemorySummaryStore } from "naru-agent-js";
|
|
254
|
+
|
|
255
|
+
const agent = new NaruAgent({
|
|
256
|
+
model,
|
|
257
|
+
contextCompressor: new ContextCompressor({
|
|
258
|
+
store: new InMemorySummaryStore(),
|
|
259
|
+
model: myModel,
|
|
260
|
+
triggerTokens: 4000,
|
|
261
|
+
}),
|
|
262
|
+
});
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
### 追蹤(Tracing)
|
|
266
|
+
|
|
267
|
+
```typescript
|
|
268
|
+
import { TraceCollector, JSONLTraceExporter } from "naru-agent-js";
|
|
269
|
+
|
|
270
|
+
const tracer = new TraceCollector({
|
|
271
|
+
exporter: new JSONLTraceExporter({ path: "./traces.jsonl" }),
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
const agent = new NaruAgent({ model, traceCollector: tracer });
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
---
|
|
278
|
+
|
|
279
|
+
## Orchestration API
|
|
280
|
+
|
|
281
|
+
### AgentOrchestrator
|
|
282
|
+
|
|
283
|
+
透過 4 階段管線路由訊息的協作層。
|
|
284
|
+
|
|
285
|
+
```typescript
|
|
286
|
+
const orchestrator = new AgentOrchestrator<MyIntentType>({
|
|
287
|
+
// 必要
|
|
288
|
+
delegate: defaultAgent,
|
|
289
|
+
|
|
290
|
+
// 多 agent 路由(可選)
|
|
291
|
+
delegates: new Map([["intent_name", specializedAgent]]),
|
|
292
|
+
|
|
293
|
+
// 意圖解析(可選)
|
|
294
|
+
intentResolver: myResolver,
|
|
295
|
+
|
|
296
|
+
// 快速路徑執行(可選)
|
|
297
|
+
directExecutors: [myExecutor],
|
|
298
|
+
|
|
299
|
+
// 狀態管理(可選)
|
|
300
|
+
pendingStateManager: new InMemoryPendingStateManager(),
|
|
301
|
+
sessionStateStore: new InMemorySessionStateStore(),
|
|
302
|
+
|
|
303
|
+
// Channel 整合(可選)
|
|
304
|
+
channelAdapter: myChannelAdapter,
|
|
305
|
+
|
|
306
|
+
// 生命週期 hooks(可選)
|
|
307
|
+
lifecycleHooks: {
|
|
308
|
+
beforeMessage: async (msg, opts) => { /* 日誌、認證等 */ },
|
|
309
|
+
afterMessage: async (result) => { /* 指標、分析 */ },
|
|
310
|
+
onError: async (error) => { /* 告警 */ },
|
|
311
|
+
},
|
|
312
|
+
});
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
### OrchestrationResult
|
|
316
|
+
|
|
317
|
+
擴展 `NaruResult`,加上 orchestration 後設資料:
|
|
318
|
+
|
|
319
|
+
| 欄位 | 型別 | 說明 |
|
|
320
|
+
|------|------|------|
|
|
321
|
+
| `content` | `string` | 回覆文字(繼承自 NaruResult) |
|
|
322
|
+
| `blocked` | `boolean` | 是否被護欄攔截(繼承自 NaruResult) |
|
|
323
|
+
| `usage` | `TokenUsage` | Token 用量(繼承自 NaruResult) |
|
|
324
|
+
| `toolCalls` | `string[]` | 使用的工具(繼承自 NaruResult) |
|
|
325
|
+
| `orchestrationIntent` | `OrchestratorIntent<T> \| null` | 解析出的意圖 |
|
|
326
|
+
| `decisionTrace` | `AgentDecisionTrace` | 完整決策追蹤含各階段耗時 |
|
|
327
|
+
| `pendingConfirmation` | `PendingState \| null` | 等待使用者確認 |
|
|
328
|
+
| `sessionId` | `string \| null` | Session 識別碼 |
|
|
329
|
+
|
|
330
|
+
### 自訂意圖型別
|
|
331
|
+
|
|
332
|
+
```typescript
|
|
333
|
+
import { GenericIntentObject } from "naru-agent-js";
|
|
334
|
+
|
|
335
|
+
// 以領域特定意圖擴展
|
|
336
|
+
type MyIntent = GenericIntentObject | "task_capture" | "calendar_query" | "reorganize";
|
|
337
|
+
|
|
338
|
+
// 所有 orchestration 類別完全型別化
|
|
339
|
+
const resolver = new DeterministicIntentResolver<MyIntent>([...]);
|
|
340
|
+
const orchestrator = new AgentOrchestrator<MyIntent>({ delegate, intentResolver: resolver });
|
|
341
|
+
// result.intent?.object 型別為 MyIntent
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
### ChannelAdapter
|
|
345
|
+
|
|
346
|
+
平台特定訊息處理的抽象介面:
|
|
347
|
+
|
|
348
|
+
```typescript
|
|
349
|
+
interface ChannelAdapter<TIn, TOut> {
|
|
350
|
+
parseIncoming(input: TIn): ChannelMessage;
|
|
351
|
+
formatOutgoing(result: OrchestrationResult): TOut;
|
|
352
|
+
loadPendingState(sessionId: string): Promise<PendingState | null>;
|
|
353
|
+
savePendingState(sessionId: string, state: PendingState): Promise<void>;
|
|
354
|
+
clearPendingState(sessionId: string): Promise<void>;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
// 使用方式
|
|
358
|
+
const result = await orchestrator.processChannel(rawLineWebhookEvent);
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
---
|
|
362
|
+
|
|
363
|
+
## Vercel / Edge Runtime
|
|
364
|
+
|
|
365
|
+
所有 I/O 透過 Vercel AI SDK — 可在 Next.js API routes、Edge functions 和 serverless 環境中運作。
|
|
366
|
+
|
|
367
|
+
## 更新日誌
|
|
368
|
+
|
|
369
|
+
### 0.2.0
|
|
370
|
+
- **AgentOrchestrator** — 4 階段路由:pending → intent → direct execute → delegate
|
|
371
|
+
- **DeterministicIntentResolver** — 零成本 keyword/regex 意圖匹配
|
|
372
|
+
- **LLMFallbackIntentResolver** — 確定性 + LLM fallback 組合
|
|
373
|
+
- **BaseDirectExecutor** — 高信心度操作跳過 LLM
|
|
374
|
+
- **ChannelAdapter** — 抽象 channel 介面(LINE、Slack、API 等)
|
|
375
|
+
- **PendingStateManager** — 多步驟確認流程
|
|
376
|
+
- **AgentSessionState** — 實體追蹤用於指代消解
|
|
377
|
+
- **多 agent 路由** — intent-to-delegate 映射給專職 agent
|
|
378
|
+
- **TypeScript 泛型** — 完全型別化的自訂意圖型別
|
|
379
|
+
|
|
380
|
+
### 0.1.2
|
|
381
|
+
- **決策模式**(`agent.decide<T>`) — 具完整上下文管線的結構化 JSON 輸出
|
|
382
|
+
- **LLMStructuredClassifier** — 以 Zod schema 驅動的分類器含上下文組裝
|
|
383
|
+
- **ToolPlanner** — 不執行的工具規劃(dry-run)
|
|
384
|
+
- `agent.chat` 的 `skip` 參數可跳過 intent/skills/toolCalling
|
|
385
|
+
|
|
386
|
+
### 0.1.1
|
|
387
|
+
- 初始公開發布
|
|
388
|
+
- 具工具呼叫、記憶、RAG、技能、護欄、串流、追蹤的 ReAct agent
|
|
389
|
+
|
|
390
|
+
## 授權
|
|
391
|
+
|
|
392
|
+
MIT
|
package/dist/agent.d.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { type TextStreamPart, type ToolSet } from "ai";
|
|
2
|
+
import type { NaruAgentConfig, NaruResult, ChatOptions } from "./types.js";
|
|
3
|
+
import type { StructuredClassifier, DecisionAgentResult, DecisionOptions } from "./decision/types.js";
|
|
4
|
+
import { EventBus } from "./event-bus.js";
|
|
5
|
+
export declare class NaruAgent {
|
|
6
|
+
private model;
|
|
7
|
+
private name;
|
|
8
|
+
private instructions;
|
|
9
|
+
private config;
|
|
10
|
+
private eventBus;
|
|
11
|
+
private skillRegistry;
|
|
12
|
+
private traceCollector;
|
|
13
|
+
private contextCompressor;
|
|
14
|
+
private traceExporters;
|
|
15
|
+
constructor(config: NaruAgentConfig);
|
|
16
|
+
/**
|
|
17
|
+
* Main chat method — full orchestration loop.
|
|
18
|
+
*/
|
|
19
|
+
chat(message: string, options?: ChatOptions): Promise<NaruResult>;
|
|
20
|
+
/**
|
|
21
|
+
* Shared prefetch logic for chat() and chatStream().
|
|
22
|
+
*/
|
|
23
|
+
private prefetch;
|
|
24
|
+
/**
|
|
25
|
+
* Streaming chat — returns an async iterable of text stream parts.
|
|
26
|
+
*/
|
|
27
|
+
chatStream(message: string, options?: ChatOptions): AsyncIterable<TextStreamPart<ToolSet>>;
|
|
28
|
+
/**
|
|
29
|
+
* Structured decision mode — uses full prefetch context (memory, summary,
|
|
30
|
+
* knowledge, hooks) but returns a typed JSON decision instead of generating
|
|
31
|
+
* a natural-language response or executing tools.
|
|
32
|
+
*/
|
|
33
|
+
decide<T>(message: string, classifier: StructuredClassifier<T>, options?: DecisionOptions): Promise<DecisionAgentResult<T>>;
|
|
34
|
+
getEventBus(): EventBus;
|
|
35
|
+
private makeResult;
|
|
36
|
+
private resolveToolChoice;
|
|
37
|
+
private getClassifierTools;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=agent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,cAAc,EACnB,KAAK,OAAO,EAEb,MAAM,IAAI,CAAC;AAEZ,OAAO,KAAK,EACV,eAAe,EACf,UAAU,EACV,WAAW,EAGZ,MAAM,YAAY,CAAC;AAEpB,OAAO,KAAK,EACV,oBAAoB,EACpB,mBAAmB,EACnB,eAAe,EAChB,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAY1C,qBAAa,SAAS;IACpB,OAAO,CAAC,KAAK,CAAgB;IAC7B,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,YAAY,CAAW;IAC/B,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,QAAQ,CAAW;IAC3B,OAAO,CAAC,aAAa,CAA8B;IACnD,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,iBAAiB,CAAkC;IAC3D,OAAO,CAAC,cAAc,CAAsB;gBAEhC,MAAM,EAAE,eAAe;IAmCnC;;OAEG;IACG,IAAI,CACR,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,WAAW,GACpB,OAAO,CAAC,UAAU,CAAC;IAuKtB;;OAEG;YACW,QAAQ;IAiMtB;;OAEG;IACI,UAAU,CACf,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,WAAW,GACpB,aAAa,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;IA8FzC;;;;OAIG;IACG,MAAM,CAAC,CAAC,EACZ,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,oBAAoB,CAAC,CAAC,CAAC,EACnC,OAAO,CAAC,EAAE,eAAe,GACxB,OAAO,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC;IAsHlC,WAAW,IAAI,QAAQ;IAIvB,OAAO,CAAC,UAAU;IAoBlB,OAAO,CAAC,iBAAiB;IAUzB,OAAO,CAAC,kBAAkB;CAM3B"}
|