@cloudbase/agent-server 0.0.14 → 1.0.1-alpha.10

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/index.d.ts CHANGED
@@ -10,6 +10,14 @@ import { Repeater } from '@repeaterjs/repeater';
10
10
  import * as _whatwg_node_server from '@whatwg-node/server';
11
11
  import { OpenAI } from 'openai';
12
12
 
13
+ /**
14
+ * Type-only reference to ObservabilityConfig for documentation purposes.
15
+ * The actual type is: ObservabilityConfig | ObservabilityConfig[]
16
+ *
17
+ * At runtime, this accepts any value matching the ObservabilityConfig interface
18
+ * from @cloudbase/agent-observability/server package (if installed).
19
+ */
20
+ type ObservabilityConfigOrArray = any;
13
21
  /**
14
22
  * Context passed to the agent factory function.
15
23
  * Contains request information for per-request agent configuration.
@@ -53,16 +61,49 @@ interface ICreateServer {
53
61
  * createExpressServer({ createAgent, logger: pino({ level: 'info' }) });
54
62
  */
55
63
  logger?: Logger;
64
+ /**
65
+ * Observability configuration for trace exporters.
66
+ *
67
+ * Requires @cloudbase/agent-observability package to be installed.
68
+ * If the package is not installed, this option is silently ignored.
69
+ *
70
+ * Type reference: ObservabilityConfig | ObservabilityConfig[] from @cloudbase/agent-observability/server
71
+ *
72
+ * @example
73
+ * // Console exporter (from env AUTO_TRACES_STDOUT)
74
+ * createExpressServer({ createAgent, observability: { type: 'console' } });
75
+ *
76
+ * // OTLP exporter (Langfuse, Jaeger, etc.)
77
+ * createExpressServer({
78
+ * createAgent,
79
+ * observability: {
80
+ * type: 'otlp',
81
+ * url: 'https://cloud.langfuse.com/api/public/otlp/v1/traces',
82
+ * headers: { 'Authorization': 'Basic xxx' }
83
+ * }
84
+ * });
85
+ *
86
+ * // Multiple exporters
87
+ * createExpressServer({
88
+ * createAgent,
89
+ * observability: [
90
+ * { type: 'console' },
91
+ * { type: 'otlp', url: 'http://localhost:4318/v1/traces' }
92
+ * ]
93
+ * });
94
+ */
95
+ observability?: ObservabilityConfigOrArray;
56
96
  }
57
97
  interface IRun extends ICreateServer {
58
98
  port?: number | string;
59
99
  }
60
100
  interface ICreateExpressRoutes extends Omit<ICreateServer, "cors"> {
61
101
  express: Express;
102
+ observability?: ICreateServer['observability'];
62
103
  }
63
104
  declare function run(props: IRun): void;
64
105
  declare function createExpressServer(props: ICreateServer): Express;
