adonis-ai-kit 0.0.0-stage → 1.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.
Files changed (196) hide show
  1. package/CHANGELOG.md +74 -0
  2. package/LICENSE +21 -0
  3. package/README.md +397 -2
  4. package/dist/commands/ai_test.d.ts +12 -0
  5. package/dist/commands/ai_test.d.ts.map +1 -0
  6. package/dist/commands/ai_test.js +98 -0
  7. package/dist/commands/ai_test.js.map +1 -0
  8. package/dist/commands/main.d.ts +14 -0
  9. package/dist/commands/main.d.ts.map +1 -0
  10. package/dist/commands/main.js +31 -0
  11. package/dist/commands/main.js.map +1 -0
  12. package/dist/commands/make_agent.d.ts +13 -0
  13. package/dist/commands/make_agent.d.ts.map +1 -0
  14. package/dist/commands/make_agent.js +116 -0
  15. package/dist/commands/make_agent.js.map +1 -0
  16. package/dist/providers/ai_provider.d.ts +23 -0
  17. package/dist/providers/ai_provider.d.ts.map +1 -0
  18. package/dist/providers/ai_provider.js +34 -0
  19. package/dist/providers/ai_provider.js.map +1 -0
  20. package/dist/services/main.d.ts +4 -0
  21. package/dist/services/main.d.ts.map +1 -0
  22. package/dist/services/main.js +7 -0
  23. package/dist/services/main.js.map +1 -0
  24. package/dist/src/acp/acp_agents.d.ts +89 -0
  25. package/dist/src/acp/acp_agents.d.ts.map +1 -0
  26. package/dist/src/acp/acp_agents.js +367 -0
  27. package/dist/src/acp/acp_agents.js.map +1 -0
  28. package/dist/src/acp/index.d.ts +4 -0
  29. package/dist/src/acp/index.d.ts.map +1 -0
  30. package/dist/src/acp/index.js +4 -0
  31. package/dist/src/acp/index.js.map +1 -0
  32. package/dist/src/acp/provider.d.ts +74 -0
  33. package/dist/src/acp/provider.d.ts.map +1 -0
  34. package/dist/src/acp/provider.js +276 -0
  35. package/dist/src/acp/provider.js.map +1 -0
  36. package/dist/src/acp/types.d.ts +128 -0
  37. package/dist/src/acp/types.d.ts.map +1 -0
  38. package/dist/src/acp/types.js +2 -0
  39. package/dist/src/acp/types.js.map +1 -0
  40. package/dist/src/agents/agent_runner.d.ts +60 -0
  41. package/dist/src/agents/agent_runner.d.ts.map +1 -0
  42. package/dist/src/agents/agent_runner.js +134 -0
  43. package/dist/src/agents/agent_runner.js.map +1 -0
  44. package/dist/src/agents/index.d.ts +4 -0
  45. package/dist/src/agents/index.d.ts.map +1 -0
  46. package/dist/src/agents/index.js +4 -0
  47. package/dist/src/agents/index.js.map +1 -0
  48. package/dist/src/agents/loader.d.ts +56 -0
  49. package/dist/src/agents/loader.d.ts.map +1 -0
  50. package/dist/src/agents/loader.js +184 -0
  51. package/dist/src/agents/loader.js.map +1 -0
  52. package/dist/src/agents/manifest.d.ts +61 -0
  53. package/dist/src/agents/manifest.d.ts.map +1 -0
  54. package/dist/src/agents/manifest.js +35 -0
  55. package/dist/src/agents/manifest.js.map +1 -0
  56. package/dist/src/ai_manager.d.ts +140 -0
  57. package/dist/src/ai_manager.d.ts.map +1 -0
  58. package/dist/src/ai_manager.js +814 -0
  59. package/dist/src/ai_manager.js.map +1 -0
  60. package/dist/src/budget/budget_allocator.d.ts +37 -0
  61. package/dist/src/budget/budget_allocator.d.ts.map +1 -0
  62. package/dist/src/budget/budget_allocator.js +98 -0
  63. package/dist/src/budget/budget_allocator.js.map +1 -0
  64. package/dist/src/budget/budget_enforcer.d.ts +70 -0
  65. package/dist/src/budget/budget_enforcer.d.ts.map +1 -0
  66. package/dist/src/budget/budget_enforcer.js +195 -0
  67. package/dist/src/budget/budget_enforcer.js.map +1 -0
  68. package/dist/src/budget/cost_tracker.d.ts +71 -0
  69. package/dist/src/budget/cost_tracker.d.ts.map +1 -0
  70. package/dist/src/budget/cost_tracker.js +199 -0
  71. package/dist/src/budget/cost_tracker.js.map +1 -0
  72. package/dist/src/budget/index.d.ts +6 -0
  73. package/dist/src/budget/index.d.ts.map +1 -0
  74. package/dist/src/budget/index.js +6 -0
  75. package/dist/src/budget/index.js.map +1 -0
  76. package/dist/src/budget/pricing.d.ts +35 -0
  77. package/dist/src/budget/pricing.d.ts.map +1 -0
  78. package/dist/src/budget/pricing.js +129 -0
  79. package/dist/src/budget/pricing.js.map +1 -0
  80. package/dist/src/budget/types.d.ts +86 -0
  81. package/dist/src/budget/types.d.ts.map +1 -0
  82. package/dist/src/budget/types.js +2 -0
  83. package/dist/src/budget/types.js.map +1 -0
  84. package/dist/src/catalog/index.d.ts +3 -0
  85. package/dist/src/catalog/index.d.ts.map +1 -0
  86. package/dist/src/catalog/index.js +3 -0
  87. package/dist/src/catalog/index.js.map +1 -0
  88. package/dist/src/catalog/models_dev.d.ts +87 -0
  89. package/dist/src/catalog/models_dev.d.ts.map +1 -0
  90. package/dist/src/catalog/models_dev.js +38 -0
  91. package/dist/src/catalog/models_dev.js.map +1 -0
  92. package/dist/src/catalog/source.d.ts +67 -0
  93. package/dist/src/catalog/source.d.ts.map +1 -0
  94. package/dist/src/catalog/source.js +678 -0
  95. package/dist/src/catalog/source.js.map +1 -0
  96. package/dist/src/circuit_breaker.d.ts +61 -0
  97. package/dist/src/circuit_breaker.d.ts.map +1 -0
  98. package/dist/src/circuit_breaker.js +217 -0
  99. package/dist/src/circuit_breaker.js.map +1 -0
  100. package/dist/src/define_config.d.ts +11 -0
  101. package/dist/src/define_config.d.ts.map +1 -0
  102. package/dist/src/define_config.js +48 -0
  103. package/dist/src/define_config.js.map +1 -0
  104. package/dist/src/error_classifier.d.ts +50 -0
  105. package/dist/src/error_classifier.d.ts.map +1 -0
  106. package/dist/src/error_classifier.js +206 -0
  107. package/dist/src/error_classifier.js.map +1 -0
  108. package/dist/src/errors.d.ts +52 -0
  109. package/dist/src/errors.d.ts.map +1 -0
  110. package/dist/src/errors.js +70 -0
  111. package/dist/src/errors.js.map +1 -0
  112. package/dist/src/guard/confirmation.d.ts +67 -0
  113. package/dist/src/guard/confirmation.d.ts.map +1 -0
  114. package/dist/src/guard/confirmation.js +180 -0
  115. package/dist/src/guard/confirmation.js.map +1 -0
  116. package/dist/src/guard/errors.d.ts +10 -0
  117. package/dist/src/guard/errors.d.ts.map +1 -0
  118. package/dist/src/guard/errors.js +14 -0
  119. package/dist/src/guard/errors.js.map +1 -0
  120. package/dist/src/guard/guard.d.ts +47 -0
  121. package/dist/src/guard/guard.d.ts.map +1 -0
  122. package/dist/src/guard/guard.js +133 -0
  123. package/dist/src/guard/guard.js.map +1 -0
  124. package/dist/src/guard/index.d.ts +7 -0
  125. package/dist/src/guard/index.d.ts.map +1 -0
  126. package/dist/src/guard/index.js +7 -0
  127. package/dist/src/guard/index.js.map +1 -0
  128. package/dist/src/guard/registry.d.ts +72 -0
  129. package/dist/src/guard/registry.d.ts.map +1 -0
  130. package/dist/src/guard/registry.js +192 -0
  131. package/dist/src/guard/registry.js.map +1 -0
  132. package/dist/src/guard/schema_registry.d.ts +37 -0
  133. package/dist/src/guard/schema_registry.d.ts.map +1 -0
  134. package/dist/src/guard/schema_registry.js +57 -0
  135. package/dist/src/guard/schema_registry.js.map +1 -0
  136. package/dist/src/guard/types.d.ts +63 -0
  137. package/dist/src/guard/types.d.ts.map +1 -0
  138. package/dist/src/guard/types.js +2 -0
  139. package/dist/src/guard/types.js.map +1 -0
  140. package/dist/src/index.d.ts +16 -0
  141. package/dist/src/index.d.ts.map +1 -0
  142. package/dist/src/index.js +14 -0
  143. package/dist/src/index.js.map +1 -0
  144. package/dist/src/logger.d.ts +7 -0
  145. package/dist/src/logger.d.ts.map +1 -0
  146. package/dist/src/logger.js +2 -0
  147. package/dist/src/logger.js.map +1 -0
  148. package/dist/src/models/catalog_resolver.d.ts +24 -0
  149. package/dist/src/models/catalog_resolver.d.ts.map +1 -0
  150. package/dist/src/models/catalog_resolver.js +66 -0
  151. package/dist/src/models/catalog_resolver.js.map +1 -0
  152. package/dist/src/models/index.d.ts +14 -0
  153. package/dist/src/models/index.d.ts.map +1 -0
  154. package/dist/src/models/index.js +8 -0
  155. package/dist/src/models/index.js.map +1 -0
  156. package/dist/src/models/keys.d.ts +9 -0
  157. package/dist/src/models/keys.d.ts.map +1 -0
  158. package/dist/src/models/keys.js +12 -0
  159. package/dist/src/models/keys.js.map +1 -0
  160. package/dist/src/models/language_model_factory.d.ts +44 -0
  161. package/dist/src/models/language_model_factory.d.ts.map +1 -0
  162. package/dist/src/models/language_model_factory.js +193 -0
  163. package/dist/src/models/language_model_factory.js.map +1 -0
  164. package/dist/src/models/model_chain.d.ts +58 -0
  165. package/dist/src/models/model_chain.d.ts.map +1 -0
  166. package/dist/src/models/model_chain.js +144 -0
  167. package/dist/src/models/model_chain.js.map +1 -0
  168. package/dist/src/models/model_ref.d.ts +12 -0
  169. package/dist/src/models/model_ref.d.ts.map +1 -0
  170. package/dist/src/models/model_ref.js +33 -0
  171. package/dist/src/models/model_ref.js.map +1 -0
  172. package/dist/src/models/protocols.d.ts +6 -0
  173. package/dist/src/models/protocols.d.ts.map +1 -0
  174. package/dist/src/models/protocols.js +33 -0
  175. package/dist/src/models/protocols.js.map +1 -0
  176. package/dist/src/models/provider_factories.d.ts +19 -0
  177. package/dist/src/models/provider_factories.d.ts.map +1 -0
  178. package/dist/src/models/provider_factories.js +70 -0
  179. package/dist/src/models/provider_factories.js.map +1 -0
  180. package/dist/src/models/types.d.ts +17 -0
  181. package/dist/src/models/types.d.ts.map +1 -0
  182. package/dist/src/models/types.js +2 -0
  183. package/dist/src/models/types.js.map +1 -0
  184. package/dist/src/response_macro.d.ts +16 -0
  185. package/dist/src/response_macro.d.ts.map +1 -0
  186. package/dist/src/response_macro.js +151 -0
  187. package/dist/src/response_macro.js.map +1 -0
  188. package/dist/src/types.d.ts +340 -0
  189. package/dist/src/types.d.ts.map +1 -0
  190. package/dist/src/types.js +2 -0
  191. package/dist/src/types.js.map +1 -0
  192. package/dist/src/usage.d.ts +13 -0
  193. package/dist/src/usage.d.ts.map +1 -0
  194. package/dist/src/usage.js +61 -0
  195. package/dist/src/usage.js.map +1 -0
  196. package/package.json +208 -4
