@tunnlo/core 0.1.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 (57) hide show
  1. package/dist/bus.d.ts +19 -0
  2. package/dist/bus.d.ts.map +1 -0
  3. package/dist/bus.js +45 -0
  4. package/dist/bus.js.map +1 -0
  5. package/dist/bus.test.d.ts +2 -0
  6. package/dist/bus.test.d.ts.map +1 -0
  7. package/dist/bus.test.js +48 -0
  8. package/dist/bus.test.js.map +1 -0
  9. package/dist/event.d.ts +16 -0
  10. package/dist/event.d.ts.map +1 -0
  11. package/dist/event.js +83 -0
  12. package/dist/event.js.map +1 -0
  13. package/dist/event.test.d.ts +2 -0
  14. package/dist/event.test.d.ts.map +1 -0
  15. package/dist/event.test.js +40 -0
  16. package/dist/event.test.js.map +1 -0
  17. package/dist/fast-bus.d.ts +25 -0
  18. package/dist/fast-bus.d.ts.map +1 -0
  19. package/dist/fast-bus.js +114 -0
  20. package/dist/fast-bus.js.map +1 -0
  21. package/dist/fast-bus.test.d.ts +2 -0
  22. package/dist/fast-bus.test.d.ts.map +1 -0
  23. package/dist/fast-bus.test.js +63 -0
  24. package/dist/fast-bus.test.js.map +1 -0
  25. package/dist/index.d.ts +16 -0
  26. package/dist/index.d.ts.map +1 -0
  27. package/dist/index.js +9 -0
  28. package/dist/index.js.map +1 -0
  29. package/dist/kafka-bus.d.ts +27 -0
  30. package/dist/kafka-bus.d.ts.map +1 -0
  31. package/dist/kafka-bus.js +142 -0
  32. package/dist/kafka-bus.js.map +1 -0
  33. package/dist/logger.d.ts +30 -0
  34. package/dist/logger.d.ts.map +1 -0
  35. package/dist/logger.js +125 -0
  36. package/dist/logger.js.map +1 -0
  37. package/dist/pipeline.d.ts +54 -0
  38. package/dist/pipeline.d.ts.map +1 -0
  39. package/dist/pipeline.js +209 -0
  40. package/dist/pipeline.js.map +1 -0
  41. package/dist/pipeline.test.d.ts +2 -0
  42. package/dist/pipeline.test.d.ts.map +1 -0
  43. package/dist/pipeline.test.js +114 -0
  44. package/dist/pipeline.test.js.map +1 -0
  45. package/dist/redis-bus.d.ts +25 -0
  46. package/dist/redis-bus.d.ts.map +1 -0
  47. package/dist/redis-bus.js +140 -0
  48. package/dist/redis-bus.js.map +1 -0
  49. package/dist/state-store.d.ts +12 -0
  50. package/dist/state-store.d.ts.map +1 -0
  51. package/dist/state-store.js +36 -0
  52. package/dist/state-store.js.map +1 -0
  53. package/dist/types.d.ts +118 -0
  54. package/dist/types.d.ts.map +1 -0
  55. package/dist/types.js +2 -0
  56. package/dist/types.js.map +1 -0
  57. package/package.json +27 -0
