adaptive-memory-multi-model-router 2.16.0 → 2.16.2

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 (248) hide show
  1. package/.github/workflows/adapters-ci.yml +142 -0
  2. package/.github/workflows/auto-submit-sitemap.yml +41 -0
  3. package/.github/workflows/ci.yml +2 -5
  4. package/.github/workflows/mcp-pypi-publish.yml +34 -0
  5. package/.github/workflows/pypi-publish.yml +146 -0
  6. package/.github/workflows/tmlpd-publish.yml +23 -0
  7. package/README.md +245 -148
  8. package/RELEASE_v2.16.0.md +149 -0
  9. package/TECHNICAL_README.md +253 -0
  10. package/adapters/README.md +36 -0
  11. package/adapters/__init__.py +25 -0
  12. package/adapters/a3m_adapter/__init__.py +51 -0
  13. package/adapters/a3m_adapter/adapter/__init__.py +22 -0
  14. package/adapters/a3m_adapter/adapter/autogen.py +169 -0
  15. package/adapters/a3m_adapter/adapter/config.py +100 -0
  16. package/adapters/a3m_adapter/adapter/haystack.py +197 -0
  17. package/adapters/a3m_adapter/adapter/langchain.py +155 -0
  18. package/adapters/a3m_adapter/adapter/langgraph.py +196 -0
  19. package/adapters/a3m_adapter/adapter/llamaindex.py +162 -0
  20. package/adapters/a3m_adapter/adapter/pinecone.py +217 -0
  21. package/adapters/a3m_adapter/adapter/vercel.py +188 -0
  22. package/adapters/a3m_adapter/tests/__init__.py +1 -0
  23. package/adapters/a3m_adapter/tests/test_adapters.py +118 -0
  24. package/adapters/a3m_adapter/tests/test_integration.py +80 -0
  25. package/adapters/requirements-dev.txt +6 -0
  26. package/adapters/requirements.txt +4 -0
  27. package/adapters/setup.py +23 -0
  28. package/demo.py +251 -0
  29. package/discoverability-diagnosis.md +280 -0
  30. package/dist/analytics/costAnalytics.d.ts.map +1 -1
  31. package/dist/benchmark/reproducible.d.ts.map +1 -1
  32. package/dist/cache/semanticCache.d.ts.map +1 -1
  33. package/dist/cli/setupWizard.d.ts +257 -50
  34. package/dist/cli/setupWizard.d.ts.map +1 -1
  35. package/dist/cli/setupWizard.js +419 -109
  36. package/dist/cli/setupWizard.js.map +1 -1
  37. package/dist/cli/tui.d.ts +6 -0
  38. package/dist/cli/tui.js +96 -67
  39. package/dist/cli/tui.js.map +1 -0
  40. package/dist/cli.js +9 -0
  41. package/dist/cost/budgetEnforcer.d.ts.map +1 -1
  42. package/dist/cost/costTracker.d.ts.map +1 -1
  43. package/dist/ensemble/multiRoundDialog.d.ts.map +1 -1
  44. package/dist/ensemble/shapleyValue.d.ts.map +1 -1
  45. package/dist/ensemble.d.ts +1 -1
  46. package/dist/ensemble.js +141 -0
  47. package/dist/integrations/langchainAdapter.d.ts.map +1 -1
  48. package/dist/integrations/langchainAdapter.js +3 -3
  49. package/dist/integrations/langchainAdapter.js.map +1 -1
  50. package/dist/integrations/oauth.d.ts.map +1 -1
  51. package/dist/integrations/scienceAdapter.d.ts.map +1 -1
  52. package/dist/memory/autoFetch.d.ts.map +1 -1
  53. package/dist/memory/hybridMemory.d.ts.map +1 -1
  54. package/dist/memory/memoryTree.d.ts.map +1 -1
  55. package/dist/memory/obsidianVault.d.ts.map +1 -1
  56. package/dist/memory/reasoningBank.d.ts.map +1 -1
  57. package/dist/observability/metrics.d.ts.map +1 -1
  58. package/dist/observability/tracer.d.ts.map +1 -1
  59. package/dist/providers/providerConfig.d.ts.map +1 -1
  60. package/dist/providers/providerConfig.js +32 -17
  61. package/dist/providers/providerConfig.js.map +1 -1
  62. package/dist/routing/advancedRouter.d.ts.map +1 -1
  63. package/dist/routing/advancedRouter.js +106 -14
  64. package/dist/routing/advancedRouter.js.map +1 -1
  65. package/dist/routing/providerHealth.d.ts.map +1 -1
  66. package/dist/routing/providerRetry.d.ts.map +1 -1
  67. package/dist/routing/shadowSampler.d.ts.map +1 -0
  68. package/dist/routing/shadowSampler.js.map +1 -1
  69. package/dist/security/guardrails.d.ts.map +1 -1
  70. package/dist/server/handlers/chatHandler.d.ts.map +1 -1
  71. package/dist/server/handlers/completionsHandler.d.ts.map +1 -1
  72. package/dist/server/handlers/embeddingsHandler.d.ts.map +1 -1
  73. package/dist/server/handlers/healthHandler.d.ts.map +1 -1
  74. package/dist/server/handlers/metricsHandler.d.ts.map +1 -1
  75. package/dist/server/handlers/modelsHandler.d.ts.map +1 -1
  76. package/dist/server/metrics.d.ts.map +1 -1
  77. package/dist/server/proxyServer.d.ts.map +1 -1
  78. package/dist/server/router.d.ts.map +1 -1
  79. package/dist/server/state.d.ts.map +1 -1
  80. package/dist/skills/__tests__/skill_manager.test.js +5 -265
  81. package/dist/skills/__tests__/skill_manager.test.js.map +1 -1
  82. package/dist/utils/tokenUtils.d.ts.map +1 -1
  83. package/docker-compose.yml +84 -60
  84. package/docs/ARTICLE_Biology_Inspired_Routing.md +208 -0
  85. package/docs/ARTICLE_Master.md +78 -0
  86. package/docs/ARTICLE_Master_CN.md +78 -0
  87. package/docs/ARTICLE_OpenRouter_Stripe.md +140 -0
  88. package/docs/DEVPTO_ARTICLE.md +84 -0
  89. package/docs/HUMAN_STYLE_GUIDE.md +75 -0
  90. package/docs/IMPRINT_PLAN.md +88 -0
  91. package/docs/OPENROUTER_ALTERNATIVE.md +184 -0
  92. package/docs/SOCIAL_CAMPAIGN.md +316 -0
  93. package/docs/anthropic.html +45 -0
  94. package/docs/best-llm-routers-2025.html +157 -0
  95. package/docs/cerebras.html +43 -0
  96. package/docs/cli-cheatsheet.md +286 -212
  97. package/docs/comparison.md +2 -2
  98. package/docs/deepseek.html +44 -0
  99. package/docs/google.html +47 -0
  100. package/docs/groq.html +44 -0
  101. package/docs/llms-full.txt +360 -138
  102. package/docs/llms.txt +70 -71
  103. package/docs/mistral.html +43 -0
  104. package/docs/ollama.html +50 -0
  105. package/docs/openai.html +57 -0
  106. package/docs/sitemap.xml +69 -57
  107. package/docs-site/blog/best-llm-routers-2025.html +157 -0
  108. package/docs-site/index.html +68 -9
  109. package/docs-site/providers/anthropic.html +45 -0
  110. package/docs-site/providers/cerebras.html +43 -0
  111. package/docs-site/providers/deepseek.html +44 -0
  112. package/docs-site/providers/google.html +47 -0
  113. package/docs-site/providers/groq.html +44 -0
  114. package/docs-site/providers/index.html +41 -0
  115. package/docs-site/providers/mistral.html +43 -0
  116. package/docs-site/providers/ollama.html +50 -0
  117. package/docs-site/providers/openai.html +57 -0
  118. package/docs-site/sitemap.xml +69 -0
  119. package/llms.txt +70 -62
  120. package/package.json +44 -182
  121. package/packages/agentkit-adapter/LICENSE +21 -0
  122. package/packages/agentkit-adapter/README.md +126 -0
  123. package/packages/agentkit-adapter/examples/agentkit-example.ts +139 -0
  124. package/packages/agentkit-adapter/package.json +57 -0
  125. package/packages/agentkit-adapter/src/adapter.ts +381 -0
  126. package/packages/agentkit-adapter/src/index.ts +36 -0
  127. package/packages/agentkit-adapter/src/types.ts +105 -0
  128. package/packages/agentkit-adapter/src/util.ts +13 -0
  129. package/packages/agentkit-adapter/tsconfig.json +22 -0
  130. package/prometheus.yml +8 -0
  131. package/python/README.md +35 -81
  132. package/python/a3m/__init__.py +32 -3
  133. package/python/a3m/adapters/__init__.py +21 -0
  134. package/python/a3m/adapters/langchain.py +190 -0
  135. package/python/a3m/adapters/llamaindex.py +249 -0
  136. package/python/a3m/adapters/qdrant.py +240 -0
  137. package/python/a3m/adapters/weaviate.py +263 -0
  138. package/python/a3m/client.py +5 -0
  139. package/python/build_verify.sh +32 -0
  140. package/python/mcp-server/README.md +172 -0
  141. package/python/mcp-server/a3m_mcp/__init__.py +25 -0
  142. package/python/mcp-server/a3m_mcp/__main__.py +15 -0
  143. package/python/mcp-server/a3m_mcp/server.py +205 -0
  144. package/python/mcp-server/pyproject.toml +24 -0
  145. package/python/pyproject.toml +60 -6
  146. package/python/setup.py +3 -28
  147. package/scripts/submit-sitemap.sh +52 -0
  148. package/src/__types__/registry.d.ts +14 -0
  149. package/src/cli/setupWizard.ts +443 -112
  150. package/src/cli/tui.ts +159 -0
  151. package/src/ensemble.ts +154 -1
  152. package/src/integrations/langchainAdapter.ts +2 -2
  153. package/src/providers/providerConfig.ts +32 -17
  154. package/src/providers/registry.js +27 -0
  155. package/src/routing/advancedRouter.ts +99 -14
  156. package/src/routing/shadowSampler.ts +1 -1
  157. package/test-install/package.json +12 -0
  158. package/tests/tsconfig.json +0 -1
  159. package/tmlpd-pi-extension/README.md +105 -44
  160. package/tmlpd-pi-extension/docs/demo.svg +33 -0
  161. package/tmlpd-pi-extension/package.json +35 -106
  162. package/tmlpd-pi-extension/src/tokenOptimization/contextStratifier.ts +163 -0
  163. package/tmlpd-pi-extension/src/tokenOptimization/fetchOnceLocal.ts +136 -0
  164. package/tmlpd-pi-extension/src/tokenOptimization/index.ts +197 -0
  165. package/tmlpd-pi-extension/src/tokenOptimization/interAgentCompression.ts +157 -0
  166. package/tmlpd-pi-extension/src/tokenOptimization/schemaContract.ts +101 -0
  167. package/tmlpd-pi-extension/src/tokenOptimization/semanticCache.ts +248 -0
  168. package/tmlpd-pi-extension/src/tokenOptimization/tokenAwareFallback.ts +192 -0
  169. package/tmlpd-pi-extension/test/verify.js +21 -0
  170. package/tsconfig.build.json +3 -2
  171. package/packages/a3m-vercel-ai/dist/a3m-language-model.d.ts +0 -12
  172. package/packages/a3m-vercel-ai/dist/a3m-language-model.d.ts.map +0 -1
  173. package/packages/a3m-vercel-ai/dist/a3m-language-model.js +0 -289
  174. package/packages/a3m-vercel-ai/dist/a3m-language-model.js.map +0 -1
  175. package/packages/a3m-vercel-ai/dist/index.d.ts +0 -82
  176. package/packages/a3m-vercel-ai/dist/index.d.ts.map +0 -1
  177. package/packages/a3m-vercel-ai/dist/index.js +0 -79
  178. package/packages/a3m-vercel-ai/dist/index.js.map +0 -1
  179. package/packages/a3m-vercel-ai/dist/types.d.ts +0 -97
  180. package/packages/a3m-vercel-ai/dist/types.d.ts.map +0 -1
  181. package/packages/a3m-vercel-ai/dist/types.js +0 -5
  182. package/packages/a3m-vercel-ai/dist/types.js.map +0 -1
  183. package/src/skills/__tests__/skill_manager.test.ts +0 -328
  184. package/tmlpd-pi-extension/dist/cache/prefixCache.d.ts +0 -114
  185. package/tmlpd-pi-extension/dist/cache/prefixCache.d.ts.map +0 -1
  186. package/tmlpd-pi-extension/dist/cache/prefixCache.js +0 -285
  187. package/tmlpd-pi-extension/dist/cache/prefixCache.js.map +0 -1
  188. package/tmlpd-pi-extension/dist/cache/responseCache.d.ts +0 -58
  189. package/tmlpd-pi-extension/dist/cache/responseCache.d.ts.map +0 -1
  190. package/tmlpd-pi-extension/dist/cache/responseCache.js +0 -153
  191. package/tmlpd-pi-extension/dist/cache/responseCache.js.map +0 -1
  192. package/tmlpd-pi-extension/dist/cli.js +0 -59
  193. package/tmlpd-pi-extension/dist/cost/costTracker.d.ts +0 -95
  194. package/tmlpd-pi-extension/dist/cost/costTracker.d.ts.map +0 -1
  195. package/tmlpd-pi-extension/dist/cost/costTracker.js +0 -240
  196. package/tmlpd-pi-extension/dist/cost/costTracker.js.map +0 -1
  197. package/tmlpd-pi-extension/dist/index.d.ts +0 -723
  198. package/tmlpd-pi-extension/dist/index.d.ts.map +0 -1
  199. package/tmlpd-pi-extension/dist/index.js +0 -239
  200. package/tmlpd-pi-extension/dist/index.js.map +0 -1
  201. package/tmlpd-pi-extension/dist/memory/episodicMemory.d.ts +0 -82
  202. package/tmlpd-pi-extension/dist/memory/episodicMemory.d.ts.map +0 -1
  203. package/tmlpd-pi-extension/dist/memory/episodicMemory.js +0 -145
  204. package/tmlpd-pi-extension/dist/memory/episodicMemory.js.map +0 -1
  205. package/tmlpd-pi-extension/dist/orchestration/haloOrchestrator.d.ts +0 -102
  206. package/tmlpd-pi-extension/dist/orchestration/haloOrchestrator.d.ts.map +0 -1
  207. package/tmlpd-pi-extension/dist/orchestration/haloOrchestrator.js +0 -207
  208. package/tmlpd-pi-extension/dist/orchestration/haloOrchestrator.js.map +0 -1
  209. package/tmlpd-pi-extension/dist/orchestration/mctsWorkflow.d.ts +0 -85
  210. package/tmlpd-pi-extension/dist/orchestration/mctsWorkflow.d.ts.map +0 -1
  211. package/tmlpd-pi-extension/dist/orchestration/mctsWorkflow.js +0 -210
  212. package/tmlpd-pi-extension/dist/orchestration/mctsWorkflow.js.map +0 -1
  213. package/tmlpd-pi-extension/dist/providers/localProvider.d.ts +0 -102
  214. package/tmlpd-pi-extension/dist/providers/localProvider.d.ts.map +0 -1
  215. package/tmlpd-pi-extension/dist/providers/localProvider.js +0 -338
  216. package/tmlpd-pi-extension/dist/providers/localProvider.js.map +0 -1
  217. package/tmlpd-pi-extension/dist/providers/registry.d.ts +0 -55
  218. package/tmlpd-pi-extension/dist/providers/registry.d.ts.map +0 -1
  219. package/tmlpd-pi-extension/dist/providers/registry.js +0 -138
  220. package/tmlpd-pi-extension/dist/providers/registry.js.map +0 -1
  221. package/tmlpd-pi-extension/dist/routing/advancedRouter.d.ts +0 -68
  222. package/tmlpd-pi-extension/dist/routing/advancedRouter.d.ts.map +0 -1
  223. package/tmlpd-pi-extension/dist/routing/advancedRouter.js +0 -332
  224. package/tmlpd-pi-extension/dist/routing/advancedRouter.js.map +0 -1
  225. package/tmlpd-pi-extension/dist/tools/tmlpdTools.d.ts +0 -101
  226. package/tmlpd-pi-extension/dist/tools/tmlpdTools.d.ts.map +0 -1
  227. package/tmlpd-pi-extension/dist/tools/tmlpdTools.js +0 -368
  228. package/tmlpd-pi-extension/dist/tools/tmlpdTools.js.map +0 -1
  229. package/tmlpd-pi-extension/dist/utils/batchProcessor.d.ts +0 -96
  230. package/tmlpd-pi-extension/dist/utils/batchProcessor.d.ts.map +0 -1
  231. package/tmlpd-pi-extension/dist/utils/batchProcessor.js +0 -170
  232. package/tmlpd-pi-extension/dist/utils/batchProcessor.js.map +0 -1
  233. package/tmlpd-pi-extension/dist/utils/compression.d.ts +0 -61
  234. package/tmlpd-pi-extension/dist/utils/compression.d.ts.map +0 -1
  235. package/tmlpd-pi-extension/dist/utils/compression.js +0 -281
  236. package/tmlpd-pi-extension/dist/utils/compression.js.map +0 -1
  237. package/tmlpd-pi-extension/dist/utils/reliability.d.ts +0 -74
  238. package/tmlpd-pi-extension/dist/utils/reliability.d.ts.map +0 -1
  239. package/tmlpd-pi-extension/dist/utils/reliability.js +0 -177
  240. package/tmlpd-pi-extension/dist/utils/reliability.js.map +0 -1
  241. package/tmlpd-pi-extension/dist/utils/speculativeDecoding.d.ts +0 -117
  242. package/tmlpd-pi-extension/dist/utils/speculativeDecoding.d.ts.map +0 -1
  243. package/tmlpd-pi-extension/dist/utils/speculativeDecoding.js +0 -246
  244. package/tmlpd-pi-extension/dist/utils/speculativeDecoding.js.map +0 -1
  245. package/tmlpd-pi-extension/dist/utils/tokenUtils.d.ts +0 -50
  246. package/tmlpd-pi-extension/dist/utils/tokenUtils.d.ts.map +0 -1
  247. package/tmlpd-pi-extension/dist/utils/tokenUtils.js +0 -124
  248. package/tmlpd-pi-extension/dist/utils/tokenUtils.js.map +0 -1
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "@a3m/agentkit-adapter",
3
+ "version": "1.0.0",
4
+ "description": "A3M Router adapter for AgentKit - enables AI agents with intelligent multi-provider routing",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "module": "dist/index.mjs",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.mjs",
12
+ "require": "./dist/index.js"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist"
17
+ ],
18
+ "scripts": {
19
+ "build": "tsup src/index.ts --format cjs,esm --dts --clean",
20
+ "dev": "tsup src/index.ts --format cjs,esm --dts --watch",
21
+ "test": "vitest",
22
+ "lint": "eslint src/",
23
+ "prepublishOnly": "npm run build"
24
+ },
25
+ "keywords": [
26
+ "agentkit",
27
+ "a3m",
28
+ "router",
29
+ "llm",
30
+ "multi-provider",
31
+ "ai",
32
+ "agent",
33
+ "openai",
34
+ "anthropic",
35
+ "routing"
36
+ ],
37
+ "author": "",
38
+ "license": "MIT",
39
+ "peerDependencies": {
40
+ "@inngest/agent-kit": ">=0.0.1"
41
+ },
42
+ "dependencies": {
43
+ "@inngest/ai": ">=0.1.0",
44
+ "zod": "^3.22.4"
45
+ },
46
+ "devDependencies": {
47
+ "@inngest/agent-kit": "^0.13.0",
48
+ "@types/node": "^20.10.0",
49
+ "tsup": "^8.0.0",
50
+ "typescript": "^5.3.0",
51
+ "vitest": "^1.0.0"
52
+ },
53
+ "repository": {
54
+ "type": "git",
55
+ "url": "https://github.com/Das-rebel/adaptive-memory-multi-model-router"
56
+ }
57
+ }
@@ -0,0 +1,381 @@
1
+ /**
2
+ * A3M Router AgentKit Adapter
3
+ *
4
+ * Wraps A3M Router as an AgentKit-compatible LLM backend.
5
+ * Supports tool calling, streaming, and parallel ensemble mode.
6
+ */
7
+
8
+ import { type AiAdapter } from "@inngest/ai";
9
+ import { z } from "zod";
10
+ import { stringifyError } from "./util";
11
+ import type {
12
+ A3MConfig,
13
+ A3MInferenceOptions,
14
+ A3MMessage,
15
+ A3MTool,
16
+ A3MStreamChunk,
17
+ A3MToolCall,
18
+ } from "./types";
19
+
20
+ /**
21
+ * A3M Router adapter for AgentKit
22
+ */
23
+ export class A3MAdapter {
24
+ private config: Required<A3MConfig>;
25
+ private format: AiAdapter.Format = "openai-chat";
26
+ private url: string;
27
+ private authKey: string = "";
28
+
29
+ constructor(config: A3MConfig = {}) {
30
+ this.config = {
31
+ baseUrl: config.baseUrl || "http://localhost:8787",
32
+ apiKey: config.apiKey || "",
33
+ defaultModel: config.defaultModel || "",
34
+ parallel: config.parallel ?? false,
35
+ temperature: config.temperature ?? 0.7,
36
+ maxTokens: config.maxTokens ?? 4096,
37
+ headers: config.headers || {},
38
+ };
39
+ this.url = `${this.config.baseUrl}/v1/chat/completions`;
40
+ this.authKey = this.config.apiKey;
41
+ }
42
+
43
+ /**
44
+ * Get the adapter format
45
+ */
46
+ getFormat(): AiAdapter.Format {
47
+ return this.format;
48
+ }
49
+
50
+ /**
51
+ * Get adapter options (required by AgentKit)
52
+ */
53
+ getOptions(): AiAdapter.Any["options"] {
54
+ return {
55
+ model: this.config.defaultModel || "auto",
56
+ apiKey: this.config.apiKey,
57
+ baseUrl: this.config.baseUrl,
58
+ } as AiAdapter.Any["options"];
59
+ }
60
+
61
+ /**
62
+ * Convert AgentKit messages to A3M format
63
+ */
64
+ private convertMessages(messages: Array<{
65
+ type: string;
66
+ role?: string;
67
+ content?: string;
68
+ tool?: { id?: string; name?: string };
69
+ tools?: unknown[];
70
+ }>): A3MMessage[] {
71
+ return messages.map((m) => {
72
+ if (m.type === "tool_result") {
73
+ return {
74
+ role: "tool" as const,
75
+ content: typeof m.content === "string" ? m.content : JSON.stringify(m.content),
76
+ toolCallId: m.tool?.id,
77
+ };
78
+ }
79
+ if (m.type === "tool_call") {
80
+ // Tool calls are handled separately
81
+ return {
82
+ role: "assistant" as const,
83
+ content: "",
84
+ };
85
+ }
86
+ return {
87
+ role: (m.role as "user" | "assistant" | "system") || "user",
88
+ content: m.content || "",
89
+ };
90
+ }).filter((m) => m.content || m.role === "system");
91
+ }
92
+
93
+ /**
94
+ * Convert AgentKit tools to A3M/OpenAI format
95
+ */
96
+ private convertTools(tools: Array<{
97
+ name: string;
98
+ description?: string;
99
+ parameters?: z.ZodType<unknown>;
100
+ strict?: boolean;
101
+ }>) {
102
+ return tools.map((t) => ({
103
+ type: "function",
104
+ function: {
105
+ name: t.name,
106
+ description: t.description || "",
107
+ parameters: t.parameters ? z.toJSONSchema(t.parameters, { target: "draft-7" }) : undefined,
108
+ strict: t.strict ?? Boolean(t.parameters),
109
+ },
110
+ }));
111
+ }
112
+
113
+ /**
114
+ * Parse A3M/OpenAI response to AgentKit messages
115
+ */
116
+ private parseResponse(input: Record<string, unknown>): Array<{
117
+ type: string;
118
+ role?: string;
119
+ content?: string;
120
+ tools?: A3MToolCall[];
121
+ stop_reason?: string;
122
+ }> {
123
+ const result: Array<{
124
+ type: string;
125
+ role?: string;
126
+ content?: string;
127
+ tools?: A3MToolCall[];
128
+ stop_reason?: string;
129
+ }> = [];
130
+
131
+ if (input.error) {
132
+ throw new Error(`A3M request failed: ${JSON.stringify(input.error)}`);
133
+ }
134
+
135
+ const choices = (input.choices as Array<Record<string, unknown>>) || [];
136
+
137
+ for (const choice of choices) {
138
+ const message = choice.message as Record<string, unknown> || {};
139
+ const finishReason = choice.finish_reason as string || "stop";
140
+
141
+ // Text content
142
+ if (message.content && (message.content as string).trim()) {
143
+ result.push({
144
+ type: "text",
145
+ role: message.role as string,
146
+ content: message.content as string,
147
+ stop_reason: finishReason,
148
+ });
149
+ }
150
+
151
+ // Tool calls
152
+ const toolCalls = message.tool_calls as Array<Record<string, unknown>> || [];
153
+ if (toolCalls.length > 0) {
154
+ result.push({
155
+ type: "tool_call",
156
+ role: message.role as string,
157
+ tools: toolCalls.map((tc) => ({
158
+ id: tc.id as string,
159
+ name: (tc.function as Record<string, string>)?.name || "",
160
+ arguments: JSON.parse((tc.function as Record<string, string>)?.arguments || "{}"),
161
+ })),
162
+ stop_reason: "tool",
163
+ });
164
+ }
165
+ }
166
+
167
+ return result;
168
+ }
169
+
170
+ /**
171
+ * Run inference through A3M Router
172
+ */
173
+ async infer(
174
+ stepID: string,
175
+ messages: Array<{
176
+ type: string;
177
+ role?: string;
178
+ content?: string;
179
+ tool?: { id?: string; name?: string };
180
+ tools?: unknown[];
181
+ }>,
182
+ tools: Array<{
183
+ name: string;
184
+ description?: string;
185
+ parameters?: z.ZodType<unknown>;
186
+ strict?: boolean;
187
+ }>,
188
+ toolChoice: "auto" | "none" | { type: "function"; function: { name: string } } = "auto",
189
+ options: A3MInferenceOptions = {}
190
+ ): Promise<{
191
+ output: Array<{ type: string; role?: string; content?: string; tools?: A3MToolCall[]; stop_reason?: string }>;
192
+ raw: Record<string, unknown>;
193
+ }> {
194
+ const body: Record<string, unknown> = {
195
+ model: options.model || this.config.defaultModel || "auto",
196
+ messages: this.convertMessages(messages),
197
+ temperature: options.temperature ?? this.config.temperature,
198
+ max_tokens: options.maxTokens ?? this.config.maxTokens,
199
+ };
200
+
201
+ if (tools.length > 0) {
202
+ body.tools = this.convertTools(tools);
203
+ if (toolChoice === "auto") {
204
+ body.tool_choice = "auto";
205
+ } else if (toolChoice === "none") {
206
+ body.tool_choice = "none";
207
+ } else if (toolChoice && typeof toolChoice === "object") {
208
+ body.tool_choice = {
209
+ type: "function",
210
+ function: { name: toolChoice.function.name },
211
+ };
212
+ }
213
+ }
214
+
215
+ if (options.provider) {
216
+ body.provider = options.provider;
217
+ }
218
+
219
+ if (options.stop) {
220
+ body.stop = options.stop;
221
+ }
222
+
223
+ // Parallel ensemble mode
224
+ if (options.parallel ?? this.config.parallel) {
225
+ body.parallel = true;
226
+ }
227
+
228
+ const headers: Record<string, string> = {
229
+ "Content-Type": "application/json",
230
+ ...this.config.headers,
231
+ };
232
+
233
+ if (this.authKey) {
234
+ headers["Authorization"] = `Bearer ${this.authKey}`;
235
+ }
236
+
237
+ try {
238
+ const response = await fetch(this.url, {
239
+ method: "POST",
240
+ headers,
241
+ body: JSON.stringify(body),
242
+ });
243
+
244
+ if (!response.ok) {
245
+ throw new Error(`A3M request failed: ${response.status} ${response.statusText}`);
246
+ }
247
+
248
+ const result = (await response.json()) as Record<string, unknown>;
249
+ return {
250
+ output: this.parseResponse(result),
251
+ raw: result,
252
+ };
253
+ } catch (err) {
254
+ throw new Error(`A3M inference error: ${stringifyError(err)}`);
255
+ }
256
+ }
257
+
258
+ /**
259
+ * Stream inference through A3M Router
260
+ */
261
+ async *stream(
262
+ messages: A3MMessage[],
263
+ tools: A3MTool[] = [],
264
+ options: A3MInferenceOptions = {}
265
+ ): AsyncGenerator<A3MStreamChunk> {
266
+ const body: Record<string, unknown> = {
267
+ model: options.model || this.config.defaultModel || "auto",
268
+ messages,
269
+ temperature: options.temperature ?? this.config.temperature,
270
+ max_tokens: options.maxTokens ?? this.config.maxTokens,
271
+ stream: true,
272
+ };
273
+
274
+ if (tools.length > 0) {
275
+ body.tools = this.convertTools(tools);
276
+ body.tool_choice = "auto";
277
+ }
278
+
279
+ if (options.provider) {
280
+ body.provider = options.provider;
281
+ }
282
+
283
+ const headers: Record<string, string> = {
284
+ "Content-Type": "application/json",
285
+ ...this.config.headers,
286
+ };
287
+
288
+ if (this.authKey) {
289
+ headers["Authorization"] = `Bearer ${this.authKey}`;
290
+ }
291
+
292
+ try {
293
+ const response = await fetch(this.url, {
294
+ method: "POST",
295
+ headers,
296
+ body: JSON.stringify(body),
297
+ });
298
+
299
+ if (!response.ok) {
300
+ throw new Error(`A3M stream failed: ${response.status} ${response.statusText}`);
301
+ }
302
+
303
+ if (!response.body) {
304
+ throw new Error("A3M stream: no response body");
305
+ }
306
+
307
+ const reader = response.body.getReader();
308
+ const decoder = new TextDecoder();
309
+ let buffer = "";
310
+
311
+ while (true) {
312
+ const { done, value } = await reader.read();
313
+ if (done) break;
314
+
315
+ buffer += decoder.decode(value, { stream: true });
316
+ const lines = buffer.split("\n");
317
+ buffer = lines.pop() || "";
318
+
319
+ for (const line of lines) {
320
+ const trimmed = line.trim();
321
+ if (!trimmed || !trimmed.startsWith("data: ")) continue;
322
+
323
+ const data = trimmed.slice(6);
324
+ if (data === "[DONE]") {
325
+ yield { type: "done" };
326
+ return;
327
+ }
328
+
329
+ try {
330
+ const chunk = JSON.parse(data) as Record<string, unknown>;
331
+ const delta = chunk.choices?.[0]?.delta as Record<string, unknown>;
332
+
333
+ if (delta?.content) {
334
+ yield { type: "text", content: delta.content as string };
335
+ }
336
+
337
+ if (delta?.tool_calls) {
338
+ for (const tc of delta.tool_calls as Array<Record<string, unknown>>) {
339
+ yield {
340
+ type: "tool_call",
341
+ toolCall: {
342
+ id: tc.id as string,
343
+ name: (tc.function as Record<string, string>)?.name || "",
344
+ arguments: JSON.parse((tc.function as Record<string, string>)?.arguments || "{}"),
345
+ },
346
+ };
347
+ }
348
+ }
349
+ } catch {
350
+ // Skip malformed JSON
351
+ }
352
+ }
353
+ }
354
+
355
+ yield { type: "done" };
356
+ } catch (err) {
357
+ yield { type: "error", error: stringifyError(err) };
358
+ }
359
+ }
360
+
361
+ /**
362
+ * Check if A3M Router is available
363
+ */
364
+ async healthCheck(): Promise<boolean> {
365
+ try {
366
+ const response = await fetch(`${this.config.baseUrl}/health`, {
367
+ method: "GET",
368
+ });
369
+ return response.ok;
370
+ } catch {
371
+ return false;
372
+ }
373
+ }
374
+ }
375
+
376
+ /**
377
+ * Create an A3M adapter with default settings
378
+ */
379
+ export function createA3MAdapter(config?: A3MConfig): A3MAdapter {
380
+ return new A3MAdapter(config);
381
+ }
@@ -0,0 +1,36 @@
1
+ /**
2
+ * A3M Router AgentKit Adapter
3
+ *
4
+ * @example
5
+ * ```typescript
6
+ * import { createAgenticModelFromAiAdapter } from "@inngest/agent-kit";
7
+ * import { createA3MAdapter } from "@a3m/agentkit-adapter";
8
+ *
9
+ * // Create A3M adapter
10
+ * const a3m = createA3MAdapter({
11
+ * baseUrl: "http://localhost:8787",
12
+ * parallel: true, // Enable parallel ensemble mode
13
+ * });
14
+ *
15
+ * // Wrap as AgentKit model
16
+ * const model = createAgenticModelFromAiAdapter(a3m as unknown as AiAdapter.Any);
17
+ *
18
+ * // Use with AgentKit agent
19
+ * const agent = new Agent({
20
+ * model,
21
+ * tools: [/* your tools *\/],
22
+ * });
23
+ * ```
24
+ */
25
+
26
+ export { A3MAdapter, createA3MAdapter } from "./adapter";
27
+ export type {
28
+ A3MConfig,
29
+ A3MInferenceOptions,
30
+ A3MMessage,
31
+ A3MTool,
32
+ A3MToolCall,
33
+ A3MStreamChunk,
34
+ A3MResponse,
35
+ ToolChoice,
36
+ } from "./types";
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Types for A3M Router AgentKit Adapter
3
+ */
4
+
5
+ import { z } from "zod";
6
+
7
+ /**
8
+ * Configuration for A3M Router
9
+ */
10
+ export interface A3MConfig {
11
+ /** A3M Router base URL (default: http://localhost:8787) */
12
+ baseUrl?: string;
13
+ /** API key for A3M Router (if required) */
14
+ apiKey?: string;
15
+ /** Default model to use (optional - A3M will route automatically) */
16
+ defaultModel?: string;
17
+ /** Enable parallel ensemble mode */
18
+ parallel?: boolean;
19
+ /** Temperature for generation (0-2) */
20
+ temperature?: number;
21
+ /** Maximum tokens to generate */
22
+ maxTokens?: number;
23
+ /** Additional headers to send with each request */
24
+ headers?: Record<string, string>;
25
+ }
26
+
27
+ /**
28
+ * A3M-specific options for inference
29
+ */
30
+ export interface A3MInferenceOptions {
31
+ /** Override the model for this call */
32
+ model?: string;
33
+ /** Enable parallel ensemble for this call */
34
+ parallel?: boolean;
35
+ /** Temperature (0-2) */
36
+ temperature?: number;
37
+ /** Maximum tokens */
38
+ maxTokens?: number;
39
+ /** Provider to use (bypass routing) */
40
+ provider?: string;
41
+ /** Stop sequences */
42
+ stop?: string[];
43
+ /** Retry on failure */
44
+ retry?: boolean;
45
+ }
46
+
47
+ /**
48
+ * Message format compatible with AgentKit
49
+ */
50
+ export interface A3MMessage {
51
+ role: "user" | "assistant" | "system" | "tool";
52
+ content: string;
53
+ name?: string;
54
+ toolCallId?: string;
55
+ }
56
+
57
+ /**
58
+ * Tool call format for A3M
59
+ */
60
+ export interface A3MToolCall {
61
+ id: string;
62
+ name: string;
63
+ arguments: Record<string, unknown>;
64
+ }
65
+
66
+ /**
67
+ * Tool definition for A3M
68
+ */
69
+ export interface A3MTool {
70
+ name: string;
71
+ description: string;
72
+ parameters?: z.ZodType<unknown>;
73
+ strict?: boolean;
74
+ }
75
+
76
+ /**
77
+ * Streaming chunk from A3M
78
+ */
79
+ export interface A3MStreamChunk {
80
+ type: "text" | "tool_call" | "done" | "error";
81
+ content?: string;
82
+ toolCall?: A3MToolCall;
83
+ error?: string;
84
+ }
85
+
86
+ /**
87
+ * Response from A3M inference
88
+ */
89
+ export interface A3MResponse {
90
+ content: string;
91
+ toolCalls?: A3MToolCall[];
92
+ model?: string;
93
+ provider?: string;
94
+ usage?: {
95
+ promptTokens: number;
96
+ completionTokens: number;
97
+ totalTokens: number;
98
+ };
99
+ finishReason?: "stop" | "length" | "tool_calls" | "content_filter";
100
+ }
101
+
102
+ /**
103
+ * Tool choice options
104
+ */
105
+ export type ToolChoice = "auto" | "none" | { type: "function"; function: { name: string } };
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Utility functions
3
+ */
4
+
5
+ export const stringifyError = (err: unknown): string => {
6
+ if (err instanceof Error) {
7
+ return err.message;
8
+ }
9
+ if (typeof err === "string") {
10
+ return err;
11
+ }
12
+ return JSON.stringify(err);
13
+ };
@@ -0,0 +1,22 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "bundler",
6
+ "lib": ["ES2022"],
7
+ "declaration": true,
8
+ "declarationMap": true,
9
+ "sourceMap": true,
10
+ "outDir": "./dist",
11
+ "rootDir": "./src",
12
+ "strict": true,
13
+ "esModuleInterop": true,
14
+ "skipLibCheck": true,
15
+ "forceConsistentCasingInFileNames": true,
16
+ "resolveJsonModule": true,
17
+ "isolatedModules": true,
18
+ "noEmit": false
19
+ },
20
+ "include": ["src/**/*"],
21
+ "exclude": ["node_modules", "dist", "examples"]
22
+ }
package/prometheus.yml ADDED
@@ -0,0 +1,8 @@
1
+ global:
2
+ scrape_interval: 15s
3
+
4
+ scrape_configs:
5
+ - job_name: 'a3m-router'
6
+ static_configs:
7
+ - targets: ['a3m-router:8787']
8
+ metrics_path: /metrics