Skip to content

Control-plane parity plus enhancements#10

Open
Telli wants to merge 1 commit intomainfrom
codex/control-plane-parity-plus-enhancements
Open

Control-plane parity plus enhancements#10
Telli wants to merge 1 commit intomainfrom
codex/control-plane-parity-plus-enhancements

Conversation

@Telli
Copy link
Copy Markdown
Contributor

@Telli Telli commented May 6, 2026

What changed

  • added durable control-plane parity features for permissions, approvals, trust, model selection, workspace init, and REPL aliases
  • added research-mode command flow and multimodal prompt-reference groundwork
  • added user-scoped provider credential storage plus auth command surface
  • added durable scheduled prompt storage, services, and hosted runner support
  • added guided self-evolution proposal storage, services, and command surface

Why it changed

This brings SharpClaw closer to the AdaL-inspired operator surface without rewriting the existing runtime. The goal is to make session behavior, model selection, approvals, auth, scheduling, and evolution workflows first-class and durable.

User and developer impact

  • operators can now persist session-level permission, approval, trust, and model preferences
  • workspaces can be initialized with native SharpClaw config and local commands/skills folders
  • provider auth can be managed without writing plaintext secrets into workspace state
  • scheduled prompts and guided evolution now have real runtime and storage seams instead of ad hoc stubs

Validation

  • checks not run in this pass
  • build not run in this pass
  • tests not run in this pass

@Telli Telli marked this pull request as ready for review May 6, 2026 20:32
Copilot AI review requested due to automatic review settings May 6, 2026 20:32
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR expands SharpClaw’s “control-plane” surface area by making session/workspace preferences, provider auth, scheduling, research mode, and guided evolution durable and host-aware, while also laying groundwork for multimodal (image) prompt references.

Changes:

  • Adds durable scheduled prompts + runner/service layer, backed by SQLite or workspace-local JSON.
  • Adds durable session preferences (trust, approvals, permission mode, model selection) and guided evolution proposal storage + apply/reject flows.
  • Introduces research mode and multimodal prompt reference support (directory/image references + structured content blocks), plus user-scoped provider credential storage.

Reviewed changes