@@ -0,0 +1,142 @@
1
+ import { validateEvent } from './event.js';
2
+ import { getLogger } from './logger.js';
3
+ export class KafkaBus {
4
+ subscribers = new Map();
5
+ closed = false;
6
+ connected = false;
7
+ kafka;
8
+ producer;
9
+ consumers = new Map();
10
+ config;
11
+ constructor(config) {
12
+ this.config = {
13
+ brokers: config.brokers,
14
+ clientId: config.clientId ?? 'tunnlo',
15
+ groupId: config.groupId ?? 'tunnlo-group',
16
+ maxBatchSize: config.maxBatchSize ?? 1000,
17
+ lingerMs: config.lingerMs ?? 5,
18
+ };
19
+ }
20
+ async connect() {
21
+ const kafkajs = await Function('return import("kafkajs")')();
22
+ const { Kafka } = kafkajs;
23
+ this.kafka = new Kafka({
24
+ clientId: this.config.clientId,
25
+ brokers: this.config.brokers,
26
+ });
27
+ this.producer = this.kafka.producer({
28
+ allowAutoTopicCreation: true,
29
+ maxInFlightRequests: 5,
30
+ idempotent: true,
31
+ });
32
+ await this.producer.connect();
33
+ this.connected = true;
34
+ }
35
+ ensureConnected() {
36
+ if (!this.connected || !this.kafka) {
37
+ throw new Error('[tunnlo:kafka-bus] Not connected. Call connect() before using the bus.');
38
+ }
39
+ }
40
+ async publish(topic, event) {
41
+ if (this.closed)
42
+ return;
43
+ this.ensureConnected();
44
+ const kafkaTopic = `tunnlo-${topic}`;
45
+ if (this.producer) {
46
+ await this.producer.send({
47
+ topic: kafkaTopic,
48
+ messages: [
49
+ {
50
+ key: event.source_id,
51
+ value: JSON.stringify(event),
52
+ headers: {
53
+ event_type: event.event_type,
54
+ priority: String(event.priority ?? 3),
55
+ },
56
+ },
57
+ ],
58
+ });
59
+ }
60
+ // Also deliver to local subscribers
61
+ const subs = this.subscribers.get(topic);
62
+ if (subs) {
63
+ for (const cb of subs) {
64
+ try {
65
+ await cb(event);
66
+ }
67
+ catch (err) {
68
+ getLogger().error(`[tunnlo:kafka-bus] subscriber error on topic "${topic}":`, err);
69
+ }
70
+ }
71
+ }
72
+ }
73
+ subscribe(topic, callback) {
74
+ if (!this.subscribers.has(topic)) {
75
+ this.subscribers.set(topic, new Set());
76
+ }
77
+ this.subscribers.get(topic).add(callback);
78
+ if (this.connected && !this.consumers.has(topic)) {
79
+ this.consumeTopic(topic).catch((err) => {
80
+ getLogger().error(`[tunnlo:kafka-bus] consumer error for "${topic}":`, err);
81
+ });
82
+ }
83
+ }
84
+ unsubscribe(topic, callback) {
85
+ this.subscribers.get(topic)?.delete(callback);
86
+ }
87
+ async close() {
88
+ this.closed = true;
89
+ for (const [, consumer] of this.consumers) {
90
+ try {
91
+ await consumer.disconnect();
92
+ }
93
+ catch {
94
+ // best effort
95
+ }
96
+ }
97
+ this.consumers.clear();
98
+ if (this.producer) {
99
+ await this.producer.disconnect();
100
+ this.producer = null;
101
+ }
102
+ this.subscribers.clear();
103
+ }
104
+ async consumeTopic(topic) {
105
+ const kafkaTopic = `tunnlo-${topic}`;
106
+ const consumer = this.kafka.consumer({
107
+ groupId: `${this.config.groupId}-${topic}`,
108
+ });
109
+ await consumer.connect();
110
+ await consumer.subscribe({ topic: kafkaTopic, fromBeginning: false });
111
+ this.consumers.set(topic, consumer);
112
+ await consumer.run({
113
+ eachMessage: async ({ message }) => {
114
+ if (this.closed)
115
+ return;
116
+ try {
117
+ const parsed = JSON.parse(message.value.toString());
118
+ if (!validateEvent(parsed)) {
119
+ getLogger().error(`[tunnlo:kafka-bus] invalid event structure, skipping`);
120
+ return;
121
+ }
122
+ const event = parsed;
123
+ const subs = this.subscribers.get(topic);
124
+ if (subs) {
125
+ for (const cb of subs) {
126
+ try {
127
+ await cb(event);
128
+ }
129
+ catch (cbErr) {
130
+ getLogger().error(`[tunnlo:kafka-bus] subscriber callback error:`, cbErr);
131
+ }
132
+ }
133
+ }
134
+ }
135
+ catch (err) {
136
+ getLogger().error(`[tunnlo:kafka-bus] message parse error:`, err);
137
+ }
138
+ },
139
+ });
140
+ }
141
+ }
142
+ //# sourceMappingURL=kafka-bus.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kafka-bus.js","sourceRoot":"","sources":["../src/kafka-bus.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ export type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'quiet';
2
+ export type LogFormat = 'text' | 'json';
3
+ export interface LoggerOptions {
4
+ level?: LogLevel;
5
+ logFile?: string;
6
+ format?: LogFormat;
7
+ }
8
+ export declare class Logger {
9
+ private level;
10
+ private fileHandle;
11
+ private format;
12
+ constructor(options?: LoggerOptions);
13
+ private shouldLog;
14
+ private formatTimestamp;
15
+ private writeToFile;
16
+ private formatOutput;
17
+ debug(msg: string, ...args: any[]): void;
18
+ info(msg: string, ...args: any[]): void;
19
+ warn(msg: string, ...args: any[]): void;
20
+ error(msg: string, ...args: any[]): void;
21
+ /** Always prints regardless of level (for banners, prompts) */
22
+ always(msg: string, ...args: any[]): void;
23
+ setLevel(level: LogLevel): void;
24
+ getLevel(): LogLevel;
25
+ getFormat(): LogFormat;
26
+ close(): Promise<void>;
27
+ }
28
+ export declare function getLogger(): Logger;
29
+ export declare function setGlobalLogger(logger: Logger): void;
30
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC;AACrE,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,MAAM,CAAC;AAUxC,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,EAAE,QAAQ,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,SAAS,CAAC;CACpB;AAED,qBAAa,MAAM;IACjB,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,UAAU,CAA4B;IAC9C,OAAO,CAAC,MAAM,CAAY;gBAEd,OAAO,GAAE,aAAkB;IAQvC,OAAO,CAAC,SAAS;IAIjB,OAAO,CAAC,eAAe;IAIvB,OAAO,CAAC,WAAW;IAMnB,OAAO,CAAC,YAAY;IAepB,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI;IAUxC,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI;IAUvC,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI;IAUvC,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI;IAUxC,+DAA+D;IAC/D,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI;IASzC,QAAQ,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI;IAI/B,QAAQ,IAAI,QAAQ;IAKpB,SAAS,IAAI,SAAS;IAIhB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAO7B;AAKD,wBAAgB,SAAS,IAAI,MAAM,CAElC;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAEpD"}
package/dist/logger.js ADDED
@@ -0,0 +1,125 @@
1
+ import { createWriteStream } from 'node:fs';
2
+ const LEVEL_ORDER = {
3
+ debug: 0,
4
+ info: 1,
5
+ warn: 2,
6
+ error: 3,
7
+ quiet: 4,
8
+ };
9
+ export class Logger {
10
+ level;
11
+ fileHandle = null;
12
+ format;
13
+ constructor(options = {}) {
14
+ this.level = LEVEL_ORDER[options.level ?? 'info'];
15
+ this.format = options.format ?? 'text';
16
+ if (options.logFile) {
17
+ this.fileHandle = createWriteStream(options.logFile, { flags: 'a' });
18
+ }
19
+ }
20
+ shouldLog(level) {
21
+ return LEVEL_ORDER[level] >= this.level;
22
+ }
23
+ formatTimestamp() {
24
+ return new Date().toISOString();
25
+ }
26
+ writeToFile(level, msg) {
27
+ if (this.fileHandle) {
28
+ this.fileHandle.write(`${this.formatTimestamp()} [${level.toUpperCase()}] ${msg}\n`);
29
+ }
30
+ }
31
+ formatOutput(level, msg, args) {
32
+ if (this.format === 'json') {
33
+ const entry = {
34
+ timestamp: this.formatTimestamp(),
35
+ level,
36
+ message: msg,
37
+ };
38
+ if (args.length > 0) {
39
+ entry.data = args.length === 1 ? args[0] : args;
40
+ }
41
+ return JSON.stringify(entry);
42
+ }
43
+ return msg;
44
+ }
45
+ debug(msg, ...args) {
46
+ this.writeToFile('debug', msg);
47
+ if (!this.shouldLog('debug'))
48
+ return;
49
+ if (this.format === 'json') {
50
+ console.debug(this.formatOutput('debug', msg, args));
51
+ }
52
+ else {
53
+ console.debug(`[tunnlo:debug] ${msg}`, ...args);
54
+ }
55
+ }
56
+ info(msg, ...args) {
57
+ this.writeToFile('info', msg);
58
+ if (!this.shouldLog('info'))
59
+ return;
60
+ if (this.format === 'json') {
61
+ console.log(this.formatOutput('info', msg, args));
62
+ }
63
+ else {
64
+ console.log(msg, ...args);
65
+ }
66
+ }
67
+ warn(msg, ...args) {
68
+ this.writeToFile('warn', msg);
69
+ if (!this.shouldLog('warn'))
70
+ return;
71
+ if (this.format === 'json') {
72
+ console.warn(this.formatOutput('warn', msg, args));
73
+ }
74
+ else {
75
+ console.warn(msg, ...args);
76
+ }
77
+ }
78
+ error(msg, ...args) {
79
+ this.writeToFile('error', msg);
80
+ if (!this.shouldLog('error'))
81
+ return;
82
+ if (this.format === 'json') {
83
+ console.error(this.formatOutput('error', msg, args));
84
+ }
85
+ else {
86
+ console.error(msg, ...args);
87
+ }
88
+ }
89
+ /** Always prints regardless of level (for banners, prompts) */
90
+ always(msg, ...args) {
91
+ this.writeToFile('info', msg);
92
+ if (this.format === 'json') {
93
+ console.log(this.formatOutput('info', msg, args));
94
+ }
95
+ else {
96
+ console.log(msg, ...args);
97
+ }
98
+ }
99
+ setLevel(level) {
100
+ this.level = LEVEL_ORDER[level];
101
+ }
102
+ getLevel() {
103
+ const entries = Object.entries(LEVEL_ORDER);
104
+ return entries.find(([, v]) => v === this.level)?.[0] ?? 'info';
105
+ }
106
+ getFormat() {
107
+ return this.format;
108
+ }
109
+ async close() {
110
+ if (this.fileHandle) {
111
+ return new Promise((resolve) => {
112
+ this.fileHandle.end(() => resolve());
113
+ });
114
+ }
115
+ }
116
+ }
117
+ /** Global singleton logger. Call `setGlobalLogger` to reconfigure. */
118
+ let globalLogger = new Logger();
119
+ export function getLogger() {
120
+ return globalLogger;
121
+ }
122
+ export function setGlobalLogger(logger) {
123
+ globalLogger = logger;
124
+ }
125
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,54 @@
1
+ import type { Adapter, AgentBridge, AgentConfig, Filter, TunnloEvent, ActionHandler, BehaviorConfig } from './types.js';
2
+ import type { MessageBus } from './bus.js';
3
+ export interface MetricsPort {
4
+ recordEventReceived(event: TunnloEvent): void;
5
+ recordEventFiltered(filterName: string, passed: boolean): void;
6
+ recordEventSentToLlm(eventId: string, latencyMs: number): void;
7
+ recordEventDropped(): void;
8
+ recordEventBuffered(): void;
9
+ recordTokensUsed(tokens: number): void;
10
+ recordError(source: string, message: string): void;
11
+ updateAdapterStatus(id: string, status: string): void;
12
+ recordLlmResponse?(entry: {
13
+ event_id: string;
14
+ source_id: string;
15
+ content: string;
16
+ tokens_used: number;
17
+ latency_ms: number;
18
+ has_actions: boolean;
19
+ }): void;
20
+ }
21
+ export interface PipelineOptions {
22
+ bus: MessageBus;
23
+ adapters: Map<string, Adapter>;
24
+ filters: Filter[];
25
+ bridge: AgentBridge;
26
+ agentConfig: AgentConfig;
27
+ actionHandlers: ActionHandler[];
28
+ behavior?: BehaviorConfig;
29
+ metrics?: MetricsPort;
30
+ }
31
+ export declare class Pipeline {
32
+ private bus;
33
+ private adapters;
34
+ private filters;
35
+ private bridge;
36
+ private agentConfig;
37
+ private actionHandlers;
38
+ private behavior;
39
+ private running;
40
+ private abortController;
41
+ private tokensUsedThisHour;
42
+ private hourStart;
43
+ private metrics?;
44
+ constructor(options: PipelineOptions);
45
+ start(): Promise<void>;
46
+ private flushFilters;
47
+ stop(): Promise<void>;
48
+ isRunning(): boolean;
49
+ private runAdapter;
50
+ private applyFilters;
51
+ private resetHourlyBudgetIfNeeded;
52
+ private sendToAgent;
53
+ }
54
+ //# sourceMappingURL=pipeline.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipeline.d.ts","sourceRoot":"","sources":["../src/pipeline.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,OAAO,EAEP,WAAW,EACX,WAAW,EACX,MAAM,EACN,WAAW,EACX,aAAa,EACb,cAAc,EACf,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAI3C,MAAM,WAAW,WAAW;IAC1B,mBAAmB,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI,CAAC;IAC9C,mBAAmB,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,IAAI,CAAC;IAC/D,oBAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/D,kBAAkB,IAAI,IAAI,CAAC;IAC3B,mBAAmB,IAAI,IAAI,CAAC;IAC5B,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACnD,mBAAmB,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtD,iBAAiB,CAAC,CAAC,KAAK,EAAE;QACxB,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,EAAE,MAAM,CAAC;QAChB,WAAW,EAAE,MAAM,CAAC;QACpB,UAAU,EAAE,MAAM,CAAC;QACnB,WAAW,EAAE,OAAO,CAAC;KACtB,GAAG,IAAI,CAAC;CACV;AAED,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,UAAU,CAAC;IAChB,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,EAAE,WAAW,CAAC;IACpB,WAAW,EAAE,WAAW,CAAC;IACzB,cAAc,EAAE,aAAa,EAAE,CAAC;IAChC,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,OAAO,CAAC,EAAE,WAAW,CAAC;CACvB;AAED,qBAAa,QAAQ;IACnB,OAAO,CAAC,GAAG,CAAa;IACxB,OAAO,CAAC,QAAQ,CAAuB;IACvC,OAAO,CAAC,OAAO,CAAW;IAC1B,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,cAAc,CAA6B;IACnD,OAAO,CAAC,QAAQ,CAAiB;IACjC,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,eAAe,CAAgC;IACvD,OAAO,CAAC,kBAAkB,CAAK;IAC/B,OAAO,CAAC,SAAS,CAAc;IAC/B,OAAO,CAAC,OAAO,CAAC,CAAc;gBAElB,OAAO,EAAE,eAAe;IAa9B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;YA8Bd,YAAY;IAWpB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IA2B3B,SAAS,IAAI,OAAO;YAIN,UAAU;IAqBxB,OAAO,CAAC,YAAY;IAgBpB,OAAO,CAAC,yBAAyB;YAQnB,WAAW;CAuE1B"}
@@ -0,0 +1,209 @@
1
+ import { createEvent } from './event.js';
2
+ import { getLogger } from './logger.js';
3
+ export class Pipeline {
4
+ bus;
5
+ adapters;
6
+ filters;
7
+ bridge;
8
+ agentConfig;
9
+ actionHandlers;
10
+ behavior;
11
+ running = false;
12
+ abortController = null;
13
+ tokensUsedThisHour = 0;
14
+ hourStart = Date.now();
15
+ metrics;
16
+ constructor(options) {
17
+ this.bus = options.bus;
18
+ this.adapters = options.adapters;
19
+ this.filters = options.filters;
20
+ this.bridge = options.bridge;
21
+ this.agentConfig = options.agentConfig;
22
+ this.actionHandlers = new Map(options.actionHandlers.map((h) => [h.type, h]));
23
+ this.behavior = options.behavior ?? { on_llm_unreachable: 'drop_and_alert' };
24
+ this.metrics = options.metrics;
25
+ }
26
+ async start() {
27
+ if (this.running)
28
+ return;
29
+ this.running = true;
30
+ this.abortController = new AbortController();
31
+ this.bus.subscribe('filtered', async (event) => {
32
+ await this.sendToAgent(event);
33
+ });
34
+ this.bus.subscribe('raw', async (event) => {
35
+ this.metrics?.recordEventReceived(event);
36
+ const { result, buffered } = this.applyFilters(event);
37
+ if (result) {
38
+ await this.bus.publish('filtered', result);
39
+ }
40
+ else if (!buffered) {
41
+ this.metrics?.recordEventDropped();
42
+ }
43
+ });
44
+ const adapterPromises = [];
45
+ for (const [id, adapter] of this.adapters) {
46
+ adapterPromises.push(this.runAdapter(id, adapter));
47
+ }
48
+ await Promise.allSettled(adapterPromises);
49
+ // Flush any buffered events from windowed filters
50
+ await this.flushFilters();
51
+ }
52
+ async flushFilters() {
53
+ for (const filter of this.filters) {
54
+ if (typeof filter.flush === 'function') {
55
+ const flushed = filter.flush();
56
+ if (flushed) {
57
+ await this.bus.publish('filtered', flushed);
58
+ }
59
+ }
60
+ }
61
+ }
62
+ async stop() {
63
+ if (!this.running)
64
+ return;
65
+ this.running = false;
66
+ this.abortController?.abort();
67
+ for (const [id, adapter] of this.adapters) {
68
+ try {
69
+ await adapter.disconnect();
70
+ this.metrics?.updateAdapterStatus(id, 'disconnected');
71
+ }
72
+ catch (err) {
73
+ getLogger().error('[tunnlo:pipeline] adapter disconnect error:', err);
74
+ this.metrics?.recordError('pipeline', `adapter "${id}" disconnect error: ${err}`);
75
+ }
76
+ }
77
+ try {
78
+ await this.bridge.close();
79
+ }
80
+ catch (err) {
81
+ getLogger().error('[tunnlo:pipeline] bridge close error:', err);
82
+ }
83
+ try {
84
+ await this.bus.close();
85
+ }
86
+ catch (err) {
87
+ getLogger().error('[tunnlo:pipeline] bus close error:', err);
88
+ }
89
+ }
90
+ isRunning() {
91
+ return this.running;
92
+ }
93
+ async runAdapter(id, adapter) {
94
+ try {
95
+ for await (const raw of adapter.read()) {
96
+ if (!this.running)
97
+ break;
98
+ try {
99
+ const event = adapter.transform(raw);
100
+ await this.bus.publish('raw', event);
101
+ }
102
+ catch (err) {
103
+ getLogger().error(`[tunnlo:pipeline] transform error from "${id}":`, err);
104
+ this.metrics?.recordError(id, `transform error: ${err}`);
105
+ }
106
+ }
107
+ }
108
+ catch (err) {
109
+ if (this.running) {
110
+ getLogger().error(`[tunnlo:pipeline] adapter "${id}" read error:`, err);
111
+ this.metrics?.recordError(id, `read error: ${err}`);
112
+ this.metrics?.updateAdapterStatus(id, 'error');
113
+ }
114
+ }
115
+ }
116
+ applyFilters(event) {
117
+ let current = event;
118
+ let buffered = false;
119
+ for (const filter of this.filters) {
120
+ if (!current)
121
+ return { result: null, buffered };
122
+ const result = filter.process(current);
123
+ const isBuffering = result === null && typeof filter.flush === 'function';
124
+ if (isBuffering) {
125
+ buffered = true;
126
+ }
127
+ this.metrics?.recordEventFiltered(filter.name, result !== null || isBuffering);
128
+ current = result;
129
+ }
130
+ return { result: current, buffered };
131
+ }
132
+ resetHourlyBudgetIfNeeded() {
133
+ const now = Date.now();
134
+ if (now - this.hourStart >= 3_600_000) {
135
+ this.tokensUsedThisHour = 0;
136
+ this.hourStart = now;
137
+ }
138
+ }
139
+ async sendToAgent(event) {
140
+ this.resetHourlyBudgetIfNeeded();
141
+ const budget = this.agentConfig.token_budget;
142
+ if (budget && this.tokensUsedThisHour >= budget.max_per_hour) {
143
+ getLogger().warn('[tunnlo:pipeline] hourly token budget exceeded, dropping event');
144
+ this.metrics?.recordEventDropped();
145
+ return;
146
+ }
147
+ const startTime = Date.now();
148
+ try {
149
+ const response = await this.bridge.send(event, this.agentConfig.system_prompt);
150
+ const latencyMs = Date.now() - startTime;
151
+ this.tokensUsedThisHour += response.tokens_used;
152
+ this.metrics?.recordEventSentToLlm(event.event_id, latencyMs);
153
+ this.metrics?.recordTokensUsed(response.tokens_used);
154
+ this.metrics?.recordLlmResponse?.({
155
+ event_id: event.event_id,
156
+ source_id: event.source_id,
157
+ content: response.content,
158
+ tokens_used: response.tokens_used,
159
+ latency_ms: latencyMs,
160
+ has_actions: Array.isArray(response.actions) && response.actions.length > 0,
161
+ });
162
+ getLogger().info(`\n[tunnlo] Event ${event.event_id} (${event.source_id})`);
163
+ getLogger().debug(`[tunnlo] Tokens used: ${response.tokens_used} | Latency: ${latencyMs}ms`);
164
+ getLogger().info(`[tunnlo] Response:\n${response.content}\n`);
165
+ if (response.actions) {
166
+ for (const actionReq of response.actions) {
167
+ const handler = this.actionHandlers.get(actionReq.type);
168
+ if (handler) {
169
+ try {
170
+ await handler.execute(actionReq);
171
+ }
172
+ catch (err) {
173
+ getLogger().error(`[tunnlo:pipeline] action "${actionReq.type}" error:`, err);
174
+ this.metrics?.recordError('action', `${actionReq.type} error: ${err}`);
175
+ }
176
+ }
177
+ else {
178
+ getLogger().warn(`[tunnlo:pipeline] no handler for action type "${actionReq.type}"`);
179
+ }
180
+ }
181
+ }
182
+ }
183
+ catch (err) {
184
+ getLogger().error('[tunnlo:pipeline] LLM bridge error:', err);
185
+ this.metrics?.recordError('bridge', `LLM error: ${err}`);
186
+ if (this.behavior.on_llm_unreachable === 'drop_and_alert') {
187
+ this.metrics?.recordEventDropped();
188
+ const alertEvent = createEvent('tunnlo:pipeline', 'ERROR', {
189
+ message: 'LLM bridge unreachable',
190
+ error: String(err),
191
+ dropped_event_id: event.event_id,
192
+ });
193
+ for (const handler of this.actionHandlers.values()) {
194
+ try {
195
+ await handler.execute({
196
+ type: handler.type,
197
+ config: {},
198
+ payload: { event: alertEvent },
199
+ });
200
+ }
201
+ catch {
202
+ // best effort
203
+ }
204
+ }
205
+ }
206
+ }
207
+ }
208
+ }
209
+ //# sourceMappingURL=pipeline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipeline.js","sourceRoot":"","sources":["../src/pipeline.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=pipeline.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipeline.test.d.ts","sourceRoot":"","sources":["../src/pipeline.test.ts"],"names":[],"mappings":""}