@traceai/cohere 0.1.0 → 0.1.1

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.
Files changed (76) hide show
  1. package/README.md +78 -369
  2. package/dist/esm/attributes.d.ts +11 -0
  3. package/dist/esm/attributes.d.ts.map +1 -0
  4. package/dist/esm/attributes.js +240 -0
  5. package/dist/esm/attributes.js.map +1 -0
  6. package/dist/esm/instrumentation.d.ts +11 -20
  7. package/dist/esm/instrumentation.d.ts.map +1 -1
  8. package/dist/esm/instrumentation.js +175 -344
  9. package/dist/esm/instrumentation.js.map +1 -1
  10. package/dist/esm/stream.d.ts +6 -0
  11. package/dist/esm/stream.d.ts.map +1 -0
  12. package/dist/esm/stream.js +215 -0
  13. package/dist/esm/stream.js.map +1 -0
  14. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
  15. package/dist/esm/version.d.ts +1 -1
  16. package/dist/esm/version.js +1 -1
  17. package/dist/esm/version.js.map +1 -1
  18. package/dist/esnext/attributes.d.ts +11 -0
  19. package/dist/esnext/attributes.d.ts.map +1 -0
  20. package/dist/esnext/attributes.js +248 -0
  21. package/dist/esnext/attributes.js.map +1 -0
  22. package/dist/esnext/instrumentation.d.ts +11 -20
  23. package/dist/esnext/instrumentation.d.ts.map +1 -1
  24. package/dist/esnext/instrumentation.js +178 -331
  25. package/dist/esnext/instrumentation.js.map +1 -1
  26. package/dist/esnext/stream.d.ts +6 -0
  27. package/dist/esnext/stream.d.ts.map +1 -0
  28. package/dist/esnext/stream.js +203 -0
  29. package/dist/esnext/stream.js.map +1 -0
  30. package/dist/esnext/tsconfig.esnext.tsbuildinfo +1 -1
  31. package/dist/esnext/version.d.ts +1 -1
  32. package/dist/esnext/version.js +1 -1
  33. package/dist/esnext/version.js.map +1 -1
  34. package/dist/src/__tests__/attributes.test.d.ts +2 -0
  35. package/dist/src/__tests__/attributes.test.d.ts.map +1 -0
  36. package/dist/src/__tests__/attributes.test.js +50 -0
  37. package/dist/src/__tests__/attributes.test.js.map +1 -0
  38. package/dist/src/__tests__/auto.test.d.ts +2 -0
  39. package/dist/src/__tests__/auto.test.d.ts.map +1 -0
  40. package/dist/src/__tests__/auto.test.js +70 -0
  41. package/dist/src/__tests__/auto.test.js.map +1 -0
  42. package/dist/src/__tests__/instrumentation.test.js +1 -1
  43. package/dist/src/__tests__/instrumentation.test.js.map +1 -1
  44. package/dist/src/__tests__/lifecycle.test.d.ts +2 -0
  45. package/dist/src/__tests__/lifecycle.test.d.ts.map +1 -0
  46. package/dist/src/__tests__/lifecycle.test.js +232 -0
  47. package/dist/src/__tests__/lifecycle.test.js.map +1 -0
  48. package/dist/src/__tests__/metadata.test.d.ts +2 -0
  49. package/dist/src/__tests__/metadata.test.d.ts.map +1 -0
  50. package/dist/src/__tests__/metadata.test.js +320 -0
  51. package/dist/src/__tests__/metadata.test.js.map +1 -0
  52. package/dist/src/__tests__/sdk.test.d.ts +2 -0
  53. package/dist/src/__tests__/sdk.test.d.ts.map +1 -0
  54. package/dist/src/__tests__/sdk.test.js +883 -0
  55. package/dist/src/__tests__/sdk.test.js.map +1 -0
  56. package/dist/src/__tests__/timing.test.d.ts +2 -0
  57. package/dist/src/__tests__/timing.test.d.ts.map +1 -0
  58. package/dist/src/__tests__/timing.test.js +158 -0
  59. package/dist/src/__tests__/timing.test.js.map +1 -0
  60. package/dist/src/attributes.d.ts +11 -0
  61. package/dist/src/attributes.d.ts.map +1 -0
  62. package/dist/src/attributes.js +257 -0
  63. package/dist/src/attributes.js.map +1 -0
  64. package/dist/src/instrumentation.d.ts +11 -20
  65. package/dist/src/instrumentation.d.ts.map +1 -1
  66. package/dist/src/instrumentation.js +176 -329
  67. package/dist/src/instrumentation.js.map +1 -1
  68. package/dist/src/stream.d.ts +6 -0
  69. package/dist/src/stream.d.ts.map +1 -0
  70. package/dist/src/stream.js +215 -0
  71. package/dist/src/stream.js.map +1 -0
  72. package/dist/src/version.d.ts +1 -1
  73. package/dist/src/version.js +1 -1
  74. package/dist/src/version.js.map +1 -1
  75. package/dist/tsconfig.tsbuildinfo +1 -1
  76. package/package.json +18 -11