Copilot reviewed 79 out of 79 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
src/SharpClaw.Code.Sessions/Storage/SqliteSessionStoreDatabase.cs Adds SQLite tables/indexes for schedules/evolution.
src/SharpClaw.Code.Sessions/Storage/SqliteScheduledPromptStore.cs SQLite scheduled prompt persistence.
src/SharpClaw.Code.Sessions/Storage/SqliteEvolutionProposalStore.cs SQLite evolution proposal persistence.
src/SharpClaw.Code.Sessions/Storage/HostAwareScheduledPromptStore.cs Host-aware store selection (file vs SQLite).
src/SharpClaw.Code.Sessions/Storage/HostAwareEvolutionProposalStore.cs Host-aware evolution store selection.
src/SharpClaw.Code.Sessions/Storage/FileScheduledPromptStore.cs File-backed scheduled prompt persistence.
src/SharpClaw.Code.Sessions/Storage/FileEvolutionProposalStore.cs File-backed evolution proposal persistence.
src/SharpClaw.Code.Sessions/Abstractions/IScheduledPromptStore.cs Scheduled prompt store abstraction.
src/SharpClaw.Code.Sessions/Abstractions/IEvolutionProposalStore.cs Evolution proposal store abstraction.
src/SharpClaw.Code.Runtime/Workflow/WorkspaceBootstrapService.cs Workspace init scaffolding for .sharpclaw.
src/SharpClaw.Code.Runtime/Workflow/SessionPreferenceService.cs Durable session preference management.
src/SharpClaw.Code.Runtime/Workflow/ScheduledPromptService.cs Schedule lifecycle + execution orchestration.
src/SharpClaw.Code.Runtime/Workflow/ScheduledPromptRunner.cs Hosted service polling due schedules.
src/SharpClaw.Code.Runtime/Workflow/ScheduleCronExpression.cs Minimal cron parsing/next-run calculation.
src/SharpClaw.Code.Runtime/Workflow/ResearchWorkflowService.cs Research-mode prompt execution flow.
src/SharpClaw.Code.Runtime/Workflow/EvolutionProposalService.cs Proposal analysis/apply/reject workflows.
src/SharpClaw.Code.Runtime/Turns/DefaultTurnRunner.cs Plumbs structured user content into turns.
src/SharpClaw.Code.Runtime/Prompts/PromptReferenceResolver.cs Adds directory/image refs + structured content.
src/SharpClaw.Code.Runtime/Context/PromptExecutionContext.cs Adds UserContent for structured blocks.
src/SharpClaw.Code.Runtime/Context/PromptContextAssembler.cs Builds durable metadata + research prompt + user blocks.
src/SharpClaw.Code.Runtime/Configuration/SharpClawConfigService.cs Moves workspace config to .sharpclaw/config.jsonc (with legacy fallback).
src/SharpClaw.Code.Runtime/Composition/RuntimeServiceCollectionExtensions.cs Registers new workflow/services + hosted runner.
src/SharpClaw.Code.Runtime/Abstractions/IWorkspaceBootstrapService.cs Abstraction for workspace initialization.
src/SharpClaw.Code.Runtime/Abstractions/ISessionPreferenceService.cs Abstraction for durable session preferences.
src/SharpClaw.Code.Runtime/Abstractions/IScheduledPromptService.cs Abstraction for schedule management/execution.
src/SharpClaw.Code.Runtime/Abstractions/IResearchWorkflowService.cs Abstraction for research-mode prompts.
src/SharpClaw.Code.Runtime/Abstractions/IEvolutionProposalService.cs Abstraction for evolution proposal workflows.
src/SharpClaw.Code.Providers/Services/ProviderCredentialStore.cs User-scoped provider credential storage.
src/SharpClaw.Code.Providers/Services/ProviderCatalogService.cs Exposes image-input capability in catalog.
src/SharpClaw.Code.Providers/ProvidersServiceCollectionExtensions.cs Registers provider credential store.
src/SharpClaw.Code.Providers/OpenAiCompatibleProvider.cs Resolves credentials + image-input capability.
src/SharpClaw.Code.Providers/Models/ProviderCredentialModels.cs Models for stored/resolved provider creds.
src/SharpClaw.Code.Providers/Internal/ProviderAuthStatusFactory.cs Enriches auth status with source/details.
src/SharpClaw.Code.Providers/Internal/OpenAiMessageBuilder.cs Maps image content blocks to MEAI content.
src/SharpClaw.Code.Providers/Internal/AnthropicMessageBuilder.cs Maps image blocks to Anthropic SDK types.
src/SharpClaw.Code.Providers/Configuration/OpenAiCompatibleProviderOptions.cs Adds SupportsImageInput option.
src/SharpClaw.Code.Providers/Configuration/AnthropicProviderOptions.cs Adds SupportsImageInput option.
src/SharpClaw.Code.Providers/AnthropicProvider.cs Resolves credentials + image-input capability.
src/SharpClaw.Code.Providers/Abstractions/IProviderCredentialStore.cs Credential store abstraction.
src/SharpClaw.Code.Providers/Abstractions/IModelProvider.cs Adds SupportsImageInput requirement.
src/SharpClaw.Code.Protocol/Serialization/ProtocolJsonContext.cs Adds source-gen types for new protocol models.
src/SharpClaw.Code.Protocol/Models/SharpClawWorkflowMetadataKeys.cs Adds metadata keys for preferences/trust/model.
src/SharpClaw.Code.Protocol/Models/ProviderRequest.cs Adds ContainsImageInput marker.
src/SharpClaw.Code.Protocol/Models/PromptReferences.cs Adds directory/image reference kinds + metadata.
src/SharpClaw.Code.Protocol/Models/OpenCodeParityModels.cs Adds provider catalog SupportsImageInput.
src/SharpClaw.Code.Protocol/Models/ContentBlock.cs Adds Image block kind + media/data/uri.
src/SharpClaw.Code.Protocol/Models/AuthStatus.cs Adds auth source/detail/local-runtime flags.
src/SharpClaw.Code.Protocol/Models/AdaLGapModels.cs Adds trust/schedule/evolution/research models.
src/SharpClaw.Code.Protocol/Enums/PrimaryMode.cs Adds Research mode.
src/SharpClaw.Code.Protocol/Commands/RunPromptRequest.cs Adds structured UserContent support.
src/SharpClaw.Code.Permissions/Rules/PrimaryModeMutationRule.cs Treats research as read-only for mutations.
src/SharpClaw.Code.Infrastructure/Services/RuntimeStoragePathResolver.cs Adds scheduled/evolution JSON + lock paths.
src/SharpClaw.Code.Infrastructure/Services/PlatformSecretProtector.cs Adds DPAPI-backed secret protection (Windows).
src/SharpClaw.Code.Infrastructure/InfrastructureServiceCollectionExtensions.cs Registers secret protector.
src/SharpClaw.Code.Infrastructure/Abstractions/ISecretProtector.cs Secret protection abstraction.
src/SharpClaw.Code.Infrastructure/Abstractions/IRuntimeStoragePathResolver.cs Adds scheduled/evolution path APIs.
src/SharpClaw.Code.Commands/Repl/ReplInteractionState.cs Adds permission override + clear helper.
src/SharpClaw.Code.Commands/Repl/ReplHost.cs Threads permission override into runtime context.
src/SharpClaw.Code.Commands/Options/GlobalCliOptions.cs Adds research mode to CLI option parsing.
src/SharpClaw.Code.Commands/Models/CommandExecutionContext.cs Adds permission override parameter plumbing.
src/SharpClaw.Code.Commands/Handlers/ScheduleCommandHandler.cs Adds schedule command + slash surface.
src/SharpClaw.Code.Commands/Handlers/ResumeSlashCommandHandler.cs Adds /resume alias + clears overrides.
src/SharpClaw.Code.Commands/Handlers/ResearchCommandHandler.cs Adds research command + slash surface.
src/SharpClaw.Code.Commands/Handlers/PermissionsCommandHandler.cs Adds durable permissions/trust/approvals CLI.
src/SharpClaw.Code.Commands/Handlers/NewSessionSlashCommandHandler.cs Adds /new session creation helper.
src/SharpClaw.Code.Commands/Handlers/ModeSlashCommandHandler.cs Adds research mode to REPL mode switch.
src/SharpClaw.Code.Commands/Handlers/ModelSlashCommandHandler.cs Adds /model alias for models commands.
src/SharpClaw.Code.Commands/Handlers/ModelsCommandHandler.cs Adds show/use/clear model preference commands.
src/SharpClaw.Code.Commands/Handlers/InitCommandHandler.cs Adds workspace init command + slash surface.
src/SharpClaw.Code.Commands/Handlers/EvolutionCommandHandler.cs Adds evolution analyze/apply/reject commands.
src/SharpClaw.Code.Commands/Handlers/ClearSlashCommandHandler.cs Adds /clear to reset overrides + screen.
src/SharpClaw.Code.Commands/Handlers/AuthCommandHandler.cs Adds auth status + credential management commands.
src/SharpClaw.Code.Commands/Handlers/ApprovalsSlashCommandHandler.cs Redirects approvals alias to durable permissions surface.
src/SharpClaw.Code.Commands/Abstractions/IReplTerminal.cs Adds ClearScreen() API.
src/SharpClaw.Code.Cli/Terminal/SpectreReplTerminal.cs Implements screen clearing via Spectre.
src/SharpClaw.Code.Cli/Composition/CliServiceCollectionExtensions.cs Registers new commands/slash handlers.
src/SharpClaw.Code.Agents/Services/AgentFrameworkBridge.cs Plumbs trust + permission preference into tools.
src/SharpClaw.Code.Agents/Models/AgentRunContext.cs Adds structured UserContent to run context.
src/SharpClaw.Code.Agents/Internal/ProviderBackedAgentKernel.cs Enforces image support + sends structured content.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +1 to +16
namespace SharpClaw.Code.Providers.Abstractions;

