{"_id":"@codefundi/dispersl-sdk","_rev":"6-9c192b21b9f75004013812461593f7b0","name":"@codefundi/dispersl-sdk","dist-tags":{"latest":"0.1.14"},"versions":{"0.1.8":{"name":"@codefundi/dispersl-sdk","version":"0.1.8","keywords":["dispersl","sdk","typescript"],"author":{"name":"Code Fundi"},"license":"MIT","_id":"@codefundi/dispersl-sdk@0.1.8","maintainers":[{"name":"whyweru","email":"wawerufelixprojects@gmail.com"}],"homepage":"https://github.com/Code-Fundi/dispersl-sdk","bugs":{"url":"https://github.com/Code-Fundi/dispersl-sdk/issues"},"dist":{"shasum":"2204fc15aff82227acf84407ea75cfbf6a476669","tarball":"https://registry.npmjs.org/@codefundi/dispersl-sdk/-/dispersl-sdk-0.1.8.tgz","fileCount":6,"integrity":"sha512-wqIgjQNRAcPZbTPDEKl1A5dTaeCjZo9I9qma+BHm0R5er00xGWfLvmZwLXpkg0kqnYqNzX99XMvYi4wLzE/4uA==","signatures":[{"sig":"MEQCIEPCuop0tG3DoRJWZHLPEDpiSiI/SfwNCQwQSxv8tshbAiAILEyrp98oT7Y12GmEJqZV3I6ZWrhRb8iaJ9bvGU14Fg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@codefundi%2fdispersl-sdk@0.1.8","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":59864},"main":"dist/index.cjs","type":"module","types":"dist/index.d.ts","module":"dist/index.js","engines":{"node":">=18"},"gitHead":"7c172e5408d9101c96332c41fc9c63fb672d913e","scripts":{"lint":"eslint src tests examples --ext .ts","test":"vitest","build":"tsup src/index.ts --format esm,cjs --dts --clean","typecheck":"tsc --noEmit"},"_npmUser":{"name":"whyweru","email":"wawerufelixprojects@gmail.com"},"repository":{"url":"git+https://github.com/Code-Fundi/dispersl-sdk.git","type":"git","directory":"typescript-sdk"},"_npmVersion":"10.8.2","description":"Production TypeScript SDK for Dispersl API","directories":{},"_nodeVersion":"20.20.0","dependencies":{"zod":"^3.23.8"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","eslint":"^9.14.0","vitest":"^2.1.4","typescript":"^5.6.3","@types/node":"^22.10.0","@typescript-eslint/parser":"^8.14.0","@typescript-eslint/eslint-plugin":"^8.14.0"},"_npmOperationalInternal":{"tmp":"tmp/dispersl-sdk_0.1.8_1773432102459_0.4958527578930527","host":"s3://npm-registry-packages-npm-production"}},"0.1.9":{"name":"@codefundi/dispersl-sdk","version":"0.1.9","keywords":["dispersl","sdk","typescript"],"author":{"name":"Code Fundi"},"license":"MIT","_id":"@codefundi/dispersl-sdk@0.1.9","maintainers":[{"name":"whyweru","email":"wawerufelixprojects@gmail.com"}],"homepage":"https://github.com/Code-Fundi/dispersl-sdk","bugs":{"url":"https://github.com/Code-Fundi/dispersl-sdk/issues"},"dist":{"shasum":"99ada2959d785fa000945f490526fbfb53106de6","tarball":"https://registry.npmjs.org/@codefundi/dispersl-sdk/-/dispersl-sdk-0.1.9.tgz","fileCount":6,"integrity":"sha512-jNFIdIYaymoCNjAF42ES6K58ChrtlDCh6Inc1wkNLAjwq1mIu2dyk3N90Wbe+d+vgltbTsjAuzDV/E1mFKG6og==","signatures":[{"sig":"MEUCIHno8Ph8bipSEaqF071HTXJ9/Vz++KB55hC3HebMjtQMAiEAsaw0DxneuGiQVUWbOhK4liIH+di9gLaEfSCe6NgVeeE=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@codefundi%2fdispersl-sdk@0.1.9","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":62132},"main":"dist/index.cjs","type":"module","types":"dist/index.d.ts","module":"dist/index.js","engines":{"node":">=18"},"gitHead":"b20a597e3a06c582672d88d41664fe452a46f5dd","scripts":{"lint":"eslint src tests examples --ext .ts","test":"vitest","build":"tsup src/index.ts --format esm,cjs --dts --clean","typecheck":"tsc --noEmit"},"_npmUser":{"name":"whyweru","email":"wawerufelixprojects@gmail.com"},"repository":{"url":"git+https://github.com/Code-Fundi/dispersl-sdk.git","type":"git","directory":"typescript-sdk"},"_npmVersion":"10.8.2","description":"Production TypeScript SDK for Dispersl API","directories":{},"_nodeVersion":"20.20.1","dependencies":{"zod":"^3.23.8"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","eslint":"^9.14.0","vitest":"^2.1.4","typescript":"^5.6.3","@types/node":"^22.10.0","@typescript-eslint/parser":"^8.14.0","@typescript-eslint/eslint-plugin":"^8.14.0"},"_npmOperationalInternal":{"tmp":"tmp/dispersl-sdk_0.1.9_1773441995822_0.8305339653231405","host":"s3://npm-registry-packages-npm-production"}},"0.1.10":{"name":"@codefundi/dispersl-sdk","version":"0.1.10","keywords":["dispersl","sdk","typescript"],"author":{"name":"Code Fundi"},"license":"MIT","_id":"@codefundi/dispersl-sdk@0.1.10","maintainers":[{"name":"whyweru","email":"wawerufelixprojects@gmail.com"}],"homepage":"https://github.com/Code-Fundi/dispersl-sdk","bugs":{"url":"https://github.com/Code-Fundi/dispersl-sdk/issues"},"dist":{"shasum":"8dc3a58bd823929d67fc2b5ba8d0d77b320bca5e","tarball":"https://registry.npmjs.org/@codefundi/dispersl-sdk/-/dispersl-sdk-0.1.10.tgz","fileCount":6,"integrity":"sha512-lrT9eFXcrg++wZiRx/Z40ZLiHXIMc4U0RkFO3b9ySOPhHzIMQnyFvDfu5Z1f6DIN/apAgi5ybBi0wNJAUv2P/g==","signatures":[{"sig":"MEQCIEbI4dHNH5vXojlUcrpQqG4N2AN647C4ZJ1JpWnaakW5AiBut+gvY0uWrAYu/i+bGvmdTYbGvMzheM/eVq2VixVEpw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":79765},"main":"dist/index.cjs","type":"module","types":"dist/index.d.ts","module":"dist/index.js","engines":{"node":">=18"},"gitHead":"f2e8c79b349449ec84d658535cc42a60df3d3831","scripts":{"lint":"eslint src tests examples --ext .ts","test":"vitest","build":"tsup src/index.ts --format esm,cjs --dts --clean","typecheck":"tsc --noEmit"},"_npmUser":{"name":"whyweru","email":"wawerufelixprojects@gmail.com"},"repository":{"url":"git+https://github.com/Code-Fundi/dispersl-sdk.git","type":"git","directory":"typescript-sdk"},"_npmVersion":"10.8.2","description":"Production TypeScript SDK for Dispersl API","directories":{},"_nodeVersion":"20.20.2","dependencies":{"zod":"^3.23.8"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","eslint":"^9.14.0","vitest":"^2.1.4","typescript":"^5.6.3","@types/node":"^22.10.0","@typescript-eslint/parser":"^8.14.0","@typescript-eslint/eslint-plugin":"^8.14.0"},"_npmOperationalInternal":{"tmp":"tmp/dispersl-sdk_0.1.10_1780672093425_0.5551550987238594","host":"s3://npm-registry-packages-npm-production"}},"0.1.11":{"name":"@codefundi/dispersl-sdk","version":"0.1.11","keywords":["dispersl","sdk","typescript"],"author":{"name":"Code Fundi"},"license":"MIT","_id":"@codefundi/dispersl-sdk@0.1.11","maintainers":[{"name":"whyweru","email":"wawerufelixprojects@gmail.com"}],"homepage":"https://github.com/Code-Fundi/dispersl-sdk","bugs":{"url":"https://github.com/Code-Fundi/dispersl-sdk/issues"},"dist":{"shasum":"5dd7082a1a367b2b7f10d9966d4942c093c518ca","tarball":"https://registry.npmjs.org/@codefundi/dispersl-sdk/-/dispersl-sdk-0.1.11.tgz","fileCount":6,"integrity":"sha512-aIbXCuOYX8rJdJpehLxUM+fntAY8UleXyNWPhOwIP6E5Cyoa8+unEx8x8dK0PWDqnTOuBSUmnVBnmCYupKYJQg==","signatures":[{"sig":"MEYCIQCHB9wzQMnXs0kqyEx29ZfpdEqN/baRO/7P0OQlz2LlNAIhAIbBGqyyX4WUwRXi2VvDJJobSUOr0DduH8kYvsRXPb1k","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":203404},"main":"dist/index.cjs","type":"module","types":"dist/index.d.ts","module":"dist/index.js","engines":{"node":">=18"},"gitHead":"94212d6559e5c64bd669e7f0c3bff16d91c27da7","scripts":{"lint":"eslint src tests examples --ext .ts","test":"vitest","build":"tsup src/index.ts --format esm,cjs --dts --clean","typecheck":"tsc --noEmit"},"_npmUser":{"name":"whyweru","email":"wawerufelixprojects@gmail.com"},"repository":{"url":"git+https://github.com/Code-Fundi/dispersl-sdk.git","type":"git","directory":"typescript-sdk"},"_npmVersion":"10.8.2","description":"Production TypeScript SDK for Dispersl API","directories":{},"_nodeVersion":"20.20.2","dependencies":{"zod":"^3.23.8"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","eslint":"^9.14.0","vitest":"^2.1.4","typescript":"^5.6.3","@types/node":"^22.10.0","@typescript-eslint/parser":"^8.14.0","@typescript-eslint/eslint-plugin":"^8.14.0"},"_npmOperationalInternal":{"tmp":"tmp/dispersl-sdk_0.1.11_1784743608421_0.40784178835573703","host":"s3://npm-registry-packages-npm-production"}},"0.1.12":{"name":"@codefundi/dispersl-sdk","version":"0.1.12","keywords":["dispersl","sdk","typescript"],"author":{"name":"Code Fundi"},"license":"MIT","_id":"@codefundi/dispersl-sdk@0.1.12","maintainers":[{"name":"whyweru","email":"wawerufelixprojects@gmail.com"}],"homepage":"https://github.com/Code-Fundi/dispersl-sdk","bugs":{"url":"https://github.com/Code-Fundi/dispersl-sdk/issues"},"dist":{"shasum":"9b85e038ae3e95297cd4bd9e381331105143b909","tarball":"https://registry.npmjs.org/@codefundi/dispersl-sdk/-/dispersl-sdk-0.1.12.tgz","fileCount":6,"integrity":"sha512-/2VjAhhy7NSSEbYdyrHYTnk80pqi99ZLWdRi+CtADU2Hxq14J/D6Izz3ZC2l59ZLsGkGJWa/INfMxpimtCeb6A==","signatures":[{"sig":"MEQCIB/MqspZ5uaMtrXc7OzFoNzpe5H71KBFw4vJmGfVUkdsAiA6sLVXndVto8YugQw6hf0cYv+PTd7rDbWaezb12FnWCg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":210808},"main":"dist/index.cjs","type":"module","types":"dist/index.d.ts","module":"dist/index.js","engines":{"node":">=18"},"gitHead":"3ab30cd65449cb86d57627dbfa5f4452d1b28c61","scripts":{"lint":"eslint src tests examples --ext .ts","test":"vitest","build":"tsup src/index.ts --format esm,cjs --dts --clean","typecheck":"tsc --noEmit"},"_npmUser":{"name":"whyweru","email":"wawerufelixprojects@gmail.com"},"repository":{"url":"git+https://github.com/Code-Fundi/dispersl-sdk.git","type":"git","directory":"typescript-sdk"},"_npmVersion":"10.8.2","description":"Production TypeScript SDK for Dispersl API","directories":{},"_nodeVersion":"20.20.2","dependencies":{"zod":"^3.23.8"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","eslint":"^9.14.0","vitest":"^2.1.4","typescript":"^5.6.3","@types/node":"^22.10.0","@typescript-eslint/parser":"^8.14.0","@typescript-eslint/eslint-plugin":"^8.14.0"},"_npmOperationalInternal":{"tmp":"tmp/dispersl-sdk_0.1.12_1784816962490_0.3711416479257934","host":"s3://npm-registry-packages-npm-production"}},"0.1.14":{"name":"@codefundi/dispersl-sdk","version":"0.1.14","description":"Production TypeScript SDK for Dispersl API","type":"module","main":"dist/index.cjs","module":"dist/index.js","types":"dist/index.d.ts","repository":{"type":"git","url":"git+https://github.com/Code-Fundi/dispersl-sdk.git","directory":"typescript-sdk"},"homepage":"https://github.com/Code-Fundi/dispersl-sdk","keywords":["dispersl","sdk","typescript"],"author":{"name":"Code Fundi"},"license":"MIT","scripts":{"build":"tsup src/index.ts --format esm,cjs --dts --clean","lint":"eslint src tests examples --ext .ts","typecheck":"tsc --noEmit","test":"vitest"},"dependencies":{"zod":"^3.23.8"},"devDependencies":{"@types/node":"^22.10.0","@typescript-eslint/eslint-plugin":"^8.14.0","@typescript-eslint/parser":"^8.14.0","eslint":"^9.14.0","tsup":"^8.3.5","typescript":"^5.6.3","vitest":"^2.1.4"},"engines":{"node":">=18"},"_id":"@codefundi/dispersl-sdk@0.1.14","gitHead":"1d12e3276fd816173181f35c0bcadfb620ef0b66","bugs":{"url":"https://github.com/Code-Fundi/dispersl-sdk/issues"},"_nodeVersion":"20.20.2","_npmVersion":"10.8.2","dist":{"integrity":"sha512-TlVlgwiRXCrX5kv53zvExo+KBndwd4Ef7e9PEYYzK4uSrHOTxPKuf+4hPMvPgyXymEuQuAsunGdbTrf6I0V3rQ==","shasum":"3d331cc3b4ad56a94f36da417f14ee75a301a955","tarball":"https://registry.npmjs.org/@codefundi/dispersl-sdk/-/dispersl-sdk-0.1.14.tgz","fileCount":6,"unpackedSize":213272,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQCWn4zAua7MB5Gdj6hYZQMsGsM6RjBhImmnou8pIdJU3wIhAP59+qB9//5UeO3SZLiQQDsGlIkX1aojRNwaVrnTb3Q1"}]},"_npmUser":{"name":"whyweru","email":"wawerufelixprojects@gmail.com"},"directories":{},"maintainers":[{"name":"whyweru","email":"wawerufelixprojects@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/dispersl-sdk_0.1.14_1785847895811_0.7613915941039879"},"_hasShrinkwrap":false}},"time":{"created":"2026-03-13T20:01:42.218Z","modified":"2026-08-04T12:51:36.237Z","0.1.8":"2026-03-13T20:01:42.664Z","0.1.9":"2026-03-13T22:46:35.993Z","0.1.10":"2026-06-05T15:08:13.589Z","0.1.11":"2026-07-22T18:06:48.559Z","0.1.12":"2026-07-23T14:29:22.626Z","0.1.14":"2026-08-04T12:51:35.947Z"},"bugs":{"url":"https://github.com/Code-Fundi/dispersl-sdk/issues"},"author":{"name":"Code Fundi"},"license":"MIT","homepage":"https://github.com/Code-Fundi/dispersl-sdk","keywords":["dispersl","sdk","typescript"],"repository":{"type":"git","url":"git+https://github.com/Code-Fundi/dispersl-sdk.git","directory":"typescript-sdk"},"description":"Production TypeScript SDK for Dispersl API","maintainers":[{"name":"whyweru","email":"wawerufelixprojects@gmail.com"}],"readme":"<p align=\"center\">\n <img width=\"300px\" src=\"https://github.com/Code-Fundi/.github/blob/main/media/dispersl/banner-light.png?raw=true\" align=\"center\" alt=\"Dispersl Multi-Agent SDK\" />\n</p>\n</p>\n\n<p align=\"center\">\n  <a href=\"https://discord.gg/6RJTWCuWZj\">\n    <img src=\"https://img.shields.io/badge/Discord-7289DA?logo=discord&logoColor=white\" />\n  </a>\n  <a href=\"https://x.com/disperslHQ\">\n    <img src=\"https://img.shields.io/badge/X/Twitter-808080?logo=x&logoColor=white\" />\n  </a>\n  <a href=\"https://www.tiktok.com/@codefundi\">\n    <img src=\"https://img.shields.io/badge/TikTok-000000?logo=tiktok&logoColor=white\" />\n  </a>\n  <a href=\"https://dispersl.com\">\n    <img src=\"https://img.shields.io/badge/Website-dispersl.com-blue\" />\n  </a>\n<br />\n</p>\n\n#\n\n<h2 align=\"center\">Dispersl TypeScript SDK</h2>\n<p align=\"center\">Flexible workflow automation with plug-and-play agents for TypeScript.</p>\n\n## Install\n\n```bash\npnpm add @codefundi/dispersl-sdk\n```\n\n## Requirements\n\n- Node.js `>=18`\n- TypeScript `>=5` (recommended for best type support)\n\n## Quick Start\n\n```ts\nimport { AgenticExecutor, DisperslClient } from \"@codefundi/dispersl-sdk\";\n\nconst client = new DisperslClient({\n  baseUrl: process.env.DISPERSL_API_URL ?? \"https://api.dispersl.com/v1\",\n  apiKey: process.env.DISPERSL_API_KEY ?? \"\",\n  timeoutMs: 120_000,\n  retryAttempts: 3\n});\n\nconst executor = new AgenticExecutor(client);\nconst result = await executor.runPlanAndAgentLoop({\n  prompt: \"Plan and implement a production webhook pipeline\",\n  agentChoices: \"auto\", // or [\"architect\", \"security-auditor\", \"release-manager\"]\n  executionSequence: \"sequential\" // or \"parallel\" for concurrent agent execution\n});\n\nconsole.log(result.taskId, result.events.length, result.toolResults.length);\n```\n\n## SDK Capabilities\n\n- Typed HTTP client with bearer auth, timeout, retry, and status-to-error mapping.\n- Full endpoint coverage for `agent/completion`, `agent/plan`, and agent lifecycle APIs.\n- Incremental NDJSON stream parser with split-buffer handling and parse errors.\n- NDJSON chunk normalization (inline `tool_calls` in content, top-level `tool_calls` → `tools`) at parse boundary.\n- Handover parser supporting nested and double-serialized tool arguments.\n- Sequential and parallel agent execution modes for flexible workflow orchestration.\n- Task continuation support via `taskId` for multi-phase workflows.\n- MCP config loading from `.dispersl/mcp.json` with env interpolation and runtime overrides.\n- Agentic execution loop with plan-to-agent transitions, tool execution, and end-session detection.\n- **Grouped multi-tool responses**: one API stream turn → N local executions → one continuation prompt.\n\n## Client API Surface\n\n### Agent execution endpoints\n\n| Method | Request | Endpoint | Returns |\n| --- | --- | --- | --- |\n| `executeAgentCompletion` | `AgentCompletionRequest` | `POST /agent/completion` | `ReadableStream<Uint8Array>` |\n| `executePlan` | `AgentPlanRequest` | `POST /agent/plan` | `ReadableStream<Uint8Array>` |\n\n### Agent plan choices\n\n`AgentPlanRequest.agent_choice` supports:\n\n- `\"auto\"` (use automatic agent selection)\n- `string[]` of explicit custom agent `name_id` values\n\nWhen `\"auto\"` is used, the SDK normalizes the wire payload to `[\"auto\"]` for API compatibility.\n\n### Execution modes\n\n`AgentPlanRequest.execution_sequence` controls agent parallelism:\n\n- `\"sequential\"` (default): agents execute one after another\n- `\"parallel\"`: multiple agents execute concurrently when handed over from plan\n\nFor parallel execution, use `parallelConcurrency` in `runPlanAndAgentLoop` to limit simultaneous agent runs.\n\n### Resource endpoints\n\n| Domain | Method | Endpoint |\n| --- | --- | --- |\n| Agents | `getAgents` | `GET /agents?limit&nextToken` |\n| Agents | `createAgent` | `POST /agents/create` |\n| Agents | `editAgent` | `POST /agents/edit/{id}` |\n| Agents | `getAgent` | `GET /agents/{id}` |\n| Agents | `deleteAgent` | `DELETE /agents/{id}` |\n\n### Agent lifecycle fields and stats\n\n`getAgents` returns a paginated envelope with:\n\n- pagination: `limit`, `hasNext`, `hasPrev`, `nextToken`, `prevToken`\n- per-agent lifecycle + stats fields: `id`, `name_id`, `name`, `description`, `prompt`, `model`, `category`, `stars_count`, `clone_count`, `created_at`\n\n`getAgent` returns per-agent detail fields including lifecycle state:\n\n- `public`, `active`, `updated_at`\n\nCreate/edit request support:\n\n- create: `name`, `prompt`, optional `description`, `model`, `category`, `public`\n- edit: optional `name`, `prompt`, `description`, `model`, `category`, `public`, `active`\n\n## Execution Loop Behavior\n\n`AgenticExecutor.runPlanAndAgentLoop` provides:\n\n- start state: `plan`\n- max loop guard (`maxLoops`, default `50`)\n- execution sequence control (`executionSequence`: `\"sequential\"` or `\"parallel\"`, detected from plan metadata)\n- parallel concurrency limit (`parallelConcurrency` for controlling simultaneous agent runs)\n- handover handling (`handover_task`)\n- explicit completion handling (`end_session` and `finish_task`)\n- task continuation support via `taskId` for multi-phase workflows\n- continuation prompts when tools run without explicit handover/end\n- optional tool execution callback via `ToolExecutorFn`\n\n### Direct Single-Agent Completion Loop\n\nUse `runAgentCompletionLoop` to execute `POST /agent/completion` directly for one `name_id` until `end_session`.\n\n```ts\nconst executor = new AgenticExecutor(client);\nconst result = await executor.runAgentCompletionLoop({\n  nameId: \"architect\",\n  prompt: \"Review this backend design and produce a migration plan\",\n  maxLoops: 50\n});\n```\n\nBehavior:\n\n- fixed agent identity across turns (`nameId`)\n- no handover transition to other agents\n- continues until `end_session`, no tool calls, or `maxLoops` reached\n\n### Task Continuation\n\nPass `taskId` to resume work on an existing task and retain context across invocations:\n\n```ts\n// First run: initial execution\nconst firstRun = await executor.runPlanAndAgentLoop({\n  prompt: \"Design the system architecture\",\n  agentChoices: \"auto\"\n});\n\n// Continue after initial completion\nconst result = await executor.runPlanAndAgentLoop({\n  prompt: \"Now implement the core modules\",\n  agentChoices: \"auto\",\n  taskId: firstRun.taskId\n});\n```\n\n## Core Types\n\n| Type | Purpose |\n| --- | --- |\n| `DisperslConfig` | client init config (`baseUrl`, `apiKey`, timeout, retries) |\n| `AgentCompletionRequest` | completion request (`name_id` + base fields) |\n| `AgentRequestBase` | common fields for agent endpoints |\n| `AgentPlanRequest` | plan request (`agent_choice` + base fields) |\n| `AgentCreateRequest` | create payload (`name`, `prompt`, optional metadata) |\n| `AgentEditRequest` | editable lifecycle fields (`name`, `prompt`, `model`, `active`, ...) |\n| `NDJSONChunk` | stream chunk payload format |\n| `ToolCall` | tool invocation structure from stream chunks |\n| `ToolResult` | local tool execution result (`toolCallId?`, `toolName`, `status`, `output`, `error?`) |\n| `ToolExecutorFn` | host callback that runs a `ToolCall` locally |\n| `StreamTurnResult` | grouped outcome of one API stream (`pendingTools`, `turnToolResults`, `nextAction`, ...) |\n| `parseAgentStream` | collect all tools from one stream, execute as a batch, return grouped results |\n| `buildGroupedToolFeedbackPrompt` | format N tool results into one continuation prompt |\n| `PaginatedResponse<T>` | list endpoints with pagination envelope |\n\n## Error Model\n\n| Error | Trigger |\n| --- | --- |\n| `AuthenticationError` | `401` or `403` |\n| `NotFoundError` | `404` |\n| `ConflictError` | `409` |\n| `RateLimitError` | `429` |\n| `ValidationError` | other `4xx` |\n| `ServerError` | `5xx` |\n| `TimeoutError` | request timeout/abort |\n| `StreamParseError` | NDJSON line/tail parse failure |\n| `ToolExecutionError` | tool callback returns error status |\n| `HandoverError` | handover contract failure (reserved class) |\n\n## Tool Setup Guide\n\nDispersl agents call tools in **turns**. When the model requests N tools in one response, the SDK collects all N calls from the stream, executes them locally, and sends **one** grouped continuation prompt with all N results.\n\n### Two-part wiring\n\n1. **Register tool schemas** so the API/model knows what is available (`McpRegistry.register`).\n2. **Provide `ToolExecutorFn`** so your host runs tools when the agent calls them.\n\nThe `execute` function on `McpRegistry.register(...)` is catalog metadata. **Runtime execution always goes through `ToolExecutorFn`.**\n\n### Registering custom tools\n\n```ts\nimport { AgenticExecutor, DisperslClient } from \"@codefundi/dispersl-sdk\";\n\nconst client = new DisperslClient({ baseUrl: \"...\", apiKey: \"...\" });\nconst executor = new AgenticExecutor(client, async (tool) => {\n  if (tool.function?.name === \"get_github_user\") {\n    const args = JSON.parse(tool.function.arguments) as { username: string };\n    const res = await fetch(`https://api.github.com/users/${args.username}`);\n    return {\n      toolCallId: tool.id,\n      toolName: \"get_github_user\",\n      status: \"success\",\n      output: JSON.stringify(await res.json()),\n    };\n  }\n  return {\n    toolCallId: tool.id,\n    toolName: tool.function?.name ?? \"unknown\",\n    status: \"error\",\n    output: \"\",\n    error: \"Unsupported tool\",\n  };\n});\n\nexecutor.mcpTools.register({\n  name: \"get_github_user\",\n  description: \"Fetch a public GitHub user profile by username.\",\n  parameters: {\n    type: \"object\",\n    additionalProperties: false,\n    properties: {\n      username: { type: \"string\", description: \"GitHub username\" },\n    },\n    required: [\"username\"],\n  },\n  execute: async () => \"handled-by-host-executor\",\n});\n```\n\n### Host-defined / built-in tools (grep, list, read, etc.)\n\nRegister each local tool on the same registry. Example names used by Code Fundi:\n\n- `read_file`, `list_files`, `grep_workspace`, `write_to_file`, `edit_file`, `execute_command`\n\n```ts\nfor (const tool of hostBuiltinTools) {\n  executor.mcpTools.register(tool);\n}\n```\n\nAll registered tools are sent to the API on every request:\n\n```ts\nconst runtimeTools = executor.mcpTools.list().map((tool) => ({\n  name: tool.name,\n  description: tool.description,\n  inputSchema: tool.parameters,\n}));\n\nawait client.executeAgentCompletion({\n  name_id: \"coder\",\n  prompt: \"Scan the repo\",\n  mcp: { ...mergedMcpConfig, tools: runtimeTools },\n});\n```\n\n`AgenticExecutor` loops do this automatically.\n\n### `.dispersl/mcp.json`\n\nPlace MCP server configuration at `.dispersl/mcp.json` (relative to your project cwd):\n\n```json\n{\n  \"version\": \"1\",\n  \"servers\": {\n    \"code-fundi\": {\n      \"transport\": \"stdio\",\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@codefundi/mcp-server\"],\n      \"env\": { \"CODEFUNDI_API_KEY\": \"${CODEFUNDI_API_KEY}\" },\n      \"enabled\": true\n    }\n  }\n}\n```\n\nLoad and merge at runtime:\n\n```ts\nimport { McpConfigLoader } from \"@codefundi/dispersl-sdk\";\n\nconst loader = new McpConfigLoader();\nconst local = loader.loadFromDefaultPath(process.cwd());\nconst merged = loader.merge(local, runtimeOverride);\n```\n\n`${ENV_VAR}` placeholders are interpolated from `process.env`.\n\n### Grouped tool responses\n\nWhen the agent emits multiple tools in one turn (e.g. `read_file` + `grep_workspace` + `list_files`):\n\n1. `parseAgentStream` collects **all** tool calls from the NDJSON stream (top-level `tools[]`, inline `tool_calls`, streaming content).\n2. Non-control tools execute locally (sequential by default).\n3. **One** continuation prompt is built via `buildGroupedToolFeedbackPrompt` containing all results:\n\n```\nTool results (3 tools executed this turn):\n1. [call_abc] read_file => SUCCESS => ...\n2. [call_def] grep_workspace => SUCCESS => ...\n3. [call_ghi] list_files => SUCCESS => ...\n```\n\nCustom streaming hosts can use `parseAgentStream` directly:\n\n```ts\nimport { parseAgentStream, isControlToolCall } from \"@codefundi/dispersl-sdk\";\n\nconst turn = await parseAgentStream(stream, {\n  toolExecutor: myExecutor,\n  captureToolErrors: true,\n  executeLocally: (tool) => !isControlToolCall(tool),\n  onChunk: (chunk) => console.log(chunk.message),\n});\n\nif (turn.turnToolResults.length > 0) {\n  const nextPrompt = buildGroupedToolFeedbackPrompt({\n    agentId: \"coder\",\n    previousPrompt: currentPrompt,\n    results: turn.turnToolResults,\n    mode: \"single\",\n  });\n}\n```\n\n### Control tools\n\nThese are **not** executed locally (workflow signals only):\n\n- `end_session`, `finish_task`, `handover_task`\n\nThey may appear in the same turn as dynamic tools. Local tool results are still grouped and sent back first.\n\n### Mixed turns (builtins + MCP + custom)\n\nGrouping is **tool-name-agnostic**. A single turn may mix `read_file`, `grep_workspace`, CodeFundi MCP tools, and custom registry tools. All are collected, executed via `ToolExecutorFn`, and returned in one grouped prompt.\n\n## MCP Support\n\n`McpConfigLoader` and `McpRegistry` support:\n\n- loading `.dispersl/mcp.json`\n- `${ENV_VAR}` interpolation\n- merge of local config with runtime overrides\n- runtime custom tool registration:\n  - `register(tool)`\n  - `unregister(name)`\n  - `list()`\n\n## Development\n\n```bash\npnpm install\npnpm run lint\npnpm run typecheck\npnpm run test -- --run\npnpm run build\n```\n\n## Example Quickstarts\n\nEnd-to-end quickstarts live in root `examples/ts`:\n\n- `examples/ts/plan-handover-loop.ts`\n- `examples/ts/single-agent-completion.ts`\n- `examples/ts/task-insight-progress.ts`\n- `examples/ts/agent-lifecycle-and-stats.ts`\n- `examples/ts/mcp-custom-agent-flow.ts`\n\n## Release\n\n- Package name: `@codefundi/dispersl-sdk`\n- TS release workflow: `.github/workflows/release-typescript.yml`\n- Trigger: push tag `ts-v*`\n","readmeFilename":"README.md"}