@cuylabs/agent-a365-observability 4.6.0 → 4.7.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/README.md CHANGED
@@ -40,6 +40,7 @@ Dependency roles:
40
40
  ```typescript
41
41
  import { createAgent } from "@cuylabs/agent-core";
42
42
  import {
43
+ createA365ObservedTurnSource,
43
44
  createA365S2STokenResolverFromEnv,
44
45
  createA365TracingConfig,
45
46
  initA365S2SObservability,
@@ -90,6 +91,25 @@ await agent.close();
90
91
  await observability.shutdown();
91
92
  ```
92
93
 
94
+ When you are adapting a custom channel around `AgentTurnSource`, use
95
+ `createA365ObservedTurnSource(...)` instead of hand-rolling async-generator
96
+ wrapping. The helper keeps the full event stream inside the Agent 365 baggage
97
+ scope while letting the channel own its own metadata mapping:
98
+
99
+ ```typescript
100
+ const observedSource = createA365ObservedTurnSource({
101
+ source: agent,
102
+ context: ({ sessionId }) => ({
103
+ tenantId: "tenant-123",
104
+ agentId: "agent-456",
105
+ conversationId: sessionId,
106
+ sessionId,
107
+ channelName: "slack",
108
+ userId: "slack-user-id",
109
+ }),
110
+ });
111
+ ```
112
+
93
113
  ## M365 / Teams bot turns
94
114
 
95
115
  When your bot uses `@microsoft/agents-hosting` `TurnContext`, use the
@@ -148,7 +168,10 @@ The integration has four separate pieces:
148
168
  contract.
149
169
  3. `runWithA365Context(...)` or `runWithA365TurnContext(...)` binds
150
170
  per-request Agent 365 baggage before `agent.chat()` runs.
151
- 4. `createA365S2STokenResolver(...)` provides a reusable service-to-service
171
+ 4. `createA365ObservedTurnSource(...)` wraps a channel-neutral
172
+ `AgentTurnSource` when a host needs streaming-safe A365 baggage around every
173
+ emitted event.
174
+ 5. `createA365S2STokenResolver(...)` provides a reusable service-to-service
152
175
  token resolver for Agent 365 Observability API export.
153
176
 
154
177
  The source follows those same boundaries: `auth/` owns Agent 365 S2S token
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { TelemetryOptions } from 'ai';
2
+ import { AgentTurnSourceChatOptions, AgentTurnSource } from '@cuylabs/agent-core';
2
3
 
3
4
  type A365TokenResolver = (agentId: string, tenantId: string) => string | null | Promise<string | null>;
