@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
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Sami Kuikka
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,314 @@
1
+ # apo SDK
2
+
3
+ TypeScript/JavaScript SDK for the [apo](.) backend — an agent testing and
4
+ observability platform. The SDK has three entry points:
5
+
6
+ - **`@apo-ai/sdk`** — config + error types shared across the surface.
7
+ - **`@apo-ai/sdk/otel`** — OpenTelemetry-native tracing. Wrap your LLM calls and
8
+ agent steps so they land in apo as structured spans, then attach scores.
9
+ - **`@apo-ai/sdk/agent-task`** — the agent-task evaluation framework. Define tasks,
10
+ adapters, and checks; run them against an agent and collect structured
11
+ results.
12
+
13
+ ## Installation
14
+
15
+ ```bash
16
+ pnpm add @apo-ai/sdk
17
+ # or: npm install @apo-ai/sdk / yarn add @apo-ai/sdk
18
+ ```
19
+
20
+ Requires Node.js ≥ 20. The package ships compiled ESM + `.d.ts` (built via
21
+ `tsup`), so no TypeScript-transpiling runtime and no `allowImportingTsExtensions`
22
+ tsconfig flag are required on the consumer side.
23
+
24
+ For TypeScript consumers, also install `@types/node` (the SDK's emitted
25
+ declarations reference Node globals like `Buffer`):
26
+
27
+ ```bash
28
+ pnpm add -D @types/node
29
+ ```
30
+
31
+ ## Releases
32
+
33
+ See [RELEASING.md](./RELEASING.md) for the maintainer runbook. The package
34
+ is published to npm via GitHub OIDC trusted publishing from `sdk-v*` tags —
35
+ no long-lived npm token is stored in the repository.
36
+
37
+ ## Configuration
38
+
39
+ `readConfig()` reads backend/project/credentials from environment variables.
40
+
41
+ | Field | Env var (server) | Env var (Next.js, browser-safe) | Required |
42
+ |-------------|-----------------------------|--------------------------------------|----------|
43
+ | `endpoint` | `APO_BACKEND_URL` | `NEXT_PUBLIC_APO_BACKEND_URL` | yes |
44
+ | `project` | `APO_PROJECT` | `NEXT_PUBLIC_APO_PROJECT` | yes |
45
+ | `publicKey` | `APO_PUBLIC_KEY` | — *(server-side only — see below)* | two-key |
46
+ | `secretKey` | `APO_SECRET_KEY` | — | two-key |
47
+ | `apiKey` | `APO_API_KEY` | — | legacy |
48
+
49
+ The Next.js (`NEXT_PUBLIC_*`) variants are read first, then the plain server
50
+ variants. `apiKey` is the legacy single-key format (`sk-…`); prefer the
51
+ two-key model (`publicKey` + `secretKey`, generated as `pk-apo-…` / `sk-apo-…`
52
+ in the dashboard).
53
+
54
+ there is no browser-safe variant of `APO_PUBLIC_KEY`. The public
55
+ identifier alone does not authorize ingestion, and exposing it in a
56
+ browser bundle creates a misleading direct-browser integration.
57
+ `NEXT_PUBLIC_APO_PUBLIC_KEY` is intentionally not read. Telemetry
58
+ submission always requires both halves of an API-key pair sent as HTTP
59
+ Basic (`base64("pk-apo-…:sk-apo-…")`); the SDK never synthesizes partial
60
+ Basic credentials from only one half.
61
+
62
+ ```ts
63
+ import { readConfig, type EnvConfig } from "@apo-ai/sdk";
64
+
65
+ const config: EnvConfig = readConfig();
66
+ ```
67
+
68
+ ## API reference — `@apo-ai/sdk`
69
+
70
+ The root entry is intentionally thin: shared types + config + errors. The
71
+ actual tracing surface lives at `@apo-ai/sdk/otel`.
72
+
73
+ ### Types
74
+
75
+ The trace/observation parameter types used by the OTel helpers:
76
+ `CreateTraceParams`, `CreateSpanParams`, `EndSpanParams`, `TraceRunContext`,
77
+ `TraceRunOptions`, `TraceStepOptions`, `TraceEventOptions`, `IngestionEvent`,
78
+ `CreateScoreParams`, `ClientOptions`, `ParameterOverrides`, `ObserveOptions`,
79
+ `ObservationContext`.
80
+
81
+ ### `readConfig(): EnvConfig`
82
+
83
+ Read endpoint/project/keys from environment variables (table above).
84
+
85
+ ### Errors
86
+
87
+ `ClientError` (Effect `Data.TaggedError`), `ConfigurationError`,
88
+ `ClientErrorCode`. `ClientError` carries a `code` field for categorising
89
+ failures.
90
+
91
+ ## Tracing — `@apo-ai/sdk/otel`
92
+
93
+ The canonical tracing path is OpenTelemetry via `@apo-ai/sdk/otel`. The old
94
+ `TraceTracker` / `createClient` custom protocol has been removed.
95
+
96
+ ```ts
97
+ import {
98
+ configureApoTelemetry,
99
+ withApoTrace,
100
+ traceTool,
101
+ traceAgent,
102
+ traceRetriever,
103
+ score,
104
+ injectTraceparent,
105
+ extractTraceparent,
106
+ } from "@apo-ai/sdk/otel";
107
+ ```
108
+
109
+ ### `configureApoTelemetry(options)`
110
+
111
+ Sets up an OTel tracer provider with an OTLP exporter pointing at apo. Requires
112
+ `takeOwnership: true` (explicit permission to own the OTel lifecycle — don't
113
+ call this if your app already configures OTel itself).
114
+
115
+ ```ts
116
+ const handle = await configureApoTelemetry({
117
+ takeOwnership: true,
118
+ endpoint: process.env.APO_OTLP_ENDPOINT ?? "http://localhost:8000/v1/otlp",
119
+ // headers, resource attributes, batch/simple processor, etc.
120
+ });
121
+
122
+ // …your traced work…
123
+
124
+ await handle.shutdown(); // flush + tear down
125
+ ```
126
+
127
+ ### `withApoTrace(name, fn, options?)`
128
+
129
+ Open a root span, run `fn` inside it, end the span, and return the result.
130
+
131
+ ```ts
132
+ const summary = await withApoTrace("analyze-doc", async (span) => {
133
+ span.setAttribute("apo.flow.name", "analyze-doc");
134
+ return runAnalysis();
135
+ });
136
+ ```
137
+
138
+ ### Typed observation helpers
139
+
140
+ For non-LLM work (tools, retrievers, chains, agents), each helper emits a
141
+ correctly-typed GenAI span:
142
+
143
+ ```ts
144
+ const docs = await traceRetriever("what is apo?", async () => [...]);
145
+ const out = await traceAgent("research-agent", async () => ({ ... }));
146
+ const tool = await traceTool("search", async () => ({ hits: 3 }));
147
+ ```
148
+
149
+ Available: `traceTool`, `traceAgent`, `traceRetriever`, `traceChain`.
150
+
151
+ ### Scoring
152
+
153
+ Attach scores (numeric / categorical / boolean) to a run or observation:
154
+
155
+ ```ts
156
+ await score(
157
+ { traceId: runId, name: "correctness", value: 0.92, source: "EVAL" },
158
+ { endpoint: config.endpoint, headers: { Authorization: `Bearer ${token}` } },
159
+ );
160
+ ```
161
+
162
+ ### Trace-context propagation
163
+
164
+ `injectTraceparent(carrier, fields)` / `extractTraceparent(carrier)` use the W3C
165
+ Trace Context propagator (correctly handles `traceparent`/`tracestate` parsing,
166
+ versioning, and edge cases) — for bridging spans across service boundaries.
167
+
168
+ ### Other exports
169
+
170
+ `createApoTraceExporter`, `createApoSpanProcessor`, `buildApoAuthHeaders`,
171
+ `ApoSpanProcessor`, plus the option types (`ConfigureApoTelemetryOptions`,
172
+ `ApoTelemetryHandle`, `ApoTraceExporterOptions`, `ApoSpanProcessorOptions`,
173
+ `ApoTraceOptions`, `ScoreOptions`).
174
+
175
+ ## Agent-task evaluation — `@apo-ai/sdk/agent-task`
176
+
177
+ The product's primary surface: define an agent task and its checks, wire an
178
+ adapter to the agent under test, then run it and collect structured results.
179
+ Import from the subpath:
180
+
181
+ ```ts
182
+ import {
183
+ task,
184
+ defineAdapter,
185
+ runTask,
186
+ turn,
187
+ includes,
188
+ } from "@apo-ai/sdk/agent-task";
189
+ ```
190
+
191
+ ### Core building blocks
192
+
193
+ - **`task(id, { adapter, deliverables, … })`** — register the task definition
194
+ and return its adapter-typed `test`.
195
+ - **`defineAdapter({ initialize, startSession, collectDeliverables, cleanup })`**
196
+ — the contract between apo and the agent under test (init, run a session,
197
+ collect deliverables, tear down).
198
+ - **`turn(fn)`** — optionally define task-specific single- or multi-turn input.
199
+ - **`test(id, fn)`** — register a test through the scope returned by `task()`.
200
+ The callback receives `t` (flat, eve-style assertions over the run's flow)
201
+ and the task-selected deliverables, inferred from the adapter.
202
+ - **`runTask(task, adapter, options?)`** — execute a single task and return a
203
+ `TaskRunResult` (transcript + evaluation).
204
+ - **`loadTask(dir)` / `discoverAgentTaskDirs()`** — load tasks from disk.
205
+ - **`createAgentTaskTraceClient(config)`** — the adapter-side trace client
206
+ passed into runs; the auth token is supplied by the backend runner via
207
+ `APO_AUTH_TOKEN`.
208
+
209
+ ### Testing (`*.eval.ts`)
210
+
211
+ One `<task-id>.eval.ts` file holds the task definition, optional turn behavior, and code or
212
+ LLM-backed checks. Checks read both the run's **flow** (what the agent did) and
213
+ its **deliverables** (what it produced).
214
+ Checks are written with a flat `t` context and value matchers — the single way
215
+ to assert. Every assertion is recorded (no die-on-first), so each check reports
216
+ all of its failures.
217
+
218
+ ```ts
219
+ import { task, includes, satisfies } from "@apo-ai/sdk/agent-task";
220
+ import { myAdapter } from "./adapter";
221
+
222
+ const { test } = task("review-output", {
223
+ adapter: myAdapter,
224
+ deliverables: ["result", "stats"],
225
+ });
226
+
227
+ test("used-the-right-tools", (t) => {
228
+ t.calledTool("read_file"); // did it call this tool
229
+ t.notCalledTool(/delete_/); // did it avoid this tool
230
+ t.toolOrder(["read_file", "search_content"]); // tools ran in this order
231
+ t.maxToolCalls(30); // didn't flail
232
+ t.noFailedActions(); // nothing errored
233
+ });
234
+
235
+ test("output-correct", (t, { deliverables }) => {
236
+ // result and stats are inferred from myAdapter.collectDeliverables().
237
+ t.check(deliverables.result, includes("finding"));
238
+ t.check(deliverables.stats, satisfies((s: { turn_count: number }) => s.turn_count > 0, "has turns"));
239
+ });
240
+ ```
241
+
242
+ The global `test<TDeliverables>(...)` export remains available for
243
+ framework-agnostic checks and existing task files. Prefer the `test` returned
244
+ by `task()` for new task files: it requires no manual generic or cast and
245
+ exposes only the deliverables selected by that task.
246
+
247
+ **`t` — flow assertions** (read the run's trace, automatically captured):
248
+ `calledTool(name, opts?)`, `notCalledTool(name, opts?)`, `toolOrder([...])`,
249
+ `usedNoTools()`, `maxToolCalls(n)`, `noFailedActions()`, `loadedSkill(skill)`,
250
+ `calledSubagent(agent)`, `messageIncludes(token)`, `maxTurns(n)`,
251
+ `maxDurationMs(n)`, `assert(label, predicate)`.
252
+
253
+ `calledTool` / `notCalledTool` take optional constraints to match a call's
254
+ **input**, **output**, and **status** (and `count` for an exact number). Each
255
+ constraint accepts a literal (partial-deep for objects), a RegExp, or a
256
+ predicate:
257
+
258
+ ```ts
259
+ t.calledTool("read_file", { input: { path: "source.py" } }); // exact arg
260
+ t.calledTool("read_file", { input: { path: /^src\// }, count: 2 }); // regex + count
261
+ t.calledTool("compute", { output: (v) => v === 42 }); // predicate on output
262
+ t.calledTool("flakey_tool", { status: "error" }); // a failed call
263
+ ```
264
+
265
+ `t.assert(label, predicate)` is the escape hatch — assert any predicate over the
266
+ typed flow view when the named methods don't cover your case:
267
+
268
+ ```ts
269
+ t.assert("read before write", (flow) =>
270
+ flow.toolNamesInOrder.indexOf("read_file") < flow.toolNamesInOrder.indexOf("write_file"),
271
+ );
272
+ ```
273
+
274
+ **`t.check(value, matcher)` — value assertions** (deliverables, parsed JSON,
275
+ anything). Matchers: `includes(substring|RegExp)`, `equals(value)` (deep),
276
+ `matches(standardSchema)` (Zod/Valibot — anything with `safeParse`),
277
+ `satisfies(predicate, label)`, `similarity(expected, threshold = 0.8)` (fuzzy,
278
+ normalized Levenshtein).
279
+
280
+ For apo tasks the flow is built automatically from the run's trace (via
281
+ `createFlowTee`) — no extra wiring.
282
+
283
+ **`t.judge(value, instruction)` — LLM-backed assertions.** Configure the judge
284
+ with `runTask(dir, { judge: { model, apiKey?, baseURL? } })`, or set
285
+ `OPENROUTER_MODEL`/`OPENAI_MODEL` for the CLI runtime. Judge verdicts use the
286
+ same recorder and result format as code assertions, including model, prompt,
287
+ response, token usage, and latency metadata.
288
+
289
+ **Testing agents not built on apo's adapter.** Build a `Flow` from the
290
+ framework's own output with a normalizer, then run the same checks:
291
+
292
+ ```ts
293
+ import { runFlowChecks, test } from "@apo-ai/sdk/agent-task";
294
+ import { fromAISDK } from "@apo-ai/sdk/agent-task"; // or fromOpenAIMessages / fromAnthropicMessages
295
+
296
+ const flow = fromAISDK(myGenerateTextResult); // their framework → Flow
297
+ test("used-tools", (t) => { t.calledTool("read_file"); });
298
+ const results = await runFlowChecks({ flow, deliverables: { reply: myGenerateTextResult.text } });
299
+ ```
300
+
301
+ `fromOpenAIMessages(messages)`, `fromAnthropicMessages(messages)`, and
302
+ `fromAISDK(result)` each convert one source into the neutral `Flow` the checks
303
+ read — the plugs that make the testing framework reusable across agent stacks.
304
+
305
+ ### CLI / runtime
306
+
307
+ `parseAgentTaskCliArgs`, `runAgentTaskCli`, `loadTaskRuntime`, `runTaskDir`,
308
+ `AgentTaskRuntime` — used by the `apo` CLI and the backend's agent-task runner.
309
+
310
+ See the `apo` CLI (`pnpm apo`) and the agent-task specs for end-to-end usage.
311
+
312
+ ## License
313
+
314
+ MIT
@@ -0,0 +1,121 @@
1
+ import { A as AgentTaskTraceContext } from '../../tracing-DtbhYQV6.js';
2
+ import '../../types-C-nrDEVf.js';
3
+
4
+ /**
5
+ * Vercel AI SDK tracing integration for apo.
6
+ *
7
+ * Pass the result of {@link createApoTracer} to `generateText`'s
8
+ * `experimental_telemetry` option. The AI SDK already emits OpenTelemetry
9
+ * spans natively (e.g. `ai.toolCall`, `ai.generateText`); this tracer
10
+ * intercepts them and translates them into apo trace spans. The FlowTee
11
+ * picks up TOOL/GENERATION observations and builds the Flow that
12
+ * `t.calledTool`, `t.noFailedActions`, and `t.messageIncludes` read.
13
+ *
14
+ * The adapter author writes zero manual span code.
15
+ *
16
+ * @example
17
+ * ```ts
18
+ * import { generateText } from "ai";
19
+ * import { createApoTracer } from "@apo-ai/sdk/agent-task";
20
+ *
21
+ * async sendUserTurn(turn, { trace, parentSpanId }) {
22
+ * const result = await generateText({
23
+ * model, system, messages, tools,
24
+ * experimental_telemetry: createApoTracer({ trace, parentSpanId }),
25
+ * });
26
+ * return { response: result.text };
27
+ * }
28
+ * ```
29
+ *
30
+ * @module
31
+ */
32
+
33
+ type OTelAttributeValue = string | number | boolean | null | undefined | Array<string | number | boolean | null | undefined>;
34
+ type OTelAttributes = Record<string, OTelAttributeValue>;
35
+ interface OTelSpanContext {
36
+ traceId: string;
37
+ spanId: string;
38
+ traceFlags: number;
39
+ }
40
+ interface OTelSpanStatus {
41
+ code: number;
42
+ message?: string;
43
+ }
44
+ interface OTelException {
45
+ name: string;
46
+ message: string;
47
+ stack?: string;
48
+ }
49
+ /**
50
+ * Minimal `Span` implementation. The AI SDK calls:
51
+ * - `setAttributes` / `setAttribute` (tool result, response text)
52
+ * - `setStatus` / `recordException` (errors)
53
+ * - `end()` (finalises the span)
54
+ *
55
+ * Other methods (`addEvent`, `addLink`, `updateName`) are no-ops but must
56
+ * exist on the object for structural type compatibility with the OTel `Span`
57
+ * interface the AI SDK expects.
58
+ */
59
+ interface ApoSpan {
60
+ spanContext(): OTelSpanContext;
61
+ setAttribute(key: string, value: OTelAttributeValue): this;
62
+ setAttributes(attrs: OTelAttributes): this;
63
+ addEvent(name: string, attributesOrStartTime?: unknown, startTime?: unknown): this;
64
+ addLink(link: unknown): this;
65
+ addLinks(links: unknown[]): this;
66
+ setStatus(status: OTelSpanStatus): this;
67
+ updateName(name: string): this;
68
+ end(endTime?: unknown): void;
69
+ isRecording(): boolean;
70
+ recordException(exception: OTelException | string, time?: unknown): this;
71
+ }
72
+ /**
73
+ * Minimal `Tracer` implementation. The AI SDK's `recordSpan` uses
74
+ * `startActiveSpan(name, { attributes }, fn)`. We also implement
75
+ * `startSpan(name, opts)` for structural compatibility — it returns a span
76
+ * without invoking a callback, and the caller is responsible for `.end()`.
77
+ */
78
+ interface ApoTracer {
79
+ startSpan(name: string, options?: {
80
+ attributes?: OTelAttributes;
81
+ }): ApoSpan;
82
+ startActiveSpan<T>(name: string, options: {
83
+ attributes?: OTelAttributes;
84
+ }, fn: (span: ApoSpan) => Promise<T> | T): Promise<T>;
85
+ startActiveSpan<T>(name: string, options: {
86
+ attributes?: OTelAttributes;
87
+ }, context: unknown, fn: (span: ApoSpan) => Promise<T> | T): Promise<T>;
88
+ startActiveSpan<T>(name: string, fn: (span: ApoSpan) => Promise<T> | T): Promise<T>;
89
+ }
90
+ interface CreateApoTracerOptions {
91
+ /** The tee'd trace context from `sendUserTurn`'s second argument. */
92
+ trace: AgentTaskTraceContext;
93
+ /** The parent span id for this turn (from `sendUserTurn`'s context). */
94
+ parentSpanId?: string;
95
+ /** Optional task id, surfaced in span metadata. */
96
+ taskId?: string;
97
+ /** Optional turn number, surfaced in span metadata. */
98
+ turnNumber?: number;
99
+ }
100
+ /**
101
+ * Build a `Tracer` compatible with the Vercel AI SDK's
102
+ * `experimental_telemetry.tracer` option. The returned object satisfies the
103
+ * shape `{ isEnabled: true, tracer }` so it can be passed directly to
104
+ * `experimental_telemetry`.
105
+ *
106
+ * The AI SDK emits spans named `ai.generateText`, `ai.generateText.doGenerate`,
107
+ * and `ai.toolCall`. We translate the load-bearing ones:
108
+ *
109
+ * - `ai.toolCall` → a TOOL span (so `t.calledTool(name)` works)
110
+ * - `ai.generateText` → a GENERATION span (so `t.messageIncludes(text)` works)
111
+ * and error status → `t.noFailedActions()` catches it
112
+ *
113
+ * Other spans (`ai.generateText.doGenerate`, etc.) are ignored — the FlowTee
114
+ * only cares about TOOL/AGENT/GENERATION observation types.
115
+ */
116
+ declare function createApoTracer(options: CreateApoTracerOptions): {
117
+ isEnabled: true;
118
+ tracer: ApoTracer;
119
+ };
120
+
121
+ export { type CreateApoTracerOptions, createApoTracer };
@@ -0,0 +1,10 @@
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
+ createApoTracer
5
+ } from "../../chunk-HKLBPIB4.js";
6
+ import "../../chunk-HWZVL6TS.js";
7
+ export {
8
+ createApoTracer
9
+ };
10
+ //# sourceMappingURL=ai-sdk.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,67 @@
1
+ import { A as AgentTaskTraceContext } from '../../tracing-DtbhYQV6.js';
2
+ import '../../types-C-nrDEVf.js';
3
+
4
+ /**
5
+ * Anthropic JS SDK tracing integration for apo.
6
+ *
7
+ * Wraps an `Anthropic` client so `messages.create()` calls are
8
+ * automatically traced. Tool calls and generations are captured without
9
+ * any manual span code in the adapter.
10
+ *
11
+ * @example
12
+ * ```ts
13
+ * import Anthropic from "@anthropic-ai/sdk";
14
+ * import { createApoAnthropic } from "@apo-ai/sdk/agent-task";
15
+ *
16
+ * async sendUserTurn(turn, { trace, parentSpanId }) {
17
+ * const client = createApoAnthropic(
18
+ * new Anthropic({ apiKey }),
19
+ * { trace, parentSpanId, taskId: ctx.task.id, turnNumber }
20
+ * );
21
+ * const response = await client.messages.create({
22
+ * model: "claude-sonnet-4-20250514",
23
+ * max_tokens: 1024,
24
+ * messages: [{ role: "user", content: String(turn) }],
25
+ * tools: [...],
26
+ * });
27
+ * const text = response.content.filter(b => b.type === "text").map(b => b.text).join("");
28
+ * return { response: text };
29
+ * }
30
+ * ```
31
+ *
32
+ * @module
33
+ */
34
+
35
+ interface CreateApoAnthropicOptions {
36
+ /** The tee'd trace context from `sendUserTurn`'s second argument. */
37
+ trace: AgentTaskTraceContext;
38
+ /** The parent span id for this turn (from `sendUserTurn`'s context). */
39
+ parentSpanId?: string;
40
+ /** Optional task id, surfaced in span metadata. */
41
+ taskId?: string;
42
+ /** Optional turn number, surfaced in span metadata. */
43
+ turnNumber?: number;
44
+ }
45
+ /**
46
+ * Minimal structural shape of the Anthropic client we intercept.
47
+ */
48
+ interface AnthropicClientLike {
49
+ messages: {
50
+ create: (...args: any[]) => Promise<any>;
51
+ };
52
+ [key: string]: any;
53
+ }
54
+ /**
55
+ * Wrap an Anthropic client so `messages.create()` is traced.
56
+ * Returns a Proxy-wrapped client — call it exactly as you would the
57
+ * original. Non-streaming only; streaming responses pass through
58
+ * untraced.
59
+ *
60
+ * For SDKs that emit OpenTelemetry natively (Claude Agent SDK, Vercel AI
61
+ * SDK), prefer `configureApoTelemetry()` instead — no wrapper needed.
62
+ * This manual wrapper is for the raw `@anthropic-ai/sdk` package or
63
+ * custom clients that don't emit OTel on their own.
64
+ */
65
+ declare function createApoAnthropic<T extends AnthropicClientLike>(client: T, options: CreateApoAnthropicOptions): T;
66
+
67
+ export { type CreateApoAnthropicOptions, createApoAnthropic };
@@ -0,0 +1,10 @@
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
+ createApoAnthropic
5
+ } from "../../chunk-SZDSIPXC.js";
6
+ import "../../chunk-GDB6SDGN.js";
7
+ export {
8
+ createApoAnthropic
9
+ };
10
+ //# sourceMappingURL=anthropic.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,77 @@
1
+ import { A as AgentTaskTraceContext } from '../../tracing-DtbhYQV6.js';
2
+ import '../../types-C-nrDEVf.js';
3
+
4
+ /**
5
+ * OpenAI JS SDK tracing integration for apo.
6
+ *
7
+ * Wraps an `OpenAI` client so `chat.completions.create()` calls are
8
+ * automatically traced. Tool calls and generations are captured without
9
+ * any manual span code in the adapter.
10
+ *
11
+ * Uses a Proxy to intercept the `create` method, then emits GENERATION +
12
+ * TOOL spans through the trace context. The FlowTee picks these up and
13
+ * builds the Flow that `t.calledTool` reads.
14
+ *
15
+ * @example
16
+ * ```ts
17
+ * import OpenAI from "openai";
18
+ * import { createApoOpenAI } from "@apo-ai/sdk/agent-task";
19
+ *
20
+ * async sendUserTurn(turn, { trace, parentSpanId }) {
21
+ * const client = createApoOpenAI(
22
+ * new OpenAI({ apiKey, baseURL: "https://openrouter.ai/api/v1" }),
23
+ * { trace, parentSpanId, taskId: ctx.task.id, turnNumber }
24
+ * );
25
+ * const response = await client.chat.completions.create({
26
+ * model: "google/gemini-2.5-flash-lite",
27
+ * messages: [{ role: "user", content: String(turn) }],
28
+ * tools: [...],
29
+ * });
30
+ * return { response: response.choices[0].message.content ?? "" };
31
+ * }
32
+ * ```
33
+ *
34
+ * @module
35
+ */
36
+
37
+ interface CreateApoOpenAIOptions {
38
+ /** The tee'd trace context from `sendUserTurn`'s second argument. */
39
+ trace: AgentTaskTraceContext;
40
+ /** The parent span id for this turn (from `sendUserTurn`'s context). */
41
+ parentSpanId?: string;
42
+ /** Optional task id, surfaced in span metadata. */
43
+ taskId?: string;
44
+ /** Optional turn number, surfaced in span metadata. */
45
+ turnNumber?: number;
46
+ }
47
+ /**
48
+ * Minimal structural shape of the OpenAI client we need to intercept.
49
+ * We avoid importing `openai` at the type level so this module doesn't
50
+ * take a runtime dependency — the wrapper works with any client that has
51
+ * `chat.completions.create`.
52
+ *
53
+ * The `create` signature uses a broad type so the OpenAI SDK's overloaded
54
+ * `create` method (which has specific param types) is assignable to this.
55
+ */
56
+ interface OpenAIClientLike {
57
+ chat: {
58
+ completions: {
59
+ create: (...args: any[]) => Promise<any>;
60
+ };
61
+ };
62
+ [key: string]: any;
63
+ }
64
+ /**
65
+ * Wrap an OpenAI client so `chat.completions.create()` is traced.
66
+ * Returns a Proxy-wrapped client — call it exactly as you would the
67
+ * original. Non-streaming only; streaming responses pass through
68
+ * untraced.
69
+ *
70
+ * For SDKs that emit OpenTelemetry natively (OpenAI Agents SDK, Vercel AI
71
+ * SDK, Claude Agent SDK), prefer `configureApoTelemetry()` instead — no
72
+ * wrapper needed. This manual wrapper is for the raw `openai` package or
73
+ * custom clients that don't emit OTel on their own.
74
+ */
75
+ declare function createApoOpenAI<T extends OpenAIClientLike>(client: T, options: CreateApoOpenAIOptions): T;
76
+
77
+ export { type CreateApoOpenAIOptions, createApoOpenAI };
@@ -0,0 +1,10 @@
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
+ createApoOpenAI
5
+ } from "../../chunk-DT2LMB7O.js";
6
+ import "../../chunk-GDB6SDGN.js";
7
+ export {
8
+ createApoOpenAI
9
+ };
10
+ //# sourceMappingURL=openai.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}