[codex] Add Tailscale and Aperture integration support#122
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughAdds Aperture/Tailscale integration: new AuthMode and SendRequestMetadata fields flow through models, validation, CLI setup, gateway client/policy, profile registry, docs, and tests to support bearer vs tailnet-identity auth and optional request metadata injection. ChangesTailscale And Aperture Provider Integration
🎯 3 (Moderate) | ⏱️ ~25 minutes
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
🤖 Augment PR SummarySummary: Adds optional Tailscale deployment documentation and first-class Aperture-by-Tailscale integration as an OpenAI-compatible upstream route, without changing the default OpenClaw.NET provider behavior. Changes:
🤖 Was this summary useful? React with 👍 or 👎 |
| return 2; | ||
| } | ||
|
|
||
| var filteredArgs = args.Where(arg => !string.Equals(arg, provider, StringComparison.Ordinal)).ToArray(); |
There was a problem hiding this comment.
src/OpenClaw.Cli/SetupCommand.cs:519: filteredArgs removes the provider token using StringComparison.Ordinal, so openclaw setup provider Aperture ... (different casing) can leave the positional arg in place and make CliArgs.Parse treat it as an unexpected argument.
Severity: medium
🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.
| }, embeddingModel!), | ||
| "gemini" or "google" => CreateGeminiEmbeddingClient(config, embeddingModel!), | ||
| "openai-compatible" or "groq" or "together" or "lmstudio" => | ||
| "openai-compatible" or "aperture" or "groq" or "together" or "lmstudio" => |
There was a problem hiding this comment.
src/OpenClaw.Gateway/Extensions/LlmClientFactory.cs:185-191: the embeddings path for "aperture"/"openai-compatible" doesn’t carry AuthMode/SendRequestMetadata, so tailnet-identity profiles may still require an API key (and metadata behavior may differ) for embeddings even though chat supports no-key mode.
Severity: medium
🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.
| if (string.IsNullOrWhiteSpace(apiKey)) | ||
| { | ||
| if (!IsTailnetIdentityAuth(llm.AuthMode)) | ||
| throw new InvalidOperationException("MODEL_PROVIDER_KEY must be set for the OpenAI-compatible provider."); |
There was a problem hiding this comment.
src/OpenClaw.Gateway/Extensions/LlmClientFactory.cs:260: when Provider="aperture" is missing an API key in bearer mode, the thrown message says “OpenAI-compatible provider”, which may mislead users who are following the Aperture docs/env var naming.
Severity: low
🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.
There was a problem hiding this comment.
Pull request overview
Adds optional first-class Tailscale deployment documentation plus an Aperture-by-Tailscale provider alias/path, including new configuration knobs (AuthMode, SendRequestMetadata), CLI setup assistance, and expanded validation/doctor/smoke behavior—without changing default provider behavior unless explicitly configured.
Changes:
- Document Tailscale Serve/Funnel deployment patterns and Aperture positioning, with security/trust-boundary notes.
- Introduce
Provider = "aperture"as an OpenAI-compatible upstream route, includingAuthMode=tailnet-identity(no bearer token) and opt-in request metadata headers. - Add
openclaw setup provider apertureflow plus updated validation/doctor/smoke checks and tests.
Reviewed changes
Copilot reviewed 18 out of 18 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| src/OpenClaw.Tests/SetupCommandTests.cs | Adds coverage for setup provider aperture writing a tailnet-identity profile and env example behavior. |
| src/OpenClaw.Tests/ModelProfileSelectionTests.cs | Adds tests for doctor behavior (no-key tailnet identity) and failure isolation for broken Aperture profiles. |
| src/OpenClaw.Tests/LlmClientFactoryTests.cs | Adds integration-style tests for Authorization stripping and metadata header propagation. |
| src/OpenClaw.Gateway/Models/ConfiguredModelProfileRegistry.cs | Extends profile status/config resolution to include Aperture labeling + auth/metadata fields and validation tweaks. |
| src/OpenClaw.Gateway/GatewayLlmExecutionService.cs | Injects opt-in request metadata into outgoing ChatOptions for compatible providers. |
| src/OpenClaw.Gateway/Extensions/LlmClientFactory.cs | Adds OpenAI-compatible client wrapper/policy to strip auth for tailnet-identity and to apply metadata headers. |
| src/OpenClaw.Core/Validation/ProviderSmokeProbe.cs | Allows smoke probe configuration for Aperture and tailnet-identity “no key” mode. |
| src/OpenClaw.Core/Validation/ModelDoctorEvaluator.cs | Updates doctor validation/capabilities to recognize Aperture and tailnet-identity credential rules. |
| src/OpenClaw.Core/Validation/ConfigValidator.cs | Adds aperture provider id and validates AuthMode values at root/profile level. |
| src/OpenClaw.Core/Models/ModelProfiles.cs | Adds AuthMode / SendRequestMetadata to profile config, model profile, and status DTOs. |
| src/OpenClaw.Core/Models/GatewayConfig.cs | Adds root Llm.AuthMode / Llm.SendRequestMetadata configuration. |
| src/OpenClaw.Cli/SetupCommand.cs | Implements openclaw setup provider aperture including tailnet-identity + metadata opt-in flags. |
| src/OpenClaw.Cli/Program.cs | Adds CLI help examples for the new setup flow. |
| README.md | Adds discoverability section + docs link for Tailscale/Aperture. |
| docs/USER_GUIDE.md | Documents Aperture provider usage and setup helper invocation. |
| docs/SITE_MAP.md | Adds nav entry for the new deployment doc. |
| docs/README.md | Adds doc index links for Tailscale/Aperture guidance. |
| docs/deployment/TAILSCALE.md | New deployment guide for Tailscale Serve/Funnel and Aperture routing patterns. |
Comments suppressed due to low confidence (1)
src/OpenClaw.Gateway/Extensions/LlmClientFactory.cs:192
- Tailnet-identity mode is supported for chat requests, but
CreateEmbeddingGeneratorroutesaperture/openai-compatibleembeddings throughCreateOpenAiEmbeddingClient, which always requires an API key and will throw at runtime (e.g., when SQLite vector memory is enabled). Either extend the tailnet-identity behavior to embeddings too (same policy + placeholder credential) or fail fast with a clearer validation/error when embeddings are requested underAuthMode=tailnet-identity.
public static IEmbeddingGenerator<string, Embedding<float>>? CreateEmbeddingGenerator(
LlmProviderConfig config, string? embeddingModel)
{
if (string.IsNullOrWhiteSpace(embeddingModel))
return null;
return config.Provider.ToLowerInvariant() switch
{
"openai" or "azure-openai" => CreateOpenAiEmbeddingClient(config, embeddingModel!),
"ollama" => new OllamaEmbeddingGenerator(new LlmProviderConfig
{
ApiKey = config.ApiKey,
Endpoint = OllamaEndpointNormalizer.NormalizeBaseUrl(config.Endpoint),
Model = config.Model
}, embeddingModel!),
"gemini" or "google" => CreateGeminiEmbeddingClient(config, embeddingModel!),
"openai-compatible" or "aperture" or "groq" or "together" or "lmstudio" =>
CreateOpenAiEmbeddingClient(new LlmProviderConfig
{
ApiKey = config.ApiKey,
Model = config.Model,
Endpoint = config.Endpoint
}, embeddingModel!),
"anthropic-vertex" or "amazon-bedrock" => null,
| return 2; | ||
| } | ||
|
|
||
| var filteredArgs = args.Where(arg => !string.Equals(arg, provider, StringComparison.Ordinal)).ToArray(); |
| var provider = args.FirstOrDefault(arg => !arg.StartsWith("--", StringComparison.Ordinal)); | ||
| if (!string.Equals(provider, "aperture", StringComparison.OrdinalIgnoreCase)) | ||
| { | ||
| error.WriteLine("Usage: openclaw setup provider aperture [--config <path>] [--endpoint <url>] [--model <route>] [--auth-mode <bearer|tailnet-identity>] [--env-var <name>] [--send-request-metadata <true|false>]"); |
| var apiKey = llm.ApiKey; | ||
| if (string.IsNullOrWhiteSpace(apiKey)) | ||
| { | ||
| if (!IsTailnetIdentityAuth(llm.AuthMode)) | ||
| throw new InvalidOperationException("MODEL_PROVIDER_KEY must be set for the OpenAI-compatible provider."); | ||
|
|
||
| apiKey = "openclaw-tailnet-identity"; | ||
| } |
| await app.StartAsync(); | ||
| var address = app.Urls.FirstOrDefault() | ||
| ?? app.Services.GetRequiredService<IServerAddressesFeature>().Addresses.First(); | ||
| return new OpenAiCompatibleTestServer(app, address.TrimEnd('/'), headers); |
There was a problem hiding this comment.
Actionable comments posted: 6
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/OpenClaw.Gateway/Extensions/LlmClientFactory.cs (1)
185-191:⚠️ Potential issue | 🟠 Major | ⚡ Quick winTailnet-identity config is inconsistent for embeddings (no-key mode breaks at runtime).
Chat supports
AuthMode=tailnet-identitywithout API key, but the embedding path still requiresApiKeyand doesn’t carryAuthMode. This creates a runtime-only failure for otherwise valid aperture profile configs.Suggested fail-fast diff (until keyless embeddings are implemented)
@@ "openai-compatible" or "aperture" or "groq" or "together" or "lmstudio" => - CreateOpenAiEmbeddingClient(new LlmProviderConfig + CreateOpenAiEmbeddingClient(new LlmProviderConfig { ApiKey = config.ApiKey, + AuthMode = config.AuthMode, Model = config.Model, Endpoint = config.Endpoint }, embeddingModel!), @@ private static IEmbeddingGenerator<string, Embedding<float>> CreateOpenAiEmbeddingClient( LlmProviderConfig config, string embeddingModel) { + if (IsTailnetIdentityAuth(config.AuthMode)) + throw new InvalidOperationException("Embeddings do not support AuthMode=tailnet-identity yet. Configure an API key or disable embeddings for this profile."); + var transport = CreateTransportOptions(config.Endpoint); var client = new OpenAI.OpenAIClient( new ApiKeyCredential(config.ApiKey ?? throw new InvalidOperationException("API key required for embeddings.")), CreateOpenAiClientOptions(transport));As per coding guidelines, "Preserve existing configuration behavior unless intentionally changing it."
Also applies to: 231-237
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/OpenClaw.Gateway/Extensions/LlmClientFactory.cs` around lines 185 - 191, The embedding client creation path (CreateOpenAiEmbeddingClient with LlmProviderConfig and embeddingModel) does not propagate AuthMode and still assumes ApiKey, causing runtime failures for `AuthMode=tailnet-identity` no-key configs; update the embedding branch to carry through the provider AuthMode from the incoming config (add AuthMode to the LlmProviderConfig passed into CreateOpenAiEmbeddingClient) and add a fail-fast check: if AuthMode is not key-based (e.g., "tailnet-identity") and no ApiKey is present, throw or return a clear configuration error until keyless embeddings are implemented (apply the same fix to the other embedding branch around the 231-237 area).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/SITE_MAP.md`:
- Line 32: The SITE_MAP.md Primary Navigation row for "Integrations | Tailscale
And Aperture" was added but the Sidebar Grouping list was not updated; open the
Sidebar Grouping section and add the entry "Tailscale And Aperture" under the
"Integrations" group (matching the label and link format used elsewhere, e.g.,
the existing Integrations items) so the Sidebar Grouping and Primary Navigation
remain consistent.
In `@src/OpenClaw.Cli/SetupCommand.cs`:
- Around line 639-641: The code is creating a directory from
config.Tooling.WorkspaceRoot without resolving config refs (e.g.,
env:OPENCLAW_WORKSPACE); instead resolve that value first and only call
Directory.CreateDirectory on the resolved path. Locate the creation logic around
Directory.CreateDirectory and replace the direct use of
config.Tooling.WorkspaceRoot with the resolved string (using the existing config
resolution utility or method you have in the project), check for null/empty
after resolution, and then call Directory.CreateDirectory on the resolved path
to avoid creating literal "env:..." folders or invalid paths.
- Around line 643-653: The code saves the merged Gateway config immediately
using GatewayConfigFile.SaveAsync without validating it first; call
ConfigValidator.Validate(config) (or the appropriate async/validation helper
used in the project) and handle/propagate any validation errors before calling
GatewayConfigFile.SaveAsync so malformed provider or tooling settings are not
persisted; locate the save call in SetupCommand.cs (the block using
GatewayConfigFile.SaveAsync and subsequent File.WriteAllTextAsync for
envExamplePath) and insert the validation step, aborting the save/write if
validation fails and surfacing the validation errors to the caller/user.
In `@src/OpenClaw.Core/Validation/ConfigValidator.cs`:
- Around line 70-72: ConfigValidator currently skips provider-specific checks
when Models.Profiles is empty; you must validate the implicit default profile
derived from OpenClaw:Llm so bad configs like Llm.Provider="aperture" fail fast.
Update ConfigValidator.Validate (or the surrounding logic where
IsValidProviderAuthMode and ValidatePromptCaching are called) to detect when
Models.Profiles is empty and materialize/validate the implicit profile using the
same validation paths (e.g., run the provider auth checks used by
IsValidProviderAuthMode, provider-specific credential/endpoint checks, and call
ValidatePromptCaching with the implicit profile's Provider and PromptCaching
values). Reuse existing symbols (IsValidProviderAuthMode, ValidatePromptCaching,
Models.Profiles, config.Llm.Provider, config.Llm.PromptCaching) rather than
duplicating logic so the implicit profile fails with the same errors as an
explicit profile.
In `@src/OpenClaw.Core/Validation/ProviderSmokeProbe.cs`:
- Around line 151-152: The OpenAI-style request builder is unconditionally
adding an Authorization header from config.ApiKey, causing tailnet-identity
probes to use the wrong auth; modify BuildOpenAiStyleRequest to accept a
suppressAuthorization (bool) parameter and, when true, skip adding the
"Authorization: Bearer ..." header even if config.ApiKey is present; update the
call sites in ProviderSmokeProbe where you build requests for
"openai"/"openai-compatible"/"aperture"/etc. (the switch branch that calls
BuildOpenAiStyleRequest and the similar block around lines 268-280) to pass
suppressAuthorization=true when HasRequiredCredentials/your probe-intent
indicates the probe should use tailnet-identity (or when provider ==
"tailnet-identity" / config indicates tailnet identity), leaving behavior
unchanged otherwise.
In `@src/OpenClaw.Gateway/Extensions/LlmClientFactory.cs`:
- Around line 375-379: OpenClawProviderRequestPolicy.Apply currently copies
arbitrary metadata headers into message.Request.Headers via the loop over
headers and message.Request.Headers.Set; modify that loop to skip injection of
sensitive header names (e.g., "Authorization", "Cookie", "Proxy-Authorization",
"WWW-Authenticate" — perform a case-insensitive comparison) so these are never
re-added, ensure you trim names/values and only set when not in the blocked
list, and optionally centralize the blocked names into a small readonly HashSet
used by the Apply method to make the rule obvious and maintainable.
---
Outside diff comments:
In `@src/OpenClaw.Gateway/Extensions/LlmClientFactory.cs`:
- Around line 185-191: The embedding client creation path
(CreateOpenAiEmbeddingClient with LlmProviderConfig and embeddingModel) does not
propagate AuthMode and still assumes ApiKey, causing runtime failures for
`AuthMode=tailnet-identity` no-key configs; update the embedding branch to carry
through the provider AuthMode from the incoming config (add AuthMode to the
LlmProviderConfig passed into CreateOpenAiEmbeddingClient) and add a fail-fast
check: if AuthMode is not key-based (e.g., "tailnet-identity") and no ApiKey is
present, throw or return a clear configuration error until keyless embeddings
are implemented (apply the same fix to the other embedding branch around the
231-237 area).
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: bdd37f63-1042-471f-a62a-050c69053da9
📒 Files selected for processing (18)
README.mddocs/README.mddocs/SITE_MAP.mddocs/USER_GUIDE.mddocs/deployment/TAILSCALE.mdsrc/OpenClaw.Cli/Program.cssrc/OpenClaw.Cli/SetupCommand.cssrc/OpenClaw.Core/Models/GatewayConfig.cssrc/OpenClaw.Core/Models/ModelProfiles.cssrc/OpenClaw.Core/Validation/ConfigValidator.cssrc/OpenClaw.Core/Validation/ModelDoctorEvaluator.cssrc/OpenClaw.Core/Validation/ProviderSmokeProbe.cssrc/OpenClaw.Gateway/Extensions/LlmClientFactory.cssrc/OpenClaw.Gateway/GatewayLlmExecutionService.cssrc/OpenClaw.Gateway/Models/ConfiguredModelProfileRegistry.cssrc/OpenClaw.Tests/LlmClientFactoryTests.cssrc/OpenClaw.Tests/ModelProfileSelectionTests.cssrc/OpenClaw.Tests/SetupCommandTests.cs
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/OpenClaw.Cli/SetupCommand.cs`:
- Line 519: The current filtering (var filteredArgs = args.Where(arg =>
!string.Equals(arg, provider, StringComparison.OrdinalIgnoreCase)).ToArray();)
removes every argument matching provider (e.g., "aperture") including legitimate
option values; change it to remove only the single positional provider token
instead of all matching values by locating the first index of the provider token
in args (or the first token that is not an option/starts-with '-' if you need to
be stricter) and creating filteredArgs by skipping/removing only that single
element; update the expression where filteredArgs is defined (reference symbols:
filteredArgs, args, provider) to use an index-based removal (e.g., find index
via Array.IndexOf or manual loop, then build a new array without that one
element) so other option values are preserved.
In `@src/OpenClaw.Core/Validation/ConfigValidator.cs`:
- Around line 70-71: Update IsValidProviderAuthMode validation to be
provider-aware: when config.Llm.AuthMode equals "tailnet-identity" ensure
config.Llm.Provider is one of the providers that support tailnet identity (use
the same provider-checking logic used elsewhere or a centralized helper like
SupportsTailnetIdentity(providerName)); if not, add a validation error stating
that tailnet-identity is unsupported for that provider. Apply the same
provider-scoped check to the other occurrences referenced (around the logic at
the blocks corresponding to lines 632-633 and 893-900) so
AuthMode="tailnet-identity" fails-fast for unsupported providers.
In `@src/OpenClaw.Core/Validation/ProviderSmokeProbe.cs`:
- Line 152: The current call in ProviderSmokeProbe to BuildOpenAiStyleRequest
passes suppressAuthorization based solely on
IsTailnetIdentityAuth(config.AuthMode), which suppresses Authorization for all
OpenAI-style providers; change it so suppression is applied only when the
provider actually supports tailnet-identity auth. In ProviderSmokeProbe (the
call site for BuildOpenAiStyleRequest), add a provider-capability check (e.g., a
new predicate like ProviderSupportsTailnetIdentity(provider) or an existing
provider.Type/Name check) and pass suppressAuthorization:
IsTailnetIdentityAuth(config.AuthMode) &&
ProviderSupportsTailnetIdentity(provider) (or equivalent), ensuring
BuildOpenAiStyleRequest is unchanged and only the argument value is constrained
to supported providers.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: ad3c46e3-dc94-4928-8d07-d80eb34cb542
📒 Files selected for processing (8)
docs/SITE_MAP.mdsrc/OpenClaw.Cli/SetupCommand.cssrc/OpenClaw.Core/Validation/ConfigValidator.cssrc/OpenClaw.Core/Validation/ProviderSmokeProbe.cssrc/OpenClaw.Gateway/Extensions/LlmClientFactory.cssrc/OpenClaw.Tests/ConfigValidatorTests.cssrc/OpenClaw.Tests/LlmClientFactoryTests.cssrc/OpenClaw.Tests/SetupCommandTests.cs
There was a problem hiding this comment.
🧹 Nitpick comments (1)
src/OpenClaw.Tests/SetupCommandTests.cs (1)
632-683: 💤 Low valueConsider using
Path.Joinfor consistency with recent fixes.The test correctly validates Aperture setup with tailnet-identity auth mode. However, lines 638 and 675 use
Path.Combine, while earlier in this file (lines 30, 72) the code was updated to usePath.Jointo avoid the "silent argument drop" behavior. For consistency and to prevent the same CodeQL warning, consider usingPath.Joinin this test as well.Suggested consistency fix
- var configPath = Path.Combine(root, "config", "openclaw.settings.json"); + var configPath = Path.Join(root, "config", "openclaw.settings.json");And at line 675:
- var envExample = await File.ReadAllTextAsync(Path.Combine(root, "config", "openclaw.settings.env.example")); + var envExample = await File.ReadAllTextAsync(Path.Join(root, "config", "openclaw.settings.env.example"));🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/OpenClaw.Tests/SetupCommandTests.cs` around lines 632 - 683, The test RunAsync_SetupProviderAperture_WritesTailnetIdentityProfile uses Path.Combine in two places (when creating configPath and when reading the env example file) which should be replaced with Path.Join to match the file's other fixes and avoid silent-argument-drop warnings; update the configPath assignment and the File.ReadAllTextAsync call that currently use Path.Combine(root, "config", "openclaw.settings.json") and Path.Combine(root, "config", "openclaw.settings.env.example") to use Path.Join(root, "config", "openclaw.settings.json") and Path.Join(root, "config", "openclaw.settings.env.example") respectively.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@src/OpenClaw.Tests/SetupCommandTests.cs`:
- Around line 632-683: The test
RunAsync_SetupProviderAperture_WritesTailnetIdentityProfile uses Path.Combine in
two places (when creating configPath and when reading the env example file)
which should be replaced with Path.Join to match the file's other fixes and
avoid silent-argument-drop warnings; update the configPath assignment and the
File.ReadAllTextAsync call that currently use Path.Combine(root, "config",
"openclaw.settings.json") and Path.Combine(root, "config",
"openclaw.settings.env.example") to use Path.Join(root, "config",
"openclaw.settings.json") and Path.Join(root, "config",
"openclaw.settings.env.example") respectively.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 2948af21-99c0-4f88-bb41-efe743676918
📒 Files selected for processing (7)
src/OpenClaw.Cli/SetupCommand.cssrc/OpenClaw.Core/Validation/ConfigValidator.cssrc/OpenClaw.Core/Validation/ProviderSmokeProbe.cssrc/OpenClaw.Gateway/Extensions/LlmClientFactory.cssrc/OpenClaw.Tests/ConfigValidatorTests.cssrc/OpenClaw.Tests/LlmClientFactoryTests.cssrc/OpenClaw.Tests/SetupCommandTests.cs
There was a problem hiding this comment.
🧹 Nitpick comments (1)
src/OpenClaw.Tests/SetupCommandTests.cs (1)
638-638: ⚡ Quick winUse
Path.Joinfor consistency with the pattern being applied in this PR.Lines 30, 72, 402, and 675 in this file were changed from
Path.CombinetoPath.Jointo address static analysis warnings. Line 638 follows the same pattern (constructingconfigPathfor file I/O) but still usesPath.Combine.♻️ Proposed fix
- var configPath = Path.Combine(root, "config", "openclaw.settings.json"); + var configPath = Path.Join(root, "config", "openclaw.settings.json");🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/OpenClaw.Tests/SetupCommandTests.cs` at line 638, Replace the use of Path.Combine with Path.Join for constructing configPath in SetupCommandTests: change the assignment to use Path.Join(root, "config", "openclaw.settings.json") where the variable configPath is declared in the SetupCommandTests class/method so it matches the other replacements (lines using Path.Join at 30, 72, 402, 675).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@src/OpenClaw.Tests/SetupCommandTests.cs`:
- Line 638: Replace the use of Path.Combine with Path.Join for constructing
configPath in SetupCommandTests: change the assignment to use Path.Join(root,
"config", "openclaw.settings.json") where the variable configPath is declared in
the SetupCommandTests class/method so it matches the other replacements (lines
using Path.Join at 30, 72, 402, 675).
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 1a966c74-ff98-4cb9-81ad-19210b4ec459
📒 Files selected for processing (1)
src/OpenClaw.Tests/SetupCommandTests.cs
dee1a3d to
288e370
Compare
Summary
Adds first-class documentation for Tailscale deployment patterns and optional Aperture-by-Tailscale provider routing without changing the default OpenClaw.NET provider behavior or quickstart.
Changes
docs/deployment/TAILSCALE.mdwith Serve/Funnel guidance, Aperture positioning, security notes, identity-header caveats, SSH future direction, and troubleshooting.Provider = "aperture"as an OpenAI-compatible upstream route with Aperture-friendly labels/status.AuthModeandSendRequestMetadataconfiguration, including no-keytailnet-identitymode.openclaw setup provider aperturehelper.Validation
dotnet test src/OpenClaw.Tests/OpenClaw.Tests.csproj --configuration Release --filter "FullyQualifiedName~LlmClientFactoryTests|FullyQualifiedName~ModelProfileSelectionTests|FullyQualifiedName~SetupCommandTests|FullyQualifiedName~DocsConsistencyTests|FullyQualifiedName~ConfigValidatorTests"dotnet test OpenClaw.Net.slnx --configuration Releasedotnet build OpenClaw.Net.slnx --configuration Release --no-restoreNotes
Metadata propagation is disabled by default and only applies to explicitly enabled profiles. Invalid Aperture profiles remain isolated from unrelated valid providers.
Summary by CodeRabbit
New Features
Documentation
Tests