diff --git a/dotnet/src/Generated/SessionEvents.cs b/dotnet/src/Generated/SessionEvents.cs index 5ed3188..acd03c6 100644 --- a/dotnet/src/Generated/SessionEvents.cs +++ b/dotnet/src/Generated/SessionEvents.cs @@ -6,7 +6,7 @@ // // Generated from: @github/copilot/session-events.schema.json // Generated by: scripts/generate-session-types.ts -// Generated at: 2026-01-15T19:22:26.479Z +// Generated at: 2026-01-16T00:52:52.781Z // // To update these types: // 1. Update the schema in copilot-agent-runtime @@ -39,6 +39,7 @@ internal class SessionEventConverter : JsonConverter ["session.model_change"] = typeof(SessionModelChangeEvent), ["session.handoff"] = typeof(SessionHandoffEvent), ["session.truncation"] = typeof(SessionTruncationEvent), + ["session.usage_info"] = typeof(SessionUsageInfoEvent), ["session.compaction_start"] = typeof(SessionCompactionStartEvent), ["session.compaction_complete"] = typeof(SessionCompactionCompleteEvent), ["user.message"] = typeof(UserMessageEvent), @@ -209,6 +210,17 @@ public partial class SessionTruncationEvent : SessionEvent public SessionTruncationData Data { get; set; } } + /// + /// Event: session.usage_info + /// + public partial class SessionUsageInfoEvent : SessionEvent + { + public override string Type => "session.usage_info"; + + [JsonPropertyName("data")] + public SessionUsageInfoData Data { get; set; } + } + /// /// Event: session.compaction_start /// @@ -592,6 +604,18 @@ public partial class SessionTruncationData public string PerformedBy { get; set; } } + public partial class SessionUsageInfoData + { + [JsonPropertyName("tokenLimit")] + public double TokenLimit { get; set; } + + [JsonPropertyName("currentTokens")] + public double CurrentTokens { get; set; } + + [JsonPropertyName("messagesLength")] + public double MessagesLength { get; set; } + } + public partial class SessionCompactionStartData { } diff --git a/dotnet/test/Harness/CapiProxy.cs b/dotnet/test/Harness/CapiProxy.cs index 18c97a4..dd7ba31 100644 --- a/dotnet/test/Harness/CapiProxy.cs +++ b/dotnet/test/Harness/CapiProxy.cs @@ -84,15 +84,16 @@ async Task StartCoreAsync() } } - public async Task StopAsync() + public async Task StopAsync(bool skipWritingCache = false) { if (_startupTask != null) { try { var url = await _startupTask; + var stopUrl = skipWritingCache ? $"{url}/stop?skipWritingCache=true" : $"{url}/stop"; using var client = new HttpClient(); - await client.PostAsync($"{url}/stop", null); + await client.PostAsync(stopUrl, null); } catch { /* Best effort */ } } diff --git a/dotnet/test/Harness/E2ETestContext.cs b/dotnet/test/Harness/E2ETestContext.cs index dcecc04..d9d47a4 100644 --- a/dotnet/test/Harness/E2ETestContext.cs +++ b/dotnet/test/Harness/E2ETestContext.cs @@ -101,7 +101,9 @@ public IReadOnlyDictionary GetEnvironment() public async ValueTask DisposeAsync() { - await _proxy.DisposeAsync(); + // Skip writing snapshots in CI to avoid corrupting them on test failures + var isCI = !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("CI")); + await _proxy.StopAsync(skipWritingCache: isCI); try { if (Directory.Exists(HomeDir)) Directory.Delete(HomeDir, true); } catch { } try { if (Directory.Exists(WorkDir)) Directory.Delete(WorkDir, true); } catch { } diff --git a/go/e2e/permissions_test.go b/go/e2e/permissions_test.go index fa5cae1..f377f01 100644 --- a/go/e2e/permissions_test.go +++ b/go/e2e/permissions_test.go @@ -99,7 +99,7 @@ func TestPermissions(t *testing.T) { } _, err = session.Send(copilot.MessageOptions{ - Prompt: "Run 'echo hello world' and tell me the output", + Prompt: "Run 'echo hello' and tell me the output", }) if err != nil { t.Fatalf("Failed to send message: %v", err) diff --git a/go/e2e/testharness/context.go b/go/e2e/testharness/context.go index b8cc3a3..718b08d 100644 --- a/go/e2e/testharness/context.go +++ b/go/e2e/testharness/context.go @@ -82,7 +82,7 @@ func NewTestContext(t *testing.T) *TestContext { } t.Cleanup(func() { - ctx.Close() + ctx.Close(t.Failed()) }) return ctx @@ -113,9 +113,9 @@ func (c *TestContext) ConfigureForTest(t *testing.T) { } // Close cleans up the test context resources. -func (c *TestContext) Close() { +func (c *TestContext) Close(testFailed bool) { if c.proxy != nil { - c.proxy.Stop() + c.proxy.StopWithOptions(testFailed) } if c.HomeDir != "" { os.RemoveAll(c.HomeDir) diff --git a/go/e2e/testharness/proxy.go b/go/e2e/testharness/proxy.go index 71f4dc9..298700e 100644 --- a/go/e2e/testharness/proxy.go +++ b/go/e2e/testharness/proxy.go @@ -75,6 +75,12 @@ func (p *CapiProxy) Start() (string, error) { // Stop gracefully shuts down the proxy server. func (p *CapiProxy) Stop() error { + return p.StopWithOptions(false) +} + +// StopWithOptions gracefully shuts down the proxy server. +// If skipWritingCache is true, the proxy won't write captured exchanges to disk. +func (p *CapiProxy) StopWithOptions(skipWritingCache bool) error { p.mu.Lock() defer p.mu.Unlock() @@ -84,8 +90,12 @@ func (p *CapiProxy) Stop() error { // Send stop request to the server if p.proxyURL != "" { + stopURL := p.proxyURL + "/stop" + if skipWritingCache { + stopURL += "?skipWritingCache=true" + } // Best effort - ignore errors - resp, err := http.Post(p.proxyURL+"/stop", "application/json", nil) + resp, err := http.Post(stopURL, "application/json", nil) if err == nil { resp.Body.Close() } diff --git a/go/generated/session_events.go b/go/generated/session_events.go index f143eac..cdd2118 100644 --- a/go/generated/session_events.go +++ b/go/generated/session_events.go @@ -2,7 +2,7 @@ // // Generated from: @github/copilot/session-events.schema.json // Generated by: scripts/generate-session-types.ts -// Generated at: 2026-01-15T19:22:26.289Z +// Generated at: 2026-01-16T00:52:52.011Z // // To update these types: // 1. Update the schema in copilot-agent-runtime @@ -70,6 +70,8 @@ type Data struct { PreTruncationTokensInMessages *float64 `json:"preTruncationTokensInMessages,omitempty"` TokenLimit *float64 `json:"tokenLimit,omitempty"` TokensRemovedDuringTruncation *float64 `json:"tokensRemovedDuringTruncation,omitempty"` + CurrentTokens *float64 `json:"currentTokens,omitempty"` + MessagesLength *float64 `json:"messagesLength,omitempty"` CompactionTokensUsed *CompactionTokensUsed `json:"compactionTokensUsed,omitempty"` Error *ErrorUnion `json:"error"` MessagesRemoved *float64 `json:"messagesRemoved,omitempty"` @@ -219,6 +221,7 @@ const ( SessionResume SessionEventType = "session.resume" SessionStart SessionEventType = "session.start" SessionTruncation SessionEventType = "session.truncation" + SessionUsageInfo SessionEventType = "session.usage_info" SubagentCompleted SessionEventType = "subagent.completed" SubagentFailed SessionEventType = "subagent.failed" SubagentSelected SessionEventType = "subagent.selected" diff --git a/nodejs/package-lock.json b/nodejs/package-lock.json index 4407e58..1bb7b99 100644 --- a/nodejs/package-lock.json +++ b/nodejs/package-lock.json @@ -9,7 +9,7 @@ "version": "0.1.8", "license": "MIT", "dependencies": { - "@github/copilot": "^0.0.382", + "@github/copilot": "^0.0.383", "vscode-jsonrpc": "^8.2.1", "zod": "^4.3.5" }, @@ -662,9 +662,9 @@ } }, "node_modules/@github/copilot": { - "version": "0.0.382", - "resolved": "https://registry.npmjs.org/@github/copilot/-/copilot-0.0.382.tgz", - "integrity": "sha512-ElrXC4W2XAiykyAaZd+IRWb3LfqLQHfNN3wZfh6FcxALM2JJar7H4pHhFWMDCKJ1XfcJ1yPwSXU2t5hUcHWwlg==", + "version": "0.0.383", + "resolved": "https://registry.npmjs.org/@github/copilot/-/copilot-0.0.383.tgz", + "integrity": "sha512-bE81nL/1YTppMS6gB/Nq7S+5EcD45awvrYgSkhLZKBuWhwOQ42jDp0g2lID1nR4GrwatV+FoDckQw2NpDPY93A==", "license": "SEE LICENSE IN LICENSE.md", "bin": { "copilot": "npm-loader.js" @@ -673,18 +673,18 @@ "node": ">=22" }, "optionalDependencies": { - "@github/copilot-darwin-arm64": "0.0.382", - "@github/copilot-darwin-x64": "0.0.382", - "@github/copilot-linux-arm64": "0.0.382", - "@github/copilot-linux-x64": "0.0.382", - "@github/copilot-win32-arm64": "0.0.382", - "@github/copilot-win32-x64": "0.0.382" + "@github/copilot-darwin-arm64": "0.0.383", + "@github/copilot-darwin-x64": "0.0.383", + "@github/copilot-linux-arm64": "0.0.383", + "@github/copilot-linux-x64": "0.0.383", + "@github/copilot-win32-arm64": "0.0.383", + "@github/copilot-win32-x64": "0.0.383" } }, "node_modules/@github/copilot-darwin-arm64": { - "version": "0.0.382", - "resolved": "https://registry.npmjs.org/@github/copilot-darwin-arm64/-/copilot-darwin-arm64-0.0.382.tgz", - "integrity": "sha512-ueu8EpI12K18LpurqGeYiW0c22umQdCKxEzEg+wJMSo5t5rnaGRvX0By3QiBWj4bI+2JjmvqHCbESey+QNZY3Q==", + "version": "0.0.383", + "resolved": "https://registry.npmjs.org/@github/copilot-darwin-arm64/-/copilot-darwin-arm64-0.0.383.tgz", + "integrity": "sha512-GfwHGgVmlYS3ksQhyBRQRUQtGtumRDoszByBfkyoJrDH9bLjAMM3EyS6r5nhmH7PMadjU4ZCkj8FGek7imDGtw==", "cpu": [ "arm64" ], @@ -698,9 +698,9 @@ } }, "node_modules/@github/copilot-darwin-x64": { - "version": "0.0.382", - "resolved": "https://registry.npmjs.org/@github/copilot-darwin-x64/-/copilot-darwin-x64-0.0.382.tgz", - "integrity": "sha512-TN7YV4wcq2lDs6kUZUXOhZWdnT7n1nei1AhM0L72yE4SUOshfaeqPr8RvTACQ4PkOiPcZcspUDGabap816TGIA==", + "version": "0.0.383", + "resolved": "https://registry.npmjs.org/@github/copilot-darwin-x64/-/copilot-darwin-x64-0.0.383.tgz", + "integrity": "sha512-4gTjY9St/MyFadPpdvVYiGjvHPPYmFns6ic3AX3q+HTpj1zqGpnjLbwfZeM/Lfb84oMIhM2sR1G/Bv8B+T3l/g==", "cpu": [ "x64" ], @@ -714,9 +714,9 @@ } }, "node_modules/@github/copilot-linux-arm64": { - "version": "0.0.382", - "resolved": "https://registry.npmjs.org/@github/copilot-linux-arm64/-/copilot-linux-arm64-0.0.382.tgz", - "integrity": "sha512-lHBL77wAkguGMIZno4FmJQlScWxgQ+yHFauJddEl6n0MO8dHIwXwJ9T+ejPbvQ8qac7PU2d5zWjn+UX7aCdoqA==", + "version": "0.0.383", + "resolved": "https://registry.npmjs.org/@github/copilot-linux-arm64/-/copilot-linux-arm64-0.0.383.tgz", + "integrity": "sha512-QoqK76G7sAh7DVpg2GlnIDa5lYe9FK9U1oFwOVjwXwwKJe8PpIWwNVeO4nERGrkc4CQy7u4U59GSmfXQzoFXvw==", "cpu": [ "arm64" ], @@ -730,9 +730,9 @@ } }, "node_modules/@github/copilot-linux-x64": { - "version": "0.0.382", - "resolved": "https://registry.npmjs.org/@github/copilot-linux-x64/-/copilot-linux-x64-0.0.382.tgz", - "integrity": "sha512-q190p9kIWUD1NoVSuzU381B6Zi3GlTv3+tY+euZyykNrkeGVxSRN7GwQMyr1cCUZgApSdK/e52+Hd/8myBNt1Q==", + "version": "0.0.383", + "resolved": "https://registry.npmjs.org/@github/copilot-linux-x64/-/copilot-linux-x64-0.0.383.tgz", + "integrity": "sha512-EJHnq575pv7N586WjQkZZdDLqfd2GemGxk3aIhWrHtXMmLY4qRAJJBUnF1MtNqccTKuPmLuD8nAUTrxQp7sWPA==", "cpu": [ "x64" ], @@ -746,9 +746,9 @@ } }, "node_modules/@github/copilot-win32-arm64": { - "version": "0.0.382", - "resolved": "https://registry.npmjs.org/@github/copilot-win32-arm64/-/copilot-win32-arm64-0.0.382.tgz", - "integrity": "sha512-XdOZxCS/DpueuxzGwMjgvXZSZIqvt48PPg/3f7+9mYXaTV6xLgSZDIA95+DldkigjFnfB8AfP76LNYVvgCgITQ==", + "version": "0.0.383", + "resolved": "https://registry.npmjs.org/@github/copilot-win32-arm64/-/copilot-win32-arm64-0.0.383.tgz", + "integrity": "sha512-76NT8ULHpbmM/YOz71FPAUUfAhfEVqhEew+Wkqtgn+eG48gCnDYu3ZQIRbnWIh/oj6nYVTyi0wg9LUt7M8sFRQ==", "cpu": [ "arm64" ], @@ -762,9 +762,9 @@ } }, "node_modules/@github/copilot-win32-x64": { - "version": "0.0.382", - "resolved": "https://registry.npmjs.org/@github/copilot-win32-x64/-/copilot-win32-x64-0.0.382.tgz", - "integrity": "sha512-hg5O3KrDUY3ClZAa2N1MOD/OT5jK0s+VpGvo2Xe8tqwte4YGpWbC5GGTnDYAIxbhyL6N+1+PKPi1rdYyqj5eUQ==", + "version": "0.0.383", + "resolved": "https://registry.npmjs.org/@github/copilot-win32-x64/-/copilot-win32-x64-0.0.383.tgz", + "integrity": "sha512-/5r5uK8pUoefS8H9cax96GqBzm62uBeXEphct7SxPU/gnf2udDvb+0iBOlvKskAwdWNXLp3Khxgm4nfFgxrr9A==", "cpu": [ "x64" ], diff --git a/nodejs/package.json b/nodejs/package.json index 80fe7f7..1042a65 100644 --- a/nodejs/package.json +++ b/nodejs/package.json @@ -40,7 +40,7 @@ "author": "GitHub", "license": "MIT", "dependencies": { - "@github/copilot": "^0.0.382", + "@github/copilot": "^0.0.383", "vscode-jsonrpc": "^8.2.1", "zod": "^4.3.5" }, diff --git a/nodejs/src/generated/session-events.ts b/nodejs/src/generated/session-events.ts index 95b5cea..ea8ed7a 100644 --- a/nodejs/src/generated/session-events.ts +++ b/nodejs/src/generated/session-events.ts @@ -3,7 +3,7 @@ * * Generated from: @github/copilot/session-events.schema.json * Generated by: scripts/generate-session-types.ts - * Generated at: 2026-01-15T19:22:25.859Z + * Generated at: 2026-01-16T00:52:51.450Z * * To update these types: * 1. Update the schema in copilot-agent-runtime @@ -115,6 +115,18 @@ export type SessionEvent = performedBy: string; }; } + | { + id: string; + timestamp: string; + parentId: string | null; + ephemeral: true; + type: "session.usage_info"; + data: { + tokenLimit: number; + currentTokens: number; + messagesLength: number; + }; + } | { id: string; timestamp: string; diff --git a/nodejs/test/e2e/harness/CapiProxy.ts b/nodejs/test/e2e/harness/CapiProxy.ts index dee498d..f08ffc5 100644 --- a/nodejs/test/e2e/harness/CapiProxy.ts +++ b/nodejs/test/e2e/harness/CapiProxy.ts @@ -43,8 +43,11 @@ export class CapiProxy { return await response.json(); } - async stop(): Promise { - const response = await fetch(`${this.proxyUrl}/stop`, { method: "POST" }); + async stop(skipWritingCache?: boolean): Promise { + const url = skipWritingCache + ? `${this.proxyUrl}/stop?skipWritingCache=true` + : `${this.proxyUrl}/stop`; + const response = await fetch(url, { method: "POST" }); expect(response.ok).toBe(true); } } diff --git a/nodejs/test/e2e/harness/sdkTestContext.ts b/nodejs/test/e2e/harness/sdkTestContext.ts index abb0a99..9137113 100644 --- a/nodejs/test/e2e/harness/sdkTestContext.ts +++ b/nodejs/test/e2e/harness/sdkTestContext.ts @@ -8,7 +8,7 @@ import os from "os"; import { basename, dirname, join, resolve } from "path"; import { rimraf } from "rimraf"; import { fileURLToPath } from "url"; -import { afterAll, afterEach, beforeEach, TestContext } from "vitest"; +import { afterAll, afterEach, beforeEach, onTestFailed, TestContext } from "vitest"; import { CopilotClient } from "../../../src"; import { CapiProxy } from "./CapiProxy"; import { retry } from "./sdkTestHelper"; @@ -17,7 +17,9 @@ const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); const SNAPSHOTS_DIR = resolve(__dirname, "../../../../test/snapshots"); -export const CLI_PATH = resolve(__dirname, "../../../node_modules/@github/copilot/index.js"); +export const CLI_PATH = + process.env.COPILOT_CLI_PATH || + resolve(__dirname, "../../../node_modules/@github/copilot/index.js"); export async function createSdkTestContext() { const homeDir = realpathSync(fs.mkdtempSync(join(os.tmpdir(), "copilot-test-config-"))); @@ -44,8 +46,16 @@ export async function createSdkTestContext() { const harness = { homeDir, workDir, openAiEndpoint, copilotClient, env }; + // Track if any test fails to avoid writing corrupted snapshots + let anyTestFailed = false; + // Wire up to Vitest lifecycle beforeEach(async (testContext) => { + // Must be inside beforeEach - vitest requires test context + onTestFailed(() => { + anyTestFailed = true; + }); + await openAiEndpoint.updateConfig({ filePath: getTrafficCapturePath(testContext), workDir, @@ -63,7 +73,7 @@ export async function createSdkTestContext() { afterAll(async () => { await copilotClient.stop(); - await openAiEndpoint.stop(); + await openAiEndpoint.stop(anyTestFailed); await rmDir("remove e2e test homeDir", homeDir); await rmDir("remove e2e test workDir", workDir); }); diff --git a/python/copilot/generated/session_events.py b/python/copilot/generated/session_events.py index 36791c1..86d27da 100644 --- a/python/copilot/generated/session_events.py +++ b/python/copilot/generated/session_events.py @@ -3,7 +3,7 @@ Generated from: @github/copilot/session-events.schema.json Generated by: scripts/generate-session-types.ts -Generated at: 2026-01-15T19:22:26.227Z +Generated at: 2026-01-16T00:52:51.909Z To update these types: 1. Update the schema in copilot-agent-runtime @@ -314,6 +314,8 @@ class Data: pre_truncation_tokens_in_messages: Optional[float] = None token_limit: Optional[float] = None tokens_removed_during_truncation: Optional[float] = None + current_tokens: Optional[float] = None + messages_length: Optional[float] = None compaction_tokens_used: Optional[CompactionTokensUsed] = None error: Optional[Union[ErrorClass, str]] = None messages_removed: Optional[float] = None @@ -397,6 +399,8 @@ def from_dict(obj: Any) -> 'Data': pre_truncation_tokens_in_messages = from_union([from_float, from_none], obj.get("preTruncationTokensInMessages")) token_limit = from_union([from_float, from_none], obj.get("tokenLimit")) tokens_removed_during_truncation = from_union([from_float, from_none], obj.get("tokensRemovedDuringTruncation")) + current_tokens = from_union([from_float, from_none], obj.get("currentTokens")) + messages_length = from_union([from_float, from_none], obj.get("messagesLength")) compaction_tokens_used = from_union([CompactionTokensUsed.from_dict, from_none], obj.get("compactionTokensUsed")) error = from_union([ErrorClass.from_dict, from_str, from_none], obj.get("error")) messages_removed = from_union([from_float, from_none], obj.get("messagesRemoved")) @@ -448,7 +452,7 @@ def from_dict(obj: Any) -> 'Data': metadata = from_union([Metadata.from_dict, from_none], obj.get("metadata")) name = from_union([from_str, from_none], obj.get("name")) role = from_union([Role, from_none], obj.get("role")) - return Data(copilot_version, producer, selected_model, session_id, start_time, version, event_count, resume_time, error_type, message, stack, info_type, new_model, previous_model, context, handoff_time, remote_session_id, repository, source_type, summary, messages_removed_during_truncation, performed_by, post_truncation_messages_length, post_truncation_tokens_in_messages, pre_truncation_messages_length, pre_truncation_tokens_in_messages, token_limit, tokens_removed_during_truncation, compaction_tokens_used, error, messages_removed, post_compaction_tokens, pre_compaction_messages_length, pre_compaction_tokens, success, summary_content, tokens_removed, attachments, content, source, transformed_content, turn_id, intent, reasoning_id, delta_content, message_id, parent_tool_call_id, tool_requests, total_response_size_bytes, api_call_id, cache_read_tokens, cache_write_tokens, cost, duration, initiator, input_tokens, model, output_tokens, provider_call_id, quota_snapshots, reason, arguments, tool_call_id, tool_name, partial_output, is_user_requested, result, tool_telemetry, agent_description, agent_display_name, agent_name, tools, hook_invocation_id, hook_type, input, output, metadata, name, role) + return Data(copilot_version, producer, selected_model, session_id, start_time, version, event_count, resume_time, error_type, message, stack, info_type, new_model, previous_model, context, handoff_time, remote_session_id, repository, source_type, summary, messages_removed_during_truncation, performed_by, post_truncation_messages_length, post_truncation_tokens_in_messages, pre_truncation_messages_length, pre_truncation_tokens_in_messages, token_limit, tokens_removed_during_truncation, current_tokens, messages_length, compaction_tokens_used, error, messages_removed, post_compaction_tokens, pre_compaction_messages_length, pre_compaction_tokens, success, summary_content, tokens_removed, attachments, content, source, transformed_content, turn_id, intent, reasoning_id, delta_content, message_id, parent_tool_call_id, tool_requests, total_response_size_bytes, api_call_id, cache_read_tokens, cache_write_tokens, cost, duration, initiator, input_tokens, model, output_tokens, provider_call_id, quota_snapshots, reason, arguments, tool_call_id, tool_name, partial_output, is_user_requested, result, tool_telemetry, agent_description, agent_display_name, agent_name, tools, hook_invocation_id, hook_type, input, output, metadata, name, role) def to_dict(self) -> dict: result: dict = {} @@ -508,6 +512,10 @@ def to_dict(self) -> dict: result["tokenLimit"] = from_union([to_float, from_none], self.token_limit) if self.tokens_removed_during_truncation is not None: result["tokensRemovedDuringTruncation"] = from_union([to_float, from_none], self.tokens_removed_during_truncation) + if self.current_tokens is not None: + result["currentTokens"] = from_union([to_float, from_none], self.current_tokens) + if self.messages_length is not None: + result["messagesLength"] = from_union([to_float, from_none], self.messages_length) if self.compaction_tokens_used is not None: result["compactionTokensUsed"] = from_union([lambda x: to_class(CompactionTokensUsed, x), from_none], self.compaction_tokens_used) if self.error is not None: @@ -636,6 +644,7 @@ class SessionEventType(Enum): SESSION_RESUME = "session.resume" SESSION_START = "session.start" SESSION_TRUNCATION = "session.truncation" + SESSION_USAGE_INFO = "session.usage_info" SUBAGENT_COMPLETED = "subagent.completed" SUBAGENT_FAILED = "subagent.failed" SUBAGENT_SELECTED = "subagent.selected" diff --git a/python/e2e/conftest.py b/python/e2e/conftest.py index d7e7717..1fac08d 100644 --- a/python/e2e/conftest.py +++ b/python/e2e/conftest.py @@ -1,17 +1,30 @@ """Shared pytest fixtures for e2e tests.""" +import pytest import pytest_asyncio from .testharness import E2ETestContext +@pytest.hookimpl(tryfirst=True, hookwrapper=True) +def pytest_runtest_makereport(item, call): + """Track test failures to avoid writing corrupted snapshots.""" + outcome = yield + rep = outcome.get_result() + if rep.when == "call" and rep.failed: + # Store on the item's stash so the fixture can access it + item.session.stash.setdefault("any_test_failed", False) + item.session.stash["any_test_failed"] = True + + @pytest_asyncio.fixture(scope="module", loop_scope="module") -async def ctx(): +async def ctx(request): """Create and teardown a test context shared across all tests in this module.""" context = E2ETestContext() await context.setup() yield context - await context.teardown() + any_failed = request.session.stash.get("any_test_failed", False) + await context.teardown(test_failed=any_failed) @pytest_asyncio.fixture(autouse=True, loop_scope="module") diff --git a/python/e2e/test_permissions.py b/python/e2e/test_permissions.py index c585ee0..7e2502e 100644 --- a/python/e2e/test_permissions.py +++ b/python/e2e/test_permissions.py @@ -56,7 +56,7 @@ def on_permission_request( session = await ctx.client.create_session({"on_permission_request": on_permission_request}) - await session.send({"prompt": "Run 'echo hello world' and tell me the output"}) + await session.send({"prompt": "Run 'echo hello' and tell me the output"}) await get_final_assistant_message(session) # Should have received at least one shell permission request diff --git a/python/e2e/testharness/context.py b/python/e2e/testharness/context.py index b1150a0..adb2f88 100644 --- a/python/e2e/testharness/context.py +++ b/python/e2e/testharness/context.py @@ -73,14 +73,18 @@ async def setup(self): } ) - async def teardown(self): - """Clean up the test context.""" + async def teardown(self, test_failed: bool = False): + """Clean up the test context. + + Args: + test_failed: If True, skip writing snapshots to avoid corruption. + """ if self._client: await self._client.stop() self._client = None if self._proxy: - await self._proxy.stop() + await self._proxy.stop(skip_writing_cache=test_failed) self._proxy = None if self.home_dir and os.path.exists(self.home_dir): diff --git a/python/e2e/testharness/proxy.py b/python/e2e/testharness/proxy.py index f0fd9a4..c1c857a 100644 --- a/python/e2e/testharness/proxy.py +++ b/python/e2e/testharness/proxy.py @@ -59,16 +59,23 @@ async def start(self) -> str: self._proxy_url = match.group(1) return self._proxy_url - async def stop(self): - """Gracefully shut down the proxy server.""" + async def stop(self, skip_writing_cache: bool = False): + """Gracefully shut down the proxy server. + + Args: + skip_writing_cache: If True, the proxy won't write captured exchanges to disk. + """ if not self._process: return # Send stop request to the server if self._proxy_url: try: + stop_url = f"{self._proxy_url}/stop" + if skip_writing_cache: + stop_url += "?skipWritingCache=true" async with httpx.AsyncClient() as client: - await client.post(f"{self._proxy_url}/stop") + await client.post(stop_url) except Exception: pass # Best effort diff --git a/test/harness/package-lock.json b/test/harness/package-lock.json index ea68e18..82814f3 100644 --- a/test/harness/package-lock.json +++ b/test/harness/package-lock.json @@ -9,7 +9,7 @@ "version": "1.0.0", "license": "ISC", "devDependencies": { - "@github/copilot": "^0.0.372", + "@github/copilot": "^0.0.383", "@types/node": "^25.0.3", "openai": "^6.15.0", "tsx": "^4.21.0", @@ -461,9 +461,9 @@ } }, "node_modules/@github/copilot": { - "version": "0.0.372", - "resolved": "https://registry.npmjs.org/@github/copilot/-/copilot-0.0.372.tgz", - "integrity": "sha512-epuWLH4tPrAcTkVepW/0aYi24IJt0IpVyBeKTmM8WsctjLyiXmaWeVd9Y9mGlANWJe6OiGLeUPWbHeMtR/6P+w==", + "version": "0.0.383", + "resolved": "https://registry.npmjs.org/@github/copilot/-/copilot-0.0.383.tgz", + "integrity": "sha512-bE81nL/1YTppMS6gB/Nq7S+5EcD45awvrYgSkhLZKBuWhwOQ42jDp0g2lID1nR4GrwatV+FoDckQw2NpDPY93A==", "dev": true, "license": "SEE LICENSE IN LICENSE.md", "bin": { @@ -473,18 +473,18 @@ "node": ">=22" }, "optionalDependencies": { - "@github/copilot-darwin-arm64": "0.0.372", - "@github/copilot-darwin-x64": "0.0.372", - "@github/copilot-linux-arm64": "0.0.372", - "@github/copilot-linux-x64": "0.0.372", - "@github/copilot-win32-arm64": "0.0.372", - "@github/copilot-win32-x64": "0.0.372" + "@github/copilot-darwin-arm64": "0.0.383", + "@github/copilot-darwin-x64": "0.0.383", + "@github/copilot-linux-arm64": "0.0.383", + "@github/copilot-linux-x64": "0.0.383", + "@github/copilot-win32-arm64": "0.0.383", + "@github/copilot-win32-x64": "0.0.383" } }, "node_modules/@github/copilot-darwin-arm64": { - "version": "0.0.372", - "resolved": "https://registry.npmjs.org/@github/copilot-darwin-arm64/-/copilot-darwin-arm64-0.0.372.tgz", - "integrity": "sha512-LHZgcGiP1YxUve4XNdYm917rz6KIFMafqsCfUmBCyYhXcfTkmtfvTkf0JmSY6qIGhKqj7K3kDfst+xYzCz1fgw==", + "version": "0.0.383", + "resolved": "https://registry.npmjs.org/@github/copilot-darwin-arm64/-/copilot-darwin-arm64-0.0.383.tgz", + "integrity": "sha512-GfwHGgVmlYS3ksQhyBRQRUQtGtumRDoszByBfkyoJrDH9bLjAMM3EyS6r5nhmH7PMadjU4ZCkj8FGek7imDGtw==", "cpu": [ "arm64" ], @@ -499,9 +499,9 @@ } }, "node_modules/@github/copilot-darwin-x64": { - "version": "0.0.372", - "resolved": "https://registry.npmjs.org/@github/copilot-darwin-x64/-/copilot-darwin-x64-0.0.372.tgz", - "integrity": "sha512-dow+jJj9tpTqM4N8B+edyuA0Dp9IjLA2mT3TRTLUR5GCumonyAoCYxyWL6wClk8yAkmzE1xEttVhQrVpHq4CSA==", + "version": "0.0.383", + "resolved": "https://registry.npmjs.org/@github/copilot-darwin-x64/-/copilot-darwin-x64-0.0.383.tgz", + "integrity": "sha512-4gTjY9St/MyFadPpdvVYiGjvHPPYmFns6ic3AX3q+HTpj1zqGpnjLbwfZeM/Lfb84oMIhM2sR1G/Bv8B+T3l/g==", "cpu": [ "x64" ], @@ -516,9 +516,9 @@ } }, "node_modules/@github/copilot-linux-arm64": { - "version": "0.0.372", - "resolved": "https://registry.npmjs.org/@github/copilot-linux-arm64/-/copilot-linux-arm64-0.0.372.tgz", - "integrity": "sha512-4gSqkfobzXUtOJeDkYExD11dHH4kv5HnSElLYuduBM+FgC3uQlC6CfzUAAd0PSqFtVmAAMy+x6VQT3owmQ6eSw==", + "version": "0.0.383", + "resolved": "https://registry.npmjs.org/@github/copilot-linux-arm64/-/copilot-linux-arm64-0.0.383.tgz", + "integrity": "sha512-QoqK76G7sAh7DVpg2GlnIDa5lYe9FK9U1oFwOVjwXwwKJe8PpIWwNVeO4nERGrkc4CQy7u4U59GSmfXQzoFXvw==", "cpu": [ "arm64" ], @@ -533,9 +533,9 @@ } }, "node_modules/@github/copilot-linux-x64": { - "version": "0.0.372", - "resolved": "https://registry.npmjs.org/@github/copilot-linux-x64/-/copilot-linux-x64-0.0.372.tgz", - "integrity": "sha512-fIVTM0tkzBxy7qk+P8SU/cmOyG+toT51FZbZtZxtIQnoIDrZ07owrhUJZnOahkW09JB756ywcAseeOwNiVtvRA==", + "version": "0.0.383", + "resolved": "https://registry.npmjs.org/@github/copilot-linux-x64/-/copilot-linux-x64-0.0.383.tgz", + "integrity": "sha512-EJHnq575pv7N586WjQkZZdDLqfd2GemGxk3aIhWrHtXMmLY4qRAJJBUnF1MtNqccTKuPmLuD8nAUTrxQp7sWPA==", "cpu": [ "x64" ], @@ -550,9 +550,9 @@ } }, "node_modules/@github/copilot-win32-arm64": { - "version": "0.0.372", - "resolved": "https://registry.npmjs.org/@github/copilot-win32-arm64/-/copilot-win32-arm64-0.0.372.tgz", - "integrity": "sha512-kB8DiOe6beWI1QWrFj3KEhqXrlN5T25A2grnyBxegokhk7LdweaDbNWGc8g+0FqoLqW+MsQC5092LOKK1IzZ8w==", + "version": "0.0.383", + "resolved": "https://registry.npmjs.org/@github/copilot-win32-arm64/-/copilot-win32-arm64-0.0.383.tgz", + "integrity": "sha512-76NT8ULHpbmM/YOz71FPAUUfAhfEVqhEew+Wkqtgn+eG48gCnDYu3ZQIRbnWIh/oj6nYVTyi0wg9LUt7M8sFRQ==", "cpu": [ "arm64" ], @@ -567,9 +567,9 @@ } }, "node_modules/@github/copilot-win32-x64": { - "version": "0.0.372", - "resolved": "https://registry.npmjs.org/@github/copilot-win32-x64/-/copilot-win32-x64-0.0.372.tgz", - "integrity": "sha512-51HeCrthzCB9hbix/g48gIGE0dQgN+Eq4hzeyb12h2qJIwtlxjkvTpdPRs+0Vy9zRjlQNrHIMMnd8C+azFBfPA==", + "version": "0.0.383", + "resolved": "https://registry.npmjs.org/@github/copilot-win32-x64/-/copilot-win32-x64-0.0.383.tgz", + "integrity": "sha512-/5r5uK8pUoefS8H9cax96GqBzm62uBeXEphct7SxPU/gnf2udDvb+0iBOlvKskAwdWNXLp3Khxgm4nfFgxrr9A==", "cpu": [ "x64" ], diff --git a/test/harness/package.json b/test/harness/package.json index 80811e4..cacceb4 100644 --- a/test/harness/package.json +++ b/test/harness/package.json @@ -11,7 +11,7 @@ "test": "vitest run" }, "devDependencies": { - "@github/copilot": "^0.0.372", + "@github/copilot": "^0.0.383", "@types/node": "^25.0.3", "openai": "^6.15.0", "tsx": "^4.21.0", diff --git a/test/harness/replayingCapiProxy.ts b/test/harness/replayingCapiProxy.ts index ba8df91..b48a5b5 100644 --- a/test/harness/replayingCapiProxy.ts +++ b/test/harness/replayingCapiProxy.ts @@ -146,12 +146,13 @@ export class ReplayingCapiProxy extends CapturingHttpProxy { // Handle /stop endpoint for stopping the proxy if ( - options.requestOptions.path === "/stop" && + options.requestOptions.path?.startsWith("/stop") && options.requestOptions.method === "POST" ) { + const skipWritingCache = options.requestOptions.path.includes("skipWritingCache=true"); options.onResponseStart(200, {}); options.onResponseEnd(); - await this.stop(); + await this.stop(skipWritingCache); process.exit(0); } diff --git a/test/snapshots/mcp-and-agents/should_accept_custom_agent_configuration_on_session_resume.yaml b/test/snapshots/mcp-and-agents/should_accept_custom_agent_configuration_on_session_resume.yaml index 16db486..9703495 100644 --- a/test/snapshots/mcp-and-agents/should_accept_custom_agent_configuration_on_session_resume.yaml +++ b/test/snapshots/mcp-and-agents/should_accept_custom_agent_configuration_on_session_resume.yaml @@ -7,8 +7,8 @@ conversations: - role: user content: What is 1+1? - role: assistant - content: 1 + 1 = 2 + content: 1+1 equals 2. - role: user content: What is 6+6? - role: assistant - content: 6 + 6 = 12 + content: 6+6 equals 12. diff --git a/test/snapshots/permissions/async_permission_handler.yaml b/test/snapshots/permissions/async_permission_handler.yaml index 38cbf14..5cc63c0 100644 --- a/test/snapshots/permissions/async_permission_handler.yaml +++ b/test/snapshots/permissions/async_permission_handler.yaml @@ -19,7 +19,24 @@ conversations: type: function function: name: ${shell} - arguments: '{"command":"echo test","description":"Run echo test"}' + arguments: '{"command":"echo test","description":"Run echo test command"}' + - messages: + - role: system + content: ${system} + - role: user + content: Run 'echo test' and tell me what happens + - role: assistant + tool_calls: + - id: toolcall_0 + type: function + function: + name: report_intent + arguments: '{"intent":"Running echo command"}' + - id: toolcall_1 + type: function + function: + name: ${shell} + arguments: '{"command":"echo test","description":"Run echo test command"}' - role: tool tool_call_id: toolcall_0 content: Intent logged @@ -29,4 +46,5 @@ conversations: test - role: assistant - content: The command printed "test" to the console and exited successfully with exit code 0. + content: The command successfully executed and outputted "test" to the console, then exited with code 0 (indicating + success). diff --git a/test/snapshots/permissions/permission_handler_errors.yaml b/test/snapshots/permissions/permission_handler_errors.yaml index 8b3467f..cee78a0 100644 --- a/test/snapshots/permissions/permission_handler_errors.yaml +++ b/test/snapshots/permissions/permission_handler_errors.yaml @@ -20,6 +20,23 @@ conversations: function: name: ${shell} arguments: '{"command":"echo test","description":"Run echo test"}' + - messages: + - role: system + content: ${system} + - role: user + content: Run 'echo test'. If you can't, say 'failed'. + - role: assistant + tool_calls: + - id: toolcall_0 + type: function + function: + name: report_intent + arguments: '{"intent":"Running echo command"}' + - id: toolcall_1 + type: function + function: + name: ${shell} + arguments: '{"command":"echo test","description":"Run echo test"}' - role: tool tool_call_id: toolcall_0 content: Intent logged diff --git a/test/snapshots/permissions/permission_handler_for_shell_commands.yaml b/test/snapshots/permissions/permission_handler_for_shell_commands.yaml index e034afe..c9fad0e 100644 --- a/test/snapshots/permissions/permission_handler_for_shell_commands.yaml +++ b/test/snapshots/permissions/permission_handler_for_shell_commands.yaml @@ -5,7 +5,7 @@ conversations: - role: system content: ${system} - role: user - content: Run 'echo hello world' and tell me the output + content: Run 'echo hello' and tell me the output - role: assistant tool_calls: - id: toolcall_0 @@ -19,14 +19,31 @@ conversations: type: function function: name: ${shell} - arguments: '{"command":"echo hello world","description":"Run echo hello world"}' + arguments: '{"command":"echo hello","description":"Run echo hello"}' + - messages: + - role: system + content: ${system} + - role: user + content: Run 'echo hello' and tell me the output + - role: assistant + tool_calls: + - id: toolcall_0 + type: function + function: + name: report_intent + arguments: '{"intent":"Running echo command"}' + - id: toolcall_1 + type: function + function: + name: ${shell} + arguments: '{"command":"echo hello","description":"Run echo hello"}' - role: tool tool_call_id: toolcall_0 content: Intent logged - role: tool tool_call_id: toolcall_1 content: |- - hello world + hello - role: assistant - content: "The output is: **hello world**" + content: The output is `hello` with exit code 0 (success). diff --git a/test/snapshots/permissions/permission_handler_for_write_operations.yaml b/test/snapshots/permissions/permission_handler_for_write_operations.yaml index f5a75a5..a086398 100644 --- a/test/snapshots/permissions/permission_handler_for_write_operations.yaml +++ b/test/snapshots/permissions/permission_handler_for_write_operations.yaml @@ -6,6 +6,8 @@ conversations: content: ${system} - role: user content: Edit test.txt and replace 'original' with 'modified' + - role: assistant + content: I'll view the file first to see its contents, then make the replacement. - role: assistant tool_calls: - id: toolcall_0 @@ -20,6 +22,24 @@ conversations: function: name: view arguments: '{"path":"${workdir}/test.txt"}' + - messages: + - role: system + content: ${system} + - role: user + content: Edit test.txt and replace 'original' with 'modified' + - role: assistant + content: I'll view the file first to see its contents, then make the replacement. + tool_calls: + - id: toolcall_0 + type: function + function: + name: report_intent + arguments: '{"intent":"Editing test.txt file"}' + - id: toolcall_1 + type: function + function: + name: view + arguments: '{"path":"${workdir}/test.txt"}' - role: tool tool_call_id: toolcall_0 content: Intent logged @@ -37,4 +57,4 @@ conversations: tool_call_id: toolcall_2 content: File ${workdir}/test.txt updated with changes. - role: assistant - content: Done! Replaced 'original' with 'modified' in test.txt. + content: Done! I've replaced 'original' with 'modified' in test.txt. diff --git a/test/snapshots/permissions/resume_session_with_permission_handler.yaml b/test/snapshots/permissions/resume_session_with_permission_handler.yaml index df6b2ed..3eb0555 100644 --- a/test/snapshots/permissions/resume_session_with_permission_handler.yaml +++ b/test/snapshots/permissions/resume_session_with_permission_handler.yaml @@ -7,7 +7,7 @@ conversations: - role: user content: What is 1+1? - role: assistant - content: 1 + 1 = 2 + content: 1+1 equals 2. - role: user content: Run 'echo resumed' for me - role: assistant @@ -24,6 +24,27 @@ conversations: function: name: ${shell} arguments: '{"command":"echo resumed","description":"Run echo resumed"}' + - messages: + - role: system + content: ${system} + - role: user + content: What is 1+1? + - role: assistant + content: 1+1 equals 2. + - role: user + content: Run 'echo resumed' for me + - role: assistant + tool_calls: + - id: toolcall_0 + type: function + function: + name: report_intent + arguments: '{"intent":"Running echo command"}' + - id: toolcall_1 + type: function + function: + name: ${shell} + arguments: '{"command":"echo resumed","description":"Run echo resumed"}' - role: tool tool_call_id: toolcall_0 content: Intent logged @@ -33,4 +54,4 @@ conversations: resumed - role: assistant - content: "The command executed successfully and output: `resumed`" + content: 'Command executed successfully - output: "resumed"' diff --git a/test/snapshots/permissions/should_handle_async_permission_handler.yaml b/test/snapshots/permissions/should_handle_async_permission_handler.yaml index 3280fc9..75d97fc 100644 --- a/test/snapshots/permissions/should_handle_async_permission_handler.yaml +++ b/test/snapshots/permissions/should_handle_async_permission_handler.yaml @@ -6,8 +6,6 @@ conversations: content: ${system} - role: user content: Run 'echo test' and tell me what happens - - role: assistant - content: I'll run the echo command for you. - role: assistant tool_calls: - id: toolcall_0 @@ -22,6 +20,23 @@ conversations: function: name: ${shell} arguments: '{"command":"echo test","description":"Run echo test"}' + - messages: + - role: system + content: ${system} + - role: user + content: Run 'echo test' and tell me what happens + - role: assistant + tool_calls: + - id: toolcall_0 + type: function + function: + name: report_intent + arguments: '{"intent":"Running echo command"}' + - id: toolcall_1 + type: function + function: + name: ${shell} + arguments: '{"command":"echo test","description":"Run echo test"}' - role: tool tool_call_id: toolcall_0 content: Intent logged @@ -31,5 +46,4 @@ conversations: test - role: assistant - content: The command executed successfully and printed "test" to the output, then exited with code 0 (indicating - success). + content: The command executed successfully and printed "test" to the console, then exited with code 0 (success). diff --git a/test/snapshots/permissions/should_handle_permission_handler_errors_gracefully.yaml b/test/snapshots/permissions/should_handle_permission_handler_errors_gracefully.yaml index c12f966..30b556f 100644 --- a/test/snapshots/permissions/should_handle_permission_handler_errors_gracefully.yaml +++ b/test/snapshots/permissions/should_handle_permission_handler_errors_gracefully.yaml @@ -20,6 +20,23 @@ conversations: function: name: ${shell} arguments: '{"command":"echo test","description":"Run echo test command"}' + - messages: + - role: system + content: ${system} + - role: user + content: Run 'echo test'. If you can't, say 'failed'. + - role: assistant + tool_calls: + - id: toolcall_0 + type: function + function: + name: report_intent + arguments: '{"intent":"Running echo command"}' + - id: toolcall_1 + type: function + function: + name: ${shell} + arguments: '{"command":"echo test","description":"Run echo test command"}' - role: tool tool_call_id: toolcall_0 content: Intent logged diff --git a/test/snapshots/permissions/should_invoke_permission_handler_for_write_operations.yaml b/test/snapshots/permissions/should_invoke_permission_handler_for_write_operations.yaml index f5a75a5..3ce2ee4 100644 --- a/test/snapshots/permissions/should_invoke_permission_handler_for_write_operations.yaml +++ b/test/snapshots/permissions/should_invoke_permission_handler_for_write_operations.yaml @@ -20,6 +20,23 @@ conversations: function: name: view arguments: '{"path":"${workdir}/test.txt"}' + - messages: + - role: system + content: ${system} + - role: user + content: Edit test.txt and replace 'original' with 'modified' + - role: assistant + tool_calls: + - id: toolcall_0 + type: function + function: + name: report_intent + arguments: '{"intent":"Editing test.txt file"}' + - id: toolcall_1 + type: function + function: + name: view + arguments: '{"path":"${workdir}/test.txt"}' - role: tool tool_call_id: toolcall_0 content: Intent logged @@ -37,4 +54,4 @@ conversations: tool_call_id: toolcall_2 content: File ${workdir}/test.txt updated with changes. - role: assistant - content: Done! Replaced 'original' with 'modified' in test.txt. + content: Done! I've replaced 'original' with 'modified' in test.txt. diff --git a/test/snapshots/permissions/should_receive_toolcallid_in_permission_requests.yaml b/test/snapshots/permissions/should_receive_toolcallid_in_permission_requests.yaml index c95028a..63fde59 100644 --- a/test/snapshots/permissions/should_receive_toolcallid_in_permission_requests.yaml +++ b/test/snapshots/permissions/should_receive_toolcallid_in_permission_requests.yaml @@ -20,6 +20,23 @@ conversations: function: name: ${shell} arguments: '{"command":"echo test","description":"Run echo test"}' + - messages: + - role: system + content: ${system} + - role: user + content: Run 'echo test' + - role: assistant + tool_calls: + - id: toolcall_0 + type: function + function: + name: report_intent + arguments: '{"intent":"Running echo command"}' + - id: toolcall_1 + type: function + function: + name: ${shell} + arguments: '{"command":"echo test","description":"Run echo test"}' - role: tool tool_call_id: toolcall_0 content: Intent logged @@ -29,4 +46,4 @@ conversations: test - role: assistant - content: "The command executed successfully and output: **test**" + content: The command executed successfully and output "test". diff --git a/test/snapshots/permissions/should_resume_session_with_permission_handler.yaml b/test/snapshots/permissions/should_resume_session_with_permission_handler.yaml index ef80b03..69a52be 100644 --- a/test/snapshots/permissions/should_resume_session_with_permission_handler.yaml +++ b/test/snapshots/permissions/should_resume_session_with_permission_handler.yaml @@ -7,7 +7,7 @@ conversations: - role: user content: What is 1+1? - role: assistant - content: 1 + 1 = 2 + content: 1+1 = 2 - role: user content: Run 'echo resumed' for me - role: assistant @@ -23,7 +23,28 @@ conversations: type: function function: name: ${shell} - arguments: '{"command":"echo resumed","description":"Run echo resumed"}' + arguments: '{"description":"Run echo resumed","command":"echo resumed"}' + - messages: + - role: system + content: ${system} + - role: user + content: What is 1+1? + - role: assistant + content: 1+1 = 2 + - role: user + content: Run 'echo resumed' for me + - role: assistant + tool_calls: + - id: toolcall_0 + type: function + function: + name: report_intent + arguments: '{"intent":"Running echo command"}' + - id: toolcall_1 + type: function + function: + name: ${shell} + arguments: '{"description":"Run echo resumed","command":"echo resumed"}' - role: tool tool_call_id: toolcall_0 content: Intent logged @@ -33,4 +54,4 @@ conversations: resumed - role: assistant - content: The command completed successfully and output "resumed". + content: "The command executed successfully and output: **resumed**" diff --git a/test/snapshots/permissions/tool_call_id_in_permission_requests.yaml b/test/snapshots/permissions/tool_call_id_in_permission_requests.yaml index ebde8aa..3620c2c 100644 --- a/test/snapshots/permissions/tool_call_id_in_permission_requests.yaml +++ b/test/snapshots/permissions/tool_call_id_in_permission_requests.yaml @@ -20,6 +20,23 @@ conversations: function: name: ${shell} arguments: '{"command":"echo test","description":"Run echo test"}' + - messages: + - role: system + content: ${system} + - role: user + content: Run 'echo test' + - role: assistant + tool_calls: + - id: toolcall_0 + type: function + function: + name: report_intent + arguments: '{"intent":"Running echo command"}' + - id: toolcall_1 + type: function + function: + name: ${shell} + arguments: '{"command":"echo test","description":"Run echo test"}' - role: tool tool_call_id: toolcall_0 content: Intent logged @@ -29,4 +46,4 @@ conversations: test - role: assistant - content: "Command executed successfully. Output: `test`" + content: "The command executed successfully and output: `test`" diff --git a/test/snapshots/session/should_abort_a_session.yaml b/test/snapshots/session/should_abort_a_session.yaml index a618779..de6c928 100644 --- a/test/snapshots/session/should_abort_a_session.yaml +++ b/test/snapshots/session/should_abort_a_session.yaml @@ -6,9 +6,10 @@ conversations: content: ${system} - role: user content: What is 1+1? - - role: assistant - content: 1 + 1 = 2 - role: user content: What is 2+2? - role: assistant - content: 2 + 2 = 4 + content: |- + 1+1 = 2 + + 2+2 = 4 diff --git a/test/snapshots/session/should_create_a_session_with_appended_systemmessage_config.yaml b/test/snapshots/session/should_create_a_session_with_appended_systemmessage_config.yaml index 3950fb0..3bf4a39 100644 --- a/test/snapshots/session/should_create_a_session_with_appended_systemmessage_config.yaml +++ b/test/snapshots/session/should_create_a_session_with_appended_systemmessage_config.yaml @@ -8,8 +8,8 @@ conversations: content: What is your full name? - role: assistant content: >- - My full name is **GitHub Copilot CLI**. I'm a terminal assistant built by GitHub to help you with software - engineering tasks directly from the command line. + I am the GitHub Copilot CLI, a terminal assistant built by GitHub. I'm an interactive command-line tool + designed to help with software engineering tasks. Have a nice day! diff --git a/test/snapshots/session/should_create_session_with_custom_tool.yaml b/test/snapshots/session/should_create_session_with_custom_tool.yaml index 69f50e6..4ae6dab 100644 --- a/test/snapshots/session/should_create_session_with_custom_tool.yaml +++ b/test/snapshots/session/should_create_session_with_custom_tool.yaml @@ -6,8 +6,6 @@ conversations: content: ${system} - role: user content: What is the secret number for key ALPHA? - - role: assistant - content: I'll get the secret number for key ALPHA. - role: assistant tool_calls: - id: toolcall_0 diff --git a/test/snapshots/session/should_have_stateful_conversation.yaml b/test/snapshots/session/should_have_stateful_conversation.yaml index bd02858..39d3c5a 100644 --- a/test/snapshots/session/should_have_stateful_conversation.yaml +++ b/test/snapshots/session/should_have_stateful_conversation.yaml @@ -7,7 +7,7 @@ conversations: - role: user content: What is 1+1? - role: assistant - content: 1 + 1 = 2 + content: 1+1 = 2 - role: user content: Now if you double that, what do you get? - role: assistant diff --git a/test/snapshots/tools/invokes_built_in_tools.yaml b/test/snapshots/tools/invokes_built_in_tools.yaml index 466d4bb..fc60c8b 100644 --- a/test/snapshots/tools/invokes_built_in_tools.yaml +++ b/test/snapshots/tools/invokes_built_in_tools.yaml @@ -12,14 +12,31 @@ conversations: type: function function: name: report_intent - arguments: '{"intent":"Reading README file"}' + arguments: '{"intent":"Reading README.md file"}' - role: assistant tool_calls: - id: toolcall_1 type: function function: name: view - arguments: '{"path":"${workdir}/README.md","view_range":[1,1]}' + arguments: '{"path":"${workdir}/README.md"}' + - messages: + - role: system + content: ${system} + - role: user + content: What's the first line of README.md in this directory? + - role: assistant + tool_calls: + - id: toolcall_0 + type: function + function: + name: report_intent + arguments: '{"intent":"Reading README.md file"}' + - id: toolcall_1 + type: function + function: + name: view + arguments: '{"path":"${workdir}/README.md"}' - role: tool tool_call_id: toolcall_0 content: Intent logged @@ -27,4 +44,9 @@ conversations: tool_call_id: toolcall_1 content: "1. # ELIZA, the only chatbot you'll ever need" - role: assistant - content: "The first line of README.md is: `# ELIZA, the only chatbot you'll ever need`" + content: |- + The first line of README.md is: + + ``` + # ELIZA, the only chatbot you'll ever need + ```