@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,322 @@
1
+ /**
2
+ * @module @kb-labs/adapters-pino
3
+ * Pino adapter implementing ILogger interface.
4
+ *
5
+ * @example
6
+ * ```typescript
7
+ * import { createAdapter } from '@kb-labs/adapters-pino';
8
+ *
9
+ * const logger = createAdapter({
10
+ * level: 'info',
11
+ * pretty: true,
12
+ * });
13
+ *
14
+ * logger.info('Server started', { port: 3000 });
15
+ * logger.error('Failed to connect', new Error('Connection timeout'));
16
+ *
17
+ * const childLogger = logger.child({ service: 'api' });
18
+ * childLogger.debug('Request received');
19
+ * ```
20
+ */
21
+
22
+ import pino, { type Logger as PinoLoggerInstance } from "pino";
23
+ import type { ILogger, ILogBuffer, LogRecord } from "@kb-labs/core-platform";
24
+ import { generateLogId } from "@kb-labs/core-platform/adapters";
25
+ import { LogRingBuffer } from "./log-ring-buffer";
26
+
27
+ // Re-export manifest
28
+ export { manifest } from "./manifest.js";
29
+
30
+ /**
31
+ * Configuration for log streaming/buffering
32
+ */
33
+ export interface StreamingConfig {
34
+ /** Enable log buffering for streaming (default: false) */
35
+ enabled: boolean;
36
+ /** Maximum buffer size (number of log records, default: 1000) */
37
+ bufferSize?: number;
38
+ /** Maximum age of logs in buffer (milliseconds, default: 3600000 = 1 hour) */
39
+ bufferMaxAge?: number;
40
+ }
41
+
42
+ /**
43
+ * Configuration for Pino logger adapter.
44
+ */
45
+ export interface PinoLoggerConfig {
46
+ /** Log level (default: 'info') */
47
+ level?: "trace" | "debug" | "info" | "warn" | "error" | "fatal";
48
+ /** Enable pretty printing for development (default: false) */
49
+ pretty?: boolean;
50
+ /** Streaming configuration (optional) */
51
+ streaming?: StreamingConfig;
52
+ /** Additional pino options */
53
+ options?: pino.LoggerOptions;
54
+ }
55
+
56
+ /**
57
+ * Pino implementation of ILogger interface.
58
+ */
59
+ export class PinoLoggerAdapter implements ILogger {
60
+ private pino: PinoLoggerInstance;
61
+ private logBuffer?: LogRingBuffer;
62
+ private logCallbacks = new Set<(record: LogRecord) => void>();
63
+ private bindings: Record<string, unknown> = {};
64
+
65
+ constructor(config: PinoLoggerConfig = {}) {
66
+ // Resolve log level with priority: ENV var > config.level > 'info'
67
+ // This allows overriding via KB_LOG_LEVEL or LOG_LEVEL environment variables
68
+ const resolvedLevel =
69
+ (process.env.KB_LOG_LEVEL as PinoLoggerConfig["level"]) ??
70
+ (process.env.LOG_LEVEL as PinoLoggerConfig["level"]) ??
71
+ config.level ??
72
+ "info";
73
+
74
+ // Initialize log buffer if streaming is enabled
75
+ if (config.streaming?.enabled) {
76
+ this.logBuffer = new LogRingBuffer(
77
+ config.streaming.bufferSize ?? 1000,
78
+ config.streaming.bufferMaxAge ?? 3600000,
79
+ );
80
+ }
81
+
82
+ const transport = config.pretty
83
+ ? {
84
+ target: "pino-pretty",
85
+ options: {
86
+ colorize: true,
87
+ translateTime: "SYS:standard",
88
+ ignore: "pid,hostname",
89
+ },
90
+ }
91
+ : undefined;
92
+
93
+ // Merge options, but transport from config.options takes precedence
94
+ const finalTransport = config.options?.transport ?? transport;
95
+
96
+ // Always use single pino instance (no multistream)
97
+ // LogRingBuffer is fed directly in log methods, not via Pino stream
98
+ this.pino = pino({
99
+ level: resolvedLevel,
100
+ ...config.options,
101
+ transport: finalTransport,
102
+ });
103
+ }
104
+
105
+ /**
106
+ * Emit log record to all registered callbacks (extensions).
107
+ * Fire-and-forget - errors in callbacks don't block logging.
108
+ */
109
+ private emitLog(record: LogRecord): void {
110
+ if (this.logCallbacks.size === 0) {
111
+ return;
112
+ }
113
+
114
+ for (const callback of this.logCallbacks) {
115
+ try {
116
+ callback(record);
117
+ } catch (error) {
118
+ console.error("[PinoLogger] Error in onLog callback:", error);
119
+ }
120
+ }
121
+ }
122
+
123
+ /**
124
+ * Internal constructor for child loggers.
125
+ */
126
+ private constructor_child(pinoInstance: PinoLoggerInstance, bindings: Record<string, unknown>) {
127
+ const instance = Object.create(PinoLoggerAdapter.prototype);
128
+ instance.pino = pinoInstance;
129
+ instance.logCallbacks = this.logCallbacks; // Share callbacks with parent
130
+ instance.logBuffer = this.logBuffer; // Share buffer with parent
131
+ instance.bindings = bindings;
132
+ return instance;
133
+ }
134
+
135
+ private mergeBindings(meta?: Record<string, unknown>): Record<string, unknown> {
136
+ if (!meta) {
137
+ return { ...this.bindings };
138
+ }
139
+ return { ...this.bindings, ...meta };
140
+ }
141
+
142
+ info(message: string, meta?: Record<string, unknown>): void {
143
+ const logId = generateLogId();
144
+ const timestamp = Date.now();
145
+ const mergedMeta = this.mergeBindings(meta);
146
+
147
+ this.pino.info(meta ?? {}, message);
148
+
149
+ const record: LogRecord = {
150
+ id: logId,
151
+ timestamp,
152
+ level: "info",
153
+ message,
154
+ fields: mergedMeta,
155
+ source: (mergedMeta.source as string) ?? "unknown",
156
+ };
157
+
158
+ this.logBuffer?.append(record);
159
+ this.emitLog(record);
160
+ }
161
+
162
+ warn(message: string, meta?: Record<string, unknown>): void {
163
+ const logId = generateLogId();
164
+ const timestamp = Date.now();
165
+ const mergedMeta = this.mergeBindings(meta);
166
+
167
+ this.pino.warn(meta ?? {}, message);
168
+
169
+ const record: LogRecord = {
170
+ id: logId,
171
+ timestamp,
172
+ level: "warn",
173
+ message,
174
+ fields: mergedMeta,
175
+ source: (mergedMeta.source as string) ?? "unknown",
176
+ };
177
+
178
+ this.logBuffer?.append(record);
179
+ this.emitLog(record);
180
+ }
181
+
182
+ error(message: string, error?: Error, meta?: Record<string, unknown>): void {
183
+ const logId = generateLogId();
184
+ const timestamp = Date.now();
185
+ const mergedMeta = this.mergeBindings(meta);
186
+
187
+ const enrichedMeta = {
188
+ ...mergedMeta,
189
+ ...(error && {
190
+ error: {
191
+ message: error.message,
192
+ stack: error.stack,
193
+ name: error.name,
194
+ },
195
+ }),
196
+ };
197
+
198
+ this.pino.error(enrichedMeta, message);
199
+
200
+ const record: LogRecord = {
201
+ id: logId,
202
+ timestamp,
203
+ level: "error",
204
+ message,
205
+ fields: enrichedMeta,
206
+ source: (mergedMeta.source as string) ?? "unknown",
207
+ };
208
+
209
+ this.logBuffer?.append(record);
210
+ this.emitLog(record);
211
+ }
212
+
213
+ fatal(message: string, error?: Error, meta?: Record<string, unknown>): void {
214
+ const logId = generateLogId();
215
+ const timestamp = Date.now();
216
+ const mergedMeta = this.mergeBindings(meta);
217
+
218
+ const enrichedMeta = {
219
+ ...mergedMeta,
220
+ ...(error && {
221
+ error: {
222
+ message: error.message,
223
+ stack: error.stack,
224
+ name: error.name,
225
+ },
226
+ }),
227
+ };
228
+
229
+ this.pino.fatal(enrichedMeta, message);
230
+
231
+ const record: LogRecord = {
232
+ id: logId,
233
+ timestamp,
234
+ level: "fatal",
235
+ message,
236
+ fields: enrichedMeta,
237
+ source: (mergedMeta.source as string) ?? "unknown",
238
+ };
239
+
240
+ this.logBuffer?.append(record);
241
+ this.emitLog(record);
242
+ }
243
+
244
+ debug(message: string, meta?: Record<string, unknown>): void {
245
+ const logId = generateLogId();
246
+ const timestamp = Date.now();
247
+ const mergedMeta = this.mergeBindings(meta);
248
+
249
+ this.pino.debug(meta ?? {}, message);
250
+
251
+ const record: LogRecord = {
252
+ id: logId,
253
+ timestamp,
254
+ level: "debug",
255
+ message,
256
+ fields: mergedMeta,
257
+ source: (mergedMeta.source as string) ?? "unknown",
258
+ };
259
+
260
+ this.logBuffer?.append(record);
261
+ this.emitLog(record);
262
+ }
263
+
264
+ trace(message: string, meta?: Record<string, unknown>): void {
265
+ const logId = generateLogId();
266
+ const timestamp = Date.now();
267
+ const mergedMeta = this.mergeBindings(meta);
268
+
269
+ this.pino.trace(meta ?? {}, message);
270
+
271
+ const record: LogRecord = {
272
+ id: logId,
273
+ timestamp,
274
+ level: "trace",
275
+ message,
276
+ fields: mergedMeta,
277
+ source: (mergedMeta.source as string) ?? "unknown",
278
+ };
279
+
280
+ this.logBuffer?.append(record);
281
+ this.emitLog(record);
282
+ }
283
+
284
+ child(bindings: Record<string, unknown>): ILogger {
285
+ const mergedBindings = { ...this.bindings, ...bindings };
286
+ const childPino = this.pino.child(bindings);
287
+ return this.constructor_child(childPino, mergedBindings);
288
+ }
289
+
290
+ /**
291
+ * Get log buffer for streaming/querying (ILogger optional method)
292
+ */
293
+ getLogBuffer(): ILogBuffer | undefined {
294
+ return this.logBuffer;
295
+ }
296
+
297
+ /**
298
+ * Register callback for every log event (ILogger optional method).
299
+ * Used by platform to connect logger extensions (ring buffer, persistence).
300
+ *
301
+ * @param callback - Function to call on each log event
302
+ * @returns Unsubscribe function to remove the callback
303
+ */
304
+ onLog(callback: (record: LogRecord) => void): () => void {
305
+ this.logCallbacks.add(callback);
306
+ return () => this.logCallbacks.delete(callback);
307
+ }
308
+ }
309
+
310
+ /**
311
+ * Create Pino logger adapter.
312
+ * This is the factory function called by initPlatform() when loading adapters.
313
+ */
314
+ export function createAdapter(config?: PinoLoggerConfig): PinoLoggerAdapter {
315
+ return new PinoLoggerAdapter(config);
316
+ }
317
+
318
+ // Default export for direct import
319
+ export default createAdapter;
320
+
321
+ // Export buffer class
322
+ export { LogRingBuffer } from "./log-ring-buffer";
@@ -0,0 +1,142 @@
1
+ /**
2
+ * @module @kb-labs/adapters-pino/log-ring-buffer
3
+ * Ring buffer for in-memory log storage with real-time streaming
4
+ */
5
+
6
+ import type {
7
+ LogRecord,
8
+ LogQuery,
9
+ ILogBuffer,
10
+ LogLevel,
11
+ } from "@kb-labs/core-platform";
12
+
13
+ /**
14
+ * Ring buffer implementation for log storage
15
+ */
16
+ export class LogRingBuffer implements ILogBuffer {
17
+ private buffer: LogRecord[] = [];
18
+ private subscribers: Set<(record: LogRecord) => void> = new Set();
19
+ private readonly maxSize: number;
20
+ private readonly maxAge: number;
21
+
22
+ constructor(maxSize: number = 1000, maxAge: number = 3600000) {
23
+ this.maxSize = maxSize;
24
+ this.maxAge = maxAge; // milliseconds
25
+ }
26
+
27
+ /**
28
+ * Append log record to buffer
29
+ */
30
+ append(record: LogRecord): void {
31
+ // Add to buffer
32
+ this.buffer.push(record);
33
+
34
+ // Evict old entries by size
35
+ if (this.buffer.length > this.maxSize) {
36
+ this.buffer.shift();
37
+ }
38
+
39
+ // Evict old entries by age
40
+ const now = Date.now();
41
+ const cutoff = now - this.maxAge;
42
+ while (this.buffer.length > 0 && this.buffer[0]!.timestamp < cutoff) {
43
+ this.buffer.shift();
44
+ }
45
+
46
+ // Notify subscribers
47
+ for (const subscriber of this.subscribers) {
48
+ try {
49
+ subscriber(record);
50
+ } catch (error) {
51
+ // Ignore subscriber errors
52
+ console.error("[LogRingBuffer] Subscriber error:", error);
53
+ }
54
+ }
55
+ }
56
+
57
+ /**
58
+ * Query logs with filters
59
+ */
60
+ query(query?: LogQuery): LogRecord[] {
61
+ let results = [...this.buffer];
62
+
63
+ if (!query) {
64
+ return results;
65
+ }
66
+
67
+ // Filter by time range
68
+ if (query.from !== undefined) {
69
+ results = results.filter((r) => r.timestamp >= query.from!);
70
+ }
71
+ if (query.to !== undefined) {
72
+ results = results.filter((r) => r.timestamp <= query.to!);
73
+ }
74
+
75
+ // Filter by source
76
+ if (query.source !== undefined) {
77
+ results = results.filter((r) => r.source === query.source);
78
+ }
79
+
80
+ // Filter by level (minimum level)
81
+ if (query.level !== undefined) {
82
+ const levels: LogLevel[] = [
83
+ "trace",
84
+ "debug",
85
+ "info",
86
+ "warn",
87
+ "error",
88
+ "fatal",
89
+ ];
90
+ const minLevelIndex = levels.indexOf(query.level);
91
+ results = results.filter((r) => {
92
+ const recordLevelIndex = levels.indexOf(r.level);
93
+ return recordLevelIndex >= minLevelIndex;
94
+ });
95
+ }
96
+
97
+ // Apply limit
98
+ if (query.limit !== undefined && query.limit > 0) {
99
+ results = results.slice(-query.limit); // Take most recent N
100
+ }
101
+
102
+ return results;
103
+ }
104
+
105
+ /**
106
+ * Subscribe to real-time log stream
107
+ */
108
+ subscribe(callback: (record: LogRecord) => void): () => void {
109
+ this.subscribers.add(callback);
110
+ return () => {
111
+ this.subscribers.delete(callback);
112
+ };
113
+ }
114
+
115
+ /**
116
+ * Find log by ID in buffer
117
+ */
118
+ findById(id: string): LogRecord | undefined {
119
+ return this.buffer.find((record) => record.id === id);
120
+ }
121
+
122
+ /**
123
+ * Get buffer statistics
124
+ */
125
+ getStats(): {
126
+ total: number;
127
+ bufferSize: number;
128
+ oldestTimestamp: number | null;
129
+ newestTimestamp: number | null;
130
+ } {
131
+ return {
132
+ total: this.buffer.length,
133
+ bufferSize: this.maxSize,
134
+ oldestTimestamp:
135
+ this.buffer.length > 0 ? this.buffer[0]!.timestamp : null,
136
+ newestTimestamp:
137
+ this.buffer.length > 0
138
+ ? this.buffer[this.buffer.length - 1]!.timestamp
139
+ : null,
140
+ };
141
+ }
142
+ }
@@ -0,0 +1,49 @@
1
+ /**
2
+ * @module @kb-labs/adapters-pino/manifest
3
+ * Adapter manifest for Pino logger.
4
+ */
5
+
6
+ import type { AdapterManifest } from "@kb-labs/core-platform";
7
+
8
+ /**
9
+ * Adapter manifest for Pino logger.
10
+ */
11
+ export const manifest: AdapterManifest = {
12
+ manifestVersion: "1.0.0",
13
+ id: "pino-logger",
14
+ name: "Pino Logger",
15
+ version: "1.0.0",
16
+ description: "Production-ready structured logger based on Pino",
17
+ author: "KB Labs Team",
18
+ license: "KBPL-1.1",
19
+ type: "core",
20
+ implements: "ILogger",
21
+ optional: {
22
+ adapters: ["analytics"],
23
+ },
24
+ capabilities: {
25
+ streaming: true,
26
+ },
27
+ configSchema: {
28
+ level: {
29
+ type: "string",
30
+ enum: ["trace", "debug", "info", "warn", "error", "fatal"],
31
+ default: "info",
32
+ description: "Minimum log level",
33
+ },
34
+ pretty: {
35
+ type: "boolean",
36
+ default: false,
37
+ description: "Enable pretty printing for development",
38
+ },
39
+ streaming: {
40
+ type: "object",
41
+ description: "Log streaming/buffering configuration",
42
+ properties: {
43
+ enabled: { type: "boolean", default: false },
44
+ bufferSize: { type: "number", default: 1000 },
45
+ bufferMaxAge: { type: "number", default: 3600000 },
46
+ },
47
+ },
48
+ },
49
+ };
@@ -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,9 @@
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
+ entry: ['src/index.ts', 'src/manifest.ts'],
8
+ dts: true,
9
+ });
@@ -0,0 +1,141 @@
1
+ # @kb-labs/adapters-pino-http
2
+
3
+ > Part of [KB Labs](https://github.com/KirillBaranov/kb-labs) ecosystem. Works exclusively within KB Labs platform.
4
+
5
+ Pino HTTP transport for streaming logs to KB Labs REST API.
6
+
7
+ ## Features
8
+
9
+ - ✅ **Batching** - Configurable batch size and flush interval
10
+ - ✅ **Retry Logic** - Exponential backoff on HTTP failures
11
+ - ✅ **Graceful Shutdown** - Flushes pending logs before exit
12
+ - ✅ **Error Handling** - Logs to stderr if HTTP fails
13
+ - ✅ **Lightweight** - Minimal dependencies, uses native `fetch`
14
+
15
+ ## Installation
16
+
17
+ ```bash
18
+ pnpm add @kb-labs/adapters-pino-http
19
+ ```
20
+
21
+ ## Usage
22
+
23
+ ### Basic Setup
24
+
25
+ ```typescript
26
+ import pino from 'pino';
27
+
28
+ const logger = pino({
29
+ transport: {
30
+ target: '@kb-labs/adapters-pino-http',
31
+ options: {
32
+ url: 'http://localhost:5050/api/v1/logs/ingest',
33
+ batchSize: 50,
34
+ flushIntervalMs: 3000,
35
+ },
36
+ },
37
+ });
38
+
39
+ logger.info('Hello from Pino HTTP Transport!');
40
+ ```
41
+
42
+ ### With Platform DI (Recommended)
43
+
44
+ Configure in `.kb/kb.config.json`:
45
+
46
+ ```json
47
+ {
48
+ "platform": {
49
+ "adapters": {
50
+ "logger": "@kb-labs/adapters-pino"
51
+ },
52
+ "adapterOptions": {
53
+ "logger": {
54
+ "level": "info",
55
+ "options": {
56
+ "transport": {
57
+ "target": "@kb-labs/adapters-pino-http",
58
+ "options": {
59
+ "url": "http://localhost:5050/api/v1/logs/ingest",
60
+ "batchSize": 50,
61
+ "flushIntervalMs": 3000
62
+ }
63
+ }
64
+ }
65
+ }
66
+ }
67
+ }
68
+ }
69
+ ```
70
+
71
+ Then use in code:
72
+
73
+ ```typescript
74
+ import { initPlatform } from '@kb-labs/core-platform';
75
+
76
+ const platform = await initPlatform();
77
+
78
+ platform.logger.info('This log will be sent to REST API!', {
79
+ plugin: 'my-plugin',
80
+ executionId: 'exec-123',
81
+ });
82
+ ```
83
+
84
+ ## Configuration
85
+
86
+ | Option | Type | Default | Description |
87
+ |--------|------|---------|-------------|
88
+ | `url` | `string` | `http://localhost:5050/api/v1/logs/ingest` | REST API endpoint for log ingestion |
89
+ | `batchSize` | `number` | `50` | Number of logs to batch before sending |
90
+ | `flushIntervalMs` | `number` | `3000` | Max time in ms to wait before flushing batch |
91
+ | `retryAttempts` | `number` | `3` | Number of retry attempts on HTTP failure |
92
+ | `retryDelayMs` | `number` | `1000` | Initial retry delay in ms (exponential backoff) |
93
+ | `headers` | `Record<string, string>` | `{}` | Custom HTTP headers (e.g., for authentication) |
94
+ | `debug` | `boolean` | `false` | Enable debug logging to stderr |
95
+
96
+ ## How It Works
97
+
98
+ 1. **Pino logs** are written to the transport stream
99
+ 2. **Batch accumulation** - Logs are collected into a batch
100
+ 3. **Flush trigger** - Batch is sent when:
101
+ - Batch size reaches `batchSize` (immediate flush)
102
+ - `flushIntervalMs` timer expires (delayed flush)
103
+ - Process exits (graceful shutdown)
104
+ 4. **HTTP POST** - Batch is sent to REST API with retry logic
105
+ 5. **Retry on failure** - Exponential backoff (1s → 2s → 4s)
106
+ 6. **Error logging** - Failures are logged to stderr
107
+
108
+ ## Performance
109
+
110
+ - **Batching reduces HTTP overhead**: 50 logs/request vs 50 requests
111
+ - **Non-blocking**: Uses async `fetch`, doesn't block Pino
112
+ - **Memory-safe**: Ring buffer in REST API prevents OOM
113
+
114
+ ## Debugging
115
+
116
+ Enable debug mode to see transport activity:
117
+
118
+ ```json
119
+ {
120
+ "transport": {
121
+ "target": "@kb-labs/adapters-pino-http",
122
+ "options": {
123
+ "url": "http://localhost:5050/api/v1/logs/ingest",
124
+ "debug": true
125
+ }
126
+ }
127
+ }
128
+ ```
129
+
130
+ Output:
131
+
132
+ ```
133
+ [PinoHTTP] Flushing 50 logs to http://localhost:5050/api/v1/logs/ingest
134
+ [PinoHTTP] Flush successful
135
+ [PinoHTTP] Shutting down, flushing pending logs...
136
+ [PinoHTTP] Shutdown complete
137
+ ```
138
+
139
+ ## License
140
+
141
+ [KB Public License v1.1](../../LICENSE) - KB Labs Team