{"_id":"@centerseedwu/naru-agent","name":"@centerseedwu/naru-agent","dist-tags":{"latest":"0.2.0"},"versions":{"0.2.0":{"name":"@centerseedwu/naru-agent","version":"0.2.0","description":"Lightweight TypeScript Agent framework with memory, RAG, skills, and guardrails","type":"module","main":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"require":"./dist-cjs/index.js","import":"./dist/index.js","default":"./dist/index.js","types":"./dist/index.d.ts"}},"scripts":{"build":"tsc && tsc -p tsconfig.cjs.json","test":"vitest run","test:watch":"vitest","test:integration":"vitest run --config vitest.integration.config.ts","lint":"tsc --noEmit"},"dependencies":{"ai":"^6.0.116","uuid":"^10.0","zod":"^4"},"devDependencies":{"@ai-sdk/google":"^3.0.43","@types/node":"^22.0","@types/pg":"^8.18.0","@types/uuid":"^10.0","typescript":"^5.6","vitest":"^2.0"},"peerDependencies":{"@ai-sdk/google":"^1.0","@ai-sdk/anthropic":"^1.0","chromadb":"^1.9","mem0ai":"^1.0"},"peerDependenciesMeta":{"@ai-sdk/google":{"optional":true},"@ai-sdk/anthropic":{"optional":true},"chromadb":{"optional":true},"mem0ai":{"optional":true}},"optionalDependencies":{"graphology":"^0.25","ioredis":"^5.0","pg":"^8.0"},"engines":{"node":">=18"},"license":"MIT","_id":"@centerseedwu/naru-agent@0.2.0","gitHead":"f3fa890fdfe7cda204646f9e73030fc80daf1806","_nodeVersion":"20.20.0","_npmVersion":"10.8.2","dist":{"integrity":"sha512-kGoix6zFhcPJk9wjf92VGoe8xWzz7QDwmMdOZwU4zKxlzfn/ZktG1DT9EY6iMDorSAUIMxQtE6EaaIAaVmk6Ww==","shasum":"30798bf6bae8ac99cb0e2bf01a7fcee9e67a9f21","tarball":"https://registry.npmjs.org/@centerseedwu/naru-agent/-/naru-agent-0.2.0.tgz","fileCount":247,"unpackedSize":382218,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCICatWMSYbmt2vm+B2u8QZr9LnBmBcNIEdvxiaOEq3Am+AiA1dvAxU8lAwYIy3VYdaUfJxvJ7Chsb1Y96VeLhDP8o6w=="}]},"_npmUser":{"name":"centerseedwu","email":"centerseedwu@gmail.com"},"directories":{},"maintainers":[{"name":"centerseedwu","email":"centerseedwu@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/naru-agent_0.2.0_1773480974308_0.35277404434839554"},"_hasShrinkwrap":false}},"time":{"created":"2026-03-14T09:36:14.146Z","0.2.0":"2026-03-14T09:36:14.457Z","modified":"2026-03-14T09:36:14.682Z"},"maintainers":[{"name":"centerseedwu","email":"centerseedwu@gmail.com"}],"description":"Lightweight TypeScript Agent framework with memory, RAG, skills, and guardrails","license":"MIT","readme":"# naru-agent-js\n\n輕量 TypeScript Agent 框架，支援 orchestration、記憶、RAG、技能、護欄及結構化決策模式。基於 [Vercel AI SDK](https://sdk.vercel.ai/) 建構，支援 100+ LLM 供應商。\n\n從單一 agent 到 Swarm 風格的多 agent 路由，同一個框架全部涵蓋。\n\n## 安裝\n\n```bash\nnpm install naru-agent-js\n# peer deps（選擇你的 LLM 供應商）\nnpm install @ai-sdk/anthropic\n```\n\n---\n\n## 架構\n\n```\n┌─────────────────────────────────────────────────────────┐\n│ AgentOrchestrator（可選的協作層）                         │\n│                                                         │\n│ Phase 0: Pending Confirmation（待確認攔截）               │\n│ Phase 1: Intent Resolution（確定性 + LLM 分類）          │\n│ Phase 2: Direct Execution（高信心度跳過 LLM）            │\n│ Phase 3: Delegate（路由到對應的 NaruAgent）               │\n└─────────────────────────┬───────────────────────────────┘\n                          │\n┌─────────────────────────▼───────────────────────────────┐\n│ NaruAgent（核心 agent，可獨立使用）                       │\n│                                                         │\n│  Tools ─ Skills ─ Memory ─ Knowledge(RAG)               │\n│  Session ─ Guardrails ─ Compression ─ Tracing           │\n└─────────────────────────────────────────────────────────┘\n```\n\n---\n\n## 快速開始\n\n### 單一 Agent\n\n```typescript\nimport { NaruAgent } from \"naru-agent-js\";\nimport { anthropic } from \"@ai-sdk/anthropic\";\n\nconst agent = new NaruAgent({\n  model: anthropic(\"claude-sonnet-4-5\"),\n  instructions: [\"你是一個實用的助手。\"],\n});\n\nconst result = await agent.chat(\"你好！\", \"session-1\");\nconsole.log(result.content);\n```\n\n### 多 Agent 協作\n\n```typescript\nimport {\n  AgentOrchestrator,\n  NaruAgent,\n  DeterministicIntentResolver,\n  LLMFallbackIntentResolver,\n  InMemoryPendingStateManager,\n} from \"naru-agent-js\";\n\n// 各自擁有不同 tools/skills 的專職 agent\nconst taskAgent = new NaruAgent({ model, tools: [brainDumpTool], instructions: [\"你負責任務記錄。\"] });\nconst calAgent  = new NaruAgent({ model, tools: [calendarTool], instructions: [\"你負責行事曆查詢。\"] });\nconst general   = new NaruAgent({ model, instructions: [\"你是通用助手。\"] });\n\n// 基於意圖的路由\nconst orchestrator = new AgentOrchestrator({\n  delegate: general,                              // 預設 fallback\n  delegates: new Map([\n    [\"task_capture\", taskAgent],\n    [\"calendar_query\", calAgent],\n  ]),\n  intentResolver: new LLMFallbackIntentResolver({\n    primary: new DeterministicIntentResolver([     // 零 LLM 成本\n      { pattern: /記一下|待辦|todo/i, intent: { object: \"task_capture\", confidence: 1.0 } },\n      { pattern: /行事曆|會議|schedule/i, intent: { object: \"calendar_query\", confidence: 1.0 } },\n    ]),\n    fallbackAgent: classifierAgent,                // 模糊訊息走 LLM fallback\n  }),\n  pendingStateManager: new InMemoryPendingStateManager(),\n});\n\nconst result = await orchestrator.chat(\"記一下明天要買牛奶\", { sessionId: \"s1\" });\n// → taskAgent 處理此訊息\n// result.decisionTrace.delegateUsed === \"taskAgent\"\n// result.decisionTrace.phaseReached === \"delegate\"\n```\n\n### 最小 Orchestrator（零開銷）\n\n```typescript\n// 僅包裝現有 agent — 行為與 agent.chat() 完全一致\nconst orchestrator = new AgentOrchestrator({ delegate: myAgent });\nconst result = await orchestrator.chat(\"Hello\");\n```\n\n---\n\n## 核心功能\n\n### 對話（`agent.chat`）\n\n標準對話模式，完整的上下文管線 — 記憶、知識檢索、技能、工具呼叫、護欄。\n\n```typescript\nconst result = await agent.chat(\"天氣如何？\", \"session-1\", {\n  userId: \"user-123\",\n});\n// result.content, result.usage, result.blocked\n```\n\n### 決策模式（`agent.decide`）\n\n回傳型別化的 JSON 決策而非自然語言。使用完整的預取管線但跳過工具執行 — 適合路由、分類和評分。\n\n```typescript\nimport { LLMStructuredClassifier } from \"naru-agent-js\";\nimport { z } from \"zod\";\n\nconst classifier = new LLMStructuredClassifier({\n  model: anthropic(\"claude-haiku-4-5\"),\n  schema: z.object({\n    intent: z.enum([\"question\", \"complaint\", \"feedback\"]),\n    urgency: z.number().min(1).max(5),\n  }),\n  systemPrompt: \"分類使用者訊息。\",\n});\n\nconst result = await agent.decide(\"我的訂單還沒到！\", classifier);\nconsole.log(result.decision);\n// { intent: \"complaint\", urgency: 4 }\n```\n\n### 工具規劃器（ToolPlanner）\n\n決定要呼叫哪些工具（含參數）但不執行。適合預覽、稽核或非同步派發。\n\n```typescript\nimport { ToolPlanner } from \"naru-agent-js\";\n\nconst planner = new ToolPlanner({ model: anthropic(\"claude-haiku-4-5\") });\nconst plan = await planner.plan(\"訂一張去東京的機票\", myTools);\n// [{ tool: \"search_flights\", args: { destination: \"Tokyo\" } }]\n```\n\n### 工具（Tools）\n\n```typescript\nimport { tool } from \"naru-agent-js\";\nimport { z } from \"zod\";\n\nconst weatherTool = tool({\n  name: \"get_weather\",\n  description: \"查詢城市目前天氣\",\n  parameters: z.object({ city: z.string() }),\n  execute: async ({ city }) => `${city} 天氣：晴天 22°C`,\n});\n\nconst agent = new NaruAgent({ model, tools: [weatherTool] });\n```\n\n### 記憶（Memory）\n\n```typescript\nimport { MemoryManager, InMemoryMemoryStore } from \"naru-agent-js\";\n\nconst memory = new MemoryManager({\n  store: new InMemoryMemoryStore(),\n  model: myModel,\n});\n\nconst agent = new NaruAgent({ model, memoryManager: memory });\n```\n\n### 知識庫（RAG）\n\n```typescript\nimport { ChromaKnowledgeStore } from \"naru-agent-js\";\n\nconst knowledge = new ChromaKnowledgeStore({\n  collectionName: \"docs\",\n  embedFn: myEmbedFn,\n  contextualRetrieval: true, // Anthropic Contextual Retrieval\n});\n\nawait knowledge.ingest([{ content: \"...\", metadata: {} }]);\nconst agent = new NaruAgent({ model, knowledgeStore: knowledge });\n```\n\n### 技能（Skills）\n\n```typescript\nimport { skill } from \"naru-agent-js\";\n\nconst summarySkill = skill({\n  name: \"summarize\",\n  description: \"摘要內容\",\n  triggers: [\"摘要\", \"重點\", \"tldr\"],\n  priority: 10,\n  run: async (message, context) => ({\n    promptInjection: \"請簡潔地摘要內容。\",\n    skillName: \"summarize\",\n  }),\n});\n\nconst agent = new NaruAgent({ model, skills: [summarySkill] });\n```\n\n### 護欄（Guardrails）\n\n```typescript\nimport { KeywordGuardrail } from \"naru-agent-js\";\n\nconst agent = new NaruAgent({\n  model,\n  guardrails: [new KeywordGuardrail({ blockedPatterns: [\"spam\", \"abuse\"] })],\n});\n```\n\n### Session 管理\n\n```typescript\nimport { InMemorySessionStore, RedisSessionStore } from \"naru-agent-js\";\n\n// 開發環境\nconst agent = new NaruAgent({ model, sessionStore: new InMemorySessionStore() });\n\n// 生產環境（多 instance）\nconst agent = new NaruAgent({\n  model,\n  sessionStore: new RedisSessionStore({ url: process.env.REDIS_URL }),\n});\n```\n\n### 串流（Streaming）\n\n```typescript\nfor await (const event of agent.stream(\"你好！\", \"session-1\")) {\n  if (event.type === \"text_delta\") process.stdout.write(event.text);\n  if (event.type === \"done\") console.log(\"\\n完成：\", event.result.usage);\n}\n```\n\n### 上下文壓縮（Context Compression）\n\n```typescript\nimport { ContextCompressor, InMemorySummaryStore } from \"naru-agent-js\";\n\nconst agent = new NaruAgent({\n  model,\n  contextCompressor: new ContextCompressor({\n    store: new InMemorySummaryStore(),\n    model: myModel,\n    triggerTokens: 4000,\n  }),\n});\n```\n\n### 追蹤（Tracing）\n\n```typescript\nimport { TraceCollector, JSONLTraceExporter } from \"naru-agent-js\";\n\nconst tracer = new TraceCollector({\n  exporter: new JSONLTraceExporter({ path: \"./traces.jsonl\" }),\n});\n\nconst agent = new NaruAgent({ model, traceCollector: tracer });\n```\n\n---\n\n## Orchestration API\n\n### AgentOrchestrator\n\n透過 4 階段管線路由訊息的協作層。\n\n```typescript\nconst orchestrator = new AgentOrchestrator<MyIntentType>({\n  // 必要\n  delegate: defaultAgent,\n\n  // 多 agent 路由（可選）\n  delegates: new Map([[\"intent_name\", specializedAgent]]),\n\n  // 意圖解析（可選）\n  intentResolver: myResolver,\n\n  // 快速路徑執行（可選）\n  directExecutors: [myExecutor],\n\n  // 狀態管理（可選）\n  pendingStateManager: new InMemoryPendingStateManager(),\n  sessionStateStore: new InMemorySessionStateStore(),\n\n  // Channel 整合（可選）\n  channelAdapter: myChannelAdapter,\n\n  // 生命週期 hooks（可選）\n  lifecycleHooks: {\n    beforeMessage: async (msg, opts) => { /* 日誌、認證等 */ },\n    afterMessage: async (result) => { /* 指標、分析 */ },\n    onError: async (error) => { /* 告警 */ },\n  },\n});\n```\n\n### OrchestrationResult\n\n擴展 `NaruResult`，加上 orchestration 後設資料：\n\n| 欄位 | 型別 | 說明 |\n|------|------|------|\n| `content` | `string` | 回覆文字（繼承自 NaruResult） |\n| `blocked` | `boolean` | 是否被護欄攔截（繼承自 NaruResult） |\n| `usage` | `TokenUsage` | Token 用量（繼承自 NaruResult） |\n| `toolCalls` | `string[]` | 使用的工具（繼承自 NaruResult） |\n| `orchestrationIntent` | `OrchestratorIntent<T> \\| null` | 解析出的意圖 |\n| `decisionTrace` | `AgentDecisionTrace` | 完整決策追蹤含各階段耗時 |\n| `pendingConfirmation` | `PendingState \\| null` | 等待使用者確認 |\n| `sessionId` | `string \\| null` | Session 識別碼 |\n\n### 自訂意圖型別\n\n```typescript\nimport { GenericIntentObject } from \"naru-agent-js\";\n\n// 以領域特定意圖擴展\ntype MyIntent = GenericIntentObject | \"task_capture\" | \"calendar_query\" | \"reorganize\";\n\n// 所有 orchestration 類別完全型別化\nconst resolver = new DeterministicIntentResolver<MyIntent>([...]);\nconst orchestrator = new AgentOrchestrator<MyIntent>({ delegate, intentResolver: resolver });\n// result.intent?.object 型別為 MyIntent\n```\n\n### ChannelAdapter\n\n平台特定訊息處理的抽象介面：\n\n```typescript\ninterface ChannelAdapter<TIn, TOut> {\n  parseIncoming(input: TIn): ChannelMessage;\n  formatOutgoing(result: OrchestrationResult): TOut;\n  loadPendingState(sessionId: string): Promise<PendingState | null>;\n  savePendingState(sessionId: string, state: PendingState): Promise<void>;\n  clearPendingState(sessionId: string): Promise<void>;\n}\n\n// 使用方式\nconst result = await orchestrator.processChannel(rawLineWebhookEvent);\n```\n\n---\n\n## Vercel / Edge Runtime\n\n所有 I/O 透過 Vercel AI SDK — 可在 Next.js API routes、Edge functions 和 serverless 環境中運作。\n\n## 更新日誌\n\n### 0.2.0\n- **AgentOrchestrator** — 4 階段路由：pending → intent → direct execute → delegate\n- **DeterministicIntentResolver** — 零成本 keyword/regex 意圖匹配\n- **LLMFallbackIntentResolver** — 確定性 + LLM fallback 組合\n- **BaseDirectExecutor** — 高信心度操作跳過 LLM\n- **ChannelAdapter** — 抽象 channel 介面（LINE、Slack、API 等）\n- **PendingStateManager** — 多步驟確認流程\n- **AgentSessionState** — 實體追蹤用於指代消解\n- **多 agent 路由** — intent-to-delegate 映射給專職 agent\n- **TypeScript 泛型** — 完全型別化的自訂意圖型別\n\n### 0.1.2\n- **決策模式**（`agent.decide<T>`） — 具完整上下文管線的結構化 JSON 輸出\n- **LLMStructuredClassifier** — 以 Zod schema 驅動的分類器含上下文組裝\n- **ToolPlanner** — 不執行的工具規劃（dry-run）\n- `agent.chat` 的 `skip` 參數可跳過 intent/skills/toolCalling\n\n### 0.1.1\n- 初始公開發布\n- 具工具呼叫、記憶、RAG、技能、護欄、串流、追蹤的 ReAct agent\n\n## 授權\n\nMIT\n","readmeFilename":"README.md","_rev":"1-256f4eb4c5fe3b01bef0389a5b137281"}