@@ -1,34 +1,25 @@
1
1
  import { InstrumentationBase, InstrumentationConfig, InstrumentationNodeModuleDefinition } from "@opentelemetry/instrumentation";
2
2
  import { TraceConfigOptions } from "@traceai/fi-core";
3
- /**
4
- * Function to check if instrumentation is enabled / disabled
5
- */
3
+ import { Data } from "./attributes";
4
+ /** True when at least one SDK method is instrumented, across module copies. */
6
5
  export declare function isPatched(): boolean;
7
- /**
8
- * @param instrumentationConfig The config for the instrumentation
9
- * @param traceConfig The FI trace configuration for masking sensitive information
10
- */
6
+ /** Cohere v1/v2 instrumentation. Install before constructing SDK clients. */
11
7
  export declare class CohereInstrumentation extends InstrumentationBase {
12
- private fiTracer;
13
8
  private _traceConfig?;
9
+ private patches?;
10
+ private manualModules?;
14
11
  readonly instrumentationName = "@traceai/cohere";
15
- constructor({ instrumentationConfig, traceConfig, }?: {
12
+ constructor({ instrumentationConfig, traceConfig }?: {
16
13
  instrumentationConfig?: InstrumentationConfig;
17
14
  traceConfig?: TraceConfigOptions;
18
15
  });
19
- enable(): void;
20
16
  protected init(): InstrumentationNodeModuleDefinition;
21
- /**
22
- * Manually instruments the Cohere module
23
- */
24
- manuallyInstrument(module: Record<string, unknown>): void;
25
- /**
26
- * Patches the Cohere module
27
- */
17
+ enable(): void;
18
+ disable(): void;
19
+ manuallyInstrument(module: Data): void;
28
20
  private patch;
29
- /**
30
- * Un-patches the Cohere module
31
- */
32
21
  private unpatch;
22
+ private restorePatches;
23
+ private wrapMethod;
33
24
  }
34
25
  //# sourceMappingURL=instrumentation.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"instrumentation.d.ts","sourceRoot":"","sources":["../../src/instrumentation.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,qBAAqB,EACrB,mCAAmC,EAEpC,MAAM,gCAAgC,CAAC;AAmBxC,OAAO,EAGL,kBAAkB,EACnB,MAAM,kBAAkB,CAAC;AAU1B;;GAEG;AACH,wBAAgB,SAAS,YAExB;AAyGD;;;GAGG;AACH,qBAAa,qBAAsB,SAAQ,mBAAmB;IAC5D,OAAO,CAAC,QAAQ,CAAY;IAC5B,OAAO,CAAC,YAAY,CAAC,CAAqB;IAC1C,SAAgB,mBAAmB,qBAAqB;gBAE5C,EACV,qBAAqB,EACrB,WAAW,GACZ,GAAE;QACD,qBAAqB,CAAC,EAAE,qBAAqB,CAAC;QAC9C,WAAW,CAAC,EAAE,kBAAkB,CAAC;KAC7B;IASU,MAAM,IAAI,IAAI;IAK9B,SAAS,CAAC,IAAI;IAUd;;OAEG;IACH,kBAAkB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAIlD;;OAEG;IACH,OAAO,CAAC,KAAK;IAoPb;;OAEG;IACH,OAAO,CAAC,OAAO;CA2BhB"}
1
+ {"version":3,"file":"instrumentation.d.ts","sourceRoot":"","sources":["../../src/instrumentation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,mCAAmC,EAAE,MAAM,gCAAgC,CAAC;AAIjI,OAAO,EAAiC,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAErF,OAAO,EAAE,IAAI,EAAoE,MAAM,cAAc,CAAC;AAUtG,+EAA+E;AAC/E,wBAAgB,SAAS,IAAI,OAAO,CAA2B;AAE/D,6EAA6E;AAC7E,qBAAa,qBAAsB,SAAQ,mBAAmB;IAC5D,OAAO,CAAC,YAAY,CAAC,CAAqB;IAE1C,OAAO,CAAC,OAAO,CAAC,CAAU;IAC1B,OAAO,CAAC,aAAa,CAAC,CAAY;IAClC,SAAgB,mBAAmB,qBAAqB;gBAE5C,EAAE,qBAAqB,EAAE,WAAW,EAAE,GAAE;QAClD,qBAAqB,CAAC,EAAE,qBAAqB,CAAC;QAC9C,WAAW,CAAC,EAAE,kBAAkB,CAAC;KAC7B;IAKN,SAAS,CAAC,IAAI;IAIE,MAAM,IAAI,IAAI;IAKd,OAAO,IAAI,IAAI;IAK/B,kBAAkB,CAAC,MAAM,EAAE,IAAI,GAAG,IAAI;IAKtC,OAAO,CAAC,KAAK;IA+Bb,OAAO,CAAC,OAAO;IAEf,OAAO,CAAC,cAAc;IAYtB,OAAO,CAAC,UAAU;CA8EnB"}
@@ -1,364 +1,211 @@
1
1
  "use strict";
2
- var __rest = (this && this.__rest) || function (s, e) {
3
- var t = {};
4
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
5
- t[p] = s[p];
6
- if (s != null && typeof Object.getOwnPropertySymbols === "function")
7
- for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
8
- if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
9
- t[p[i]] = s[p[i]];
10
- }
11
- return t;
12
- };
13
2
  Object.defineProperty(exports, "__esModule", { value: true });
14
3
  exports.CohereInstrumentation = void 0;
15
4
  exports.isPatched = isPatched;
16
5
  const instrumentation_1 = require("@opentelemetry/instrumentation");
17
6
  const api_1 = require("@opentelemetry/api");
18
- const version_1 = require("./version");
19
- const fi_semantic_conventions_1 = require("@traceai/fi-semantic-conventions");
20
7
  const core_1 = require("@opentelemetry/core");
8
+ const node_perf_hooks_1 = require("node:perf_hooks");
21
9
  const fi_core_1 = require("@traceai/fi-core");
22
- const MODULE_NAME = "cohere-ai";
23
- /**
24
- * Flag to check if the Cohere module has been patched
25
- */
26
- let _isFIPatched = false;
27
- /**
28
- * Function to check if instrumentation is enabled / disabled
29
- */
30
- function isPatched() {
31
- return _isFIPatched;
32
- }
33
- /**
34
- * Resolves the execution context for the current span
35
- */
36
- function getExecContext(span) {
37
- const activeContext = api_1.context.active();
38
- const suppressTracing = (0, core_1.isTracingSuppressed)(activeContext);
39
- const execContext = suppressTracing
40
- ? api_1.trace.setSpan(api_1.context.active(), span)
41
- : activeContext;
42
- if (suppressTracing) {
43
- api_1.trace.deleteSpan(activeContext);
44
- }
45
- return execContext;
46
- }
47
- /**
48
- * @param instrumentationConfig The config for the instrumentation
49
- * @param traceConfig The FI trace configuration for masking sensitive information
50
- */
10
+ const version_1 = require("./version");
11
+ const attributes_1 = require("./attributes");
12
+ const stream_1 = require("./stream");
13
+ const OPERATIONS = ["chat", "chatStream", "embed", "rerank"];
14
+ const IN_COHERE_CALL = (0, api_1.createContextKey)("traceai.cohere.call");
15
+ const owners = new WeakMap();
16
+ let patchCount = 0;
17
+ /** True when at least one SDK method is instrumented, across module copies. */
18
+ function isPatched() { return patchCount > 0; }
19
+ /** Cohere v1/v2 instrumentation. Install before constructing SDK clients. */
51
20
  class CohereInstrumentation extends instrumentation_1.InstrumentationBase {
52
- constructor({ instrumentationConfig, traceConfig, } = {}) {
21
+ constructor({ instrumentationConfig, traceConfig } = {}) {
53
22
  super("@traceai/cohere", version_1.VERSION, Object.assign({}, instrumentationConfig));
54
23
  this.instrumentationName = "@traceai/cohere";
55
24
  this._traceConfig = traceConfig;
56
25
  }
26
+ init() {
27
+ return new instrumentation_1.InstrumentationNodeModuleDefinition("cohere-ai", [">=7.0.0 <9"], this.patch.bind(this), this.unpatch.bind(this));
28
+ }
57
29
  enable() {
30
+ var _a;
58
31
  super.enable();
59
- this.fiTracer = new fi_core_1.FITracer({ tracer: this.tracer, traceConfig: this._traceConfig });
32
+ for (const module of (_a = this.manualModules) !== null && _a !== void 0 ? _a : [])
33
+ this.patch(module);
60
34
  }
61
- init() {
62
- const module = new instrumentation_1.InstrumentationNodeModuleDefinition("cohere-ai", [">=7.0.0"], this.patch.bind(this), this.unpatch.bind(this));
63
- return module;
35
+ disable() {
36
+ super.disable();
37
+ this.restorePatches();
64
38
  }
65
- /**
66
- * Manually instruments the Cohere module
67
- */
68
39
  manuallyInstrument(module) {
69
- this.patch(module);
40
+ var _a;
41
+ ((_a = this.manualModules) !== null && _a !== void 0 ? _a : (this.manualModules = new Set())).add(module);
42
+ if (this.isEnabled())
43
+ this.patch(module);
70
44
  }
71
- /**
72
- * Patches the Cohere module
73
- */
74
- patch(module, moduleVersion) {
45
+ patch(module) {
75
46
  var _a, _b;
76
- if ((module === null || module === void 0 ? void 0 : module.fiPatched) || _isFIPatched) {
77
- return module;
78
- }
79
- const instrumentation = this;
80
- // Ensure fiTracer uses the most up-to-date tracer
81
- if (!((_a = instrumentation.fiTracer) === null || _a === void 0 ? void 0 : _a.tracer) ||
82
- ((_b = instrumentation.fiTracer) === null || _b === void 0 ? void 0 : _b.tracer) !== instrumentation.tracer) {
83
- instrumentation.fiTracer = new fi_core_1.FITracer({
84
- tracer: instrumentation.tracer,
85
- traceConfig: instrumentation._traceConfig
86
- });
87
- }
88
- // Patch CohereClient class
89
- const CohereClient = module.CohereClient;
90
- if (CohereClient === null || CohereClient === void 0 ? void 0 : CohereClient.prototype) {
91
- // Patch chat method
92
- if (typeof CohereClient.prototype.chat === 'function') {
93
- this._wrap(CohereClient.prototype, "chat",
94
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
95
- (original) => {
96
- return function patchedChat(...args) {
97
- var _a;
98
- const request = args[0];
99
- const modelName = request.model || 'command';
100
- const { message, chat_history, preamble } = request, invocationParameters = __rest(request, ["message", "chat_history", "preamble"]);
101
- const span = instrumentation.fiTracer.startSpan(`Cohere Chat`, {
102
- kind: api_1.SpanKind.INTERNAL,
103
- attributes: Object.assign(Object.assign(Object.assign({ [fi_semantic_conventions_1.SemanticConventions.FI_SPAN_KIND]: fi_semantic_conventions_1.FISpanKind.LLM, [fi_semantic_conventions_1.SemanticConventions.LLM_MODEL_NAME]: modelName, [fi_semantic_conventions_1.SemanticConventions.INPUT_VALUE]: request.message, [fi_semantic_conventions_1.SemanticConventions.INPUT_MIME_TYPE]: fi_semantic_conventions_1.MimeType.TEXT, [fi_semantic_conventions_1.SemanticConventions.LLM_INVOCATION_PARAMETERS]: JSON.stringify(invocationParameters), [fi_semantic_conventions_1.SemanticConventions.LLM_PROVIDER]: fi_semantic_conventions_1.LLMProvider.COHERE, [fi_semantic_conventions_1.SemanticConventions.GEN_AI_OPERATION_NAME]: "chat" }, getChatInputMessagesAttributes(request)), getChatToolsAttributes(request)), { [fi_semantic_conventions_1.SemanticConventions.RAW_INPUT]: (_a = (0, fi_core_1.safelyJSONStringify)(request)) !== null && _a !== void 0 ? _a : "" }),
104
- });
105
- const execContext = getExecContext(span);
106
- const execPromise = (0, instrumentation_1.safeExecuteInTheMiddle)(() => {
107
- return api_1.context.with(api_1.trace.setSpan(execContext, span), () => {
108
- return original.apply(this, args);
109
- });
110
- }, (error) => {
111
- if (error) {
112
- span.recordException(error);
113
- span.setStatus({ code: api_1.SpanStatusCode.ERROR, message: error.message });
114
- span.end();
115
- }
116
- });
117
- const wrappedPromise = execPromise.then((result) => {
118
- var _a;
119
- span.setAttributes(Object.assign(Object.assign(Object.assign({ [fi_semantic_conventions_1.SemanticConventions.OUTPUT_VALUE]: result.text, [fi_semantic_conventions_1.SemanticConventions.OUTPUT_MIME_TYPE]: fi_semantic_conventions_1.MimeType.TEXT }, getChatOutputMessagesAttributes(result)), getChatUsageAttributes(result)), { [fi_semantic_conventions_1.SemanticConventions.RAW_OUTPUT]: (_a = (0, fi_core_1.safelyJSONStringify)(result)) !== null && _a !== void 0 ? _a : "" }));
120
- span.setStatus({ code: api_1.SpanStatusCode.OK });
121
- span.end();
122
- return result;
123
- }).catch((error) => {
124
- span.recordException(error);
125
- span.setStatus({ code: api_1.SpanStatusCode.ERROR, message: error.message });
126
- span.end();
127
- throw error;
128
- });
129
- return api_1.context.bind(execContext, wrappedPromise);
130
- };
131
- });
132
- }
133
- // Patch embed method
134
- if (typeof CohereClient.prototype.embed === 'function') {
135
- this._wrap(CohereClient.prototype, "embed",
136
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
137
- (original) => {
138
- return function patchedEmbed(...args) {
139
- var _a;
140
- const request = args[0];
141
- const modelName = request.model || 'embed-english-v3.0';
142
- const span = instrumentation.fiTracer.startSpan(`Cohere Embed`, {
143
- kind: api_1.SpanKind.INTERNAL,
144
- attributes: Object.assign(Object.assign({ [fi_semantic_conventions_1.SemanticConventions.FI_SPAN_KIND]: fi_semantic_conventions_1.FISpanKind.EMBEDDING, [fi_semantic_conventions_1.SemanticConventions.EMBEDDING_MODEL_NAME]: modelName, [fi_semantic_conventions_1.SemanticConventions.INPUT_VALUE]: JSON.stringify(request.texts), [fi_semantic_conventions_1.SemanticConventions.INPUT_MIME_TYPE]: fi_semantic_conventions_1.MimeType.JSON, [fi_semantic_conventions_1.SemanticConventions.LLM_PROVIDER]: fi_semantic_conventions_1.LLMProvider.COHERE, [fi_semantic_conventions_1.SemanticConventions.GEN_AI_OPERATION_NAME]: "embeddings" }, getEmbedTextAttributes(request)), { [fi_semantic_conventions_1.SemanticConventions.RAW_INPUT]: (_a = (0, fi_core_1.safelyJSONStringify)(request)) !== null && _a !== void 0 ? _a : "" }),
145
- });
146
- const execContext = getExecContext(span);
147
- const execPromise = (0, instrumentation_1.safeExecuteInTheMiddle)(() => {
148
- return api_1.context.with(api_1.trace.setSpan(execContext, span), () => {
149
- return original.apply(this, args);
150
- });
151
- }, (error) => {
152
- if (error) {
153
- span.recordException(error);
154
- span.setStatus({ code: api_1.SpanStatusCode.ERROR, message: error.message });
155
- span.end();
156
- }
157
- });
158
- const wrappedPromise = execPromise.then((result) => {
159
- var _a;
160
- span.setAttributes(Object.assign(Object.assign({}, getEmbedVectorAttributes(result)), { [fi_semantic_conventions_1.SemanticConventions.RAW_OUTPUT]: (_a = (0, fi_core_1.safelyJSONStringify)(result)) !== null && _a !== void 0 ? _a : "" }));
161
- span.setStatus({ code: api_1.SpanStatusCode.OK });
162
- span.end();
163
- return result;
164
- }).catch((error) => {
165
- span.recordException(error);
166
- span.setStatus({ code: api_1.SpanStatusCode.ERROR, message: error.message });
167
- span.end();
168
- throw error;
169
- });
170
- return api_1.context.bind(execContext, wrappedPromise);
171
- };
172
- });
47
+ const Client = module.CohereClient;
48
+ const targets = [Client === null || Client === void 0 ? void 0 : Client.prototype];
49
+ // V2Client is not exported at the module root. The public client.v2 getter
50
+ // exposes the same generated class used by CohereClientV2's bound methods.
51
+ // Construction performs no I/O; an explicit inert token avoids env lookup.
52
+ if (typeof Client === "function" && Client.prototype && "v2" in Client.prototype) {
53
+ try {
54
+ const v2 = new Client({ token: "traceai-instrumentation-placeholder" }).v2;
55
+ if (v2)
56
+ targets.push(Object.getPrototypeOf(v2));
173
57
  }
174
- // Patch rerank method
175
- if (typeof CohereClient.prototype.rerank === 'function') {
176
- this._wrap(CohereClient.prototype, "rerank",
177
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
178
- (original) => {
179
- return function patchedRerank(...args) {
180
- var _a;
181
- const request = args[0];
182
- const modelName = request.model || 'rerank-english-v3.0';
183
- const span = instrumentation.fiTracer.startSpan(`Cohere Rerank`, {
184
- kind: api_1.SpanKind.INTERNAL,
185
- attributes: {
186
- [fi_semantic_conventions_1.SemanticConventions.FI_SPAN_KIND]: fi_semantic_conventions_1.FISpanKind.LLM,
187
- [fi_semantic_conventions_1.SemanticConventions.LLM_MODEL_NAME]: modelName,
188
- [fi_semantic_conventions_1.SemanticConventions.INPUT_VALUE]: request.query,
189
- [fi_semantic_conventions_1.SemanticConventions.INPUT_MIME_TYPE]: fi_semantic_conventions_1.MimeType.TEXT,
190
- [fi_semantic_conventions_1.SemanticConventions.LLM_PROVIDER]: fi_semantic_conventions_1.LLMProvider.COHERE,
191
- [fi_semantic_conventions_1.SemanticConventions.GEN_AI_OPERATION_NAME]: "rerank",
192
- "cohere.rerank.query": request.query,
193
- "cohere.rerank.documents_count": request.documents.length,
194
- "cohere.rerank.top_n": request.top_n,
195
- [fi_semantic_conventions_1.SemanticConventions.RAW_INPUT]: (_a = (0, fi_core_1.safelyJSONStringify)(request)) !== null && _a !== void 0 ? _a : "",
196
- },
197
- });
198
- const execContext = getExecContext(span);
199
- const execPromise = (0, instrumentation_1.safeExecuteInTheMiddle)(() => {
200
- return api_1.context.with(api_1.trace.setSpan(execContext, span), () => {
201
- return original.apply(this, args);
202
- });
203
- }, (error) => {
204
- if (error) {
205
- span.recordException(error);
206
- span.setStatus({ code: api_1.SpanStatusCode.ERROR, message: error.message });
207
- span.end();
208
- }
209
- });
210
- const wrappedPromise = execPromise.then((result) => {
211
- var _a;
212
- span.setAttributes(Object.assign(Object.assign({ "cohere.rerank.results_count": result.results.length }, getRerankResultsAttributes(result)), { [fi_semantic_conventions_1.SemanticConventions.RAW_OUTPUT]: (_a = (0, fi_core_1.safelyJSONStringify)(result)) !== null && _a !== void 0 ? _a : "" }));
213
- span.setStatus({ code: api_1.SpanStatusCode.OK });
214
- span.end();
215
- return result;
216
- }).catch((error) => {
217
- span.recordException(error);
218
- span.setStatus({ code: api_1.SpanStatusCode.ERROR, message: error.message });
219
- span.end();
220
- throw error;
221
- });
222
- return api_1.context.bind(execContext, wrappedPromise);
223
- };
224
- });
58
+ catch (_c) {
59
+ // Telemetry must not prevent module loading; v1 remains usable.
60
+ api_1.diag.warn("Cohere instrumentation could not discover the v2 client");
225
61
  }
226
62
  }
227
- _isFIPatched = true;
228
- try {
229
- module.fiPatched = true;
230
- }
231
- catch (e) {
232
- api_1.diag.warn(`Failed to set fiPatched flag on module '${MODULE_NAME}'. Error: ${e}`);
63
+ for (const target of targets) {
64
+ if (!target)
65
+ continue;
66
+ for (const method of OPERATIONS) {
67
+ if (typeof target[method] !== "function" || ((_a = owners.get(target)) === null || _a === void 0 ? void 0 : _a.has(method)))
68
+ continue;
69
+ const hadOwn = Object.prototype.hasOwnProperty.call(target, method);
70
+ this._wrap(target, method, (original) => this.wrapMethod(method, original));
71
+ const wrapped = target[method];
72
+ ((_b = this.patches) !== null && _b !== void 0 ? _b : (this.patches = [])).push({ target, method, wrapped, hadOwn });
73
+ if (!owners.has(target))
74
+ owners.set(target, new Map());
75
+ owners.get(target).set(method, this);
76
+ patchCount++;
77
+ }
233
78
  }
234
79
  return module;
235
80
  }
236
- /**
237
- * Un-patches the Cohere module
238
- */
239
- unpatch(moduleExports, moduleVersion) {
240
- const CohereClient = moduleExports.CohereClient;
241
- if (CohereClient === null || CohereClient === void 0 ? void 0 : CohereClient.prototype) {
242
- if (CohereClient.prototype.chat) {
243
- this._unwrap(CohereClient.prototype, "chat");
244
- }
245
- if (CohereClient.prototype.embed) {
246
- this._unwrap(CohereClient.prototype, "embed");
247
- }
248
- if (CohereClient.prototype.rerank) {
249
- this._unwrap(CohereClient.prototype, "rerank");
81
+ unpatch() { this.restorePatches(); }
82
+ restorePatches() {
83
+ var _a, _b;
84
+ for (const { target, method, wrapped, hadOwn } of (_a = this.patches) !== null && _a !== void 0 ? _a : []) {
85
+ if (target[method] === wrapped) {
86
+ this._unwrap(target, method);
87
+ if (!hadOwn)
88
+ delete target[method];
250
89
  }
90
+ (_b = owners.get(target)) === null || _b === void 0 ? void 0 : _b.delete(method);
91
+ patchCount--;
251
92
  }
252
- _isFIPatched = false;
253
- try {
254
- moduleExports.fiPatched = false;
255
- }
256
- catch (e) {
257
- api_1.diag.warn(`Failed to unset fiPatched flag on module '${MODULE_NAME}'. Error: ${e}`);
258
- }
93
+ this.patches = [];
259
94
  }
260
- }
261
- exports.CohereInstrumentation = CohereInstrumentation;
262
- /**
263
- * Converts the chat request to LLM input messages
264
- */
265
- function getChatInputMessagesAttributes(request) {
266
- var _a;
267
- const messages = [];
268
- if (request.preamble) {
269
- messages.push({ role: 'system', content: request.preamble });
270
- }
271
- if (request.chat_history) {
272
- request.chat_history.forEach((msg) => {
273
- messages.push({ role: msg.role, content: msg.message });
274
- });
275
- }
276
- messages.push({ role: 'user', content: request.message });
277
- return { [fi_semantic_conventions_1.SemanticConventions.LLM_INPUT_MESSAGES]: (_a = (0, fi_core_1.safelyJSONStringify)(messages)) !== null && _a !== void 0 ? _a : "[]" };
278
- }
279
- /**
280
- * Gets chat tools attributes
281
- */
282
- function getChatToolsAttributes(request) {
283
- var _a;
284
- if (!request.tools) {
285
- return {};
286
- }
287
- return { [fi_semantic_conventions_1.SemanticConventions.LLM_TOOLS]: (_a = (0, fi_core_1.safelyJSONStringify)(request.tools)) !== null && _a !== void 0 ? _a : "[]" };
288
- }
289
- /**
290
- * Gets chat output messages attributes
291
- */
292
- function getChatOutputMessagesAttributes(response) {
293
- var _a;
294
- const msg = { role: 'assistant', content: response.text };
295
- if (response.tool_calls) {
296
- msg.tool_calls = response.tool_calls.map((tc) => ({
297
- function: { name: tc.name, arguments: JSON.stringify(tc.parameters) },
298
- }));
299
- }
300
- return { [fi_semantic_conventions_1.SemanticConventions.LLM_OUTPUT_MESSAGES]: (_a = (0, fi_core_1.safelyJSONStringify)([msg])) !== null && _a !== void 0 ? _a : "[]" };
301
- }
302
- /**
303
- * Gets chat usage attributes
304
- */
305
- function getChatUsageAttributes(response) {
306
- const meta = response.meta;
307
- if (!meta) {
308
- return {};
309
- }
310
- const billedUnits = meta.billed_units;
311
- const tokens = meta.tokens;
312
- if (billedUnits) {
313
- return {
314
- [fi_semantic_conventions_1.SemanticConventions.LLM_TOKEN_COUNT_PROMPT]: billedUnits.input_tokens,
315
- [fi_semantic_conventions_1.SemanticConventions.LLM_TOKEN_COUNT_COMPLETION]: billedUnits.output_tokens,
316
- [fi_semantic_conventions_1.SemanticConventions.LLM_TOKEN_COUNT_TOTAL]: (billedUnits.input_tokens || 0) + (billedUnits.output_tokens || 0),
317
- };
318
- }
319
- if (tokens) {
320
- return {
321
- [fi_semantic_conventions_1.SemanticConventions.LLM_TOKEN_COUNT_PROMPT]: tokens.input_tokens,
322
- [fi_semantic_conventions_1.SemanticConventions.LLM_TOKEN_COUNT_COMPLETION]: tokens.output_tokens,
323
- [fi_semantic_conventions_1.SemanticConventions.LLM_TOKEN_COUNT_TOTAL]: (tokens.input_tokens || 0) + (tokens.output_tokens || 0),
95
+ wrapMethod(operation, original) {
96
+ const instrumentation = this;
97
+ return function (...args) {
98
+ const parent = api_1.context.active();
99
+ // Bound v2 methods can outlive unpatch. Respect disable even for those.
100
+ if (!instrumentation.isEnabled() || (0, core_1.isTracingSuppressed)(parent) || parent.getValue(IN_COHERE_CALL)) {
101
+ return original.apply(this, args);
102
+ }
103
+ const config = (0, fi_core_1.generateTraceConfig)(instrumentation._traceConfig);
104
+ let span;
105
+ try {
106
+ const tracer = new fi_core_1.FITracer({ tracer: instrumentation.tracer, traceConfig: config });
107
+ const name = operation === "chatStream" ? "Chat Stream" : operation[0].toUpperCase() + operation.slice(1);
108
+ span = tracer.startSpan(`Cohere ${name}`, { kind: api_1.SpanKind.INTERNAL, attributes: (0, attributes_1.inputAttributes)(operation, (0, attributes_1.object)(args[0]), config) }, parent);
109
+ }
110
+ catch (_a) {
111
+ api_1.diag.warn("Cohere instrumentation could not start span");
112
+ return original.apply(this, args);
113
+ }
114
+ const execContext = api_1.trace.setSpan(parent, span).setValue(IN_COHERE_CALL, true);
115
+ let ended = false;
116
+ const finish = (response, error, cancelled = false, timeToFirstTokenMs) => {
117
+ var _a;
118
+ if (ended)
119
+ return;
120
+ ended = true;
121
+ try {
122
+ // Resolved HTTP-200 chat responses can still signal failure or user
123
+ // cancellation. Use the same classification for both chat paths,
124
+ // independent of content capture and without rejecting SDK results.
125
+ if ((operation === "chat" || operation === "chatStream") && error === undefined && !cancelled) {
126
+ const reason = (_a = response.finishReason) !== null && _a !== void 0 ? _a : response.finish_reason;
127
+ switch (reason) {
128
+ case "ERROR":
129
+ case "ERROR_TOXIC":
130
+ case "ERROR_LIMIT":
131
+ case "TIMEOUT":
132
+ error = new Error(`Cohere generation failed (${reason})`);
133
+ break;
134
+ case "USER_CANCEL":
135
+ cancelled = true;
136
+ break;
137
+ }
138
+ }
139
+ span.setAttributes((0, attributes_1.outputAttributes)(operation, response, config));
140
+ if (timeToFirstTokenMs !== undefined)
141
+ span.setAttribute("cohere.stream.time_to_first_token_ms", timeToFirstTokenMs);
142
+ if (error !== undefined) {
143
+ span.recordException(error instanceof Error ? error : new Error(String(error)));
144
+ span.setStatus({ code: api_1.SpanStatusCode.ERROR, message: error instanceof Error ? error.message : String(error) });
145
+ }
146
+ else if (cancelled) {
147
+ span.setAttribute(operation === "chatStream" ? "cohere.stream.cancelled" : "cohere.request.cancelled", true);
148
+ }
149
+ else {
150
+ span.setStatus({ code: api_1.SpanStatusCode.OK });
151
+ }
152
+ }
153
+ catch (_b) {
154
+ api_1.diag.warn("Cohere instrumentation could not record response");
155
+ }
156
+ finally {
157
+ span.end();
158
+ }
159
+ };
160
+ const streams = new WeakMap();
161
+ const resolved = (result) => {
162
+ if (operation === "chatStream" && result && typeof result[Symbol.asyncIterator] === "function") {
163
+ if (!streams.has(result))
164
+ streams.set(result, (0, stream_1.wrapStream)(result, execContext, !(0, attributes_1.hideOutput)(config), finish, requestStart));
165
+ return streams.get(result);
166
+ }
167
+ finish((0, attributes_1.object)(result));
168
+ return result;
169
+ };
170
+ const rejected = (error) => {
171
+ finish({}, error !== null && error !== void 0 ? error : new Error("Cohere request failed"));
172
+ throw error;
173
+ };
174
+ let pending;
175
+ const requestStart = node_perf_hooks_1.performance.now();
176
+ try {
177
+ pending = api_1.context.with(execContext, () => original.apply(this, args));
178
+ }
179
+ catch (error) {
180
+ return rejected(error);
181
+ }
182
+ return observePromise(pending, resolved, rejected);
324
183
  };
325
184
  }
326
- return {};
327
- }
328
- /**
329
- * Gets embed text attributes
330
- */
331
- function getEmbedTextAttributes(request) {
332
- return request.texts.reduce((acc, text, index) => {
333
- acc[`${fi_semantic_conventions_1.SemanticConventions.EMBEDDING_EMBEDDINGS}.${index}.${fi_semantic_conventions_1.SemanticConventions.EMBEDDING_TEXT}`] = text;
334
- return acc;
335
- }, {});
336
- }
337
- /**
338
- * Gets embed vector attributes
339
- */
340
- function getEmbedVectorAttributes(response) {
341
- var _a;
342
- const embeddings = Array.isArray(response.embeddings)
343
- ? response.embeddings
344
- : ((_a = response.embeddings) === null || _a === void 0 ? void 0 : _a.float) || [];
345
- return embeddings.reduce((acc, embedding, index) => {
346
- acc[`${fi_semantic_conventions_1.SemanticConventions.EMBEDDING_EMBEDDINGS}.${index}.${fi_semantic_conventions_1.SemanticConventions.EMBEDDING_VECTOR}`] = embedding;
347
- return acc;
348
- }, {});
349
185
  }
350
- /**
351
- * Gets rerank results attributes
352
- */
353
- function getRerankResultsAttributes(response) {
354
- const attributes = {};
355
- response.results.forEach((result, index) => {
356
- attributes[`cohere.rerank.results.${index}.index`] = result.index;
357
- attributes[`cohere.rerank.results.${index}.relevance_score`] = result.relevance_score;
358
- if (result.document) {
359
- attributes[`cohere.rerank.results.${index}.document`] = result.document.text;
360
- }
186
+ exports.CohereInstrumentation = CohereInstrumentation;
187
+ /** Keep SDK promise helpers (notably HttpResponsePromise.withRawResponse). */
188
+ function observePromise(pending, resolved, rejected) {
189
+ const promise = pending;
190
+ const observed = promise.then(resolved, rejected);
191
+ if (typeof promise.withRawResponse !== "function")
192
+ return observed;
193
+ // A caller may exclusively use withRawResponse. Do not leave an unobserved
194
+ // rejected branch merely because telemetry also observes the normal promise.
195
+ void observed.catch(() => { });
196
+ return new Proxy(promise, {
197
+ get(target, key) {
198
+ if (key === "then")
199
+ return observed.then.bind(observed);
200
+ if (key === "catch")
201
+ return observed.catch.bind(observed);
202
+ if (key === "finally")
203
+ return observed.finally.bind(observed);
204
+ if (key === "withRawResponse")
205
+ return () => target.withRawResponse().then((raw) => (Object.assign(Object.assign({}, raw), { data: resolved(raw.data) })), rejected);
206
+ const value = Reflect.get(target, key, target);
207
+ return typeof value === "function" ? value.bind(target) : value;
208
+ },
361
209
  });
362
- return attributes;
363
210
  }
364
211
  //# sourceMappingURL=instrumentation.js.map