@looopy-ai/core 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (132) hide show
  1. package/LICENSE +9 -0
  2. package/dist/core/agent.d.ts +53 -0
  3. package/dist/core/agent.js +416 -0
  4. package/dist/core/cleanup.d.ts +12 -0
  5. package/dist/core/cleanup.js +45 -0
  6. package/dist/core/index.d.ts +3 -0
  7. package/dist/core/index.js +3 -0
  8. package/dist/core/iteration.d.ts +5 -0
  9. package/dist/core/iteration.js +60 -0
  10. package/dist/core/logger.d.ts +11 -0
  11. package/dist/core/logger.js +31 -0
  12. package/dist/core/loop.d.ts +5 -0
  13. package/dist/core/loop.js +125 -0
  14. package/dist/core/tools.d.ts +4 -0
  15. package/dist/core/tools.js +78 -0
  16. package/dist/core/types.d.ts +30 -0
  17. package/dist/core/types.js +1 -0
  18. package/dist/events/index.d.ts +3 -0
  19. package/dist/events/index.js +2 -0
  20. package/dist/events/utils.d.ts +250 -0
  21. package/dist/events/utils.js +263 -0
  22. package/dist/index.d.ts +8 -0
  23. package/dist/index.js +8 -0
  24. package/dist/observability/index.d.ts +1 -0
  25. package/dist/observability/index.js +1 -0
  26. package/dist/observability/spans/agent-turn.d.ts +31 -0
  27. package/dist/observability/spans/agent-turn.js +94 -0
  28. package/dist/observability/spans/index.d.ts +5 -0
  29. package/dist/observability/spans/index.js +5 -0
  30. package/dist/observability/spans/iteration.d.ts +14 -0
  31. package/dist/observability/spans/iteration.js +41 -0
  32. package/dist/observability/spans/llm-call.d.ts +14 -0
  33. package/dist/observability/spans/llm-call.js +50 -0
  34. package/dist/observability/spans/loop.d.ts +14 -0
  35. package/dist/observability/spans/loop.js +40 -0
  36. package/dist/observability/spans/tool.d.ts +14 -0
  37. package/dist/observability/spans/tool.js +44 -0
  38. package/dist/observability/tracing.d.ts +58 -0
  39. package/dist/observability/tracing.js +203 -0
  40. package/dist/providers/chat-completions/aggregate.d.ts +4 -0
  41. package/dist/providers/chat-completions/aggregate.js +152 -0
  42. package/dist/providers/chat-completions/content.d.ts +25 -0
  43. package/dist/providers/chat-completions/content.js +229 -0
  44. package/dist/providers/chat-completions/index.d.ts +4 -0
  45. package/dist/providers/chat-completions/index.js +4 -0
  46. package/dist/providers/chat-completions/streaming.d.ts +12 -0
  47. package/dist/providers/chat-completions/streaming.js +3 -0
  48. package/dist/providers/chat-completions/types.d.ts +39 -0
  49. package/dist/providers/chat-completions/types.js +1 -0
  50. package/dist/providers/index.d.ts +2 -0
  51. package/dist/providers/index.js +1 -0
  52. package/dist/providers/litellm-provider.d.ts +43 -0
  53. package/dist/providers/litellm-provider.js +377 -0
  54. package/dist/server/event-buffer.d.ts +37 -0
  55. package/dist/server/event-buffer.js +116 -0
  56. package/dist/server/event-router.d.ts +31 -0
  57. package/dist/server/event-router.js +91 -0
  58. package/dist/server/index.d.ts +3 -0
  59. package/dist/server/index.js +3 -0
  60. package/dist/server/sse.d.ts +60 -0
  61. package/dist/server/sse.js +159 -0
  62. package/dist/stores/artifacts/artifact-scheduler.d.ts +50 -0
  63. package/dist/stores/artifacts/artifact-scheduler.js +86 -0
  64. package/dist/stores/artifacts/index.d.ts +3 -0
  65. package/dist/stores/artifacts/index.js +3 -0
  66. package/dist/stores/artifacts/internal-event-artifact-store.d.ts +54 -0
  67. package/dist/stores/artifacts/internal-event-artifact-store.js +126 -0
  68. package/dist/stores/artifacts/memory-artifact-store.d.ts +52 -0
  69. package/dist/stores/artifacts/memory-artifact-store.js +268 -0
  70. package/dist/stores/filesystem/filesystem-agent-store.d.ts +18 -0
  71. package/dist/stores/filesystem/filesystem-agent-store.js +61 -0
  72. package/dist/stores/filesystem/filesystem-artifact-store.d.ts +59 -0
  73. package/dist/stores/filesystem/filesystem-artifact-store.js +325 -0
  74. package/dist/stores/filesystem/filesystem-context-store.d.ts +37 -0
  75. package/dist/stores/filesystem/filesystem-context-store.js +245 -0
  76. package/dist/stores/filesystem/filesystem-message-store.d.ts +28 -0
  77. package/dist/stores/filesystem/filesystem-message-store.js +149 -0
  78. package/dist/stores/filesystem/filesystem-task-state-store.d.ts +27 -0
  79. package/dist/stores/filesystem/filesystem-task-state-store.js +220 -0
  80. package/dist/stores/filesystem/index.d.ts +10 -0
  81. package/dist/stores/filesystem/index.js +5 -0
  82. package/dist/stores/index.d.ts +5 -0
  83. package/dist/stores/index.js +5 -0
  84. package/dist/stores/memory/memory-state-store.d.ts +15 -0
  85. package/dist/stores/memory/memory-state-store.js +55 -0
  86. package/dist/stores/messages/hybrid-message-store.d.ts +29 -0
  87. package/dist/stores/messages/hybrid-message-store.js +72 -0
  88. package/dist/stores/messages/index.d.ts +4 -0
  89. package/dist/stores/messages/index.js +4 -0
  90. package/dist/stores/messages/interfaces.d.ts +42 -0
  91. package/dist/stores/messages/interfaces.js +18 -0
  92. package/dist/stores/messages/mem0-message-store.d.ts +34 -0
  93. package/dist/stores/messages/mem0-message-store.js +218 -0
  94. package/dist/stores/messages/memory-message-store.d.ts +27 -0
  95. package/dist/stores/messages/memory-message-store.js +183 -0
  96. package/dist/tools/artifact-tools.d.ts +4 -0
  97. package/dist/tools/artifact-tools.js +277 -0
  98. package/dist/tools/client-tool-provider.d.ts +25 -0
  99. package/dist/tools/client-tool-provider.js +139 -0
  100. package/dist/tools/index.d.ts +4 -0
  101. package/dist/tools/index.js +4 -0
  102. package/dist/tools/local-tools.d.ts +13 -0
  103. package/dist/tools/local-tools.js +70 -0
  104. package/dist/tools/mcp-client.d.ts +29 -0
  105. package/dist/tools/mcp-client.js +62 -0
  106. package/dist/tools/mcp-tool-provider.d.ts +22 -0
  107. package/dist/tools/mcp-tool-provider.js +86 -0
  108. package/dist/types/a2a.d.ts +36 -0
  109. package/dist/types/a2a.js +1 -0
  110. package/dist/types/agent.d.ts +14 -0
  111. package/dist/types/agent.js +1 -0
  112. package/dist/types/artifact.d.ts +126 -0
  113. package/dist/types/artifact.js +1 -0
  114. package/dist/types/context.d.ts +13 -0
  115. package/dist/types/context.js +1 -0
  116. package/dist/types/event.d.ts +360 -0
  117. package/dist/types/event.js +30 -0
  118. package/dist/types/index.d.ts +9 -0
  119. package/dist/types/index.js +9 -0
  120. package/dist/types/llm.d.ts +24 -0
  121. package/dist/types/llm.js +1 -0
  122. package/dist/types/message.d.ts +9 -0
  123. package/dist/types/message.js +1 -0
  124. package/dist/types/state.d.ts +86 -0
  125. package/dist/types/state.js +1 -0
  126. package/dist/types/tools.d.ts +57 -0
  127. package/dist/types/tools.js +53 -0
  128. package/dist/utils/error.d.ts +8 -0
  129. package/dist/utils/error.js +23 -0
  130. package/dist/utils/process-signals.d.ts +3 -0
  131. package/dist/utils/process-signals.js +67 -0
  132. package/package.json +54 -0