/// <summary>
/// Resolves and persists user-scoped provider credentials without writing plaintext workspace state.
/// </summary>
public interface IProviderCredentialStore
{
/// <summary>
/// Resolves the effective API key for a provider, if available.
/// </summary>
Task<ResolvedProviderCredential> ResolveAsync(string providerName, CancellationToken cancellationToken);

/// <summary>
/// Lists stored credential descriptors without exposing secret material.
/// </summary>
Task<IReadOnlyList<ProviderCredentialDescriptor>> ListAsync(CancellationToken cancellationToken);
Comment on lines 9 to +20
public interface IModelProvider
{
/// <summary>
/// Gets the provider name used for resolution.
/// </summary>
string ProviderName { get; }

/// <summary>
/// Gets whether the provider accepts structured image input.
/// </summary>
bool SupportsImageInput { get; }

Comment on lines +110 to +121
private async Task<StoredCredentialDocument> LoadAsync(CancellationToken cancellationToken)
{
var path = GetPath();
var text = await fileSystem.ReadAllTextIfExistsAsync(path, cancellationToken).ConfigureAwait(false);
if (string.IsNullOrWhiteSpace(text))
{
return new StoredCredentialDocument(new Dictionary<string, StoredCredentialEntry>(StringComparer.OrdinalIgnoreCase));
}

return JsonSerializer.Deserialize<StoredCredentialDocument>(text, JsonOptions)
?? new StoredCredentialDocument(new Dictionary<string, StoredCredentialEntry>(StringComparer.OrdinalIgnoreCase));
}
Comment on lines +290 to +303
var files = Directory.EnumerateFiles(directoryPath, "*", SearchOption.AllDirectories)
.Where(static path => !ShouldSkipPath(path))
.OrderBy(static path => path, StringComparer.OrdinalIgnoreCase)
.ToArray();

var included = new List<(string RelativePath, string Content)>();
var totalBytes = 0;
foreach (var file in files)
{
cancellationToken.ThrowIfCancellationRequested();
if (included.Count >= MaxDirectoryReferenceFiles)
{
break;
}
Comment on lines +231 to +260
if (ImageExtensions.Contains(Path.GetExtension(resolvedFull)))
{
var bytes = await File.ReadAllBytesAsync(resolvedFull, cancellationToken).ConfigureAwait(false);
var mediaType = ResolveMediaType(resolvedFull);
var placeholder =
$"[Referenced image: {display} ({mediaType})]" + Environment.NewLine
+ $"[End referenced image: {display}]";
return (
placeholder,
new PromptReference(
PromptReferenceKind.Image,
rawToken,
pathPart,
resolvedFull,
display,
outsideWorkspace,
placeholder,
MediaType: mediaType,
IncludedEntryCount: 1),
new ContentBlock(
ContentBlockKind.Image,
Text: display,
ToolUseId: null,
ToolName: null,
ToolInputJson: null,
IsError: null,
MediaType: mediaType,
Data: Convert.ToBase64String(bytes),
Uri: resolvedFull));
}
Comment on lines 60 to 109
@@ -84,29 +94,18 @@ private async IAsyncEnumerable<ProviderEvent> StreamEventsAsync(
}
}

private OpenAIClient GetOrCreateOpenAiClient(LocalRuntimeProfileOptions? profile)
private OpenAIClient CreateOpenAiClient(LocalRuntimeProfileOptions? profile, string? resolvedApiKey)
{
if (profile is null && _cachedOpenAiClient is not null)
{
return _cachedOpenAiClient;
}

var openAiOptions = new OpenAIClientOptions();
var normalized = Internal.ProviderHttpHelpers.NormalizeBaseUrl(profile?.BaseUrl ?? _options.BaseUrl);
if (normalized is not null)
{
openAiOptions.Endpoint = new Uri(normalized);
}

var apiKey = profile?.ApiKey ?? _options.ApiKey ?? "local-runtime";
var apiKey = profile?.ApiKey ?? resolvedApiKey ?? _options.ApiKey ?? "local-runtime";
var credential = new ApiKeyCredential(apiKey);
var client = new OpenAIClient(credential, openAiOptions);
if (profile is null)
{
_cachedOpenAiClient = client;
}

return client;
return new OpenAIClient(credential, openAiOptions);
}
Comment on lines 112 to 115
refs.Reverse();
return new PromptReferenceResolution(original, expanded.ToString(), refs);
structuredContent.Reverse();
return new PromptReferenceResolution(original, expanded.ToString(), refs, structuredContent);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants