From 66f314ee376ffd3b257efda45c45f94231a38b1d Mon Sep 17 00:00:00 2001 From: Vinicius Mello Date: Sat, 29 Aug 2026 15:20:48 -0300 Subject: [PATCH] feat(OPEN-11243): add GitHub Copilot SDK tracing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Trace agents built on the GitHub Copilot SDK (`@github/copilot-sdk`) to Openlayer. TypeScript counterpart to the Python integration, structurally mirroring it so the two stay comparable. import { traceCopilot } from "openlayer/lib/integrations/copilotSdk"; traceCopilot(); patches `CopilotClient.prototype.createSession`, so every session is traced with no change to the code that builds them. `openlayerEventHandler()` is the explicit alternative for callers who build sessions themselves. Both compose with a user-supplied `onEvent` and never replace it; an exception in either handler cannot break the other. Combining the two is safe: the patch defers to a caller-supplied Openlayer handler rather than adding a second collector, so mixing the quickstart with the per-session snippet cannot produce duplicate rows. Trace shape — one trace per `send()`: AGENT "GitHub Copilot" user prompt in, final answer out ├─ CHAT_COMPLETION "turn 0" model, provider, tokens, latency ├─ TOOL "bash" arguments in, result out ├─ AGENT "subagent: Explore Agent" a `task` dispatch │ ├─ CHAT_COMPLETION "turn 0" │ └─ TOOL "view" └─ CHAT_COMPLETION "turn 1" Architecture: buffer live, build deferred ----------------------------------------- `assistant.usage` — which carries every token count — is ephemeral and absent from `getEvents()`, so we must subscribe live. But Copilot fires tool calls *concurrently*, with completions arriving out of order, so building steps from the live callbacks would nest siblings inside one another. We buffer live and build the whole trace in one deterministic, correctly-nested pass at `session.idle`. Cost ---- Copilot's `cost` field is premium-request units, not dollars, so it is recorded as metadata. We emit provider+model and let Openlayer price it, mapping the model prefix to the real vendor — `llm-costs` has no `github` provider, so labelling it that way would silently yield $0. GitHub meters each call in AIU and ships its own per-token rates, which are the vendor's list prices scaled by exactly 100 (1 AIU = $0.01), verified on both an Anthropic and an OpenAI model. Each chat step records `copilot_metered_cost_usd` so the priced cost is checkable per row; on live traces the two agree to twelve decimal places. An unmapped model falls back to that figure rather than landing at $0. Packaging --------- New subpath export `./integrations/copilot-sdk`, with `@github/copilot-sdk` declared as an optional peerDependency (^1.0.11). The lockfile carries all platform binaries, so a Linux CI runner resolves. Tests ----- 28 unit tests over the same two captured sessions (converted to the camelCase shape this binding delivers) covering concurrent tools, subagent nesting, the apiCallId usage join, the token partition, handler composition, and the patch itself. Plus a live end-to-end test gated on OPENLAYER_COPILOT_LIVE_TEST=1. Example: examples/copilot-sdk-tracing.ts, verified running end to end. Related: openlayer-python (Python parity), openlayer-docs (docs page). Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01S48tdMHz7rjd7aJeZCkVic --- examples/copilot-sdk-tracing.ts | 148 +++ package.json | 10 + src/lib/integrations/copilotSdk.ts | 903 ++++++++++++++++++ src/lib/integrations/index.ts | 1 + tests/integrations/copilotSdk.live.test.ts | 76 ++ tests/integrations/copilotSdk.test.ts | 375 ++++++++ .../fixtures/copilotSdk/session_basic.jsonl | 55 ++ .../copilotSdk/session_tools_subagent.jsonl | 93 ++ yarn.lock | 174 +++- 9 files changed, 1834 insertions(+), 1 deletion(-) create mode 100644 examples/copilot-sdk-tracing.ts create mode 100644 src/lib/integrations/copilotSdk.ts create mode 100644 tests/integrations/copilotSdk.live.test.ts create mode 100644 tests/integrations/copilotSdk.test.ts create mode 100644 tests/integrations/fixtures/copilotSdk/session_basic.jsonl create mode 100644 tests/integrations/fixtures/copilotSdk/session_tools_subagent.jsonl diff --git a/examples/copilot-sdk-tracing.ts b/examples/copilot-sdk-tracing.ts new file mode 100644 index 0000000..136bf10 --- /dev/null +++ b/examples/copilot-sdk-tracing.ts @@ -0,0 +1,148 @@ +#!/usr/bin/env -S npx ts-node +/** + * Openlayer tracing for the GitHub Copilot SDK. + * + * Run with: + * OPENLAYER_API_KEY=... \ + * OPENLAYER_INFERENCE_PIPELINE_ID=... \ + * GITHUB_TOKEN=$(gh auth token) \ + * npx ts-node examples/copilot-sdk-tracing.ts + * + * Requires `@github/copilot-sdk` and a GitHub account with Copilot access. + */ +import * as fs from 'fs'; +import * as os from 'os'; +import * as path from 'path'; + +import { openlayerEventHandler, traceCopilot } from '../src/lib/integrations/copilotSdk'; + +// eslint-disable-next-line @typescript-eslint/no-require-imports +const { CopilotClient, approveAll, defineTool } = require('@github/copilot-sdk'); +// eslint-disable-next-line @typescript-eslint/no-require-imports +const { z } = require('zod'); + +/** A throwaway workspace so the agent has something real to look at. */ +function makeWorkspace(): string { + const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'openlayer-copilot-')); + fs.writeFileSync(path.join(dir, 'app.ts'), 'export const greet = (n: string) => `hi ${n}`;\n'); + fs.writeFileSync(path.join(dir, 'README.md'), '# Demo\n\nA tiny example project.\n'); + return dir; +} + +/** + * Scenario 1 — one line of setup traces every session. + * + * `traceCopilot()` patches `CopilotClient.prototype.createSession`, so you do + * not have to touch the code that builds sessions. + */ +async function basicSession() { + console.log('\n=== Scenario 1: one-line setup ==='); + traceCopilot(); + + const workspace = makeWorkspace(); + const client = new CopilotClient({ workingDirectory: workspace, logLevel: 'error' }); + await client.start(); + try { + const session = await client.createSession({ + workingDirectory: workspace, + onPermissionRequest: approveAll, + }); + const reply = await session.sendAndWait( + { prompt: 'List the files here with bash, then summarize the project in one sentence.' }, + 280_000, + ); + console.log('Assistant:', reply?.data?.content); + await session.disconnect(); + } finally { + await client.stop(); + } +} + +/** + * Scenario 2 — an explicit handler, a client-side tool, and a subagent. + * + * Use `openlayerEventHandler()` when you build sessions yourself and want to + * be explicit about which ones are traced. It composes with your own + * `onEvent`: pass both and each still receives every event. + */ +async function toolsAndSubagent() { + console.log('\n=== Scenario 2: custom tool + subagent dispatch ==='); + + const getWeather = defineTool('get_weather', { + description: 'Get the current weather for a city.', + parameters: z.object({ city: z.string() }), + handler: ({ city }: { city: string }) => `It is 22C and sunny in ${city}.`, + }); + + const workspace = makeWorkspace(); + const client = new CopilotClient({ workingDirectory: workspace, logLevel: 'error' }); + await client.start(); + try { + const session = await client.createSession({ + workingDirectory: workspace, + onPermissionRequest: approveAll, + tools: [getWeather], + // An explicit handler instead of the global patch. Passing both is safe -- + // traceCopilot() defers to a handler you supply rather than adding a + // second collector -- but one or the other is clearer. + onEvent: openlayerEventHandler({ truncateToolOutputChars: 4096 }), + }); + const reply = await session.sendAndWait( + { + prompt: + 'Do two things: call get_weather for Lisbon, and delegate to a subagent to ' + + 'read app.ts and summarize it.', + }, + 280_000, + ); + console.log('Assistant:', reply?.data?.content); + await session.disconnect(); + } finally { + await client.stop(); + } +} + +/** + * Scenario 3 — several sends on one session. + * + * Each `send()` becomes its own Openlayer trace, and all of them share the + * Copilot session id, so they group into a single session in the UI. + */ +async function multiTurnSession() { + console.log('\n=== Scenario 3: multi-turn session grouping ==='); + + const workspace = makeWorkspace(); + const client = new CopilotClient({ workingDirectory: workspace, logLevel: 'error' }); + await client.start(); + try { + const session = await client.createSession({ + workingDirectory: workspace, + onPermissionRequest: approveAll, + onEvent: openlayerEventHandler(), + }); + for (const prompt of ['What files are in this directory?', 'What does app.ts export?']) { + const reply = await session.sendAndWait({ prompt }, 280_000); + console.log(`Q: ${prompt}\nA: ${reply?.data?.content}\n`); + } + await session.disconnect(); + } finally { + await client.stop(); + } +} + +async function main() { + for (const key of ['OPENLAYER_API_KEY', 'OPENLAYER_INFERENCE_PIPELINE_ID']) { + if (!process.env[key]) { + console.error(`Missing ${key}. Traces will not be published.`); + } + } + await basicSession(); + await toolsAndSubagent(); + await multiTurnSession(); + console.log('\nDone — check your Openlayer inference pipeline for the traces.'); +} + +main().catch((err) => { + console.error(err); + process.exit(1); +}); diff --git a/package.json b/package.json index f7487d8..42d7e23 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,7 @@ "devDependencies": { "@anthropic-ai/claude-agent-sdk": "^0.2.111", "@arethetypeswrong/cli": "^0.17.0", + "@github/copilot-sdk": "^1.0.11", "@google/genai": "^2.13.0", "@langchain/community": "^1.1.29", "@langchain/core": "^1.1.49", @@ -95,6 +96,11 @@ "require": "./dist/lib/integrations/claudeAgentSdk.js", "types": "./dist/lib/integrations/claudeAgentSdk.d.ts" }, + "./integrations/copilot-sdk": { + "import": "./dist/lib/integrations/copilotSdk.mjs", + "require": "./dist/lib/integrations/copilotSdk.js", + "types": "./dist/lib/integrations/copilotSdk.d.ts" + }, "./*.mjs": { "default": "./dist/*.mjs" }, @@ -108,6 +114,7 @@ }, "peerDependencies": { "@anthropic-ai/claude-agent-sdk": "^0.2.111", + "@github/copilot-sdk": "^1.0.11", "@google/genai": ">=1 <3", "@langchain/community": ">=0.3.59 <2", "@langchain/core": ">=0.3.80 <2", @@ -128,6 +135,9 @@ }, "@langchain/langgraph": { "optional": true + }, + "@github/copilot-sdk": { + "optional": true } } } diff --git a/src/lib/integrations/copilotSdk.ts b/src/lib/integrations/copilotSdk.ts new file mode 100644 index 0000000..9c5e7d2 --- /dev/null +++ b/src/lib/integrations/copilotSdk.ts @@ -0,0 +1,903 @@ +/** + * Openlayer tracing integration for the GitHub Copilot SDK (TypeScript). + * + * The Copilot SDK (`@github/copilot-sdk`) drives the Copilot CLI over JSON-RPC + * and exposes a rich session event stream. This module subscribes to that + * stream and turns each `send()` into an Openlayer trace with nested steps for + * assistant turns, tool calls and subagents. + * + * Why we buffer instead of building steps live + * -------------------------------------------- + * `assistant.usage` -- which carries every token count and the premium-request + * figure -- is `ephemeral` and absent from `session.getEvents()`, so we have to + * listen live. But Copilot fires tool calls *concurrently*: three + * `tool.execution_start` events arrive before any completion, and the + * completions come back out of order. Driving step creation straight from the + * live callbacks would therefore nest sibling tools inside one another. We + * buffer live and build the whole trace in one deterministic, correctly-nested + * pass when the session goes idle. + * + * Trace shape (one trace per `send()`): + * + * ``` + * AGENT "GitHub Copilot" + * |-- CHAT_COMPLETION "turn 0" + * |-- TOOL "bash" + * |-- AGENT "subagent: Explore Agent" + * | |-- CHAT_COMPLETION "turn 0" + * | `-- TOOL "view" + * `-- CHAT_COMPLETION "turn 1" + * ``` + * + * See `docs/superpowers/specs/2026-08-27-github-copilot-sdk-integration-design.md`. + */ +import { StepType } from '../tracing/steps'; +import { _internalCreateStep } from '../tracing/tracer'; + +export const ROOT_STEP_NAME = 'GitHub Copilot'; + +/** Tunable per-integration configuration. */ +export interface CopilotConfig { + /** Inference pipeline ID. Falls back to `OPENLAYER_INFERENCE_PIPELINE_ID`. */ + inferencePipelineId?: string | undefined; + /** Max characters to keep from each tool output before truncation. */ + truncateToolOutputChars: number; + /** Whether to capture reasoning text into chat-step metadata. */ + captureReasoning: boolean; +} + +const DEFAULT_CONFIG: CopilotConfig = { + truncateToolOutputChars: 8192, + captureReasoning: true, +}; + +/** + * High-frequency events that carry no step-level meaning. Dropped at ingest so + * the buffer stays small -- a single session emits hundreds of these. + */ +const IGNORED_EVENT_TYPES = new Set([ + 'assistant.message_delta', + 'assistant.reasoning_delta', + 'assistant.streaming_delta', + 'assistant.tool_call_delta', + 'tool.execution_partial_result', + 'session.background_tasks_changed', +]); + +/** + * Copilot routes to several model families. The Openlayer cost service keys on + * the *real* provider, and Copilot's model ids match its slugs verbatim + * (verified: anthropic/claude-haiku-4.5 and openai/gpt-5.4 both resolve, while + * github/* returns "No cost data found"). Labelling these "github" would yield + * a silent $0, so an unrecognized prefix omits the provider entirely -- + * landing unpriced is recoverable, landing priced-wrong is not. + */ +const PROVIDER_PREFIXES: ReadonlyArray = [ + ['claude-', 'anthropic'], + ['gpt-', 'openai'], + ['o1', 'openai'], + ['o3', 'openai'], + ['o4', 'openai'], + ['gemini-', 'google'], + ['grok-', 'xai'], +]; + +// --------------------------------------------------------------------------- // +// Event accessors +// --------------------------------------------------------------------------- // + +function snakeToCamel(name: string): string { + return name.replace(/_([a-z0-9])/g, (_m, c) => c.toUpperCase()); +} + +/** + * Read a field tolerating snake_case and camelCase. + * + * The TypeScript binding yields `toolCallId`; keeping the tolerant accessor + * lets this file stay structurally identical to its Python counterpart and + * makes the recorded fixtures interchangeable. + */ +function field(data: any, name: string): any { + if (data === null || typeof data !== 'object') return undefined; + if (name in data) return data[name]; + return data[snakeToCamel(name)]; +} + +/** An event's `type` as a plain string (the binding may hand back an enum). */ +function eventType(event: any): string { + if (event === null || typeof event !== 'object') return ''; + const raw = event.type; + if (raw === null || raw === undefined) return ''; + const value = typeof raw === 'object' && 'value' in raw ? raw.value : raw; + return typeof value === 'string' ? value : String(value); +} + +function eventData(event: any): any { + if (event === null || typeof event !== 'object') return {}; + return event.data ?? {}; +} + +function envelope(event: any, name: string): any { + if (event === null || typeof event !== 'object') return undefined; + return field(event, name); +} + +/** ISO-8601 event timestamp to epoch milliseconds (the unit TS steps use). */ +function timestampMs(event: any): number | undefined { + const raw = envelope(event, 'timestamp'); + if (!raw) return undefined; + if (typeof raw === 'number') return raw; + const parsed = Date.parse(String(raw)); + return Number.isNaN(parsed) ? undefined : parsed; +} + +/** Cap oversized tool payloads; results can contain whole files. */ +function truncate(value: any, maxChars: number): any { + if (typeof value === 'string' && value.length > maxChars) { + return `${value.slice(0, maxChars)}…`; + } + return value; +} + +// --------------------------------------------------------------------------- // +// Mapping helpers +// --------------------------------------------------------------------------- // + +/** Map a Copilot model id to the real underlying provider slug. */ +export function providerForModel(model?: string | null): string | undefined { + if (!model) return undefined; + const lowered = String(model).toLowerCase(); + for (const [prefix, provider] of PROVIDER_PREFIXES) { + if (lowered.startsWith(prefix)) return provider; + } + return undefined; +} + +/** + * Build the non-overlapping token partition the cost backend prices. + * + * Copilot reports `inputTokens` as a *superset* that already contains + * `cacheReadTokens` and `cacheWriteTokens`. The backend sums a price per + * recognized key, so the granular categories must be broken out and subtracted + * from the base or cached tokens get charged twice. Reasoning stays folded into + * `output_tokens`, matching the convention in `langchainCallback`. + */ +export function usageDetails(usage: any): Record { + const inputTotal = Number(field(usage, 'input_tokens') ?? 0); + const outputTotal = Number(field(usage, 'output_tokens') ?? 0); + const cacheRead = Number(field(usage, 'cache_read_tokens') ?? 0); + const cacheWrite = Number(field(usage, 'cache_write_tokens') ?? 0); + + const details: Record = {}; + const entries: ReadonlyArray = [ + ['input_tokens', inputTotal - cacheRead - cacheWrite], + ['output_tokens', outputTotal], + ['cached_tokens', cacheRead], + ['cache_creation_tokens', cacheWrite], + ]; + for (const [key, value] of entries) { + if (value && value > 0) details[key] = value; + } + return details; +} + +/** + * GitHub meters every call in AIU ("AI Units") and reports the total on + * `copilot_usage.total_nano_aiu`. Decoding the per-token rates GitHub ships + * alongside it (`copilot_usage._token_details`) for `claude-haiku-4.5` gives + * 100 / 500 / 10 / 125 AIU per 1M input / output / cache-read / cache-write + * tokens -- exactly Anthropic's published list prices scaled by 100. So one AIU + * is one US cent, and `total_nano_aiu / 1e11` reproduced the priced cost of an + * observed call to twelve decimal places ($0.01675375 both ways). + * + * Confirmed across two vendors: `gpt-5-mini` bills 25 / 200 / 2.5 AIU per 1M + * input / output / cache-read tokens, which is OpenAI's $0.25 / $2.00 / $0.025 + * list pricing under the same 1 AIU = $0.01 constant. Live rows carry both + * figures and they agree to twelve decimal places. + * + * Still not proven for *every* vendor Copilot may route to, so this is used as a + * *fallback* for models we cannot map to a provider, and as a cross-check + * alongside the priced cost -- never in place of Openlayer's own pricing when + * the provider is known. + */ +const NANO_AIU_PER_USD = 1e11; + +/** GitHub's own metered value of a call, in USD, or undefined if unavailable. */ +export function meteredCostUsd(usage: any): number | undefined { + const copilotUsage = field(usage, 'copilot_usage'); + if (!copilotUsage || typeof copilotUsage !== 'object') return undefined; + const nanoAiu = field(copilotUsage, 'total_nano_aiu'); + if (!nanoAiu) return undefined; + const value = Number(nanoAiu); + return Number.isFinite(value) ? value / NANO_AIU_PER_USD : undefined; +} + +// --------------------------------------------------------------------------- // +// Buffered records +// --------------------------------------------------------------------------- // + +interface Interaction { + interactionId: string; + userPrompt: string; + events: any[]; + startTime: number; +} + +interface TurnRecord { + kind: 'turn'; + agentId?: string | undefined; + turnId: any; + model?: string | undefined; + startTime?: number | undefined; + endTime?: number | undefined; + output: string; + reasoning: string; + usage: any; + apiCallId?: string | undefined; + error?: Record | undefined; + parentToolCallId?: string | undefined; +} + +interface ToolRecord { + kind: 'tool'; + toolCallId: string; + name: string; + arguments?: any | undefined; + result?: any | undefined; + error?: any | undefined; + success?: boolean | undefined; + startTime?: number | undefined; + endTime?: number | undefined; + parentToolCallId?: string | undefined; + agentId?: string | undefined; + mcpServerName?: string | undefined; + isSubagent: boolean; + subagentName?: string | undefined; + subagentMetadata: Record; + permission?: string | undefined; +} + +type Record_ = TurnRecord | ToolRecord; + +// --------------------------------------------------------------------------- // +// Collector +// --------------------------------------------------------------------------- // + +/** + * Buffers a Copilot session's events and builds traces when it goes idle. + * One instance per session. + */ +export class CopilotTraceCollector { + readonly config: CopilotConfig; + sessionId?: string | undefined; + sessionModel?: string | undefined; + interactions = new Map(); + builtCount = 0; + + // Correlation tables. Needed because assistant.turn_end and assistant.usage + // carry no interactionId at all. + private turnToInteraction = new Map(); + private toolToInteraction = new Map(); + private apiCallToInteraction = new Map(); + private agentToInteraction = new Map(); + private currentInteractionId?: string | undefined; + + constructor(config: Partial = {}) { + this.config = { ...DEFAULT_CONFIG, ...config }; + } + + /** + * Entry point wired to `createSession({ onEvent })`. + * + * Must never throw: it runs inside the SDK's own event dispatch, and + * observability must not be able to break the customer's agent. + */ + handle = (event: any): void => { + try { + this.handleInner(event); + } catch (err) { + console.debug('Openlayer: failed to handle Copilot event', err); + } + }; + + /** Build any still-open interactions (e.g. on disconnect). */ + flush(): void { + try { + this.buildAll(); + } catch (err) { + console.debug('Openlayer: failed to flush Copilot traces', err); + } + } + + private handleInner(event: any): void { + const type = eventType(event); + if (!type || IGNORED_EVENT_TYPES.has(type)) return; + + const data = eventData(event); + + if (type === 'session.start') { + this.sessionId = field(data, 'session_id') ?? this.sessionId; + return; + } + if (type === 'session.model_change') { + this.sessionModel = field(data, 'model') ?? this.sessionModel; + return; + } + if (type === 'session.idle' || type === 'session.shutdown') { + // "The session went quiescent" -- not "this send finished". Two + // overlapping send() calls are serialized by Copilot and produce a single + // idle with both interactions open, so build them all. + this.buildAll(); + return; + } + + const agentId = envelope(event, 'agent_id'); + + if (type === 'user.message' && !agentId) { + // Root-agent user messages open an interaction. Subagents emit their own + // user.message; those belong to the dispatching interaction. + const interactionId = field(data, 'interaction_id') ?? `_auto_${this.interactions.size}`; + const interaction: Interaction = { + interactionId, + userPrompt: field(data, 'content') ?? '', + events: [event], + startTime: timestampMs(event) ?? Date.now(), + }; + this.interactions.set(interactionId, interaction); + this.currentInteractionId = interactionId; + return; + } + + const interactionId = this.route(data, event); + if (!interactionId) return; + const interaction = this.interactions.get(interactionId); + if (!interaction) return; + interaction.events.push(event); + this.rememberCorrelations(type, data, interactionId, event); + } + + /** + * Find the interaction an event belongs to. + * + * Order matters. `assistant.usage` carries no interactionId and no turnId, + * and its apiCallId is only learned from the `assistant.message` that arrives + * *after* it -- so it must be routable by parentToolCallId or agentId before + * any fallback. + */ + private route(data: any, event: any): string | undefined { + const explicit = field(data, 'interaction_id'); + if (explicit && this.interactions.has(explicit)) return explicit; + + const lookups: ReadonlyArray]> = [ + ['tool_call_id', this.toolToInteraction], + ['parent_tool_call_id', this.toolToInteraction], + ['api_call_id', this.apiCallToInteraction], + ]; + for (const [key, table] of lookups) { + const value = field(data, key); + if (value && table.has(value)) return table.get(value); + } + + const agentId = envelope(event, 'agent_id'); + if (agentId && this.agentToInteraction.has(agentId)) { + return this.agentToInteraction.get(agentId); + } + const turnKey = `${agentId ?? ''}::${field(data, 'turn_id')}`; + if (this.turnToInteraction.has(turnKey)) return this.turnToInteraction.get(turnKey); + + return this.currentInteractionId; + } + + private rememberCorrelations(type: string, data: any, interactionId: string, event: any): void { + const toolCallId = field(data, 'tool_call_id'); + if (toolCallId) this.toolToInteraction.set(toolCallId, interactionId); + const apiCallId = field(data, 'api_call_id'); + if (apiCallId) this.apiCallToInteraction.set(apiCallId, interactionId); + // subagent.started is the first event tying an agentId to an interaction, + // and it arrives before any of that subagent's own events. + if (type === 'subagent.started' && toolCallId) { + this.agentToInteraction.set(toolCallId, interactionId); + } + if (type === 'assistant.turn_start') { + const agentId = envelope(event, 'agent_id'); + this.turnToInteraction.set(`${agentId ?? ''}::${field(data, 'turn_id')}`, interactionId); + } + } + + // ----------------------------- assembly ----------------------------- // + + private buildAll(): void { + for (const interaction of Array.from(this.interactions.values())) { + if (interaction.events.length) this.buildInteraction(interaction); + } + this.interactions.clear(); + this.currentInteractionId = undefined; + } + + private assemble(interaction: Interaction): { + turns: Map; + tools: Map; + order: TurnRecord[]; + } { + const turns = new Map(); + const tools = new Map(); + const order: TurnRecord[] = []; + // assistant.usage arrives *before* the assistant.message it belongs to and + // carries no turnId, so park it by apiCallId until the message names the + // turn. Never join on adjacency. + const pendingUsage = new Map(); + + const turnKey = (agentId: any, turnId: any) => `${agentId ?? ''}::${turnId}`; + + for (const event of interaction.events) { + const type = eventType(event); + const data = eventData(event); + const agentId = envelope(event, 'agent_id'); + const ts = timestampMs(event); + const key = turnKey(agentId, field(data, 'turn_id')); + + switch (type) { + case 'assistant.turn_start': { + const turn: TurnRecord = { + kind: 'turn', + agentId, + turnId: field(data, 'turn_id'), + model: field(data, 'model'), + startTime: ts, + output: '', + reasoning: '', + usage: {}, + }; + turns.set(key, turn); + order.push(turn); + break; + } + case 'model.call_start': { + const turn = turns.get(key); + if (turn) { + turn.model = field(data, 'model') ?? turn.model; + turn.startTime = turn.startTime ?? ts; + } + break; + } + case 'assistant.usage': { + const apiCallId = field(data, 'api_call_id'); + if (apiCallId) pendingUsage.set(apiCallId, data); + break; + } + case 'assistant.message': { + let turn = turns.get(key); + if (!turn) { + turn = { + kind: 'turn', + agentId, + turnId: field(data, 'turn_id'), + startTime: ts, + output: '', + reasoning: '', + usage: {}, + }; + turns.set(key, turn); + order.push(turn); + } + turn.output += field(data, 'content') ?? ''; + turn.model = field(data, 'model') ?? turn.model; + turn.endTime = ts ?? turn.endTime; + turn.parentToolCallId = field(data, 'parent_tool_call_id'); + const apiCallId = field(data, 'api_call_id'); + turn.apiCallId = apiCallId; + const reasoning = field(data, 'reasoning_text'); + if (reasoning) turn.reasoning = reasoning; + // Join usage to message on apiCallId -- verified 1:1 across every + // turn, including inside subagents. + if (apiCallId && pendingUsage.has(apiCallId)) { + turn.usage = pendingUsage.get(apiCallId); + pendingUsage.delete(apiCallId); + } + break; + } + case 'assistant.reasoning': { + const turn = turns.get(key); + const text = field(data, 'text') ?? field(data, 'content'); + if (turn && text && !turn.reasoning) turn.reasoning = text; + break; + } + case 'assistant.turn_end': { + const turn = turns.get(key); + if (turn && ts) turn.endTime = ts; + break; + } + case 'model.call_failure': { + const turn = turns.get(key); + if (turn) { + turn.error = { + message: field(data, 'error_message'), + code: field(data, 'error_code'), + type: field(data, 'error_type'), + statusCode: field(data, 'status_code'), + }; + } + break; + } + case 'tool.execution_start': { + const toolCallId = field(data, 'tool_call_id'); + if (!toolCallId) break; + tools.set(toolCallId, { + kind: 'tool', + toolCallId, + name: field(data, 'tool_name') ?? 'tool', + arguments: field(data, 'arguments'), + startTime: ts, + parentToolCallId: field(data, 'parent_tool_call_id'), + agentId, + mcpServerName: field(data, 'mcp_server_name'), + isSubagent: false, + subagentMetadata: {}, + }); + break; + } + case 'tool.execution_complete': { + const tool = tools.get(field(data, 'tool_call_id')); + if (!tool) break; + tool.success = field(data, 'success'); + tool.error = field(data, 'error'); + tool.result = field(data, 'result'); + tool.endTime = ts; + break; + } + case 'subagent.started': { + const tool = tools.get(field(data, 'tool_call_id')); + if (!tool) break; + tool.isSubagent = true; + tool.subagentName = field(data, 'agent_display_name') ?? field(data, 'agent_name'); + Object.assign(tool.subagentMetadata, { + agent_name: field(data, 'agent_name'), + agent_description: field(data, 'agent_description'), + model: field(data, 'model'), + }); + break; + } + case 'subagent.completed': { + const tool = tools.get(field(data, 'tool_call_id')); + if (!tool) break; + Object.assign(tool.subagentMetadata, { + total_tokens: field(data, 'total_tokens'), + total_tool_calls: field(data, 'total_tool_calls'), + duration_ms: field(data, 'duration_ms'), + cancelled: field(data, 'cancelled'), + }); + break; + } + case 'permission.completed': { + const tool = tools.get(field(data, 'tool_call_id')); + if (tool) tool.permission = field(data, 'decision') ?? field(data, 'outcome'); + break; + } + default: + break; + } + } + + return { turns, tools, order }; + } + + // ----------------------------- building ----------------------------- // + + buildInteraction(interaction: Interaction): void { + const { tools, order } = this.assemble(interaction); + + // The root's output is the LAST root-agent assistant message. Openlayer + // builds a row's output from the root step, so an empty root silently + // yields an unusable row. + let finalOutput = ''; + for (let i = order.length - 1; i >= 0; i -= 1) { + const turn = order[i]!; + if (!turn.agentId && turn.output) { + finalOutput = turn.output; + break; + } + } + + // A record's parent is its parentToolCallId, else the tool call that + // dispatched its agent, else the root. Never parentId -- that is a + // chronological chain, not a tree. + const children = new Map(); + const parentOf = (record: Record_): string => { + if (record.parentToolCallId) return record.parentToolCallId; + if (record.agentId && tools.has(record.agentId)) return record.agentId; + return ''; + }; + const all: Record_[] = [...order, ...Array.from(tools.values())]; + for (const record of all) { + const parent = parentOf(record); + if (!children.has(parent)) children.set(parent, []); + children.get(parent)!.push(record); + } + for (const bucket of children.values()) { + bucket.sort((a, b) => (a.startTime ?? 0) - (b.startTime ?? 0)); + } + + const endTimes = all.map((r) => r.endTime).filter((t): t is number => !!t); + const rootEnd = endTimes.length ? Math.max(...endTimes) : undefined; + + const [root, endRoot] = _internalCreateStep( + ROOT_STEP_NAME, + StepType.AGENT, + { prompt: interaction.userPrompt }, + finalOutput, + { + copilot_session_id: this.sessionId, + copilot_interaction_id: interaction.interactionId, + model: this.sessionModel, + }, + interaction.startTime, + rootEnd ?? null, + this.config.inferencePipelineId, + ); + if (rootEnd) (root as any).log({ latency: rootEnd - interaction.startTime }); + this.emit(children, ''); + endRoot(); + + this.builtCount += 1; + } + + /** + * Recursively open and close steps in correct nesting order. + * + * Because this pass is synchronous and properly nested, the tracer's step + * stack yields the right tree -- the concurrency hazard was removed by + * deferring construction until every event was in hand. + */ + private emit(children: Map, parentKey: string): void { + for (const record of children.get(parentKey) ?? []) { + if (record.kind === 'turn') this.emitTurn(record); + else this.emitTool(record, children); + } + } + + private emitTurn(turn: TurnRecord): void { + const usage = turn.usage ?? {}; + const metadata: Record = { turn_id: turn.turnId }; + if (turn.agentId) metadata['agent_id'] = turn.agentId; + + const premium = field(usage, 'cost'); + if (premium !== undefined && premium !== null) { + // NOT dollars -- Copilot premium-request units, a flat per-model + // multiplier. Kept as metadata so the step's real cost is priced by + // Openlayer from provider+model instead. + metadata['copilot_premium_requests'] = premium; + } + const copilotUsage = field(usage, 'copilot_usage'); + const nanoAiu = copilotUsage ? field(copilotUsage, 'total_nano_aiu') : undefined; + if (nanoAiu !== undefined && nanoAiu !== null) metadata['copilot_nano_aiu'] = nanoAiu; + const meteredCost = meteredCostUsd(usage); + if (meteredCost !== undefined) { + // GitHub's own metered value of this call in USD. Recorded even when + // Openlayer prices the step, so the two figures can be compared. + metadata['copilot_metered_cost_usd'] = meteredCost; + } + for (const key of ['finish_reason', 'api_endpoint', 'service_request_id', 'initiator']) { + const value = field(usage, key); + if (value !== undefined && value !== null) metadata[`copilot_${key}`] = value; + } + if (turn.reasoning && this.config.captureReasoning) metadata['reasoning'] = turn.reasoning; + if (turn.error) metadata['error'] = turn.error; + + const details = usageDetails(usage); + const total = Object.values(details).reduce((a, b) => a + b, 0); + const name = turn.turnId !== undefined ? `turn ${turn.turnId}` : 'assistant turn'; + + const [step, endStep] = _internalCreateStep( + name, + StepType.CHAT_COMPLETION, + { prompt: [] }, + turn.output, + metadata, + turn.startTime ?? null, + turn.endTime ?? null, + this.config.inferencePipelineId, + ); + const provider = providerForModel(turn.model); + (step as any).log({ + model: turn.model ?? null, + provider: provider ?? null, + promptTokens: details['input_tokens'] ?? null, + completionTokens: details['output_tokens'] ?? null, + tokens: total || null, + usageDetails: Object.keys(details).length ? details : null, + }); + if (provider === undefined && meteredCost !== undefined) { + // Without a provider Openlayer cannot price the step, and an unpriced + // step reads as $0. GitHub's own metered figure is far better than + // nothing, so a model we have no mapping for still lands costed. + (step as any).log({ cost: meteredCost }); + } + if (turn.endTime && turn.startTime) (step as any).log({ latency: turn.endTime - turn.startTime }); + endStep(); + } + + private emitTool(tool: ToolRecord, children: Map): void { + const metadata: Record = { + tool_call_id: tool.toolCallId, + success: tool.success ?? null, + }; + if (tool.error) metadata['error'] = tool.error; + if (tool.mcpServerName) metadata['mcp_server_name'] = tool.mcpServerName; + if (tool.permission) metadata['permission'] = tool.permission; + + let stepType = StepType.TOOL; + let name = tool.name; + if (tool.isSubagent) { + stepType = StepType.AGENT; + name = `subagent: ${tool.subagentName ?? 'unknown'}`; + Object.assign(metadata, tool.subagentMetadata); + } + + const [step, endStep] = _internalCreateStep( + name, + stepType, + tool.arguments ?? null, + truncate(tool.result, this.config.truncateToolOutputChars), + metadata, + tool.startTime ?? null, + tool.endTime ?? null, + this.config.inferencePipelineId, + ); + if (tool.endTime && tool.startTime) (step as any).log({ latency: tool.endTime - tool.startTime }); + this.emit(children, tool.toolCallId); + endStep(); + } +} + +// --------------------------------------------------------------------------- // +// Public API +// --------------------------------------------------------------------------- // + +const OPENLAYER_HANDLER_FLAG = '__openlayerCopilotHandler'; + +/** True if `handler` was produced by {@link openlayerEventHandler}. */ +function isOpenlayerHandler(handler: any): handler is OpenlayerEventHandler { + return Boolean(handler && (handler as any)[OPENLAYER_HANDLER_FLAG]); +} + +/** Run both handlers; neither may break the other. */ +export function composeHandlers( + userHandler: ((event: any) => void) | undefined, + ourHandler: (event: any) => void, +): (event: any) => void { + return (event: any) => { + if (userHandler) { + try { + userHandler(event); + } catch (err) { + console.debug('Openlayer: user onEvent handler threw', err); + } + } + ourHandler(event); + }; +} + +/** + * Return an `onEvent` handler that traces one Copilot session. + * + * @example + * ```typescript + * import { openlayerEventHandler } from "openlayer/lib/integrations/copilotSdk"; + * const session = await client.createSession({ onEvent: openlayerEventHandler() }); + * ``` + */ +export interface OpenlayerEventHandler { + (event: any): void; + /** Publish any interaction that never reached `session.idle`. */ + flush(): void; + /** The underlying collector, exposed for advanced use. */ + collector: CopilotTraceCollector; +} + +export function openlayerEventHandler(config: Partial = {}): OpenlayerEventHandler { + const collector = new CopilotTraceCollector(config); + const handler = ((event: any) => collector.handle(event)) as OpenlayerEventHandler; + handler.flush = () => collector.flush(); + handler.collector = collector; + (handler as any)[OPENLAYER_HANDLER_FLAG] = true; + return handler; +} + +/** + * Flush any still-open interaction when the session is disconnected. + * + * `session.idle` is the normal trigger, but a session torn down mid-flight + * never emits it and the buffered work would otherwise be dropped silently. + * Flushing is idempotent: `buildAll` clears the buffer, so a disconnect after a + * normal idle publishes nothing extra. + */ +function wrapDisconnect(session: any, collector: CopilotTraceCollector): void { + const originalDisconnect = session?.disconnect; + if (typeof originalDisconnect !== 'function') return; + try { + session.disconnect = async (...args: any[]) => { + try { + collector.flush(); + } catch (err) { + console.debug('Openlayer: failed to flush on disconnect', err); + } + return originalDisconnect.apply(session, args); + }; + } catch (err) { + console.debug('Openlayer: could not wrap session.disconnect', err); + } +} + +let patched = false; +let originalCreateSession: ((...args: any[]) => any) | null = null; +let patchedClass: any = null; + +/** + * Patch an explicit `CopilotClient` class. Exposed as a testable seam so unit + * tests need not have `@github/copilot-sdk` installed. + */ +export function traceCopilotOn(clientClass: any, config: Partial = {}): void { + if (patched) return; + originalCreateSession = clientClass.prototype.createSession; + patchedClass = clientClass; + const original = originalCreateSession!; + + clientClass.prototype.createSession = async function (sessionConfig: any = {}) { + const existing = sessionConfig?.onEvent; + if (isOpenlayerHandler(existing)) { + // The caller already passed an `openlayerEventHandler()`. Adding a second + // collector would build the same interaction twice and publish duplicate + // rows -- and mixing the two entry points is easy to do by following the + // quickstart and then the "trace specific sessions" snippet. Defer to + // theirs. + const session = await original.call(this, sessionConfig); + wrapDisconnect(session, existing.collector); + return session; + } + const handler = openlayerEventHandler(config); + const composed = composeHandlers(existing, handler); + const session = await original.call(this, { ...sessionConfig, onEvent: composed }); + wrapDisconnect(session, handler.collector); + return session; + }; + patched = true; +} + +/** + * Enable Openlayer tracing for every GitHub Copilot SDK session. + * + * Patches `CopilotClient.prototype.createSession` so each session gets an + * Openlayer event handler, composed with any `onEvent` the caller supplies. + * Idempotent. + * + * Requires `@github/copilot-sdk >= 1.0.11` to be installed. + * + * @example + * ```typescript + * import { traceCopilot } from "openlayer/lib/integrations/copilotSdk"; + * traceCopilot(); + * ``` + */ +export function traceCopilot(config: Partial = {}): void { + if (patched) return; + let sdk: any; + try { + // eslint-disable-next-line @typescript-eslint/no-require-imports + sdk = require('@github/copilot-sdk'); + } catch { + throw new Error( + '@github/copilot-sdk is required for Copilot SDK tracing. ' + + 'Install with: npm install @github/copilot-sdk', + ); + } + traceCopilotOn(sdk.CopilotClient, config); +} + +/** Undo {@link traceCopilot}. Primarily for tests. */ +export function untraceCopilot(): void { + if (!patched || !patchedClass || !originalCreateSession) return; + patchedClass.prototype.createSession = originalCreateSession; + patched = false; + patchedClass = null; + originalCreateSession = null; +} diff --git a/src/lib/integrations/index.ts b/src/lib/integrations/index.ts index cf4a65c..0f76f22 100644 --- a/src/lib/integrations/index.ts +++ b/src/lib/integrations/index.ts @@ -1,5 +1,6 @@ export * from './bedrockAgentTracer'; export * from './claudeAgentSdk'; +export * from './copilotSdk'; export * from './googleGenAiTracer'; export * from './langchainCallback'; export * from './openAiTracer'; diff --git a/tests/integrations/copilotSdk.live.test.ts b/tests/integrations/copilotSdk.live.test.ts new file mode 100644 index 0000000..7c42b3b --- /dev/null +++ b/tests/integrations/copilotSdk.live.test.ts @@ -0,0 +1,76 @@ +/** + * Live end-to-end test for the GitHub Copilot SDK integration. + * + * Opt-in is explicit rather than keyed on GITHUB_TOKEN alone: that variable is + * commonly exported by developers and by CI steps that have nothing to do with + * Copilot, and an installation token has no Copilot access -- so keying on it + * would turn a normal test run into a five-minute live session that then fails + * on auth. Run with: + * OPENLAYER_COPILOT_LIVE_TEST=1 GITHUB_TOKEN=$(gh auth token) \ + * npx jest tests/integrations/copilotSdk.live.test.ts + */ +import * as fs from 'fs'; +import * as os from 'os'; +import * as path from 'path'; + +import { ROOT_STEP_NAME, openlayerEventHandler } from '../../src/lib/integrations/copilotSdk'; +import { getCurrentTrace } from '../../src/lib/tracing/tracer'; + +const describeLive = process.env['OPENLAYER_COPILOT_LIVE_TEST'] === '1' ? describe : describe.skip; + +describeLive('Copilot SDK live', () => { + jest.setTimeout(300_000); + + it('produces a trace with priced chat steps and a real tool call', async () => { + // eslint-disable-next-line @typescript-eslint/no-require-imports + const { CopilotClient, approveAll } = require('@github/copilot-sdk'); + + const workspace = fs.mkdtempSync(path.join(os.tmpdir(), 'ol-copilot-')); + fs.writeFileSync(path.join(workspace, 'hello.ts'), "console.log('hello');\n"); + fs.writeFileSync(path.join(workspace, 'notes.txt'), 'some notes\n'); + + const client = new CopilotClient({ workingDirectory: workspace, logLevel: 'error' }); + await client.start(); + try { + const session = await client.createSession({ + workingDirectory: workspace, + onPermissionRequest: approveAll, + onEvent: openlayerEventHandler(), + }); + await session.sendAndWait( + { prompt: 'Run `ls` with bash and tell me how many files there are, in one sentence.' }, + 280_000, + ); + await session.disconnect(); + } finally { + await client.stop(); + } + + const trace = getCurrentTrace(); + expect(trace).toBeTruthy(); + const root = trace!.toJSON()[0] as any; + + expect(root.type).toBe('agent'); + expect(root.name).toBe(ROOT_STEP_NAME); + // The root's output is what becomes the row's output column. + expect(typeof root.output).toBe('string'); + expect(root.output.trim().length).toBeGreaterThan(0); + expect(root.inputs.prompt).toMatch(/^Run `ls`/); + expect(root.metadata['copilot_session_id']).toBeTruthy(); + + const chats = root.steps.filter((s: any) => s.type === 'chat_completion'); + expect(chats.length).toBeGreaterThan(0); + for (const chat of chats) { + expect(chat.model).toBeTruthy(); + // A real provider slug is what lets Openlayer price the call; "github" + // would silently yield $0. + expect(['anthropic', 'openai', 'google', 'xai']).toContain(chat.provider); + expect(chat.cost).toBeNull(); + } + expect(chats.some((c: any) => (c.usageDetails?.['output_tokens'] ?? 0) > 0)).toBe(true); + + const tools = root.steps.filter((s: any) => s.type === 'tool'); + expect(tools.length).toBeGreaterThan(0); + expect(tools.some((t: any) => t.name === 'bash')).toBe(true); + }); +}); diff --git a/tests/integrations/copilotSdk.test.ts b/tests/integrations/copilotSdk.test.ts new file mode 100644 index 0000000..7043a5e --- /dev/null +++ b/tests/integrations/copilotSdk.test.ts @@ -0,0 +1,375 @@ +/** + * Unit tests for the GitHub Copilot SDK integration. + * + * The fixtures are real captured sessions (trimmed of base64 blobs and the 24KB + * CLI system prompt), converted to the camelCase shape the TypeScript binding + * delivers. They exercise the actual wire format rather than an assumption. + */ +import * as fs from 'fs'; +import * as path from 'path'; + +import { + CopilotTraceCollector, + ROOT_STEP_NAME, + composeHandlers, + openlayerEventHandler, + meteredCostUsd, + providerForModel, + traceCopilotOn, + untraceCopilot, + usageDetails, +} from '../../src/lib/integrations/copilotSdk'; +import { getCurrentTrace } from '../../src/lib/tracing/tracer'; + +const FIXTURES = path.join(__dirname, 'fixtures', 'copilotSdk'); + +function loadFixture(name: string): any[] { + return fs + .readFileSync(path.join(FIXTURES, name), 'utf8') + .split('\n') + .filter((line) => line.trim()) + .map((line) => JSON.parse(line)); +} + +function runFixture(name: string): any { + const collector = new CopilotTraceCollector(); + for (const event of loadFixture(name)) { + collector.handle(event); + } + const trace = getCurrentTrace(); + if (!trace) throw new Error('no trace was produced'); + return trace.toJSON()[0]; +} + +function find(steps: any[], predicate: (s: any) => boolean): any { + for (const step of steps) { + if (predicate(step)) return step; + const found = find(step.steps || [], predicate); + if (found) return found; + } + return null; +} + +function walkNames(step: any): string[] { + return [step.name, ...(step.steps || []).flatMap(walkNames)]; +} + +describe('Copilot SDK integration', () => { + describe('provider mapping', () => { + it('maps from the model prefix and never labels it "github"', () => { + // Verified against llm-costs.openlayer.com: anthropic/claude-haiku-4.5 and + // openai/gpt-5.4 resolve; github/* returns "No cost data found". + expect(providerForModel('claude-haiku-4.5')).toBe('anthropic'); + expect(providerForModel('gpt-5.4')).toBe('openai'); + expect(providerForModel('o3-mini')).toBe('openai'); + expect(providerForModel('gemini-2.5-pro')).toBe('google'); + // Unknown prefixes omit provider rather than guess -- unpriced beats wrong. + expect(providerForModel('some-future-model')).toBeUndefined(); + expect(providerForModel('')).toBeUndefined(); + expect(providerForModel(undefined)).toBeUndefined(); + }); + }); + + describe('token partition', () => { + it('subtracts cache categories so the partition does not overlap', () => { + // Observed live: inputTokens=12509 already contains cacheWriteTokens=12499, + // and Copilot's own _token_details reported an input count of 10. + const details = usageDetails({ + inputTokens: 12509, + outputTokens: 224, + cacheWriteTokens: 12499, + cacheReadTokens: 0, + reasoningTokens: 143, + }); + expect(details['input_tokens']).toBe(10); + expect(details['output_tokens']).toBe(224); + expect(details['cache_creation_tokens']).toBe(12499); + expect(details['cached_tokens']).toBeUndefined(); + // reasoning stays folded into output_tokens, matching langchainCallback + expect(details['reasoning_tokens']).toBeUndefined(); + }); + + it('handles cache reads and stays exact', () => { + const details = usageDetails({ + inputTokens: 12754, + outputTokens: 122, + cacheWriteTokens: 249, + cacheReadTokens: 12499, + }); + expect(details['input_tokens']).toBe(6); + expect(details['cached_tokens']).toBe(12499); + expect(details['cache_creation_tokens']).toBe(249); + const total = Object.values(details).reduce((a, b) => a + b, 0); + expect(total).toBe(12754 + 122); + }); + }); + + describe('trace shape', () => { + it('emits chat steps with tokens and a priced provider', () => { + const root = runFixture('session_basic.jsonl'); + const chats = root.steps.filter((s: any) => s.type === 'chat_completion'); + expect(chats).toHaveLength(3); + for (const chat of chats) { + expect(chat.model).toBe('claude-haiku-4.5'); + expect(chat.provider).toBe('anthropic'); + expect(chat.usageDetails['output_tokens']).toBeGreaterThan(0); + // Copilot's premium-request figure must NOT be published as cost; + // leaving it unset lets Openlayer price from provider+model. + expect(chat.cost).toBeNull(); + expect(chat.metadata['copilot_premium_requests']).toBe(0.33); + } + }); + + it('sets the root output to the final assistant message', () => { + // Openlayer builds a row's output from the root step; an empty root + // silently produces an unusable row. + const root = runFixture('session_tools_subagent.jsonl'); + expect(root.type).toBe('agent'); + expect(root.name).toBe(ROOT_STEP_NAME); + expect(typeof root.output).toBe('string'); + expect(root.output).toContain('Lisbon'); + expect(root.inputs.prompt).toMatch(/^Do these three things/); + }); + + it('keeps concurrent tool calls as siblings rather than nesting them', () => { + // Three tool.execution_start fire before any completion and the + // completions arrive out of order; a step-stack design would nest them. + const root = runFixture('session_tools_subagent.jsonl'); + const topLevelNames = root.steps.map((s: any) => s.name); + expect(topLevelNames).toContain('bash'); + expect(topLevelNames).toContain('get_weather'); + }); + + it('nests a subagent dispatch as an AGENT step with its own work inside', () => { + const root = runFixture('session_tools_subagent.jsonl'); + const subagent = find( + root.steps, + (s: any) => s.type === 'agent' && s.name.toLowerCase().includes('explore'), + ); + expect(subagent).not.toBeNull(); + expect(subagent.steps.some((s: any) => s.type === 'chat_completion')).toBe(true); + expect(subagent.steps.some((s: any) => s.name === 'view')).toBe(true); + }); + + it('captures tool arguments and failures', () => { + const root = runFixture('session_basic.jsonl'); + const bash = find(root.steps, (s: any) => s.name === 'bash'); + expect(bash).not.toBeNull(); + expect(bash.inputs.command).toBe('ls -lhS'); + // this fixture's bash call was permission-denied + expect(bash.metadata.success).toBe(false); + expect(JSON.stringify(bash.metadata.error).toLowerCase()).toContain('denied'); + }); + + it('never creates a step from a delta event', () => { + const root = runFixture('session_basic.jsonl'); + expect(walkNames(root).some((n) => n.includes('delta'))).toBe(false); + }); + + it('records the Copilot session id for session grouping', () => { + const root = runFixture('session_basic.jsonl'); + expect(root.metadata['copilot_session_id']).toBeTruthy(); + }); + }); + + describe('handler composition', () => { + it('still delivers every event to a user-supplied handler', () => { + const seen: any[] = []; + const composed = composeHandlers((e: any) => seen.push(e), openlayerEventHandler()); + composed({ type: 'session.start', data: { sessionId: 's1' } }); + expect(seen).toHaveLength(1); + }); + + it('survives a throwing user handler', () => { + const composed = composeHandlers(() => { + throw new Error('customer bug'); + }, openlayerEventHandler()); + expect(() => composed({ type: 'session.start', data: { sessionId: 's1' } })).not.toThrow(); + }); + + it('never throws on a malformed event', () => { + const collector = new CopilotTraceCollector(); + for (const junk of [null, undefined, {}, { type: 'user.message' }, 42]) { + expect(() => collector.handle(junk)).not.toThrow(); + } + }); + }); + + describe('traceCopilot patching', () => { + // The one-line entry point the docs lead with. Driven through an explicit + // class seam so the tests need not have @github/copilot-sdk installed. + class FakeClient { + static lastOnEvent: ((e: any) => void) | undefined; + declare disconnect: () => Promise; + async createSession(config: any = {}): Promise { + FakeClient.lastOnEvent = config.onEvent; + return { disconnect: async () => undefined }; + } + } + + let original: any; + beforeEach(() => { + original = FakeClient.prototype.createSession; + FakeClient.lastOnEvent = undefined; + }); + afterEach(() => { + untraceCopilot(); + FakeClient.prototype.createSession = original; + }); + + it('patches createSession and is idempotent', async () => { + traceCopilotOn(FakeClient); + const patchedOnce = FakeClient.prototype.createSession; + expect(patchedOnce).not.toBe(original); + traceCopilotOn(FakeClient); + expect(FakeClient.prototype.createSession).toBe(patchedOnce); + }); + + it('preserves a user-supplied onEvent', async () => { + const seen: any[] = []; + traceCopilotOn(FakeClient); + await new FakeClient().createSession({ onEvent: (e: any) => seen.push(e) }); + + const composed = FakeClient.lastOnEvent!; + expect(composed).toBeDefined(); + composed({ type: 'session.start', data: { sessionId: 's1' } }); + expect(seen).toHaveLength(1); + }); + + it('traces sessions created after patching', async () => { + traceCopilotOn(FakeClient); + await new FakeClient().createSession(); + const handler = FakeClient.lastOnEvent!; + for (const event of loadFixture('session_basic.jsonl')) handler(event); + + const root = getCurrentTrace()!.toJSON()[0] as any; + expect(root.name).toBe(ROOT_STEP_NAME); + }); + + it('untraceCopilot restores the original', () => { + traceCopilotOn(FakeClient); + untraceCopilot(); + expect(FakeClient.prototype.createSession).toBe(original); + }); + }); + + describe('flush', () => { + it('publishes an interaction that never went idle', () => { + // A session torn down mid-flight must not silently drop its buffer. + const collector = new CopilotTraceCollector(); + for (const event of loadFixture('session_basic.jsonl')) { + const t = typeof event.type === 'string' ? event.type : ''; + if (t === 'session.idle' || t === 'session.shutdown') continue; + collector.handle(event); + } + expect(collector.builtCount).toBe(0); + collector.flush(); + expect(collector.builtCount).toBe(1); + }); + + it('does not double-publish after a normal idle', () => { + const collector = new CopilotTraceCollector(); + for (const event of loadFixture('session_basic.jsonl')) collector.handle(event); + expect(collector.builtCount).toBe(1); + collector.flush(); + expect(collector.builtCount).toBe(1); + }); + + it('is exposed on the event handler', () => { + const handler = openlayerEventHandler(); + expect(typeof handler.flush).toBe('function'); + expect(handler.collector).toBeInstanceOf(CopilotTraceCollector); + }); + }); + + describe('metered cost', () => { + // GitHub meters each call in AIU; its per-token rates for claude-haiku-4.5 + // are Anthropic's list prices scaled by exactly 100, so total_nano_aiu/1e11 + // reproduces the priced cost to 12 decimal places. + it('converts total_nano_aiu to USD', () => { + const usage = { copilotUsage: { totalNanoAiu: 1675375000.0 } }; + expect(meteredCostUsd(usage)).toBeCloseTo(0.01675375, 9); + }); + + it('is undefined without AIU data', () => { + expect(meteredCostUsd({})).toBeUndefined(); + expect(meteredCostUsd({ copilotUsage: {} })).toBeUndefined(); + expect(meteredCostUsd({ copilotUsage: { totalNanoAiu: 0 } })).toBeUndefined(); + }); + + it('records the metered figure but lets Openlayer price a known provider', () => { + const root = runFixture('session_basic.jsonl'); + const chat = root.steps[0]; + expect(chat.provider).toBe('anthropic'); + expect(chat.cost).toBeNull(); + expect(chat.metadata['copilot_metered_cost_usd']).toBeCloseTo(0.01675375, 9); + }); + + it('falls back to the metered cost for an unmapped model', () => { + // A model we have no prefix for must land priced, not at $0. + const events = loadFixture('session_basic.jsonl'); + for (const event of events) { + if (event.data && 'model' in event.data) event.data.model = 'some-future-model-9'; + } + const collector = new CopilotTraceCollector(); + for (const event of events) collector.handle(event); + + const chat = (getCurrentTrace()!.toJSON()[0] as any).steps[0]; + expect(chat.provider).toBeNull(); + expect(chat.cost).toBeCloseTo(0.01675375, 9); + }); + }); + + describe('metered cost, live shapes', () => { + it('reads copilot_usage when it is a class instance, not a plain object', () => { + class CopilotUsage { + constructor(public totalNanoAiu: number) {} + } + expect(meteredCostUsd({ copilotUsage: new CopilotUsage(1675375000.0) })).toBeCloseTo(0.01675375, 9); + }); + + it('holds for a second vendor', () => { + // Verified live on gpt-5-mini: GitHub bills 25/200/2.5 AIU per 1M + // input/output/cache-read -- OpenAI's $0.25/$2.00/$0.025 list prices. + const expected = 449 * 0.25e-6 + 9216 * 0.025e-6 + 107 * 2.0e-6; + expect(meteredCostUsd({ copilotUsage: { totalNanoAiu: 55665000.0 } })).toBeCloseTo(expected, 9); + }); + }); + + describe('double-tracing guard', () => { + // Mixing traceCopilot() with an explicit openlayerEventHandler() must not + // publish the interaction twice. Both are documented entry points, so a + // reader following the quickstart and then the "trace specific sessions" + // snippet ends up with both active on the same session. + class GuardClient { + static lastOnEvent: ((e: any) => void) | undefined; + async createSession(config: any = {}): Promise { + GuardClient.lastOnEvent = config.onEvent; + return { disconnect: async () => undefined }; + } + } + + afterEach(() => untraceCopilot()); + + it('defers to a caller-supplied Openlayer handler', async () => { + traceCopilotOn(GuardClient); + const mine = openlayerEventHandler(); + await new GuardClient().createSession({ onEvent: mine }); + // The patch must hand back the caller's handler untouched, not a + // composition wrapping a second collector. + expect(GuardClient.lastOnEvent).toBe(mine); + + for (const event of loadFixture('session_basic.jsonl')) GuardClient.lastOnEvent!(event); + expect(mine.collector.builtCount).toBe(1); + }); + + it('still wraps a non-Openlayer handler', async () => { + traceCopilotOn(GuardClient); + const userHandler = jest.fn(); + await new GuardClient().createSession({ onEvent: userHandler }); + expect(GuardClient.lastOnEvent).not.toBe(userHandler); + GuardClient.lastOnEvent!({ type: 'session.start', data: { sessionId: 's1' } }); + expect(userHandler).toHaveBeenCalledTimes(1); + }); + }); +}); diff --git a/tests/integrations/fixtures/copilotSdk/session_basic.jsonl b/tests/integrations/fixtures/copilotSdk/session_basic.jsonl new file mode 100644 index 0000000..e31d4ad --- /dev/null +++ b/tests/integrations/fixtures/copilotSdk/session_basic.jsonl @@ -0,0 +1,55 @@ +{"agentId": null, "data": {"alreadyInUse": false, "context": {"baseCommit": null, "branch": null, "cwd": "/private/tmp/claude-501/-Users-vini-Workspace-Openlayer-integrations-sdks/b3978e0d-127c-460e-869e-357293ac3d63/scratchpad/copilot-probe/ws", "gitRoot": null, "headCommit": null, "hostType": null, "pendingGitContext": null, "repository": null, "repositoryHost": null}, "contextTier": null, "copilotVersion": "1.0.79", "detachedFromSpawningParentSessionId": null, "githubMcpToolConfig": null, "producer": "copilot-agent", "reasoningEffort": null, "reasoningSummary": null, "remoteSteerable": false, "selectedModel": null, "sessionId": "60c4e8f8-b3c1-4d59-a721-f79b63af74f7", "sessionLimits": null, "startTime": "2026-08-27 12:18:55.025000+00:00", "verbosity": null, "version": 1}, "ephemeral": null, "id": "7f0d0183-cb64-4e04-a5cf-06825c1821e7", "parentId": null, "rawType": null, "timestamp": "2026-08-27 12:18:55.041000+00:00", "type": "session.start"} +{"agentId": null, "data": {"bypassPermissionsDisabled": false, "clientManaged": false, "deviceManaged": false, "failClosed": false, "managedKeys": [], "permissionsAllowIntersected": null, "serverManaged": false, "settings": null, "source": "none"}, "ephemeral": true, "id": "04172e2c-b1fb-4c02-9b91-2c2fa44aee1d", "parentId": "7f0d0183-cb64-4e04-a5cf-06825c1821e7", "rawType": null, "timestamp": "2026-08-27 12:18:55.050000+00:00", "type": "session.managed_settings_resolved"} +{"agentId": null, "data": {}, "ephemeral": true, "id": "8c61a2da-6b83-4d11-9d9b-c28c497c27de", "parentId": "7f0d0183-cb64-4e04-a5cf-06825c1821e7", "rawType": null, "timestamp": "2026-08-27 12:18:55.053000+00:00", "type": "pending_messages.modified"} +{"agentId": null, "data": {"cause": null, "contextTier": null, "newModel": "auto", "previousModel": null, "previousReasoningEffort": null, "previousReasoningSummary": null, "previousVerbosity": null, "reasoningEffort": null, "reasoningSummary": null, "verbosity": null}, "ephemeral": null, "id": "80d5f4be-5bf8-401d-ad11-ba163862a9f3", "parentId": "7f0d0183-cb64-4e04-a5cf-06825c1821e7", "rawType": null, "timestamp": "2026-08-27 12:18:56.049000+00:00", "type": "session.model_change"} +{"agentId": null, "data": {"skills": [{"argumentHint": null, "commandName": "customize-cloud-agent", "description": "Skill for customizing the Copilot cloud agent (formerly known as Copilot coding agent) environment, including copilot-setup-steps.yml configuration, preinstalling tools and dependencies, runners, and settings. Use when the user mentions copilot-setup-steps, copilot setup steps, or wants to configure the cloud agent environment.", "enabled": true, "name": "customize-cloud-agent", "path": "/Users/vini/Library/Caches/copilot/pkg/darwin-arm64/1.0.79/builtin/customize-cloud-agent/SKILL.md", "source": "builtin", "userInvocable": false}, {"argumentHint": null, "commandName": "github-pr-media", "description": "Upload an image or video to GitHub's user attachments API and embed it in a pull request description or comment. Use when asked to add screenshots, diagrams, recordings, or other media to a PR or GitHub comment.", "enabled": true, "name": "github-pr-media", "path": "/Users/vini/Library/Caches/copilot/pkg/darwin-arm64/1.0.79/builtin/github-pr-media/SKILL.md", "source": "builtin", "userInvocable": false}]}, "ephemeral": true, "id": "12634645-3331-439d-a5dc-107b89087947", "parentId": "80d5f4be-5bf8-401d-ad11-ba163862a9f3", "rawType": null, "timestamp": "2026-08-27 12:18:56.223000+00:00", "type": "session.skills_loaded"} +{"agentId": null, "data": {"availableModels": ["claude-haiku-4.5", "gpt-5-mini"], "candidateModels": ["claude-haiku-4.5", "gpt-5-mini"], "categoryScores": {"codeGen": 0.0097, "debugging": 0.0015, "reasoning": 0.0321, "toolUse": 0.0139}, "chosenModel": "claude-haiku-4.5", "chosenShortfall": 0.0, "confidence": 0.97, "endToEndLatencyMs": 227.0, "fallback": false, "fallbackReason": null, "hasImage": false, "predictedLabel": "no_reasoning", "reasoningBucket": "low", "routerLatencyMs": 63.0, "routingMethod": "hydra", "stickyOverride": false}, "ephemeral": null, "id": "4cdcda66-ef59-497d-b21d-c2e6eabcc763", "parentId": "80d5f4be-5bf8-401d-ad11-ba163862a9f3", "rawType": null, "timestamp": "2026-08-27 12:18:56.448000+00:00", "type": "session.auto_mode_resolved"} +{"agentId": null, "data": {"content": "You are the GitHub Copilot CLI, a terminal assistant built by GitHub. You are an interactive CLI tool that helps users with software engineering tasks.\n\n# Tone and style\n* When providing output or exp\u2026", "interactionId": "8b56955c-c140-4d44-837e-500dc7029967", "metadata": null, "name": null, "role": "system"}, "ephemeral": null, "id": "de620d97-2c17-41a7-9f02-5f0f9ff4fc6c", "parentId": "4cdcda66-ef59-497d-b21d-c2e6eabcc763", "rawType": null, "timestamp": "2026-08-27 12:18:56.461000+00:00", "type": "system.message"} +{"agentId": null, "data": {"model": "claude-haiku-4.5"}, "ephemeral": true, "id": "29fbf204-9a82-4cde-95ba-f6a093b5bccb", "parentId": "de620d97-2c17-41a7-9f02-5f0f9ff4fc6c", "rawType": null, "timestamp": "2026-08-27 12:18:56.462000+00:00", "type": "session.tools_updated"} +{"agentId": null, "data": {"agentMode": null, "attachments": [], "content": "List the files in this directory, then read the largest one and tell me in one sentence what it contains.", "delivery": "idle", "interactionId": "8b56955c-c140-4d44-837e-500dc7029967", "isAutopilotContinuation": null, "nativeDocumentPathFallbackPaths": null, "parentAgentTaskId": "9fd8b79d-f716-47e8-a3aa-5646c90fdc4c", "source": null, "supportedNativeDocumentMimeTypes": [], "transformedContent": "2026-08-27T09:18:56.465-03:00\n\nList the files in this directory, then read the largest one and tell me in one sentence what it contains.\n\n\nAvailable tables: todos, todo_deps\n"}, "ephemeral": null, "id": "d053fd78-7d16-48b4-bc8a-9ebebc9ce4cd", "parentId": "de620d97-2c17-41a7-9f02-5f0f9ff4fc6c", "rawType": null, "timestamp": "2026-08-27 12:18:56.465000+00:00", "type": "user.message"} +{"agentId": null, "data": {"title": "List the files in this directory, then read the largest one and tell me in one sentence what it contains."}, "ephemeral": true, "id": "14cc91e4-500c-4296-9c04-ac52d86a5d67", "parentId": "d053fd78-7d16-48b4-bc8a-9ebebc9ce4cd", "rawType": null, "timestamp": "2026-08-27 12:18:56.468000+00:00", "type": "session.title_changed"} +{"agentId": null, "data": {"interactionId": "8b56955c-c140-4d44-837e-500dc7029967", "model": null, "turnId": "0"}, "ephemeral": null, "id": "07045487-b0d9-40dd-be37-e592ac006435", "parentId": "d053fd78-7d16-48b4-bc8a-9ebebc9ce4cd", "rawType": null, "timestamp": "2026-08-27 12:18:56.483000+00:00", "type": "assistant.turn_start"} +{"agentId": null, "data": {"conversationTokens": 78, "currentTokens": 10491, "isInitial": true, "messagesLength": 3, "systemTokens": 5225, "tokenLimit": 128000, "toolDefinitionsTokens": 5188}, "ephemeral": true, "id": "2d910e31-f4e7-461a-be2d-f368eea112a3", "parentId": "07045487-b0d9-40dd-be37-e592ac006435", "rawType": null, "timestamp": "2026-08-27 12:18:56.484000+00:00", "type": "session.usage_info"} +{"agentId": null, "data": {"_previous_response_id": null, "model": "claude-haiku-4.5", "turnId": "0"}, "ephemeral": true, "id": "5c8af4e3-1552-41d0-a8e4-4c6052e9db20", "parentId": "07045487-b0d9-40dd-be37-e592ac006435", "rawType": null, "timestamp": "2026-08-27 12:18:56.487000+00:00", "type": "model.call_start"} +{"agentId": null, "data": {"totalResponseSizeBytes": 14}, "ephemeral": true, "id": "667079c4-ef38-4c9d-92e1-79a1de3904c6", "parentId": "07045487-b0d9-40dd-be37-e592ac006435", "rawType": null, "timestamp": "2026-08-27 12:18:57.666000+00:00", "type": "assistant.streaming_delta"} +{"agentId": null, "data": {"deltaContent": "The user wants", "reasoningId": "c920d2ed-6265-4189-933e-81c4ca76af3b"}, "ephemeral": true, "id": "5044512f-64aa-448d-a974-19a268236a82", "parentId": "07045487-b0d9-40dd-be37-e592ac006435", "rawType": null, "timestamp": "2026-08-27 12:18:57.667000+00:00", "type": "assistant.reasoning_delta"} +{"agentId": null, "data": {"totalResponseSizeBytes": 158}, "ephemeral": true, "id": "868b0080-eb16-487e-b02c-2562b186d7a1", "parentId": "07045487-b0d9-40dd-be37-e592ac006435", "rawType": null, "timestamp": "2026-08-27 12:18:58.277000+00:00", "type": "assistant.streaming_delta"} +{"agentId": null, "data": {"deltaContent": " me to:\n1. List the files in the current directory\n2. Find the largest one\n3. Read it\n4. Describe what it contains in one sentence\n\nLet me start", "reasoningId": "c920d2ed-6265-4189-933e-81c4ca76af3b"}, "ephemeral": true, "id": "59af88fb-fc51-4857-ab55-b3b12a45948e", "parentId": "07045487-b0d9-40dd-be37-e592ac006435", "rawType": null, "timestamp": "2026-08-27 12:18:58.277000+00:00", "type": "assistant.reasoning_delta"} +{"agentId": null, "data": {"totalResponseSizeBytes": 275}, "ephemeral": true, "id": "0cfb2d6f-b4d6-4976-b06f-7acee2b1584c", "parentId": "07045487-b0d9-40dd-be37-e592ac006435", "rawType": null, "timestamp": "2026-08-27 12:18:58.278000+00:00", "type": "assistant.streaming_delta"} +{"agentId": null, "data": {"deltaContent": " by listing the files in the current directory. According to the environment context, I'm in: /private/tmp/claude-501", "reasoningId": "c920d2ed-6265-4189-933e-81c4ca76af3b"}, "ephemeral": true, "id": "120514e1-584e-4e3a-bc5a-21d0e0605152", "parentId": "07045487-b0d9-40dd-be37-e592ac006435", "rawType": null, "timestamp": "2026-08-27 12:18:58.278000+00:00", "type": "assistant.reasoning_delta"} +{"agentId": null, "data": {"inputDelta": "{\"co", "toolCallId": "toolu_01FU6XYF6G4memQfhA8qW55F", "toolName": "bash", "toolType": null}, "ephemeral": true, "id": "bf28992f-626f-4da9-8f17-8ae1a6330920", "parentId": "07045487-b0d9-40dd-be37-e592ac006435", "rawType": null, "timestamp": "2026-08-27 12:19:00.114000+00:00", "type": "assistant.tool_call_delta"} +{"agentId": null, "data": {"inputDelta": "mmand\":", "toolCallId": "toolu_01FU6XYF6G4memQfhA8qW55F", "toolName": "bash", "toolType": null}, "ephemeral": true, "id": "36af4f68-9405-4052-81ac-0bb932069273", "parentId": "07045487-b0d9-40dd-be37-e592ac006435", "rawType": null, "timestamp": "2026-08-27 12:19:00.114000+00:00", "type": "assistant.tool_call_delta"} +{"agentId": null, "data": {"inputDelta": " \"ls ", "toolCallId": "toolu_01FU6XYF6G4memQfhA8qW55F", "toolName": "bash", "toolType": null}, "ephemeral": true, "id": "0bf872b7-3227-4cec-bbf7-949535ff84a7", "parentId": "07045487-b0d9-40dd-be37-e592ac006435", "rawType": null, "timestamp": "2026-08-27 12:19:00.115000+00:00", "type": "assistant.tool_call_delta"} +{"agentId": null, "data": {"_available_tool_count": 16, "_num_tool_calls": 1, "_tool_counts": {"bash": 1}, "_tool_token_count": 5188, "apiCallId": "msg_011CeTEvNdFGjEND3RsV9GSv", "apiEndpoint": "/v1/messages", "cacheExpiresAt": "2026-08-27 12:23:56.500000+00:00", "cacheReadTokens": 0, "cacheWriteTokens": 12499, "contentFilterTriggered": false, "copilotUsage": {"_token_details": [{"batchSize": 1000000, "costPerBatch": 100000000000, "tokenCount": 10, "tokenType": "input"}, {"batchSize": 1000000, "costPerBatch": 10000000000, "tokenCount": 0, "tokenType": "cache_read"}, {"batchSize": 1000000, "costPerBatch": 125000000000, "tokenCount": 12499, "tokenType": "cache_write"}, {"batchSize": 1000000, "costPerBatch": 500000000000, "tokenCount": 224, "tokenType": "output"}], "totalNanoAiu": 1675375000.0}, "cost": 0.33, "duration": "0:00:03.625000", "finishReason": "tool_calls", "initiator": "user", "inputTokens": 12509, "interTokenLatency": "0:00:00.128785", "interactionType": "conversation-agent", "model": "claude-haiku-4.5", "outputTokens": 224, "parentToolCallId": null, "providerCallId": "29E8:3AC232:11AD842:1495100:6A902B30", "reasoningEffort": null, "reasoningTokens": 143, "rte": true, "serviceRequestId": "e0bb44ce-ebc4-4841-8abb-35f4cf782ec4", "timeToFirstToken": "0:00:01.178403"}, "ephemeral": true, "id": "eacb7e74-71cc-476c-8889-3a8f27b2aa6c", "parentId": "07045487-b0d9-40dd-be37-e592ac006435", "rawType": null, "timestamp": "2026-08-27 12:19:00.126000+00:00", "type": "assistant.usage"} +{"agentId": null, "data": {"apiCallId": "msg_011CeTEvNdFGjEND3RsV9GSv", "chunkCount": null, "chunkIndex": null, "citations": null, "clientRequestId": "00000-7dc0aaea-2628-405f-b886-42f9208d7a13", "content": "", "interactionId": "8b56955c-c140-4d44-837e-500dc7029967", "messageId": "a656af25-8d8c-4a46-9010-f7cf47557ee4", "model": "claude-haiku-4.5", "outputTokens": 224, "parentToolCallId": null, "phase": null, "reasoningText": "The user wants me to:\n1. List the files in the current directory\n2. Find the largest one\n3. Read it\n4. Describe what it contains in one sentence\n\nLet me start by listing the files in the current directory. According to the environment context, I'm in: /private/tmp/claude-501/-Users-vini-Workspace-Openlayer-integrations-sdks/b3978e0d-127c-460e-869e-357293ac3d63/scratchpad/copilot-probe/ws\n\nI'll use bash to list files and find the largest one.", "requestId": "29E8:3AC232:11AD842:1495100:6A902B30", "rte": true, "serverTools": null, "serviceRequestId": "e0bb44ce-ebc4-4841-8abb-35f4cf782ec4", "toolRequests": [{"arguments": {"command": "ls -lhS", "description": "List files by size (largest first)"}, "intentionSummary": "List files by size (largest first)", "mcpServerName": null, "mcpToolName": null, "name": "bash", "toolCallId": "toolu_01FU6XYF6G4memQfhA8qW55F", "toolTitle": null, "type": "function"}], "turnId": "0"}, "ephemeral": null, "id": "53ab4340-b370-4b15-86c5-86b97c512aea", "parentId": "07045487-b0d9-40dd-be37-e592ac006435", "rawType": null, "timestamp": "2026-08-27 12:19:00.129000+00:00", "type": "assistant.message"} +{"agentId": null, "data": {"content": "The user wants me to:\n1. List the files in the current directory\n2. Find the largest one\n3. Read it\n4. Describe what it contains in one sentence\n\nLet me start by listing the files in the current directory. According to the environment context, I'm in: /private/tmp/claude-501/-Users-vini-Workspace-Openlayer-integrations-sdks/b3978e0d-127c-460e-869e-357293ac3d63/scratchpad/copilot-probe/ws\n\nI'll use bash to list files and find the largest one.", "reasoningId": "c920d2ed-6265-4189-933e-81c4ca76af3b", "rte": true}, "ephemeral": true, "id": "72a8546c-0c0c-434a-8993-f7eac249265e", "parentId": "53ab4340-b370-4b15-86c5-86b97c512aea", "rawType": null, "timestamp": "2026-08-27 12:19:00.130000+00:00", "type": "assistant.reasoning"} +{"agentId": null, "data": {"arguments": {"command": "ls -lhS", "description": "List files by size (largest first)"}, "displayVerbatim": null, "mcpServerName": null, "mcpToolName": null, "model": "claude-haiku-4.5", "parentToolCallId": null, "rte": true, "shellToolInfo": {"displayCommand": null, "hasWriteFileRedirection": false, "possiblePaths": []}, "toolCallId": "toolu_01FU6XYF6G4memQfhA8qW55F", "toolDescription": null, "toolName": "bash", "turnId": "0"}, "ephemeral": null, "id": "70ae0565-704b-46b7-a1e0-1cc5b397f8ad", "parentId": "53ab4340-b370-4b15-86c5-86b97c512aea", "rawType": null, "timestamp": "2026-08-27 12:19:00.131000+00:00", "type": "tool.execution_start"} +{"agentId": null, "data": {}, "ephemeral": true, "id": "4301bc46-3ca7-44ac-9704-3b730a7ca5f1", "parentId": "70ae0565-704b-46b7-a1e0-1cc5b397f8ad", "rawType": null, "timestamp": "2026-08-27 12:19:00.138000+00:00", "type": "session.background_tasks_changed"} +{"agentId": null, "data": {}, "ephemeral": true, "id": "0d641c48-0fbc-484e-babb-f337b805a89b", "parentId": "70ae0565-704b-46b7-a1e0-1cc5b397f8ad", "rawType": null, "timestamp": "2026-08-27 12:19:00.138000+00:00", "type": "session.background_tasks_changed"} +{"agentId": null, "data": {}, "ephemeral": true, "id": "45962801-ce47-4add-9529-0cc8467e3d05", "parentId": "70ae0565-704b-46b7-a1e0-1cc5b397f8ad", "rawType": null, "timestamp": "2026-08-27 12:19:00.142000+00:00", "type": "session.background_tasks_changed"} +{"agentId": null, "data": {"error": {"code": "denied", "message": "Permission denied and could not request permission from user"}, "interactionId": "8b56955c-c140-4d44-837e-500dc7029967", "isUserRequested": null, "mcpMeta": null, "model": "claude-haiku-4.5", "parentToolCallId": null, "result": null, "rte": true, "sandboxed": null, "success": false, "toolCallId": "toolu_01FU6XYF6G4memQfhA8qW55F", "toolDescription": null, "toolTelemetry": {"properties": {"shellErrorCategory": "permission_denied"}}, "turnId": "0"}, "ephemeral": null, "id": "cf384e22-5c36-4fe5-9f9e-e171886a82b2", "parentId": "70ae0565-704b-46b7-a1e0-1cc5b397f8ad", "rawType": null, "timestamp": "2026-08-27 12:19:00.146000+00:00", "type": "tool.execution_complete"} +{"agentId": null, "data": {"model": null, "turnId": "0"}, "ephemeral": null, "id": "aedc2996-01a8-4395-9c3c-86c1b7116bf2", "parentId": "cf384e22-5c36-4fe5-9f9e-e171886a82b2", "rawType": null, "timestamp": "2026-08-27 12:19:00.167000+00:00", "type": "assistant.turn_end"} +{"agentId": null, "data": {"interactionId": "8b56955c-c140-4d44-837e-500dc7029967", "model": null, "turnId": "1"}, "ephemeral": null, "id": "d024549c-38c3-4b31-bdd8-ab445fd808c6", "parentId": "aedc2996-01a8-4395-9c3c-86c1b7116bf2", "rawType": null, "timestamp": "2026-08-27 12:19:00.169000+00:00", "type": "assistant.turn_start"} +{"agentId": null, "data": {"conversationTokens": 336, "currentTokens": 10749, "isInitial": false, "messagesLength": 5, "systemTokens": 5225, "tokenLimit": 128000, "toolDefinitionsTokens": 5188}, "ephemeral": true, "id": "c5c9c65a-a07f-451d-ae58-afaca4b0aa43", "parentId": "d024549c-38c3-4b31-bdd8-ab445fd808c6", "rawType": null, "timestamp": "2026-08-27 12:19:00.172000+00:00", "type": "session.usage_info"} +{"agentId": null, "data": {"_previous_response_id": null, "model": "claude-haiku-4.5", "turnId": "1"}, "ephemeral": true, "id": "2a94a917-907b-4bcb-9b66-379a4594dea1", "parentId": "d024549c-38c3-4b31-bdd8-ab445fd808c6", "rawType": null, "timestamp": "2026-08-27 12:19:00.175000+00:00", "type": "model.call_start"} +{"agentId": null, "data": {"messageId": "372bf886-57c5-47a1-b8ba-6f91d49f63a0", "phase": null}, "ephemeral": true, "id": "bfcafdf4-e10d-43f7-b5a3-1507f9424f19", "parentId": "d024549c-38c3-4b31-bdd8-ab445fd808c6", "rawType": null, "timestamp": "2026-08-27 12:19:01.306000+00:00", "type": "assistant.message_start"} +{"agentId": null, "data": {"deltaContent": "Let", "messageId": "372bf886-57c5-47a1-b8ba-6f91d49f63a0", "parentToolCallId": null}, "ephemeral": true, "id": "e21dd773-eeb0-4ed3-ac1d-35c1d001b4c1", "parentId": "d024549c-38c3-4b31-bdd8-ab445fd808c6", "rawType": null, "timestamp": "2026-08-27 12:19:01.306000+00:00", "type": "assistant.message_delta"} +{"agentId": null, "data": {"deltaContent": " me try using the", "messageId": "372bf886-57c5-47a1-b8ba-6f91d49f63a0", "parentToolCallId": null}, "ephemeral": true, "id": "0ebd151e-b40c-4cc2-94ad-d4ff41fff077", "parentId": "d024549c-38c3-4b31-bdd8-ab445fd808c6", "rawType": null, "timestamp": "2026-08-27 12:19:01.307000+00:00", "type": "assistant.message_delta"} +{"agentId": null, "data": {"deltaContent": " view", "messageId": "372bf886-57c5-47a1-b8ba-6f91d49f63a0", "parentToolCallId": null}, "ephemeral": true, "id": "01120c1a-b10d-4ca7-bc71-0eaafc527bfc", "parentId": "d024549c-38c3-4b31-bdd8-ab445fd808c6", "rawType": null, "timestamp": "2026-08-27 12:19:01.307000+00:00", "type": "assistant.message_delta"} +{"agentId": null, "data": {"_available_tool_count": 16, "_num_tool_calls": 1, "_tool_counts": {"view": 1}, "_tool_token_count": 5188, "apiCallId": "msg_011CeTEve3hKaz8wn5VCvcKi", "apiEndpoint": "/v1/messages", "cacheExpiresAt": "2026-08-27 12:24:00.185000+00:00", "cacheReadTokens": 12499, "cacheWriteTokens": 249, "contentFilterTriggered": false, "copilotUsage": {"_token_details": [{"batchSize": 1000000, "costPerBatch": 100000000000, "tokenCount": 6, "tokenType": "input"}, {"batchSize": 1000000, "costPerBatch": 10000000000, "tokenCount": 12499, "tokenType": "cache_read"}, {"batchSize": 1000000, "costPerBatch": 125000000000, "tokenCount": 249, "tokenType": "cache_write"}, {"batchSize": 1000000, "costPerBatch": 500000000000, "tokenCount": 122, "tokenType": "output"}], "totalNanoAiu": 217715000.0}, "cost": 0.33, "duration": "0:00:01.944000", "finishReason": "tool_calls", "initiator": "agent", "inputTokens": 12754, "interTokenLatency": "0:00:00.025412", "interactionType": "conversation-agent", "model": "claude-haiku-4.5", "outputTokens": 122, "parentToolCallId": null, "providerCallId": "29E8:3AC232:11AE5F5:14960C9:6A902B34", "reasoningEffort": null, "reasoningTokens": 0, "rte": true, "serviceRequestId": "e2ff792e-9b20-43ed-a6c5-37f901ed10b5", "timeToFirstToken": "0:00:01.131452"}, "ephemeral": true, "id": "330e53a0-f3c6-48c2-ae2d-1497b43c02a2", "parentId": "d024549c-38c3-4b31-bdd8-ab445fd808c6", "rawType": null, "timestamp": "2026-08-27 12:19:02.129000+00:00", "type": "assistant.usage"} +{"agentId": null, "data": {"apiCallId": "msg_011CeTEve3hKaz8wn5VCvcKi", "chunkCount": null, "chunkIndex": null, "citations": null, "clientRequestId": "00000-e35fd329-4333-4b36-8264-b70c3ad1735a", "content": "Let me try using the view tool instead:", "interactionId": "8b56955c-c140-4d44-837e-500dc7029967", "messageId": "372bf886-57c5-47a1-b8ba-6f91d49f63a0", "model": "claude-haiku-4.5", "outputTokens": 122, "parentToolCallId": null, "phase": null, "reasoningText": "The user wants me to:\n1. List the files in the current directory\n2. Find the largest one\n3. Read it\n4. Describe what it contains in one sentence\n\nLet me start by listing the files in the current directory. According to the environment context, I'm in: /private/tmp/claude-501/-Users-vini-Workspace-Openlayer-integrations-sdks/b3978e0d-127c-460e-869e-357293ac3d63/scratchpad/copilot-probe/ws\n\nI'll use bash to list files and find the largest one.", "requestId": "29E8:3AC232:11AE5F5:14960C9:6A902B34", "rte": true, "serverTools": null, "serviceRequestId": "e2ff792e-9b20-43ed-a6c5-37f901ed10b5", "toolRequests": [{"arguments": {"path": "/private/tmp/claude-501/-Users-vini-Workspace-Openlayer-integrations-sdks/b3978e0d-127c-460e-869e-357293ac3d63/scratchpad/copilot-probe/ws"}, "intentionSummary": "view the file at /private/tmp/claude-501/-Users-vini-Workspace-Openlayer-integrations-sdks/b3978e0d-127c-460e-869e-357293ac3d63/scratchpad/copilot-probe/ws.", "mcpServerName": null, "mcpToolName": null, "name": "view", "toolCallId": "toolu_01XGaT85UjmjwdjBvSUyq4pR", "toolTitle": null, "type": "function"}], "turnId": "1"}, "ephemeral": null, "id": "5926bc39-1a73-4aab-82fd-ab266b057180", "parentId": "d024549c-38c3-4b31-bdd8-ab445fd808c6", "rawType": null, "timestamp": "2026-08-27 12:19:02.132000+00:00", "type": "assistant.message"} +{"agentId": null, "data": {"content": "The user wants me to:\n1. List the files in the current directory\n2. Find the largest one\n3. Read it\n4. Describe what it contains in one sentence\n\nLet me start by listing the files in the current directory. According to the environment context, I'm in: /private/tmp/claude-501/-Users-vini-Workspace-Openlayer-integrations-sdks/b3978e0d-127c-460e-869e-357293ac3d63/scratchpad/copilot-probe/ws\n\nI'll use bash to list files and find the largest one.", "reasoningId": "EtMFCrIBCBEYAipAJxE97+DjjDVs+bGpHa8dQ5VSPOiiCUTaNEFSDl8DtAClc+NOxKQ2705W5y9y/9pgDBuTFT+O+zKldneiyuvr+zIZY2xhdWRlLWhhaWt1LTQtNS0yMDI1MTAwMTgAQgh0aGlua2luZ1okY2VkMWY5OGUtMGI1MS00NjEwLTgyODItNGU1ZDg4Mzg0NTc0chAFJi2jM86AcGV3hjaN37r2iAEBqAG01sDUBrABAhIMF1ZrovH4Ic5Eh0jCGgzf7CUQ+Pi+9vSJjCsiMOY64NBjwtdHREJ9AdnWhwd6RbBs3vPGdFR5EGslesoW08mOBzMZI9fBkyq8FK+OiyrNAzbk7XOz6lHlIXhW6mmQFyn5JXZFsrHb0f+WT11juJg5auJiWXR9CnNg22Jnbx4xPs1tM4IRdAQd241Nl5wiVV46Q81QYQb3T03bpDuKyMLXWNx/vjnSQ0sPhxIfupFIzXmTUv/dr8LLdYnjEnPWCWS55KaGWPYz08IIS/FYG2fH3tYuXURI8JmivWNe/Uq63H3lMPg/Qp2zVNrkSWUhx+5/RRZe5jWLRL3UekQ6AdnZaIBeq7S50ZGILZykh2Qm8DobJiEBWFdnmojzOPZ7l4bvSkPCIRUsicuPT+vw9//aQfjO7ssjuC8ADlf2libVRA3UN8FHb1W8o9nr8MOidj+11EW5AXMCcwjqUtnqdSgNSLNAicQVBhr4uZsgt6NtUSg6mPuFvxnD5DT3I0FA0SWdxbOs6wbbItKuYTqqb689h+f3g09qBGIqlczX24Wdg74vkB4MahAeicJsZu/OniDGHT+1HxOlOIiZhfNNUPgHeRiQ4ROXv0ENraz75a3O94NFJFR9pk5FEySMdz2OtX5xKe7EU/PwXRze9NFsCwEvNSEXNMi9UVGvQpHB+ADcb3xSFFSSsMwpOTbbGDbDWwCG3BeC6Zqa3XVL9l9jGAE=", "rte": true}, "ephemeral": true, "id": "ac86007d-5d99-4acb-9816-bd8f0fdd9a15", "parentId": "5926bc39-1a73-4aab-82fd-ab266b057180", "rawType": null, "timestamp": "2026-08-27 12:19:02.132000+00:00", "type": "assistant.reasoning"} +{"agentId": null, "data": {"arguments": {"path": "/private/tmp/claude-501/-Users-vini-Workspace-Openlayer-integrations-sdks/b3978e0d-127c-460e-869e-357293ac3d63/scratchpad/copilot-probe/ws"}, "displayVerbatim": null, "mcpServerName": null, "mcpToolName": null, "model": "claude-haiku-4.5", "parentToolCallId": null, "rte": true, "shellToolInfo": null, "toolCallId": "toolu_01XGaT85UjmjwdjBvSUyq4pR", "toolDescription": null, "toolName": "view", "turnId": "1"}, "ephemeral": null, "id": "3ff7e21d-9a6b-43cd-98e3-a51031a7286e", "parentId": "5926bc39-1a73-4aab-82fd-ab266b057180", "rawType": null, "timestamp": "2026-08-27 12:19:02.133000+00:00", "type": "tool.execution_start"} +{"agentId": null, "data": {"error": {"code": "denied", "message": "Permission denied and could not request permission from user"}, "interactionId": "8b56955c-c140-4d44-837e-500dc7029967", "isUserRequested": null, "mcpMeta": null, "model": "claude-haiku-4.5", "parentToolCallId": null, "result": null, "rte": true, "sandboxed": null, "success": false, "toolCallId": "toolu_01XGaT85UjmjwdjBvSUyq4pR", "toolDescription": null, "toolTelemetry": {"metrics": {"responseTokenLimit": 32000, "resultForLlmLength": 60, "resultLength": 60}, "properties": {"command": "view", "fileExtension": "[\"directory\"]", "inputs": "[\"path\",\"command\"]", "options": "{\"truncateBasedOn\":\"tokenCount\",\"truncateStyle\":\"middle\"}", "resolvedPathAgainstCwd": "false"}, "restrictedProperties": {}}, "turnId": "1"}, "ephemeral": null, "id": "4d9bffcb-4a6f-4383-b89c-ddd17ee66a46", "parentId": "3ff7e21d-9a6b-43cd-98e3-a51031a7286e", "rawType": null, "timestamp": "2026-08-27 12:19:02.137000+00:00", "type": "tool.execution_complete"} +{"agentId": null, "data": {"model": null, "turnId": "1"}, "ephemeral": null, "id": "8e58e1f7-756e-4f56-aabb-f419216e0d52", "parentId": "4d9bffcb-4a6f-4383-b89c-ddd17ee66a46", "rawType": null, "timestamp": "2026-08-27 12:19:02.147000+00:00", "type": "assistant.turn_end"} +{"agentId": null, "data": {"interactionId": "8b56955c-c140-4d44-837e-500dc7029967", "model": null, "turnId": "2"}, "ephemeral": null, "id": "373d63a9-96ad-42c3-af02-01f2b530142a", "parentId": "8e58e1f7-756e-4f56-aabb-f419216e0d52", "rawType": null, "timestamp": "2026-08-27 12:19:02.148000+00:00", "type": "assistant.turn_start"} +{"agentId": null, "data": {"conversationTokens": 493, "currentTokens": 10906, "isInitial": false, "messagesLength": 7, "systemTokens": 5225, "tokenLimit": 128000, "toolDefinitionsTokens": 5188}, "ephemeral": true, "id": "9aec684c-5356-4035-b8ec-8b9bf2d0821d", "parentId": "373d63a9-96ad-42c3-af02-01f2b530142a", "rawType": null, "timestamp": "2026-08-27 12:19:02.148000+00:00", "type": "session.usage_info"} +{"agentId": null, "data": {"_previous_response_id": null, "model": "claude-haiku-4.5", "turnId": "2"}, "ephemeral": true, "id": "04ae2075-c781-4014-a8d9-c625c263b00e", "parentId": "373d63a9-96ad-42c3-af02-01f2b530142a", "rawType": null, "timestamp": "2026-08-27 12:19:02.151000+00:00", "type": "model.call_start"} +{"agentId": null, "data": {"messageId": "1cfb775b-75bd-4569-8f3f-944d5d64bb0f", "phase": null}, "ephemeral": true, "id": "7cc30638-b0e4-4843-805e-e4648b27cb66", "parentId": "373d63a9-96ad-42c3-af02-01f2b530142a", "rawType": null, "timestamp": "2026-08-27 12:19:03.260000+00:00", "type": "assistant.message_start"} +{"agentId": null, "data": {"_available_tool_count": 16, "_num_tool_calls": 0, "_tool_counts": {}, "_tool_token_count": 5188, "apiCallId": "msg_011CeTEvnFZMMX8hePHkcccx", "apiEndpoint": "/v1/messages", "cacheExpiresAt": "2026-08-27 12:24:02.157000+00:00", "cacheReadTokens": 12748, "cacheWriteTokens": 296, "contentFilterTriggered": false, "copilotUsage": {"_token_details": [{"batchSize": 1000000, "costPerBatch": 100000000000, "tokenCount": 6, "tokenType": "input"}, {"batchSize": 1000000, "costPerBatch": 10000000000, "tokenCount": 12748, "tokenType": "cache_read"}, {"batchSize": 1000000, "costPerBatch": 125000000000, "tokenCount": 296, "tokenType": "cache_write"}, {"batchSize": 1000000, "costPerBatch": 500000000000, "tokenCount": 57, "tokenType": "output"}], "totalNanoAiu": 193580000.0}, "cost": 0.33, "duration": "0:00:01.530000", "finishReason": "stop", "initiator": "agent", "inputTokens": 13050, "interTokenLatency": "0:00:00.070205", "interactionType": "conversation-agent", "model": "claude-haiku-4.5", "outputTokens": 57, "parentToolCallId": null, "providerCallId": "29E8:3AC232:11AEDA6:149699D:6A902B36", "reasoningEffort": null, "reasoningTokens": 0, "rte": true, "serviceRequestId": "590a04cd-ce38-45b7-9825-b49b355549c8", "timeToFirstToken": "0:00:01.107547"}, "ephemeral": true, "id": "1caa46c0-a8f4-447b-ae27-1eaae4d73c45", "parentId": "373d63a9-96ad-42c3-af02-01f2b530142a", "rawType": null, "timestamp": "2026-08-27 12:19:03.688000+00:00", "type": "assistant.usage"} +{"agentId": null, "data": {"apiCallId": "msg_011CeTEvnFZMMX8hePHkcccx", "chunkCount": null, "chunkIndex": null, "citations": null, "clientRequestId": "00000-97e40043-a738-46a1-94f3-d4eb31c498fe", "content": "I don't have permission to access the current directory. Could you verify the working directory or provide the path to the files you'd like me to examine? Alternatively, if there's a specific file you'd like me to read, please let me know its path.", "interactionId": "8b56955c-c140-4d44-837e-500dc7029967", "messageId": "1cfb775b-75bd-4569-8f3f-944d5d64bb0f", "model": "claude-haiku-4.5", "outputTokens": 57, "parentToolCallId": null, "phase": null, "reasoningText": "The user wants me to:\n1. List the files in the current directory\n2. Find the largest one\n3. Read it\n4. Describe what it contains in one sentence\n\nLet me start by listing the files in the current directory. According to the environment context, I'm in: /private/tmp/claude-501/-Users-vini-Workspace-Openlayer-integrations-sdks/b3978e0d-127c-460e-869e-357293ac3d63/scratchpad/copilot-probe/ws\n\nI'll use bash to list files and find the largest one.", "requestId": "29E8:3AC232:11AEDA6:149699D:6A902B36", "rte": true, "serverTools": null, "serviceRequestId": "590a04cd-ce38-45b7-9825-b49b355549c8", "toolRequests": [], "turnId": "2"}, "ephemeral": null, "id": "a05bc6a4-55f8-485e-aeb4-5b05a8c0176e", "parentId": "373d63a9-96ad-42c3-af02-01f2b530142a", "rawType": null, "timestamp": "2026-08-27 12:19:03.689000+00:00", "type": "assistant.message"} +{"agentId": null, "data": {"content": "The user wants me to:\n1. List the files in the current directory\n2. Find the largest one\n3. Read it\n4. Describe what it contains in one sentence\n\nLet me start by listing the files in the current directory. According to the environment context, I'm in: /private/tmp/claude-501/-Users-vini-Workspace-Openlayer-integrations-sdks/b3978e0d-127c-460e-869e-357293ac3d63/scratchpad/copilot-probe/ws\n\nI'll use bash to list files and find the largest one.", "reasoningId": "EtMFCrIBCBEYAipAJxE97+DjjDVs+bGpHa8dQ5VSPOiiCUTaNEFSDl8DtAClc+NOxKQ2705W5y9y/9pgDBuTFT+O+zKldneiyuvr+zIZY2xhdWRlLWhhaWt1LTQtNS0yMDI1MTAwMTgAQgh0aGlua2luZ1okY2VkMWY5OGUtMGI1MS00NjEwLTgyODItNGU1ZDg4Mzg0NTc0chAFJi2jM86AcGV3hjaN37r2iAEBqAG01sDUBrABAhIMF1ZrovH4Ic5Eh0jCGgzf7CUQ+Pi+9vSJjCsiMOY64NBjwtdHREJ9AdnWhwd6RbBs3vPGdFR5EGslesoW08mOBzMZI9fBkyq8FK+OiyrNAzbk7XOz6lHlIXhW6mmQFyn5JXZFsrHb0f+WT11juJg5auJiWXR9CnNg22Jnbx4xPs1tM4IRdAQd241Nl5wiVV46Q81QYQb3T03bpDuKyMLXWNx/vjnSQ0sPhxIfupFIzXmTUv/dr8LLdYnjEnPWCWS55KaGWPYz08IIS/FYG2fH3tYuXURI8JmivWNe/Uq63H3lMPg/Qp2zVNrkSWUhx+5/RRZe5jWLRL3UekQ6AdnZaIBeq7S50ZGILZykh2Qm8DobJiEBWFdnmojzOPZ7l4bvSkPCIRUsicuPT+vw9//aQfjO7ssjuC8ADlf2libVRA3UN8FHb1W8o9nr8MOidj+11EW5AXMCcwjqUtnqdSgNSLNAicQVBhr4uZsgt6NtUSg6mPuFvxnD5DT3I0FA0SWdxbOs6wbbItKuYTqqb689h+f3g09qBGIqlczX24Wdg74vkB4MahAeicJsZu/OniDGHT+1HxOlOIiZhfNNUPgHeRiQ4ROXv0ENraz75a3O94NFJFR9pk5FEySMdz2OtX5xKe7EU/PwXRze9NFsCwEvNSEXNMi9UVGvQpHB+ADcb3xSFFSSsMwpOTbbGDbDWwCG3BeC6Zqa3XVL9l9jGAE=", "rte": true}, "ephemeral": true, "id": "09912008-abaf-4b19-bdbe-b1b8ee8baab8", "parentId": "a05bc6a4-55f8-485e-aeb4-5b05a8c0176e", "rawType": null, "timestamp": "2026-08-27 12:19:03.689000+00:00", "type": "assistant.reasoning"} +{"agentId": null, "data": {"model": null, "turnId": "2"}, "ephemeral": null, "id": "582200b5-fdae-48b2-8fc9-62744e7ce1ee", "parentId": "a05bc6a4-55f8-485e-aeb4-5b05a8c0176e", "rawType": null, "timestamp": "2026-08-27 12:19:03.690000+00:00", "type": "assistant.turn_end"} +{"agentId": null, "data": {"_model_cache_state": [{"_cache_ttl_seconds": 300, "cacheExpiresAt": "2026-08-27 12:24:02.157000+00:00", "modelId": "claude-haiku-4.5"}], "_total_premium_requests": 0.33, "totalNanoAiu": 2086670000.0}, "ephemeral": null, "id": "034f74aa-61d7-4b68-915d-26ddb5485ea7", "parentId": "582200b5-fdae-48b2-8fc9-62744e7ce1ee", "rawType": null, "timestamp": "2026-08-27 12:19:03.693000+00:00", "type": "session.usage_checkpoint"} +{"agentId": null, "data": {"aborted": null}, "ephemeral": true, "id": "ccc72a5f-14c4-4e47-9923-f9ca0b534a93", "parentId": "034f74aa-61d7-4b68-915d-26ddb5485ea7", "rawType": null, "timestamp": "2026-08-27 12:19:03.693000+00:00", "type": "assistant.idle"} +{"agentId": null, "data": {"aborted": null}, "ephemeral": true, "id": "0ba8dd42-349e-4a23-b618-15e8cee83f7e", "parentId": "034f74aa-61d7-4b68-915d-26ddb5485ea7", "rawType": null, "timestamp": "2026-08-27 12:19:03.694000+00:00", "type": "session.idle"} diff --git a/tests/integrations/fixtures/copilotSdk/session_tools_subagent.jsonl b/tests/integrations/fixtures/copilotSdk/session_tools_subagent.jsonl new file mode 100644 index 0000000..174f196 --- /dev/null +++ b/tests/integrations/fixtures/copilotSdk/session_tools_subagent.jsonl @@ -0,0 +1,93 @@ +{"agentId": null, "data": {"alreadyInUse": false, "context": {"baseCommit": null, "branch": null, "cwd": "/private/tmp/claude-501/-Users-vini-Workspace-Openlayer-integrations-sdks/b3978e0d-127c-460e-869e-357293ac3d63/scratchpad/copilot-probe/ws", "gitRoot": null, "headCommit": null, "hostType": null, "pendingGitContext": null, "repository": null, "repositoryHost": null}, "contextTier": null, "copilotVersion": "1.0.79", "detachedFromSpawningParentSessionId": null, "githubMcpToolConfig": null, "producer": "copilot-agent", "reasoningEffort": null, "reasoningSummary": null, "remoteSteerable": false, "selectedModel": null, "sessionId": "89b7a3bf-b6a4-432e-8271-6baa38edf1d3", "sessionLimits": null, "startTime": "2026-08-27 12:21:28.603000+00:00", "verbosity": null, "version": 1}, "ephemeral": null, "id": "a8a5a710-a6b0-4c89-ad7c-c24906175372", "parentId": null, "rawType": null, "timestamp": "2026-08-27 12:21:28.656000+00:00", "type": "session.start"} +{"agentId": null, "data": {"bypassPermissionsDisabled": false, "clientManaged": false, "deviceManaged": false, "failClosed": false, "managedKeys": [], "permissionsAllowIntersected": null, "serverManaged": false, "settings": null, "source": "none"}, "ephemeral": true, "id": "2fef70c7-8424-4648-b448-809578eb11db", "parentId": "a8a5a710-a6b0-4c89-ad7c-c24906175372", "rawType": null, "timestamp": "2026-08-27 12:21:28.669000+00:00", "type": "session.managed_settings_resolved"} +{"agentId": null, "data": {}, "ephemeral": true, "id": "e8af1eb4-4811-4307-9307-e5841dbf81fc", "parentId": "a8a5a710-a6b0-4c89-ad7c-c24906175372", "rawType": null, "timestamp": "2026-08-27 12:21:28.674000+00:00", "type": "pending_messages.modified"} +{"agentId": null, "data": {"cause": null, "contextTier": null, "newModel": "auto", "previousModel": null, "previousReasoningEffort": null, "previousReasoningSummary": null, "previousVerbosity": null, "reasoningEffort": null, "reasoningSummary": null, "verbosity": null}, "ephemeral": null, "id": "e8bae77f-b343-4c09-8e5e-17f85fb492fb", "parentId": "a8a5a710-a6b0-4c89-ad7c-c24906175372", "rawType": null, "timestamp": "2026-08-27 12:21:29.551000+00:00", "type": "session.model_change"} +{"agentId": null, "data": {"skills": [{"argumentHint": null, "commandName": "customize-cloud-agent", "description": "Skill for customizing the Copilot cloud agent (formerly known as Copilot coding agent) environment, including copilot-setup-steps.yml configuration, preinstalling tools and dependencies, runners, and settings. Use when the user mentions copilot-setup-steps, copilot setup steps, or wants to configure the cloud agent environment.", "enabled": true, "name": "customize-cloud-agent", "path": "/Users/vini/Library/Caches/copilot/pkg/darwin-arm64/1.0.79/builtin/customize-cloud-agent/SKILL.md", "source": "builtin", "userInvocable": false}, {"argumentHint": null, "commandName": "github-pr-media", "description": "Upload an image or video to GitHub's user attachments API and embed it in a pull request description or comment. Use when asked to add screenshots, diagrams, recordings, or other media to a PR or GitHub comment.", "enabled": true, "name": "github-pr-media", "path": "/Users/vini/Library/Caches/copilot/pkg/darwin-arm64/1.0.79/builtin/github-pr-media/SKILL.md", "source": "builtin", "userInvocable": false}]}, "ephemeral": true, "id": "f354a21d-3643-4732-bfae-189dab93d218", "parentId": "e8bae77f-b343-4c09-8e5e-17f85fb492fb", "rawType": null, "timestamp": "2026-08-27 12:21:29.792000+00:00", "type": "session.skills_loaded"} +{"agentId": null, "data": {"availableModels": ["claude-haiku-4.5", "gpt-5-mini"], "candidateModels": ["claude-haiku-4.5", "gpt-5-mini"], "categoryScores": {"codeGen": 0.3495, "debugging": 0.0107, "reasoning": 0.3958, "toolUse": 0.3711}, "chosenModel": "claude-haiku-4.5", "chosenShortfall": 0.3983, "confidence": 0.72, "endToEndLatencyMs": 281.0, "fallback": false, "fallbackReason": null, "hasImage": false, "predictedLabel": "no_reasoning", "reasoningBucket": "medium", "routerLatencyMs": 101.0, "routingMethod": "hydra", "stickyOverride": false}, "ephemeral": null, "id": "6bc111d2-c81f-4244-984d-645bde5cae81", "parentId": "e8bae77f-b343-4c09-8e5e-17f85fb492fb", "rawType": null, "timestamp": "2026-08-27 12:21:30.068000+00:00", "type": "session.auto_mode_resolved"} +{"agentId": null, "data": {"content": "You are the GitHub Copilot CLI, a terminal assistant built by GitHub. You are an interactive CLI tool that helps users with software engineering tasks.\n\n# Tone and style\n* When providing output or exp\u2026", "interactionId": "56b1e0b4-f34f-43d0-a86f-0692557873f7", "metadata": null, "name": null, "role": "system"}, "ephemeral": null, "id": "6574bd88-61f9-4c46-99e4-9a9b276b1533", "parentId": "6bc111d2-c81f-4244-984d-645bde5cae81", "rawType": null, "timestamp": "2026-08-27 12:21:30.081000+00:00", "type": "system.message"} +{"agentId": null, "data": {"model": "claude-haiku-4.5"}, "ephemeral": true, "id": "23af3eba-0234-4433-b39c-05e3ad76e5c5", "parentId": "6574bd88-61f9-4c46-99e4-9a9b276b1533", "rawType": null, "timestamp": "2026-08-27 12:21:30.083000+00:00", "type": "session.tools_updated"} +{"agentId": null, "data": {"agentMode": null, "attachments": [], "content": "Do these three things: (1) call the get_weather tool for Lisbon, (2) run `ls -l` with bash, and (3) delegate to a subagent to summarize what big.py contains.", "delivery": "idle", "interactionId": "56b1e0b4-f34f-43d0-a86f-0692557873f7", "isAutopilotContinuation": null, "nativeDocumentPathFallbackPaths": null, "parentAgentTaskId": "2898e84c-4e1b-4783-949f-9ddb6511c5f8", "source": null, "supportedNativeDocumentMimeTypes": [], "transformedContent": "2026-08-27T09:21:30.087-03:00\n\nDo these three things: (1) call the get_weather tool for Lisbon, (2) run `ls -l` with bash, and (3) delegate to a subagent to summarize what big.py contains.\n\n\nAvailable tables: todos, todo_deps\n"}, "ephemeral": null, "id": "7642476a-a36b-46da-93d0-25c9cd582489", "parentId": "6574bd88-61f9-4c46-99e4-9a9b276b1533", "rawType": null, "timestamp": "2026-08-27 12:21:30.087000+00:00", "type": "user.message"} +{"agentId": null, "data": {"title": "Do these three things: (1) call the get_weather tool for Lisbon, (2) run `ls -l` with bash, and (3) delegate to a subagent to summarize what big.py contains."}, "ephemeral": true, "id": "484952a0-4827-41de-8ea8-73c3453b95c1", "parentId": "7642476a-a36b-46da-93d0-25c9cd582489", "rawType": null, "timestamp": "2026-08-27 12:21:30.090000+00:00", "type": "session.title_changed"} +{"agentId": null, "data": {"interactionId": "56b1e0b4-f34f-43d0-a86f-0692557873f7", "model": null, "turnId": "0"}, "ephemeral": null, "id": "bf9b429a-39ae-4354-ad02-4330e9762697", "parentId": "7642476a-a36b-46da-93d0-25c9cd582489", "rawType": null, "timestamp": "2026-08-27 12:21:30.111000+00:00", "type": "assistant.turn_start"} +{"agentId": null, "data": {"conversationTokens": 100, "currentTokens": 10563, "isInitial": true, "messagesLength": 3, "systemTokens": 5224, "tokenLimit": 128000, "toolDefinitionsTokens": 5239}, "ephemeral": true, "id": "56627b3e-ea28-4bd7-bda2-0ea2ba5b1e67", "parentId": "bf9b429a-39ae-4354-ad02-4330e9762697", "rawType": null, "timestamp": "2026-08-27 12:21:30.112000+00:00", "type": "session.usage_info"} +{"agentId": null, "data": {"_previous_response_id": null, "model": "claude-haiku-4.5", "turnId": "0"}, "ephemeral": true, "id": "a8abfffa-5d4b-458f-8789-e03718e930cd", "parentId": "bf9b429a-39ae-4354-ad02-4330e9762697", "rawType": null, "timestamp": "2026-08-27 12:21:30.116000+00:00", "type": "model.call_start"} +{"agentId": null, "data": {"totalResponseSizeBytes": 14}, "ephemeral": true, "id": "77c6d080-fa5e-439a-affc-4cf0af51bcd6", "parentId": "bf9b429a-39ae-4354-ad02-4330e9762697", "rawType": null, "timestamp": "2026-08-27 12:21:31.428000+00:00", "type": "assistant.streaming_delta"} +{"agentId": null, "data": {"deltaContent": "The user wants", "reasoningId": "2f86c4a2-46af-478e-bbec-e89af25bc0d7"}, "ephemeral": true, "id": "a14a5e63-1f73-41ae-af34-e69d94338d27", "parentId": "bf9b429a-39ae-4354-ad02-4330e9762697", "rawType": null, "timestamp": "2026-08-27 12:21:31.428000+00:00", "type": "assistant.reasoning_delta"} +{"agentId": null, "data": {"totalResponseSizeBytes": 23}, "ephemeral": true, "id": "1bb08afa-4860-4278-a9b4-b0573bcf590a", "parentId": "bf9b429a-39ae-4354-ad02-4330e9762697", "rawType": null, "timestamp": "2026-08-27 12:21:31.428000+00:00", "type": "assistant.streaming_delta"} +{"agentId": null, "data": {"deltaContent": " me to do", "reasoningId": "2f86c4a2-46af-478e-bbec-e89af25bc0d7"}, "ephemeral": true, "id": "fb73e919-e18d-4744-b6fd-4f5c175ecfac", "parentId": "bf9b429a-39ae-4354-ad02-4330e9762697", "rawType": null, "timestamp": "2026-08-27 12:21:31.428000+00:00", "type": "assistant.reasoning_delta"} +{"agentId": null, "data": {"totalResponseSizeBytes": 37}, "ephemeral": true, "id": "49c33ab6-56da-470a-b520-c7d019a99638", "parentId": "bf9b429a-39ae-4354-ad02-4330e9762697", "rawType": null, "timestamp": "2026-08-27 12:21:31.429000+00:00", "type": "assistant.streaming_delta"} +{"agentId": null, "data": {"deltaContent": " three things:", "reasoningId": "2f86c4a2-46af-478e-bbec-e89af25bc0d7"}, "ephemeral": true, "id": "1ca3782f-4fc2-4d74-929b-d597e5f1b768", "parentId": "bf9b429a-39ae-4354-ad02-4330e9762697", "rawType": null, "timestamp": "2026-08-27 12:21:31.429000+00:00", "type": "assistant.reasoning_delta"} +{"agentId": null, "data": {"inputDelta": "{\"city", "toolCallId": "toolu_01QdopvJHQsZ7XUzM4oHnFie", "toolName": "get_weather", "toolType": null}, "ephemeral": true, "id": "9c4800a8-b80b-4b95-b223-e0b24b32e7db", "parentId": "bf9b429a-39ae-4354-ad02-4330e9762697", "rawType": null, "timestamp": "2026-08-27 12:21:33.340000+00:00", "type": "assistant.tool_call_delta"} +{"agentId": null, "data": {"inputDelta": "\": \"Li", "toolCallId": "toolu_01QdopvJHQsZ7XUzM4oHnFie", "toolName": "get_weather", "toolType": null}, "ephemeral": true, "id": "59bf2c41-e814-4b44-9e9d-1a4cb2c8ad50", "parentId": "bf9b429a-39ae-4354-ad02-4330e9762697", "rawType": null, "timestamp": "2026-08-27 12:21:33.340000+00:00", "type": "assistant.tool_call_delta"} +{"agentId": null, "data": {"inputDelta": "sbon\"}", "toolCallId": "toolu_01QdopvJHQsZ7XUzM4oHnFie", "toolName": "get_weather", "toolType": null}, "ephemeral": true, "id": "af49ffdc-c402-4042-8867-781027915bb9", "parentId": "bf9b429a-39ae-4354-ad02-4330e9762697", "rawType": null, "timestamp": "2026-08-27 12:21:33.340000+00:00", "type": "assistant.tool_call_delta"} +{"agentId": null, "data": {"_available_tool_count": 17, "_num_tool_calls": 3, "_tool_counts": {"bash": 1, "getWeather": 1, "task": 1}, "_tool_token_count": 5239, "apiCallId": "msg_011CeTF7ha5jd6tEsQJyQZqf", "apiEndpoint": "/v1/messages", "cacheExpiresAt": "2026-08-27 12:26:30.126000+00:00", "cacheReadTokens": 6179, "cacheWriteTokens": 6416, "contentFilterTriggered": false, "copilotUsage": {"_token_details": [{"batchSize": 1000000, "costPerBatch": 100000000000, "tokenCount": 10, "tokenType": "input"}, {"batchSize": 1000000, "costPerBatch": 10000000000, "tokenCount": 6179, "tokenType": "cache_read"}, {"batchSize": 1000000, "costPerBatch": 125000000000, "tokenCount": 6416, "tokenType": "cache_write"}, {"batchSize": 1000000, "costPerBatch": 500000000000, "tokenCount": 395, "tokenType": "output"}], "totalNanoAiu": 1062290000.0}, "cost": 0.33, "duration": "0:00:04.673000", "finishReason": "tool_calls", "initiator": "user", "inputTokens": 12605, "interTokenLatency": "0:00:00.044229", "interactionType": "conversation-agent", "model": "claude-haiku-4.5", "outputTokens": 395, "parentToolCallId": null, "providerCallId": "29D8:38DC23:19954C5:1C5376B:6A902BCA", "reasoningEffort": null, "reasoningTokens": 130, "rte": true, "serviceRequestId": "a229c750-5902-470a-9017-33196165a23f", "timeToFirstToken": "0:00:01.310968"}, "ephemeral": true, "id": "acd9905c-cdb9-4df8-8931-07d0872b2915", "parentId": "bf9b429a-39ae-4354-ad02-4330e9762697", "rawType": null, "timestamp": "2026-08-27 12:21:34.799000+00:00", "type": "assistant.usage"} +{"agentId": null, "data": {"apiCallId": "msg_011CeTF7ha5jd6tEsQJyQZqf", "chunkCount": null, "chunkIndex": null, "citations": null, "clientRequestId": "00000-0225e8ce-5fa6-4a60-99f7-1965d37c515e", "content": "", "interactionId": "56b1e0b4-f34f-43d0-a86f-0692557873f7", "messageId": "ad58c6e2-b92b-4c9e-9550-803296ae4b31", "model": "claude-haiku-4.5", "outputTokens": 395, "parentToolCallId": null, "phase": null, "reasoningText": "The user wants me to do three things:\n1. Call get_weather tool for Lisbon\n2. Run `ls -l` with bash\n3. Delegate to a subagent to summarize what big.py contains\n\nLet me do all three in parallel since they're independent. I'll:\n1. Call get_weather with city \"Lisbon\"\n2. Call bash with command \"ls -l\"\n3. Call task tool to delegate to an explore agent to summarize big.py\n\nAll three can be done in parallel in one function_calls block.", "requestId": "29D8:38DC23:19954C5:1C5376B:6A902BCA", "rte": true, "serverTools": null, "serviceRequestId": "a229c750-5902-470a-9017-33196165a23f", "toolRequests": [{"arguments": {"city": "Lisbon"}, "intentionSummary": null, "mcpServerName": null, "mcpToolName": null, "name": "get_weather", "toolCallId": "toolu_01QdopvJHQsZ7XUzM4oHnFie", "toolTitle": null, "type": "function"}, {"arguments": {"command": "ls -l", "description": "List files in current directory"}, "intentionSummary": "List files in current directory", "mcpServerName": null, "mcpToolName": null, "name": "bash", "toolCallId": "toolu_01EBTnVYRCkb8NdiWsyoTGxR", "toolTitle": null, "type": "function"}, {"arguments": {"agentType": "explore", "description": "Summarize big.py file", "mode": "sync", "name": "big-py-summary", "prompt": "Find and summarize what the file big.py contains. Provide a concise overview of its purpose, main components, and key functions or classes. Start from the current working directory."}, "intentionSummary": "Summarize big.py file", "mcpServerName": null, "mcpToolName": null, "name": "task", "toolCallId": "toolu_013RHgDCCnyFpE52pN1qXV2V", "toolTitle": null, "type": "function"}], "turnId": "0"}, "ephemeral": null, "id": "6df83a27-b1f0-420d-8b1f-d2d8de0653bc", "parentId": "bf9b429a-39ae-4354-ad02-4330e9762697", "rawType": null, "timestamp": "2026-08-27 12:21:34.805000+00:00", "type": "assistant.message"} +{"agentId": null, "data": {"content": "The user wants me to do three things:\n1. Call get_weather tool for Lisbon\n2. Run `ls -l` with bash\n3. Delegate to a subagent to summarize what big.py contains\n\nLet me do all three in parallel since they're independent. I'll:\n1. Call get_weather with city \"Lisbon\"\n2. Call bash with command \"ls -l\"\n3. Call task tool to delegate to an explore agent to summarize big.py\n\nAll three can be done in parallel in one function_calls block.", "reasoningId": "2f86c4a2-46af-478e-bbec-e89af25bc0d7", "rte": true}, "ephemeral": true, "id": "fb098e69-8513-499b-b606-c2992b59c8e3", "parentId": "6df83a27-b1f0-420d-8b1f-d2d8de0653bc", "rawType": null, "timestamp": "2026-08-27 12:21:34.806000+00:00", "type": "assistant.reasoning"} +{"agentId": null, "data": {"arguments": {"city": "Lisbon"}, "displayVerbatim": null, "mcpServerName": null, "mcpToolName": null, "model": "claude-haiku-4.5", "parentToolCallId": null, "rte": true, "shellToolInfo": null, "toolCallId": "toolu_01QdopvJHQsZ7XUzM4oHnFie", "toolDescription": null, "toolName": "get_weather", "turnId": "0"}, "ephemeral": null, "id": "9332c2d2-2355-48ba-8c88-726c46dc5923", "parentId": "6df83a27-b1f0-420d-8b1f-d2d8de0653bc", "rawType": null, "timestamp": "2026-08-27 12:21:34.807000+00:00", "type": "tool.execution_start"} +{"agentId": null, "data": {"arguments": {"command": "ls -l", "description": "List files in current directory"}, "displayVerbatim": null, "mcpServerName": null, "mcpToolName": null, "model": "claude-haiku-4.5", "parentToolCallId": null, "rte": true, "shellToolInfo": {"displayCommand": null, "hasWriteFileRedirection": false, "possiblePaths": []}, "toolCallId": "toolu_01EBTnVYRCkb8NdiWsyoTGxR", "toolDescription": null, "toolName": "bash", "turnId": "0"}, "ephemeral": null, "id": "4a2dc110-a46d-45f9-8785-d7c90105a062", "parentId": "9332c2d2-2355-48ba-8c88-726c46dc5923", "rawType": null, "timestamp": "2026-08-27 12:21:34.811000+00:00", "type": "tool.execution_start"} +{"agentId": null, "data": {"arguments": {"agentType": "explore", "description": "Summarize big.py file", "mode": "sync", "name": "big-py-summary", "prompt": "Find and summarize what the file big.py contains. Provide a concise overview of its purpose, main components, and key functions or classes. Start from the current working directory."}, "displayVerbatim": null, "mcpServerName": null, "mcpToolName": null, "model": "claude-haiku-4.5", "parentToolCallId": null, "rte": true, "shellToolInfo": null, "toolCallId": "toolu_013RHgDCCnyFpE52pN1qXV2V", "toolDescription": null, "toolName": "task", "turnId": "0"}, "ephemeral": null, "id": "3798b1a1-7e4a-4ae0-846a-d15b4c6a12de", "parentId": "4a2dc110-a46d-45f9-8785-d7c90105a062", "rawType": null, "timestamp": "2026-08-27 12:21:34.811000+00:00", "type": "tool.execution_start"} +{"agentId": null, "data": {"permissionRequest": {"args": {"city": "Lisbon"}, "managedApprovalRequired": null, "toolCallId": "toolu_01QdopvJHQsZ7XUzM4oHnFie", "toolDescription": "Get the current weather for a city.", "toolName": "get_weather"}, "promptRequest": {"args": {"city": "Lisbon"}, "autoApproval": null, "toolCallId": "toolu_01QdopvJHQsZ7XUzM4oHnFie", "toolDescription": "Get the current weather for a city.", "toolName": "get_weather"}, "requestId": "09eda3f9-5b3a-435c-9e74-f298a75d4fec", "resolvedByHook": null, "riskAssessment": null}, "ephemeral": null, "id": "d1b6d721-e038-4907-8b5c-3dfcafc8e19f", "parentId": "3798b1a1-7e4a-4ae0-846a-d15b4c6a12de", "rawType": null, "timestamp": "2026-08-27 12:21:34.816000+00:00", "type": "permission.requested"} +{"agentId": null, "data": {}, "ephemeral": true, "id": "d13f4d37-eec5-49af-988d-d924cfbd14f1", "parentId": "d1b6d721-e038-4907-8b5c-3dfcafc8e19f", "rawType": null, "timestamp": "2026-08-27 12:21:34.817000+00:00", "type": "session.background_tasks_changed"} +{"agentId": null, "data": {"requestId": "09eda3f9-5b3a-435c-9e74-f298a75d4fec", "result": {}, "toolCallId": "toolu_01QdopvJHQsZ7XUzM4oHnFie"}, "ephemeral": null, "id": "33338f8d-0c8a-437c-9ddb-09091634a9b1", "parentId": "d1b6d721-e038-4907-8b5c-3dfcafc8e19f", "rawType": null, "timestamp": "2026-08-27 12:21:34.818000+00:00", "type": "permission.completed"} +{"agentId": null, "data": {}, "ephemeral": true, "id": "74964823-15e1-489a-a041-75b37d33c754", "parentId": "33338f8d-0c8a-437c-9ddb-09091634a9b1", "rawType": null, "timestamp": "2026-08-27 12:21:34.819000+00:00", "type": "session.background_tasks_changed"} +{"agentId": null, "data": {}, "ephemeral": true, "id": "64d1d3b1-ea2e-4bc2-b7c5-916f1f92cdc9", "parentId": "33338f8d-0c8a-437c-9ddb-09091634a9b1", "rawType": null, "timestamp": "2026-08-27 12:21:34.819000+00:00", "type": "session.background_tasks_changed"} +{"agentId": null, "data": {"arguments": {"city": "Lisbon"}, "requestId": "4aa0bf2f-3bef-4e2c-8595-d7135ebb4f94", "sessionId": "89b7a3bf-b6a4-432e-8271-6baa38edf1d3", "toolCallId": "toolu_01QdopvJHQsZ7XUzM4oHnFie", "toolName": "get_weather", "traceparent": null, "tracestate": null, "workingDirectory": "/private/tmp/claude-501/-Users-vini-Workspace-Openlayer-integrations-sdks/b3978e0d-127c-460e-869e-357293ac3d63/scratchpad/copilot-probe/ws"}, "ephemeral": null, "id": "39b7f2fb-9bc7-4f1c-b2e4-e66cfd201278", "parentId": "33338f8d-0c8a-437c-9ddb-09091634a9b1", "rawType": null, "timestamp": "2026-08-27 12:21:34.820000+00:00", "type": "external_tool.requested"} +{"agentId": "toolu_013RHgDCCnyFpE52pN1qXV2V", "data": {"agentDescription": "Fast codebase exploration and answering questions. Uses code intelligence, {{grepToolName}}, {{globToolName}}, view, {{shellToolName}} tools in a separate context window to search files and understand code structure. Safe to call in parallel.\n", "agentDisplayName": "Explore Agent", "agentName": "explore", "model": "claude-haiku-4.5", "toolCallId": "toolu_013RHgDCCnyFpE52pN1qXV2V"}, "ephemeral": null, "id": "30c62b1e-86bf-4b5b-af4d-fa9445bdff3d", "parentId": "39b7f2fb-9bc7-4f1c-b2e4-e66cfd201278", "rawType": null, "timestamp": "2026-08-27 12:21:34.823000+00:00", "type": "subagent.started"} +{"agentId": null, "data": {"permissionRequest": {"canOfferSessionApproval": false, "commandSegments": [{"fullCommandText": "ls -l", "identifier": "ls"}], "commands": [{"identifier": "ls -l", "readOnly": false}], "fullCommandText": "ls -l", "hasWriteFileRedirection": false, "intention": "List files in current directory", "managedApprovalRequired": null, "possiblePaths": [], "possibleUrls": [], "requestSandboxBypass": null, "requestSandboxBypassReason": null, "toolCallId": "toolu_01EBTnVYRCkb8NdiWsyoTGxR", "warning": null}, "promptRequest": {"autoApproval": null, "canOfferSessionApproval": false, "commandIdentifiers": ["ls -l"], "fullCommandText": "ls -l", "intention": "List files in current directory", "managedApprovalRequired": null, "toolCallId": "toolu_01EBTnVYRCkb8NdiWsyoTGxR", "warning": null}, "requestId": "5bda488a-4ada-495e-8df3-9bf79e470ae3", "resolvedByHook": null, "riskAssessment": null}, "ephemeral": null, "id": "16a07421-9ffa-448a-89be-cdccfbf7202a", "parentId": "30c62b1e-86bf-4b5b-af4d-fa9445bdff3d", "rawType": null, "timestamp": "2026-08-27 12:21:34.825000+00:00", "type": "permission.requested"} +{"agentId": null, "data": {"requestId": "5bda488a-4ada-495e-8df3-9bf79e470ae3", "result": {}, "toolCallId": "toolu_01EBTnVYRCkb8NdiWsyoTGxR"}, "ephemeral": null, "id": "301fab39-b1e3-41b4-be46-b03ccafd1666", "parentId": "16a07421-9ffa-448a-89be-cdccfbf7202a", "rawType": null, "timestamp": "2026-08-27 12:21:34.828000+00:00", "type": "permission.completed"} +{"agentId": null, "data": {"requestId": "4aa0bf2f-3bef-4e2c-8595-d7135ebb4f94"}, "ephemeral": null, "id": "2308cb42-34cd-45d7-913f-024ab26da245", "parentId": "301fab39-b1e3-41b4-be46-b03ccafd1666", "rawType": null, "timestamp": "2026-08-27 12:21:34.828000+00:00", "type": "external_tool.completed"} +{"agentId": null, "data": {}, "ephemeral": true, "id": "4f063056-86c6-4175-b483-1343bea00d4f", "parentId": "2308cb42-34cd-45d7-913f-024ab26da245", "rawType": null, "timestamp": "2026-08-27 12:21:34.829000+00:00", "type": "session.background_tasks_changed"} +{"agentId": null, "data": {}, "ephemeral": true, "id": "5ee38a35-a50e-4037-bdec-fc748b1ddc34", "parentId": "2308cb42-34cd-45d7-913f-024ab26da245", "rawType": null, "timestamp": "2026-08-27 12:21:34.829000+00:00", "type": "session.background_tasks_changed"} +{"agentId": null, "data": {}, "ephemeral": true, "id": "2b531dd9-6ff5-4bae-a4c9-2dd838e72abd", "parentId": "2308cb42-34cd-45d7-913f-024ab26da245", "rawType": null, "timestamp": "2026-08-27 12:21:34.830000+00:00", "type": "session.background_tasks_changed"} +{"agentId": null, "data": {}, "ephemeral": true, "id": "d4368bca-e20c-4e38-8727-5e57683a5afc", "parentId": "2308cb42-34cd-45d7-913f-024ab26da245", "rawType": null, "timestamp": "2026-08-27 12:21:34.839000+00:00", "type": "session.background_tasks_changed"} +{"agentId": null, "data": {"partialOutput": "total 16\n-rw-r--r-- 1 vini wheel 2049 Aug 27 09:18 big.py\n-rw-r--r-- 1 vini wheel 29 Aug 27 09:18 small.py\n", "toolCallId": "toolu_01EBTnVYRCkb8NdiWsyoTGxR"}, "ephemeral": true, "id": "04d89451-12eb-4a49-a50e-67134e88d215", "parentId": "2308cb42-34cd-45d7-913f-024ab26da245", "rawType": null, "timestamp": "2026-08-27 12:21:34.847000+00:00", "type": "tool.execution_partial_result"} +{"agentId": null, "data": {"partialOutput": "total 16\n-rw-r--r-- 1 vini wheel 2049 Aug 27 09:18 big.py\n-rw-r--r-- 1 vini wheel 29 Aug 27 09:18 small.py\n", "toolCallId": "toolu_01EBTnVYRCkb8NdiWsyoTGxR"}, "ephemeral": true, "id": "3c57a41e-6e68-4aa1-a0cc-324a0b866a2d", "parentId": "2308cb42-34cd-45d7-913f-024ab26da245", "rawType": null, "timestamp": "2026-08-27 12:21:34.847000+00:00", "type": "tool.execution_partial_result"} +{"agentId": null, "data": {}, "ephemeral": true, "id": "3be66f6c-8dce-4508-9505-57986b4a7762", "parentId": "2308cb42-34cd-45d7-913f-024ab26da245", "rawType": null, "timestamp": "2026-08-27 12:21:34.847000+00:00", "type": "session.background_tasks_changed"} +{"agentId": null, "data": {}, "ephemeral": true, "id": "c852c767-09a0-4646-9aac-4e0141e7ef12", "parentId": "2308cb42-34cd-45d7-913f-024ab26da245", "rawType": null, "timestamp": "2026-08-27 12:21:34.848000+00:00", "type": "session.background_tasks_changed"} +{"agentId": null, "data": {}, "ephemeral": true, "id": "5ba9ee28-61e9-495d-8713-6e484804bddd", "parentId": "2308cb42-34cd-45d7-913f-024ab26da245", "rawType": null, "timestamp": "2026-08-27 12:21:34.848000+00:00", "type": "session.background_tasks_changed"} +{"agentId": null, "data": {}, "ephemeral": true, "id": "af0f2e6a-45b5-421b-9e9b-b9b3801e3a9d", "parentId": "2308cb42-34cd-45d7-913f-024ab26da245", "rawType": null, "timestamp": "2026-08-27 12:21:34.849000+00:00", "type": "session.background_tasks_changed"} +{"agentId": null, "data": {}, "ephemeral": true, "id": "9f3a9f64-ae65-43f5-a40a-8bf348388dea", "parentId": "2308cb42-34cd-45d7-913f-024ab26da245", "rawType": null, "timestamp": "2026-08-27 12:21:34.851000+00:00", "type": "session.background_tasks_changed"} +{"agentId": "toolu_013RHgDCCnyFpE52pN1qXV2V", "data": {"content": "You are an exploration agent. Answer the question as fast as possible, then stop.\n\n**File paths:**\n- Use absolute paths for all file references (your working directory is shown in the `", "interactionId": "20eb84fb-e525-431a-bb8b-a32042706ccf", "metadata": null, "name": null, "role": "system"}, "ephemeral": null, "id": "aa7bf5c6-59d7-4322-a5df-9f6abe236cfa", "parentId": "2308cb42-34cd-45d7-913f-024ab26da245", "rawType": null, "timestamp": "2026-08-27 12:21:34.890000+00:00", "type": "system.message"} +{"agentId": "toolu_013RHgDCCnyFpE52pN1qXV2V", "data": {"agentMode": null, "attachments": [], "content": "Find and summarize what the file big.py contains. Provide a concise overview of its purpose, main components, and key functions or classes. Start from the current working directory.", "delivery": "idle", "interactionId": "20eb84fb-e525-431a-bb8b-a32042706ccf", "isAutopilotContinuation": null, "nativeDocumentPathFallbackPaths": null, "parentAgentTaskId": "7c6fc151-1157-4d51-9a61-6092756baaa6", "source": "agent-89b7a3bf-b6a4-432e-8271-6baa38edf1d3", "supportedNativeDocumentMimeTypes": [], "transformedContent": "2026-08-27T09:21:34.891-03:00\n\nFind and summarize what the file big.py contains. Provide a concise overview of its purpose, main components, and key functions or classes. Start from the current working directory."}, "ephemeral": null, "id": "640a157e-9c48-49b9-9707-a43ef3c8aec2", "parentId": "aa7bf5c6-59d7-4322-a5df-9f6abe236cfa", "rawType": null, "timestamp": "2026-08-27 12:21:34.892000+00:00", "type": "user.message"} +{"agentId": "toolu_013RHgDCCnyFpE52pN1qXV2V", "data": {"interactionId": "20eb84fb-e525-431a-bb8b-a32042706ccf", "model": null, "turnId": "0"}, "ephemeral": true, "id": "c59d2699-e88b-4faa-8acc-3158c26a0fba", "parentId": "640a157e-9c48-49b9-9707-a43ef3c8aec2", "rawType": null, "timestamp": "2026-08-27 12:21:34.898000+00:00", "type": "assistant.turn_start"} +{"agentId": "toolu_013RHgDCCnyFpE52pN1qXV2V", "data": {"_previous_response_id": null, "model": "claude-haiku-4.5", "turnId": "0"}, "ephemeral": true, "id": "c9ef5c22-61e5-4edb-9f53-7e54b97d8a82", "parentId": "640a157e-9c48-49b9-9707-a43ef3c8aec2", "rawType": null, "timestamp": "2026-08-27 12:21:34.901000+00:00", "type": "model.call_start"} +{"agentId": "toolu_013RHgDCCnyFpE52pN1qXV2V", "data": {"_available_tool_count": 7, "_num_tool_calls": 1, "_tool_counts": {"view": 1}, "_tool_token_count": 1927, "apiCallId": "msg_011CeTF85PzNVko4FesJVGMr", "apiEndpoint": "/v1/messages", "cacheExpiresAt": null, "cacheReadTokens": 4459, "cacheWriteTokens": 617, "contentFilterTriggered": false, "copilotUsage": {"_token_details": [{"batchSize": 1000000, "costPerBatch": 100000000000, "tokenCount": 10, "tokenType": "input"}, {"batchSize": 1000000, "costPerBatch": 10000000000, "tokenCount": 4459, "tokenType": "cache_read"}, {"batchSize": 1000000, "costPerBatch": 125000000000, "tokenCount": 617, "tokenType": "cache_write"}, {"batchSize": 1000000, "costPerBatch": 500000000000, "tokenCount": 261, "tokenType": "output"}], "totalNanoAiu": 253215000.0}, "cost": 0.33, "duration": "0:00:03.295000", "finishReason": "tool_calls", "initiator": "sub-agent", "inputTokens": 5086, "interTokenLatency": "0:00:00.065564", "interactionType": "conversation-subagent", "model": "claude-haiku-4.5", "outputTokens": 261, "parentToolCallId": "toolu_013RHgDCCnyFpE52pN1qXV2V", "providerCallId": "29D8:38DC23:1996F14:1C55442:6A902BCF", "reasoningEffort": null, "reasoningTokens": 142, "rte": true, "serviceRequestId": "b283c0f7-fb2f-4206-b4f9-b0eaf5949313", "timeToFirstToken": "0:00:01.452775"}, "ephemeral": true, "id": "41a0285e-55ff-44a9-91ab-e7b3516a1b43", "parentId": "640a157e-9c48-49b9-9707-a43ef3c8aec2", "rawType": null, "timestamp": "2026-08-27 12:21:38.201000+00:00", "type": "assistant.usage"} +{"agentId": null, "data": {}, "ephemeral": true, "id": "d2dabef8-ef45-4d70-b6e7-52dbbddc9b07", "parentId": "640a157e-9c48-49b9-9707-a43ef3c8aec2", "rawType": null, "timestamp": "2026-08-27 12:21:38.202000+00:00", "type": "session.background_tasks_changed"} +{"agentId": null, "data": {}, "ephemeral": true, "id": "4bab9b94-fae6-4c01-ac30-1bbeecf1bb91", "parentId": "640a157e-9c48-49b9-9707-a43ef3c8aec2", "rawType": null, "timestamp": "2026-08-27 12:21:38.203000+00:00", "type": "session.background_tasks_changed"} +{"agentId": "toolu_013RHgDCCnyFpE52pN1qXV2V", "data": {"apiCallId": "msg_011CeTF85PzNVko4FesJVGMr", "chunkCount": null, "chunkIndex": null, "citations": null, "clientRequestId": "00000-4133c6d0-ad80-44d2-8ea2-105b83a494b6", "content": "", "interactionId": "20eb84fb-e525-431a-bb8b-a32042706ccf", "messageId": "4b674a04-f16a-4c0c-aeb3-9e095174669e", "model": "claude-haiku-4.5", "outputTokens": 261, "parentToolCallId": "toolu_013RHgDCCnyFpE52pN1qXV2V", "phase": null, "reasoningText": "The user wants me to find and summarize what the file `big.py` contains. They mention to start from the current working directory, which is `/private/tmp/claude-501/-Users-vini-Workspace-Openlayer-integrations-sdks/b3978e0d-127c-460e-869e-357293ac3d63/scratchpad/copilot-probe/ws`.\n\nLooking at the directory contents snapshot, I can see there are files: `big.py` and `small.py`.\n\nI should read the `big.py` file from the current working directory.", "requestId": "29D8:38DC23:1996F14:1C55442:6A902BCF", "rte": true, "serverTools": null, "serviceRequestId": "b283c0f7-fb2f-4206-b4f9-b0eaf5949313", "toolRequests": [{"arguments": {"path": "/private/tmp/claude-501/-Users-vini-Workspace-Openlayer-integrations-sdks/b3978e0d-127c-460e-869e-357293ac3d63/scratchpad/copilot-probe/ws/big.py"}, "intentionSummary": "view the file at /private/tmp/claude-501/-Users-vini-Workspace-Openlayer-integrations-sdks/b3978e0d-127c-460e-869e-357293ac3d63/scratchpad/copilot-probe/ws/big.py.", "mcpServerName": null, "mcpToolName": null, "name": "view", "toolCallId": "toolu_01SgcAmR9KobrmGTHzSSxx3T", "toolTitle": null, "type": "function"}], "turnId": "0"}, "ephemeral": null, "id": "34f4ef7e-210a-4d03-8a5a-87ac0db647a6", "parentId": "640a157e-9c48-49b9-9707-a43ef3c8aec2", "rawType": null, "timestamp": "2026-08-27 12:21:38.204000+00:00", "type": "assistant.message"} +{"agentId": "toolu_013RHgDCCnyFpE52pN1qXV2V", "data": {"arguments": {"path": "/private/tmp/claude-501/-Users-vini-Workspace-Openlayer-integrations-sdks/b3978e0d-127c-460e-869e-357293ac3d63/scratchpad/copilot-probe/ws/big.py"}, "displayVerbatim": null, "mcpServerName": null, "mcpToolName": null, "model": "claude-haiku-4.5", "parentToolCallId": "toolu_013RHgDCCnyFpE52pN1qXV2V", "rte": true, "shellToolInfo": null, "toolCallId": "toolu_01SgcAmR9KobrmGTHzSSxx3T", "toolDescription": null, "toolName": "view", "turnId": "0"}, "ephemeral": null, "id": "d1a6b884-0f35-4ec2-9570-8763d6ef3d28", "parentId": "34f4ef7e-210a-4d03-8a5a-87ac0db647a6", "rawType": null, "timestamp": "2026-08-27 12:21:38.205000+00:00", "type": "tool.execution_start"} +{"agentId": null, "data": {"permissionRequest": {"intention": "Read file: /private/tmp/claude-501/-Users-vini-Workspace-Openlayer-integrations-sdks/b3978e0d-127c-460e-869e-357293ac3d63/scratchpad/copilot-probe/ws/big.py", "managedApprovalRequired": null, "path": "/private/tmp/claude-501/-Users-vini-Workspace-Openlayer-integrations-sdks/b3978e0d-127c-460e-869e-357293ac3d63/scratchpad/copilot-probe/ws/big.py", "requestSandboxBypass": null, "requestSandboxBypassReason": null, "toolCallId": "toolu_01SgcAmR9KobrmGTHzSSxx3T"}, "promptRequest": {"autoApproval": null, "intention": "Read file: /private/tmp/claude-501/-Users-vini-Workspace-Openlayer-integrations-sdks/b3978e0d-127c-460e-869e-357293ac3d63/scratchpad/copilot-probe/ws/big.py", "managedApprovalRequired": null, "path": "/private/tmp/claude-501/-Users-vini-Workspace-Openlayer-integrations-sdks/b3978e0d-127c-460e-869e-357293ac3d63/scratchpad/copilot-probe/ws/big.py", "toolCallId": "toolu_01SgcAmR9KobrmGTHzSSxx3T"}, "requestId": "b48ecd49-bca6-47b6-ab9f-e90b220c496d", "resolvedByHook": null, "riskAssessment": null}, "ephemeral": null, "id": "fcd2b7da-6e0c-4a95-a67b-8caca9db9812", "parentId": "d1a6b884-0f35-4ec2-9570-8763d6ef3d28", "rawType": null, "timestamp": "2026-08-27 12:21:38.211000+00:00", "type": "permission.requested"} +{"agentId": null, "data": {"requestId": "b48ecd49-bca6-47b6-ab9f-e90b220c496d", "result": {}, "toolCallId": "toolu_01SgcAmR9KobrmGTHzSSxx3T"}, "ephemeral": null, "id": "1799aae9-808c-482d-ba44-f5acd0b5d63c", "parentId": "fcd2b7da-6e0c-4a95-a67b-8caca9db9812", "rawType": null, "timestamp": "2026-08-27 12:21:38.212000+00:00", "type": "permission.completed"} +{"agentId": "toolu_013RHgDCCnyFpE52pN1qXV2V", "data": {"error": null, "interactionId": "20eb84fb-e525-431a-bb8b-a32042706ccf", "isUserRequested": null, "mcpMeta": null, "model": "claude-haiku-4.5", "parentToolCallId": "toolu_013RHgDCCnyFpE52pN1qXV2V", "result": {"binaryResultsForLlm": null, "citableSources": null, "content": "1. def f0(x):\n2. \"\"\"Function 0.\"\"\"\n3. return x*0\n4. \n5. def f1(x):\n6. \"\"\"Function 1.\"\"\"\n7. return x*1\n8. \n9. def f2(x):\n10. \"\"\"Function 2.\"\"\"\n11. return x*2\n12. \n13. def f3(x):\n14. \"\"\"Function 3.\"\"\"\n15. return x*3\n16. \n17. def f4(x):\n18. \"\"\"Function 4.\"\"\"\n19. return x*4\n20. \n21. def f5(x):\n22. \"\"\"Function 5.\"\"\"\n23. return x*5\n24. \n25. def f6(x):\n26. \"\"\"Function 6.\"\"\"\n27. return x*6\n28. \n29. def f7(x):\n30. \"\"\"Function 7.\"\"\"\n31. return x*7\n32. \n33. def f8(x):\n34. \"\"\"Function 8.\"\"\"\n35. return x*8\n36. \n37. def f9(x):\n38. \"\"\"Function 9.\"\"\"\n39. return x*9\n40. \n41. def f10(x):\n42. \"\"\"Function 10.\"\"\"\n43. return x*10\n44. \n45. def f11(x):\n46. \"\"\"Function 11.\"\"\"\n47. return x*11\n48. \n49. def f12(x):\n50. \"\"\"Function 12.\"\"\"\n51. return x*12\n52. \n53. def f13(x):\n54. \"\"\"Function 13.\"\"\"\n55. return x*13\n56. \n57. def f14(x):\n58. \"\"\"Function 14.\"\"\"\n59. return x*14\n60. \n61. def f15(x):\n62. \"\"\"Function 15.\"\"\"\n63. return x*15\n64. \n65. def f16(x):\n66. \"\"\"Function 16.\"\"\"\n67. return x*16\n68. \n69. def f17(x):\n70. \"\"\"Function 17.\"\"\"\n71. return x*17\n72. \n73. def f18(x):\n74. \"\"\"Function 18.\"\"\"\n75. return x*18\n76. \n77. def f19(x):\n78. \"\"\"Function 19.\"\"\"\n79. return x*19\n80. \n81. def f20(x):\n82. \"\"\"Function 20.\"\"\"\n83. return x*20\n84. \n85. def f21(x):\n86. \"\"\"Function 21.\"\"\"\n87. return x*21\n88. \n89. def f22(x):\n90. \"\"\"Function 22.\"\"\"\n91. return x*22\n92. \n93. def f23(x):\n94. \"\"\"Function 23.\"\"\"\n95. return x*23\n96. \n97. def f24(x):\n98. \"\"\"Function 24.\"\"\"\n99. return x*24\n100. \n101. def f25(x):\n102. \"\"\"Function 25.\"\"\"\n103. return x*25\n104. \n105. def f26(x):\n106. \"\"\"Function 26.\"\"\"\n107. return x*26\n108. \n109. def f27(x):\n110. \"\"\"Function 27.\"\"\"\n111. return x*27\n112. \n113. def f28(x):\n114. \"\"\"Function 28.\"\"\"\n115. return x*28\n116. \n117. def f29(x):\n118. \"\"\"Function 29.\"\"\"\n119. return x*29\n120. \n121. def f30(x):\n122. \"\"\"Function 30.\"\"\"\n123. return x*30\n124. \n125. def f31(x):\n126. \"\"\"Function 31.\"\"\"\n127. return x*31\n128. \n129. def f32(x):\n130. \"\"\"Function 32.\"\"\"\n131. return x*32\n132. \n133. def f33(x):\n134. \"\"\"Function 33.\"\"\"\n135. return x*33\n136. \n137. def f34(x):\n138. \"\"\"Function 34.\"\"\"\n139. return x*34\n140. \n141. def f35(x):\n142. \"\"\"Function 35.\"\"\"\n143. return x*35\n144. \n145. def f36(x):\n146. \"\"\"Function 36.\"\"\"\n147. return x*36\n148. \n149. def f37(x):\n150. \"\"\"Function 37.\"\"\"\n151. return x*37\n152. \n153. def f38(x):\n154. \"\"\"Function 38.\"\"\"\n155. return x*38\n156. \n157. def f39(x):\n158. \"\"\"Function 39.\"\"\"\n159. return x*39\n160. ", "contents": null, "detailedContent": "\ndiff --git a/private/tmp/claude-501/-Users-vini-Workspace-Openlayer-integrations-sdks/b3978e0d-127c-460e-869e-357293ac3d63/scratchpad/copilot-probe/ws/big.py b/private/tmp/claude-501/-Users-vini-Workspace-Openlayer-integrations-sdks/b3978e0d-127c-460e-869e-357293ac3d63/scratchpad/copilot-probe/ws/big.py\nindex 0000000..0000000 100644\n--- a/private/tmp/claude-501/-Users-vini-Workspace-Openlayer-integrations-sdks/b3978e0d-127c-460e-869e-357293ac3d63/scratchpad/copilot-probe/ws/big.py\n+++ b/private/tmp/claude-501/-Users-vini-Workspace-Openlayer-integrations-sdks/b3978e0d-127c-460e-869e-357293ac3d63/scratchpad/copilot-probe/ws/big.py\n@@ -1,160 +1,160 @@\n def f0(x):\n \"\"\"Function 0.\"\"\"\n return x*0\n \n def f1(x):\n \"\"\"Function 1.\"\"\"\n return x*1\n \n def f2(x):\n \"\"\"Function 2.\"\"\"\n return x*2\n \n def f3(x):\n \"\"\"Function 3.\"\"\"\n return x*3\n \n def f4(x):\n \"\"\"Function 4.\"\"\"\n return x*4\n \n def f5(x):\n \"\"\"Function 5.\"\"\"\n return x*5\n \n def f6(x):\n \"\"\"Function 6.\"\"\"\n return x*6\n \n def f7(x):\n \"\"\"Function 7.\"\"\"\n return x*7\n \n def f8(x):\n \"\"\"Function 8.\"\"\"\n return x*8\n \n def f9(x):\n \"\"\"Function 9.\"\"\"\n return x*9\n \n def f10(x):\n \"\"\"Function 10.\"\"\"\n return x*10\n \n def f11(x):\n \"\"\"Function 11.\"\"\"\n return x*11\n \n def f12(x):\n \"\"\"Function 12.\"\"\"\n return x*12\n \n def f13(x):\n \"\"\"Function 13.\"\"\"\n return x*13\n \n def f14(x):\n \"\"\"Function 14.\"\"\"\n return x*14\n \n def f15(x):\n \"\"\"Function 15.\"\"\"\n return x*15\n \n def f16(x):\n \"\"\"Function 16.\"\"\"\n return x*16\n \n def f17(x):\n \"\"\"Function 17.\"\"\"\n return x*17\n \n def f18(x):\n \"\"\"Function 18.\"\"\"\n return x*18\n \n def f19(x):\n \"\"\"Function 19.\"\"\"\n return x*19\n \n def f20(x):\n \"\"\"Function 20.\"\"\"\n return x*20\n \n def f21(x):\n \"\"\"Function 21.\"\"\"\n return x*21\n \n def f22(x):\n \"\"\"Function 22.\"\"\"\n return x*22\n \n def f23(x):\n \"\"\"Function 23.\"\"\"\n return x*23\n \n def f24(x):\n \"\"\"Function 24.\"\"\"\n return x*24\n \n def f25(x):\n \"\"\"Function 25.\"\"\"\n return x*25\n \n def f26(x):\n \"\"\"Function 26.\"\"\"\n return x*26\n \n def f27(x):\n \"\"\"Function 27.\"\"\"\n return x*27\n \n def f28(x):\n \"\"\"Function 28.\"\"\"\n return x*28\n \n def f29(x):\n \"\"\"Function 29.\"\"\"\n return x*29\n \n def f30(x):\n \"\"\"Function 30.\"\"\"\n return x*30\n \n def f31(x):\n \"\"\"Function 31.\"\"\"\n return x*31\n \n def f32(x):\n \"\"\"Function 32.\"\"\"\n return x*32\n \n def f33(x):\n \"\"\"Function 33.\"\"\"\n return x*33\n \n def f34(x):\n \"\"\"Function 34.\"\"\"\n return x*34\n \n def f35(x):\n \"\"\"Function 35.\"\"\"\n return x*35\n \n def f36(x):\n \"\"\"Function 36.\"\"\"\n return x*36\n \n def f37(x):\n \"\"\"Function 37.\"\"\"\n return x*37\n \n def f38(x):\n \"\"\"Function 38.\"\"\"\n return x*38\n \n def f39(x):\n \"\"\"Function 39.\"\"\"\n return x*39\n \n", "mcpMeta": null, "structuredContent": null, "uiResource": null}, "rte": true, "sandboxed": null, "success": true, "toolCallId": "toolu_01SgcAmR9KobrmGTHzSSxx3T", "toolDescription": null, "toolTelemetry": {"metrics": {"responseTokenLimit": 32000, "resultForLlmLength": 2741, "resultLength": 2741}, "properties": {"command": "view", "fileExtension": "[\".py\"]", "inputs": "[\"path\",\"command\"]", "options": "{\"truncateBasedOn\":\"tokenCount\",\"truncateStyle\":\"middle\"}", "resolvedPathAgainstCwd": "false", "viewType": "file"}, "restrictedProperties": {}}, "turnId": "0"}, "ephemeral": null, "id": "f2ae002a-3a10-4448-81f1-979f3e775dcb", "parentId": "1799aae9-808c-482d-ba44-f5acd0b5d63c", "rawType": null, "timestamp": "2026-08-27 12:21:38.215000+00:00", "type": "tool.execution_complete"} +{"agentId": null, "data": {}, "ephemeral": true, "id": "ff7f2a82-9552-46d9-9c2b-01237ac14082", "parentId": "f2ae002a-3a10-4448-81f1-979f3e775dcb", "rawType": null, "timestamp": "2026-08-27 12:21:38.217000+00:00", "type": "session.background_tasks_changed"} +{"agentId": "toolu_013RHgDCCnyFpE52pN1qXV2V", "data": {"model": null, "turnId": "0"}, "ephemeral": true, "id": "4dd58e1c-111f-444a-85ee-65819a409138", "parentId": "f2ae002a-3a10-4448-81f1-979f3e775dcb", "rawType": null, "timestamp": "2026-08-27 12:21:38.223000+00:00", "type": "assistant.turn_end"} +{"agentId": "toolu_013RHgDCCnyFpE52pN1qXV2V", "data": {"interactionId": "20eb84fb-e525-431a-bb8b-a32042706ccf", "model": null, "turnId": "1"}, "ephemeral": true, "id": "2955fdb0-5c9c-47e9-ae02-5f656577c131", "parentId": "f2ae002a-3a10-4448-81f1-979f3e775dcb", "rawType": null, "timestamp": "2026-08-27 12:21:38.223000+00:00", "type": "assistant.turn_start"} +{"agentId": "toolu_013RHgDCCnyFpE52pN1qXV2V", "data": {"_previous_response_id": null, "model": "claude-haiku-4.5", "turnId": "1"}, "ephemeral": true, "id": "d674ee34-3683-402f-b264-2c60a99bda3a", "parentId": "f2ae002a-3a10-4448-81f1-979f3e775dcb", "rawType": null, "timestamp": "2026-08-27 12:21:38.225000+00:00", "type": "model.call_start"} +{"agentId": "toolu_013RHgDCCnyFpE52pN1qXV2V", "data": {"deltaContent": "##", "messageId": "0189d126-23f1-4aad-ad6d-d4539eaf7380", "parentToolCallId": "toolu_013RHgDCCnyFpE52pN1qXV2V"}, "ephemeral": true, "id": "225c3c0d-83a1-4665-9863-7c46a74e217d", "parentId": "f2ae002a-3a10-4448-81f1-979f3e775dcb", "rawType": null, "timestamp": "2026-08-27 12:21:39.109000+00:00", "type": "assistant.message_delta"} +{"agentId": "toolu_013RHgDCCnyFpE52pN1qXV2V", "data": {"deltaContent": " Summary of `big.py`\n\n**Purpose:** A utility module containing simple", "messageId": "0189d126-23f1-4aad-ad6d-d4539eaf7380", "parentToolCallId": "toolu_013RHgDCCnyFpE52pN1qXV2V"}, "ephemeral": true, "id": "80bb265a-2339-470a-a743-a583b147347a", "parentId": "f2ae002a-3a10-4448-81f1-979f3e775dcb", "rawType": null, "timestamp": "2026-08-27 12:21:39.637000+00:00", "type": "assistant.message_delta"} +{"agentId": "toolu_013RHgDCCnyFpE52pN1qXV2V", "data": {"deltaContent": " mathematical multiplication functions.\n\n**Main Components:**\n- **40 simple functions** named `f0()", "messageId": "0189d126-23f1-4aad-ad6d-d4539eaf7380", "parentToolCallId": "toolu_013RHgDCCnyFpE52pN1qXV2V"}, "ephemeral": true, "id": "1ec96ac2-1353-4fa1-8a49-726fa479c7b0", "parentId": "f2ae002a-3a10-4448-81f1-979f3e775dcb", "rawType": null, "timestamp": "2026-08-27 12:21:39.638000+00:00", "type": "assistant.message_delta"} +{"agentId": "toolu_013RHgDCCnyFpE52pN1qXV2V", "data": {"_available_tool_count": 7, "_num_tool_calls": 0, "_tool_counts": {}, "_tool_token_count": 1927, "apiCallId": "msg_011CeTF8HBexg1qmKgJneMfz", "apiEndpoint": "/v1/messages", "cacheExpiresAt": null, "cacheReadTokens": 5076, "cacheWriteTokens": 1475, "contentFilterTriggered": false, "copilotUsage": {"_token_details": [{"batchSize": 1000000, "costPerBatch": 100000000000, "tokenCount": 6, "tokenType": "input"}, {"batchSize": 1000000, "costPerBatch": 10000000000, "tokenCount": 5076, "tokenType": "cache_read"}, {"batchSize": 1000000, "costPerBatch": 125000000000, "tokenCount": 1475, "tokenType": "cache_write"}, {"batchSize": 1000000, "costPerBatch": 500000000000, "tokenCount": 186, "tokenType": "output"}], "totalNanoAiu": 328735000.0}, "cost": 0.33, "duration": "0:00:02.959000", "finishReason": "stop", "initiator": "sub-agent", "inputTokens": 6557, "interTokenLatency": "0:00:00.259051", "interactionType": "conversation-subagent", "model": "claude-haiku-4.5", "outputTokens": 186, "parentToolCallId": "toolu_013RHgDCCnyFpE52pN1qXV2V", "providerCallId": "29D8:38DC23:19981E1:1C568E0:6A902BD2", "reasoningEffort": null, "reasoningTokens": 0, "rte": true, "serviceRequestId": "6bc6efd5-fab7-4316-a75d-71815f0b600e", "timeToFirstToken": "0:00:00.883867"}, "ephemeral": true, "id": "79578a1e-17c2-4b9d-a8a2-c119a064dea3", "parentId": "f2ae002a-3a10-4448-81f1-979f3e775dcb", "rawType": null, "timestamp": "2026-08-27 12:21:41.188000+00:00", "type": "assistant.usage"} +{"agentId": null, "data": {}, "ephemeral": true, "id": "43e11e75-bd5c-4020-ba1e-58a487b4f7a7", "parentId": "f2ae002a-3a10-4448-81f1-979f3e775dcb", "rawType": null, "timestamp": "2026-08-27 12:21:41.189000+00:00", "type": "session.background_tasks_changed"} +{"agentId": null, "data": {}, "ephemeral": true, "id": "6ed2cbe2-801c-4eb6-9a97-d0464d03dbc1", "parentId": "f2ae002a-3a10-4448-81f1-979f3e775dcb", "rawType": null, "timestamp": "2026-08-27 12:21:41.189000+00:00", "type": "session.background_tasks_changed"} +{"agentId": "toolu_013RHgDCCnyFpE52pN1qXV2V", "data": {"apiCallId": "msg_011CeTF8HBexg1qmKgJneMfz", "chunkCount": null, "chunkIndex": null, "citations": null, "clientRequestId": "00000-4637bc37-e1a9-43ec-aa4b-ec70801981de", "content": "## Summary of `big.py`\n\n**Purpose:** A utility module containing simple mathematical multiplication functions.\n\n**Main Components:**\n- **40 simple functions** named `f0()` through `f39()`\n- Each function follows an identical pattern with a docstring\n\n**Key Functions:**\n- `f0(x)` through `f39(x)` - Each function takes a single parameter `x` and returns `x` multiplied by the function's index number\n - Example: `f0(x)` returns `x*0`, `f1(x)` returns `x*1`, `f39(x)` returns `x*39`\n\n**Overall:** A straightforward module containing 40 repetitive multiplication functions with predictable behavior. Each function multiplies its input by its corresponding index (0-39).", "interactionId": "20eb84fb-e525-431a-bb8b-a32042706ccf", "messageId": "0189d126-23f1-4aad-ad6d-d4539eaf7380", "model": "claude-haiku-4.5", "outputTokens": 186, "parentToolCallId": "toolu_013RHgDCCnyFpE52pN1qXV2V", "phase": null, "reasoningText": "The user wants me to find and summarize what the file `big.py` contains. They mention to start from the current working directory, which is `/private/tmp/claude-501/-Users-vini-Workspace-Openlayer-integrations-sdks/b3978e0d-127c-460e-869e-357293ac3d63/scratchpad/copilot-probe/ws`.\n\nLooking at the directory contents snapshot, I can see there are files: `big.py` and `small.py`.\n\nI should read the `big.py` file from the current working directory.", "requestId": "29D8:38DC23:19981E1:1C568E0:6A902BD2", "rte": true, "serverTools": null, "serviceRequestId": "6bc6efd5-fab7-4316-a75d-71815f0b600e", "toolRequests": [], "turnId": "1"}, "ephemeral": null, "id": "588c31d8-eb5a-435e-a927-77e52b53aadf", "parentId": "f2ae002a-3a10-4448-81f1-979f3e775dcb", "rawType": null, "timestamp": "2026-08-27 12:21:41.190000+00:00", "type": "assistant.message"} +{"agentId": "toolu_013RHgDCCnyFpE52pN1qXV2V", "data": {"model": null, "turnId": "1"}, "ephemeral": true, "id": "8cc74619-a76b-46be-be76-f6920c4b5360", "parentId": "588c31d8-eb5a-435e-a927-77e52b53aadf", "rawType": null, "timestamp": "2026-08-27 12:21:41.190000+00:00", "type": "assistant.turn_end"} +{"agentId": null, "data": {}, "ephemeral": true, "id": "56e0152c-4047-491e-ac83-377c42c5382b", "parentId": "588c31d8-eb5a-435e-a927-77e52b53aadf", "rawType": null, "timestamp": "2026-08-27 12:21:41.201000+00:00", "type": "session.background_tasks_changed"} +{"agentId": null, "data": {}, "ephemeral": true, "id": "31c0a579-bd7a-480f-addd-cef84066a9fc", "parentId": "588c31d8-eb5a-435e-a927-77e52b53aadf", "rawType": null, "timestamp": "2026-08-27 12:21:41.202000+00:00", "type": "session.background_tasks_changed"} +{"agentId": "toolu_013RHgDCCnyFpE52pN1qXV2V", "data": {"agentDisplayName": "Explore Agent", "agentName": "explore", "cancelled": null, "duration": "0:00:06.385000", "model": "claude-haiku-4.5", "toolCallId": "toolu_013RHgDCCnyFpE52pN1qXV2V", "totalTokens": 12090, "totalToolCalls": 1}, "ephemeral": null, "id": "88ae233c-99ff-4ede-8f07-05bef88568fe", "parentId": "588c31d8-eb5a-435e-a927-77e52b53aadf", "rawType": null, "timestamp": "2026-08-27 12:21:41.203000+00:00", "type": "subagent.completed"} +{"agentId": null, "data": {}, "ephemeral": true, "id": "eafe0dec-0512-4dd0-baa8-67e1cd84793f", "parentId": "88ae233c-99ff-4ede-8f07-05bef88568fe", "rawType": null, "timestamp": "2026-08-27 12:21:41.203000+00:00", "type": "session.background_tasks_changed"} +{"agentId": null, "data": {}, "ephemeral": true, "id": "954eb7dc-0186-4073-98e2-c2d2e800affb", "parentId": "88ae233c-99ff-4ede-8f07-05bef88568fe", "rawType": null, "timestamp": "2026-08-27 12:21:41.204000+00:00", "type": "session.background_tasks_changed"} +{"agentId": null, "data": {"error": null, "interactionId": "56b1e0b4-f34f-43d0-a86f-0692557873f7", "isUserRequested": null, "mcpMeta": null, "model": "claude-haiku-4.5", "parentToolCallId": null, "result": {"binaryResultsForLlm": null, "citableSources": null, "content": "It is 22C and sunny in Lisbon.", "contents": null, "detailedContent": "It is 22C and sunny in Lisbon.", "mcpMeta": null, "structuredContent": null, "uiResource": null}, "rte": true, "sandboxed": null, "success": true, "toolCallId": "toolu_01QdopvJHQsZ7XUzM4oHnFie", "toolDescription": null, "toolTelemetry": {}, "turnId": "0"}, "ephemeral": null, "id": "1b1d5f1a-f2a4-42c9-9326-25536c96988c", "parentId": "88ae233c-99ff-4ede-8f07-05bef88568fe", "rawType": null, "timestamp": "2026-08-27 12:21:41.206000+00:00", "type": "tool.execution_complete"} +{"agentId": null, "data": {"error": null, "interactionId": "56b1e0b4-f34f-43d0-a86f-0692557873f7", "isUserRequested": null, "mcpMeta": null, "model": "claude-haiku-4.5", "parentToolCallId": null, "result": {"binaryResultsForLlm": null, "citableSources": null, "content": "total 16\n-rw-r--r-- 1 vini wheel 2049 Aug 27 09:18 big.py\n-rw-r--r-- 1 vini wheel 29 Aug 27 09:18 small.py\n", "contents": [{"cwd": "/private/tmp/claude-501/-Users-vini-Workspace-Openlayer-integrations-sdks/b3978e0d-127c-460e-869e-357293ac3d63/scratchpad/copilot-probe/ws", "exitCode": 0, "outputPreview": "total 16\n-rw-r--r-- 1 vini wheel 2049 Aug 27 09:18 big.py\n-rw-r--r-- 1 vini wheel 29 Aug 27 09:18 small.py\n", "outputTruncated": false, "shellId": "0"}], "detailedContent": "total 16\n-rw-r--r-- 1 vini wheel 2049 Aug 27 09:18 big.py\n-rw-r--r-- 1 vini wheel 29 Aug 27 09:18 small.py\n", "mcpMeta": null, "structuredContent": null, "uiResource": null}, "rte": true, "sandboxed": null, "success": true, "toolCallId": "toolu_01EBTnVYRCkb8NdiWsyoTGxR", "toolDescription": null, "toolTelemetry": {"metrics": {"commandTimeout": 30000}, "properties": {"asyncOnlyShell": "false", "customTimeout": "false", "detached": "false", "executionMode": "sync", "sandboxApplied": "false", "sandboxOptOutRequested": "false"}}, "turnId": "0"}, "ephemeral": null, "id": "96838c32-66ef-4e0f-ab59-2946e4e6b0a5", "parentId": "1b1d5f1a-f2a4-42c9-9326-25536c96988c", "rawType": null, "timestamp": "2026-08-27 12:21:41.207000+00:00", "type": "tool.execution_complete"} +{"agentId": null, "data": {"error": null, "interactionId": "56b1e0b4-f34f-43d0-a86f-0692557873f7", "isUserRequested": null, "mcpMeta": null, "model": "claude-haiku-4.5", "parentToolCallId": null, "result": {"binaryResultsForLlm": null, "citableSources": null, "content": "## Summary of `big.py`\n\n**Purpose:** A utility module containing simple mathematical multiplication functions.\n\n**Main Components:**\n- **40 simple functions** named `f0()` through `f39()`\n- Each function follows an identical pattern with a docstring\n\n**Key Functions:**\n- `f0(x)` through `f39(x)` - Each function takes a single parameter `x` and returns `x` multiplied by the function's index number\n - Example: `f0(x)` returns `x*0`, `f1(x)` returns `x*1`, `f39(x)` returns `x*39`\n\n**Overall:** A straightforward module containing 40 repetitive multiplication functions with predictable behavior. Each function multiplies its input by its corresponding index (0-39).", "contents": null, "detailedContent": "## Summary of `big.py`\n\n**Purpose:** A utility module containing simple mathematical multiplication functions.\n\n**Main Components:**\n- **40 simple functions** named `f0()` through `f39()`\n- Each function follows an identical pattern with a docstring\n\n**Key Functions:**\n- `f0(x)` through `f39(x)` - Each function takes a single parameter `x` and returns `x` multiplied by the function's index number\n - Example: `f0(x)` returns `x*0`, `f1(x)` returns `x*1`, `f39(x)` returns `x*39`\n\n**Overall:** A straightforward module containing 40 repetitive multiplication functions with predictable behavior. Each function multiplies its input by its corresponding index (0-39).", "mcpMeta": null, "structuredContent": null, "uiResource": null}, "rte": true, "sandboxed": null, "success": true, "toolCallId": "toolu_013RHgDCCnyFpE52pN1qXV2V", "toolDescription": null, "toolTelemetry": {"metrics": {"numberOfToolCallsMadeByAgent": 1, "responseLength": 668}, "properties": {"agentName": "explore", "agentType": "explore", "executionMode": "sync", "promptLength": "181", "responseLength": "668"}, "restrictedProperties": {"agentId": "big-py-summary", "agentName": "explore"}}, "turnId": "0"}, "ephemeral": null, "id": "c0d22056-0fb8-4ddb-96fd-d8dfc9b03cb4", "parentId": "96838c32-66ef-4e0f-ab59-2946e4e6b0a5", "rawType": null, "timestamp": "2026-08-27 12:21:41.209000+00:00", "type": "tool.execution_complete"} +{"agentId": null, "data": {"model": null, "turnId": "0"}, "ephemeral": null, "id": "497eb10e-3023-46a4-88e7-c51f472282a3", "parentId": "c0d22056-0fb8-4ddb-96fd-d8dfc9b03cb4", "rawType": null, "timestamp": "2026-08-27 12:21:41.218000+00:00", "type": "assistant.turn_end"} +{"agentId": null, "data": {"interactionId": "56b1e0b4-f34f-43d0-a86f-0692557873f7", "model": null, "turnId": "1"}, "ephemeral": null, "id": "ea076ab4-bdf6-4177-8671-a35bc1dc5ee0", "parentId": "497eb10e-3023-46a4-88e7-c51f472282a3", "rawType": null, "timestamp": "2026-08-27 12:21:41.219000+00:00", "type": "assistant.turn_start"} +{"agentId": null, "data": {"conversationTokens": 808, "currentTokens": 11271, "isInitial": false, "messagesLength": 7, "systemTokens": 5224, "tokenLimit": 128000, "toolDefinitionsTokens": 5239}, "ephemeral": true, "id": "522e46c7-be4f-416c-862b-eaf550485ee1", "parentId": "ea076ab4-bdf6-4177-8671-a35bc1dc5ee0", "rawType": null, "timestamp": "2026-08-27 12:21:41.220000+00:00", "type": "session.usage_info"} +{"agentId": null, "data": {"_previous_response_id": null, "model": "claude-haiku-4.5", "turnId": "1"}, "ephemeral": true, "id": "3da937fc-3b65-4f37-b0d7-053e3b9ddde7", "parentId": "ea076ab4-bdf6-4177-8671-a35bc1dc5ee0", "rawType": null, "timestamp": "2026-08-27 12:21:41.222000+00:00", "type": "model.call_start"} +{"agentId": null, "data": {"messageId": "917ef4ed-490b-46e6-93ea-6b1960aa5e40", "phase": null}, "ephemeral": true, "id": "3e37b21a-904e-4b7f-bb74-7d53b41277a1", "parentId": "ea076ab4-bdf6-4177-8671-a35bc1dc5ee0", "rawType": null, "timestamp": "2026-08-27 12:21:42.255000+00:00", "type": "assistant.message_start"} +{"agentId": null, "data": {"_available_tool_count": 17, "_num_tool_calls": 0, "_tool_counts": {}, "_tool_token_count": 5239, "apiCallId": "msg_011CeTF8WA1np73VJacyyHRj", "apiEndpoint": "/v1/messages", "cacheExpiresAt": "2026-08-27 12:26:41.232000+00:00", "cacheReadTokens": 12595, "cacheWriteTokens": 754, "contentFilterTriggered": false, "copilotUsage": {"_token_details": [{"batchSize": 1000000, "costPerBatch": 100000000000, "tokenCount": 7, "tokenType": "input"}, {"batchSize": 1000000, "costPerBatch": 10000000000, "tokenCount": 12595, "tokenType": "cache_read"}, {"batchSize": 1000000, "costPerBatch": 125000000000, "tokenCount": 754, "tokenType": "cache_write"}, {"batchSize": 1000000, "costPerBatch": 500000000000, "tokenCount": 127, "tokenType": "output"}], "totalNanoAiu": 284400000.0}, "cost": 0.33, "duration": "0:00:02.066000", "finishReason": "stop", "initiator": "agent", "inputTokens": 13356, "interTokenLatency": "0:00:00.206742", "interactionType": "conversation-agent", "model": "claude-haiku-4.5", "outputTokens": 127, "parentToolCallId": null, "providerCallId": "29D8:38DC23:1999209:1C57AD8:6A902BD5", "reasoningEffort": null, "reasoningTokens": 0, "rte": true, "serviceRequestId": "9db204e2-902b-43e6-a4a7-144e2e6b29c3", "timeToFirstToken": "0:00:01.032130"}, "ephemeral": true, "id": "1f797f42-565b-4a0d-8df3-48fcb64c581a", "parentId": "ea076ab4-bdf6-4177-8671-a35bc1dc5ee0", "rawType": null, "timestamp": "2026-08-27 12:21:43.298000+00:00", "type": "assistant.usage"} +{"agentId": null, "data": {"apiCallId": "msg_011CeTF8WA1np73VJacyyHRj", "chunkCount": null, "chunkIndex": null, "citations": null, "clientRequestId": "00000-7b0604cd-46a1-43f4-9078-862dbace3125", "content": "Done! Here's what I found:\n\n**Weather:** It's 22\u00b0C and sunny in Lisbon \ud83c\udf1e\n\n**Directory listing:** Two Python files in the current directory:\n- `big.py` (2049 bytes)\n- `small.py` (29 bytes)\n\n**big.py summary:** A utility module with 40 simple mathematical functions (`f0()` through `f39()`), each multiplying its input by its corresponding index number (e.g., `f5(x)` returns `x*5`).", "interactionId": "56b1e0b4-f34f-43d0-a86f-0692557873f7", "messageId": "917ef4ed-490b-46e6-93ea-6b1960aa5e40", "model": "claude-haiku-4.5", "outputTokens": 127, "parentToolCallId": null, "phase": null, "reasoningText": "The user wants me to do three things:\n1. Call get_weather tool for Lisbon\n2. Run `ls -l` with bash\n3. Delegate to a subagent to summarize what big.py contains\n\nLet me do all three in parallel since they're independent. I'll:\n1. Call get_weather with city \"Lisbon\"\n2. Call bash with command \"ls -l\"\n3. Call task tool to delegate to an explore agent to summarize big.py\n\nAll three can be done in parallel in one function_calls block.", "requestId": "29D8:38DC23:1999209:1C57AD8:6A902BD5", "rte": true, "serverTools": null, "serviceRequestId": "9db204e2-902b-43e6-a4a7-144e2e6b29c3", "toolRequests": [], "turnId": "1"}, "ephemeral": null, "id": "cdd6ad3e-f99d-4de4-8362-4a227a7896cd", "parentId": "ea076ab4-bdf6-4177-8671-a35bc1dc5ee0", "rawType": null, "timestamp": "2026-08-27 12:21:43.300000+00:00", "type": "assistant.message"} +{"agentId": null, "data": {"content": "The user wants me to do three things:\n1. Call get_weather tool for Lisbon\n2. Run `ls -l` with bash\n3. Delegate to a subagent to summarize what big.py contains\n\nLet me do all three in parallel since they're independent. I'll:\n1. Call get_weather with city \"Lisbon\"\n2. Call bash with command \"ls -l\"\n3. Call task tool to delegate to an explore agent to summarize big.py\n\nAll three can be done in parallel in one function_calls block.", "reasoningId": "EsUFCrIBCBEYAipAxEZVo6VXl5V7Q6WG0A1LMnhXGT2yrx7QNKYH4t9NyVQCWnZxoMQw7RpOU2dXaN6CvYfM9nq0FxgC/cOxlVPpAzIZY2xhdWRlLWhhaWt1LTQtNS0yMDI1MTAwMTgAQgh0aGlua2luZ1okY2VkMWY5OGUtMGI1MS00NjEwLTgyODItNGU1ZDg4Mzg0NTc0chAFJi2jM86AcGV3hjaN37r2iAEBqAHN18DUBrABAhIMM3OXz1+2fTUJJFIYGgz5Vne6wpbmMYkZyLoiMEjaGlA4NC92mWYqFLeKvOqwlEJmUJiTZSsnKS31By+pFwBS9QHE3hAjS4gYVzYfPiq/A2bIw/J1D6LK0twDbft4FYTd3rLO9Rfyi1z2R98LLrRSuUncvUTb82mfi3WddrFm5yyb8SdOLx5sWJ5L8+QiWmBAbK/r/0ANrjuQ/WJLtaaQUGxpklMkP5dkRln/HNHHj7DN1nsc50bzoZT+XccpQrTFzvrmvGfAmypFX3i9dQC6ties53zr8se4tWq14cis1VvMee9NGCFDM+mUg5jpod6qWAVOj90Eog9o+K0iF7KtiDQEn4tfxF4H1ZwhEN86W5+Nyd8ZYB20VVF0Rfb0mYqZs/6PhPbhKg9P62aeB5uroajOlIqaTU6n4ntPgxwZLUllGA2CdquV8ivqrDGHamRz6jaZxp1nrkyGR3EL8NSyZ0huU/p12A+BXEu1dEgjXljSrG/vppe7C54edM9/1MwVkX4FlEYhbk9fzxU8XTonqwbF18bl61bzgCpH+VUcwewNCRHUnh2rF06gECr7UL6zKzZoojC4JQ/xiV/GNjnpbhxV12NpvlZvU8MfrJKP4+2IzSDTpCHPbqm4v6aAKDk22h9UwfWce24bFXaNmWnpnvsrueCfCCXTiAy+wVU7OJQTOerZi8jTqoprf+QE/xgB", "rte": true}, "ephemeral": true, "id": "17894d9c-8ed4-4cc3-82de-24cd232d7579", "parentId": "cdd6ad3e-f99d-4de4-8362-4a227a7896cd", "rawType": null, "timestamp": "2026-08-27 12:21:43.300000+00:00", "type": "assistant.reasoning"} +{"agentId": null, "data": {"model": null, "turnId": "1"}, "ephemeral": null, "id": "b84bebdc-21cc-4959-b23a-6b4175bd4258", "parentId": "cdd6ad3e-f99d-4de4-8362-4a227a7896cd", "rawType": null, "timestamp": "2026-08-27 12:21:43.301000+00:00", "type": "assistant.turn_end"} +{"agentId": null, "data": {"_model_cache_state": [{"_cache_ttl_seconds": 300, "cacheExpiresAt": "2026-08-27 12:26:41.232000+00:00", "modelId": "claude-haiku-4.5"}], "_total_premium_requests": 0.33, "totalNanoAiu": 1928640000.0}, "ephemeral": null, "id": "dd58783f-5bf3-426b-a1bd-0419ced3ecd7", "parentId": "b84bebdc-21cc-4959-b23a-6b4175bd4258", "rawType": null, "timestamp": "2026-08-27 12:21:43.304000+00:00", "type": "session.usage_checkpoint"} +{"agentId": null, "data": {"aborted": null}, "ephemeral": true, "id": "c74ec7dd-9876-4003-9f71-ad3495cbe25d", "parentId": "dd58783f-5bf3-426b-a1bd-0419ced3ecd7", "rawType": null, "timestamp": "2026-08-27 12:21:43.304000+00:00", "type": "assistant.idle"} +{"agentId": null, "data": {"aborted": null}, "ephemeral": true, "id": "58ac9671-ed32-4a42-a2e8-a5c87fc6dd31", "parentId": "dd58783f-5bf3-426b-a1bd-0419ced3ecd7", "rawType": null, "timestamp": "2026-08-27 12:21:43.304000+00:00", "type": "session.idle"} diff --git a/yarn.lock b/yarn.lock index 50932e5..b9c148a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1007,6 +1007,72 @@ "@eslint/core" "^0.17.0" levn "^0.4.1" +"@github/copilot-darwin-arm64@1.0.80": + version "1.0.80" + resolved "https://registry.yarnpkg.com/@github/copilot-darwin-arm64/-/copilot-darwin-arm64-1.0.80.tgz#3bb3de320f1036b2d59abda8249d95546cacc262" + integrity sha512-fzn4PnSx3+O/a3ip72KVsjnzORsEygK+0i21bFAnFBYS+0Wi1Pk+o/CmNsJ7aRbf1enSJrcH8UDVkyc9pMGEBg== + +"@github/copilot-darwin-x64@1.0.80": + version "1.0.80" + resolved "https://registry.yarnpkg.com/@github/copilot-darwin-x64/-/copilot-darwin-x64-1.0.80.tgz#ee9d7bebd904f803c62937e21454ad63186ad318" + integrity sha512-PKsyGk5DccNzR3bYXcYTGB9N6sHzhzGqEwq/2t1qBwqPbrC98Zo2dOT2G40/QYpJ4XdrGmTmdmfPJQ9PJknlIQ== + +"@github/copilot-linux-arm64@1.0.80": + version "1.0.80" + resolved "https://registry.yarnpkg.com/@github/copilot-linux-arm64/-/copilot-linux-arm64-1.0.80.tgz#02afc9e7d4b2ee0c39c523cf0f6d357316aece0b" + integrity sha512-8oXwN2luyHEjIoSk8AkATBjXDhRoQtuiUvC93GpfQKFHI+I1eoOVwIsAq5fKP8jNCF2rOrYFIcTjwmRt38kCcQ== + +"@github/copilot-linux-x64@1.0.80": + version "1.0.80" + resolved "https://registry.yarnpkg.com/@github/copilot-linux-x64/-/copilot-linux-x64-1.0.80.tgz#8418f636cf15277bd1c3497d52ebf9d4249a77ce" + integrity sha512-qv1ytVNwA3IDK7kcQow+fAikD67t42+AQ8X42bK/7oudNiv4frVZMO0yh1DYIebVRcmEhmPvbVPY/ptVUK3cbA== + +"@github/copilot-linuxmusl-arm64@1.0.80": + version "1.0.80" + resolved "https://registry.yarnpkg.com/@github/copilot-linuxmusl-arm64/-/copilot-linuxmusl-arm64-1.0.80.tgz#0b0ab0e212a46f8643eb0e495c88db3f04cde3ef" + integrity sha512-Qjyi+OlVnPC4Lkuy7blDMMwMUQI/yELl7gDnqQlaN8TEbhZqZueuf3p0a+kEjXcNsw4XtNYQc0eMJqSIYy/Pjg== + +"@github/copilot-linuxmusl-x64@1.0.80": + version "1.0.80" + resolved "https://registry.yarnpkg.com/@github/copilot-linuxmusl-x64/-/copilot-linuxmusl-x64-1.0.80.tgz#c5da0ee18c6411597af950b183a2f9328ab22954" + integrity sha512-rBg8pugf+5FhiZxi2zkOr+rlcOVF6Xg63j1FvryfwPT4DJ2w5Na7O3lpS4sgu8QmsP5H+dAqjlXYLYsvSoVQ0g== + +"@github/copilot-sdk@^1.0.11": + version "1.0.11" + resolved "https://registry.yarnpkg.com/@github/copilot-sdk/-/copilot-sdk-1.0.11.tgz#6605d21a133641b2080cce5c6ea1444f00925732" + integrity sha512-ngrnfa9052fLTOMoY0iiQS2B6pFDYJpWNj3syCdjzdje0R5mWoij9b8exJZciLvX7BbJjKz2/lIdwo24av3e3A== + dependencies: + "@github/copilot" "^1.0.79" + koffi "^3.1.0" + vscode-jsonrpc "^8.2.1" + zod "^4.3.6" + +"@github/copilot-win32-arm64@1.0.80": + version "1.0.80" + resolved "https://registry.yarnpkg.com/@github/copilot-win32-arm64/-/copilot-win32-arm64-1.0.80.tgz#db2a85b3652a522b0462ae648b1d6cc475729210" + integrity sha512-+f7Vkd3vt2DYOxRnS8dStvYu3DY638N/AuLuIjxZp1F9GgwCUZK69wspqIxg2L59PmRRQcH4AGTrRDR60ENIZA== + +"@github/copilot-win32-x64@1.0.80": + version "1.0.80" + resolved "https://registry.yarnpkg.com/@github/copilot-win32-x64/-/copilot-win32-x64-1.0.80.tgz#312fa2a0f7c1ad9360d8456bf73dc25df475e148" + integrity sha512-PO0kPqhRTWQfsqGaj4UN3cj8ttkcJYy4wmXiArtFm+03AIFu8xTvuhQDPn2xEOsUome7m7t2XomKoavcrCcRsw== + +"@github/copilot@^1.0.79": + version "1.0.80" + resolved "https://registry.yarnpkg.com/@github/copilot/-/copilot-1.0.80.tgz#5f18fe4252bfe70ce86a4d186f6cadfdf920fae1" + integrity sha512-6tf93ZF56KOiTTAjK/UhLZkl1W543IzaTQly288kockJZFswpRTnQEI00Yvacpb39DTvTYu3/ha9SeKpo/pgZQ== + dependencies: + detect-libc "^2.1.2" + optionalDependencies: + "@github/copilot-darwin-arm64" "1.0.80" + "@github/copilot-darwin-x64" "1.0.80" + "@github/copilot-linux-arm64" "1.0.80" + "@github/copilot-linux-x64" "1.0.80" + "@github/copilot-linuxmusl-arm64" "1.0.80" + "@github/copilot-linuxmusl-x64" "1.0.80" + "@github/copilot-win32-arm64" "1.0.80" + "@github/copilot-win32-x64" "1.0.80" + "@google/genai@^2.13.0": version "2.13.0" resolved "https://registry.yarnpkg.com/@google/genai/-/genai-2.13.0.tgz#16506a7c7397ebb89385a247e28aefae2ab4555b" @@ -1312,6 +1378,81 @@ "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" +"@koromix/koffi-darwin-arm64@3.1.6": + version "3.1.6" + resolved "https://registry.yarnpkg.com/@koromix/koffi-darwin-arm64/-/koffi-darwin-arm64-3.1.6.tgz#50c886ee86b5a178b4e09871de44840a829d99c7" + integrity sha512-8FHyXGCZN7/iQf4f7W5BRysmtdlAFvSx6FpmX4u6wmkZiX/2e9hIRdGLiZYlHGudlcA18UmXB/cMiyhJ7fJkzA== + +"@koromix/koffi-darwin-x64@3.1.6": + version "3.1.6" + resolved "https://registry.yarnpkg.com/@koromix/koffi-darwin-x64/-/koffi-darwin-x64-3.1.6.tgz#b7f0ebf5ddbf00c35a8c3c69c72f2308284c6f7a" + integrity sha512-uzx/jqFQuSHqgg1zaRidTBTCfj8Y9M0SDTO8HeoI9s9fJhiJ1mbB9TTwJO5c2hiMnuWg2m1byczC8BaIH6cG/w== + +"@koromix/koffi-freebsd-arm64@3.1.6": + version "3.1.6" + resolved "https://registry.yarnpkg.com/@koromix/koffi-freebsd-arm64/-/koffi-freebsd-arm64-3.1.6.tgz#70f6605ffb40b21947a240e9ce4796dcf6909f20" + integrity sha512-PjpTVrsCK5YTtixOw7VsseYXJOyoY6k0qBt+bf0T9h3wyV06y73rALsorFDDEoYpLUBZO7R6EIMs6CpUrEkNTQ== + +"@koromix/koffi-freebsd-ia32@3.1.6": + version "3.1.6" + resolved "https://registry.yarnpkg.com/@koromix/koffi-freebsd-ia32/-/koffi-freebsd-ia32-3.1.6.tgz#1bce6d72a5d62423d06867eec7647ad877043df2" + integrity sha512-ETYwL820HtFwYoOVzgyvmFmzTHRo9DJtGYTxa5Nb7ajaa5ldCum0jbmUJ3PMECxFTLxD5Q6PYZ8Xbp101bGeSg== + +"@koromix/koffi-freebsd-x64@3.1.6": + version "3.1.6" + resolved "https://registry.yarnpkg.com/@koromix/koffi-freebsd-x64/-/koffi-freebsd-x64-3.1.6.tgz#ab741c18c33257392f3f8a4b1c6dc0233d5bf33c" + integrity sha512-BkqxkNXhAAT9toU2stvLwx1iKHPDx7h08NCICyBbjYEXkCAEr84igTkpE5V3XJ9xZZ2gKll7VvdhxorHtHUqZw== + +"@koromix/koffi-linux-arm64@3.1.6": + version "3.1.6" + resolved "https://registry.yarnpkg.com/@koromix/koffi-linux-arm64/-/koffi-linux-arm64-3.1.6.tgz#be25d8e302a4aa23e25547ba2bb4050ec7d5cdba" + integrity sha512-cM4XPm9ljbCrcPgXjzFYjDNxDUvvuR7TCYaEoo1AKjwZT/vmWhu2xN3pomfbsHh6aVn80SFA3enufQnaETW1rQ== + +"@koromix/koffi-linux-ia32@3.1.6": + version "3.1.6" + resolved "https://registry.yarnpkg.com/@koromix/koffi-linux-ia32/-/koffi-linux-ia32-3.1.6.tgz#c6eb1b5df5397038a3080524b31db01e3a4ebd4b" + integrity sha512-l1SVTpO10iaQt8slbowJpzK4fbwQZ7ufj9tmCyAcIwWUpyAbPS83mJMctU72If6N9/gCS2wuRqwnYB2uPLLhLg== + +"@koromix/koffi-linux-loong64@3.1.6": + version "3.1.6" + resolved "https://registry.yarnpkg.com/@koromix/koffi-linux-loong64/-/koffi-linux-loong64-3.1.6.tgz#2b478f74bc6a9e9b90ec7f03d7b97504f532709d" + integrity sha512-KpTJpMSbIdCVFU26ynt0xy4x15h+y6AwPJxj2+iVxJhCzJf4oisCPc0YH2VnutuLV2nVzSrFm7sL/WSOqPgkXw== + +"@koromix/koffi-linux-riscv64@3.1.6": + version "3.1.6" + resolved "https://registry.yarnpkg.com/@koromix/koffi-linux-riscv64/-/koffi-linux-riscv64-3.1.6.tgz#7e79bf9b8a4259e344b544529d97f894e96cf3cb" + integrity sha512-YdFNpsywnXiYOYQlDAatf7TJLnspbGXdmfwIZhf82kbKSflYUsq4tI6NmoUOzM89oIWDGpYqd4Hz3xL7tsyXsw== + +"@koromix/koffi-linux-x64@3.1.6": + version "3.1.6" + resolved "https://registry.yarnpkg.com/@koromix/koffi-linux-x64/-/koffi-linux-x64-3.1.6.tgz#f408894379b28192ce35d5b22a0ec6903de347c5" + integrity sha512-Xx5mpr9VcaMCXfvbqIiLIWIL9Iuu6F4r3iMXg7+zZCqYUFZPFwJgiDQBLxctHv2OYgIfAoaaHMW0GC1cJkHfbA== + +"@koromix/koffi-openbsd-ia32@3.1.6": + version "3.1.6" + resolved "https://registry.yarnpkg.com/@koromix/koffi-openbsd-ia32/-/koffi-openbsd-ia32-3.1.6.tgz#1ae194e34c776b6d1ad5821138b8490dd0609a97" + integrity sha512-39Np4QTxhTlTT6RRveIeP+TnbzrwuDJ0UMyHxEZ+oGtzmb9GqWhl9T1oyehG6v/O+c4BffafG2NwLkCZ7tDKWw== + +"@koromix/koffi-openbsd-x64@3.1.6": + version "3.1.6" + resolved "https://registry.yarnpkg.com/@koromix/koffi-openbsd-x64/-/koffi-openbsd-x64-3.1.6.tgz#a02626a74c1828e958e68f19c96a18f974e553cb" + integrity sha512-3EynGn3ycQRqaMWGmUJ0tdtuQdStByqSy/tJ0ZGKWizbMGdFAE73YpgLsyd8BDvwnKWytVG/OLNb5nDHpfd9Dg== + +"@koromix/koffi-win32-arm64@3.1.6": + version "3.1.6" + resolved "https://registry.yarnpkg.com/@koromix/koffi-win32-arm64/-/koffi-win32-arm64-3.1.6.tgz#014ddb302702469eea9ad51edd4091344f3e4fc9" + integrity sha512-27FdPPRtT4xbO9bsd2OZa95M5YQ7bcJ8QjCRO57UUMI21REfkDegjqKwqo/CFlugxXlJf5IYtG2rq4BEYIrvxg== + +"@koromix/koffi-win32-ia32@3.1.6": + version "3.1.6" + resolved "https://registry.yarnpkg.com/@koromix/koffi-win32-ia32/-/koffi-win32-ia32-3.1.6.tgz#ad056d9d8353e337e4bb3ec6d42ab8b1360bb035" + integrity sha512-5mVelLKVDup4eoxZOpCzCyMPxoctsg+Qe4J9O5BP4KbBEdqoOEqaNEBBRgNzXcdr2g+GGfmIUo+oVR1NvIdiJw== + +"@koromix/koffi-win32-x64@3.1.6": + version "3.1.6" + resolved "https://registry.yarnpkg.com/@koromix/koffi-win32-x64/-/koffi-win32-x64-3.1.6.tgz#6d22794be9454cd2b87f1b128ebc7df5be3a1c40" + integrity sha512-lPKjAaHz0aoiZXT/wDVqH+joR5y3lCZj1s9Bk5qx/DGRq+0MK8Ib8VoqiBOrJ69NG5AsJSvn0tQDcSqfRgLmBQ== + "@langchain/classic@^1.0.27": version "1.0.40" resolved "https://registry.yarnpkg.com/@langchain/classic/-/classic-1.0.40.tgz#e0b699f3ff83849de3619d8a8917f9bd7719c845" @@ -2895,6 +3036,11 @@ depd@^2.0.0, depd@~2.0.0: resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== +detect-libc@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.1.2.tgz#689c5dcdc1900ef5583a4cb9f6d7b473742074ad" + integrity sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ== + detect-newline@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" @@ -4387,6 +4533,27 @@ kleur@^3.0.3: resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== +koffi@^3.1.0: + version "3.1.6" + resolved "https://registry.yarnpkg.com/koffi/-/koffi-3.1.6.tgz#97fa8bc50c2af6e1a873fdee3713cc128bf286ff" + integrity sha512-ln60chEb3o7Du1ayjwl6BFiNN1wZK+3cTM2wWGiHLEzCY/FdTIN1ER5VWDwHq7J/j4tSnnrHaH5ABS1EO6+6ag== + optionalDependencies: + "@koromix/koffi-darwin-arm64" "3.1.6" + "@koromix/koffi-darwin-x64" "3.1.6" + "@koromix/koffi-freebsd-arm64" "3.1.6" + "@koromix/koffi-freebsd-ia32" "3.1.6" + "@koromix/koffi-freebsd-x64" "3.1.6" + "@koromix/koffi-linux-arm64" "3.1.6" + "@koromix/koffi-linux-ia32" "3.1.6" + "@koromix/koffi-linux-loong64" "3.1.6" + "@koromix/koffi-linux-riscv64" "3.1.6" + "@koromix/koffi-linux-x64" "3.1.6" + "@koromix/koffi-openbsd-ia32" "3.1.6" + "@koromix/koffi-openbsd-x64" "3.1.6" + "@koromix/koffi-win32-arm64" "3.1.6" + "@koromix/koffi-win32-ia32" "3.1.6" + "@koromix/koffi-win32-x64" "3.1.6" + "langsmith@>=0.4.0 <1.0.0", "langsmith@>=0.5.0 <1.0.0": version "0.8.7" resolved "https://registry.yarnpkg.com/langsmith/-/langsmith-0.8.7.tgz#1152855dc77890c9190461b6eb3583a8a97b12e3" @@ -5675,6 +5842,11 @@ vary@^1, vary@^1.1.2: resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== +vscode-jsonrpc@^8.2.1: + version "8.2.1" + resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-8.2.1.tgz#a322cc0f1d97f794ffd9c4cd2a898a0bde097f34" + integrity sha512-kdjOSJ2lLIn7r1rtrMbbNCHjyMPfRnowdKjBQ+mGq6NAW5QY2bEZC/khaC5OR8svbbjvLEaIXkOq45e2X9BIbQ== + walker@^1.0.8: version "1.0.8" resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f" @@ -5815,7 +5987,7 @@ zod-to-json-schema@^3.25.1: resolved "https://registry.yarnpkg.com/zod-to-json-schema/-/zod-to-json-schema-3.25.2.tgz#3fa799a7badd554541472fb65843fdc460b2e5aa" integrity sha512-O/PgfnpT1xKSDeQYSCfRI5Gy3hPf91mKVDuYLUHZJMiDFptvP41MSnWofm8dnCm0256ZNfZIM7DSzuSMAFnjHA== -"zod@^3.25 || ^4.0", "zod@^3.25.76 || ^4": +"zod@^3.25 || ^4.0", "zod@^3.25.76 || ^4", zod@^4.3.6: version "4.4.3" resolved "https://registry.yarnpkg.com/zod/-/zod-4.4.3.tgz#b680f172885d18bbebf21a834ea25e55a1bbf356" integrity sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==