Skip to content

Commit 010840f

Browse files
authored
Merge branch 'main' into belaltaher8/tool-meta-passthrough
2 parents 9aa5e0a + 584a239 commit 010840f

134 files changed

Lines changed: 5751 additions & 617 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/go-sdk-tests.yml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,15 @@ permissions:
2929

3030
jobs:
3131
test:
32-
name: "Go SDK Tests"
32+
name: "Go SDK Tests (${{ matrix.os }}, ${{ matrix.transport }})"
3333
if: github.event.repository.fork == false
3434
env:
3535
POWERSHELL_UPDATECHECK: Off
3636
strategy:
3737
fail-fast: false
3838
matrix:
3939
os: [ubuntu-latest, macos-latest, windows-latest]
40+
transport: ["default", "inprocess"]
4041
runs-on: ${{ matrix.os }}
4142
defaults:
4243
run:
@@ -78,6 +79,12 @@ jobs:
7879
if: runner.os == 'Windows'
7980
run: pwsh.exe -Command "Write-Host 'PowerShell ready'"
8081

82+
- name: Select inprocess transport
83+
if: matrix.transport == 'inprocess'
84+
run: |
85+
echo "COPILOT_SDK_DEFAULT_CONNECTION=inprocess" >> "$GITHUB_ENV"
86+
echo "GOFLAGS=-tags=copilot_inprocess" >> "$GITHUB_ENV"
87+
8188
- name: Run Go SDK tests
8289
env:
8390
COPILOT_HMAC_KEY: ${{ secrets.COPILOT_DEVELOPER_CLI_INTEGRATION_HMAC_KEY }}

.github/workflows/python-sdk-tests.yml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ permissions:
3131

3232
jobs:
3333
test:
34-
name: "Python SDK Tests"
34+
name: "Python SDK Tests (${{ matrix.os }}, ${{ matrix.transport }})"
3535
if: github.event.repository.fork == false
3636
env:
3737
POWERSHELL_UPDATECHECK: Off
@@ -41,6 +41,7 @@ jobs:
4141
os: [ubuntu-latest, macos-latest, windows-latest]
4242
# Test the oldest supported Python version to make sure compatibility is maintained.
4343
python-version: ["3.11"]
44+
transport: ["default", "inprocess"]
4445
runs-on: ${{ matrix.os }}
4546
defaults:
4647
run:
@@ -86,6 +87,11 @@ jobs:
8687
if: runner.os == 'Windows'
8788
run: pwsh.exe -Command "Write-Host 'PowerShell ready'"
8889

90+
- name: Select inprocess transport
91+
if: matrix.transport == 'inprocess'
92+
run: |
93+
echo "COPILOT_SDK_DEFAULT_CONNECTION=inprocess" >> "$GITHUB_ENV"
94+
8995
- name: Run Python SDK tests
9096
env:
9197
COPILOT_HMAC_KEY: ${{ secrets.COPILOT_DEVELOPER_CLI_INTEGRATION_HMAC_KEY }}

docs/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copilot SDK
1+
# Copilot SDK
22

33
Welcome to the GitHub Copilot SDK docs. Whether you're building your first Copilot-powered app or deploying to production, you'll find what you need here.
44