@@ -0,0 +1,263 @@
1
+ export function generateEventId() {
2
+ return `${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
3
+ }
4
+ export function createTaskCreatedEvent(options) {
5
+ return {
6
+ kind: 'task-created',
7
+ contextId: options.contextId,
8
+ taskId: options.taskId,
9
+ parentTaskId: options.parentTaskId,
10
+ initiator: options.initiator,
11
+ timestamp: new Date().toISOString(),
12
+ metadata: options.metadata,
13
+ };
14
+ }
15
+ export function createTaskStatusEvent(options) {
16
+ return {
17
+ kind: 'task-status',
18
+ contextId: options.contextId,
19
+ taskId: options.taskId,
20
+ status: options.status,
21
+ message: options.message,
22
+ timestamp: new Date().toISOString(),
23
+ metadata: options.metadata,
24
+ };
25
+ }
26
+ export function createTaskCompleteEvent(options) {
27
+ return {
28
+ kind: 'task-complete',
29
+ contextId: options.contextId,
30
+ taskId: options.taskId,
31
+ content: options.content,
32
+ artifacts: options.artifacts,
33
+ timestamp: new Date().toISOString(),
34
+ metadata: options.metadata,
35
+ };
36
+ }
37
+ export function createContentDeltaEvent(options) {
38
+ return {
39
+ kind: 'content-delta',
40
+ contextId: options.contextId,
41
+ taskId: options.taskId,
42
+ delta: options.delta,
43
+ index: options.index,
44
+ timestamp: new Date().toISOString(),
45
+ };
46
+ }
47
+ export function createContentCompleteEvent(options) {
48
+ return {
49
+ kind: 'content-complete',
50
+ contextId: options.contextId,
51
+ taskId: options.taskId,
52
+ content: options.content,
53
+ finishReason: options.finishReason || 'stop',
54
+ timestamp: new Date().toISOString(),
55
+ };
56
+ }
57
+ export function createToolStartEvent(options) {
58
+ return {
59
+ kind: 'tool-start',
60
+ contextId: options.contextId,
61
+ taskId: options.taskId,
62
+ toolCallId: options.toolCallId,
63
+ toolName: options.toolName,
64
+ arguments: options.arguments,
65
+ timestamp: new Date().toISOString(),
66
+ metadata: options.metadata,
67
+ };
68
+ }
69
+ export function createToolProgressEvent(options) {
70
+ return {
71
+ kind: 'tool-progress',
72
+ contextId: options.contextId,
73
+ taskId: options.taskId,
74
+ toolCallId: options.toolCallId,
75
+ progress: options.progress,
76
+ message: options.message,
77
+ timestamp: new Date().toISOString(),
78
+ metadata: options.metadata,
79
+ };
80
+ }
81
+ export function createToolCompleteEvent(options) {
82
+ return {
83
+ kind: 'tool-complete',
84
+ contextId: options.contextId,
85
+ taskId: options.taskId,
86
+ toolCallId: options.toolCallId,
87
+ toolName: options.toolName,
88
+ success: options.success,
89
+ result: options.result,
90
+ error: options.error,
91
+ timestamp: new Date().toISOString(),
92
+ metadata: options.metadata,
93
+ };
94
+ }
95
+ export function createInputRequiredEvent(options) {
96
+ return {
97
+ kind: 'input-required',
98
+ contextId: options.contextId,
99
+ taskId: options.taskId,
100
+ inputId: options.inputId,
101
+ requireUser: options.requireUser,
102
+ inputType: options.inputType,
103
+ prompt: options.prompt,
104
+ schema: options.schema,
105
+ options: options.options,
106
+ timestamp: new Date().toISOString(),
107
+ metadata: options.metadata,
108
+ };
109
+ }
110
+ export function createInputReceivedEvent(options) {
111
+ return {
112
+ kind: 'input-received',
113
+ contextId: options.contextId,
114
+ taskId: options.taskId,
115
+ inputId: options.inputId,
116
+ providedBy: options.providedBy,
117
+ userId: options.userId,
118
+ agentId: options.agentId,
119
+ timestamp: new Date().toISOString(),
120
+ metadata: options.metadata,
121
+ };
122
+ }
123
+ export function createAuthRequiredEvent(options) {
124
+ return {
125
+ kind: 'auth-required',
126
+ contextId: options.contextId,
127
+ taskId: options.taskId,
128
+ authId: options.authId,
129
+ authType: options.authType,
130
+ provider: options.provider,
131
+ scopes: options.scopes,
132
+ prompt: options.prompt,
133
+ authUrl: options.authUrl,
134
+ timestamp: new Date().toISOString(),
135
+ metadata: options.metadata,
136
+ };
137
+ }
138
+ export function createAuthCompletedEvent(options) {
139
+ return {
140
+ kind: 'auth-completed',
141
+ contextId: options.contextId,
142
+ taskId: options.taskId,
143
+ authId: options.authId,
144
+ userId: options.userId,
145
+ timestamp: new Date().toISOString(),
146
+ metadata: options.metadata,
147
+ };
148
+ }
149
+ export function createFileWriteEvent(options) {
150
+ return {
151
+ kind: 'file-write',
152
+ contextId: options.contextId,
153
+ taskId: options.taskId,
154
+ artifactId: options.artifactId,
155
+ data: options.data,
156
+ index: options.index,
157
+ complete: options.complete,
158
+ timestamp: new Date().toISOString(),
159
+ name: options.name,
160
+ description: options.description,
161
+ mimeType: options.mimeType,
162
+ encoding: options.encoding,
163
+ metadata: options.metadata,
164
+ };
165
+ }
166
+ export function createDataWriteEvent(options) {
167
+ return {
168
+ kind: 'data-write',
169
+ contextId: options.contextId,
170
+ taskId: options.taskId,
171
+ artifactId: options.artifactId,
172
+ data: options.data,
173
+ name: options.name,
174
+ description: options.description,
175
+ timestamp: new Date().toISOString(),
176
+ metadata: options.metadata,
177
+ };
178
+ }
179
+ export function createDatasetWriteEvent(options) {
180
+ return {
181
+ kind: 'dataset-write',
182
+ contextId: options.contextId,
183
+ taskId: options.taskId,
184
+ artifactId: options.artifactId,
185
+ rows: options.rows,
186
+ index: options.index,
187
+ complete: options.complete,
188
+ timestamp: new Date().toISOString(),
189
+ name: options.name,
190
+ description: options.description,
191
+ schema: options.schema,
192
+ metadata: options.metadata,
193
+ };
194
+ }
195
+ export function createSubtaskCreatedEvent(options) {
196
+ return {
197
+ kind: 'subtask-created',
198
+ contextId: options.contextId,
199
+ taskId: options.taskId,
200
+ subtaskId: options.subtaskId,
201
+ agentId: options.agentId,
202
+ prompt: options.prompt,
203
+ timestamp: new Date().toISOString(),
204
+ };
205
+ }
206
+ export function createThoughtStreamEvent(options) {
207
+ return {
208
+ kind: 'thought-stream',
209
+ contextId: options.contextId,
210
+ taskId: options.taskId,
211
+ thoughtId: options.thoughtId,
212
+ thoughtType: options.thoughtType,
213
+ verbosity: options.verbosity,
214
+ content: options.content,
215
+ index: options.index,
216
+ timestamp: new Date().toISOString(),
217
+ metadata: options.metadata,
218
+ };
219
+ }
220
+ export function createInternalThoughtProcessEvent(options) {
221
+ return {
222
+ kind: 'internal:thought-process',
223
+ contextId: options.contextId,
224
+ taskId: options.taskId,
225
+ iteration: options.iteration,
226
+ stage: options.stage,
227
+ reasoning: options.reasoning,
228
+ state: options.state,
229
+ timestamp: new Date().toISOString(),
230
+ };
231
+ }
232
+ export function createInternalLLMCallEvent(options) {
233
+ return {
234
+ kind: 'internal:llm-call',
235
+ contextId: options.contextId,
236
+ taskId: options.taskId,
237
+ iteration: options.iteration,
238
+ messageCount: options.messageCount,
239
+ toolCount: options.toolCount,
240
+ timestamp: new Date().toISOString(),
241
+ };
242
+ }
243
+ export function createInternalCheckpointEvent(options) {
244
+ return {
245
+ kind: 'internal:checkpoint',
246
+ contextId: options.contextId,
247
+ taskId: options.taskId,
248
+ iteration: options.iteration,
249
+ timestamp: new Date().toISOString(),
250
+ };
251
+ }
252
+ export function filterExternalEvents(events) {
253
+ return events.filter((event) => !event.kind.startsWith('internal:'));
254
+ }
255
+ export function filterByTaskId(events, taskId) {
256
+ return events.filter((event) => event.taskId === taskId);
257
+ }
258
+ export function filterByContextId(events, contextId) {
259
+ return events.filter((event) => event.contextId === contextId);
260
+ }
261
+ export function filterByKind(events, kind) {
262
+ return events.filter((event) => event.kind === kind);
263
+ }
@@ -0,0 +1,8 @@
1
+ export * from './core';
2
+ export * from './events';
3
+ export * from './observability';
4
+ export * from './providers';
5
+ export * from './server';
6
+ export * from './stores';
7
+ export * from './tools';
8
+ export * from './types';
package/dist/index.js ADDED
@@ -0,0 +1,8 @@
1
+ export * from './core';
2
+ export * from './events';
3
+ export * from './observability';
4
+ export * from './providers';
5
+ export * from './server';
6
+ export * from './stores';
7
+ export * from './tools';
8
+ export * from './types';
@@ -0,0 +1 @@
1
+ export { getTracer, initializeTracing, SpanAttributes, SpanNames, shutdownTracing, type TelemetryConfig, type TraceContext, } from './tracing';
@@ -0,0 +1 @@
1
+ export { getTracer, initializeTracing, SpanAttributes, SpanNames, shutdownTracing, } from './tracing';
@@ -0,0 +1,31 @@
1
+ import { type Context, type Span } from '@opentelemetry/api';
2
+ import type { AnyEvent } from '../../types/event';
3
+ export interface AgentTurnSpanParams {
4
+ agentId: string;
5
+ taskId: string;
6
+ contextId: string;
7
+ turnNumber: number;
8
+ userMessage: string | null;
9
+ }
10
+ export declare const startAgentTurnSpan: (params: AgentTurnSpanParams) => {
11
+ span: Span;
12
+ traceContext: Context;
13
+ tapFinish: import("rxjs").MonoTypeOperatorFunction<AnyEvent>;
14
+ };
15
+ export declare function addMessagesLoadedEvent(span: Span, count: number): void;
16
+ export declare function addMessagesCompactedEvent(span: Span): void;
17
+ export declare function setTurnOutputAttribute(span: Span, output: string): void;
18
+ export declare function setTurnCountAttribute(span: Span, turnCount: number): void;
19
+ export declare function completeAgentTurnSpan(span: Span): void;
20
+ export declare function failAgentTurnSpan(span: Span, error: Error): void;
21
+ export declare const startAgentInitializeSpan: (params: {
22
+ agentId: string;
23
+ contextId: string;
24
+ parentContext: Context;
25
+ }) => {
26
+ span: Span;
27
+ traceContext: Context;
28
+ };
29
+ export declare function setResumeAttributes(span: Span, existingMessageCount: number): void;
30
+ export declare function completeAgentInitializeSpan(span: Span): void;
31
+ export declare function failAgentInitializeSpan(span: Span, error: Error): void;
@@ -0,0 +1,94 @@
1
+ import { context, SpanStatusCode, trace } from '@opentelemetry/api';
2
+ import { tap } from 'rxjs/internal/operators/tap';
3
+ import { SpanAttributes } from '../tracing';
4
+ const safeName = (name) => name.replace(/[^a-zA-Z0-9_-]+/g, '-');
5
+ export const startAgentTurnSpan = (params) => {
6
+ const tracer = trace.getTracer('looopy-agent');
7
+ const span = tracer.startSpan(`agent[${safeName(params.agentId)}]`, {
8
+ attributes: {
9
+ [SpanAttributes.SESSION_ID]: params.contextId,
10
+ [SpanAttributes.AGENT_ID]: params.agentId,
11
+ [SpanAttributes.TASK_ID]: params.taskId,
12
+ 'agent.turn.number': params.turnNumber,
13
+ [SpanAttributes.LANGFUSE_OBSERVATION_TYPE]: 'agent',
14
+ ...(params.userMessage ? { input: params.userMessage } : {}),
15
+ },
16
+ });
17
+ const traceContext = trace.setSpan(context.active(), span);
18
+ return {
19
+ span,
20
+ traceContext,
21
+ tapFinish: tap({
22
+ next: (event) => {
23
+ switch (event.kind) {
24
+ case 'task-complete':
25
+ if (event.content) {
26
+ span.setAttribute(SpanAttributes.OUTPUT, event.content);
27
+ }
28
+ span.setStatus({ code: SpanStatusCode.OK });
29
+ break;
30
+ default:
31
+ break;
32
+ }
33
+ },
34
+ complete: () => span.end(),
35
+ error: (err) => {
36
+ span.recordException(err);
37
+ span.setStatus({ code: SpanStatusCode.ERROR, message: err.message });
38
+ span.end();
39
+ },
40
+ }),
41
+ };
42
+ };
43
+ export function addMessagesLoadedEvent(span, count) {
44
+ span.addEvent('messages.loaded', { count });
45
+ }
46
+ export function addMessagesCompactedEvent(span) {
47
+ span.addEvent('messages.compacted');
48
+ }
49
+ export function setTurnOutputAttribute(span, output) {
50
+ span.setAttribute('output', output);
51
+ }
52
+ export function setTurnCountAttribute(span, turnCount) {
53
+ span.setAttribute('agent.turn.count', turnCount);
54
+ }
55
+ export function completeAgentTurnSpan(span) {
56
+ span.setStatus({ code: 1 });
57
+ span.end();
58
+ }
59
+ export function failAgentTurnSpan(span, error) {
60
+ span.setStatus({
61
+ code: 2,
62
+ message: error.message,
63
+ });
64
+ span.recordException(error);
65
+ span.end();
66
+ }
67
+ export const startAgentInitializeSpan = (params) => {
68
+ const tracer = trace.getTracer('looopy-agent');
69
+ const spanOptions = {
70
+ attributes: {
71
+ [SpanAttributes.SESSION_ID]: params.contextId,
72
+ [SpanAttributes.AGENT_ID]: params.agentId,
73
+ },
74
+ };
75
+ const span = tracer.startSpan(`agent.initialize`, spanOptions, params.parentContext);
76
+ const traceContext = trace.setSpan(params.parentContext, span);
77
+ return { span, traceContext };
78
+ };
79
+ export function setResumeAttributes(span, existingMessageCount) {
80
+ span.setAttribute('agent.resumed', true);
81
+ span.setAttribute('agent.existingMessages', existingMessageCount);
82
+ }
83
+ export function completeAgentInitializeSpan(span) {
84
+ span.setStatus({ code: 1 });
85
+ span.end();
86
+ }
87
+ export function failAgentInitializeSpan(span, error) {
88
+ span.setStatus({
89
+ code: 2,
90
+ message: error.message,
91
+ });
92
+ span.recordException(error);
93
+ span.end();
94
+ }
@@ -0,0 +1,5 @@
1
+ export * from './agent-turn';
2
+ export * from './iteration';
3
+ export * from './llm-call';
4
+ export * from './loop';
5
+ export * from './tool';
@@ -0,0 +1,5 @@
1
+ export * from './agent-turn';
2
+ export * from './iteration';
3
+ export * from './llm-call';
4
+ export * from './loop';
5
+ export * from './tool';
@@ -0,0 +1,14 @@
1
+ import type { LoopContext } from '../../core/types';
2
+ import type { AnyEvent } from '../../types/event';
3
+ export interface LoopIterationSpanParams {
4
+ agentId: string;
5
+ contextId: string;
6
+ taskId: string;
7
+ iteration: number;
8
+ parentContext: import('@opentelemetry/api').Context;
9
+ }
10
+ export declare const startLoopIterationSpan: (context: LoopContext, iteration: number) => {
11
+ span: import("@opentelemetry/api").Span;
12
+ traceContext: import("@opentelemetry/api").Context;
13
+ tapFinish: import("rxjs").MonoTypeOperatorFunction<AnyEvent>;
14
+ };
@@ -0,0 +1,41 @@
1
+ import { SpanStatusCode, trace } from '@opentelemetry/api';
2
+ import { tap } from 'rxjs/internal/operators/tap';
3
+ import { SpanAttributes, SpanNames } from '../tracing';
4
+ export const startLoopIterationSpan = (context, iteration) => {
5
+ const logger = context.logger;
6
+ logger.info('Starting iteration');
7
+ const tracer = trace.getTracer('looopy');
8
+ const span = tracer.startSpan(SpanNames.LOOP_ITERATION, {
9
+ attributes: {
10
+ [SpanAttributes.SESSION_ID]: context.contextId,
11
+ [SpanAttributes.AGENT_ID]: context.agentId,
12
+ [SpanAttributes.TASK_ID]: context.taskId,
13
+ [SpanAttributes.ITERATION]: iteration,
14
+ [SpanAttributes.LANGFUSE_OBSERVATION_TYPE]: 'chain',
15
+ },
16
+ }, context.parentContext);
17
+ const traceContext = trace.setSpan(context.parentContext, span);
18
+ return {
19
+ span,
20
+ traceContext,
21
+ tapFinish: tap({
22
+ next: (event) => {
23
+ if (event.kind === 'content-complete') {
24
+ if (event.content) {
25
+ span.setAttribute(SpanAttributes.OUTPUT, event.content);
26
+ span.setAttribute(SpanAttributes.LLM_FINISH_REASON, event.finishReason);
27
+ span.setStatus({ code: SpanStatusCode.OK });
28
+ }
29
+ logger.debug({ finishReason: event.finishReason }, 'Iteration completed successfully');
30
+ }
31
+ },
32
+ complete: () => span.end(),
33
+ error: (err) => {
34
+ span.recordException(err);
35
+ span.setStatus({ code: SpanStatusCode.ERROR, message: err.message });
36
+ span.end();
37
+ logger.error({ error: err.message }, 'Iteration failed');
38
+ },
39
+ }),
40
+ };
41
+ };
@@ -0,0 +1,14 @@
1
+ import type { LoopContext } from '../../core/types';
2
+ import type { AnyEvent } from '../../types/event';
3
+ import type { Message } from '../../types/message';
4
+ export interface LLMCallSpanParams {
5
+ agentId: string;
6
+ taskId: string;
7
+ messages: Message[];
8
+ parentContext: import('@opentelemetry/api').Context;
9
+ }
10
+ export declare const startLLMCallSpan: (context: LoopContext, messages: Message[]) => {
11
+ span: import("@opentelemetry/api").Span;
12
+ traceContext: import("@opentelemetry/api").Context;
13
+ tapFinish: import("rxjs").MonoTypeOperatorFunction<AnyEvent>;
14
+ };
@@ -0,0 +1,50 @@
1
+ import { SpanStatusCode, trace } from '@opentelemetry/api';
2
+ import { tap } from 'rxjs/internal/operators/tap';
3
+ import { SpanAttributes, SpanNames } from '../tracing';
4
+ export const startLLMCallSpan = (context, messages) => {
5
+ const tracer = trace.getTracer('looopy');
6
+ const span = tracer.startSpan(SpanNames.LLM_CALL, {
7
+ attributes: {
8
+ [SpanAttributes.AGENT_ID]: context.agentId,
9
+ [SpanAttributes.TASK_ID]: context.taskId,
10
+ [SpanAttributes.GEN_AI_PROMPT]: JSON.stringify(messages),
11
+ [SpanAttributes.LANGFUSE_OBSERVATION_TYPE]: 'generation',
12
+ },
13
+ }, context.parentContext);
14
+ const traceContext = trace.setSpan(context.parentContext, span);
15
+ return {
16
+ span,
17
+ traceContext,
18
+ tapFinish: tap({
19
+ next: (event) => {
20
+ switch (event.kind) {
21
+ case 'content-complete':
22
+ if (event.content) {
23
+ span.setAttribute(SpanAttributes.GEN_AI_COMPLETION, event.content);
24
+ }
25
+ span.setAttribute(SpanAttributes.LLM_FINISH_REASON, event.finishReason || 'unknown');
26
+ span.setStatus({ code: SpanStatusCode.OK });
27
+ break;
28
+ case 'llm-usage':
29
+ span.setAttribute(SpanAttributes.GEN_AI_RESPONSE_MODEL, event.model);
30
+ span.setAttribute(SpanAttributes.GEN_AI_USAGE_PROMPT_TOKENS, event.prompt_tokens || 0);
31
+ span.setAttribute(SpanAttributes.GEN_AI_USAGE_COMPLETION_TOKENS, event.completion_tokens || 0);
32
+ span.setAttribute(SpanAttributes.GEN_AI_USAGE_TOTAL_TOKENS, event.total_tokens || 0);
33
+ span.setAttribute(SpanAttributes.GEN_AI_USAGE_COMPLETION_TOKENS_DETAILS, JSON.stringify(event.completion_tokens_details || {}));
34
+ span.setAttribute(SpanAttributes.GEN_AI_USAGE_PROMPT_TOKENS_DETAILS, JSON.stringify(event.prompt_tokens_details || {}));
35
+ span.setAttribute(SpanAttributes.GEN_AI_USAGE_CACHE_CREATION_INPUT_TOKENS, event.cache_creation_input_tokens || 0);
36
+ span.setAttribute(SpanAttributes.GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS, event.cache_read_input_tokens || 0);
37
+ break;
38
+ default:
39
+ break;
40
+ }
41
+ },
42
+ complete: () => span.end(),
43
+ error: (err) => {
44
+ span.recordException(err);
45
+ span.setStatus({ code: SpanStatusCode.ERROR, message: err.message });
46
+ span.end();
47
+ },
48
+ }),
49
+ };
50
+ };
@@ -0,0 +1,14 @@
1
+ import { type Context } from '@opentelemetry/api';
2
+ import type { AnyEvent } from '../../types/event';
3
+ export interface AgentLoopSpanParams {
4
+ agentId: string;
5
+ taskId: string;
6
+ contextId: string;
7
+ prompt?: string;
8
+ parentContext: Context;
9
+ }
10
+ export declare const startAgentLoopSpan: (params: AgentLoopSpanParams) => {
11
+ span: import("@opentelemetry/api").Span;
12
+ traceContext: Context;
13
+ tapFinish: import("rxjs").MonoTypeOperatorFunction<AnyEvent>;
14
+ };
@@ -0,0 +1,40 @@
1
+ import { SpanStatusCode, trace } from '@opentelemetry/api';
2
+ import { tap } from 'rxjs/internal/operators/tap';
3
+ import { SpanAttributes, SpanNames } from '../tracing';
4
+ export const startAgentLoopSpan = (params) => {
5
+ const tracer = trace.getTracer('looopy');
6
+ const span = tracer.startSpan(SpanNames.LOOP_START, {
7
+ attributes: {
8
+ [SpanAttributes.SESSION_ID]: params.contextId,
9
+ [SpanAttributes.AGENT_ID]: params.agentId,
10
+ [SpanAttributes.TASK_ID]: params.taskId,
11
+ input: params.prompt,
12
+ [SpanAttributes.LANGFUSE_OBSERVATION_TYPE]: 'event',
13
+ },
14
+ }, params.parentContext);
15
+ const traceContext = trace.setSpan(params.parentContext, span);
16
+ return {
17
+ span,
18
+ traceContext,
19
+ tapFinish: tap({
20
+ next: (event) => {
21
+ switch (event.kind) {
22
+ case 'content-complete':
23
+ if (event.content) {
24
+ span.setAttribute(SpanAttributes.OUTPUT, event.content);
25
+ }
26
+ span.setStatus({ code: SpanStatusCode.OK });
27
+ break;
28
+ default:
29
+ break;
30
+ }
31
+ },
32
+ complete: () => span.end(),
33
+ error: (err) => {
34
+ span.recordException(err);
35
+ span.setStatus({ code: SpanStatusCode.ERROR, message: err.message });
36
+ span.end();
37
+ },
38
+ }),
39
+ };
40
+ };
@@ -0,0 +1,14 @@
1
+ import type { IterationContext } from '../../core/types';
2
+ import type { ToolExecutionEvent, ToolStartEvent } from '../../types/event';
3
+ import type { ToolCall } from '../../types/tools';
4
+ export interface ToolExecutionSpanParams {
5
+ agentId: string;
6
+ taskId: string;
7
+ toolCall: ToolCall;
8
+ parentContext?: import('@opentelemetry/api').Context;
9
+ }
10
+ export declare const startToolExecuteSpan: (context: IterationContext, toolStart: ToolStartEvent) => {
11
+ span: import("@opentelemetry/api").Span;
12
+ traceContext: import("@opentelemetry/api").Context;
13
+ tapFinish: import("rxjs").MonoTypeOperatorFunction<ToolExecutionEvent>;
14
+ };
@@ -0,0 +1,44 @@
1
+ import { context as otelContext, SpanStatusCode, trace } from '@opentelemetry/api';
2
+ import { tap } from 'rxjs/internal/operators/tap';
3
+ import { SpanAttributes, SpanNames } from '../tracing';
4
+ export const startToolExecuteSpan = (context, toolStart) => {
5
+ const tracer = trace.getTracer('looopy');
6
+ const span = tracer.startSpan(SpanNames.TOOL_EXECUTE, {
7
+ attributes: {
8
+ [SpanAttributes.AGENT_ID]: context.agentId,
9
+ [SpanAttributes.TASK_ID]: context.taskId,
10
+ [SpanAttributes.TOOL_NAME]: toolStart.toolName,
11
+ [SpanAttributes.TOOL_CALL_ID]: toolStart.toolCallId,
12
+ [SpanAttributes.LANGFUSE_OBSERVATION_TYPE]: 'tool',
13
+ input: JSON.stringify(toolStart.arguments),
14
+ },
15
+ }, context.parentContext);
16
+ const traceContext = trace.setSpan(context.parentContext || otelContext.active(), span);
17
+ return {
18
+ span,
19
+ traceContext,
20
+ tapFinish: tap({
21
+ next: (event) => {
22
+ if (event.kind === 'tool-complete') {
23
+ if (event.success) {
24
+ span.setAttribute('output', JSON.stringify(event.result));
25
+ span.setStatus({ code: SpanStatusCode.OK });
26
+ }
27
+ else {
28
+ span.setAttribute('output', event.error || 'Tool execution failed');
29
+ span.setStatus({ code: SpanStatusCode.ERROR });
30
+ if (event.error) {
31
+ span.setAttribute('error.message', event.error);
32
+ }
33
+ }
34
+ }
35
+ },
36
+ complete: () => span.end(),
37
+ error: (err) => {
38
+ span.recordException(err);
39
+ span.setStatus({ code: SpanStatusCode.ERROR, message: err.message });
40
+ span.end();
41
+ },
42
+ }),
43
+ };
44
+ };