@kb-labs/adapters 0.5.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 (276) hide show
  1. package/.cursorrules +32 -0
  2. package/.github/workflows/ci.yml +13 -0
  3. package/.github/workflows/deploy.yml +28 -0
  4. package/.github/workflows/docker-build.yml +25 -0
  5. package/.github/workflows/drift-check.yml +10 -0
  6. package/.github/workflows/profiles-validate.yml +16 -0
  7. package/.github/workflows/release.yml +8 -0
  8. package/.kb/devkit/agents/devkit-maintainer/context.globs +15 -0
  9. package/.kb/devkit/agents/devkit-maintainer/permissions.yml +17 -0
  10. package/.kb/devkit/agents/devkit-maintainer/prompt.md +28 -0
  11. package/.kb/devkit/agents/devkit-maintainer/runbook.md +31 -0
  12. package/.kb/devkit/agents/docs-crafter/prompt.md +24 -0
  13. package/.kb/devkit/agents/docs-crafter/runbook.md +18 -0
  14. package/.kb/devkit/agents/release-manager/context.globs +7 -0
  15. package/.kb/devkit/agents/release-manager/prompt.md +27 -0
  16. package/.kb/devkit/agents/release-manager/runbook.md +17 -0
  17. package/.kb/devkit/agents/test-generator/context.globs +7 -0
  18. package/.kb/devkit/agents/test-generator/prompt.md +27 -0
  19. package/.kb/devkit/agents/test-generator/runbook.md +18 -0
  20. package/CONTRIBUTING.md +90 -0
  21. package/IMPLEMENTATION_COMPLETE.md +416 -0
  22. package/LICENSE +186 -0
  23. package/README-TEMPLATE.md +179 -0
  24. package/README.md +306 -0
  25. package/docs/DOCUMENTATION.md +74 -0
  26. package/docs/adr/0000-template.md +49 -0
  27. package/docs/adr/0001-architecture-and-repository-layout.md +33 -0
  28. package/docs/adr/0002-plugins-and-extensibility.md +46 -0
  29. package/docs/adr/0003-package-and-module-boundaries.md +37 -0
  30. package/docs/adr/0004-versioning-and-release-policy.md +38 -0
  31. package/docs/adr/0005-use-devkit-for-shared-tooling.md +48 -0
  32. package/docs/adr/0006-adopt-devkit-sync.md +47 -0
  33. package/docs/adr/0007-drift-kit-check.md +72 -0
  34. package/docs/adr/0008-devkit-sync-wrapper-strategy.md +67 -0
  35. package/docs/naming-convention.md +272 -0
  36. package/eslint.config.js +27 -0
  37. package/kb-labs.config.json +5 -0
  38. package/package.json +84 -0
  39. package/package.json.bin +25 -0
  40. package/package.json.lib +30 -0
  41. package/packages/adapters-analytics-duckdb/package.json +54 -0
  42. package/packages/adapters-analytics-duckdb/scripts/migrate-from-jsonl.mjs +253 -0
  43. package/packages/adapters-analytics-duckdb/src/index.ts +380 -0
  44. package/packages/adapters-analytics-duckdb/src/manifest.ts +36 -0
  45. package/packages/adapters-analytics-duckdb/src/schema.ts +161 -0
  46. package/packages/adapters-analytics-duckdb/tsconfig.build.json +15 -0
  47. package/packages/adapters-analytics-duckdb/tsconfig.json +9 -0
  48. package/packages/adapters-analytics-duckdb/tsup.config.ts +9 -0
  49. package/packages/adapters-analytics-file/README.md +32 -0
  50. package/packages/adapters-analytics-file/eslint.config.js +27 -0
  51. package/packages/adapters-analytics-file/package.json +50 -0
  52. package/packages/adapters-analytics-file/src/__tests__/daily-stats.spec.ts +287 -0
  53. package/packages/adapters-analytics-file/src/__tests__/scoped-analytics.test.ts +233 -0
  54. package/packages/adapters-analytics-file/src/index.test.ts +214 -0
  55. package/packages/adapters-analytics-file/src/index.ts +830 -0
  56. package/packages/adapters-analytics-file/src/manifest.ts +45 -0
  57. package/packages/adapters-analytics-file/tsconfig.build.json +15 -0
  58. package/packages/adapters-analytics-file/tsconfig.json +9 -0
  59. package/packages/adapters-analytics-file/tsup.config.ts +9 -0
  60. package/packages/adapters-analytics-sqlite/package.json +55 -0
  61. package/packages/adapters-analytics-sqlite/scripts/migrate-from-jsonl.mjs +194 -0
  62. package/packages/adapters-analytics-sqlite/src/index.ts +460 -0
  63. package/packages/adapters-analytics-sqlite/src/manifest.ts +41 -0
  64. package/packages/adapters-analytics-sqlite/tsconfig.build.json +15 -0
  65. package/packages/adapters-analytics-sqlite/tsconfig.json +9 -0
  66. package/packages/adapters-analytics-sqlite/tsup.config.ts +9 -0
  67. package/packages/adapters-environment-docker/README.md +28 -0
  68. package/packages/adapters-environment-docker/eslint.config.js +5 -0
  69. package/packages/adapters-environment-docker/package.json +49 -0
  70. package/packages/adapters-environment-docker/src/index.test.ts +138 -0
  71. package/packages/adapters-environment-docker/src/index.ts +439 -0
  72. package/packages/adapters-environment-docker/src/manifest.ts +65 -0
  73. package/packages/adapters-environment-docker/tsconfig.build.json +15 -0
  74. package/packages/adapters-environment-docker/tsconfig.json +16 -0
  75. package/packages/adapters-environment-docker/tsup.config.ts +9 -0
  76. package/packages/adapters-eventbus-cache/README.md +242 -0
  77. package/packages/adapters-eventbus-cache/eslint.config.js +27 -0
  78. package/packages/adapters-eventbus-cache/package.json +46 -0
  79. package/packages/adapters-eventbus-cache/src/index.test.ts +235 -0
  80. package/packages/adapters-eventbus-cache/src/index.ts +215 -0
  81. package/packages/adapters-eventbus-cache/src/manifest.ts +50 -0
  82. package/packages/adapters-eventbus-cache/src/types.ts +58 -0
  83. package/packages/adapters-eventbus-cache/tsconfig.build.json +15 -0
  84. package/packages/adapters-eventbus-cache/tsconfig.json +9 -0
  85. package/packages/adapters-eventbus-cache/tsup.config.ts +9 -0
  86. package/packages/adapters-fs/README.md +171 -0
  87. package/packages/adapters-fs/allowed.txt +1 -0
  88. package/packages/adapters-fs/conflict.txt +1 -0
  89. package/packages/adapters-fs/dest.txt +1 -0
  90. package/packages/adapters-fs/eslint.config.js +27 -0
  91. package/packages/adapters-fs/exists.txt +1 -0
  92. package/packages/adapters-fs/not-allowed.txt +1 -0
  93. package/packages/adapters-fs/other.txt +1 -0
  94. package/packages/adapters-fs/package.json +55 -0
  95. package/packages/adapters-fs/public/file1.txt +1 -0
  96. package/packages/adapters-fs/public/file2.txt +1 -0
  97. package/packages/adapters-fs/secret.txt +1 -0
  98. package/packages/adapters-fs/secrets/key.txt +1 -0
  99. package/packages/adapters-fs/src/index.test.ts +243 -0
  100. package/packages/adapters-fs/src/index.ts +258 -0
  101. package/packages/adapters-fs/src/manifest.ts +35 -0
  102. package/packages/adapters-fs/src/secure-storage.test.ts +380 -0
  103. package/packages/adapters-fs/src/secure-storage.ts +268 -0
  104. package/packages/adapters-fs/test.json +1 -0
  105. package/packages/adapters-fs/test.txt +1 -0
  106. package/packages/adapters-fs/test.xyz +1 -0
  107. package/packages/adapters-fs/test1.txt +1 -0
  108. package/packages/adapters-fs/test2.txt +1 -0
  109. package/packages/adapters-fs/tsconfig.build.json +15 -0
  110. package/packages/adapters-fs/tsconfig.json +9 -0
  111. package/packages/adapters-fs/tsup.config.ts +8 -0
  112. package/packages/adapters-fs/vitest.config.ts +19 -0
  113. package/packages/adapters-log-ringbuffer/README.md +228 -0
  114. package/packages/adapters-log-ringbuffer/eslint.config.js +27 -0
  115. package/packages/adapters-log-ringbuffer/package.json +47 -0
  116. package/packages/adapters-log-ringbuffer/src/__tests__/ring-buffer.test.ts +450 -0
  117. package/packages/adapters-log-ringbuffer/src/index.ts +212 -0
  118. package/packages/adapters-log-ringbuffer/src/manifest.ts +30 -0
  119. package/packages/adapters-log-ringbuffer/tsconfig.build.json +15 -0
  120. package/packages/adapters-log-ringbuffer/tsconfig.json +9 -0
  121. package/packages/adapters-log-ringbuffer/tsup.config.ts +9 -0
  122. package/packages/adapters-log-ringbuffer/vitest.config.ts +14 -0
  123. package/packages/adapters-log-sqlite/README.md +396 -0
  124. package/packages/adapters-log-sqlite/eslint.config.js +27 -0
  125. package/packages/adapters-log-sqlite/package.json +49 -0
  126. package/packages/adapters-log-sqlite/src/__tests__/log-persistence.test.ts +718 -0
  127. package/packages/adapters-log-sqlite/src/index.ts +1068 -0
  128. package/packages/adapters-log-sqlite/src/manifest.ts +36 -0
  129. package/packages/adapters-log-sqlite/src/schema.sql +46 -0
  130. package/packages/adapters-log-sqlite/tsconfig.build.json +15 -0
  131. package/packages/adapters-log-sqlite/tsconfig.json +9 -0
  132. package/packages/adapters-log-sqlite/tsup.config.ts +9 -0
  133. package/packages/adapters-log-sqlite/vitest.config.ts +15 -0
  134. package/packages/adapters-mongodb/README.md +147 -0
  135. package/packages/adapters-mongodb/eslint.config.js +27 -0
  136. package/packages/adapters-mongodb/package.json +53 -0
  137. package/packages/adapters-mongodb/src/index.ts +428 -0
  138. package/packages/adapters-mongodb/src/manifest.ts +45 -0
  139. package/packages/adapters-mongodb/src/secure-document.ts +231 -0
  140. package/packages/adapters-mongodb/tsconfig.build.json +15 -0
  141. package/packages/adapters-mongodb/tsconfig.json +9 -0
  142. package/packages/adapters-mongodb/tsup.config.ts +8 -0
  143. package/packages/adapters-openai/README.md +151 -0
  144. package/packages/adapters-openai/embeddings.ts +37 -0
  145. package/packages/adapters-openai/eslint.config.js +26 -0
  146. package/packages/adapters-openai/index.ts +22 -0
  147. package/packages/adapters-openai/package.json +57 -0
  148. package/packages/adapters-openai/src/embeddings-manifest.ts +45 -0
  149. package/packages/adapters-openai/src/embeddings.ts +104 -0
  150. package/packages/adapters-openai/src/index.ts +13 -0
  151. package/packages/adapters-openai/src/llm.ts +304 -0
  152. package/packages/adapters-openai/src/manifest.ts +47 -0
  153. package/packages/adapters-openai/tsconfig.build.json +15 -0
  154. package/packages/adapters-openai/tsconfig.json +9 -0
  155. package/packages/adapters-openai/tsup.config.ts +8 -0
  156. package/packages/adapters-pino/README.md +152 -0
  157. package/packages/adapters-pino/eslint.config.js +27 -0
  158. package/packages/adapters-pino/package.json +49 -0
  159. package/packages/adapters-pino/src/index.test.ts +44 -0
  160. package/packages/adapters-pino/src/index.ts +322 -0
  161. package/packages/adapters-pino/src/log-ring-buffer.ts +142 -0
  162. package/packages/adapters-pino/src/manifest.ts +49 -0
  163. package/packages/adapters-pino/tsconfig.build.json +15 -0
  164. package/packages/adapters-pino/tsconfig.json +9 -0
  165. package/packages/adapters-pino/tsup.config.ts +9 -0
  166. package/packages/adapters-pino-http/README.md +141 -0
  167. package/packages/adapters-pino-http/eslint.config.js +27 -0
  168. package/packages/adapters-pino-http/package.json +46 -0
  169. package/packages/adapters-pino-http/src/index.ts +229 -0
  170. package/packages/adapters-pino-http/tsconfig.build.json +15 -0
  171. package/packages/adapters-pino-http/tsconfig.json +9 -0
  172. package/packages/adapters-pino-http/tsup.config.ts +9 -0
  173. package/packages/adapters-qdrant/README.md +166 -0
  174. package/packages/adapters-qdrant/eslint.config.js +27 -0
  175. package/packages/adapters-qdrant/package.json +49 -0
  176. package/packages/adapters-qdrant/src/index.ts +490 -0
  177. package/packages/adapters-qdrant/src/manifest.ts +54 -0
  178. package/packages/adapters-qdrant/src/retry.ts +204 -0
  179. package/packages/adapters-qdrant/tsconfig.build.json +15 -0
  180. package/packages/adapters-qdrant/tsconfig.json +9 -0
  181. package/packages/adapters-qdrant/tsup.config.ts +9 -0
  182. package/packages/adapters-redis/README.md +159 -0
  183. package/packages/adapters-redis/eslint.config.js +27 -0
  184. package/packages/adapters-redis/package.json +49 -0
  185. package/packages/adapters-redis/src/index.ts +164 -0
  186. package/packages/adapters-redis/src/manifest.ts +49 -0
  187. package/packages/adapters-redis/tsconfig.build.json +15 -0
  188. package/packages/adapters-redis/tsconfig.json +9 -0
  189. package/packages/adapters-redis/tsup.config.ts +9 -0
  190. package/packages/adapters-snapshot-localfs/README.md +10 -0
  191. package/packages/adapters-snapshot-localfs/eslint.config.js +2 -0
  192. package/packages/adapters-snapshot-localfs/package.json +46 -0
  193. package/packages/adapters-snapshot-localfs/src/index.test.ts +40 -0
  194. package/packages/adapters-snapshot-localfs/src/index.ts +292 -0
  195. package/packages/adapters-snapshot-localfs/src/manifest.ts +32 -0
  196. package/packages/adapters-snapshot-localfs/tsconfig.build.json +15 -0
  197. package/packages/adapters-snapshot-localfs/tsconfig.json +16 -0
  198. package/packages/adapters-snapshot-localfs/tsup.config.ts +11 -0
  199. package/packages/adapters-sqlite/README.md +163 -0
  200. package/packages/adapters-sqlite/eslint.config.js +27 -0
  201. package/packages/adapters-sqlite/package.json +54 -0
  202. package/packages/adapters-sqlite/src/index.test.ts +245 -0
  203. package/packages/adapters-sqlite/src/index.ts +382 -0
  204. package/packages/adapters-sqlite/src/manifest.ts +47 -0
  205. package/packages/adapters-sqlite/src/secure-sql.test.ts +290 -0
  206. package/packages/adapters-sqlite/src/secure-sql.ts +281 -0
  207. package/packages/adapters-sqlite/tsconfig.build.json +15 -0
  208. package/packages/adapters-sqlite/tsconfig.json +9 -0
  209. package/packages/adapters-sqlite/tsup.config.ts +8 -0
  210. package/packages/adapters-sqlite/vitest.config.ts +19 -0
  211. package/packages/adapters-transport/README.md +170 -0
  212. package/packages/adapters-transport/eslint.config.js +27 -0
  213. package/packages/adapters-transport/package.json +49 -0
  214. package/packages/adapters-transport/src/__tests__/unix-socket-server.test.ts +550 -0
  215. package/packages/adapters-transport/src/index.ts +101 -0
  216. package/packages/adapters-transport/src/ipc-transport.ts +228 -0
  217. package/packages/adapters-transport/src/transport.ts +224 -0
  218. package/packages/adapters-transport/src/types.ts +92 -0
  219. package/packages/adapters-transport/src/unix-socket-server.ts +193 -0
  220. package/packages/adapters-transport/src/unix-socket-transport.ts +280 -0
  221. package/packages/adapters-transport/tsconfig.build.json +15 -0
  222. package/packages/adapters-transport/tsconfig.json +9 -0
  223. package/packages/adapters-transport/tsup.config.ts +9 -0
  224. package/packages/adapters-vibeproxy/README.md +159 -0
  225. package/packages/adapters-vibeproxy/eslint.config.js +27 -0
  226. package/packages/adapters-vibeproxy/package.json +51 -0
  227. package/packages/adapters-vibeproxy/src/index.ts +13 -0
  228. package/packages/adapters-vibeproxy/src/llm.ts +437 -0
  229. package/packages/adapters-vibeproxy/src/manifest.ts +51 -0
  230. package/packages/adapters-vibeproxy/tsconfig.build.json +15 -0
  231. package/packages/adapters-vibeproxy/tsconfig.json +9 -0
  232. package/packages/adapters-vibeproxy/tsup.config.ts +8 -0
  233. package/packages/adapters-workspace-agent/package.json +46 -0
  234. package/packages/adapters-workspace-agent/src/__tests__/adapter.test.ts +212 -0
  235. package/packages/adapters-workspace-agent/src/index.ts +220 -0
  236. package/packages/adapters-workspace-agent/src/manifest.ts +36 -0
  237. package/packages/adapters-workspace-agent/tsconfig.build.json +15 -0
  238. package/packages/adapters-workspace-agent/tsconfig.json +16 -0
  239. package/packages/adapters-workspace-agent/tsup.config.ts +11 -0
  240. package/packages/adapters-workspace-localfs/README.md +9 -0
  241. package/packages/adapters-workspace-localfs/eslint.config.js +2 -0
  242. package/packages/adapters-workspace-localfs/package.json +46 -0
  243. package/packages/adapters-workspace-localfs/src/index.test.ts +27 -0
  244. package/packages/adapters-workspace-localfs/src/index.ts +172 -0
  245. package/packages/adapters-workspace-localfs/src/manifest.ts +32 -0
  246. package/packages/adapters-workspace-localfs/tsconfig.build.json +15 -0
  247. package/packages/adapters-workspace-localfs/tsconfig.json +16 -0
  248. package/packages/adapters-workspace-localfs/tsup.config.ts +11 -0
  249. package/packages/adapters-workspace-worktree/README.md +9 -0
  250. package/packages/adapters-workspace-worktree/eslint.config.js +2 -0
  251. package/packages/adapters-workspace-worktree/package.json +46 -0
  252. package/packages/adapters-workspace-worktree/src/index.test.ts +38 -0
  253. package/packages/adapters-workspace-worktree/src/index.ts +245 -0
  254. package/packages/adapters-workspace-worktree/src/manifest.ts +38 -0
  255. package/packages/adapters-workspace-worktree/tsconfig.build.json +15 -0
  256. package/packages/adapters-workspace-worktree/tsconfig.json +16 -0
  257. package/packages/adapters-workspace-worktree/tsup.config.ts +11 -0
  258. package/pnpm-workspace.yaml +2800 -0
  259. package/prettierrc.json +1 -0
  260. package/scripts/devkit-sync.mjs +37 -0
  261. package/scripts/hooks/post-push +9 -0
  262. package/scripts/hooks/pre-commit +9 -0
  263. package/scripts/hooks/pre-push +9 -0
  264. package/test-integration.ts +242 -0
  265. package/test.txt +1 -0
  266. package/tsconfig.base.json +6 -0
  267. package/tsconfig.build.json +15 -0
  268. package/tsconfig.json +9 -0
  269. package/tsconfig.paths.json +26 -0
  270. package/tsconfig.tools.json +17 -0
  271. package/tsup.config.bin.ts +34 -0
  272. package/tsup.config.cli.ts +41 -0
  273. package/tsup.config.dual.ts +46 -0
  274. package/tsup.config.ts +36 -0
  275. package/tsup.external.json +103 -0
  276. package/vitest.config.ts +2 -0
