{"_id":"@bernierllc/ai-agent-runtime","_rev":"3-f188533f1acb0edd7e15f4d14c2bf800","name":"@bernierllc/ai-agent-runtime","dist-tags":{"latest":"0.2.1"},"versions":{"0.0.1":{"name":"@bernierllc/ai-agent-runtime","version":"0.0.1","keywords":["oidc","trusted-publishing","setup"],"_id":"@bernierllc/ai-agent-runtime@0.0.1","maintainers":[{"name":"alikhan410","email":"mczeyo@gmail.com"},{"name":"mkbernier","email":"mkbernier@gmail.com"}],"dist":{"shasum":"e3545bffd98550204705588dc3f922d8b7da2dbc","tarball":"https://registry.npmjs.org/@bernierllc/ai-agent-runtime/-/ai-agent-runtime-0.0.1.tgz","fileCount":2,"integrity":"sha512-6HBti4nlmQRTZGyxVmuqFVHKKFEA5uGWNNArDPR38fPw8iXvhSSnauflel9PhJfa4yuL94xoawiiK7mcyJadew==","signatures":[{"sig":"MEQCIAHTsDIds5NxA3+u3sYqbi8gqeyljRXl4sZxurMXxYupAiBIizasT7uul1D3rfuSn/f2yGDVxv2xT43nUeopmGfenA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":2075},"_npmUser":{"name":"mkbernier","email":"mkbernier@gmail.com"},"_npmVersion":"11.12.1","description":"OIDC trusted publishing setup package for @bernierllc/ai-agent-runtime","directories":{},"_nodeVersion":"25.9.0","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/ai-agent-runtime_0.0.1_1781312307371_0.9795689802114929","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@bernierllc/ai-agent-runtime","version":"0.2.0","keywords":["ai","agent","llm","streaming","tool-calls","bernierllc"],"author":{"name":"Bernier LLC"},"license":"Bernier LLC","_id":"@bernierllc/ai-agent-runtime@0.2.0","maintainers":[{"name":"alikhan410","email":"mczeyo@gmail.com"},{"name":"mkbernier","email":"mkbernier@gmail.com"}],"homepage":"https://github.com/bernierllc/tools#readme","bugs":{"url":"https://github.com/bernierllc/tools/issues"},"dist":{"shasum":"5179c8b4372e06750141a73250901fc0d5202fc7","tarball":"https://registry.npmjs.org/@bernierllc/ai-agent-runtime/-/ai-agent-runtime-0.2.0.tgz","fileCount":19,"integrity":"sha512-dMPfkV/rCOAydNZNcth6JYg/YVkCdOciPT4TLJpnX4jYJm+82isvEdN8KEM37JAPfgWNIt+0I6JeXR8nGcWpDw==","signatures":[{"sig":"MEYCIQDMB5pEukJNVRA/f22uhYLPjAcxRpxP469ujK+P4Z0HhwIhALtFRUehL+MG8EJ9YAXKJ6Muoy1BqfkkNzyVbJHY0jx2","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":55600},"main":"dist/index.js","_from":"file:bernierllc-ai-agent-runtime-0.2.0.tgz","types":"dist/index.d.ts","engines":{"node":">=18.0.0"},"scripts":{"lint":"eslint src/**/*.ts","test":"jest","build":"tsc","clean":"rm -rf dist","prebuild":"npm run clean","test:run":"jest","test:watch":"jest --watch","test:coverage":"jest --coverage"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:632da0f4-eae4-42ca-a580-83b2498c2cd6"}},"_resolved":"/home/runner/work/tools/tools/packages/core/ai-agent-runtime/bernierllc-ai-agent-runtime-0.2.0.tgz","_integrity":"sha512-dMPfkV/rCOAydNZNcth6JYg/YVkCdOciPT4TLJpnX4jYJm+82isvEdN8KEM37JAPfgWNIt+0I6JeXR8nGcWpDw==","repository":{"url":"git+https://github.com/bernierllc/tools.git","type":"git","directory":"packages/core/ai-agent-runtime"},"_npmVersion":"11.17.0","description":"Framework-agnostic streaming agent loop for multi-turn LLM tool-call orchestration","directories":{},"_nodeVersion":"24.16.0","dependencies":{"@bernierllc/logger":"1.7.0","@bernierllc/ai-provider-core":"1.6.0"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","eslint":"^8.0.0","rimraf":"^5.0.0","ts-jest":"^29.1.2","typescript":"^5.3.3","@types/jest":"^29.5.12","@types/node":"^20.11.19","@bernierllc/ai-provider-openai":"1.2.0"},"peerDependencies":{"@bernierllc/neverhub-adapter":"^0.4.0"},"peerDependenciesMeta":{"@bernierllc/neverhub-adapter":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/ai-agent-runtime_0.2.0_1781313847669_0.32621187379956584","host":"s3://npm-registry-packages-npm-production"}},"0.2.1":{"name":"@bernierllc/ai-agent-runtime","version":"0.2.1","description":"Framework-agnostic streaming agent loop for multi-turn LLM tool-call orchestration","main":"dist/index.js","types":"dist/index.d.ts","keywords":["ai","agent","llm","streaming","tool-calls","bernierllc"],"author":{"name":"Bernier LLC"},"license":"Bernier LLC","repository":{"type":"git","url":"git+https://github.com/bernierllc/tools.git","directory":"packages/core/ai-agent-runtime"},"dependencies":{"@bernierllc/logger":"1.7.1","@bernierllc/ai-provider-core":"1.6.1"},"peerDependencies":{"@bernierllc/neverhub-adapter":"^0.4.0"},"peerDependenciesMeta":{"@bernierllc/neverhub-adapter":{"optional":true}},"devDependencies":{"@types/jest":"^29.5.12","@types/node":"^20.11.19","eslint":"^8.0.0","jest":"^29.7.0","rimraf":"^5.0.0","ts-jest":"^29.1.2","typescript":"^5.3.3","@bernierllc/ai-provider-openai":"1.2.1"},"engines":{"node":">=18.0.0"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"scripts":{"build":"tsc","test":"jest","test:watch":"jest --watch","test:coverage":"jest --coverage","lint":"eslint src/**/*.ts","clean":"rm -rf dist","prebuild":"npm run clean","test:run":"jest"},"_id":"@bernierllc/ai-agent-runtime@0.2.1","bugs":{"url":"https://github.com/bernierllc/tools/issues"},"homepage":"https://github.com/bernierllc/tools#readme","_integrity":"sha512-GRSM156+UPL5fsK668ksqri2QAAXZMUk7eeF/rBYdxue8l6zPdSntQ23otswlIxhlQBI+aSj5fvHZAB96Upn/Q==","_resolved":"/home/runner/work/tools/tools/packages/core/ai-agent-runtime/bernierllc-ai-agent-runtime-0.2.1.tgz","_from":"file:bernierllc-ai-agent-runtime-0.2.1.tgz","_nodeVersion":"24.18.0","_npmVersion":"12.0.1","dist":{"integrity":"sha512-GRSM156+UPL5fsK668ksqri2QAAXZMUk7eeF/rBYdxue8l6zPdSntQ23otswlIxhlQBI+aSj5fvHZAB96Upn/Q==","shasum":"98372ab64d4070afdc852999b4f25094098c7086","tarball":"https://registry.npmjs.org/@bernierllc/ai-agent-runtime/-/ai-agent-runtime-0.2.1.tgz","fileCount":19,"unpackedSize":55600,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIHFV1gMK01Kv1EYwiXMFrSqmt6r2y7SXo8of6j1fCPLHAiAIkZNozbY/pIuxACGpUm1BMCq0qkSpHui0nTTaW2v8XQ=="}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:632da0f4-eae4-42ca-a580-83b2498c2cd6"}},"directories":{},"maintainers":[{"name":"alikhan410","email":"mczeyo@gmail.com"},{"name":"mkbernier","email":"mkbernier@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/ai-agent-runtime_0.2.1_1784015474685_0.17251791173293496"},"_hasShrinkwrap":false}},"time":{"created":"2026-06-13T00:58:27.253Z","modified":"2026-07-14T07:51:14.970Z","0.0.1":"2026-06-13T00:58:27.510Z","0.2.0":"2026-06-13T01:24:07.826Z","0.2.1":"2026-07-14T07:51:14.812Z"},"bugs":{"url":"https://github.com/bernierllc/tools/issues"},"author":{"name":"Bernier LLC"},"license":"Bernier LLC","homepage":"https://github.com/bernierllc/tools#readme","keywords":["ai","agent","llm","streaming","tool-calls","bernierllc"],"repository":{"type":"git","url":"git+https://github.com/bernierllc/tools.git","directory":"packages/core/ai-agent-runtime"},"description":"Framework-agnostic streaming agent loop for multi-turn LLM tool-call orchestration","maintainers":[{"name":"alikhan410","email":"mczeyo@gmail.com"},{"name":"mkbernier","email":"mkbernier@gmail.com"}],"readme":"# @bernierllc/ai-agent-runtime\n\nFramework-agnostic streaming agent loop for multi-turn LLM execution with any `@bernierllc/ai-provider-core` provider. Owns the full agent execution loop — LLM call, tool-call detection, tool dispatch, result injection, budget/turn/timeout guards — and emits every step as `AsyncIterable<AgentEvent>` so callers can stream output progressively.\n\n## Installation\n\n```bash\nnpm install @bernierllc/ai-agent-runtime\n```\n\n## Usage\n\n```typescript\nimport { createAgentRuntime } from '@bernierllc/ai-agent-runtime';\nimport { OpenAIProvider } from '@bernierllc/ai-provider-openai';\n\nconst provider = new OpenAIProvider({ apiKey: process.env.OPENAI_API_KEY! });\n\nconst runtime = createAgentRuntime({\n  provider,\n  systemPrompt: 'You are a helpful assistant.',\n  maxTurns: 10,\n  tokenBudget: 20_000,\n  timeoutMs: 30_000,\n});\n\nconst messages = [{ role: 'user' as const, content: 'What is the weather in Paris?' }];\nconst context  = { conversationId: crypto.randomUUID(), messages: [] };\n\nfor await (const event of runtime.run(messages, context)) {\n  switch (event.type) {\n    case 'text-delta':\n      process.stdout.write(event.delta);\n      break;\n    case 'tool-call-start':\n      console.log(`\\nCalling tool: ${event.toolName}`);\n      break;\n    case 'tool-call-result':\n      console.log(`Tool result:`, event.result);\n      break;\n    case 'done':\n      console.log(`\\nFinished in ${event.totalTurns} turn(s), ${event.totalTokens} tokens`);\n      break;\n    case 'error':\n      console.error('Agent error:', event.error.message);\n      break;\n  }\n}\n```\n\n## With tools\n\n```typescript\nimport {\n  createAgentRuntime,\n  type ToolExecutor,\n  type ToolResult,\n  type AgentContext,\n} from '@bernierllc/ai-agent-runtime';\n\nconst weatherTool: ToolExecutor = {\n  name: 'get_weather',\n  description: 'Get current weather for a city',\n  schema: {\n    type: 'object',\n    properties: {\n      city: { type: 'string', description: 'City name' },\n    },\n    required: ['city'],\n  },\n  async execute(input: unknown, _ctx: AgentContext): Promise<ToolResult> {\n    const { city } = input as { city: string };\n    // Real implementation would call a weather API\n    return {\n      success: true,\n      message: `Weather fetched for ${city}`,\n      data: { city, temp: 22, condition: 'Sunny' },\n    };\n  },\n};\n\nconst runtime = createAgentRuntime({\n  provider,\n  systemPrompt: 'You are a weather assistant.',\n  tools: [weatherTool],\n  maxTurns: 5,\n});\n\nfor await (const event of runtime.run(messages, context)) {\n  // handle events\n}\n```\n\n## Dynamic system prompt\n\nPass a function to generate the system prompt per-run from the agent context:\n\n```typescript\nconst runtime = createAgentRuntime({\n  provider,\n  systemPrompt: async (ctx) => {\n    const prefs = await loadUserPreferences(ctx.conversationId);\n    return `You are a helpful assistant. User preferences: ${JSON.stringify(prefs)}`;\n  },\n});\n```\n\n## Abort signal\n\nPass a standard `AbortSignal` to cancel an in-flight run:\n\n```typescript\nconst controller = new AbortController();\n\n// Cancel after 5 seconds\nsetTimeout(() => controller.abort(), 5_000);\n\nfor await (const event of runtime.run(messages, context, controller.signal)) {\n  if (event.type === 'error') {\n    // AgentRuntimeAbortError if cancelled by caller\n    // AgentRuntimeTimeoutError if per-turn timeoutMs fired\n    console.error(event.error.code, event.error.message);\n  }\n}\n```\n\n## API\n\n### `createAgentRuntime(config): AgentRuntime`\n\nCreates a new agent runtime instance.\n\n| Field | Type | Default | Description |\n|---|---|---|---|\n| `provider` | `AIProvider` | required | Any `@bernierllc/ai-provider-core` provider |\n| `systemPrompt` | `string \\| (ctx) => string \\| Promise<string>` | none | System prompt or dynamic factory |\n| `maxTurns` | `number` | `10` | Maximum turns before `AgentRuntimeMaxTurnsError` |\n| `tokenBudget` | `number` | none | Maximum cumulative tokens before `AgentRuntimeTokenBudgetError` |\n| `timeoutMs` | `number` | none | Per-turn timeout in milliseconds before `AgentRuntimeTimeoutError` |\n| `tools` | `ToolExecutor[]` | `[]` | Tool executors available to the agent |\n\n### `AgentRuntime.run(messages, context, signal?)`\n\nReturns `AsyncIterable<AgentEvent>`. Drives the multi-turn loop until the agent produces a final text response, a safety guard fires, or the caller aborts.\n\n### `AgentEvent` union\n\n| `type` | Fields | When emitted |\n|---|---|---|\n| `text-delta` | `delta: string` | Provider returns a non-empty text response |\n| `tool-call-start` | `toolName`, `toolCallId`, `input` | Before a tool is executed |\n| `tool-call-result` | `toolName`, `toolCallId`, `result` | After a tool returns |\n| `turn-complete` | `turnIndex`, `totalTokens` | End of each turn |\n| `done` | `finalText`, `totalTurns`, `totalTokens` | Run finished successfully |\n| `error` | `error: AgentRuntimeError` | Any failure — loop terminates after this event |\n\n### Error classes\n\n| Class | Code | When thrown |\n|---|---|---|\n| `AgentRuntimeError` | `AGENT_RUNTIME_ERROR` | Base class for all errors |\n| `AgentRuntimeMaxTurnsError` | `MAX_TURNS_EXCEEDED` | Loop reached `maxTurns` without a text response |\n| `AgentRuntimeTokenBudgetError` | `TOKEN_BUDGET_EXCEEDED` | Cumulative tokens exceeded `tokenBudget` |\n| `AgentRuntimeTimeoutError` | `TURN_TIMEOUT` | A single turn took longer than `timeoutMs` |\n| `AgentRuntimeAbortError` | `RUN_ABORTED` | Caller's `AbortSignal` fired |\n\nAll errors carry `Error.cause` chains for full stack trace preservation.\n\n## Integrations\n\n### Logger integration\n\n`@bernierllc/ai-agent-runtime` uses `@bernierllc/logger` internally for structured logging at `debug`, `warn`, and `error` levels. All log output flows through the shared logger configuration — no extra setup needed.\n\n### NeverHub integration\n\nThis is a **core** package. NeverHub integration is optional and handled by the service layer (for example, `@bernierllc/agent-service` or whichever service orchestrates this runtime). This package does not register with `@bernierllc/neverhub-adapter` directly.\n\nIf you are building a service that wraps this runtime, wire in NeverHub at the service boundary:\n\n```typescript\nimport { NeverHubAdapter } from '@bernierllc/neverhub-adapter';\n\nif (await NeverHubAdapter.detect()) {\n  const hub = new NeverHubAdapter();\n  await hub.register({ type: 'agent-runtime-service', version: '1.0.0' });\n}\n// Core runtime works regardless — graceful degradation is built in.\n```\n\n### Graceful degradation\n\nAll optional integrations (NeverHub, telemetry, external logging) are additive. The runtime works correctly without any of them, and callers that do not configure optional integrations will see no change in behaviour.\n\n## License\n\nBernier LLC limited-use license. See [LICENSE](./LICENSE).\n","readmeFilename":"README.md"}