@recombine-ai/engine 1.0.0-beta-2 → 1.0.0-beta-4

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 (62) hide show
  1. package/.github/workflows/linting.yml +2 -2
  2. package/.github/workflows/publish.yml +1 -2
  3. package/build/index.d.ts +2 -2
  4. package/build/index.d.ts.map +1 -1
  5. package/build/index.js +3 -2
  6. package/build/lib/bosun/action.d.ts.map +1 -1
  7. package/build/lib/bosun/action.js +1 -0
  8. package/build/lib/bosun/agent.d.ts +1 -4
  9. package/build/lib/bosun/agent.d.ts.map +1 -1
  10. package/build/lib/engine.d.ts +31 -0
  11. package/build/lib/engine.d.ts.map +1 -0
  12. package/build/lib/interfaces/adapter.d.ts +13 -0
  13. package/build/lib/interfaces/adapter.d.ts.map +1 -0
  14. package/build/lib/interfaces/conversation.d.ts +63 -0
  15. package/build/lib/interfaces/conversation.d.ts.map +1 -0
  16. package/build/lib/interfaces/engine.d.ts +65 -0
  17. package/build/lib/interfaces/engine.d.ts.map +1 -0
  18. package/build/lib/interfaces/engine.js +2 -0
  19. package/build/lib/interfaces/index.d.ts +8 -0
  20. package/build/lib/interfaces/index.d.ts.map +1 -0
  21. package/build/lib/interfaces/index.js +23 -0
  22. package/build/lib/{interfaces.d.ts → interfaces/other.d.ts} +1 -1
  23. package/build/lib/interfaces/other.d.ts.map +1 -0
  24. package/build/lib/interfaces/other.js +2 -0
  25. package/build/lib/interfaces/steps.d.ts +84 -0
  26. package/build/lib/interfaces/steps.d.ts.map +1 -0
  27. package/build/lib/interfaces/steps.js +2 -0
  28. package/build/lib/{stream/interfaces.d.ts → interfaces/stream.d.ts} +8 -22
  29. package/build/lib/interfaces/stream.d.ts.map +1 -0
  30. package/build/lib/interfaces/stream.js +2 -0
  31. package/build/lib/interfaces/workflow.d.ts +44 -0
  32. package/build/lib/interfaces/workflow.d.ts.map +1 -0
  33. package/build/lib/interfaces/workflow.js +2 -0
  34. package/build/lib/llm-adapters/mock.d.ts +1 -1
  35. package/build/lib/llm-adapters/mock.d.ts.map +1 -1
  36. package/build/lib/llm-adapters/openai-stream.d.ts +1 -1
  37. package/build/lib/llm-adapters/openai.d.ts +1 -1
  38. package/build/lib/llm-adapters/openai.d.ts.map +1 -1
  39. package/build/lib/stream/engine.d.ts +3 -0
  40. package/build/lib/stream/engine.d.ts.map +1 -0
  41. package/build/lib/stream/engine.js +174 -0
  42. package/build/lib/stream/index.d.ts +2 -2
  43. package/build/lib/stream/index.d.ts.map +1 -1
  44. package/build/lib/stream/index.js +2 -2
  45. package/build/lib/stream/token-transformers.d.ts +6 -0
  46. package/build/lib/stream/token-transformers.d.ts.map +1 -0
  47. package/build/lib/stream/token-transformers.js +62 -0
  48. package/changelog.md +1 -0
  49. package/package.json +1 -1
  50. package/build/lib/ai.d.ts +0 -286
  51. package/build/lib/ai.d.ts.map +0 -1
  52. package/build/lib/interfaces.d.ts.map +0 -1
  53. package/build/lib/stream/ai.d.ts +0 -3
  54. package/build/lib/stream/ai.d.ts.map +0 -1
  55. package/build/lib/stream/ai.js +0 -224
  56. package/build/lib/stream/filter.d.ts +0 -6
  57. package/build/lib/stream/filter.d.ts.map +0 -1
  58. package/build/lib/stream/filter.js +0 -20
  59. package/build/lib/stream/interfaces.d.ts.map +0 -1
  60. /package/build/lib/{ai.js → engine.js} +0 -0
  61. /package/build/lib/{interfaces.js → interfaces/adapter.js} +0 -0
  62. /package/build/lib/{stream/interfaces.js → interfaces/conversation.js} +0 -0