@@ -0,0 +1,304 @@
1
+ /**
2
+ * @module @kb-labs/adapters-openai/llm
3
+ * OpenAI implementation of ILLM interface.
4
+ */
5
+
6
+ import OpenAI from "openai";
7
+ import type {
8
+ ILLM,
9
+ LLMOptions,
10
+ LLMResponse,
11
+ LLMMessage,
12
+ LLMToolCallOptions,
13
+ LLMToolCallResponse,
14
+ LLMTool,
15
+ LLMToolCall,
16
+ LLMProtocolCapabilities,
17
+ } from "@kb-labs/core-platform";
18
+
19
+ /**
20
+ * Configuration for OpenAI LLM adapter.
21
+ */
22
+ export interface OpenAILLMConfig {
23
+ /** OpenAI API key (defaults to OPENAI_API_KEY env var) */
24
+ apiKey?: string;
25
+ /** Base URL for API (optional, for proxies or Azure) */
26
+ baseURL?: string;
27
+ /** Default model to use */
28
+ defaultModel?: string;
29
+ /** Organization ID (optional) */
30
+ organization?: string;
31
+ /** Default max output tokens when caller does not specify. Overrides the API default (4096). */
32
+ defaultMaxTokens?: number;
33
+ }
34
+
35
+ /** Default max output tokens — avoids hitting the 4096 API default mid-response. */
36
+ const DEFAULT_MAX_TOKENS = 16_384;
37
+
38
+ /**
39
+ * OpenAI implementation of ILLM interface.
40
+ */
41
+ export class OpenAILLM implements ILLM {
42
+ private client: OpenAI;
43
+ private defaultModel: string;
44
+ private defaultMaxTokens: number;
45
+
46
+ constructor(config: OpenAILLMConfig = {}) {
47
+ this.client = new OpenAI({
48
+ apiKey: config.apiKey ?? process.env.OPENAI_API_KEY,
49
+ baseURL: config.baseURL,
50
+ organization: config.organization,
51
+ });
52
+ this.defaultModel = config.defaultModel ?? "gpt-4o-mini";
53
+ this.defaultMaxTokens = config.defaultMaxTokens ?? DEFAULT_MAX_TOKENS;
54
+ }
55
+
56
+ getProtocolCapabilities(): LLMProtocolCapabilities {
57
+ return {
58
+ cache: {
59
+ supported: true,
60
+ protocol: "auto_prefix",
61
+ scopes: ["prefix", "segments"],
62
+ },
63
+ stream: {
64
+ supported: true,
65
+ },
66
+ };
67
+ }
68
+
69
+ private buildCacheRequestPatch(options?: LLMOptions): Record<string, unknown> {
70
+ const cache = options?.execution?.cache;
71
+ if (!cache) {
72
+ return {};
73
+ }
74
+
75
+ const patch: Record<string, unknown> = {
76
+ metadata: {
77
+ kb_cache_mode: cache.mode ?? "prefer",
78
+ kb_cache_scope: cache.scope ?? "prefix",
79
+ },
80
+ };
81
+
82
+ if (typeof cache.ttlSec === "number") {
83
+ (patch.metadata as Record<string, unknown>).kb_cache_ttl_sec = String(
84
+ cache.ttlSec,
85
+ );
86
+ }
87
+
88
+ if (cache.key) {
89
+ // Best-effort hint: supported by newer OpenAI prompt caching stacks.
90
+ patch.prompt_cache_key = cache.key;
91
+ (patch.metadata as Record<string, unknown>).kb_cache_key = cache.key;
92
+ }
93
+
94
+ return patch;
95
+ }
96
+
97
+ async complete(prompt: string, options?: LLMOptions): Promise<LLMResponse> {
98
+ const model = options?.model ?? this.defaultModel;
99
+ const messages: OpenAI.ChatCompletionMessageParam[] = [];
100
+
101
+ // Add system prompt if provided
102
+ if (options?.systemPrompt) {
103
+ messages.push({ role: "system", content: options.systemPrompt });
104
+ }
105
+
106
+ // Add user prompt
107
+ messages.push({ role: "user", content: prompt });
108
+
109
+ const response = await this.client.chat.completions.create({
110
+ model,
111
+ messages,
112
+ temperature: options?.temperature,
113
+ max_tokens: options?.maxTokens ?? this.defaultMaxTokens,
114
+ stop: options?.stop,
115
+ ...(this.buildCacheRequestPatch(options) as Record<string, unknown>),
116
+ });
117
+
118
+ const choice = response.choices[0];
119
+ const content = choice?.message?.content ?? "";
120
+
121
+ return {
122
+ content,
123
+ usage: {
124
+ promptTokens: response.usage?.prompt_tokens ?? 0,
125
+ completionTokens: response.usage?.completion_tokens ?? 0,
126
+ cacheReadTokens:
127
+ (response.usage as unknown as { prompt_tokens_details?: { cached_tokens?: number } })
128
+ ?.prompt_tokens_details?.cached_tokens ?? 0,
129
+ providerUsage: response.usage as unknown as Record<string, unknown>,
130
+ },
131
+ model: response.model,
132
+ };
133
+ }
134
+
135
+ async *stream(prompt: string, options?: LLMOptions): AsyncIterable<string> {
136
+ const model = options?.model ?? this.defaultModel;
137
+ const messages: OpenAI.ChatCompletionMessageParam[] = [];
138
+
139
+ // Add system prompt if provided
140
+ if (options?.systemPrompt) {
141
+ messages.push({ role: "system", content: options.systemPrompt });
142
+ }
143
+
144
+ // Add user prompt
145
+ messages.push({ role: "user", content: prompt });
146
+
147
+ const stream = await this.client.chat.completions.create({
148
+ model,
149
+ messages,
150
+ temperature: options?.temperature,
151
+ max_tokens: options?.maxTokens ?? this.defaultMaxTokens,
152
+ stop: options?.stop,
153
+ stream: true,
154
+ ...(this.buildCacheRequestPatch(options) as Record<string, unknown>),
155
+ });
156
+
157
+ for await (const chunk of stream) {
158
+ const content = chunk.choices[0]?.delta?.content;
159
+ if (content) {
160
+ yield content;
161
+ }
162
+ }
163
+ }
164
+
165
+ /**
166
+ * Chat with native tool calling support.
167
+ * Uses OpenAI's native function calling API.
168
+ */
169
+ // eslint-disable-next-line sonarjs/cognitive-complexity -- Complex due to OpenAI API format conversion (messages, tools, tool_choice)
170
+ async chatWithTools(
171
+ messages: LLMMessage[],
172
+ options: LLMToolCallOptions,
173
+ ): Promise<LLMToolCallResponse> {
174
+ const model = options?.model ?? this.defaultModel;
175
+
176
+ // Convert LLMMessage[] to OpenAI format
177
+ const openaiMessages: OpenAI.ChatCompletionMessageParam[] = messages.map(
178
+ (msg) => {
179
+ if (msg.role === "tool") {
180
+ return {
181
+ role: "tool" as const,
182
+ content: msg.content,
183
+ tool_call_id: msg.toolCallId || "",
184
+ };
185
+ }
186
+ if (msg.role === "assistant" && msg.toolCalls && msg.toolCalls.length > 0) {
187
+ // Assistant message with tool calls
188
+ return {
189
+ role: "assistant" as const,
190
+ content: msg.content || null,
191
+ tool_calls: msg.toolCalls.map((tc) => ({
192
+ id: tc.id,
193
+ type: "function" as const,
194
+ function: {
195
+ name: tc.name,
196
+ arguments: typeof tc.input === "string" ? tc.input : JSON.stringify(tc.input),
197
+ },
198
+ })),
199
+ };
200
+ }
201
+ return {
202
+ role: msg.role as "system" | "user" | "assistant",
203
+ content: msg.content,
204
+ };
205
+ },
206
+ );
207
+
208
+ // Convert LLMTool[] to OpenAI tools format
209
+ const tools: OpenAI.ChatCompletionTool[] = options.tools.map(
210
+ (tool: LLMTool) => ({
211
+ type: "function" as const,
212
+ function: {
213
+ name: tool.name,
214
+ description: tool.description,
215
+ parameters: tool.inputSchema,
216
+ },
217
+ }),
218
+ );
219
+
220
+ // Convert tool choice
221
+ let tool_choice: OpenAI.ChatCompletionToolChoiceOption | undefined;
222
+ if (options.toolChoice === "auto") {
223
+ tool_choice = "auto";
224
+ } else if (options.toolChoice === "required") {
225
+ tool_choice = "required";
226
+ } else if (options.toolChoice === "none") {
227
+ tool_choice = "none";
228
+ } else if (options.toolChoice && typeof options.toolChoice === "object") {
229
+ tool_choice = {
230
+ type: "function",
231
+ function: { name: options.toolChoice.function.name },
232
+ };
233
+ }
234
+
235
+ // Call OpenAI API
236
+ const response = await this.client.chat.completions.create({
237
+ model,
238
+ messages: openaiMessages,
239
+ tools,
240
+ tool_choice,
241
+ temperature: options?.temperature,
242
+ max_tokens: options?.maxTokens ?? this.defaultMaxTokens,
243
+ stop: options?.stop,
244
+ ...(this.buildCacheRequestPatch(options) as Record<string, unknown>),
245
+ });
246
+
247
+ const choice = response.choices[0];
248
+ const content = choice?.message?.content ?? "";
249
+
250
+ // Extract tool calls if any
251
+ const toolCalls: LLMToolCall[] = [];
252
+ if (choice?.message?.tool_calls) {
253
+ for (const tc of choice.message.tool_calls) {
254
+ try {
255
+ const input = JSON.parse(tc.function.arguments);
256
+ toolCalls.push({
257
+ id: tc.id,
258
+ name: tc.function.name,
259
+ input,
260
+ });
261
+ } catch (error) {
262
+ // Failed to parse tool arguments - skip this tool call
263
+ console.warn("Failed to parse tool arguments", {
264
+ toolName: tc.function.name,
265
+ error: error instanceof Error ? error.message : String(error),
266
+ });
267
+ }
268
+ }
269
+ }
270
+
271
+ // Map OpenAI finish_reason to normalized stopReason
272
+ const finishReason = choice?.finish_reason;
273
+ const stopReason = finishReason === 'stop' ? 'end_turn'
274
+ : finishReason === 'tool_calls' ? 'tool_use'
275
+ : finishReason === 'length' ? 'max_tokens'
276
+ : finishReason ?? undefined;
277
+
278
+ return {
279
+ content,
280
+ usage: {
281
+ promptTokens: response.usage?.prompt_tokens ?? 0,
282
+ completionTokens: response.usage?.completion_tokens ?? 0,
283
+ cacheReadTokens:
284
+ (response.usage as unknown as { prompt_tokens_details?: { cached_tokens?: number } })
285
+ ?.prompt_tokens_details?.cached_tokens ?? 0,
286
+ providerUsage: response.usage as unknown as Record<string, unknown>,
287
+ },
288
+ model: response.model,
289
+ toolCalls: toolCalls.length > 0 ? toolCalls : undefined,
290
+ stopReason,
291
+ };
292
+ }
293
+ }
294
+
295
+ /**
296
+ * Create OpenAI LLM adapter.
297
+ * This is the factory function called by initPlatform() when loading adapters.
298
+ */
299
+ export function createAdapter(config?: OpenAILLMConfig): OpenAILLM {
300
+ return new OpenAILLM(config);
301
+ }
302
+
303
+ // Default export for direct import
304
+ export default createAdapter;
@@ -0,0 +1,47 @@
1
+ /**
2
+ * @module @kb-labs/adapters-openai/manifest
3
+ * Adapter manifest for OpenAI LLM.
4
+ */
5
+
6
+ import type { AdapterManifest } from "@kb-labs/core-platform";
7
+
8
+ /**
9
+ * Adapter manifest for OpenAI LLM.
10
+ */
11
+ export const manifest: AdapterManifest = {
12
+ manifestVersion: "1.0.0",
13
+ id: "openai-llm",
14
+ name: "OpenAI LLM",
15
+ version: "1.0.0",
16
+ description: "OpenAI language model adapter (GPT-4, GPT-3.5, etc.)",
17
+ author: "KB Labs Team",
18
+ license: "KBPL-1.1",
19
+ type: "core",
20
+ implements: "ILLM",
21
+ capabilities: {
22
+ streaming: true,
23
+ custom: {
24
+ functionCalling: true,
25
+ },
26
+ },
27
+ configSchema: {
28
+ apiKey: {
29
+ type: "string",
30
+ description: "OpenAI API key (defaults to OPENAI_API_KEY env var)",
31
+ },
32
+ model: {
33
+ type: "string",
34
+ default: "gpt-4o",
35
+ description: "Model to use (gpt-4o, gpt-4-turbo, gpt-3.5-turbo, etc.)",
36
+ },
37
+ temperature: {
38
+ type: "number",
39
+ default: 0.7,
40
+ description: "Sampling temperature (0.0 to 2.0)",
41
+ },
42
+ maxTokens: {
43
+ type: "number",
44
+ description: "Maximum tokens to generate",
45
+ },
46
+ },
47
+ };
@@ -0,0 +1,15 @@
1
+ {
2
+ "extends": "../../tsconfig.base.json",
3
+ "compilerOptions": {
4
+ "outDir": "dist",
5
+ "baseUrl": ".",
6
+ "paths": {}
7
+ },
8
+ "include": [
9
+ "src/**/*"
10
+ ],
11
+ "exclude": [
12
+ "dist",
13
+ "node_modules"
14
+ ]
15
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "$schema": "https://json.schemastore.org/tsconfig",
3
+ "extends": "@kb-labs/devkit/tsconfig/node.json",
4
+ "compilerOptions": {
5
+ "rootDir": "src",
6
+ "outDir": "dist"
7
+ },
8
+ "include": ["src"]
9
+ }
@@ -0,0 +1,8 @@
1
+ import { defineConfig } from 'tsup';
2
+ import nodePreset from '@kb-labs/devkit/tsup/node';
3
+
4
+ export default defineConfig({
5
+ ...nodePreset,
6
+ tsconfig: 'tsconfig.build.json',
7
+ dts: true,
8
+ });
@@ -0,0 +1,152 @@
1
+ # @kb-labs/adapters-pino
2
+
3
+ > Part of [KB Labs](https://github.com/KirillBaranov/kb-labs) ecosystem. Works exclusively within KB Labs platform.
4
+
5
+ Production-ready structured logger based on Pino with streaming and analytics integration.
6
+
7
+ ## Overview
8
+
9
+ | Property | Value |
10
+ |----------|-------|
11
+ | **Implements** | `ILogger` |
12
+ | **Type** | `core` |
13
+ | **Requires** | None (optional: `analytics`) |
14
+ | **Category** | Logging |
15
+
16
+ ## Features
17
+
18
+ - **Structured Logging** - JSON-formatted logs with context
19
+ - **High Performance** - Built on Pino (fastest Node.js logger)
20
+ - **Log Levels** - trace, debug, info, warn, error, fatal
21
+ - **Pretty Printing** - Human-readable output for development
22
+ - **Streaming Support** - Buffered log streaming
23
+
24
+ ## Installation
25
+
26
+ ```bash
27
+ pnpm add @kb-labs/adapters-pino
28
+ ```
29
+
30
+ ## Configuration
31
+
32
+ Add to your `kb.config.json`:
33
+
34
+ ```json
35
+ {
36
+ "platform": {
37
+ "adapters": {
38
+ "logger": "@kb-labs/adapters-pino"
39
+ },
40
+ "adapterOptions": {
41
+ "logger": {
42
+ "level": "info",
43
+ "pretty": false,
44
+ "streaming": {
45
+ "enabled": true,
46
+ "bufferSize": 1000,
47
+ "bufferMaxAge": 3600000
48
+ }
49
+ }
50
+ }
51
+ }
52
+ }
53
+ ```
54
+
55
+ ### Options
56
+
57
+ | Option | Type | Default | Description |
58
+ |--------|------|---------|-------------|
59
+ | `level` | `string` | `"info"` | Minimum log level |
60
+ | `pretty` | `boolean` | `false` | Enable pretty printing for development |
61
+ | `streaming.enabled` | `boolean` | `false` | Enable log streaming/buffering |
62
+ | `streaming.bufferSize` | `number` | `1000` | Buffer size for streaming |
63
+ | `streaming.bufferMaxAge` | `number` | `3600000` | Max age of buffered logs (1 hour) |
64
+
65
+ ## Usage
66
+
67
+ ### Via Platform (Recommended)
68
+
69
+ ```typescript
70
+ import { usePlatform } from '@kb-labs/sdk';
71
+
72
+ const platform = usePlatform();
73
+
74
+ // Basic logging
75
+ platform.logger.info('Server started', { port: 3000 });
76
+ platform.logger.error('Request failed', { error, requestId });
77
+
78
+ // With child logger
79
+ const reqLogger = platform.logger.child({ requestId: 'req-123' });
80
+ reqLogger.info('Processing request');
81
+ ```
82
+
83
+ ### Standalone (Testing/Development)
84
+
85
+ ```typescript
86
+ import { createAdapter } from '@kb-labs/adapters-pino';
87
+
88
+ const logger = createAdapter({
89
+ level: 'debug',
90
+ pretty: true
91
+ });
92
+
93
+ logger.info('Hello, world!');
94
+ ```
95
+
96
+ ## Adapter Manifest
97
+
98
+ ```typescript
99
+ {
100
+ id: 'pino-logger',
101
+ name: 'Pino Logger',
102
+ version: '1.0.0',
103
+ implements: 'ILogger',
104
+ optional: {
105
+ adapters: ['analytics'],
106
+ },
107
+ capabilities: {
108
+ streaming: true,
109
+ },
110
+ }
111
+ ```
112
+
113
+ ## Log Levels
114
+
115
+ | Level | When to use |
116
+ |-------|-------------|
117
+ | `trace` | Very detailed debugging info |
118
+ | `debug` | Debugging information |
119
+ | `info` | General operational events |
120
+ | `warn` | Warning conditions |
121
+ | `error` | Error conditions |
122
+ | `fatal` | System is unusable |
123
+
124
+ ## FAQ
125
+
126
+ <details>
127
+ <summary><strong>Q: How do I enable pretty printing in development?</strong></summary>
128
+
129
+ Set `pretty: true` in config or use environment:
130
+
131
+ ```bash
132
+ KB_LOG_PRETTY=true pnpm dev
133
+ ```
134
+ </details>
135
+
136
+ <details>
137
+ <summary><strong>Q: How do I send logs to remote service?</strong></summary>
138
+
139
+ Use `@kb-labs/adapters-pino-http` as a transport to stream logs to REST API.
140
+ </details>
141
+
142
+ ## Related Adapters
143
+
144
+ | Adapter | Use Case |
145
+ |---------|----------|
146
+ | `@kb-labs/adapters-pino-http` | HTTP transport for remote logging |
147
+ | `@kb-labs/adapters-log-ringbuffer` | In-memory log streaming |
148
+ | `@kb-labs/adapters-log-sqlite` | Persistent log storage |
149
+
150
+ ## License
151
+
152
+ [KB Public License v1.1](../../LICENSE) - KB Labs Team
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Standard ESLint configuration template
3
+ *
4
+ * This is the canonical template for all @kb-labs packages.
5
+ * DO NOT modify this file locally - it is synced from @kb-labs/devkit
6
+ *
7
+ * Customization guidelines:
8
+ * - DevKit preset already includes all standard ignores
9
+ * - Only add project-specific ignores if absolutely necessary
10
+ * - Document why custom ignores are needed
11
+ *
12
+ * @see https://github.com/kb-labs/devkit#eslint-configuration
13
+ */
14
+ import nodePreset from '@kb-labs/devkit/eslint/node.js';
15
+
16
+ export default [
17
+ ...nodePreset,
18
+
19
+ // OPTIONAL: Add project-specific ignores only if needed
20
+ // DevKit preset already ignores: dist/, coverage/, node_modules/, *.d.ts, scripts/, etc.
21
+ // {
22
+ // ignores: [
23
+ // // Add ONLY project-specific patterns here
24
+ // // Example: '**/*.generated.ts',
25
+ // ]
26
+ // }
27
+ ];
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "@kb-labs/adapters-pino",
3
+ "version": "0.5.0",
4
+ "description": "Pino adapter implementing ILogger interface",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.js",
11
+ "types": "./dist/index.d.ts"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist",
16
+ "README.md"
17
+ ],
18
+ "sideEffects": false,
19
+ "scripts": {
20
+ "clean": "rimraf dist",
21
+ "build": "tsup",
22
+ "dev": "tsup --watch",
23
+ "type-check": "tsc --noEmit",
24
+ "test": "vitest run --passWithNoTests",
25
+ "test:watch": "vitest",
26
+ "lint": "eslint src --ext .ts",
27
+ "lint:fix": "eslint . --fix"
28
+ },
29
+ "dependencies": {
30
+ "pino": "^9.0.0"
31
+ },
32
+ "peerDependencies": {
33
+ "@kb-labs/core-platform": "*"
34
+ },
35
+ "devDependencies": {
36
+ "@kb-labs/core-platform": "link:../../../../platform/kb-labs-core/packages/core-platform",
37
+ "@types/node": "^24.3.3",
38
+ "eslint": "^9",
39
+ "tsup": "^8.5.0",
40
+ "typescript": "^5.6.3",
41
+ "vitest": "^3.2.4",
42
+ "@kb-labs/devkit": "link:../../../kb-labs-devkit",
43
+ "rimraf": "^6.0.1"
44
+ },
45
+ "engines": {
46
+ "node": ">=20.0.0",
47
+ "pnpm": ">=9.0.0"
48
+ }
49
+ }
@@ -0,0 +1,44 @@
1
+ import { describe, expect, it, vi } from 'vitest';
2
+ import { PinoLoggerAdapter } from './index.js';
3
+
4
+ describe('PinoLoggerAdapter', () => {
5
+ it('includes child bindings in onLog records', () => {
6
+ const logger = new PinoLoggerAdapter({ level: 'debug' });
7
+ const callback = vi.fn();
8
+ logger.onLog(callback);
9
+
10
+ const child = logger.child({
11
+ traceId: 'trace-1',
12
+ requestId: 'req-1',
13
+ invocationId: 'inv-1',
14
+ });
15
+
16
+ child.info('hello', { step: 'start' });
17
+
18
+ expect(callback).toHaveBeenCalledTimes(1);
19
+ const [record] = callback.mock.calls[0]!;
20
+ expect(record.fields).toMatchObject({
21
+ traceId: 'trace-1',
22
+ requestId: 'req-1',
23
+ invocationId: 'inv-1',
24
+ step: 'start',
25
+ });
26
+ });
27
+
28
+ it('propagates nested child bindings in onLog records', () => {
29
+ const logger = new PinoLoggerAdapter({ level: 'debug' });
30
+ const callback = vi.fn();
31
+ logger.onLog(callback);
32
+
33
+ const child = logger.child({ traceId: 'trace-1' }).child({ spanId: 'span-2' });
34
+ child.debug('nested');
35
+
36
+ expect(callback).toHaveBeenCalledTimes(1);
37
+ const [record] = callback.mock.calls[0]!;
38
+ expect(record.fields).toMatchObject({
39
+ traceId: 'trace-1',
40
+ spanId: 'span-2',
41
+ });
42
+ });
43
+ });
44
+