Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 25 additions & 1 deletion dotnet/src/Generated/SessionEvents.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -39,6 +39,7 @@ internal class SessionEventConverter : JsonConverter<SessionEvent>
["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),
Expand Down Expand Up @@ -209,6 +210,17 @@ public partial class SessionTruncationEvent : SessionEvent
public SessionTruncationData Data { get; set; }
}

/// <summary>
/// Event: session.usage_info
/// </summary>
public partial class SessionUsageInfoEvent : SessionEvent
{
public override string Type => "session.usage_info";

[JsonPropertyName("data")]
public SessionUsageInfoData Data { get; set; }
}

/// <summary>
/// Event: session.compaction_start
/// </summary>
Expand Down Expand Up @@ -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
{
}
Expand Down
5 changes: 3 additions & 2 deletions dotnet/test/Harness/CapiProxy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,15 +84,16 @@ async Task<string> 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 */ }
}
Expand Down
4 changes: 3 additions & 1 deletion dotnet/test/Harness/E2ETestContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,9 @@ public IReadOnlyDictionary<string, string> 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 { }
Expand Down
2 changes: 1 addition & 1 deletion go/e2e/permissions_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
6 changes: 3 additions & 3 deletions go/e2e/testharness/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ func NewTestContext(t *testing.T) *TestContext {
}

t.Cleanup(func() {
ctx.Close()
ctx.Close(t.Failed())
})

return ctx
Expand Down Expand Up @@ -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)
Expand Down
12 changes: 11 additions & 1 deletion go/e2e/testharness/proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()

Expand All @@ -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()
}
Expand Down
5 changes: 4 additions & 1 deletion go/generated/session_events.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

56 changes: 28 additions & 28 deletions nodejs/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion nodejs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
},
Expand Down
14 changes: 13 additions & 1 deletion nodejs/src/generated/session-events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down
7 changes: 5 additions & 2 deletions nodejs/test/e2e/harness/CapiProxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,11 @@ export class CapiProxy {
return await response.json();
}

async stop(): Promise<void> {
const response = await fetch(`${this.proxyUrl}/stop`, { method: "POST" });
async stop(skipWritingCache?: boolean): Promise<void> {
const url = skipWritingCache
? `${this.proxyUrl}/stop?skipWritingCache=true`
: `${this.proxyUrl}/stop`;
const response = await fetch(url, { method: "POST" });
expect(response.ok).toBe(true);
}
}
16 changes: 13 additions & 3 deletions nodejs/test/e2e/harness/sdkTestContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand All @@ -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-")));
Expand All @@ -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,
Expand All @@ -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);
});
Expand Down
Loading
Loading