@looopy-ai/core 2.1.1 → 2.1.2

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.
@@ -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,6 +179,8 @@ 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) {
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({
@@ -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
  }
@@ -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;
@@ -261,3 +261,6 @@ export function filterByContextId(events, contextId) {
261
261
  export function filterByKind(events, kind) {
262
262
  return events.filter((event) => event.kind === kind);
263
263
  }
264
+ export const isChildTaskEvent = (event) => {
265
+ return !!event.parentTaskId;
266
+ };
@@ -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 {
@@ -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;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@looopy-ai/core",
3
- "version": "2.1.1",
3
+ "version": "2.1.2",
4
4
  "description": "RxJS-based AI agent framework",
5
5
  "keywords": [
6
6
  "agent",