Skip to content
Closed
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
38 changes: 0 additions & 38 deletions apps/Agentweaver.AgentHost/AgentHostOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -129,42 +129,4 @@ public sealed class AgentHostOptions
/// <summary>Optional system prompt context injected by the workflow graph.</summary>
public string? SystemPromptContext { get; init; }

// ── Token store selection ─────────────────────────────────────────────────

/// <summary>
/// When <see langword="true"/>, the agent-host reads GitHub tokens from the shared RWX
/// filesystem store written by the API/worker tier (spec-018 P1.5). See
/// <see cref="SharedTokenStorePath"/>. Takes effect only when
/// <see cref="KvTokenMountPath"/> is not set.
/// Config key: <c>AgentHost:UseSharedTokenStore</c>.
/// </summary>
public bool UseSharedTokenStore { get; init; }

/// <summary>
/// Root path of the shared RWX auth directory, used with <see cref="UseSharedTokenStore"/>.
/// Passed to <see cref="SharedTokenStorePaths.ResolveAuthDir"/>.
/// Config key: <c>AgentHost:SharedTokenStorePath</c>.
/// </summary>
public string? SharedTokenStorePath { get; init; }

/// <summary>
/// When set, GitHub user tokens are read from CSI-mounted files at this path (Option B).
/// The CSI driver mounts per-user token files from Key Vault as
/// <c>{KvTokenMountPath}/user_{userId}.json</c>.
/// Config key: <c>AgentHost:KvTokenMountPath</c>.
/// When set, takes precedence over <see cref="UseSharedTokenStore"/>.
/// </summary>
public string? KvTokenMountPath { get; init; }

/// <summary>Azure Key Vault URI for runtime token fetch (Option C warm-pool path).
/// When set, overrides KvTokenMountPath — token is fetched via workload identity at configure-time.
/// Config key: AgentHost:KeyVaultUri
/// </summary>
public string? KeyVaultUri { get; init; }

/// <summary>Key Vault secret name for the run owner's GitHub token.
/// Passed in the /configure call. Format: ghtok-user--{base32(userId)}.
/// Config key: AgentHost:KvUserSecretName
/// </summary>
public string? KvUserSecretName { get; init; }
}
37 changes: 12 additions & 25 deletions apps/Agentweaver.AgentHost/AgentHostRuntimeState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ namespace Agentweaver.AgentHost;
/// <list type="bullet">
/// <item>Env-var launch (non-warm pod): <see cref="AgentHostStartupService"/> seeds this from
/// <see cref="AgentHostOptions"/> at startup via <see cref="InitializeFromOptions"/>.</item>
/// <item>Warm pool: the pod starts in standby with no run context; the executor injects RunId /
/// UserId / TurnBearerToken / KvUserSecretName at run-launch time via <see cref="TryConfigure"/>.</item>
/// <item>Warm pool: the pod starts in standby with no run context; the executor injects run-bound
/// control data through <see cref="TryConfigure"/>.</item>
/// </list>
/// </para>
///
Expand Down Expand Up @@ -74,22 +74,15 @@ internal sealed class AgentHostRuntimeState
public string PreviewRunnerCredential { get; private set; } = string.Empty;

/// <summary>
/// Key Vault secret name for the run owner's GitHub token (Option C warm-pool path).
/// Supplied by the executor in the /configure call; consumed by
/// <see cref="KeyVaultUserTokenProvider"/>. Null on the file-mount/shared-store paths.
/// </summary>
public string? KvUserSecretName { get; private set; }

/// <summary>
/// Pre-resolved GitHub OAuth access token supplied by the API in the /configure body.
/// When set, <see cref="KeyVaultUserTokenProvider"/> uses this directly and skips the KV call,
/// allowing the pod to work without outbound access to Azure AD or Key Vault.
/// Bounded Copilot sign-in material delivered in memory to this trusted host only. It is never
/// inherited by the executor sidecar or preview children and is not a repository credential.
/// </summary>
public string? GitHubAccessToken { get; private set; }
public string? CopilotAccessToken { get; private set; }

/// <summary>
/// The authenticated platform caller token forwarded only for operator-assistant MCP requests.
/// This is distinct from <see cref="GitHubAccessToken"/>: in Entra deployments the former is the
/// This is distinct from <see cref="CopilotAccessToken"/>: in Entra deployments the former is the
/// Entra API access token while the latter is the linked GitHub token used by Copilot.
/// </summary>
public string? CallerBearerToken { get; private set; }
Expand All @@ -105,8 +98,7 @@ public void InitializeFromOptions(AgentHostOptions options)
UserId = options.UserId ?? string.Empty;
TurnBearerToken = options.TurnBearerToken ?? string.Empty;
PreviewRunnerCredential = string.Empty; // not available on env-var launch path
KvUserSecretName = options.KvUserSecretName;
GitHubAccessToken = null; // not available on env-var launch path
CopilotAccessToken = null; // credentials are never injected through the pod environment
CallerBearerToken = null; // operator-assistant-only warm-pod input
Purpose = AgentHostPurpose.Default;
WorkspaceMode = ExecutionWorkspaceMode.Shared;
Expand All @@ -127,13 +119,12 @@ public void InitializeFromOptions(AgentHostOptions options)
/// Atomically transitions the pod from standby to configured. Returns <see langword="false"/>
/// when the pod was already configured (one-time semantics → caller returns 409).
/// </summary>
public bool TryConfigure(string runId, string userId, string turnBearerToken, string? kvUserSecretName, string? gitHubAccessToken, string? previewRunnerCredential = null)
public bool TryConfigure(string runId, string userId, string turnBearerToken, string? copilotAccessToken, string? previewRunnerCredential = null)
=> TryConfigure(new AgentHostRunConfiguration(
runId,
userId,
turnBearerToken,
kvUserSecretName,
gitHubAccessToken,
copilotAccessToken,
previewRunnerCredential,
SharedWorkingDirectory: null));

