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

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 (245) 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.js +96 -67
  38. package/dist/cli.js +9 -0
  39. package/dist/cost/budgetEnforcer.d.ts.map +1 -1
  40. package/dist/cost/costTracker.d.ts.map +1 -1
  41. package/dist/ensemble/multiRoundDialog.d.ts.map +1 -1
  42. package/dist/ensemble/shapleyValue.d.ts.map +1 -1
  43. package/dist/ensemble.d.ts +1 -1
  44. package/dist/ensemble.js +141 -0
  45. package/dist/integrations/langchainAdapter.d.ts.map +1 -1
  46. package/dist/integrations/langchainAdapter.js +3 -3
  47. package/dist/integrations/langchainAdapter.js.map +1 -1
  48. package/dist/integrations/oauth.d.ts.map +1 -1
  49. package/dist/integrations/scienceAdapter.d.ts.map +1 -1
  50. package/dist/memory/autoFetch.d.ts.map +1 -1
  51. package/dist/memory/hybridMemory.d.ts.map +1 -1
  52. package/dist/memory/memoryTree.d.ts.map +1 -1
  53. package/dist/memory/obsidianVault.d.ts.map +1 -1
  54. package/dist/memory/reasoningBank.d.ts.map +1 -1
  55. package/dist/observability/metrics.d.ts.map +1 -1
  56. package/dist/observability/tracer.d.ts.map +1 -1
  57. package/dist/providers/providerConfig.d.ts.map +1 -1
  58. package/dist/providers/providerConfig.js +32 -17
  59. package/dist/providers/providerConfig.js.map +1 -1
  60. package/dist/routing/advancedRouter.d.ts.map +1 -1
  61. package/dist/routing/advancedRouter.js +106 -14
  62. package/dist/routing/advancedRouter.js.map +1 -1
  63. package/dist/routing/providerHealth.d.ts.map +1 -1
  64. package/dist/routing/providerRetry.d.ts.map +1 -1
  65. package/dist/routing/shadowSampler.js.map +1 -1
  66. package/dist/security/guardrails.d.ts.map +1 -1
  67. package/dist/server/handlers/chatHandler.d.ts.map +1 -1
  68. package/dist/server/handlers/completionsHandler.d.ts.map +1 -1
  69. package/dist/server/handlers/embeddingsHandler.d.ts.map +1 -1
  70. package/dist/server/handlers/healthHandler.d.ts.map +1 -1
  71. package/dist/server/handlers/metricsHandler.d.ts.map +1 -1
  72. package/dist/server/handlers/modelsHandler.d.ts.map +1 -1
  73. package/dist/server/metrics.d.ts.map +1 -1
  74. package/dist/server/proxyServer.d.ts.map +1 -1
  75. package/dist/server/router.d.ts.map +1 -1
  76. package/dist/server/state.d.ts.map +1 -1
  77. package/dist/skills/__tests__/skill_manager.test.js +5 -265
  78. package/dist/skills/__tests__/skill_manager.test.js.map +1 -1
  79. package/dist/utils/tokenUtils.d.ts.map +1 -1
  80. package/docker-compose.yml +84 -60
  81. package/docs/ARTICLE_Biology_Inspired_Routing.md +208 -0
  82. package/docs/ARTICLE_Master.md +78 -0
  83. package/docs/ARTICLE_Master_CN.md +78 -0
  84. package/docs/ARTICLE_OpenRouter_Stripe.md +140 -0
  85. package/docs/DEVPTO_ARTICLE.md +84 -0
  86. package/docs/HUMAN_STYLE_GUIDE.md +75 -0
  87. package/docs/IMPRINT_PLAN.md +88 -0
  88. package/docs/OPENROUTER_ALTERNATIVE.md +184 -0
  89. package/docs/SOCIAL_CAMPAIGN.md +316 -0
  90. package/docs/anthropic.html +45 -0
  91. package/docs/best-llm-routers-2025.html +157 -0
  92. package/docs/cerebras.html +43 -0
  93. package/docs/cli-cheatsheet.md +286 -212
  94. package/docs/comparison.md +2 -2
  95. package/docs/deepseek.html +44 -0
  96. package/docs/google.html +47 -0
  97. package/docs/groq.html +44 -0
  98. package/docs/llms-full.txt +360 -138
  99. package/docs/llms.txt +70 -71
  100. package/docs/mistral.html +43 -0
  101. package/docs/ollama.html +50 -0
  102. package/docs/openai.html +57 -0
  103. package/docs/sitemap.xml +69 -57
  104. package/docs-site/blog/best-llm-routers-2025.html +157 -0
  105. package/docs-site/index.html +68 -9
  106. package/docs-site/providers/anthropic.html +45 -0
  107. package/docs-site/providers/cerebras.html +43 -0
  108. package/docs-site/providers/deepseek.html +44 -0
  109. package/docs-site/providers/google.html +47 -0
  110. package/docs-site/providers/groq.html +44 -0
  111. package/docs-site/providers/index.html +41 -0
  112. package/docs-site/providers/mistral.html +43 -0
  113. package/docs-site/providers/ollama.html +50 -0
  114. package/docs-site/providers/openai.html +57 -0
  115. package/docs-site/sitemap.xml +69 -0
  116. package/llms.txt +70 -62
  117. package/package.json +44 -182
  118. package/packages/agentkit-adapter/LICENSE +21 -0
  119. package/packages/agentkit-adapter/README.md +126 -0
  120. package/packages/agentkit-adapter/examples/agentkit-example.ts +139 -0
  121. package/packages/agentkit-adapter/package.json +57 -0
  122. package/packages/agentkit-adapter/src/adapter.ts +381 -0
  123. package/packages/agentkit-adapter/src/index.ts +36 -0
  124. package/packages/agentkit-adapter/src/types.ts +105 -0
  125. package/packages/agentkit-adapter/src/util.ts +13 -0
  126. package/packages/agentkit-adapter/tsconfig.json +22 -0
  127. package/prometheus.yml +8 -0
  128. package/python/README.md +35 -81
  129. package/python/a3m/__init__.py +32 -3
  130. package/python/a3m/adapters/__init__.py +21 -0
  131. package/python/a3m/adapters/langchain.py +190 -0
  132. package/python/a3m/adapters/llamaindex.py +249 -0
  133. package/python/a3m/adapters/qdrant.py +240 -0
  134. package/python/a3m/adapters/weaviate.py +263 -0
  135. package/python/a3m/client.py +5 -0
  136. package/python/build_verify.sh +32 -0
  137. package/python/mcp-server/README.md +172 -0
  138. package/python/mcp-server/a3m_mcp/__init__.py +25 -0
  139. package/python/mcp-server/a3m_mcp/__main__.py +15 -0
  140. package/python/mcp-server/a3m_mcp/server.py +205 -0
  141. package/python/mcp-server/pyproject.toml +24 -0
  142. package/python/pyproject.toml +60 -6
  143. package/python/setup.py +3 -28
  144. package/scripts/submit-sitemap.sh +52 -0
  145. package/src/__types__/registry.d.ts +14 -0
  146. package/src/cli/setupWizard.ts +443 -112
  147. package/src/cli/tui.ts +159 -0
  148. package/src/ensemble.ts +154 -1
  149. package/src/integrations/langchainAdapter.ts +2 -2
  150. package/src/providers/providerConfig.ts +32 -17
  151. package/src/providers/registry.js +27 -0
  152. package/src/routing/advancedRouter.ts +99 -14
  153. package/src/routing/shadowSampler.ts +1 -1
  154. package/test-install/package.json +12 -0
  155. package/tests/tsconfig.json +0 -1
  156. package/tmlpd-pi-extension/README.md +105 -44
  157. package/tmlpd-pi-extension/docs/demo.svg +33 -0
  158. package/tmlpd-pi-extension/package.json +35 -106
  159. package/tmlpd-pi-extension/src/tokenOptimization/contextStratifier.ts +163 -0
  160. package/tmlpd-pi-extension/src/tokenOptimization/fetchOnceLocal.ts +136 -0
  161. package/tmlpd-pi-extension/src/tokenOptimization/index.ts +197 -0
  162. package/tmlpd-pi-extension/src/tokenOptimization/interAgentCompression.ts +157 -0
  163. package/tmlpd-pi-extension/src/tokenOptimization/schemaContract.ts +101 -0
  164. package/tmlpd-pi-extension/src/tokenOptimization/semanticCache.ts +248 -0
  165. package/tmlpd-pi-extension/src/tokenOptimization/tokenAwareFallback.ts +192 -0
  166. package/tmlpd-pi-extension/test/verify.js +21 -0
  167. package/tsconfig.build.json +3 -2
  168. package/packages/a3m-vercel-ai/dist/a3m-language-model.d.ts +0 -12
  169. package/packages/a3m-vercel-ai/dist/a3m-language-model.d.ts.map +0 -1
  170. package/packages/a3m-vercel-ai/dist/a3m-language-model.js +0 -289
  171. package/packages/a3m-vercel-ai/dist/a3m-language-model.js.map +0 -1
  172. package/packages/a3m-vercel-ai/dist/index.d.ts +0 -82
  173. package/packages/a3m-vercel-ai/dist/index.d.ts.map +0 -1
  174. package/packages/a3m-vercel-ai/dist/index.js +0 -79
  175. package/packages/a3m-vercel-ai/dist/index.js.map +0 -1
  176. package/packages/a3m-vercel-ai/dist/types.d.ts +0 -97
  177. package/packages/a3m-vercel-ai/dist/types.d.ts.map +0 -1
  178. package/packages/a3m-vercel-ai/dist/types.js +0 -5
  179. package/packages/a3m-vercel-ai/dist/types.js.map +0 -1
  180. package/src/skills/__tests__/skill_manager.test.ts +0 -328
  181. package/tmlpd-pi-extension/dist/cache/prefixCache.d.ts +0 -114
  182. package/tmlpd-pi-extension/dist/cache/prefixCache.d.ts.map +0 -1
  183. package/tmlpd-pi-extension/dist/cache/prefixCache.js +0 -285
  184. package/tmlpd-pi-extension/dist/cache/prefixCache.js.map +0 -1
  185. package/tmlpd-pi-extension/dist/cache/responseCache.d.ts +0 -58
  186. package/tmlpd-pi-extension/dist/cache/responseCache.d.ts.map +0 -1
  187. package/tmlpd-pi-extension/dist/cache/responseCache.js +0 -153
  188. package/tmlpd-pi-extension/dist/cache/responseCache.js.map +0 -1
  189. package/tmlpd-pi-extension/dist/cli.js +0 -59
  190. package/tmlpd-pi-extension/dist/cost/costTracker.d.ts +0 -95
  191. package/tmlpd-pi-extension/dist/cost/costTracker.d.ts.map +0 -1
  192. package/tmlpd-pi-extension/dist/cost/costTracker.js +0 -240
  193. package/tmlpd-pi-extension/dist/cost/costTracker.js.map +0 -1
  194. package/tmlpd-pi-extension/dist/index.d.ts +0 -723
  195. package/tmlpd-pi-extension/dist/index.d.ts.map +0 -1
  196. package/tmlpd-pi-extension/dist/index.js +0 -239
  197. package/tmlpd-pi-extension/dist/index.js.map +0 -1
  198. package/tmlpd-pi-extension/dist/memory/episodicMemory.d.ts +0 -82
  199. package/tmlpd-pi-extension/dist/memory/episodicMemory.d.ts.map +0 -1
  200. package/tmlpd-pi-extension/dist/memory/episodicMemory.js +0 -145
  201. package/tmlpd-pi-extension/dist/memory/episodicMemory.js.map +0 -1
  202. package/tmlpd-pi-extension/dist/orchestration/haloOrchestrator.d.ts +0 -102
  203. package/tmlpd-pi-extension/dist/orchestration/haloOrchestrator.d.ts.map +0 -1
  204. package/tmlpd-pi-extension/dist/orchestration/haloOrchestrator.js +0 -207
  205. package/tmlpd-pi-extension/dist/orchestration/haloOrchestrator.js.map +0 -1
  206. package/tmlpd-pi-extension/dist/orchestration/mctsWorkflow.d.ts +0 -85
  207. package/tmlpd-pi-extension/dist/orchestration/mctsWorkflow.d.ts.map +0 -1
  208. package/tmlpd-pi-extension/dist/orchestration/mctsWorkflow.js +0 -210
  209. package/tmlpd-pi-extension/dist/orchestration/mctsWorkflow.js.map +0 -1
  210. package/tmlpd-pi-extension/dist/providers/localProvider.d.ts +0 -102
  211. package/tmlpd-pi-extension/dist/providers/localProvider.d.ts.map +0 -1
  212. package/tmlpd-pi-extension/dist/providers/localProvider.js +0 -338
  213. package/tmlpd-pi-extension/dist/providers/localProvider.js.map +0 -1
  214. package/tmlpd-pi-extension/dist/providers/registry.d.ts +0 -55
  215. package/tmlpd-pi-extension/dist/providers/registry.d.ts.map +0 -1
  216. package/tmlpd-pi-extension/dist/providers/registry.js +0 -138
  217. package/tmlpd-pi-extension/dist/providers/registry.js.map +0 -1
  218. package/tmlpd-pi-extension/dist/routing/advancedRouter.d.ts +0 -68
  219. package/tmlpd-pi-extension/dist/routing/advancedRouter.d.ts.map +0 -1
  220. package/tmlpd-pi-extension/dist/routing/advancedRouter.js +0 -332
  221. package/tmlpd-pi-extension/dist/routing/advancedRouter.js.map +0 -1
  222. package/tmlpd-pi-extension/dist/tools/tmlpdTools.d.ts +0 -101
  223. package/tmlpd-pi-extension/dist/tools/tmlpdTools.d.ts.map +0 -1
  224. package/tmlpd-pi-extension/dist/tools/tmlpdTools.js +0 -368
  225. package/tmlpd-pi-extension/dist/tools/tmlpdTools.js.map +0 -1
  226. package/tmlpd-pi-extension/dist/utils/batchProcessor.d.ts +0 -96
  227. package/tmlpd-pi-extension/dist/utils/batchProcessor.d.ts.map +0 -1
  228. package/tmlpd-pi-extension/dist/utils/batchProcessor.js +0 -170
  229. package/tmlpd-pi-extension/dist/utils/batchProcessor.js.map +0 -1
  230. package/tmlpd-pi-extension/dist/utils/compression.d.ts +0 -61
  231. package/tmlpd-pi-extension/dist/utils/compression.d.ts.map +0 -1
  232. package/tmlpd-pi-extension/dist/utils/compression.js +0 -281
  233. package/tmlpd-pi-extension/dist/utils/compression.js.map +0 -1
  234. package/tmlpd-pi-extension/dist/utils/reliability.d.ts +0 -74
  235. package/tmlpd-pi-extension/dist/utils/reliability.d.ts.map +0 -1
  236. package/tmlpd-pi-extension/dist/utils/reliability.js +0 -177
  237. package/tmlpd-pi-extension/dist/utils/reliability.js.map +0 -1
  238. package/tmlpd-pi-extension/dist/utils/speculativeDecoding.d.ts +0 -117
  239. package/tmlpd-pi-extension/dist/utils/speculativeDecoding.d.ts.map +0 -1
  240. package/tmlpd-pi-extension/dist/utils/speculativeDecoding.js +0 -246
  241. package/tmlpd-pi-extension/dist/utils/speculativeDecoding.js.map +0 -1
  242. package/tmlpd-pi-extension/dist/utils/tokenUtils.d.ts +0 -50
  243. package/tmlpd-pi-extension/dist/utils/tokenUtils.d.ts.map +0 -1
  244. package/tmlpd-pi-extension/dist/utils/tokenUtils.js +0 -124
  245. 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