docs/auth/authenticate.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ The GitHub Copilot SDK supports multiple authentication methods to fit different
99
| [GitHub Signed-in User](#github-signed-in-user) | Interactive apps where users sign in with GitHub | Yes |
1010
| [OAuth GitHub App](#oauth-github-app) | Apps acting on behalf of users via OAuth | Yes |
1111
| [Environment Variables](#environment-variables) | CI/CD, automation, server-to-server | Yes |
12-
| [BYOK (Bring Your Own Key)](./byok.md) | Using your own API keys (Azure AI Foundry, OpenAI, etc.) | No |
12+
| [BYOK (Bring Your Own Key)](./byok.md) | Using your own API keys (Azure AI Foundry, OpenAI, and more) | No |
1313

1414
## GitHub signed-in user
1515

@@ -221,7 +221,7 @@ client.start().get();
221221

222222
**Supported token types:**
223223
* `gho_` - OAuth user access tokens
224-
* `ghu_` - GitHub App user access tokens
224+
* `ghu_` - GitHub App user access tokens
225225
* `github_pat_` - Fine-grained personal access tokens
226226

227227
**Not supported:**
@@ -275,7 +275,7 @@ await client.start()
275275
</details>
276276

277277
**When to use:**
278-
* CI/CD pipelines (GitHub Actions, Jenkins, etc.)
278+
* CI/CD pipelines (GitHub Actions, Jenkins, and more)
279279
* Automated testing
280280
* Server-side applications with service accounts
281281
* Development when you don't want to use interactive login

docs/features/cloud-sessions.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ Capture the URL by subscribing to `session.info` and filtering by `infoType: "re
235235
session.on("session.info", (event) => {
236236
if (event.data?.infoType === "remote" && event.data.url) {
237237
console.log("Open from web or mobile:", event.data.url);
238-
// e.g. surface in your UI as a shareable link or QR code.
238+
// For example, surface in your UI as a shareable link or QR code.
239239
}
240240
});
241241
```

docs/setup/choosing-a-setup-path.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ Use this table to find the right guides based on what you need to do:
8888
| Getting started quickly | [Default Setup (Bundled CLI)](./bundled-cli.md) |
8989
| Use your own CLI binary or server | [Local CLI](./local-cli.md) |
9090
| Users sign in with GitHub | [GitHub OAuth](./github-oauth.md) |
91-
| Use your own model keys (OpenAI, Azure, etc.) | [BYOK](../auth/byok.md) |
91+
| Use your own model keys (OpenAI, Azure, and more) | [BYOK](../auth/byok.md) |
9292
| Azure BYOK with Managed Identity (no API keys) | [Azure Managed Identity](./azure-managed-identity.md) |
9393
| Run the SDK on a server | [Backend Services](./backend-services.md) |
9494
| Configure SDK options for concurrent users | [Multi-tenancy and server deployments](./multi-tenancy.md) |

docs/troubleshooting/mcp-debugging.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -446,10 +446,10 @@ When opening an issue or asking for help, collect:
446446

447447
* [ ] SDK language and version
448448
* [ ] CLI version (`copilot --version`)
449-
* [ ] MCP server type (Node.js, Python, .NET, Go, Rust, etc.)
449+
* [ ] MCP server type (Node.js, Python, .NET, Go, Rust, and more)
450450
* [ ] Full MCP server configuration (redact secrets)
451451
* [ ] Result of manual `initialize` test
452-
* [ ] Result of manual `tools/list` test
452+
* [ ] Result of manual `tools/list` test
453453
* [ ] Debug logs from SDK
454454
* [ ] Any error messages
455455

dotnet/src/Client.cs

Lines changed: 70 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,17 @@ private static void ValidateEnvironmentOptions(CopilotClientOptions options, Run
238238
nameof(options));
239239
}
240240

241+
if (options.WorkingDirectory is not null)
242+
{
243+
throw new ArgumentException(
244+
$"{nameof(CopilotClientOptions)}.{nameof(CopilotClientOptions.WorkingDirectory)} is not supported with " +
245+
$"{nameof(RuntimeConnection)}.{nameof(RuntimeConnection.ForInProcess)}(): the in-process transport hosts " +
246+
"the native runtime in the shared host process and spawns the worker without a working-directory " +
247+
"parameter, so a per-client working directory cannot be honored in-process. Use a child-process " +
248+
"transport, or set the process working directory before creating the client.",
249+
nameof(options));
250+
}
251+
241252
return;
242253
}
243254

@@ -339,16 +350,49 @@ async Task<Connection> StartCoreAsync(CancellationToken ct)
339350
{
340351
if (_connection is InProcessRuntimeConnection)
341352
{
342-
// In-process FFI hosting: load the Rust cdylib and let it spawn
343-
// the CLI worker, instead of the SDK launching a CLI child process.
344-
// The worker reads its configuration (telemetry export, etc.) from
345-
// the environment passed here, so apply the same telemetry-derived
346-
// vars the child-process path sets on its startInfo.Environment.
347-
var ffiEnvironment = _options.Environment?.ToDictionary(kvp => kvp.Key, kvp => (string?)kvp.Value)
348-
?? new Dictionary<string, string?>();
349-
ApplyTelemetryEnvironment(ffiEnvironment, _options.Telemetry);
350-
var resolvedFfiEnvironment = ffiEnvironment.ToDictionary(kvp => kvp.Key, kvp => kvp.Value!);
351-
var ffiHost = FfiRuntimeHost.Create(ResolveCliPathForFfi(), GetNapiPrebuildsFolderOrThrow(), resolvedFfiEnvironment, _logger);
353+
var ffiEnvironment = new Dictionary<string, string>();
354+
if (!string.IsNullOrEmpty(_options.GitHubToken))
355+
{
356+
ffiEnvironment["COPILOT_SDK_AUTH_TOKEN"] = _options.GitHubToken!;
357+
}
358+
if (!string.IsNullOrEmpty(_options.BaseDirectory))
359+
{
360+
ffiEnvironment["COPILOT_HOME"] = _options.BaseDirectory!;
361+
}
362+
if (_options.Mode == CopilotClientMode.Empty)
363+
{
364+
ffiEnvironment["COPILOT_DISABLE_KEYTAR"] = "1";
365+
}
366+
367+
var ffiArgs = new List<string>();
368+
if (_options.LogLevel is { } logLevel && !string.IsNullOrEmpty(logLevel.Value))
369+
{
370+
ffiArgs.AddRange(["--log-level", logLevel.Value]);
371+
}
372+
if (!string.IsNullOrEmpty(_options.GitHubToken))
373+
{
374+
ffiArgs.AddRange(["--auth-token-env", "COPILOT_SDK_AUTH_TOKEN"]);
375+
}
376+
var useLoggedInUser = _options.UseLoggedInUser ?? string.IsNullOrEmpty(_options.GitHubToken);
377+
if (!useLoggedInUser)
378+
{
379+
ffiArgs.Add("--no-auto-login");
380+
}
381+
if (_options.SessionIdleTimeoutSeconds is > 0)
382+
{
383+
ffiArgs.AddRange(["--session-idle-timeout", _options.SessionIdleTimeoutSeconds.Value.ToString(CultureInfo.InvariantCulture)]);
384+
}
385+
if (_options.EnableRemoteSessions)
386+
{
387+
ffiArgs.Add("--remote");
388+
}
389+
390+
var ffiHost = FfiRuntimeHost.Create(
391+
ResolveCliPathForFfi(),
392+
GetNapiPrebuildsFolderOrThrow(),
393+
ffiEnvironment,
394+
ffiArgs,
395+
_logger);
352396
_ffiHost = ffiHost;
353397
await ffiHost.StartAsync(ct);
354398
connection = await ConnectToServerAsync(null, null, null, null, ct, ffiHost);
@@ -1138,6 +1182,7 @@ public async Task<CopilotSession> CreateSessionAsync(SessionConfig config, Cance
11381182
InstructionDirectories: config.InstructionDirectories,
11391183
PluginDirectories: config.PluginDirectories,
11401184
LargeOutput: config.LargeOutput,
1185+
ToolSearch: config.ToolSearch,
11411186
Memory: config.Memory,
11421187
Canvases: config.Canvases,
11431188
RequestCanvasRenderer: config.RequestCanvasRenderer,
@@ -1349,6 +1394,7 @@ public async Task<CopilotSession> ResumeSessionAsync(string sessionId, ResumeSes
13491394
InstructionDirectories: config.InstructionDirectories,
13501395
PluginDirectories: config.PluginDirectories,
13511396
LargeOutput: config.LargeOutput,
1397+
ToolSearch: config.ToolSearch,
13521398
Memory: config.Memory,
13531399
Canvases: config.Canvases,
13541400
RequestCanvasRenderer: config.RequestCanvasRenderer,
@@ -2202,7 +2248,12 @@ private static void ApplyTelemetryEnvironment(IDictionary<string, string?> envir
22022248
{
22032249
string os;
22042250
if (OperatingSystem.IsWindows()) os = "win";
2205-
else if (OperatingSystem.IsLinux()) os = "linux";
2251+
else if (OperatingSystem.IsLinux())
2252+
{
2253+
os = RuntimeInformation.RuntimeIdentifier.StartsWith("linux-musl-", StringComparison.Ordinal)
2254+
? "linux-musl"
2255+
: "linux";
2256+
}
22062257
else if (OperatingSystem.IsMacOS()) os = "osx";
22072258
else return null;
22082259

@@ -2249,7 +2300,12 @@ private string ResolveCliPathForFfi()
22492300
{
22502301
string platform;
22512302
if (OperatingSystem.IsWindows()) platform = "win32";
2252-
else if (OperatingSystem.IsLinux()) platform = "linux";
2303+
else if (OperatingSystem.IsLinux())
2304+
{
2305+
platform = RuntimeInformation.RuntimeIdentifier.StartsWith("linux-musl-", StringComparison.Ordinal)
2306+
? "linuxmusl"
2307+
: "linux";
2308+
}
22532309
else if (OperatingSystem.IsMacOS()) platform = "darwin";
22542310
else return null;
22552311

@@ -2690,6 +2746,7 @@ internal record CreateSessionRequest(
26902746
IList<string>? InstructionDirectories = null,
26912747
IList<string>? PluginDirectories = null,
26922748
LargeToolOutputConfig? LargeOutput = null,
2749+
ToolSearchConfig? ToolSearch = null,
26932750
MemoryConfiguration? Memory = null,
26942751
#pragma warning disable GHCP001
26952752
IList<CanvasDeclaration>? Canvases = null,
@@ -2794,6 +2851,7 @@ internal record ResumeSessionRequest(
27942851
IList<string>? InstructionDirectories = null,
27952852
IList<string>? PluginDirectories = null,
27962853
LargeToolOutputConfig? LargeOutput = null,
2854+
ToolSearchConfig? ToolSearch = null,
27972855
MemoryConfiguration? Memory = null,
27982856
#pragma warning disable GHCP001
27992857
IList<CanvasDeclaration>? Canvases = null,

dotnet/src/FfiRuntimeHost.cs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ internal sealed partial class FfiRuntimeHost : IDisposable
4444
private readonly string _cliEntrypoint;
4545
private readonly string _libraryPath;
4646
private readonly IReadOnlyDictionary<string, string>? _environment;
47+
private readonly IReadOnlyList<string> _args;
4748

4849
private readonly CallbackReceiveStream _receiveStream = new();
4950
private CallbackSendStream? _sendStream;
@@ -52,11 +53,12 @@ internal sealed partial class FfiRuntimeHost : IDisposable
5253
private uint _connectionId;
5354
private bool _disposed;
5455

55-
private FfiRuntimeHost(string libraryPath, string cliEntrypoint, IReadOnlyDictionary<string, string>? environment, ILogger logger)
56+
private FfiRuntimeHost(string libraryPath, string cliEntrypoint, IReadOnlyDictionary<string, string>? environment, IReadOnlyList<string> args, ILogger logger)
5657
{
5758
_libraryPath = libraryPath;
5859
_cliEntrypoint = cliEntrypoint;
5960
_environment = environment;
61+
_args = args;
6062
_logger = logger;
6163
}
6264

@@ -79,7 +81,7 @@ private FfiRuntimeHost(string libraryPath, string cliEntrypoint, IReadOnlyDictio
7981
/// <paramref name="prebuildsFolder"/> is the napi-rs
8082
/// <c>&lt;node-platform&gt;-&lt;arch&gt;</c> folder name (e.g. <c>win32-x64</c>).
8183
/// </summary>
82-
public static FfiRuntimeHost Create(string cliEntrypoint, string prebuildsFolder, IReadOnlyDictionary<string, string>? environment, ILogger logger)
84+
public static FfiRuntimeHost Create(string cliEntrypoint, string prebuildsFolder, IReadOnlyDictionary<string, string>? environment, IReadOnlyList<string> args, ILogger logger)
8385
{
8486
var fullEntrypoint = Path.GetFullPath(cliEntrypoint);
8587
var distDir = Path.GetDirectoryName(fullEntrypoint)
@@ -96,7 +98,7 @@ public static FfiRuntimeHost Create(string cliEntrypoint, string prebuildsFolder
9698
$"FFI runtime library not found. Looked for '{flatLibraryPath}' and '{prebuildsLibraryPath}'.");
9799

98100
PrepareNativeLibrary(libraryPath);
99-
return new FfiRuntimeHost(libraryPath, fullEntrypoint, environment, logger);
101+
return new FfiRuntimeHost(libraryPath, fullEntrypoint, environment, args, logger);
100102
}
101103

102104
/// <summary>
@@ -122,7 +124,7 @@ public async Task StartAsync(CancellationToken cancellationToken)
122124
// perform the blocking FFI handshake on a background thread.
123125
await Task.Run(() =>
124126
{
125-
var argvJson = BuildArgvJson(_cliEntrypoint);
127+
var argvJson = BuildArgvJson(_cliEntrypoint, _args);
126128
var envJson = BuildEnvJson(_environment);
127129

128130
_serverId = NativeHostStart(argvJson, envJson);
@@ -152,7 +154,7 @@ await Task.Run(() =>
152154
}
153155
}
154156

155-
private static byte[] BuildArgvJson(string cliEntrypoint)
157+
private static byte[] BuildArgvJson(string cliEntrypoint, IReadOnlyList<string> args)
156158
{
157159
// A .js entrypoint (dev / dist-cli) is launched via node; the packaged
158160
// single-file CLI binary embeds its own Node and is invoked directly.
@@ -170,6 +172,10 @@ private static byte[] BuildArgvJson(string cliEntrypoint)
170172
// Pin the worker to the bundled pkg matching the loaded cdylib, instead of
171173
// drifting to a newer version under the user's ~/.copilot/pkg (ABI skew).
172174
writer.WriteStringValue("--no-auto-update");
175+
foreach (var arg in args)
176+
{
177+
writer.WriteStringValue(arg);
178+
}
173179
writer.WriteEndArray();
174180
}
175181
return stream.ToArray();

dotnet/src/Generated/Rpc.cs

Lines changed: 26 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)