Expand All @@ -147,12 +138,9 @@ public bool TryConfigure(AgentHostRunConfiguration configuration)
UserId = configuration.UserId ?? string.Empty;
TurnBearerToken = configuration.TurnBearerToken ?? string.Empty;
PreviewRunnerCredential = configuration.PreviewRunnerCredential ?? string.Empty;
KvUserSecretName = string.IsNullOrWhiteSpace(configuration.KvUserSecretName)
? null
: configuration.KvUserSecretName;
GitHubAccessToken = string.IsNullOrWhiteSpace(configuration.GitHubAccessToken)
CopilotAccessToken = string.IsNullOrWhiteSpace(configuration.CopilotAccessToken)
? null
: configuration.GitHubAccessToken;
: configuration.CopilotAccessToken;
CallerBearerToken = string.IsNullOrWhiteSpace(configuration.CallerBearerToken)
? null
: configuration.CallerBearerToken;
Expand Down Expand Up @@ -193,8 +181,7 @@ internal sealed record AgentHostRunConfiguration(
string RunId,
string UserId,
string TurnBearerToken,
string? KvUserSecretName,
string? GitHubAccessToken,
string? CopilotAccessToken,
string? PreviewRunnerCredential,
string? SharedWorkingDirectory,
AgentHostPurpose Purpose = AgentHostPurpose.Default,
Expand Down
11 changes: 4 additions & 7 deletions apps/Agentweaver.AgentHost/AgentHostStartupService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ namespace Agentweaver.AgentHost;
/// <item><b>Env-var launch</b> (non-warm pod): <see cref="AgentHostOptions.RunId"/> is set at
/// startup, so <see cref="StartAsync"/> runs <c>SetupAsync</c> immediately and the pod is ready
/// when <see cref="StartAsync"/> returns (legacy behaviour).</item>
/// <item><b>Warm pool</b> (Option C): the pod starts with NO RunId and enters <b>standby</b> —
/// <item><b>Warm pool</b>: the pod starts with NO RunId and enters <b>standby</b> —
/// <c>SetupAsync</c> is deferred until the executor calls <see cref="ConfigureAsync"/> from the
/// <c>POST /configure</c> handler at run-launch time. The .NET process and Copilot SDK are
/// already warm, so only the per-run setup runs on the request path.</item>
Expand Down Expand Up @@ -89,8 +89,7 @@ await RunSetupAsync(
opts.RunId,
opts.UserId ?? string.Empty,
opts.TurnBearerToken ?? string.Empty,
opts.KvUserSecretName,
GitHubAccessToken: null,
CopilotAccessToken: null,
PreviewRunnerCredential: null,
SharedWorkingDirectory: null,
ProjectId: opts.ProjectId,
Expand All @@ -106,8 +105,7 @@ public async Task ConfigureAsync(
string runId,
string userId,
string turnBearerToken,
string? kvUserSecretName,
string? gitHubAccessToken,
string? copilotAccessToken,
string? workingDirectory,
bool autoApproveTools,
CancellationToken ct)
Expand All @@ -116,8 +114,7 @@ public async Task ConfigureAsync(
runId,
userId,
turnBearerToken,
kvUserSecretName,
gitHubAccessToken,
copilotAccessToken,
PreviewRunnerCredential: null,
SharedWorkingDirectory: workingDirectory),
autoApproveTools,
Expand Down
8 changes: 0 additions & 8 deletions apps/Agentweaver.AgentHost/Agentweaver.AgentHost.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,6 @@
</ItemGroup>

<ItemGroup>
<!--
Option C warm-pool path: fetch the run owner's GitHub token from Key Vault at /configure-time
via workload identity (DefaultAzureCredential), replacing the per-run CSI secret mount.
Not transitive via AgentRuntime (which only pulls Azure.AI.OpenAI), so referenced explicitly.
Versions match Agentweaver.Api.
-->
<PackageReference Include="Azure.Security.KeyVault.Secrets" Version="4.11.0" />
<PackageReference Include="Azure.Identity" Version="1.21.0" />
<PackageReference Include="Microsoft.Extensions.AI" Version="10.9.0" />
</ItemGroup>

Expand Down
72 changes: 0 additions & 72 deletions apps/Agentweaver.AgentHost/CsiMountedGitHubTokenStore.cs

This file was deleted.

Loading
Loading