@@ -1,224 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.createAIStreamEngine = createAIStreamEngine;
7
- // cspell:words TTFT lstrip
8
- const nunjucks_1 = __importDefault(require("nunjucks"));
9
- const bosun_1 = require("../bosun");
10
- const filter_1 = require("./filter");
11
- const step_registry_1 = require("../bosun/step-registry");
12
- function createAIStreamEngine(cfg) {
13
- function createWorkflow({ name, prompt, model, filter = filter_1.defaultFilter, onError, }) {
14
- const logger = cfg.logger || console;
15
- logger.debug('streamAiEngine.createWorkflow');
16
- const stepTracer = cfg.stepTracer || (0, bosun_1.createStubStepTracer)(logger);
17
- cfg.stepRegistry?.addStep({
18
- type: 'streaming-response',
19
- name,
20
- prompt: (0, step_registry_1.stdPrompt)(prompt),
21
- });
22
- async function run(messages, ctx) {
23
- let streamCancelled = false;
24
- return new ReadableStream({
25
- cancel: (reason) => {
26
- logger.debug(`streamingWorkflow.run cancelled: ${reason}`);
27
- streamCancelled = true;
28
- },
29
- start: async (controller) => {
30
- try {
31
- const stream = await generateResponseStream(messages, ctx);
32
- for await (const chunk of stream) {
33
- if (streamCancelled)
34
- return;
35
- controller.enqueue(chunk);
36
- }
37
- if (streamCancelled)
38
- return;
39
- controller.close();
40
- }
41
- catch (e) {
42
- if (streamCancelled) {
43
- logger.debug('streamingWorkflow.run will not propagate error due to stream cancellation', e);
44
- return;
45
- }
46
- controller.error(e);
47
- await onError(e, ctx);
48
- }
49
- },
50
- });
51
- }
52
- async function generateResponseStream(messages, ctx) {
53
- const runId = crypto.randomUUID();
54
- logger.debug(`streamingWorkflow.run runId: ${runId}`);
55
- const startTime = performance.now();
56
- const transcript = createTranscript(logger, messages);
57
- let currentFilter = null;
58
- let filteredTokens = [];
59
- // Create step trace for telescope
60
- const mainStepTrace = {
61
- workflowId: name,
62
- workflowRunId: runId,
63
- name: name,
64
- model: String(model.getOptions()),
65
- createdAt: Date.now(),
66
- response: '',
67
- };
68
- const renderedPrompt = await renderPrompt(prompt, ctx);
69
- const stringifiedConversation = transcript.toString();
70
- mainStepTrace.renderedPrompt = renderedPrompt;
71
- mainStepTrace.stringifiedConversation = stringifiedConversation;
72
- let mainStepStream;
73
- try {
74
- mainStepStream = await model.generateStream(renderedPrompt, stringifiedConversation);
75
- }
76
- catch (error) {
77
- logger.error('AI Engine Stream: LLM error', { error });
78
- if (mainStepTrace) {
79
- mainStepTrace.error = error instanceof Error ? error : new Error(String(error));
80
- cfg.stepTracer?.addStepTrace(mainStepTrace);
81
- await cfg.stepTracer?.flush();
82
- }
83
- throw error;
84
- }
85
- logger.debug(`[MARK] stream created: ${(performance.now() - startTime).toFixed(2)}ms`);
86
- let measureTtft = true;
87
- let streamCancelled = false;
88
- return new ReadableStream({
89
- cancel: (reason) => {
90
- logger.debug(`streamingWorkflow.generateResponseStream cancelled: ${reason}`);
91
- streamCancelled = true;
92
- },
93
- async start(controller) {
94
- logger.debug('streamingWorkflow.run: starting main stream');
95
- for await (const chunk of mainStepStream) {
96
- if (measureTtft) {
97
- logger.debug(`[MARK] TTFT: ${(performance.now() - startTime).toFixed(2)}ms`);
98
- measureTtft = false;
99
- }
100
- const delta = chunk;
101
- if (!delta) {
102
- continue;
103
- }
104
- let tokensToRelease = [];
105
- if (currentFilter) {
106
- filteredTokens.push(delta);
107
- const filterResult = currentFilter.onNewToken(transcript, filteredTokens);
108
- if (filterResult.action === 'RELEASE_TOKENS') {
109
- logger.debug('streamingWorkflow.run: programmatic filter releasing tokens: ', JSON.stringify(filterResult.tokens));
110
- tokensToRelease = filterResult.tokens;
111
- currentFilter = null;
112
- filteredTokens = [];
113
- }
114
- }
115
- else if (filter?.shouldStartFiltering(transcript, delta)) {
116
- filteredTokens = [delta];
117
- currentFilter = filter;
118
- logger.debug('streamingWorkflow.run: programmatic filter is applied on token: ', delta);
119
- }
120
- else {
121
- tokensToRelease = [delta];
122
- }
123
- releaseMainStreamTokens(tokensToRelease);
124
- }
125
- if (currentFilter) {
126
- // stream has ended, but the filter still has some tokens to release
127
- releaseMainStreamTokens(currentFilter.onStreamEnd(transcript, filteredTokens).tokensToRelease);
128
- currentFilter = null;
129
- filteredTokens = [];
130
- }
131
- function releaseMainStreamTokens(tokens) {
132
- for (const token of tokens) {
133
- if (streamCancelled) {
134
- break;
135
- }
136
- transcript.responseChunks.push({ role: 'agent', delta: token });
137
- controller.enqueue({ role: 'agent', delta: token });
138
- }
139
- }
140
- logger.debug('streamingWorkflow.run: markMainResponseFinished', {
141
- elapsedMs: (performance.now() - startTime).toFixed(2),
142
- });
143
- transcript.markMainResponseFinished();
144
- // Add step trace and flush to telescope
145
- cfg.stepTracer?.addStepTrace(mainStepTrace);
146
- await cfg.stepTracer?.flush();
147
- if (!streamCancelled) {
148
- controller.close();
149
- }
150
- await stepTracer.flush();
151
- },
152
- });
153
- }
154
- async function renderPrompt(prompt, context) {
155
- logger.debug('Streaming AI, CONTEXT:', context);
156
- const template = typeof prompt === 'string' ? prompt : await prompt.content();
157
- if (context) {
158
- logger.debug('Loaded context: ', context);
159
- nunjucks_1.default.configure({
160
- autoescape: true,
161
- trimBlocks: true,
162
- lstripBlocks: true,
163
- });
164
- return nunjucks_1.default.renderString(template, context);
165
- }
166
- return template;
167
- }
168
- return {
169
- run,
170
- };
171
- }
172
- return {
173
- createWorkflow,
174
- };
175
- }
176
- function createTranscript(logger, initialMessages) {
177
- let finished = false;
178
- const messages = [...initialMessages];
179
- const directivesFormatter = (msg) => `${msg.sender}: ${msg.text}`;
180
- const currentResponseFormatter = (partial) => `Current response: ${partial}`;
181
- const responseTokens = [];
182
- const names = {
183
- agent: 'Agent',
184
- user: 'User',
185
- system: 'System',
186
- };
187
- return {
188
- responseChunks: responseTokens,
189
- get currentResponse() {
190
- return responseTokens
191
- .filter((token) => token.role === 'agent')
192
- .map((token) => token?.delta)
193
- .join('');
194
- },
195
- get mainResponseFinished() {
196
- return finished;
197
- },
198
- get messages() {
199
- return initialMessages;
200
- },
201
- markMainResponseFinished() {
202
- logger.debug('Conversation, markMainResponseFinished');
203
- finished = true;
204
- },
205
- toString(ignoreDirectives = false) {
206
- const serializedMessages = messages
207
- .map((msg) => {
208
- if (msg.sender === 'system') {
209
- return ignoreDirectives ? null : directivesFormatter(msg);
210
- }
211
- return `${names[msg.sender]}: ${msg.text}`;
212
- })
213
- .filter((line) => line !== null)
214
- .join('\n');
215
- if (responseTokens.length === 0) {
216
- return serializedMessages;
217
- }
218
- return serializedMessages + '\n' + currentResponseFormatter(this.currentResponse);
219
- },
220
- getConversation() {
221
- return messages;
222
- },
223
- };
224
- }
@@ -1,6 +0,0 @@
1
- import { ProgrammaticFilter } from './interfaces';
2
- /**
3
- * filter out 'Agent:' at the beginning of the llm response
4
- */
5
- export declare const defaultFilter: ProgrammaticFilter;
6
- //# sourceMappingURL=filter.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"filter.d.ts","sourceRoot":"","sources":["../../../src/lib/stream/filter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAA;AAEjD;;GAEG;AACH,eAAO,MAAM,aAAa,EAAE,kBAc3B,CAAA"}
@@ -1,20 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.defaultFilter = void 0;
4
- /**
5
- * filter out 'Agent:' at the beginning of the llm response
6
- */
7
- exports.defaultFilter = {
8
- shouldStartFiltering(state, newToken) {
9
- return state.currentResponse.trim().length === 0 && newToken.toLowerCase() === 'agent';
10
- },
11
- onNewToken(_state, filteredTokens) {
12
- if (filteredTokens.length >= 2 && filteredTokens[1] === ':') {
13
- return { action: 'RELEASE_TOKENS', tokens: filteredTokens.slice(2) };
14
- }
15
- return { action: 'RELEASE_TOKENS', tokens: filteredTokens };
16
- },
17
- onStreamEnd(_state, filteredTokens) {
18
- return { tokensToRelease: filteredTokens };
19
- },
20
- };
@@ -1 +0,0 @@
1
- {"version":3,"file":"interfaces.d.ts","sourceRoot":"","sources":["../../../src/lib/stream/interfaces.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAA;AAC/B,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AACtC,OAAO,EAAwB,YAAY,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AACzE,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAEzC,MAAM,WAAW,cAAc;IAC3B,iCAAiC;IACjC,cAAc,EAAE,CAAC,GAAG,SAAS,EAAE,EAC3B,MAAM,EAAE,cAAc,CAAC,GAAG,CAAC,KAC1B;QACD;;;;;WAKG;QACH,GAAG,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC,cAAc,CAAC,aAAa,CAAC,CAAC,CAAA;KACjF,CAAA;CACJ;AAED,MAAM,WAAW,qBAAqB;IAClC,4DAA4D;IAC5D,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,+DAA+D;IAC/D,YAAY,CAAC,EAAE,YAAY,CAAA;IAC3B,iGAAiG;IACjG,UAAU,CAAC,EAAE,UAAU,CAAA;CAC1B;AAED,MAAM,WAAW,cAAc,CAAC,GAAG;IAC/B,8EAA8E;IAC9E,IAAI,EAAE,MAAM,CAAA;IACZ,oBAAoB;IACpB,MAAM,EAAE,MAAM,GAAG,UAAU,CAAA;IAC3B,uCAAuC;IACvC,KAAK,EAAE,gBAAgB,CAAA;IACvB,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,EAAE,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC3D,wCAAwC;IACxC,MAAM,CAAC,EAAE,kBAAkB,CAAA;CAC9B;AAED,MAAM,WAAW,UAAU;IACvB,cAAc,EAAE,aAAa,EAAE,CAAA;IAC/B,QAAQ,EAAE,OAAO,EAAE,CAAA;IACnB,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAA;IAChC,QAAQ,CAAC,oBAAoB,EAAE,OAAO,CAAA;IACtC,wBAAwB,IAAI,IAAI,CAAA;IAChC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,OAAO,GAAG,MAAM,CAAA;IAC5C,eAAe,IAAI,OAAO,EAAE,CAAA;CAC/B;AAED,MAAM,WAAW,gBAAgB;IAC7B;;;;OAIG;IACH,cAAc,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,CAAA;IAC3F,0DAA0D;IAC1D,UAAU,EAAE,MAAM,OAAO,CAAA;CAC5B;AAED,MAAM,WAAW,kBAAkB;IAC/B,oBAAoB,EAAE,CAAC,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAA;IACtE,UAAU,EAAE,CACR,KAAK,EAAE,UAAU,EACjB,cAAc,EAAE,MAAM,EAAE,KACvB;QAAE,MAAM,EAAE,oBAAoB,CAAA;KAAE,GAAG;QAAE,MAAM,EAAE,gBAAgB,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE,CAAA;IACtF,WAAW,EAAE,CAAC,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,EAAE,KAAK;QAAE,eAAe,EAAE,MAAM,EAAE,CAAA;KAAE,CAAA;CAC9F;AAED,MAAM,WAAW,aAAa;IAC1B,IAAI,EAAE,OAAO,GAAG,QAAQ,CAAA;IACxB,KAAK,EAAE,MAAM,CAAA;CAChB"}
File without changes