{"_id":"@aid-on/synapser","_rev":"3-fa3b81108d1ec9538ed13ed86947e337","name":"@aid-on/synapser","dist-tags":{"latest":"0.1.3"},"versions":{"0.1.1":{"name":"@aid-on/synapser","version":"0.1.1","keywords":["llm","agent","tools","mastra","ai"],"author":{"name":"Aid-On"},"license":"MIT","_id":"@aid-on/synapser@0.1.1","maintainers":[{"name":"aid-on","email":"hiromi.motodera@aid-on.org"}],"dist":{"shasum":"249091a965c25a5dac12674e06a78468e100caab","tarball":"https://registry.npmjs.org/@aid-on/synapser/-/synapser-0.1.1.tgz","fileCount":55,"integrity":"sha512-nCCa0oqy06XLEXzcOdHhSfnO7SsYCyBoHIb5gWxF54SNrndWA5TYgjKTxdfA3JoFX/guqBX6SmCYaeaZ7Xc8pw==","signatures":[{"sig":"MEUCIQCDuIz2fCypTdCPXDw4heRflGTsMgIReeHLODHw57LXWwIgUZDL9dOlSJufaQ+nqiysbZeAur1rzcf+LJ9HHzUA4x4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":291386},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./reporters/sse":{"types":"./dist/reporters/sse.d.ts","import":"./dist/reporters/sse.js"},"./adapters/mastra":{"types":"./dist/adapters/mastra.d.ts","import":"./dist/adapters/mastra.js"},"./reporters/artifact":{"types":"./dist/reporters/artifact.d.ts","import":"./dist/reporters/artifact.js"}},"gitHead":"45f550388ad3243b44a0c55acee0004baad4e91e","scripts":{"dev":"tsc --watch","test":"vitest run","build":"tsc","typecheck":"tsc --noEmit","test:watch":"vitest","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"aid-on","email":"hiromi.motodera@aid-on.org"},"_npmVersion":"10.8.2","description":"Neural Signal Processing for LLM Agents - Stimulus → Synapse → Response → Signal","directories":{},"_nodeVersion":"20.19.6","_hasShrinkwrap":false,"devDependencies":{"vitest":"^2.0.0","typescript":"^5.0.0","@cloudflare/workers-types":"^4.20241230.0"},"peerDependencies":{"@mastra/core":"^0.10.0"},"peerDependenciesMeta":{"@mastra/core":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/synapser_0.1.1_1771341162897_0.9156823654941524","host":"s3://npm-registry-packages-npm-production"}},"0.1.2":{"name":"@aid-on/synapser","version":"0.1.2","keywords":["llm","agent","tools","mastra","ai"],"author":{"name":"Aid-On"},"license":"MIT","_id":"@aid-on/synapser@0.1.2","maintainers":[{"name":"aid-on","email":"hiromi.motodera@aid-on.org"}],"dist":{"shasum":"66e6b9c2bfefe4e91f95a080df76b1432c686986","tarball":"https://registry.npmjs.org/@aid-on/synapser/-/synapser-0.1.2.tgz","fileCount":55,"integrity":"sha512-yF/BL7rXD9nhA4Y8LET/pMCVpNK5MjUM6sdXcx6TItNL032sJI1U7UGYvkPpRdI6lcbsrK5DqrA8ZRCwjueIjQ==","signatures":[{"sig":"MEYCIQC1ddH7r285p9msUjrcLQmWPPL6JRhjvIL2juMLStHG8gIhAJzfUP9niCRrz0xxg+UMJyisoV8Z8SyZx9pToIOHxxEx","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":291386},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./reporters/sse":{"types":"./dist/reporters/sse.d.ts","import":"./dist/reporters/sse.js"},"./adapters/mastra":{"types":"./dist/adapters/mastra.d.ts","import":"./dist/adapters/mastra.js"},"./reporters/artifact":{"types":"./dist/reporters/artifact.d.ts","import":"./dist/reporters/artifact.js"}},"gitHead":"45f550388ad3243b44a0c55acee0004baad4e91e","scripts":{"dev":"tsc --watch","test":"vitest run","build":"tsc","typecheck":"tsc --noEmit","test:watch":"vitest","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"aid-on","email":"hiromi.motodera@aid-on.org"},"_npmVersion":"10.8.2","description":"Neural Signal Processing for LLM Agents - Stimulus → Synapse → Response → Signal","directories":{},"_nodeVersion":"20.19.6","_hasShrinkwrap":false,"devDependencies":{"vitest":"^2.0.0","typescript":"^5.0.0","@cloudflare/workers-types":"^4.20241230.0"},"peerDependencies":{"@mastra/core":"^0.10.0"},"peerDependenciesMeta":{"@mastra/core":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/synapser_0.1.2_1771343128129_0.9450805162634235","host":"s3://npm-registry-packages-npm-production"}},"0.1.3":{"name":"@aid-on/synapser","version":"0.1.3","description":"Neural Signal Processing for LLM Agents - Stimulus → Synapse → Response → Signal","type":"module","main":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"import":"./dist/index.js","types":"./dist/index.d.ts"},"./adapters/mastra":{"import":"./dist/adapters/mastra.js","types":"./dist/adapters/mastra.d.ts"},"./reporters/artifact":{"import":"./dist/reporters/artifact.js","types":"./dist/reporters/artifact.d.ts"},"./reporters/sse":{"import":"./dist/reporters/sse.js","types":"./dist/reporters/sse.d.ts"}},"scripts":{"build":"tsc","dev":"tsc --watch","typecheck":"tsc --noEmit","test":"vitest run","test:watch":"vitest","test:coverage":"vitest run --coverage"},"keywords":["llm","agent","tools","mastra","ai"],"author":{"name":"Aid-On"},"license":"MIT","devDependencies":{"@cloudflare/workers-types":"^4.20241230.0","typescript":"^5.0.0","vitest":"^2.0.0"},"peerDependencies":{"@mastra/core":"^0.10.0"},"peerDependenciesMeta":{"@mastra/core":{"optional":true}},"_id":"@aid-on/synapser@0.1.3","_nodeVersion":"20.19.6","_npmVersion":"10.8.2","dist":{"integrity":"sha512-S+C+EoRFmdtRV+UwHVXFzidp04cL5XW7lOwKuj6Hvuy1aJAlRItPax/f8h7xi+K9qw2R7tXLhEWtPggRmQBjrA==","shasum":"42868fb06a9894fdf06384ec037e4600ea2963bd","tarball":"https://registry.npmjs.org/@aid-on/synapser/-/synapser-0.1.3.tgz","fileCount":72,"unpackedSize":292947,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQD5M0vis3hdvIJav1PtJK5w9Z/aUQAXHSplnV+4iP9hGgIhAM6RqFDtVRJ2yEWi6owrtYKGZVPpQ2fM5WLcjbFcD9UI"}]},"_npmUser":{"name":"aid-on","email":"hiromi.motodera@aid-on.org"},"directories":{},"maintainers":[{"name":"aid-on","email":"hiromi.motodera@aid-on.org"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/synapser_0.1.3_1771435129984_0.3730765630411774"},"_hasShrinkwrap":false}},"time":{"created":"2026-02-17T15:12:42.824Z","modified":"2026-02-18T17:18:50.246Z","0.1.1":"2026-02-17T15:12:43.074Z","0.1.2":"2026-02-17T15:45:28.279Z","0.1.3":"2026-02-18T17:18:50.144Z"},"author":{"name":"Aid-On"},"license":"MIT","keywords":["llm","agent","tools","mastra","ai"],"description":"Neural Signal Processing for LLM Agents - Stimulus → Synapse → Response → Signal","maintainers":[{"name":"aid-on","email":"hiromi.motodera@aid-on.org"}],"readme":"# @aid-on/synapser\n\n<div align=\"center\">\n\n[![npm version](https://img.shields.io/npm/v/@aid-on/synapser.svg?style=flat-square&color=00DC82)](https://www.npmjs.com/package/@aid-on/synapser)\n[![TypeScript](https://img.shields.io/badge/TypeScript-5.7-3178C6?style=flat-square&logo=typescript&logoColor=white)](https://www.typescriptlang.org/)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg?style=flat-square)](https://opensource.org/licenses/MIT)\n\n<br />\n\n<h3>\n<b>synapser</b> - Neural Signal Processing for LLM Agents\n</h3>\n\n<p align=\"center\">\n<b>Not just another agent framework.</b><br/>\nA type-safe 4-phase pipeline that gives structure to the chaos of LLM agent processing.\n</p>\n\n<br/>\n\n[**日本語**](./README.ja.md) | **English**\n\n<br/>\n\n</div>\n\n## Why synapser\n\nLLM agent code tends to become tangled spaghetti: user input parsing, LLM calls, tool execution, and response formatting all mixed together. synapser separates these concerns into four distinct phases inspired by neural signal processing:\n\n```\nStimulus → Synapse → Response → Signal\n(Input)    (LLM Decision)  (Tool Execution)  (UI Output)\n```\n\nZero runtime dependencies. Mastra adapter available as an optional peer dependency.\n\n## Installation\n\n```bash\nnpm install @aid-on/synapser\n```\n\n## Quick Start\n\n```typescript\nimport { createFlow, runFlow, chatStimulus, createActionRegistry } from \"@aid-on/synapser\";\n\n// 1. Register tools\nconst actions = createActionRegistry()\n  .register(\"get_weather\", async ({ location }: { location: string }) => {\n    const res = await fetch(`https://wttr.in/${location}?format=j1`);\n    return res.json();\n  });\n\n// 2. Build a flow\nconst flow = createFlow<string, unknown, unknown>()\n  .stimulus((msg) => chatStimulus(msg))\n  .synapse(async (stimulus) => {\n    // LLM decides what to do (plug in any LLM call here)\n    return { action: \"get_weather\", params: { location: \"Tokyo\" } };\n  })\n  .response((decision) => actions.execute(decision.action, decision.params))\n  .signal((response) => ({\n    message: response.success ? JSON.stringify(response.data) : \"Error\",\n  }))\n  .build();\n\n// 3. Run\nconst result = await runFlow(flow, \"What's the weather in Tokyo?\");\nconsole.log(result.signal?.message);\n```\n\n## SSE Streaming\n\nStream results from server to client in real time.\n\n```typescript\nimport { createSSEStream, streamSignal, SSE_HEADERS } from \"@aid-on/synapser\";\n\napp.post(\"/api/chat\", async (c) => {\n  const { message } = await c.req.json();\n  const { stream, writer } = createSSEStream();\n\n  (async () => {\n    writer.sendStatus(\"thinking\");\n    const result = await runFlow(chatFlow, message);\n\n    if (result.success && result.signal) {\n      await streamSignal(writer, result.signal);\n    } else {\n      writer.sendError(result.error?.message || \"Unknown error\");\n    }\n    writer.done();\n  })();\n\n  return new Response(stream, { headers: SSE_HEADERS });\n});\n```\n\n### SSEWriter Methods\n\n```typescript\nwriter.sendStatus(\"generating\");       // Status update\nwriter.sendText(\"Hello\");              // Text chunk (OpenAI-compatible)\nwriter.sendArtifact(artifact);         // Send artifact\nwriter.sendToolCall(id, name, args);   // Tool call info\nwriter.sendToolResult(id, name, result); // Tool execution result\nwriter.sendError(\"Something failed\");  // Error\nwriter.done();                         // Completion signal\n```\n\n## Artifact Reporter\n\nConvert tool results into UI-ready artifacts.\n\n```typescript\nimport { createArtifactReporter } from \"@aid-on/synapser/reporters/artifact\";\n\nconst reporter = createArtifactReporter({\n  converters: {\n    get_weather: (data) => ({\n      type: \"weather\",\n      location: data.location,\n      temperature: data.temp_C,\n      description: data.weatherDesc,\n    }),\n    generate_code: (data) => ({\n      type: \"code\",\n      language: data.language,\n      code: data.code,\n    }),\n  },\n});\n\n// Response -> Signal conversion\nconst signal = reporter.report(response);\n// signal.artifact.type === \"weather\" | \"code\"\n```\n\nBuilt-in artifact types: `WeatherArtifact`, `CodeArtifact`, `CommandArtifact`\n\n## Mastra Adapter\n\nUse a Mastra Agent as your Synapse handler.\n\n```typescript\nimport { createMastraSynapse, streamMastraAgent } from \"@aid-on/synapser/adapters/mastra\";\n\n// Non-streaming\nconst synapse = createMastraSynapse(\n  { apiKey: process.env.LLM_API_KEY, model: \"gpt-4o\", locale: \"ja\" },\n  agentFactory\n);\n\nconst flow = createFlow()\n  .stimulus((msg) => chatStimulus(msg))\n  .synapse(synapse)\n  .response((decision) => actions.execute(decision.action, decision.params))\n  .signal((response) => reporter.report(response))\n  .build();\n```\n\n```typescript\n// Streaming (direct SSE output)\nimport { streamMastraAgent } from \"@aid-on/synapser/adapters/mastra\";\n\nconst { stream, writer } = createSSEStream();\nconst result = await streamMastraAgent(agent, messages, writer, {\n  onToolCall: (call) => console.log(\"Tool:\", call.toolName),\n  onText: (text) => console.log(\"Text:\", text),\n});\n```\n\n### actionsToMastraTools\n\nConvert ActionRegistry definitions to Mastra tool format.\n\n```typescript\nimport { actionsToMastraTools } from \"@aid-on/synapser/adapters/mastra\";\n\nconst mastraTools = actionsToMastraTools(actions.list());\n```\n\n## Action Registry\n\nType-safe registration and execution of tools (actions).\n\n```typescript\nconst actions = createActionRegistry()\n  .register(\"search\", async ({ query }: { query: string }) => {\n    return await searchAPI.search(query);\n  })\n  .register(\"translate\", async ({ text, to }: { text: string; to: string }) => {\n    return await translateAPI.translate(text, to);\n  });\n\n// Execute\nconst result = await actions.execute(\"search\", { query: \"TypeScript\" });\n// result: { success: boolean, data, action: \"search\", duration_ms: number }\n\n// List registered actions\nactions.list(); // [\"search\", \"translate\"]\nactions.has(\"search\"); // true\n```\n\n## Flow Builder\n\nAssemble the 4 phases with full type safety.\n\n```typescript\nconst flow = createFlow<TInput, TData, TArtifact>()\n  .stimulus(handler)   // (input: TInput) => Stimulus\n  .synapse(handler)    // (stimulus: Stimulus) => SynapseDecision\n  .response(handler)   // (decision: SynapseDecision) => Response<TData>\n  .signal(handler)     // (response: Response<TData>) => Signal<TArtifact>\n  .build();\n```\n\n### runFlow Options\n\n```typescript\nconst result = await runFlow(flow, input, {\n  timeout: 30000,\n  debug: true,\n  onPhaseComplete: (phase, result) => console.log(phase, result),\n  onError: (error, phase) => console.error(phase, error),\n});\n\n// result.success\n// result.signal?.artifact\n// result.phases.stimulus.duration_ms\n// result.phases.synapse.duration_ms\n// result.total_duration_ms\n```\n\n## Types\n\n```typescript\n// Stimulus\ninterface Stimulus<TInput = unknown> {\n  type: \"chat\" | \"webhook\" | \"cron\" | \"event\" | \"sensor\" | string;\n  input: TInput;\n  context?: StimulusContext;\n  timestamp: number;\n  id: string;\n}\n\n// Synapse Decision\ninterface SynapseDecision {\n  action: string;\n  params: Record<string, unknown>;\n  confidence?: number;    // 0-1\n  reasoning?: string;\n  noAction?: boolean;     // If true, skip Response phase\n}\n\n// Response\ninterface Response<TData = unknown> {\n  success: boolean;\n  data?: TData;\n  error?: { code: string; message: string; details?: unknown };\n  duration_ms: number;\n  action: string;\n}\n\n// Signal\ninterface Signal<TArtifact = unknown> {\n  artifact?: TArtifact;\n  message?: string;\n  events?: SignalEvent[];\n  stream?: AsyncIterable<SignalChunk>;\n}\n```\n\n## Exports\n\n```typescript\n// Main\nimport {\n  createFlow, runFlow, FlowRunner, SynapseFlowBuilder,\n  createStimulus, chatStimulus, eventStimulus, webhookStimulus,\n  createActionRegistry, ActionRegistry,\n  SSEWriter, createSSEStream, createSSEResponse, streamSignal, SSE_HEADERS,\n  streamMastraAgent, createMastraSynapse, createMastraSynapseStream, actionsToMastraTools,\n} from \"@aid-on/synapser\";\n\n// Sub-exports\nimport { createArtifactReporter } from \"@aid-on/synapser/reporters/artifact\";\nimport { createSSEStream } from \"@aid-on/synapser/reporters/sse\";\nimport { createMastraSynapse } from \"@aid-on/synapser/adapters/mastra\";\n```\n\n## Tests\n\n```\n86 tests, 6 test files -- all passing\n\n  synapse.test.ts                 22 tests  (flow builder, runner, action registry)\n  sse.test.ts                     19 tests  (SSE writer, streaming)\n  sse-stream-signal.test.ts       13 tests  (streamSignal integration)\n  artifact-reporter.test.ts       12 tests  (artifact conversion)\n  artifact.test.ts                10 tests  (built-in converters)\n  action-registry.test.ts         10 tests  (register, execute, list)\n```\n\n## License\n\nMIT © Aid-On\n\n---\n\n<div align=\"center\">\n\n**Structure for your agents. Freedom for your code.**\n\n<br/>\n\n[NPM](https://www.npmjs.com/package/@aid-on/synapser) •\n[GitHub](https://github.com/Aid-On/aid-on-platform)\n\n</div>\n","readmeFilename":"README.md"}