@looopy-ai/core 2.1.1 → 2.1.3
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.
- package/dist/core/agent.js +6 -2
- package/dist/core/loop.js +3 -2
- package/dist/core/tools.js +3 -0
- package/dist/events/utils.d.ts +2 -1
- package/dist/events/utils.js +3 -0
- package/dist/observability/spans/agent-turn.js +3 -0
- package/dist/observability/spans/iteration.js +3 -0
- package/dist/observability/spans/llm-call.js +3 -0
- package/dist/observability/spans/loop.js +3 -0
- package/dist/observability/spans/tool.js +2 -1
- package/dist/tools/agent-tool-provider.js +3 -0
- package/dist/types/event.d.ts +3 -0
- package/package.json +1 -1
package/dist/core/agent.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { catchError, concat, filter, Observable, of, tap } from 'rxjs';
|
|
2
2
|
import { createTaskStatusEvent } from '../events';
|
|
3
|
+
import { isChildTaskEvent } from '../events/utils';
|
|
3
4
|
import { addMessagesCompactedEvent, addMessagesLoadedEvent, completeAgentInitializeSpan, completeAgentTurnSpan, failAgentInitializeSpan, failAgentTurnSpan, setResumeAttributes, setTurnCountAttribute, startAgentInitializeSpan, startAgentTurnSpan, } from '../observability/spans';
|
|
4
5
|
import { serializeError } from '../utils/error';
|
|
5
6
|
import { getLogger } from './logger';
|
|
@@ -178,9 +179,12 @@ export class Agent {
|
|
|
178
179
|
maxIterations: 5,
|
|
179
180
|
stopOnToolError: false,
|
|
180
181
|
}, messages).pipe(tap(async (event) => {
|
|
182
|
+
if (isChildTaskEvent(event))
|
|
183
|
+
return;
|
|
181
184
|
switch (event.kind) {
|
|
182
185
|
case 'content-complete':
|
|
183
186
|
if (event.content || event.toolCalls) {
|
|
187
|
+
logger.debug({ event }, 'Saving content-complete to message store');
|
|
184
188
|
await this.config.messageStore.append(this.config.contextId, [
|
|
185
189
|
{
|
|
186
190
|
role: 'assistant',
|
|
@@ -198,6 +202,7 @@ export class Agent {
|
|
|
198
202
|
}
|
|
199
203
|
break;
|
|
200
204
|
case 'tool-complete': {
|
|
205
|
+
logger.debug({ event }, 'Saving tool-complete to message store');
|
|
201
206
|
const message = {
|
|
202
207
|
role: 'tool',
|
|
203
208
|
content: JSON.stringify({
|
|
@@ -207,12 +212,11 @@ export class Agent {
|
|
|
207
212
|
}),
|
|
208
213
|
toolCallId: event.toolCallId,
|
|
209
214
|
};
|
|
210
|
-
logger.debug({ message }, 'Saving tool message to message store');
|
|
211
215
|
await this.config.messageStore.append(this.config.contextId, [message]);
|
|
212
216
|
break;
|
|
213
217
|
}
|
|
214
218
|
case 'internal:tool-message':
|
|
215
|
-
logger.debug({
|
|
219
|
+
logger.debug({ event }, 'Saving internal:tool-message to message store');
|
|
216
220
|
await this.config.messageStore.append(this.config.contextId, [event.message]);
|
|
217
221
|
break;
|
|
218
222
|
default:
|
package/dist/core/loop.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { concat, EMPTY, mergeMap, of, reduce, shareReplay } from 'rxjs';
|
|
2
2
|
import { createTaskCompleteEvent, createTaskCreatedEvent, createTaskStatusEvent } from '../events';
|
|
3
|
+
import { isChildTaskEvent } from '../events/utils';
|
|
3
4
|
import { startAgentLoopSpan } from '../observability/spans';
|
|
4
5
|
import { recursiveMerge } from '../utils/recursive-merge';
|
|
5
6
|
import { runIteration } from './iteration';
|
|
@@ -37,8 +38,8 @@ export const runLoop = (context, config, history) => {
|
|
|
37
38
|
}, state.messages), (state, { events }) => ({
|
|
38
39
|
...state,
|
|
39
40
|
messages: [...state.messages, ...eventsToMessages(events)],
|
|
40
|
-
}), (e) => e.kind === 'content-complete' && e.finishReason !== 'tool_calls').pipe(shareReplay({ refCount: true }));
|
|
41
|
-
const finalSummary$ = merged$.pipe(reduce((last, e) => (e.kind === 'content-complete' ? e : last), null), mergeMap((last) => {
|
|
41
|
+
}), (e) => !isChildTaskEvent(e) && e.kind === 'content-complete' && e.finishReason !== 'tool_calls').pipe(shareReplay({ refCount: true }));
|
|
42
|
+
const finalSummary$ = merged$.pipe(reduce((last, e) => (!isChildTaskEvent(e) && e.kind === 'content-complete' ? e : last), null), mergeMap((last) => {
|
|
42
43
|
if (!last)
|
|
43
44
|
return EMPTY;
|
|
44
45
|
return of(createTaskCompleteEvent({
|
package/dist/core/tools.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { catchError, concat, defer, mergeMap, of, tap } from 'rxjs';
|
|
2
|
+
import { isChildTaskEvent } from '../events/utils';
|
|
2
3
|
import { startToolExecuteSpan } from '../observability/spans';
|
|
3
4
|
import { toolErrorEvent } from '../tools/tool-result-events';
|
|
4
5
|
export const runToolCall = (context, toolCall) => {
|
|
@@ -42,6 +43,8 @@ export const runToolCall = (context, toolCall) => {
|
|
|
42
43
|
try {
|
|
43
44
|
logger.trace({ providerName: provider.name }, 'Executing tool');
|
|
44
45
|
return provider.execute(toolCallInput, context).pipe(tap((event) => {
|
|
46
|
+
if (isChildTaskEvent(event))
|
|
47
|
+
return;
|
|
45
48
|
if (event.kind !== 'tool-complete') {
|
|
46
49
|
return;
|
|
47
50
|
}
|
package/dist/events/utils.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AuthCompletedEvent, AuthRequiredEvent, AuthType, ContentCompleteEvent, ContentDeltaEvent, ContextAnyEvent, ContextEvent, DatasetWriteEvent, DataWriteEvent, FileWriteEvent, FinishReason, InputProvider, InputReceivedEvent, InputRequiredEvent, InputType, InternalCheckpointEvent, InternalLLMCallEvent, InternalThoughtProcessEvent, JSONSchema, SubtaskCreatedEvent, TaskCompleteEvent, TaskCreatedEvent, TaskInitiator, TaskStatus, TaskStatusEvent, ThoughtStreamEvent, ThoughtType, ThoughtVerbosity, ToolCompleteEvent, ToolProgressEvent, ToolStartEvent } from '../types/event';
|
|
1
|
+
import type { AnyEvent, AuthCompletedEvent, AuthRequiredEvent, AuthType, ContentCompleteEvent, ContentDeltaEvent, ContextAnyEvent, ContextEvent, DatasetWriteEvent, DataWriteEvent, FileWriteEvent, FinishReason, InputProvider, InputReceivedEvent, InputRequiredEvent, InputType, InternalCheckpointEvent, InternalLLMCallEvent, InternalThoughtProcessEvent, JSONSchema, SubtaskCreatedEvent, TaskCompleteEvent, TaskCreatedEvent, TaskInitiator, TaskStatus, TaskStatusEvent, ThoughtStreamEvent, ThoughtType, ThoughtVerbosity, ToolCompleteEvent, ToolProgressEvent, ToolStartEvent } from '../types/event';
|
|
2
2
|
export declare function generateEventId(): string;
|
|
3
3
|
export interface CreateTaskCreatedEventOptions {
|
|
4
4
|
contextId: string;
|
|
@@ -248,3 +248,4 @@ export declare function filterByContextId(events: ContextAnyEvent[], contextId:
|
|
|
248
248
|
export declare function filterByKind<K extends ContextAnyEvent['kind']>(events: ContextAnyEvent[], kind: K): Extract<ContextAnyEvent, {
|
|
249
249
|
kind: K;
|
|
250
250
|
}>[];
|
|
251
|
+
export declare const isChildTaskEvent: (event: AnyEvent) => boolean;
|
package/dist/events/utils.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { context, SpanStatusCode, trace } from '@opentelemetry/api';
|
|
2
2
|
import { tap } from 'rxjs/internal/operators/tap';
|
|
3
|
+
import { isChildTaskEvent } from '../../events/utils';
|
|
3
4
|
import { SpanAttributes } from '../tracing';
|
|
4
5
|
const safeName = (name) => name.replace(/[^a-zA-Z0-9_-]+/g, '-');
|
|
5
6
|
export const startAgentTurnSpan = (params) => {
|
|
@@ -20,6 +21,8 @@ export const startAgentTurnSpan = (params) => {
|
|
|
20
21
|
traceContext,
|
|
21
22
|
tapFinish: tap({
|
|
22
23
|
next: (event) => {
|
|
24
|
+
if (isChildTaskEvent(event))
|
|
25
|
+
return;
|
|
23
26
|
switch (event.kind) {
|
|
24
27
|
case 'task-complete':
|
|
25
28
|
if (event.content) {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { SpanStatusCode, trace } from '@opentelemetry/api';
|
|
2
2
|
import { tap } from 'rxjs/internal/operators/tap';
|
|
3
|
+
import { isChildTaskEvent } from '../../events/utils';
|
|
3
4
|
import { SpanAttributes, SpanNames } from '../tracing';
|
|
4
5
|
export const startLoopIterationSpan = (context, iteration) => {
|
|
5
6
|
const logger = context.logger;
|
|
@@ -20,6 +21,8 @@ export const startLoopIterationSpan = (context, iteration) => {
|
|
|
20
21
|
traceContext,
|
|
21
22
|
tapFinish: tap({
|
|
22
23
|
next: (event) => {
|
|
24
|
+
if (isChildTaskEvent(event))
|
|
25
|
+
return;
|
|
23
26
|
if (event.kind === 'content-complete') {
|
|
24
27
|
if (event.content) {
|
|
25
28
|
span.setAttribute(SpanAttributes.OUTPUT, event.content);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { SpanStatusCode, trace } from '@opentelemetry/api';
|
|
2
2
|
import { tap } from 'rxjs/internal/operators/tap';
|
|
3
|
+
import { isChildTaskEvent } from '../../events/utils';
|
|
3
4
|
import { SpanAttributes, SpanNames } from '../tracing';
|
|
4
5
|
export const startLLMCallSpan = (context, systemPrompt, messages, tools) => {
|
|
5
6
|
const tracer = trace.getTracer('looopy');
|
|
@@ -20,6 +21,8 @@ export const startLLMCallSpan = (context, systemPrompt, messages, tools) => {
|
|
|
20
21
|
traceContext,
|
|
21
22
|
tapFinish: tap({
|
|
22
23
|
next: (event) => {
|
|
24
|
+
if (isChildTaskEvent(event))
|
|
25
|
+
return;
|
|
23
26
|
switch (event.kind) {
|
|
24
27
|
case 'content-complete':
|
|
25
28
|
if (event.content) {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { SpanStatusCode, trace } from '@opentelemetry/api';
|
|
2
2
|
import { tap } from 'rxjs/internal/operators/tap';
|
|
3
|
+
import { isChildTaskEvent } from '../../events/utils';
|
|
3
4
|
import { SpanAttributes, SpanNames } from '../tracing';
|
|
4
5
|
export const startAgentLoopSpan = (params) => {
|
|
5
6
|
const tracer = trace.getTracer('looopy');
|
|
@@ -18,6 +19,8 @@ export const startAgentLoopSpan = (params) => {
|
|
|
18
19
|
traceContext,
|
|
19
20
|
tapFinish: tap({
|
|
20
21
|
next: (event) => {
|
|
22
|
+
if (isChildTaskEvent(event))
|
|
23
|
+
return;
|
|
21
24
|
switch (event.kind) {
|
|
22
25
|
case 'content-complete':
|
|
23
26
|
if (event.content) {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { context as otelContext, SpanStatusCode, trace } from '@opentelemetry/api';
|
|
2
2
|
import { tap } from 'rxjs';
|
|
3
|
+
import { isChildTaskEvent } from '../../events/utils';
|
|
3
4
|
import { SpanAttributes, SpanNames } from '../tracing';
|
|
4
5
|
export const startToolExecuteSpan = (context, toolStart) => {
|
|
5
6
|
const tracer = trace.getTracer('looopy');
|
|
@@ -19,7 +20,7 @@ export const startToolExecuteSpan = (context, toolStart) => {
|
|
|
19
20
|
traceContext,
|
|
20
21
|
tapFinish: tap({
|
|
21
22
|
next: (event) => {
|
|
22
|
-
if (!isToolCompleteEvent(event)) {
|
|
23
|
+
if (isChildTaskEvent(event) || !isToolCompleteEvent(event)) {
|
|
23
24
|
return;
|
|
24
25
|
}
|
|
25
26
|
try {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { consumeSSEStream } from '@geee-be/sse-stream-parser';
|
|
2
|
+
import { trace } from '@opentelemetry/api';
|
|
2
3
|
import { Observable } from 'rxjs';
|
|
3
4
|
import z from 'zod';
|
|
4
5
|
import { getLogger } from '../core';
|
|
@@ -96,6 +97,8 @@ export class AgentToolProvider {
|
|
|
96
97
|
subscriber.complete();
|
|
97
98
|
return;
|
|
98
99
|
}
|
|
100
|
+
const span = trace.getSpan(context.parentContext);
|
|
101
|
+
span?.updateName(`agent.invoke[${toolCall.function.name}]`);
|
|
99
102
|
const res = await fetch(`${this.card.url}/invocations?qualifier=DEFAULT`, {
|
|
100
103
|
method: 'POST',
|
|
101
104
|
headers: {
|
package/dist/types/event.d.ts
CHANGED
|
@@ -315,6 +315,9 @@ export type ContextEvent<T> = T & {
|
|
|
315
315
|
contextId: string;
|
|
316
316
|
taskId: string;
|
|
317
317
|
};
|
|
318
|
+
export type ChildTaskEvent<T> = T & {
|
|
319
|
+
parentTaskId: string;
|
|
320
|
+
};
|
|
318
321
|
export type ContextAnyEvent = ContextEvent<AnyEvent>;
|
|
319
322
|
export type ExternalEvent = Exclude<AnyEvent, InternalDebugEvent>;
|
|
320
323
|
export type DebugEvent = InternalDebugEvent;
|