@apo-ai/sdk 0.2.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.
Files changed (35) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +314 -0
  3. package/dist/agent-task/integrations/ai-sdk.d.ts +121 -0
  4. package/dist/agent-task/integrations/ai-sdk.js +10 -0
  5. package/dist/agent-task/integrations/ai-sdk.js.map +1 -0
  6. package/dist/agent-task/integrations/anthropic.d.ts +67 -0
  7. package/dist/agent-task/integrations/anthropic.js +10 -0
  8. package/dist/agent-task/integrations/anthropic.js.map +1 -0
  9. package/dist/agent-task/integrations/openai.d.ts +77 -0
  10. package/dist/agent-task/integrations/openai.js +10 -0
  11. package/dist/agent-task/integrations/openai.js.map +1 -0
  12. package/dist/agent-task/public.d.ts +1326 -0
  13. package/dist/agent-task/public.js +3026 -0
  14. package/dist/agent-task/public.js.map +1 -0
  15. package/dist/chunk-DT2LMB7O.js +80 -0
  16. package/dist/chunk-DT2LMB7O.js.map +1 -0
  17. package/dist/chunk-GDB6SDGN.js +75 -0
  18. package/dist/chunk-GDB6SDGN.js.map +1 -0
  19. package/dist/chunk-HKLBPIB4.js +232 -0
  20. package/dist/chunk-HKLBPIB4.js.map +1 -0
  21. package/dist/chunk-HWZVL6TS.js +37 -0
  22. package/dist/chunk-HWZVL6TS.js.map +1 -0
  23. package/dist/chunk-PMYLL2H4.js +495 -0
  24. package/dist/chunk-PMYLL2H4.js.map +1 -0
  25. package/dist/chunk-SZDSIPXC.js +74 -0
  26. package/dist/chunk-SZDSIPXC.js.map +1 -0
  27. package/dist/index.d.ts +95 -0
  28. package/dist/index.js +39 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/otel/index.d.ts +270 -0
  31. package/dist/otel/index.js +32 -0
  32. package/dist/otel/index.js.map +1 -0
  33. package/dist/tracing-DtbhYQV6.d.ts +26 -0
  34. package/dist/types-C-nrDEVf.d.ts +140 -0
  35. package/package.json +92 -0