package/CHANGELOG.md ADDED
@@ -0,0 +1,74 @@
1
+ # Changelog
2
+
3
+ All notable changes to `adonis-ai-kit` are documented in this file.
4
+ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
5
+
6
+ ## [1.2.0] - 2026-10-22
7
+
8
+ Includes the work previously staged as the 1.3.0 and 1.4.0 candidates, which were never published.
9
+
10
+ ### Added
11
+
12
+ - `adonis-ai-kit/models` subpath export:
13
+ - Types and helpers: `ResolvedModel`, `parseModelRef`, `modelKeyFor`, `breakerKeyFor`, `PROTOCOL_TO_NPM`, `resolveProviderNpm`.
14
+ - `ProviderFactory`, `BUILTIN_PROVIDER_EXPORTS` and `ProviderFactoryRegistry` (lazy import of known AI SDK provider packages, plus `register()` for custom ones).
15
+ - `LanguageModelFactory`: 180 s fetch timeout, secret-header redaction in logs, ACP models through `AcpDriver`, and `shutdown()`.
16
+ - `ModelResolver` and `CatalogModelResolver`.
17
+ - `buildChainCandidates`, `runModelChain` and `FallbackEvent` for running a call over an ordered model chain with per-credential circuit breakers.
18
+ - `AcpDriverDeps.runtime`: a prebuilt runtime config for the ACP driver.
19
+ - `AiManager` call options:
20
+ - `schema` (structured `output` on `generateText` and `streamText`), `stopWhen`, `maxRetries`, `onStepFinish`.
21
+ - `models` and `onFallback` to run a call over a dynamic model chain.
22
+ - `AiConfig.resolver` and `AiConfig.languageModels`.
23
+ - Optional `peerDependencies` for the AI SDK provider packages.
24
+ - `LanguageModelFactory` options `acp.inheritEnv` (pass the full server environment to agents) and `acp.shareDriver` (set to `false` to give every model its own driver and agent process).
25
+ - Single `Logger` type shared by all modules (`LoggerContract` stays as a deprecated alias).
26
+ - `ErrorClassification.errorClass` and `ErrorClassification.countsAsFailure`, plus the `countsAsBreakerFailure()` helper.
27
+ - `CircuitBreaker.acquire()` returning a `BreakerPermit`, and `CircuitBreaker.resetAll()`.
28
+ - `ToolAccessOptions.permissions` for per-call tool permissions.
29
+ - ACP: `AcpAgentConfig.credentialEnv` and `buildAcpRuntimeConfig(agentId, options)` with `projectMcpPath` (the positional form keeps working).
30
+ - Error taxonomy exported from the package root: `ErrorClass` (11 classes), `classifyErrorClass()`, `isRetryableError()` and `getUserFriendlyMessage()`.
31
+ - Replaceable ACP agent registry: `registerAcpAgent()`, `setAcpAgents()` and `resetAcpAgents()`, so an application can point an agent at the binary installed on the machine.
32
+ - Catalog option `injectSystemProviders` (default `true`) to turn off the automatic injection of openai/anthropic/google; superseded within this release by `systemProviders` and kept as a deprecated alias.
33
+ - Catalog: `systemProviders: { fallback, acp }` option (also available as `CatalogConfig.systemProviders`) to inject fallback and ACP providers independently.
34
+
35
+ ### Changed
36
+
37
+ - Optional provider peer dependencies accept any version.
38
+ - Behavior changes to be aware of:
39
+ - `prompt_too_long` and `no_output_generated` errors now fall back to the next provider but never open the circuit breaker.
40
+ - Errors recognised only through `isRetryable === true` fall back, but no longer count against the circuit breaker.
41
+ - `ErrorClassification` gained two required fields (`errorClass`, `countsAsFailure`). This only affects code that constructs the interface itself.
42
+ - `dist/` is no longer tracked in git (it is still built and shipped in the npm package).
43
+
44
+ ### Deprecated
45
+
46
+ - `injectSystemProviders` (added earlier in this release, then superseded by `systemProviders`) — use `systemProviders`.
47
+ - The `sourcecraft` and `freebuff` default ACP agents — they will be removed from the defaults in 2.0; register them with `registerAcpAgent()`.
48
+ - `LoggerContract` — use `Logger`.
49
+
50
+ ### Fixed
51
+
52
+ - `ToolDefinition.description` accepts the AI SDK v7 tool description type (string or function); the confirmation action falls back to the tool name.
53
+ - One error taxonomy now drives both fallback and circuit-breaker decisions.
54
+ - HTTP status codes are found in `status`, `response.status`, nested `cause` and `lastError` (AI SDK `RetryError`).
55
+ - HTTP 409 and 425 are classified as `overloaded`.
56
+ - ACP agents registered with `setAcpAgents()`/`registerAcpAgent()` without `credentialEnv` inherit the built-in agent's credentials for the same id; `credentialEnv: []` opts out.
57
+ - `CircuitBreaker.execute()` frees its probe slot even if `isFailure` throws.
58
+ - Model chains fall through to the next candidate on missing provider packages, config errors and open breakers (without counting against the breaker), and reject a missing resolver up front.
59
+ - Rejections of an async `onFallback` handler are caught and logged.
60
+ - ACP models in `AiManager` chains use its `ConfirmationService`.
61
+ - `AcpDriver` blanks `process.env` keys that are missing from a custom env source.
62
+ - `LanguageModelFactory` with `acp.shareDriver: false` no longer retains a driver per call: the driver is released when its call ends.
63
+
64
+ ### Notes
65
+
66
+ - An exhausted `models` chain rethrows the last error (or `ProviderUnavailableError` if no candidate could be attempted), unlike the provider cascade, which throws `CascadingFallbackError`.
67
+
68
+ ### Development
69
+
70
+ - Japa test harness.
71
+
72
+ ## [1.1.0]
73
+
74
+ Initial public release.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 IvanGlazyrin
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,398 @@
1
- # Temporary Holding Version
1
+ # adonis-ai-kit
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ > **Production-grade AI & Agentic workflow toolkit for AdonisJS 7**, powered by Vercel AI SDK v7, multi-provider cascading fallback, circuit breakers, tool security guardrails, token budget tracking, models.dev live catalog, and ACP (Agent Client Protocol) coding agents.
4
+
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
6
+ [![npm](https://img.shields.io/npm/v/adonis-ai-kit.svg)](https://www.npmjs.com/package/adonis-ai-kit)
7
+ [![AdonisJS](https://img.shields.io/badge/AdonisJS-7.x-5A45FF.svg)](https://adonisjs.com)
8
+ [![TypeScript](https://img.shields.io/badge/TypeScript-ES2022%20%2F%20NodeNext-blue.svg)](https://www.typescriptlang.org)
9
+ [![Vercel AI SDK](https://img.shields.io/badge/Vercel%20AI%20SDK-v7.x-black.svg)](https://sdk.vercel.ai)
10
+ [![Node](https://img.shields.io/badge/node-%3E%3D22.0.0-brightgreen.svg)](https://nodejs.org)
11
+
12
+ ---
13
+
14
+ ## Highlights & Architectural Comparison
15
+
16
+ While frameworks like **Laravel AI** and **Prism** bring basic prompt-level abstractions to PHP, enterprise production systems require strict SRE resilience, tool execution guardrails, cost guarantees, and streaming protocol integrity. **`adonis-ai-kit`** is built from the ground up for high-concurrency Node.js microservices:
17
+
18
+ | Feature | `adonis-ai-kit` (AdonisJS 7) | Laravel AI / Prism (PHP) |
19
+ | :--- | :--- | :--- |
20
+ | **Foundation Engine** | **Vercel AI SDK v7** (native Node.js async streams & tool calls) | Custom cURL/Guzzle wrappers |
21
+ | **Circuit Breaker** | **Per `provider:model` key** (isolated half-open state, probe limits) | Global or none |
22
+ | **Cascading Fallbacks** | **Safe**: never replays side-effects if tool calls already started | Retries from scratch (risk of double actions) |
23
+ | **Tool Security (Guardrails)** | **Fail-closed** with Human-in-the-Loop (HITL), concurrent slots | Basic parameter mapping |
24
+ | **Token Budget & Cost** | **Live USD pricing**, ring-buffer memory, cache-read & reasoning tokens | Raw token count or static tables |
25
+ | **Catalog Auto-Discovery** | **models.dev integration** with TTL cache & atomic writes | Static configuration files |
26
+ | **Agent Protocols** | **ACP (Agent Client Protocol)** for Claude Code, opencode & subagents | Basic prompt templates |
27
+ | **HTTP Streaming** | **`response.streamAI()` macro** with heartbeats, SSE frames & client-abort hook | PHP chunked response buffers |
28
+
29
+ ---
30
+
31
+ ## Architecture Overview
32
+
33
+ ```mermaid
34
+ flowchart TD
35
+ UserApp["AdonisJS Controller / Service"] --> AiManager["AiManager (Singleton Service)"]
36
+
37
+ subgraph SRE_Resilience ["SRE Resilience & Fallback Layer"]
38
+ AiManager --> CircuitBreaker["Circuit Breaker (provider:model)"]
39
+ CircuitBreaker --> FallbackCascade["Cascading Provider Fallback"]
40
+ end
41
+
42
+ subgraph Execution_Layer ["Execution & Agent Layer"]
43
+ FallbackCascade --> Providers["LLM Drivers (OpenAI, Anthropic, Google, Groq, ACP)"]
44
+ FallbackCascade --> AgentRunner["AgentRunner (Manifest + Skills)"]
45
+ AgentRunner --> ToolRegistry["Tool Registry (PolicyGuard)"]
46
+ ToolRegistry --> HITL["ConfirmationService (Human-in-the-Loop)"]
47
+ end
48
+
49
+ subgraph Observability_Cost ["Observability & Governance"]
50
+ Providers --> CostTracker["CostTracker (Ring Buffer)"]
51
+ Providers --> BudgetEnforcer["BudgetEnforcer (Atomic Reservations)"]
52
+ AiManager -.-> ModelsDev["models.dev Catalog (Live Pricing & Limits)"]
53
+ end
54
+
55
+ subgraph Transport_Layer ["Transport Layer"]
56
+ AiManager --> SSE["response.streamAI() Macro (SSE / Heartbeats / Abort)"]
57
+ end
58
+ ```
59
+
60
+ ---
61
+
62
+ ## Installation
63
+
64
+ ```bash
65
+ npm install adonis-ai-kit
66
+ # or
67
+ pnpm add adonis-ai-kit
68
+ ```
69
+
70
+ > Package name on npm is `adonis-ai-kit` (the `adonis-ai` name on npm is taken by another project).
71
+ > The source repository is [github.com/IvanGlazyrin/adonis-ai-kit](https://github.com/IvanGlazyrin/adonis-ai-kit).
72
+
73
+ Add the provider to `adonisrc.ts`:
74
+
75
+ ```ts
76
+ export default defineConfig({
77
+ providers: [
78
+ // ...
79
+ () => import('adonis-ai-kit/providers/ai_provider')
80
+ ]
81
+ })
82
+ ```
83
+
84
+ Configure your providers in `config/ai.ts`:
85
+
86
+ ```ts
87
+ import env from '#start/env'
88
+ import { defineConfig } from 'adonis-ai-kit'
89
+
90
+ export default defineConfig({
91
+ default: 'openai',
92
+ providers: {
93
+ openai: {
94
+ driver: 'openai',
95
+ apiKey: env.get('OPENAI_API_KEY'),
96
+ defaultModel: 'gpt-4o',
97
+ },
98
+ anthropic: {
99
+ driver: 'anthropic',
100
+ apiKey: env.get('ANTHROPIC_API_KEY'),
101
+ defaultModel: 'claude-3-7-sonnet-20250219',
102
+ },
103
+ },
104
+ // Automatically fallback to Anthropic if OpenAI is throttled (429) or down (5xx)
105
+ fallbackCascade: ['anthropic'],
106
+ circuitBreaker: {
107
+ failureThreshold: 5,
108
+ recoveryTimeoutMs: 30_000,
109
+ halfOpenMaxAttempts: 2,
110
+ },
111
+ })
112
+ ```
113
+
114
+ ---
115
+
116
+ ## Core Capabilities
117
+
118
+ ### 1. Basic Generation & Multi-Provider Fallback
119
+
120
+ Generate text with automatic token usage tracking and USD calculation:
121
+
122
+ ```ts
123
+ import ai from 'adonis-ai-kit/services/main'
124
+
125
+ const result = await ai.generateText({
126
+ prompt: 'Explain vector indexing in 3 sentences',
127
+ })
128
+
129
+ console.log(result.text)
130
+ console.log(`Duration: ${result.durationMs}ms, Cost: $${result.costUsd}`)
131
+ console.log(`Tokens: in=${result.usage.inputTokens}, out=${result.usage.outputTokens}, cached=${result.usage.cacheReadTokens}`)
132
+ ```
133
+
134
+ If OpenAI returns `429 Rate Limit` or `503 Service Unavailable`, `adonis-ai-kit` automatically routes the request to `anthropic` with its configured model, recording circuit breaker metrics. A `prompt_too_long` failure also moves on to the next model, but never counts against (or opens) the circuit breaker.
135
+
136
+ ---
137
+
138
+ ### 2. Structured Output with Zod Schema
139
+
140
+ ```ts
141
+ import { z } from 'zod'
142
+ import ai from 'adonis-ai-kit/services/main'
143
+
144
+ const resumeSchema = z.object({
145
+ fullName: z.string(),
146
+ skills: z.array(z.string()),
147
+ yearsOfExperience: z.number(),
148
+ })
149
+
150
+ const { object } = await ai.generateObject({
151
+ prompt: 'Extract candidate details: Ivan Glazyrin, 9 years in TS and Go',
152
+ schema: resumeSchema,
153
+ })
154
+
155
+ console.log(object.skills) // ['TypeScript', 'Go', ...]
156
+ ```
157
+
158
+ ---
159
+
160
+ ### 3. Server-Sent Events (SSE) Streaming in AdonisJS Controllers
161
+
162
+ Use the built-in `response.streamAI()` macro:
163
+
164
+ ```ts
165
+ import type { HttpContext } from '@adonisjs/core/http'
166
+ import ai from 'adonis-ai-kit/services/main'
167
+
168
+ export default class ChatController {
169
+ async stream({ request, response }: HttpContext) {
170
+ const stream = await ai.streamText({
171
+ prompt: request.input('message'),
172
+ model: 'gpt-4o',
173
+ })
174
+
175
+ // Sets 'Content-Type: text/event-stream', sends heartbeat pings,
176
+ // and automatically calls stream.abort() if the client disconnects!
177
+ return response.streamAI(stream, {
178
+ heartbeatMs: 15_000,
179
+ mode: 'sse',
180
+ })
181
+ }
182
+ }
183
+ ```
184
+
185
+ #### Structured output with tools in a stream
186
+
187
+ `schema`, `stopWhen`, `maxRetries` and `onStepFinish` work for both `generateText` and `streamText`:
188
+
189
+ ```ts
190
+ import { stepCountIs } from 'ai'
191
+ import { z } from 'zod'
192
+
193
+ const stream = await ai.streamText({
194
+ prompt: 'Find the cheapest flight and summarise it.',
195
+ tools: { searchFlights },
196
+ schema: z.object({ airline: z.string(), priceUsd: z.number() }),
197
+ stopWhen: stepCountIs(6), // takes precedence over `maxSteps`
198
+ maxRetries: 0, // fail fast, let the fallback chain take over
199
+ onStepFinish: (step) => console.log('step done', step.finishReason),
200
+ })
201
+
202
+ for await (const part of stream.fullStream) {
203
+ // forward parts to the client...
204
+ }
205
+ const flight = await stream.output // parsed against the schema
206
+ ```
207
+
208
+ ---
209
+
210
+ ### 4. Tool Security Guardrails & Human-in-the-Loop (HITL)
211
+
212
+ Prevent untrusted AI models from executing destructive operations:
213
+
214
+ ```ts
215
+ import { ToolRegistry, ConfirmationService, PolicyGuard } from 'adonis-ai-kit/guard'
216
+ import { tool } from 'ai'
217
+ import { z } from 'zod'
218
+
219
+ const confirmationService = new ConfirmationService({ timeoutMs: 60_000 })
220
+ const registry = new ToolRegistry(confirmationService)
221
+
222
+ // Define tools
223
+ registry.register(
224
+ 'deploy_service',
225
+ tool({
226
+ description: 'Deploy service to cluster',
227
+ parameters: z.object({ cluster: z.string(), service: z.string() }),
228
+ execute: async ({ cluster, service }) => `Deployed ${service} to ${cluster}`,
229
+ }),
230
+ { permission: 'ask', maxCallsPerSession: 1 } // Requires human confirmation!
231
+ )
232
+
233
+ // When the model calls 'deploy_service', confirmationService pauses execution,
234
+ // emits a confirmation request event, and resumes only when approved!
235
+ ```
236
+
237
+ ---
238
+
239
+ ### 5. Cost Tracking & Atomic Token Budget Enforcement
240
+
241
+ ```ts
242
+ import { CostTracker, BudgetEnforcer } from 'adonis-ai-kit/budget'
243
+
244
+ const tracker = new CostTracker({ maxRecords: 10_000 })
245
+ const enforcer = new BudgetEnforcer({
246
+ maxCostUsd: 100.0,
247
+ maxInputTokens: 5_000_000,
248
+ maxOutputTokens: 1_000_000,
249
+ })
250
+
251
+ // Atomic pre-flight reservation prevents concurrent race conditions
252
+ const reservation = enforcer.reserve('user-session-42', { estimatedCostUsd: 0.05 })
253
+ if (!reservation.allowed) {
254
+ throw new Error('Budget exceeded')
255
+ }
256
+
257
+ try {
258
+ // run LLM request...
259
+ enforcer.settle(reservation.reservationId, { costUsd: 0.038 })
260
+ } catch (e) {
261
+ enforcer.release(reservation.reservationId)
262
+ }
263
+ ```
264
+
265
+ ---
266
+
267
+ ### 6. ACP (Agent Client Protocol) Coding Agents
268
+
269
+ Run subagents using local CLI tools like **Claude Code**, **opencode**, or custom ACP binaries with sanitized environments:
270
+
271
+ ```ts
272
+ import { AgentRunner, AgentLoader } from 'adonis-ai-kit/agents'
273
+
274
+ const loader = new AgentLoader({
275
+ configsDir: './resources/agent-configs',
276
+ skillsDir: './resources/agent-skills',
277
+ })
278
+
279
+ const runner = new AgentRunner(aiManager, registry, loader)
280
+ const execution = await runner.run({
281
+ agentId: 'code-reviewer',
282
+ userPrompt: 'Audit packages/adonis-ai for race conditions',
283
+ })
284
+ ```
285
+
286
+ Agents declare the credentials they need and can receive a project MCP server explicitly:
287
+
288
+ ```ts
289
+ import { registerAcpAgent, buildAcpRuntimeConfig } from 'adonis-ai-kit/acp'
290
+
291
+ registerAcpAgent('my-agent', {
292
+ id: 'my-agent', name: 'My Agent', description: '', command: 'my-agent-acp', args: [],
293
+ envVarPrefix: 'ACP_MY_AGENT', supportsMcpServers: true,
294
+ // the first set source is passed to the agent process as `target`
295
+ credentialEnv: [{ target: 'MY_API_KEY', sources: ['MY_API_KEY', 'MY_KEY'] }],
296
+ })
297
+
298
+ const runtime = buildAcpRuntimeConfig('my-agent', {
299
+ projectMcpPath: './mcp/server.js', // used when ACP_MY_AGENT_PROJECT_MCP_PATH is unset
300
+ // the project MCP server is still only attached when ACP_MY_AGENT_ENABLE_PROJECT_MCP=true
301
+ })
302
+ ```
303
+
304
+ ACP agents in a `models` chain ask a human through the manager's `ConfirmationService` (see `getConfirmationService()`), like the provider cascade does.
305
+
306
+ Calling `buildAcpRuntimeConfig` + `createACPProvider` directly bypasses the env sanitizing that `AcpDriver` applies: the agent then inherits the full server environment.
307
+
308
+ The `sourcecraft` and `freebuff` default agents are deprecated and will be removed from the defaults in 2.0; register them with `registerAcpAgent()` if you need them.
309
+
310
+ ---
311
+
312
+ ### 7. Dynamic Credentials & Model Chains
313
+
314
+ Apps with per-user credentials can't use a static provider cascade. Pass `models` — an ordered chain of
315
+ `ResolvedModel | string` — to `generateText`, `streamText` or `generateObject`; the provider cascade is then not used.
316
+
317
+ ```ts
318
+ const result = await ai.generateText({
319
+ prompt: 'Summarize this',
320
+ models: [userKeyModel, teamKeyModel, 'anthropic/claude-sonnet-4-5'],
321
+ onFallback: ({ fromModel, toModel, errorClass }) => log.warn(`${fromModel} -> ${toModel} (${errorClass})`),
322
+ })
323
+ result.provider // providerID of the model that answered
324
+ result.model // its modelID
325
+ // fromModel / toModel are breaker keys: the credential key when the model has one, otherwise provider/model
326
+ ```
327
+
328
+ - Entries are tried in order. Retryable failures (429, 5xx, network) and entries that cannot be attempted (missing provider
329
+ package, config error, open breaker) move on to the next entry; bad requests, caller aborts and any failure after a
330
+ tool has run are thrown as is. `streamText` falls back on errors before the first chunk.
331
+ - Each entry has its own circuit breaker, keyed by `credentialKey` when present (so one bad key doesn't block the others).
332
+ - String entries are resolved through `config.resolver` (e.g. a `CatalogModelResolver`); without one a `ProviderConfigError` is thrown.
333
+ - Models are built by `config.languageModels` (a `LanguageModelFactory`); when absent a default one is created lazily.
334
+ `manager.shutdown()` shuts it down (stops ACP agents).
335
+ - `schema`, `stopWhen`, `maxRetries` and `onStepFinish` work on the chain path too. Empty `models` uses the provider cascade.
336
+
337
+ ## Ace CLI Commands
338
+
339
+ `adonis-ai-kit` registers helpful Ace commands:
340
+
341
+ ```bash
342
+ # Test connectivity, latency, and model availability across configured providers
343
+ node ace ai:test
344
+
345
+ # Scaffold a new production agent prompt and schema
346
+ node ace make:ai-agent backend-architect --mode=primary
347
+ ```
348
+
349
+ ---
350
+
351
+ ## Testing & Quality
352
+
353
+ The package includes a comprehensive regression test suite with 100% pass rate:
354
+
355
+ ```bash
356
+ npm run test:regression
357
+ ```
358
+
359
+ - **Token Budget**: Rate calculations, cache-read discounts, reasoning token surcharges, ring-buffer bounded memory.
360
+ - **Tool Guard**: Policy enforcement (`allow`, `ask`, `deny`), concurrency slots, fail-closed handlers, session validation.
361
+ - **Adonis AI Core**: Cascading failovers without duplicate side-effects, SSE keepalive frames, models.dev live discovery & TTL, ACP command sanitization.
362
+
363
+ ---
364
+
365
+ ## Development & Release
366
+
367
+ ```bash
368
+ git clone https://github.com/IvanGlazyrin/adonis-ai-kit.git
369
+ cd adonis-ai-kit
370
+ npm install
371
+ npm run build
372
+ npm run test:regression
373
+ ```
374
+
375
+ Consume the local build from an AdonisJS app without publishing:
376
+
377
+ ```bash
378
+ # in the app
379
+ npm install ../path/to/adonis-ai-kit # file: dependency
380
+ # or globally
381
+ cd ../adonis-ai-kit && npm link
382
+ cd ../my-app && npm link adonis-ai-kit
383
+ ```
384
+
385
+ Releases are published to npm by pushing a version tag:
386
+
387
+ ```bash
388
+ npm version patch # bumps package.json + tag v1.1.1
389
+ git push --follow-tags # .github/workflows/release.yml runs npm publish
390
+ ```
391
+
392
+ The workflow requires an `NPM_TOKEN` secret in the repository settings.
393
+
394
+ ---
395
+
396
+ ## License
397
+
398
+ MIT © [Ivan Glazyrin](https://github.com/IvanGlazyrin) (glazrus97@gmail.com)
@@ -0,0 +1,12 @@
1
+ import { BaseCommand } from '@adonisjs/core/ace';
2
+ import type { CommandOptions } from '@adonisjs/core/types/ace';
3
+ export default class AiTestCommand extends BaseCommand {
4
+ static commandName: string;
5
+ static description: string;
6
+ static options: CommandOptions;
7
+ provider?: string;
8
+ model?: string;
9
+ testPrompt: string;
10
+ run(): Promise<void>;
11
+ }
12
+ //# sourceMappingURL=ai_test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai_test.d.ts","sourceRoot":"","sources":["../../commands/ai_test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAS,MAAM,oBAAoB,CAAA;AACvD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA;AAE9D,MAAM,CAAC,OAAO,OAAO,aAAc,SAAQ,WAAW;IACpD,MAAM,CAAC,WAAW,SAAY;IAC9B,MAAM,CAAC,WAAW,SAA4E;IAE9F,MAAM,CAAC,OAAO,EAAE,cAAc,CAE7B;IAGO,QAAQ,CAAC,EAAE,MAAM,CAAA;IAGjB,KAAK,CAAC,EAAE,MAAM,CAAA;IAOd,UAAU,EAAE,MAAM,CAAA;IAEpB,GAAG;CA4EV"}
@@ -0,0 +1,98 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ import { BaseCommand, flags } from '@adonisjs/core/ace';
11
+ export default class AiTestCommand extends BaseCommand {
12
+ static commandName = 'ai:test';
13
+ static description = 'Test connectivity, latency, and generation with configured AI providers';
14
+ static options = {
15
+ startApp: true,
16
+ };
17
+ async run() {
18
+ const ai = await this.app.container.make('ai');
19
+ this.ui.logger.info('🤖 Testing Adonis AI Provider Connectivity...\n');
20
+ const config = ai.getConfig();
21
+ const providersToTest = this.provider ? [this.provider] : Object.keys(config.providers);
22
+ if (providersToTest.length === 0) {
23
+ this.ui.logger.error('No AI providers configured in config/ai.ts!');
24
+ return;
25
+ }
26
+ const table = this.ui.table();
27
+ table.head(['Provider', 'Model', 'Status', 'Latency', 'Circuit Breaker', 'Cost ($)']);
28
+ for (const pName of providersToTest) {
29
+ const pConfig = config.providers[pName];
30
+ if (!pConfig) {
31
+ this.ui.logger.error(`Provider "${pName}" not found in config!`);
32
+ continue;
33
+ }
34
+ const testModel = this.model ?? pConfig.defaultModel ?? 'default';
35
+ const start = Date.now();
36
+ try {
37
+ const response = await ai.generateText({
38
+ provider: pName,
39
+ model: this.model,
40
+ prompt: this.testPrompt || "Respond with PONG and your model identity in 10 words or less.",
41
+ maxOutputTokens: 50,
42
+ agentName: 'ace-ai-test',
43
+ });
44
+ const latency = Date.now() - start;
45
+ const stats = ai.getCircuitBreaker().getStats(`${response.provider}:${response.model}`);
46
+ // A fallback provider answering is NOT a pass for the provider under test
47
+ const answeredByFallback = response.provider !== pName;
48
+ table.row([
49
+ this.colors.cyan(pName),
50
+ response.model,
51
+ answeredByFallback
52
+ ? this.colors.yellow(`⚠ FALLBACK (${response.provider})`)
53
+ : this.colors.green('✔ OK'),
54
+ `${latency}ms`,
55
+ this.colors.green(stats.state.toUpperCase()),
56
+ response.costUsd !== undefined ? `$${response.costUsd.toFixed(6)}` : 'N/A',
57
+ ]);
58
+ this.ui.logger.info(`[${pName}] Output: "${response.text.trim()}"`);
59
+ }
60
+ catch (err) {
61
+ const latency = Date.now() - start;
62
+ const stats = ai.getCircuitBreaker().getStats(`${pName}:${testModel}`);
63
+ table.row([
64
+ this.colors.cyan(pName),
65
+ testModel,
66
+ this.colors.red('✖ FAILED'),
67
+ `${latency}ms`,
68
+ this.colors.red(stats.state.toUpperCase()),
69
+ 'N/A',
70
+ ]);
71
+ this.ui.logger.error(`[${pName}] Error: ${err.message}`);
72
+ }
73
+ }
74
+ this.ui.logger.log('');
75
+ table.render();
76
+ this.ui.logger.log('');
77
+ const totalCost = ai.getCostTracker().getTotalCost();
78
+ const totalTokens = ai.getCostTracker().getTotalTokens();
79
+ this.ui.logger.info(`Total session cost: ${totalCost.toFixed(6)} | Tokens: ${totalTokens}`);
80
+ }
81
+ }
82
+ __decorate([
83
+ flags.string({ description: 'Specific provider to test (e.g. openai, anthropic, gemini, groq, ollama)' }),
84
+ __metadata("design:type", String)
85
+ ], AiTestCommand.prototype, "provider", void 0);
86
+ __decorate([
87
+ flags.string({ description: 'Model to test with' }),
88
+ __metadata("design:type", String)
89
+ ], AiTestCommand.prototype, "model", void 0);
90
+ __decorate([
91
+ flags.string({
92
+ name: 'prompt',
93
+ description: 'Test prompt to send',
94
+ default: 'Respond with "PONG" and your model identity in 10 words or less.',
95
+ }),
96
+ __metadata("design:type", String)
97
+ ], AiTestCommand.prototype, "testPrompt", void 0);
98
+ //# sourceMappingURL=ai_test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai_test.js","sourceRoot":"","sources":["../../commands/ai_test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import type { CommandMetaData } from '@adonisjs/core/types/ace';
2
+ import type { BaseCommand } from '@adonisjs/core/ace';
3
+ type CommandClass = typeof BaseCommand;
4
+ /**
5
+ * Ace command loader contract: returns metadata of every command in this package.
6
+ * Metadata is derived from the command classes themselves, so no generated `commands.json` is needed.
7
+ */
8
+ export declare function getMetaData(): Promise<CommandMetaData[]>;
9
+ /**
10
+ * Ace command loader contract: resolves the command class for the given metadata.
11
+ */
12
+ export declare function getCommand(metaData: Pick<CommandMetaData, 'commandName'>): Promise<CommandClass | null>;
13
+ export {};
14
+ //# sourceMappingURL=main.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../commands/main.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAA;AAC/D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAErD,KAAK,YAAY,GAAG,OAAO,WAAW,CAAA;AActC;;;GAGG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC,CAM9D;AAED;;GAEG;AACH,wBAAsB,UAAU,CAAC,QAAQ,EAAE,IAAI,CAAC,eAAe,EAAE,aAAa,CAAC,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAG7G"}
@@ -0,0 +1,31 @@
1
+ const loaders = [
2
+ () => import('./ai_test.js'),
3
+ () => import('./make_agent.js'),
4
+ ];
5
+ let cachedMetaData;
6
+ const cachedCommands = new Map();
7
+ async function loadAll() {
8
+ return Promise.all(loaders.map(async (load) => (await load()).default));
9
+ }
10
+ /**
11
+ * Ace command loader contract: returns metadata of every command in this package.
12
+ * Metadata is derived from the command classes themselves, so no generated `commands.json` is needed.
13
+ */
14
+ export async function getMetaData() {
15
+ if (cachedMetaData)
16
+ return cachedMetaData;
17
+ const commands = await loadAll();
18
+ for (const command of commands)
19
+ cachedCommands.set(command.commandName, command);
20
+ cachedMetaData = commands.map((command) => command.serialize());
21
+ return cachedMetaData;
22
+ }
23
+ /**
24
+ * Ace command loader contract: resolves the command class for the given metadata.
25
+ */
26
+ export async function getCommand(metaData) {
27
+ if (cachedCommands.size === 0)
28
+ await getMetaData();
29
+ return cachedCommands.get(metaData.commandName) ?? null;
30
+ }
31
+ //# sourceMappingURL=main.js.map