65
- declare function createExpressRoutes({ createAgent, basePath: _basePath, express, useAGUI: _useAGUI, aguiOptions, logger: _logger, }: ICreateExpressRoutes): expressLib.Express;
106
+ declare function createExpressRoutes({ createAgent, basePath: _basePath, express, useAGUI: _useAGUI, aguiOptions, logger: _logger, observability, }: ICreateExpressRoutes): expressLib.Express;
66
107
  interface AGUIOptions {
67
108
  runtimeOptions?: Partial<CopilotRuntimeOptions>;
68
109
  endpointOptions?: Partial<CreateCopilotRuntimeServerOptions>;
package/dist/index.js CHANGED
@@ -389,12 +389,45 @@ var ErrorCode = {
389
389
  };
390
390
 
391
391
  // src/agui/sendMessageAGUI/server.ts
392
+ var startObservation;
393
+ var setupObservability;
394
+ var observabilityLoadAttempted = false;
395
+ async function loadObservability() {
396
+ if (!observabilityLoadAttempted) {
397
+ observabilityLoadAttempted = true;
398
+ try {
399
+ const obs = await import("@cloudbase/agent-observability");
400
+ const obsServer = await import("@cloudbase/agent-observability/server");
401
+ startObservation = obs.startObservation;
402
+ setupObservability = obsServer.setupObservability;
403
+ return true;
404
+ } catch (e) {
405
+ return false;
406
+ }
407
+ }
408
+ return !!startObservation;
409
+ }
410
+ async function ensureObservabilityReady() {
411
+ if (!setupObservability) return false;
412
+ try {
413
+ const timeoutPromise = new Promise((_, reject) => {
414
+ setTimeout(() => reject(new Error("Observability setup timeout")), 2e3);
415
+ });
416
+ await Promise.race([
417
+ setupObservability(),
418
+ timeoutPromise
419
+ ]);
420
+ return true;
421
+ } catch (e) {
422
+ return false;
423
+ }
424
+ }
392
425
  function createServerAdapter2(createAgent, options) {
393
426
  var _a;
394
427
  const { logger: parentLogger = import_agent_shared2.noopLogger } = options ?? {};
395
428
  const adapterLogger = ((_a = parentLogger.child) == null ? void 0 : _a.call(parentLogger, { component: "sendMessageAGUI" })) ?? parentLogger;
396
429
  return (0, import_server3.createServerAdapter)(async (request) => {
397
- var _a2, _b, _c, _d, _e, _f, _g, _h;
430
+ var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
398
431
  const requestId = getOrGenerateRequestId(request.headers, "agui");
399
432
  const logger = ((_a2 = adapterLogger.child) == null ? void 0 : _a2.call(adapterLogger, { requestId })) ?? adapterLogger;
400
433
  (_b = logger.info) == null ? void 0 : _b.call(logger, "Request received");
@@ -474,11 +507,46 @@ function createServerAdapter2(createAgent, options) {
474
507
  }
475
508
  );
476
509
  }
477
- const events = handler2(
478
- inputRes.result,
479
- createAgentRes.result.agent
480
- );
481
- let heartbeat;
510
+ const hasObservability = await loadObservability();
511
+ let serverSpan = null;
512
+ let serverContextData = null;
513
+ if (hasObservability && startObservation) {
514
+ try {
515
+ const isReady = await ensureObservabilityReady();
516
+ if (isReady) {
517
+ serverSpan = startObservation(
518
+ "AG-UI.Server",
519
+ {
520
+ "http.method": request.method,
521
+ "http.url": request.url,
522
+ "http.host": request.headers.get("host") || "unknown",
523
+ "http.user_agent": request.headers.get("user-agent") || "unknown",
524
+ "agui.thread_id": inputRes.result.threadId,
525
+ "agui.run_id": inputRes.result.runId
526
+ },
527
+ { asType: "span" }
528
+ );
529
+ const spanContext = serverSpan.otelSpan.spanContext();
530
+ serverContextData = {
531
+ traceId: spanContext.traceId,
532
+ spanId: spanContext.spanId,
533
+ traceFlags: spanContext.traceFlags
534
+ };
535
+ inputRes.result.forwardedProps = {
536
+ ...inputRes.result.forwardedProps,
537
+ __agui_server_context: serverContextData
538
+ };
539
+ (_i = logger.debug) == null ? void 0 : _i.call(logger, "\u2713 Server span created:", {
540
+ traceId: serverContextData.traceId,
541
+ spanId: serverContextData.spanId
542
+ });
543
+ } else {
544
+ (_j = logger.debug) == null ? void 0 : _j.call(logger, "Observability not ready, skipping span creation");
545
+ }
546
+ } catch (e) {
547
+ (_k = logger.debug) == null ? void 0 : _k.call(logger, "Failed to create server span:", e);
548
+ }
549
+ }
482
550
  let cleanupCalled = false;
483
551
  const safeCleanup = () => {
484
552
  var _a3, _b2, _c2;
@@ -491,9 +559,36 @@ function createServerAdapter2(createAgent, options) {
491
559
  }
492
560
  }
493
561
  };
562
+ const eventsResult = safe(
563
+ () => handler2(
564
+ inputRes.result,
565
+ createAgentRes.result.agent
566
+ )
567
+ );
568
+ if ("error" in eventsResult) {
569
+ const { error } = eventsResult;
570
+ (_l = logger.error) == null ? void 0 : _l.call(logger, { err: error }, "Run agent failed");
571
+ const errorCode = (0, import_agent_shared3.isErrorWithCode)(error) ? error.code : ErrorCode.INTERNAL_ERROR;
572
+ const errorMessage = error instanceof Error ? error.message : String(error);
573
+ return new Response(
574
+ JSON.stringify({
575
+ error: {
576
+ code: errorCode,
577
+ message: errorMessage
578
+ },
579
+ requestId
580
+ }),
581
+ {
582
+ status: 500,
583
+ headers: { "Content-Type": "application/json" }
584
+ }
585
+ );
586
+ }
587
+ const { result: events } = eventsResult;
588
+ let heartbeat;
494
589
  const stream = new ReadableStream({
495
590
  async start(controller) {
496
- var _a3, _b2, _c2, _d2;
591
+ var _a3, _b2, _c2, _d2, _e2;
497
592
  const encoder = new TextEncoder();
498
593
  heartbeat = setInterval(() => {
499
594
  controller.enqueue(encoder.encode(":ping\n\n"));
@@ -532,13 +627,21 @@ function createServerAdapter2(createAgent, options) {
532
627
  if (heartbeat) clearInterval(heartbeat);
533
628
  controller.close();
534
629
  safeCleanup();
630
+ if (serverSpan) {
631
+ serverSpan.end();
632
+ (_e2 = logger.debug) == null ? void 0 : _e2.call(logger, "\u2713 Server span ended");
633
+ }
535
634
  }
536
635
  },
537
636
  cancel() {
538
- var _a3;
637
+ var _a3, _b2;
539
638
  (_a3 = logger.info) == null ? void 0 : _a3.call(logger, "Request cancelled by client");
540
639
  if (heartbeat) clearInterval(heartbeat);
541
640
  safeCleanup();
641
+ if (serverSpan) {
642
+ serverSpan.end();
643
+ (_b2 = logger.debug) == null ? void 0 : _b2.call(logger, "\u2713 Server span ended (cancelled)");
644
+ }
542
645
  }
543
646
  });
544
647
  const headers = new Headers({
@@ -558,6 +661,15 @@ async function safeAsync(fn) {
558
661
  return { error };
559
662
  }
560
663
  }
664
+ function safe(fn) {
665
+ try {
666
+ return {
667
+ result: fn()
668
+ };
669
+ } catch (error) {
670
+ return { error };
671
+ }
672
+ }
561
673
 
562
674
  // src/agui/healthz/index.ts
563
675
  var healthz_exports = {};
@@ -756,6 +868,13 @@ var import_cors = __toESM(require("cors"));
756
868
  var import_async_hooks = require("async_hooks");
757
869
  var import_server8 = require("@whatwg-node/server");
758
870
  var DefaultFetchAPI = __toESM(require("@whatwg-node/fetch"));
871
+ async function setupObservabilityIfAvailable(configs) {
872
+ try {
873
+ const { setupObservability: setupObservability2 } = await import("@cloudbase/agent-observability/server");
874
+ await setupObservability2(configs);
875
+ } catch (error) {
876
+ }
877
+ }
759
878
  var preparedAgentStorage = new import_async_hooks.AsyncLocalStorage();
760
879
  function agentCloneFn() {
761
880
  const preparedAgent = preparedAgentStorage.getStore();
@@ -790,7 +909,8 @@ function createExpressRoutes({
790
909
  express,
791
910
  useAGUI: _useAGUI,
792
911
  aguiOptions,
793
- logger: _logger
912
+ logger: _logger,
913
+ observability
794
914
  }) {
795
915
  var _a, _b, _c;
796
916
  const useAGUI = _useAGUI ?? true;
@@ -798,6 +918,10 @@ function createExpressRoutes({
798
918
  const basePath = _basePath ?? (process.env.TENCENTCLOUD_RUNENV === "SCF" ? "/v1/aibot/bots/:agentId/" : "/");
799
919
  const serverLogger = ((_a = logger.child) == null ? void 0 : _a.call(logger, { component: "server" })) ?? logger;
800
920
  (_b = serverLogger.debug) == null ? void 0 : _b.call(serverLogger, { basePath, useAGUI }, "Initializing server routes");
921
+ if (observability) {
922
+ setupObservabilityIfAvailable(observability).catch(() => {
923
+ });
924
+ }
801
925
  const sendMessageServerAdapter = useAGUI ? sendMessageAGUI_exports.createServerAdapter(createAgent, { logger: serverLogger }) : sendMessage_exports.createServerAdapter(createAgent);
802
926
  if (useAGUI) {
803
927
  createAGUIRoute({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cloudbase/agent-server",
3
- "version": "0.0.14",
3
+ "version": "1.0.1-alpha.10",
4
4
  "main": "dist/index.js",
5
5
  "files": [
6
6
  "dist/",
@@ -20,11 +20,14 @@
20
20
  "express": "^5.1.0",
21
21
  "openai": "6.3.0",
22
22
  "uuid": "^10.0.0",
23
- "@cloudbase/agent-shared": "^0.0.14"
23
+ "@cloudbase/agent-shared": "^1.0.1-alpha.10"
24
24
  },
25
25
  "peerDependencies": {
26
26
  "zod": "^3.25.0 || ^4.0.0"
27
27
  },
28
+ "optionalDependencies": {
29
+ "@cloudbase/agent-observability": "1.0.1-alpha.10"
30
+ },
28
31
  "devDependencies": {
29
32
  "@types/cors": "^2.8.19",
30
33
  "@types/express": "^5.0.3",