@@ -0,0 +1,74 @@
1
+ // Auto-generated by `pnpm --filter @apo-ai/sdk build` (tsup.config.ts).
2
+ // Do not edit by hand — edit the src/ originals and rebuild.
3
+ import {
4
+ emitGenerationAndTools,
5
+ startGeneration
6
+ } from "./chunk-GDB6SDGN.js";
7
+
8
+ // src/agent-task/integrations/anthropic.ts
9
+ function createApoAnthropic(client, options) {
10
+ const { trace, parentSpanId, taskId, turnNumber } = options;
11
+ const realCreate = client.messages.create.bind(client.messages);
12
+ const tracedCreate = async (...args) => {
13
+ const params = args[0] ?? {};
14
+ const model = String(params.model ?? "unknown");
15
+ if (params.stream === true) {
16
+ return realCreate(params);
17
+ }
18
+ const { spanId, startedAt } = startGeneration(trace, {
19
+ model,
20
+ system: typeof params.system === "string" ? params.system : void 0,
21
+ messages: params.messages,
22
+ parentSpanId,
23
+ taskId,
24
+ turnNumber
25
+ });
26
+ try {
27
+ const response = await realCreate(params);
28
+ const blocks = response.content ?? [];
29
+ const text = blocks.filter((b) => b.type === "text").map((b) => b.text).join("\n");
30
+ const toolCalls = blocks.filter(
31
+ (b) => b.type === "tool_use"
32
+ ).map((b) => ({
33
+ name: b.name,
34
+ input: b.input
35
+ }));
36
+ emitGenerationAndTools(trace, spanId, startedAt, {
37
+ text: text || void 0,
38
+ promptTokens: response.usage?.input_tokens,
39
+ completionTokens: response.usage?.output_tokens,
40
+ toolCalls,
41
+ taskId,
42
+ turnNumber
43
+ });
44
+ return response;
45
+ } catch (error) {
46
+ emitGenerationAndTools(trace, spanId, startedAt, {
47
+ taskId,
48
+ turnNumber,
49
+ error: { message: error instanceof Error ? error.message : String(error) }
50
+ });
51
+ throw error;
52
+ }
53
+ };
54
+ return new Proxy(client, {
55
+ get(target, prop, receiver) {
56
+ if (prop === "messages") {
57
+ return new Proxy(target.messages, {
58
+ get(messagesTarget, messagesProp) {
59
+ if (messagesProp === "create") {
60
+ return tracedCreate;
61
+ }
62
+ return Reflect.get(messagesTarget, messagesProp);
63
+ }
64
+ });
65
+ }
66
+ return Reflect.get(target, prop, receiver);
67
+ }
68
+ });
69
+ }
70
+
71
+ export {
72
+ createApoAnthropic
73
+ };
74
+ //# sourceMappingURL=chunk-SZDSIPXC.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/agent-task/integrations/anthropic.ts"],"sourcesContent":["/**\n * Anthropic JS SDK tracing integration for apo.\n *\n * Wraps an `Anthropic` client so `messages.create()` calls are\n * automatically traced. Tool calls and generations are captured without\n * any manual span code in the adapter.\n *\n * @example\n * ```ts\n * import Anthropic from \"@anthropic-ai/sdk\";\n * import { createApoAnthropic } from \"@apo-ai/sdk/agent-task\";\n *\n * async sendUserTurn(turn, { trace, parentSpanId }) {\n * const client = createApoAnthropic(\n * new Anthropic({ apiKey }),\n * { trace, parentSpanId, taskId: ctx.task.id, turnNumber }\n * );\n * const response = await client.messages.create({\n * model: \"claude-sonnet-4-20250514\",\n * max_tokens: 1024,\n * messages: [{ role: \"user\", content: String(turn) }],\n * tools: [...],\n * });\n * const text = response.content.filter(b => b.type === \"text\").map(b => b.text).join(\"\");\n * return { response: text };\n * }\n * ```\n *\n * @module\n */\n\nimport type { AgentTaskTraceContext } from \"../tracing.ts\";\nimport { startGeneration, emitGenerationAndTools } from \"./span-helpers.ts\";\n\nexport interface CreateApoAnthropicOptions {\n /** The tee'd trace context from `sendUserTurn`'s second argument. */\n trace: AgentTaskTraceContext;\n /** The parent span id for this turn (from `sendUserTurn`'s context). */\n parentSpanId?: string;\n /** Optional task id, surfaced in span metadata. */\n taskId?: string;\n /** Optional turn number, surfaced in span metadata. */\n turnNumber?: number;\n}\n\n/**\n * Minimal structural shape of the Anthropic client we intercept.\n */\ninterface AnthropicClientLike {\n messages: {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n create: (...args: any[]) => Promise<any>;\n };\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n [key: string]: any;\n}\n\n/**\n * The response shape we read from `messages.create()`.\n */\ninterface AnthropicResponseLike {\n model?: string;\n content?: Array<\n | { type: \"text\"; text: string }\n | { type: \"tool_use\"; name: string; input?: unknown }\n | { type: string }\n >;\n usage?: {\n input_tokens?: number;\n output_tokens?: number;\n };\n}\n\n/**\n * Wrap an Anthropic client so `messages.create()` is traced.\n * Returns a Proxy-wrapped client — call it exactly as you would the\n * original. Non-streaming only; streaming responses pass through\n * untraced.\n *\n * For SDKs that emit OpenTelemetry natively (Claude Agent SDK, Vercel AI\n * SDK), prefer `configureApoTelemetry()` instead — no wrapper needed.\n * This manual wrapper is for the raw `@anthropic-ai/sdk` package or\n * custom clients that don't emit OTel on their own.\n */\nexport function createApoAnthropic<T extends AnthropicClientLike>(\n client: T,\n options: CreateApoAnthropicOptions,\n): T {\n const { trace, parentSpanId, taskId, turnNumber } = options;\n const realCreate = client.messages.create.bind(client.messages);\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const tracedCreate = async (...args: any[]): Promise<any> => {\n const params = (args[0] ?? {}) as Record<string, unknown>;\n const model = String(params.model ?? \"unknown\");\n\n // Non-streaming: trace fully. Streaming (stream: true): pass through.\n if (params.stream === true) {\n return realCreate(params);\n }\n\n const { spanId, startedAt } = startGeneration(trace, {\n model,\n system: typeof params.system === \"string\" ? params.system : undefined,\n messages: params.messages,\n parentSpanId,\n taskId,\n turnNumber,\n });\n\n try {\n const response = (await realCreate(params)) as AnthropicResponseLike;\n const blocks = response.content ?? [];\n const text = blocks\n .filter((b): b is { type: \"text\"; text: string } => b.type === \"text\")\n .map((b) => b.text)\n .join(\"\\n\");\n const toolCalls = blocks\n .filter(\n (b): b is { type: \"tool_use\"; name: string; input?: unknown } =>\n b.type === \"tool_use\",\n )\n .map((b) => ({\n name: b.name,\n input: b.input,\n }));\n\n emitGenerationAndTools(trace, spanId, startedAt, {\n text: text || undefined,\n promptTokens: response.usage?.input_tokens,\n completionTokens: response.usage?.output_tokens,\n toolCalls,\n taskId,\n turnNumber,\n });\n\n return response;\n } catch (error) {\n emitGenerationAndTools(trace, spanId, startedAt, {\n taskId,\n turnNumber,\n error: { message: error instanceof Error ? error.message : String(error) },\n });\n throw error;\n }\n };\n\n // Proxy that intercepts client.messages.create but passes\n // everything else through unchanged.\n return new Proxy(client, {\n get(target, prop, receiver) {\n if (prop === \"messages\") {\n return new Proxy(target.messages, {\n get(messagesTarget, messagesProp) {\n if (messagesProp === \"create\") {\n return tracedCreate;\n }\n return Reflect.get(messagesTarget, messagesProp);\n },\n });\n }\n return Reflect.get(target, prop, receiver);\n },\n }) as T;\n}\n"],"mappings":";;;;;;;;AAoFO,SAAS,mBACd,QACA,SACG;AACH,QAAM,EAAE,OAAO,cAAc,QAAQ,WAAW,IAAI;AACpD,QAAM,aAAa,OAAO,SAAS,OAAO,KAAK,OAAO,QAAQ;AAG9D,QAAM,eAAe,UAAU,SAA8B;AAC3D,UAAM,SAAU,KAAK,CAAC,KAAK,CAAC;AAC5B,UAAM,QAAQ,OAAO,OAAO,SAAS,SAAS;AAG9C,QAAI,OAAO,WAAW,MAAM;AAC1B,aAAO,WAAW,MAAM;AAAA,IAC1B;AAEA,UAAM,EAAE,QAAQ,UAAU,IAAI,gBAAgB,OAAO;AAAA,MACnD;AAAA,MACA,QAAQ,OAAO,OAAO,WAAW,WAAW,OAAO,SAAS;AAAA,MAC5D,UAAU,OAAO;AAAA,MACjB;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAED,QAAI;AACF,YAAM,WAAY,MAAM,WAAW,MAAM;AACzC,YAAM,SAAS,SAAS,WAAW,CAAC;AACpC,YAAM,OAAO,OACV,OAAO,CAAC,MAA2C,EAAE,SAAS,MAAM,EACpE,IAAI,CAAC,MAAM,EAAE,IAAI,EACjB,KAAK,IAAI;AACZ,YAAM,YAAY,OACf;AAAA,QACC,CAAC,MACC,EAAE,SAAS;AAAA,MACf,EACC,IAAI,CAAC,OAAO;AAAA,QACX,MAAM,EAAE;AAAA,QACR,OAAO,EAAE;AAAA,MACX,EAAE;AAEJ,6BAAuB,OAAO,QAAQ,WAAW;AAAA,QAC/C,MAAM,QAAQ;AAAA,QACd,cAAc,SAAS,OAAO;AAAA,QAC9B,kBAAkB,SAAS,OAAO;AAAA,QAClC;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AAED,aAAO;AAAA,IACT,SAAS,OAAO;AACd,6BAAuB,OAAO,QAAQ,WAAW;AAAA,QAC/C;AAAA,QACA;AAAA,QACA,OAAO,EAAE,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,EAAE;AAAA,MAC3E,CAAC;AACD,YAAM;AAAA,IACR;AAAA,EACF;AAIA,SAAO,IAAI,MAAM,QAAQ;AAAA,IACvB,IAAI,QAAQ,MAAM,UAAU;AAC1B,UAAI,SAAS,YAAY;AACvB,eAAO,IAAI,MAAM,OAAO,UAAU;AAAA,UAChC,IAAI,gBAAgB,cAAc;AAChC,gBAAI,iBAAiB,UAAU;AAC7B,qBAAO;AAAA,YACT;AACA,mBAAO,QAAQ,IAAI,gBAAgB,YAAY;AAAA,UACjD;AAAA,QACF,CAAC;AAAA,MACH;AACA,aAAO,QAAQ,IAAI,QAAQ,MAAM,QAAQ;AAAA,IAC3C;AAAA,EACF,CAAC;AACH;","names":[]}
@@ -0,0 +1,95 @@
1
+ export { b as ClientOptions, c as CreateScoreParams, C as CreateSpanParams, d as CreateTraceParams, E as EndSpanParams, I as IngestionEvent, O as ObservationContext, e as ObserveOptions, P as ParameterOverrides, f as TraceEventOptions, T as TraceRunContext, a as TraceRunOptions, g as TraceStepOptions } from './types-C-nrDEVf.js';
2
+ import * as effect_Cause from 'effect/Cause';
3
+ import * as effect_Types from 'effect/Types';
4
+
5
+ type ClientErrorCode = "VALIDATION" | "HTTP" | "NETWORK" | "TIMEOUT" | "DECODE" | "UNKNOWN";
6
+ declare const ClientError_base: new <A extends Record<string, any> = {}>(args: effect_Types.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => effect_Cause.YieldableError & {
7
+ readonly _tag: "ClientError";
8
+ } & Readonly<A>;
9
+ declare class ClientError extends ClientError_base<{
10
+ code: ClientErrorCode;
11
+ message: string;
12
+ status?: number;
13
+ body?: string;
14
+ retryable?: boolean;
15
+ cause?: unknown;
16
+ }> {
17
+ }
18
+ declare const ConfigurationError_base: new <A extends Record<string, any> = {}>(args: effect_Types.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => effect_Cause.YieldableError & {
19
+ readonly _tag: "ConfigurationError";
20
+ } & Readonly<A>;
21
+ declare class ConfigurationError extends ConfigurationError_base<{
22
+ message: string;
23
+ suggestion?: string;
24
+ }> {
25
+ }
26
+
27
+ /**
28
+ * Configuration management for apo SDK.
29
+ *
30
+ * Centralizes environment variable reading so all wrappers use the same logic.
31
+ */
32
+ interface EnvConfig {
33
+ /** Backend endpoint URL */
34
+ endpoint: string;
35
+ /** Project name for optimization tracking */
36
+ project: string;
37
+ /**
38
+ * Public identifier for the two-key model. this is the
39
+ * ``pk-apo-*`` value, used as the Basic-auth username alongside
40
+ * ``secretKey``. It is NOT a usable credential on its own — the SDK
41
+ * never reads ``NEXT_PUBLIC_APO_PUBLIC_KEY`` because publishing a public
42
+ * identifier in a browser bundle creates a misleading direct-browser
43
+ * integration. Server-only.
44
+ */
45
+ publicKey?: string;
46
+ /** Secret key for two-key auth (server-only). */
47
+ secretKey?: string;
48
+ /** Legacy single-key auth token */
49
+ apiKey?: string;
50
+ }
51
+ /**
52
+ * Read optimizer configuration from environment variables.
53
+ *
54
+ * This function centralizes all environment variable reading for the SDK,
55
+ * ensuring consistent behavior across all wrapper functions.
56
+ *
57
+ * **Environment Variables (in order of priority):**
58
+ *
59
+ * For `endpoint`:
60
+ * - `NEXT_PUBLIC_APO_BACKEND_URL` (Next.js public env var)
61
+ * - `APO_BACKEND_URL` (standard env var)
62
+ * - Falls back to `http://localhost:8000`
63
+ *
64
+ * For `project`:
65
+ * - `APO_PROJECT` (standard env var)
66
+ * - `NEXT_PUBLIC_APO_PROJECT` (Next.js public env var)
67
+ * - Falls back to `default-project`
68
+ *
69
+ * For `publicKey`:
70
+ * - `APO_PUBLIC_KEY` (server-side public identifier; paired with
71
+ * `APO_SECRET_KEY` to form HTTP Basic credentials). Support for `NEXT_PUBLIC_APO_PUBLIC_KEY` was removed:
72
+ * the public identifier alone
73
+ * does not authorize ingestion, so publishing it as a browser-safe env
74
+ * var is actively misleading.
75
+ *
76
+ * For `secretKey`:
77
+ * - `APO_SECRET_KEY` (server-side only)
78
+ *
79
+ * For `apiKey` (legacy single-key auth):
80
+ * - `APO_API_KEY`
81
+ *
82
+ * @example
83
+ * ```ts
84
+ * import { readConfig } from "@apo-ai/sdk";
85
+ *
86
+ * const config = readConfig();
87
+ * console.log(config.endpoint); // "http://localhost:8000" or env value
88
+ * console.log(config.project); // "default-project" or env value
89
+ * ```
90
+ *
91
+ * @returns Client configuration from environment
92
+ */
93
+ declare function readConfig(): EnvConfig;
94
+
95
+ export { ClientError, type ClientErrorCode, ConfigurationError, type EnvConfig, readConfig };
package/dist/index.js ADDED
@@ -0,0 +1,39 @@
1
+ // Auto-generated by `pnpm --filter @apo-ai/sdk build` (tsup.config.ts).
2
+ // Do not edit by hand — edit the src/ originals and rebuild.
3
+
4
+ // src/errors.ts
5
+ import { Data } from "effect";
6
+ var ClientError = class extends Data.TaggedError("ClientError") {
7
+ };
8
+ var ValidationError = class extends Data.TaggedError("ValidationError") {
9
+ };
10
+ var NetworkError = class extends Data.TaggedError("NetworkError") {
11
+ };
12
+ var DecodeError = class extends Data.TaggedError("DecodeError") {
13
+ };
14
+ var TimeoutError = class extends Data.TaggedError("TimeoutError") {
15
+ };
16
+ var RegisterParametersError = class extends Data.TaggedError(
17
+ "RegisterParametersError"
18
+ ) {
19
+ };
20
+ var ConfigurationError = class extends Data.TaggedError("ConfigurationError") {
21
+ };
22
+ var RenderParameterError = class extends Data.TaggedError("RenderParameterError") {
23
+ };
24
+
25
+ // src/config.ts
26
+ function readConfig() {
27
+ const endpoint = process.env.NEXT_PUBLIC_APO_BACKEND_URL ?? process.env.APO_BACKEND_URL ?? "http://localhost:8000";
28
+ const project = process.env.APO_PROJECT ?? process.env.NEXT_PUBLIC_APO_PROJECT ?? "default-project";
29
+ const publicKey = process.env.APO_PUBLIC_KEY;
30
+ const secretKey = process.env.APO_SECRET_KEY;
31
+ const apiKey = process.env.APO_API_KEY;
32
+ return { endpoint, project, publicKey, secretKey, apiKey };
33
+ }
34
+ export {
35
+ ClientError,
36
+ ConfigurationError,
37
+ readConfig
38
+ };
39
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/errors.ts","../src/config.ts"],"sourcesContent":["import { Data } from \"effect\";\n\nexport type ClientErrorCode =\n | \"VALIDATION\"\n | \"HTTP\"\n | \"NETWORK\"\n | \"TIMEOUT\"\n | \"DECODE\"\n | \"UNKNOWN\";\n\nexport class ClientError extends Data.TaggedError(\"ClientError\")<{\n code: ClientErrorCode;\n message: string;\n status?: number;\n body?: string;\n retryable?: boolean;\n cause?: unknown;\n}> {}\n\nexport class ValidationError extends Data.TaggedError(\"ValidationError\")<{}> {}\n\nexport class NetworkError extends Data.TaggedError(\"NetworkError\")<{\n message: string;\n cause?: unknown;\n}> {}\n\nexport class DecodeError extends Data.TaggedError(\"DecodeError\")<{\n message: string;\n cause?: unknown;\n}> {}\n\nexport class TimeoutError extends Data.TaggedError(\"TimeoutError\")<{\n message: string;\n cause?: unknown;\n}> {}\n\nexport class RegisterParametersError extends Data.TaggedError(\n \"RegisterParametersError\"\n)<{\n status: number;\n body: string;\n}> {}\n\nexport class ConfigurationError extends Data.TaggedError(\"ConfigurationError\")<{\n message: string;\n suggestion?: string;\n}> {}\n\nconst asMessage = (e: unknown): string =>\n e instanceof Error\n ? e.message\n : typeof e === \"string\"\n ? e\n : JSON.stringify(e);\n\nexport const normalizeError = (e: unknown): ClientError => {\n if (e instanceof ValidationError) {\n return new ClientError({\n code: \"VALIDATION\",\n message: \"Invalid parameter definitions (flowName mismatch / missing).\",\n cause: e,\n });\n }\n\n if (e instanceof ConfigurationError) {\n return new ClientError({\n code: \"VALIDATION\",\n message: e.message,\n cause: e,\n });\n }\n\n if (e instanceof RegisterParametersError) {\n return new ClientError({\n code: \"HTTP\",\n message: `Parameter registration failed (HTTP ${e.status}).`,\n status: e.status,\n body: e.body,\n retryable: e.status >= 500 || e.status === 429,\n cause: e,\n });\n }\n\n if (e instanceof NetworkError) {\n return new ClientError({\n code: \"NETWORK\",\n message: e.message,\n retryable: true,\n cause: e,\n });\n }\n\n if (e instanceof DecodeError) {\n return new ClientError({\n code: \"DECODE\",\n message: e.message,\n retryable: false,\n cause: e,\n });\n }\n\n if (e instanceof TimeoutError) {\n return new ClientError({\n code: \"TIMEOUT\",\n message: e.message,\n retryable: true,\n cause: e,\n });\n }\n\n return new ClientError({\n code: \"UNKNOWN\",\n message: asMessage(e) || \"Unknown error.\",\n retryable: false,\n cause: e,\n });\n};\n\nexport class RenderParameterError extends Data.TaggedError(\"RenderParameterError\")<{\n message: string;\n}> {}\n","/**\n * Configuration management for apo SDK.\n *\n * Centralizes environment variable reading so all wrappers use the same logic.\n */\n\nexport interface EnvConfig {\n /** Backend endpoint URL */\n endpoint: string;\n /** Project name for optimization tracking */\n project: string;\n /**\n * Public identifier for the two-key model. this is the\n * ``pk-apo-*`` value, used as the Basic-auth username alongside\n * ``secretKey``. It is NOT a usable credential on its own — the SDK\n * never reads ``NEXT_PUBLIC_APO_PUBLIC_KEY`` because publishing a public\n * identifier in a browser bundle creates a misleading direct-browser\n * integration. Server-only.\n */\n publicKey?: string;\n /** Secret key for two-key auth (server-only). */\n secretKey?: string;\n /** Legacy single-key auth token */\n apiKey?: string;\n}\n\n/**\n * Read optimizer configuration from environment variables.\n *\n * This function centralizes all environment variable reading for the SDK,\n * ensuring consistent behavior across all wrapper functions.\n *\n * **Environment Variables (in order of priority):**\n *\n * For `endpoint`:\n * - `NEXT_PUBLIC_APO_BACKEND_URL` (Next.js public env var)\n * - `APO_BACKEND_URL` (standard env var)\n * - Falls back to `http://localhost:8000`\n *\n * For `project`:\n * - `APO_PROJECT` (standard env var)\n * - `NEXT_PUBLIC_APO_PROJECT` (Next.js public env var)\n * - Falls back to `default-project`\n *\n * For `publicKey`:\n * - `APO_PUBLIC_KEY` (server-side public identifier; paired with\n * `APO_SECRET_KEY` to form HTTP Basic credentials). Support for `NEXT_PUBLIC_APO_PUBLIC_KEY` was removed:\n * the public identifier alone\n * does not authorize ingestion, so publishing it as a browser-safe env\n * var is actively misleading.\n *\n * For `secretKey`:\n * - `APO_SECRET_KEY` (server-side only)\n *\n * For `apiKey` (legacy single-key auth):\n * - `APO_API_KEY`\n *\n * @example\n * ```ts\n * import { readConfig } from \"@apo-ai/sdk\";\n *\n * const config = readConfig();\n * console.log(config.endpoint); // \"http://localhost:8000\" or env value\n * console.log(config.project); // \"default-project\" or env value\n * ```\n *\n * @returns Client configuration from environment\n */\nexport function readConfig(): EnvConfig {\n const endpoint =\n process.env.NEXT_PUBLIC_APO_BACKEND_URL ??\n process.env.APO_BACKEND_URL ??\n \"http://localhost:8000\";\n\n const project =\n process.env.APO_PROJECT ??\n process.env.NEXT_PUBLIC_APO_PROJECT ??\n \"default-project\";\n\n const publicKey = process.env.APO_PUBLIC_KEY;\n\n const secretKey = process.env.APO_SECRET_KEY;\n const apiKey = process.env.APO_API_KEY;\n\n return { endpoint, project, publicKey, secretKey, apiKey };\n}\n"],"mappings":";;;;AAAA,SAAS,YAAY;AAUd,IAAM,cAAN,cAA0B,KAAK,YAAY,aAAa,EAO5D;AAAC;AAEG,IAAM,kBAAN,cAA8B,KAAK,YAAY,iBAAiB,EAAM;AAAC;AAEvE,IAAM,eAAN,cAA2B,KAAK,YAAY,cAAc,EAG9D;AAAC;AAEG,IAAM,cAAN,cAA0B,KAAK,YAAY,aAAa,EAG5D;AAAC;AAEG,IAAM,eAAN,cAA2B,KAAK,YAAY,cAAc,EAG9D;AAAC;AAEG,IAAM,0BAAN,cAAsC,KAAK;AAAA,EAChD;AACF,EAGG;AAAC;AAEG,IAAM,qBAAN,cAAiC,KAAK,YAAY,oBAAoB,EAG1E;AAAC;AAwEG,IAAM,uBAAN,cAAmC,KAAK,YAAY,sBAAsB,EAE9E;AAAC;;;ACpDG,SAAS,aAAwB;AACtC,QAAM,WACJ,QAAQ,IAAI,+BACZ,QAAQ,IAAI,mBACZ;AAEF,QAAM,UACJ,QAAQ,IAAI,eACZ,QAAQ,IAAI,2BACZ;AAEF,QAAM,YAAY,QAAQ,IAAI;AAE9B,QAAM,YAAY,QAAQ,IAAI;AAC9B,QAAM,SAAS,QAAQ,IAAI;AAE3B,SAAO,EAAE,UAAU,SAAS,WAAW,WAAW,OAAO;AAC3D;","names":[]}
@@ -0,0 +1,270 @@
1
+ import { Tracer, TracerProvider, Span } from '@opentelemetry/api';
2
+ import { SpanProcessor, SpanExporter } from '@opentelemetry/sdk-trace-base';
3
+
4
+ /**
5
+ * OTel-native tracing setup for the apo SDK.
6
+ *
7
+ * This module provides the standard OpenTelemetry setup path for apo:
8
+ * - ``configureApoTelemetry`` creates a tracer provider with an OTLP exporter
9
+ * - ``withApoTrace`` creates root/child spans using standard OTel context
10
+ * - Helper functions (``traceTool``, ``traceAgent``, etc.) emit normal OTel
11
+ * spans with GenAI or apo vendor attributes
12
+ *
13
+ * This replaces the deprecated ``TraceTracker`` custom event protocol. New
14
+ * users should use this module; existing ``TraceTracker`` code continues to
15
+ * work through a compatibility bridge.
16
+ *
17
+ * @module @apo-ai/sdk/otel
18
+ */
19
+
20
+ interface ConfigureApoTelemetryOptions {
21
+ /** Explicit permission for this standalone helper to own OTel lifecycle. */
22
+ takeOwnership: true;
23
+ /**
24
+ * Full OTLP traces endpoint URL. Falls back to the `APO_OTLP_ENDPOINT` env
25
+ * var when omitted, then to `http://localhost:8000/api/public/otel/v1/traces`.
26
+ */
27
+ endpoint?: string;
28
+ /**
29
+ * Diagnostic resource attribute only. Auth owns tenancy — the project is
30
+ * determined by the API key / service token, never by this field.
31
+ * Falls back to the `APO_PROJECT` env var when omitted.
32
+ */
33
+ project?: string;
34
+ /**
35
+ * Service name for the OTel resource (required). Defaults to `"apo-agent"`.
36
+ */
37
+ serviceName?: string;
38
+ /** Service version for the OTel resource. */
39
+ serviceVersion?: string;
40
+ /** Deployment environment (production, staging, etc.). */
41
+ environment?: string;
42
+ /**
43
+ * Auth headers (Authorization: Basic/Bearer). Falls back to headers derived
44
+ * from `APO_PUBLIC_KEY`+`APO_SECRET_KEY` (Basic) or `APO_AUTH_TOKEN` (Bearer)
45
+ * env vars when omitted. Use {@link buildApoAuthHeaders} to build them
46
+ * explicitly.
47
+ */
48
+ headers?: Record<string, string>;
49
+ /**
50
+ * Public key for Basic auth. Falls back to `APO_PUBLIC_KEY` env var.
51
+ * Used with `secretKey` to build `Authorization: Basic base64(pk:sk)`.
52
+ */
53
+ publicKey?: string;
54
+ /**
55
+ * Secret key for Basic auth. Falls back to `APO_SECRET_KEY` env var.
56
+ */
57
+ secretKey?: string;
58
+ /**
59
+ * Bearer auth token. Falls back to `APO_AUTH_TOKEN` env var. Used only when
60
+ * `publicKey`/`secretKey` are absent.
61
+ */
62
+ authToken?: string;
63
+ /**
64
+ * @deprecated OTel JS 2.x providers cannot accept processors after
65
+ * construction. Use `createApoSpanProcessor()` in the host provider's
66
+ * `spanProcessors` array instead.
67
+ */
68
+ provider?: TracerProvider;
69
+ /** Batch for services; simple is useful for short-lived task subprocesses. */
70
+ processor?: "batch" | "simple";
71
+ /**
72
+ * Whether to register apo's provider as the global tracer provider. Defaults
73
+ * to false. When true, registration only happens if no global provider is
74
+ * registered yet — apo never silently replaces an existing global provider.
75
+ */
76
+ registerGlobal?: boolean;
77
+ }
78
+ interface ApoTelemetryHandle {
79
+ /** The OTel tracer for creating spans. */
80
+ tracer: Tracer;
81
+ /** The provider, for advanced use. */
82
+ provider: TracerProvider;
83
+ /** Export all ended spans without relinquishing provider ownership. */
84
+ forceFlush(): Promise<void>;
85
+ /** Gracefully shut down the provider and flush pending spans. */
86
+ shutdown(): Promise<void>;
87
+ }
88
+ interface ApoTraceExporterOptions {
89
+ /** Full standard OTLP/HTTP traces endpoint. */
90
+ endpoint: string;
91
+ /** Authentication headers sent by the official OTLP exporter. */
92
+ headers: Record<string, string>;
93
+ }
94
+ interface ApoSpanProcessorOptions extends ApoTraceExporterOptions {
95
+ /** Batch for long-lived services (default), simple for short-lived jobs. */
96
+ processor?: "batch" | "simple";
97
+ }
98
+ interface ApoTraceOptions {
99
+ /** Span name. */
100
+ name: string;
101
+ /** apo.observation.type override. */
102
+ observationType?: string;
103
+ /** Additional attributes. */
104
+ attributes?: Record<string, unknown>;
105
+ }
106
+ /** Create the official OTLP/HTTP exporter for a host-owned OTel provider. */
107
+ declare function createApoTraceExporter(options: ApoTraceExporterOptions): SpanExporter;
108
+ /**
109
+ * Create an apo OTLP processor for inclusion when constructing a host provider.
110
+ * This factory has no global side effects and transfers lifecycle ownership to
111
+ * the host provider.
112
+ */
113
+ declare function createApoSpanProcessor(options: ApoSpanProcessorOptions): SpanProcessor;
114
+ /**
115
+ * Build the `Authorization` header for apo's OTLP endpoint.
116
+ *
117
+ * - If `publicKey` + `secretKey` are given (or read from `APO_PUBLIC_KEY` /
118
+ * `APO_SECRET_KEY`), returns HTTP Basic: `Basic base64(pk:sk)`. * both halves are required — a public identifier alone is not a
119
+ * credential, so partial Basic is never synthesized.
120
+ * - Else if `authToken` is given (or read from `APO_AUTH_TOKEN`), returns
121
+ * `Bearer <token>`. (Covers short-lived task-run/attempt tokens and
122
+ * secret-bearing legacy API keys.)
123
+ * - Else returns an empty object (unauthenticated).
124
+ *
125
+ * Mirrors Python's `_build_auth_headers` in apo-otel-python.
126
+ */
127
+ declare function buildApoAuthHeaders(publicKey?: string, secretKey?: string, authToken?: string): Record<string, string>;
128
+ /**
129
+ * Configure apo's OpenTelemetry tracing.
130
+ *
131
+ * Builds apo's trace export from official OTel components: a real
132
+ * {@link Resource} (service.name, service.version, deployment.environment)
133
+ * and the official {@link OTLPTraceExporter} (standard OTLP/HTTP, no custom
134
+ * wire format). This is the explicit standalone bootstrap. Host applications
135
+ * that already own a provider should use `createApoSpanProcessor()` instead.
136
+ *
137
+ * @example
138
+ * ```ts
139
+ * import { configureApoTelemetry } from "@apo-ai/sdk/otel";
140
+ *
141
+ * const apo = await configureApoTelemetry({
142
+ * takeOwnership: true,
143
+ * endpoint: "https://apo.example.com/api/public/otel/v1/traces",
144
+ * serviceName: "my-agent",
145
+ * headers: { Authorization: `Basic ${btoa("pk-apo-...:sk-apo-...")}` },
146
+ * });
147
+ *
148
+ * const result = await withApoTrace({ name: "chat" }, apo.tracer, async (span) => {
149
+ * span.setAttribute("gen_ai.request.model", "gpt-4o");
150
+ * // ... do work ...
151
+ * return "done";
152
+ * });
153
+ *
154
+ * await apo.shutdown();
155
+ * ```
156
+ */
157
+ declare function configureApoTelemetry(options: ConfigureApoTelemetryOptions): Promise<ApoTelemetryHandle>;
158
+ /**
159
+ * Run a function inside an OTel span.
160
+ *
161
+ * Creates a span using the active OTel context (standard context propagation,
162
+ * not apo-specific span IDs passed by hand). The span automatically ends when
163
+ * the function returns or throws.
164
+ *
165
+ * @example
166
+ * ```ts
167
+ * const result = await withApoTrace(
168
+ * { name: "agent-turn", observationType: "AGENT" },
169
+ * apo.tracer,
170
+ * async (span) => {
171
+ * span.setAttribute("gen_ai.request.model", "gpt-4o");
172
+ * return await llm.complete("hello");
173
+ * },
174
+ * );
175
+ * ```
176
+ */
177
+ declare function withApoTrace<T>(options: ApoTraceOptions, tracer: Tracer, fn: (span: Span) => Promise<T>): Promise<T>;
178
+ /**
179
+ * Trace a tool execution as an OTel span.
180
+ *
181
+ * Creates a span with ``gen_ai.tool.name``, ``gen_ai.tool.call.arguments``,
182
+ * and ``gen_ai.tool.call.result`` attributes so the backend normalizer
183
+ * classifies it as a TOOL observation.
184
+ */
185
+ declare function traceTool<T>(tracer: Tracer, name: string, params: Record<string, unknown>, fn: () => Promise<T>): Promise<T>;
186
+ /**
187
+ * Trace an agent invocation as an OTel span.
188
+ */
189
+ declare function traceAgent<T>(tracer: Tracer, name: string, fn: () => Promise<T>): Promise<T>;
190
+ /**
191
+ * Trace a chain/step as an OTel span.
192
+ */
193
+ declare function traceChain<T>(tracer: Tracer, name: string, fn: () => Promise<T>): Promise<T>;
194
+ /**
195
+ * Trace a retrieval as an OTel span.
196
+ */
197
+ declare function traceRetriever<T>(tracer: Tracer, query: string, fn: () => Promise<T>): Promise<T>;
198
+ interface ScoreOptions {
199
+ name: string;
200
+ value: number | string | boolean;
201
+ dataType?: "NUMERIC" | "CATEGORICAL" | "BOOLEAN";
202
+ source?: "API" | "EVAL" | "ANNOTATION";
203
+ comment?: string;
204
+ observationId?: string;
205
+ }
206
+ /**
207
+ * Record a score for a trace (or a specific observation within a trace).
208
+ *
209
+ * "A Score is an apo domain record attached to a Trace or
210
+ * Observation. It is not encoded as a fake span."
211
+ *
212
+ * This calls the native score API (`POST /api/v1/traces/{id}/scores` or
213
+ * `POST /api/v1/observations/{id}/scores`) instead of creating a sentinel
214
+ * span. The score is stored as a `RunMetricDB` or `CallMetricDB` row.
215
+ *
216
+ * @example
217
+ * ```ts
218
+ * await score({
219
+ * traceId: "abc123...",
220
+ * name: "helpfulness",
221
+ * value: 0.85,
222
+ * dataType: "NUMERIC",
223
+ * source: "EVAL",
224
+ * }, { endpoint: "http://localhost:8000", headers: authHeaders });
225
+ * ```
226
+ */
227
+ declare function score(params: ScoreOptions & {
228
+ traceId: string;
229
+ }, config: {
230
+ endpoint: string;
231
+ headers: Record<string, string>;
232
+ }): Promise<void>;
233
+ /**
234
+ * Inject the current span's trace context into a headers dict for outbound
235
+ * HTTP/queue calls. Produces a standard W3C `traceparent` header so the
236
+ * downstream service can extract it and create a child span in the same trace.
237
+ *
238
+ * Delegates to OTel's official `W3CTraceContextPropagator`, which also emits
239
+ * `tracestate` and handles the spec's edge cases.
240
+ *
241
+ * @example
242
+ * ```ts
243
+ * const headers = injectTraceparent();
244
+ * await fetch("http://downstream-service/api", { headers });
245
+ * ```
246
+ */
247
+ declare function injectTraceparent(): Record<string, string>;
248
+ /**
249
+ * Extract a W3C trace context from inbound headers and run a function as a
250
+ * child span within that trace. If no `traceparent` header is present (or it
251
+ * is malformed), a new root span is created.
252
+ *
253
+ * Transport parsing is delegated to OTel's `W3CTraceContextPropagator`; the
254
+ * span creation on top of the extracted remote parent is apo-specific and
255
+ * kept here.
256
+ *
257
+ * @example
258
+ * ```ts
259
+ * // In a downstream HTTP handler:
260
+ * app.post("/api", (req, res) => {
261
+ * const result = await extractTraceparent(req.headers, tracer, async (span) => {
262
+ * return await doWork();
263
+ * });
264
+ * res.json(result);
265
+ * });
266
+ * ```
267
+ */
268
+ declare function extractTraceparent<T>(headers: Record<string, string>, tracer: Tracer, fn: (span: Span) => Promise<T>): Promise<T>;
269
+
270
+ export { type ApoSpanProcessorOptions, type ApoTelemetryHandle, type ApoTraceExporterOptions, type ApoTraceOptions, type ConfigureApoTelemetryOptions, type ScoreOptions, buildApoAuthHeaders, configureApoTelemetry, createApoSpanProcessor, createApoTraceExporter, extractTraceparent, injectTraceparent, score, traceAgent, traceChain, traceRetriever, traceTool, withApoTrace };
@@ -0,0 +1,32 @@
1
+ // Auto-generated by `pnpm --filter @apo-ai/sdk build` (tsup.config.ts).
2
+ // Do not edit by hand — edit the src/ originals and rebuild.
3
+ import {
4
+ buildApoAuthHeaders,
5
+ configureApoTelemetry,
6
+ createApoSpanProcessor,
7
+ createApoTraceExporter,
8
+ extractTraceparent,
9
+ injectTraceparent,
10
+ score,
11
+ traceAgent,
12
+ traceChain,
13
+ traceRetriever,
14
+ traceTool,
15
+ withApoTrace
16
+ } from "../chunk-PMYLL2H4.js";
17
+ import "../chunk-HWZVL6TS.js";
18
+ export {
19
+ buildApoAuthHeaders,
20
+ configureApoTelemetry,
21
+ createApoSpanProcessor,
22
+ createApoTraceExporter,
23
+ extractTraceparent,
24
+ injectTraceparent,
25
+ score,
26
+ traceAgent,
27
+ traceChain,
28
+ traceRetriever,
29
+ traceTool,
30
+ withApoTrace
31
+ };
32
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,26 @@
1
+ import { T as TraceRunContext, C as CreateSpanParams, E as EndSpanParams, a as TraceRunOptions } from './types-C-nrDEVf.js';
2
+
3
+ type AgentTaskTraceContext = TraceRunContext & {
4
+ createSpan: (options: Omit<CreateSpanParams, "project" | "run_id">) => string;
5
+ endSpan: (spanId: string, params?: Omit<EndSpanParams, "id">) => void;
6
+ };
7
+ type AgentTaskTraceOptions = {
8
+ client: {
9
+ traceRun<T>(params: TraceRunOptions, fn: (trace: AgentTaskTraceContext) => Promise<T>): Promise<T>;
10
+ };
11
+ project?: string;
12
+ flowName?: string;
13
+ version?: string;
14
+ environment?: string;
15
+ tags?: string[];
16
+ runMetadata?: Record<string, unknown>;
17
+ /**
18
+ * The Task Run ID this trace should claim. Emitted as the
19
+ * `apo.task.run.id` root-span attribute so the backend projector can
20
+ * atomically link this trace to the task run. Omit for local/programmatic
21
+ * runs that don't have a backend task run.
22
+ */
23
+ taskRunId?: string;
24
+ };
25
+
26
+ export type { AgentTaskTraceContext as A, AgentTaskTraceOptions as a };