@aigne/core 1.38.1 → 1.39.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.
package/CHANGELOG.md CHANGED
@@ -12,6 +12,25 @@
12
12
  * dependencies
13
13
  * @aigne/observability bumped to 0.1.0
14
14
 
15
+ ## [1.39.0](https://github.com/AIGNE-io/aigne-framework/compare/core-v1.38.1...core-v1.39.0) (2025-07-28)
16
+
17
+
18
+ ### Features
19
+
20
+ * **cli:** add inquirer/prompts integrations for cli ([#286](https://github.com/AIGNE-io/aigne-framework/issues/286)) ([33af756](https://github.com/AIGNE-io/aigne-framework/commit/33af7567fe2e7f9fb4b1633127e1d54fd65cb2a8))
21
+
22
+
23
+ ### Bug Fixes
24
+
25
+ * **observability:** uniq index on insert and perf on trace query ([#268](https://github.com/AIGNE-io/aigne-framework/issues/268)) ([bd02d2e](https://github.com/AIGNE-io/aigne-framework/commit/bd02d2ef4dadc3df7e4806746fede2faa5cc50bb))
26
+
27
+
28
+ ### Dependencies
29
+
30
+ * The following workspace dependencies were updated
31
+ * dependencies
32
+ * @aigne/observability-api bumped to 0.8.2
33
+
15
34
  ## [1.38.1](https://github.com/AIGNE-io/aigne-framework/compare/core-v1.38.0...core-v1.38.1) (2025-07-24)
16
35
 
17
36
 
@@ -1,4 +1,5 @@
1
1
  import { nodejs } from "@aigne/platform-helpers/nodejs/index.js";
2
+ import type * as prompts from "@inquirer/prompts";
2
3
  import { ZodObject, type ZodType } from "zod";
3
4
  import type { AgentEvent, Context, UserContext } from "../aigne/context.js";
4
5
  import type { MessagePayload } from "../aigne/message-queue.js";
@@ -146,7 +147,13 @@ export interface AgentInvokeOptions<U extends UserContext = UserContext> {
146
147
  /**
147
148
  * Optional hooks for agent invocation
148
149
  */
149
- hooks?: AgentHooks<any, any>;
150
+ hooks?: AgentHooks<any, any> | AgentHooks<any, any>[];
151
+ /**
152
+ * @inquirer/prompts used for collecting user input during agent execution
153
+ *
154
+ * This property only exists in the CLI context by command `aigne run`
155
+ */
156
+ prompts?: typeof prompts;
150
157
  }
151
158
  /**
152
159
  * Agent is the base class for all agents.
@@ -536,13 +543,16 @@ export interface AgentHooks<I extends Message = Message, O extends Message = Mes
536
543
  */
537
544
  onStart?: ((event: {
538
545
  context: Context;
546
+ agent: Agent;
539
547
  input: I;
540
548
  }) => PromiseOrValue<void | {
541
549
  input?: I;
550
+ options?: any;
542
551
  }>) | Agent<{
543
552
  input: I;
544
553
  }, {
545
554
  input?: I;
555
+ options?: any;
546
556
  }>;
547
557
  /**
548
558
  * Called when agent processing completes or fails
@@ -555,6 +565,7 @@ export interface AgentHooks<I extends Message = Message, O extends Message = Mes
555
565
  */
556
566
  onEnd?: ((event: XOr<{
557
567
  context: Context;
568
+ agent: Agent;
558
569
  input: I;
559
570
  output: O;
560
571
  error: Error;
@@ -569,6 +580,7 @@ export interface AgentHooks<I extends Message = Message, O extends Message = Mes
569
580
  }>;
570
581
  onSuccess?: ((event: {
571
582
  context: Context;
583
+ agent: Agent;
572
584
  input: I;
573
585
  output: O;
574
586
  }) => PromiseOrValue<void | {
@@ -581,6 +593,7 @@ export interface AgentHooks<I extends Message = Message, O extends Message = Mes
581
593
  }>;
582
594
  onError?: ((event: {
583
595
  context: Context;
596
+ agent: Agent;
584
597
  input: I;
585
598
  error: Error;
586
599
  }) => void) | Agent<{
@@ -597,6 +610,7 @@ export interface AgentHooks<I extends Message = Message, O extends Message = Mes
597
610
  */
598
611
  onSkillStart?: ((event: {
599
612
  context: Context;
613
+ agent: Agent;
600
614
  skill: Agent;
601
615
  input: Message;
602
616
  }) => PromiseOrValue<void>) | Agent<{
@@ -614,6 +628,7 @@ export interface AgentHooks<I extends Message = Message, O extends Message = Mes
614
628
  */
615
629
  onSkillEnd?: ((event: XOr<{
616
630
  context: Context;
631
+ agent: Agent;
617
632
  skill: Agent;
618
633
  input: Message;
619
634
  output: Message;
@@ -644,7 +659,7 @@ export interface AgentHooks<I extends Message = Message, O extends Message = Mes
644
659
  input: I;
645
660
  }>;
646
661
  }
647
- export type AgentHookInput<H extends keyof AgentHooks, Hook extends AgentHooks[H] = AgentHooks[H]> = Hook extends (input: infer I) => any ? Omit<I, "context"> : never;
662
+ export type AgentHookInput<H extends keyof AgentHooks, Hook extends AgentHooks[H] = AgentHooks[H]> = Hook extends (input: infer I) => any ? Omit<I, "context" | "agent"> : never;
648
663
  export type AgentHookOutput<H extends keyof AgentHooks, Hook extends AgentHooks[H] = AgentHooks[H]> = Hook extends (...args: any[]) => any ? Exclude<Awaited<ReturnType<Hook>>, void> | undefined : never;
649
664
  /**
650
665
  * Response type for an agent, can be:
@@ -348,6 +348,8 @@ class Agent {
348
348
  const s = await this.callHooks("onStart", { input }, opts);
349
349
  if (s?.input)
350
350
  input = s.input;
351
+ if (s?.options)
352
+ Object.assign(opts, s.options);
351
353
  input = (0, type_utils_js_1.checkArguments)(`Agent ${this.name} input`, this.inputSchema, input);
352
354
  await this.preprocess(input, opts);
353
355
  this.checkContextStatus(opts);
@@ -386,10 +388,10 @@ class Agent {
386
388
  if (!h)
387
389
  continue;
388
390
  if (typeof h === "function") {
389
- Object.assign(result, await h({ ...input, context }));
391
+ Object.assign(result, await h({ ...input, context, agent: this }));
390
392
  }
391
393
  else {
392
- Object.assign(result, await context.invoke(h, input));
394
+ Object.assign(result, await context.invoke(h, { ...input, agent: this }));
393
395
  }
394
396
  }
395
397
  return result;
@@ -156,6 +156,7 @@ export declare class AIGNEContext implements Context {
156
156
  get observer(): AIGNEObserver | undefined;
157
157
  get limits(): ContextLimits | undefined;
158
158
  get status(): "normal" | "timeout";
159
+ get spans(): Span[];
159
160
  get usage(): ContextUsage;
160
161
  get userContext(): Context["userContext"];
161
162
  set userContext(userContext: Context["userContext"]);
@@ -170,6 +171,7 @@ export declare class AIGNEContext implements Context {
170
171
  subscribe: Context["subscribe"];
171
172
  unsubscribe: Context["unsubscribe"];
172
173
  emit<K extends keyof ContextEmitEventMap>(eventName: K, ...args: Args<K, ContextEmitEventMap>): boolean;
174
+ private endAllSpans;
173
175
  private trace;
174
176
  on<K extends keyof ContextEventMap>(eventName: K, listener: Listener<K, ContextEventMap>): this;
175
177
  once<K extends keyof ContextEventMap>(eventName: K, listener: Listener<K, ContextEventMap>): this;
@@ -177,7 +179,7 @@ export declare class AIGNEContext implements Context {
177
179
  }
178
180
  declare class AIGNEContextShared {
179
181
  private readonly parent?;
180
- span?: Span;
182
+ spans: Span[];
181
183
  constructor(parent?: (Pick<Context, "model" | "skills" | "limits" | "observer"> & {
182
184
  messageQueue?: MessageQueue;
183
185
  events?: Emitter<any>;
@@ -188,6 +190,7 @@ declare class AIGNEContextShared {
188
190
  get skills(): Agent<any, any>[] | undefined;
189
191
  get observer(): AIGNEObserver | undefined;
190
192
  get limits(): ContextLimits | undefined;
193
+ addSpan(span: Span): void;
191
194
  usage: ContextUsage;
192
195
  userContext: Context["userContext"];
193
196
  memories: Context["memories"];
@@ -40,11 +40,14 @@ class AIGNEContext {
40
40
  }
41
41
  }
42
42
  else {
43
- this.internal = new AIGNEContextShared(parent instanceof AIGNEContext ? parent.internal : parent);
44
43
  this.span = tracer?.startSpan("AIGNEContext");
44
+ this.internal = new AIGNEContextShared(parent instanceof AIGNEContext ? parent.internal : parent);
45
45
  // 修改了 rootId 是否会之前的有影响?,之前为 this.id
46
46
  this.rootId = this.span?.spanContext?.().traceId ?? (0, uuid_1.v7)();
47
47
  }
48
+ if (this.span) {
49
+ this.internal.addSpan(this.span);
50
+ }
48
51
  this.id = this.span?.spanContext()?.spanId ?? (0, uuid_1.v7)();
49
52
  }
50
53
  id;
@@ -70,6 +73,9 @@ class AIGNEContext {
70
73
  get status() {
71
74
  return this.internal.status;
72
75
  }
76
+ get spans() {
77
+ return this.internal.spans;
78
+ }
73
79
  get usage() {
74
80
  return this.internal.usage;
75
81
  }
@@ -111,12 +117,18 @@ class AIGNEContext {
111
117
  const newContext = options?.newContext === false ? this : this.newContext();
112
118
  return Promise.resolve(newContext.internal.invoke(agent, message, newContext, options)).then(async (response) => {
113
119
  if (!options?.streaming) {
114
- let { __activeAgent__: activeAgent, ...output } = await (0, stream_utils_js_1.agentResponseStreamToObject)(response);
115
- output = await this.onInvocationResult(output, options);
116
- if (options?.returnActiveAgent) {
117
- return [output, activeAgent];
120
+ try {
121
+ let { __activeAgent__: activeAgent, ...output } = await (0, stream_utils_js_1.agentResponseStreamToObject)(response);
122
+ output = await this.onInvocationResult(output, options);
123
+ if (options?.returnActiveAgent) {
124
+ return [output, activeAgent];
125
+ }
126
+ return output;
127
+ }
128
+ catch (error) {
129
+ this.endAllSpans(error);
130
+ throw error;
118
131
  }
119
- return output;
120
132
  }
121
133
  const activeAgentPromise = (0, promise_js_1.promiseWithResolvers)();
122
134
  const stream = (0, stream_utils_js_1.onAgentResponseStreamEnd)((0, stream_utils_js_1.asyncGeneratorToReadableStream)(response), {
@@ -135,6 +147,10 @@ class AIGNEContext {
135
147
  activeAgentPromise.resolve(output.__activeAgent__);
136
148
  return await this.onInvocationResult(output, options);
137
149
  },
150
+ onError: (error) => {
151
+ this.endAllSpans(error);
152
+ return error;
153
+ },
138
154
  });
139
155
  const finalStream = !options.returnProgressChunks
140
156
  ? stream
@@ -189,6 +205,12 @@ class AIGNEContext {
189
205
  this.trace(eventName, args, b);
190
206
  return this.internal.events.emit(eventName, ...newArgs);
191
207
  }
208
+ async endAllSpans(error) {
209
+ this.spans.forEach((span) => {
210
+ span.setStatus({ code: api_1.SpanStatusCode.ERROR, message: error?.message });
211
+ span.end();
212
+ });
213
+ }
192
214
  async trace(eventName, args, b) {
193
215
  const span = this.span;
194
216
  if (!span)
@@ -220,11 +242,7 @@ class AIGNEContext {
220
242
  logger_js_1.logger.error("parse memories error", _e.message);
221
243
  span.setAttribute("memories", JSON.stringify([]));
222
244
  }
223
- await this.observer?.traceExporter
224
- ?.upsertInitialSpan?.(span)
225
- .catch((err) => {
226
- logger_js_1.logger.error("upsertInitialSpan error", err?.message || err);
227
- });
245
+ await this.observer?.flush(span);
228
246
  break;
229
247
  }
230
248
  case "agentSucceed": {
@@ -268,7 +286,7 @@ class AIGNEContext {
268
286
  exports.AIGNEContext = AIGNEContext;
269
287
  class AIGNEContextShared {
270
288
  parent;
271
- span;
289
+ spans = [];
272
290
  constructor(parent) {
273
291
  this.parent = parent;
274
292
  this.messageQueue = this.parent?.messageQueue ?? new message_queue_js_1.MessageQueue();
@@ -288,6 +306,9 @@ class AIGNEContextShared {
288
306
  get limits() {
289
307
  return this.parent?.limits;
290
308
  }
309
+ addSpan(span) {
310
+ this.spans.push(span);
311
+ }
291
312
  usage = (0, usage_js_1.newEmptyContextUsage)();
292
313
  userContext = {};
293
314
  memories = [];
@@ -317,7 +338,7 @@ class AIGNEContextShared {
317
338
  for (;;) {
318
339
  const result = {};
319
340
  if (options?.sourceAgent && activeAgent !== options.sourceAgent) {
320
- for (const { onHandoff } of [options.hooks ?? {}, ...options.sourceAgent.hooks]) {
341
+ for (const { onHandoff } of (0, type_utils_js_1.flat)(options.hooks, options.sourceAgent.hooks)) {
321
342
  if (!onHandoff)
322
343
  continue;
323
344
  await (typeof onHandoff === "function"
@@ -1,4 +1,5 @@
1
1
  import { nodejs } from "@aigne/platform-helpers/nodejs/index.js";
2
+ import type * as prompts from "@inquirer/prompts";
2
3
  import { ZodObject, type ZodType } from "zod";
3
4
  import type { AgentEvent, Context, UserContext } from "../aigne/context.js";
4
5
  import type { MessagePayload } from "../aigne/message-queue.js";
@@ -146,7 +147,13 @@ export interface AgentInvokeOptions<U extends UserContext = UserContext> {
146
147
  /**
147
148
  * Optional hooks for agent invocation
148
149
  */
149
- hooks?: AgentHooks<any, any>;
150
+ hooks?: AgentHooks<any, any> | AgentHooks<any, any>[];
151
+ /**
152
+ * @inquirer/prompts used for collecting user input during agent execution
153
+ *
154
+ * This property only exists in the CLI context by command `aigne run`
155
+ */
156
+ prompts?: typeof prompts;
150
157
  }
151
158
  /**
152
159
  * Agent is the base class for all agents.
@@ -536,13 +543,16 @@ export interface AgentHooks<I extends Message = Message, O extends Message = Mes
536
543
  */
537
544
  onStart?: ((event: {
538
545
  context: Context;
546
+ agent: Agent;
539
547
  input: I;
540
548
  }) => PromiseOrValue<void | {
541
549
  input?: I;
550
+ options?: any;
542
551
  }>) | Agent<{
543
552
  input: I;
544
553
  }, {
545
554
  input?: I;
555
+ options?: any;
546
556
  }>;
547
557
  /**
548
558
  * Called when agent processing completes or fails
@@ -555,6 +565,7 @@ export interface AgentHooks<I extends Message = Message, O extends Message = Mes
555
565
  */
556
566
  onEnd?: ((event: XOr<{
557
567
  context: Context;
568
+ agent: Agent;
558
569
  input: I;
559
570
  output: O;
560
571
  error: Error;
@@ -569,6 +580,7 @@ export interface AgentHooks<I extends Message = Message, O extends Message = Mes
569
580
  }>;
570
581
  onSuccess?: ((event: {
571
582
  context: Context;
583
+ agent: Agent;
572
584
  input: I;
573
585
  output: O;
574
586
  }) => PromiseOrValue<void | {
@@ -581,6 +593,7 @@ export interface AgentHooks<I extends Message = Message, O extends Message = Mes
581
593
  }>;
582
594
  onError?: ((event: {
583
595
  context: Context;
596
+ agent: Agent;
584
597
  input: I;
585
598
  error: Error;
586
599
  }) => void) | Agent<{
@@ -597,6 +610,7 @@ export interface AgentHooks<I extends Message = Message, O extends Message = Mes
597
610
  */
598
611
  onSkillStart?: ((event: {
599
612
  context: Context;
613
+ agent: Agent;
600
614
  skill: Agent;
601
615
  input: Message;
602
616
  }) => PromiseOrValue<void>) | Agent<{
@@ -614,6 +628,7 @@ export interface AgentHooks<I extends Message = Message, O extends Message = Mes
614
628
  */
615
629
  onSkillEnd?: ((event: XOr<{
616
630
  context: Context;
631
+ agent: Agent;
617
632
  skill: Agent;
618
633
  input: Message;
619
634
  output: Message;
@@ -644,7 +659,7 @@ export interface AgentHooks<I extends Message = Message, O extends Message = Mes
644
659
  input: I;
645
660
  }>;
646
661
  }
647
- export type AgentHookInput<H extends keyof AgentHooks, Hook extends AgentHooks[H] = AgentHooks[H]> = Hook extends (input: infer I) => any ? Omit<I, "context"> : never;
662
+ export type AgentHookInput<H extends keyof AgentHooks, Hook extends AgentHooks[H] = AgentHooks[H]> = Hook extends (input: infer I) => any ? Omit<I, "context" | "agent"> : never;
648
663
  export type AgentHookOutput<H extends keyof AgentHooks, Hook extends AgentHooks[H] = AgentHooks[H]> = Hook extends (...args: any[]) => any ? Exclude<Awaited<ReturnType<Hook>>, void> | undefined : never;
649
664
  /**
650
665
  * Response type for an agent, can be:
@@ -156,6 +156,7 @@ export declare class AIGNEContext implements Context {
156
156
  get observer(): AIGNEObserver | undefined;
157
157
  get limits(): ContextLimits | undefined;
158
158
  get status(): "normal" | "timeout";
159
+ get spans(): Span[];
159
160
  get usage(): ContextUsage;
160
161
  get userContext(): Context["userContext"];
161
162
  set userContext(userContext: Context["userContext"]);
@@ -170,6 +171,7 @@ export declare class AIGNEContext implements Context {
170
171
  subscribe: Context["subscribe"];
171
172
  unsubscribe: Context["unsubscribe"];
172
173
  emit<K extends keyof ContextEmitEventMap>(eventName: K, ...args: Args<K, ContextEmitEventMap>): boolean;
174
+ private endAllSpans;
173
175
  private trace;
174
176
  on<K extends keyof ContextEventMap>(eventName: K, listener: Listener<K, ContextEventMap>): this;
175
177
  once<K extends keyof ContextEventMap>(eventName: K, listener: Listener<K, ContextEventMap>): this;
@@ -177,7 +179,7 @@ export declare class AIGNEContext implements Context {
177
179
  }
178
180
  declare class AIGNEContextShared {
179
181
  private readonly parent?;
180
- span?: Span;
182
+ spans: Span[];
181
183
  constructor(parent?: (Pick<Context, "model" | "skills" | "limits" | "observer"> & {
182
184
  messageQueue?: MessageQueue;
183
185
  events?: Emitter<any>;
@@ -188,6 +190,7 @@ declare class AIGNEContextShared {
188
190
  get skills(): Agent<any, any>[] | undefined;
189
191
  get observer(): AIGNEObserver | undefined;
190
192
  get limits(): ContextLimits | undefined;
193
+ addSpan(span: Span): void;
191
194
  usage: ContextUsage;
192
195
  userContext: Context["userContext"];
193
196
  memories: Context["memories"];
@@ -1,4 +1,5 @@
1
1
  import { nodejs } from "@aigne/platform-helpers/nodejs/index.js";
2
+ import type * as prompts from "@inquirer/prompts";
2
3
  import { ZodObject, type ZodType } from "zod";
3
4
  import type { AgentEvent, Context, UserContext } from "../aigne/context.js";
4
5
  import type { MessagePayload } from "../aigne/message-queue.js";
@@ -146,7 +147,13 @@ export interface AgentInvokeOptions<U extends UserContext = UserContext> {
146
147
  /**
147
148
  * Optional hooks for agent invocation
148
149
  */
149
- hooks?: AgentHooks<any, any>;
150
+ hooks?: AgentHooks<any, any> | AgentHooks<any, any>[];
151
+ /**
152
+ * @inquirer/prompts used for collecting user input during agent execution
153
+ *
154
+ * This property only exists in the CLI context by command `aigne run`
155
+ */
156
+ prompts?: typeof prompts;
150
157
  }
151
158
  /**
152
159
  * Agent is the base class for all agents.
@@ -536,13 +543,16 @@ export interface AgentHooks<I extends Message = Message, O extends Message = Mes
536
543
  */
537
544
  onStart?: ((event: {
538
545
  context: Context;
546
+ agent: Agent;
539
547
  input: I;
540
548
  }) => PromiseOrValue<void | {
541
549
  input?: I;
550
+ options?: any;
542
551
  }>) | Agent<{
543
552
  input: I;
544
553
  }, {
545
554
  input?: I;
555
+ options?: any;
546
556
  }>;
547
557
  /**
548
558
  * Called when agent processing completes or fails
@@ -555,6 +565,7 @@ export interface AgentHooks<I extends Message = Message, O extends Message = Mes
555
565
  */
556
566
  onEnd?: ((event: XOr<{
557
567
  context: Context;
568
+ agent: Agent;
558
569
  input: I;
559
570
  output: O;
560
571
  error: Error;
@@ -569,6 +580,7 @@ export interface AgentHooks<I extends Message = Message, O extends Message = Mes
569
580
  }>;
570
581
  onSuccess?: ((event: {
571
582
  context: Context;
583
+ agent: Agent;
572
584
  input: I;
573
585
  output: O;
574
586
  }) => PromiseOrValue<void | {
@@ -581,6 +593,7 @@ export interface AgentHooks<I extends Message = Message, O extends Message = Mes
581
593
  }>;
582
594
  onError?: ((event: {
583
595
  context: Context;
596
+ agent: Agent;
584
597
  input: I;
585
598
  error: Error;
586
599
  }) => void) | Agent<{
@@ -597,6 +610,7 @@ export interface AgentHooks<I extends Message = Message, O extends Message = Mes
597
610
  */
598
611
  onSkillStart?: ((event: {
599
612
  context: Context;
613
+ agent: Agent;
600
614
  skill: Agent;
601
615
  input: Message;
602
616
  }) => PromiseOrValue<void>) | Agent<{
@@ -614,6 +628,7 @@ export interface AgentHooks<I extends Message = Message, O extends Message = Mes
614
628
  */
615
629
  onSkillEnd?: ((event: XOr<{
616
630
  context: Context;
631
+ agent: Agent;
617
632
  skill: Agent;
618
633
  input: Message;
619
634
  output: Message;
@@ -644,7 +659,7 @@ export interface AgentHooks<I extends Message = Message, O extends Message = Mes
644
659
  input: I;
645
660
  }>;
646
661
  }
647
- export type AgentHookInput<H extends keyof AgentHooks, Hook extends AgentHooks[H] = AgentHooks[H]> = Hook extends (input: infer I) => any ? Omit<I, "context"> : never;
662
+ export type AgentHookInput<H extends keyof AgentHooks, Hook extends AgentHooks[H] = AgentHooks[H]> = Hook extends (input: infer I) => any ? Omit<I, "context" | "agent"> : never;
648
663
  export type AgentHookOutput<H extends keyof AgentHooks, Hook extends AgentHooks[H] = AgentHooks[H]> = Hook extends (...args: any[]) => any ? Exclude<Awaited<ReturnType<Hook>>, void> | undefined : never;
649
664
  /**
650
665
  * Response type for an agent, can be:
@@ -303,6 +303,8 @@ export class Agent {
303
303
  const s = await this.callHooks("onStart", { input }, opts);
304
304
  if (s?.input)
305
305
  input = s.input;
306
+ if (s?.options)
307
+ Object.assign(opts, s.options);
306
308
  input = checkArguments(`Agent ${this.name} input`, this.inputSchema, input);
307
309
  await this.preprocess(input, opts);
308
310
  this.checkContextStatus(opts);
@@ -341,10 +343,10 @@ export class Agent {
341
343
  if (!h)
342
344
  continue;
343
345
  if (typeof h === "function") {
344
- Object.assign(result, await h({ ...input, context }));
346
+ Object.assign(result, await h({ ...input, context, agent: this }));
345
347
  }
346
348
  else {
347
- Object.assign(result, await context.invoke(h, input));
349
+ Object.assign(result, await context.invoke(h, { ...input, agent: this }));
348
350
  }
349
351
  }
350
352
  return result;
@@ -156,6 +156,7 @@ export declare class AIGNEContext implements Context {
156
156
  get observer(): AIGNEObserver | undefined;
157
157
  get limits(): ContextLimits | undefined;
158
158
  get status(): "normal" | "timeout";
159
+ get spans(): Span[];
159
160
  get usage(): ContextUsage;
160
161
  get userContext(): Context["userContext"];
161
162
  set userContext(userContext: Context["userContext"]);
@@ -170,6 +171,7 @@ export declare class AIGNEContext implements Context {
170
171
  subscribe: Context["subscribe"];
171
172
  unsubscribe: Context["unsubscribe"];
172
173
  emit<K extends keyof ContextEmitEventMap>(eventName: K, ...args: Args<K, ContextEmitEventMap>): boolean;
174
+ private endAllSpans;
173
175
  private trace;
174
176
  on<K extends keyof ContextEventMap>(eventName: K, listener: Listener<K, ContextEventMap>): this;
175
177
  once<K extends keyof ContextEventMap>(eventName: K, listener: Listener<K, ContextEventMap>): this;
@@ -177,7 +179,7 @@ export declare class AIGNEContext implements Context {
177
179
  }
178
180
  declare class AIGNEContextShared {
179
181
  private readonly parent?;
180
- span?: Span;
182
+ spans: Span[];
181
183
  constructor(parent?: (Pick<Context, "model" | "skills" | "limits" | "observer"> & {
182
184
  messageQueue?: MessageQueue;
183
185
  events?: Emitter<any>;
@@ -188,6 +190,7 @@ declare class AIGNEContextShared {
188
190
  get skills(): Agent<any, any>[] | undefined;
189
191
  get observer(): AIGNEObserver | undefined;
190
192
  get limits(): ContextLimits | undefined;
193
+ addSpan(span: Span): void;
191
194
  usage: ContextUsage;
192
195
  userContext: Context["userContext"];
193
196
  memories: Context["memories"];
@@ -10,7 +10,7 @@ import { AgentResponseProgressStream } from "../utils/event-stream.js";
10
10
  import { logger } from "../utils/logger.js";
11
11
  import { promiseWithResolvers } from "../utils/promise.js";
12
12
  import { agentResponseStreamToObject, asyncGeneratorToReadableStream, mergeReadableStreams, onAgentResponseStreamEnd, } from "../utils/stream-utils.js";
13
- import { checkArguments, isEmpty, isNil, omit, } from "../utils/type-utils.js";
13
+ import { checkArguments, flat, isEmpty, isNil, omit, } from "../utils/type-utils.js";
14
14
  import { MessageQueue, toMessagePayload, } from "./message-queue.js";
15
15
  import { newEmptyContextUsage } from "./usage.js";
16
16
  /**
@@ -34,11 +34,14 @@ export class AIGNEContext {
34
34
  }
35
35
  }
36
36
  else {
37
- this.internal = new AIGNEContextShared(parent instanceof AIGNEContext ? parent.internal : parent);
38
37
  this.span = tracer?.startSpan("AIGNEContext");
38
+ this.internal = new AIGNEContextShared(parent instanceof AIGNEContext ? parent.internal : parent);
39
39
  // 修改了 rootId 是否会之前的有影响?,之前为 this.id
40
40
  this.rootId = this.span?.spanContext?.().traceId ?? v7();
41
41
  }
42
+ if (this.span) {
43
+ this.internal.addSpan(this.span);
44
+ }
42
45
  this.id = this.span?.spanContext()?.spanId ?? v7();
43
46
  }
44
47
  id;
@@ -64,6 +67,9 @@ export class AIGNEContext {
64
67
  get status() {
65
68
  return this.internal.status;
66
69
  }
70
+ get spans() {
71
+ return this.internal.spans;
72
+ }
67
73
  get usage() {
68
74
  return this.internal.usage;
69
75
  }
@@ -105,12 +111,18 @@ export class AIGNEContext {
105
111
  const newContext = options?.newContext === false ? this : this.newContext();
106
112
  return Promise.resolve(newContext.internal.invoke(agent, message, newContext, options)).then(async (response) => {
107
113
  if (!options?.streaming) {
108
- let { __activeAgent__: activeAgent, ...output } = await agentResponseStreamToObject(response);
109
- output = await this.onInvocationResult(output, options);
110
- if (options?.returnActiveAgent) {
111
- return [output, activeAgent];
114
+ try {
115
+ let { __activeAgent__: activeAgent, ...output } = await agentResponseStreamToObject(response);
116
+ output = await this.onInvocationResult(output, options);
117
+ if (options?.returnActiveAgent) {
118
+ return [output, activeAgent];
119
+ }
120
+ return output;
121
+ }
122
+ catch (error) {
123
+ this.endAllSpans(error);
124
+ throw error;
112
125
  }
113
- return output;
114
126
  }
115
127
  const activeAgentPromise = promiseWithResolvers();
116
128
  const stream = onAgentResponseStreamEnd(asyncGeneratorToReadableStream(response), {
@@ -129,6 +141,10 @@ export class AIGNEContext {
129
141
  activeAgentPromise.resolve(output.__activeAgent__);
130
142
  return await this.onInvocationResult(output, options);
131
143
  },
144
+ onError: (error) => {
145
+ this.endAllSpans(error);
146
+ return error;
147
+ },
132
148
  });
133
149
  const finalStream = !options.returnProgressChunks
134
150
  ? stream
@@ -183,6 +199,12 @@ export class AIGNEContext {
183
199
  this.trace(eventName, args, b);
184
200
  return this.internal.events.emit(eventName, ...newArgs);
185
201
  }
202
+ async endAllSpans(error) {
203
+ this.spans.forEach((span) => {
204
+ span.setStatus({ code: SpanStatusCode.ERROR, message: error?.message });
205
+ span.end();
206
+ });
207
+ }
186
208
  async trace(eventName, args, b) {
187
209
  const span = this.span;
188
210
  if (!span)
@@ -214,11 +236,7 @@ export class AIGNEContext {
214
236
  logger.error("parse memories error", _e.message);
215
237
  span.setAttribute("memories", JSON.stringify([]));
216
238
  }
217
- await this.observer?.traceExporter
218
- ?.upsertInitialSpan?.(span)
219
- .catch((err) => {
220
- logger.error("upsertInitialSpan error", err?.message || err);
221
- });
239
+ await this.observer?.flush(span);
222
240
  break;
223
241
  }
224
242
  case "agentSucceed": {
@@ -261,7 +279,7 @@ export class AIGNEContext {
261
279
  }
262
280
  class AIGNEContextShared {
263
281
  parent;
264
- span;
282
+ spans = [];
265
283
  constructor(parent) {
266
284
  this.parent = parent;
267
285
  this.messageQueue = this.parent?.messageQueue ?? new MessageQueue();
@@ -281,6 +299,9 @@ class AIGNEContextShared {
281
299
  get limits() {
282
300
  return this.parent?.limits;
283
301
  }
302
+ addSpan(span) {
303
+ this.spans.push(span);
304
+ }
284
305
  usage = newEmptyContextUsage();
285
306
  userContext = {};
286
307
  memories = [];
@@ -310,7 +331,7 @@ class AIGNEContextShared {
310
331
  for (;;) {
311
332
  const result = {};
312
333
  if (options?.sourceAgent && activeAgent !== options.sourceAgent) {
313
- for (const { onHandoff } of [options.hooks ?? {}, ...options.sourceAgent.hooks]) {
334
+ for (const { onHandoff } of flat(options.hooks, options.sourceAgent.hooks)) {
314
335
  if (!onHandoff)
315
336
  continue;
316
337
  await (typeof onHandoff === "function"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aigne/core",
3
- "version": "1.38.1",
3
+ "version": "1.39.0",
4
4
  "description": "AIGNE core library for building AI-powered applications",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -63,6 +63,7 @@
63
63
  },
64
64
  "dependencies": {
65
65
  "@aigne/json-schema-to-zod": "^1.3.3",
66
+ "@inquirer/prompts": "^7.6.0",
66
67
  "@modelcontextprotocol/sdk": "^1.15.0",
67
68
  "@opentelemetry/api": "^1.9.0",
68
69
  "@opentelemetry/sdk-trace-base": "^2.0.1",
@@ -85,7 +86,7 @@
85
86
  "yaml": "^2.8.0",
86
87
  "zod": "^3.25.67",
87
88
  "zod-to-json-schema": "^3.24.6",
88
- "@aigne/observability-api": "^0.8.1",
89
+ "@aigne/observability-api": "^0.8.2",
89
90
  "@aigne/platform-helpers": "^0.4.0"
90
91
  },
91
92
  "devDependencies": {