4
5
  type A365Logger = {
@@ -301,6 +302,19 @@ declare function createA365ContextFromTurnContext(turnContext: A365TurnContextLi
301
302
  declare function runWithA365TurnContext<T>(turnContext: A365TurnContextLike, fn: () => T, runtimeOptions?: A365ObservabilityRuntimeOptions): Promise<Awaited<T>>;
302
303
  declare function runWithA365TurnContext<T>(turnContext: A365TurnContextLike, options: A365TurnContextOptions, fn: () => T, runtimeOptions?: A365ObservabilityRuntimeOptions): Promise<Awaited<T>>;
303
304
 
305
+ type A365ObservedTurnSourceContextInput = {
306
+ sessionId: string;
307
+ message: string;
308
+ options?: AgentTurnSourceChatOptions;
309
+ };
310
+ type A365ObservedTurnSourceContextFactory = (input: A365ObservedTurnSourceContextInput) => A365RequestContext | Promise<A365RequestContext>;
311
+ type A365ObservedTurnSourceOptions = {
312
+ source: AgentTurnSource;
313
+ context: A365RequestContext | A365ObservedTurnSourceContextFactory;
314
+ runtimeOptions?: A365ObservabilityRuntimeOptions;
315
+ };
316
+ declare function createA365ObservedTurnSource({ context, runtimeOptions, source, }: A365ObservedTurnSourceOptions): AgentTurnSource;
317
+
304
318
  declare function initA365Observability(options: InitA365ObservabilityOptions): Promise<A365ObservabilityHandle>;
305
319
  declare function runWithA365Context<T>(requestContext: A365RequestContext, fn: () => T, options?: A365ObservabilityRuntimeOptions): Promise<Awaited<T>>;
306
320
  declare function updateA365ExportToken(token: string, options?: A365ObservabilityRuntimeOptions): Promise<boolean>;
@@ -346,4 +360,4 @@ type A365OutputScopeContext = A365RequestContext & {
346
360
  };
347
361
  declare function runWithA365OutputMessages<T>(output: A365OutputScopeContext, fn: () => T, options?: A365ObservabilityRuntimeOptions): Promise<Awaited<T>>;
348
362
 
349
- export { type A365ActivityAccountLike, type A365ActivityLike, type A365AuthorizationLike, type A365Environment, type A365ExporterEventName, type A365HeadersCarrier, type A365Logger, type A365ManagedIdentityAssertionProvider, type A365MutableHeadersCarrier, type A365OboTokenCacheOptions, type A365ObservabilityConfiguration, type A365ObservabilityHandle, A365ObservabilityHostingModuleLoadError, A365ObservabilityModuleLoadError, type A365ObservabilityModuleLoader, type A365ObservabilityRuntimeOptions, type A365OutputMessagesParam, type A365OutputScopeContext, type A365ParentSpanRef, type A365PerRequestExportConfiguration, type A365RefreshOboObservabilityTokenOptions, type A365RequestContext, type A365ResolvedObservabilityEnvironment, type A365S2STokenResolverFromEnvOptions, type A365S2STokenResolverLogger, type A365S2STokenResolverOptions, type A365TokenResolver, type A365TraceContextOptions, type A365TracingConfig, type A365TracingConfigOptions, type A365TurnContextLike, type A365TurnContextOptions, A365_BAGGAGE_KEYS, A365_EXPORTER_EVENT_NAMES, type InitA365ObservabilityOptions, type InitA365S2SObservabilityOptions, type SpanAttributeValue, applyA365PerRequestEnvironment, buildA365BaggagePairs, createA365ContextFromTurnContext, createA365ContextWithParentSpanRef, createA365OboTokenResolver, createA365S2STokenResolver, createA365S2STokenResolverFromEnv, createA365TracingConfig, extractA365TraceContextFromHeaders, initA365Observability, initA365S2SObservability, injectA365TraceContextToHeaders, invalidateA365OboObservabilityToken, invalidateAllA365OboObservabilityTokens, refreshA365OboObservabilityToken, resolveA365ObservabilityEnvironment, runWithA365Context, runWithA365ExtractedTraceContext, runWithA365OutputMessages, runWithA365ParentSpanRef, runWithA365TurnContext, updateA365ExportToken };
363
+ export { type A365ActivityAccountLike, type A365ActivityLike, type A365AuthorizationLike, type A365Environment, type A365ExporterEventName, type A365HeadersCarrier, type A365Logger, type A365ManagedIdentityAssertionProvider, type A365MutableHeadersCarrier, type A365OboTokenCacheOptions, type A365ObservabilityConfiguration, type A365ObservabilityHandle, A365ObservabilityHostingModuleLoadError, A365ObservabilityModuleLoadError, type A365ObservabilityModuleLoader, type A365ObservabilityRuntimeOptions, type A365ObservedTurnSourceContextFactory, type A365ObservedTurnSourceContextInput, type A365ObservedTurnSourceOptions, type A365OutputMessagesParam, type A365OutputScopeContext, type A365ParentSpanRef, type A365PerRequestExportConfiguration, type A365RefreshOboObservabilityTokenOptions, type A365RequestContext, type A365ResolvedObservabilityEnvironment, type A365S2STokenResolverFromEnvOptions, type A365S2STokenResolverLogger, type A365S2STokenResolverOptions, type A365TokenResolver, type A365TraceContextOptions, type A365TracingConfig, type A365TracingConfigOptions, type A365TurnContextLike, type A365TurnContextOptions, A365_BAGGAGE_KEYS, A365_EXPORTER_EVENT_NAMES, type InitA365ObservabilityOptions, type InitA365S2SObservabilityOptions, type SpanAttributeValue, applyA365PerRequestEnvironment, buildA365BaggagePairs, createA365ContextFromTurnContext, createA365ContextWithParentSpanRef, createA365OboTokenResolver, createA365ObservedTurnSource, createA365S2STokenResolver, createA365S2STokenResolverFromEnv, createA365TracingConfig, extractA365TraceContextFromHeaders, initA365Observability, initA365S2SObservability, injectA365TraceContextToHeaders, invalidateA365OboObservabilityToken, invalidateAllA365OboObservabilityTokens, refreshA365OboObservabilityToken, resolveA365ObservabilityEnvironment, runWithA365Context, runWithA365ExtractedTraceContext, runWithA365OutputMessages, runWithA365ParentSpanRef, runWithA365TurnContext, updateA365ExportToken };
package/dist/index.js CHANGED
@@ -876,6 +876,98 @@ async function runWithA365TurnContext(turnContext, optionsOrFn, maybeFnOrRuntime
876
876
  );
877
877
  }
878
878
 
879
+ // src/internal/async-queue.ts
880
+ var AsyncQueue = class {
881
+ values = [];
882
+ waiters = [];
883
+ closed = false;
884
+ push(value) {
885
+ if (this.closed) {
886
+ return;
887
+ }
888
+ const waiter = this.waiters.shift();
889
+ if (waiter) {
890
+ waiter({ value, done: false });
891
+ return;
892
+ }
893
+ this.values.push(value);
894
+ }
895
+ close() {
896
+ if (this.closed) {
897
+ return;
898
+ }
899
+ this.closed = true;
900
+ for (const waiter of this.waiters.splice(0)) {
901
+ waiter({ value: void 0, done: true });
902
+ }
903
+ }
904
+ [Symbol.asyncIterator]() {
905
+ return {
906
+ next: () => this.next()
907
+ };
908
+ }
909
+ next() {
910
+ if (this.values.length > 0) {
911
+ const value = this.values.shift();
912
+ return Promise.resolve({ value, done: false });
913
+ }
914
+ if (this.closed) {
915
+ return Promise.resolve({ value: void 0, done: true });
916
+ }
917
+ return new Promise((resolve) => {
918
+ this.waiters.push(resolve);
919
+ });
920
+ }
921
+ };
922
+
923
+ // src/context/turn-source.ts
924
+ function createA365ObservedTurnSource({
925
+ context,
926
+ runtimeOptions,
927
+ source
928
+ }) {
929
+ const resolveContext = typeof context === "function" ? context : () => context;
930
+ return {
931
+ async *chat(sessionId, message, options) {
932
+ const requestContext = await resolveContext({
933
+ sessionId,
934
+ message,
935
+ options
936
+ });
937
+ const queue = new AsyncQueue();
938
+ let failure;
939
+ void runWithA365Context(
940
+ requestContext,
941
+ async () => {
942
+ try {
943
+ for await (const event of source.chat(
944
+ sessionId,
945
+ message,
946
+ options
947
+ )) {
948
+ queue.push(event);
949
+ }
950
+ } catch (error) {
951
+ failure = error;
952
+ } finally {
953
+ queue.close();
954
+ }
955
+ },
956
+ runtimeOptions
957
+ ).catch((error) => {
958
+ failure = error;
959
+ queue.close();
960
+ });
961
+ for await (const event of queue) {
962
+ yield event;
963
+ }
964
+ if (failure) {
965
+ throw failure;
966
+ }
967
+ }
968
+ };
969
+ }
970
+
879
971
  // src/runtime/s2s.ts
880
972
  async function initA365S2SObservability(options) {
881
973
  const env = resolveA365ObservabilityEnvironment(options.s2s?.env);
@@ -1041,6 +1133,7 @@ export {
1041
1133
  createA365ContextFromTurnContext,
1042
1134
  createA365ContextWithParentSpanRef,
1043
1135
  createA365OboTokenResolver,
1136
+ createA365ObservedTurnSource,
1044
1137
  createA365S2STokenResolver,
1045
1138
  createA365S2STokenResolverFromEnv,
1046
1139
  createA365TracingConfig,
package/docs/README.md CHANGED
@@ -29,5 +29,6 @@ The short version:
29
29
  - `agent-channel-m365` owns Activity ingress and turn wrapping for M365 hosts.
30
30
  - Microsoft's Agent 365 observability SDK owns exporter registration and
31
31
  baggage-to-span enrichment.
32
- - this package starts Microsoft observability and wraps each agent turn with
33
- the Agent 365 baggage that Microsoft expects.
32
+ - this package starts Microsoft observability and wraps callbacks,
33
+ TurnContexts, or generic `AgentTurnSource` streams with the Agent 365 baggage
34
+ that Microsoft expects.
@@ -35,8 +35,9 @@ Per agent:
35
35
 
36
36
  Per turn:
37
37
 
38
- 1. the host or M365 channel calls `runWithA365Context(...)` or
39
- `runWithA365TurnContext(...)`;
38
+ 1. the host or M365 channel calls `runWithA365Context(...)`,
39
+ `runWithA365TurnContext(...)`, or wraps an `AgentTurnSource` with
40
+ `createA365ObservedTurnSource(...)`;
40
41
  2. this package builds Agent 365 baggage from tenant, agent, conversation,
41
42
  channel, and caller identity;
42
43
  3. agent-core runs the turn inside that baggage scope;
@@ -67,3 +68,15 @@ Agent 365 observability has Microsoft-specific concepts:
67
68
 
68
69
  Putting those in agent-core would make core platform-specific. This adapter
69
70
  keeps the runtime portable while still supporting Agent 365 deployment.
71
+
72
+ ## Channel Bridges
73
+
74
+ Channel-specific packages should not depend on this package just to describe
75
+ their native metadata. For example, a Slack adapter can parse Slack user,
76
+ channel, and thread fields without knowing Agent 365 semantic keys.
77
+
78
+ The bridge that combines a channel with Agent 365 should map those fields into
79
+ `A365RequestContext`, then pass that mapping to `createA365ObservedTurnSource`.
80
+ That keeps the async stream and baggage lifecycle reusable while preserving the
81
+ right ownership boundary: channels own channel facts, and the Agent 365 adapter
82
+ owns Microsoft baggage/export behavior.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cuylabs/agent-a365-observability",
3
- "version": "4.6.0",
3
+ "version": "4.7.0",
4
4
  "description": "Microsoft Agent 365 observability adapter for @cuylabs/agent-core",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -26,7 +26,7 @@
26
26
  "typescript": "^5.7.0",
27
27
  "vitest": "^4.0.18",
28
28
  "zod": "^3.25.76 || ^4.1.8",
29
- "@cuylabs/agent-core": "^4.6.0"
29
+ "@cuylabs/agent-core": "^4.7.0"
30
30
  },
31
31
  "peerDependencies": {
32
32
  "@cuylabs/agent-core": "^4.0.0",