Skip to content

Develop#279

Merged
Alex793x merged 89 commits intomainfrom
develop
Jan 20, 2026
Merged

Develop#279
Alex793x merged 89 commits intomainfrom
develop

Conversation

@Alex793x
Copy link
Copy Markdown
Contributor

No description provided.

Alex Holmberg and others added 30 commits January 16, 2026 23:42
Add new platform module for managing CLI session state:
- PlatformSession struct with project/org context
- Persistent storage to ~/.syncable/platform-session.json
- Load/save/clear operations with proper error handling
- Display context helper for showing selected project

This is a new parallel system for platform state, separate from
conversation persistence.

Co-Authored-By: Claude <noreply@anthropic.com>
Integrate PlatformSession into the agent:
- Add platform_session field to ChatSession struct
- Load platform session from disk in ChatSession::new()
- Add update_platform_session() method for saving changes
- Display platform context on agent startup when project selected

This is informational only - loads and displays the platform context
but does not change any agent behavior yet.

Co-Authored-By: Claude <noreply@anthropic.com>
Add new platform API client module with:
- PlatformApiError enum with comprehensive error types (HttpError, ApiError,
  ParseError, Unauthorized, NotFound, PermissionDenied, RateLimited, ServerError)
- Response types: Organization, Project, ProjectMember, UserProfile
- PlatformApiClient with HTTP client configured for 30s timeout and custom user-agent
- Integration with existing credentials module for auth token retrieval
- API methods: get_current_user, list_organizations, get_organization,
  list_projects, get_project, create_project
- Proper HTTP status code handling (401, 403, 404, 429, 5xx)
- Unit tests for client construction, URL building, and error types

Co-Authored-By: Claude <noreply@anthropic.com>
Add new platform tools module for Syncable Platform API integration:
- ListOrganizationsTool: List organizations user belongs to
- ListProjectsTool: List projects within an organization
- SelectProjectTool: Select a project as current context (persists to session)
- CurrentContextTool: Get the currently selected project context

Tools use PlatformApiClient for API calls and PlatformSession for
persistence. Error handling follows existing tool patterns with
format_error_for_llm for LLM-friendly error responses.

Co-Authored-By: Claude <noreply@anthropic.com>
Add platform tools to all agent builder chains (OpenAI, Anthropic,
Bedrock) in both run_interactive and run_query functions.

Registered tools:
- ListOrganizationsTool
- ListProjectsTool
- SelectProjectTool
- CurrentContextTool

These tools are available in all modes (analysis, planning, generation)
to allow users to manage their Syncable Platform project context.

Co-Authored-By: Claude <noreply@anthropic.com>
Add CloudProvider enum and CloudCredentialStatus types for checking
cloud provider connection status. The API only returns connection
metadata (id, provider name) and NEVER exposes actual credentials
like OAuth tokens or API keys.

Co-Authored-By: Claude <noreply@anthropic.com>
Add two new agent tools for cloud provider connection management:

- OpenProviderSettingsTool: Opens the cloud providers settings page
  in the user's browser where they can connect GCP/AWS/Azure/Hetzner

- CheckProviderConnectionTool: Checks if a provider is connected to
  a project (returns status only, NEVER credentials)

SECURITY: The agent never handles actual credentials. All OAuth/API
key management happens securely in the browser through the platform.

Co-Authored-By: Claude <noreply@anthropic.com>
Register OpenProviderSettingsTool and CheckProviderConnectionTool
in all agent builder chains (OpenAI, Anthropic, Bedrock providers
for both interactive and single-query modes).

Co-Authored-By: Claude <noreply@anthropic.com>
Add deployment-related types (DeploymentConfig, TriggerDeploymentRequest,
TriggerDeploymentResponse, DeploymentTaskStatus, DeployedService,
PaginatedDeployments) and corresponding PlatformApiClient methods for:
- list_deployment_configs
- trigger_deployment
- get_deployment_status
- list_deployments

Co-Authored-By: Claude <noreply@anthropic.com>
Add four new agent tools for service deployment management:
- ListDeploymentConfigsTool: List deployment configs for a project
- TriggerDeploymentTool: Trigger deployment using a config
- GetDeploymentStatusTool: Get deployment task status/progress
- ListDeploymentsTool: List recent deployments with URLs

Each tool follows the established platform tool patterns with
proper error handling and user-friendly JSON responses.

Co-Authored-By: Claude <noreply@anthropic.com>
Register four deployment tools with the agent builder for all providers:
- ListDeploymentConfigsTool
- TriggerDeploymentTool
- GetDeploymentStatusTool
- ListDeploymentsTool

Update tools module exports and documentation to include the new
deployment tools.

Co-Authored-By: Claude <noreply@anthropic.com>
Add LogEntry, LogQueryStats, and GetLogsResponse types for container logs.
Add get_service_logs method to PlatformApiClient for fetching service logs
with support for time filters (start/end) and line limits.

Co-Authored-By: Claude <noreply@anthropic.com>
Add GetServiceLogsTool for fetching container logs from deployed services.
Features:
- Retrieves logs with timestamps and container metadata
- Supports time filtering (start/end ISO timestamps)
- Supports line limits for efficient retrieval
- Returns user-friendly JSON output for the agent

Register tool in all agent builder chains.

Co-Authored-By: Claude <noreply@anthropic.com>
- Add ProjectCommand enum with list, select, current, info subcommands
- Add OrgCommand enum with list, select subcommands
- Add Project and Org variants to Commands enum
Backend API returns responses wrapped in GenericResponse<T> format
({"data": ...}) but CLI was deserializing directly to T, causing
parse errors.

Co-Authored-By: Claude <noreply@anthropic.com>
Add handlers for new CLI commands:
- project list: List projects in current organization
- project select: Select a project by ID
- project current: Show current org/project context
- project info: Show project details
- org list: List organizations
- org select: Select an organization

Uses PlatformApiClient for API calls and PlatformSession for
context persistence.

Co-Authored-By: Claude <noreply@anthropic.com>
Add Project and Org commands to main.rs routing:
- Added to command_name match for telemetry tracking
- Added to result match for command execution
- Routes to lib.rs handlers

Co-Authored-By: Claude <noreply@anthropic.com>
Shows selected org/project in chat welcome banner:
- If project selected: "📦 Project: org-name/project-name"
- If no project: "📦 Project: (none selected)" with hint

Co-Authored-By: Claude <noreply@anthropic.com>
Shows selected org/project in the input prompt:
- If project selected: "[org/project] >"
- If no project: ">" (standard prompt)

Co-Authored-By: Claude <noreply@anthropic.com>
- Add retry configuration constants (3 retries, 500ms-5s backoff)
- Add is_retryable_error() for HttpError, RateLimited, ServerError
- Update get() with exponential backoff retry for transient errors
- Update get_optional() with same retry logic
- Update post() to only retry on network errors (safe for non-idempotent)
- Log retry attempts to stderr for user visibility

Co-Authored-By: Claude <noreply@anthropic.com>
- Add suggestion() method returning user-friendly resolution advice
- Add with_suggestion() for formatted error + suggestion output
- Cover all error variants with appropriate suggestions
- Suggestions help users understand how to fix common issues

Co-Authored-By: Claude <noreply@anthropic.com>
- Add ConnectionFailed error variant for explicit connection failures
- Add check_connection() method with 5s timeout for quick health checks
- Add suggestion for ConnectionFailed error
- Update is_retryable_error() to include ConnectionFailed
- Update all platform tool format_api_error functions to handle ConnectionFailed

Co-Authored-By: Claude <noreply@anthropic.com>
- Add ClusterEntity and ClusterStatus types for K8s clusters
- Add ArtifactRegistry and RegistryStatus types for container registries
- Add list_clusters_for_project() and get_cluster() methods
- Add list_registries_for_project() and list_ready_registries_for_project()
- Export new types from platform::api module

Part of v1.10 CLI Service Deployment (Phase 54)

Co-Authored-By: Claude <noreply@anthropic.com>
- Add DiscoveredDockerfile type with deployment-focused fields
- Add suggest_service_name() with sanitization for K8s service names
- Add compute_build_context() for relative path computation
- Add infer_default_port() for common base images
- Add discover_dockerfiles_for_deployment() main discovery function
- Export new types from analyzer module
- Add 16 unit tests for discovery functions

Co-Authored-By: Claude <noreply@anthropic.com>
- Add DeploymentTarget enum (CloudRunner vs Kubernetes)
- Add WizardDeploymentConfig for wizard state tracking
- Add CreateDeploymentConfigRequest for API calls
- Add ProviderDeploymentStatus with ClusterSummary/RegistrySummary
- Add 8 unit tests for new types

Co-Authored-By: Claude <noreply@anthropic.com>
Add wizard module with shared rendering utilities for deployment wizard:
- wizard_render_config(): Custom RenderConfig with LightCyan styling
- display_step_header(): Box UI for wizard steps with term_width support
- status_indicator(): Green checkmark/red X for connection status
- count_badge(): Formatted count display

Co-Authored-By: Claude <noreply@anthropic.com>
Add get_provider_deployment_statuses() to query clusters/registries:
- Groups resources by cloud provider
- Determines connection status from existing resources
- Identifies Cloud Runner availability (GCP/Hetzner)
- Builds human-readable status summary
- Add Hash derive to CloudProvider for HashMap key usage

Co-Authored-By: Claude <noreply@anthropic.com>
Add interactive provider selection with visual status display:
- ProviderSelectionResult enum for selection outcomes
- select_provider() with inquire Select prompt
- Status indicators (checkmark/X) for connection state
- Graceful handling for no connected providers
- Cancel and escape handling
- Update mod.rs with explicit named exports

Co-Authored-By: Claude <noreply@anthropic.com>
Add deployment target selection (Cloud Runner vs Kubernetes):
- TargetSelectionResult enum with Selected/Back/Cancelled
- select_target() shows targets available for selected provider
- Cloud Runner shows "fully managed" description
- Kubernetes shows cluster count
- Back option for wizard navigation

Co-Authored-By: Claude <noreply@anthropic.com>
Add Kubernetes cluster selection for deployments:
- ClusterSelectionResult enum with Selected/Back/Cancelled
- select_cluster() shows healthy clusters with regions
- Status indicators (checkmark) for cluster health
- Back option to return to target selection

Co-Authored-By: Claude <noreply@anthropic.com>
Alex Holmberg and others added 25 commits January 18, 2026 14:12
…mmand

Bug fixes for deployment flow:

1. Fix dockerfile_path to be relative to build_context
   - When build_context is a subdirectory (e.g., services/api), the
     dockerfile_path was being sent as the full repo-relative path
     (e.g., services/api/Dockerfile)
   - Docker build expects the path relative to the context directory
     (just "Dockerfile" in this case)
   - Now strips the build_context prefix from dockerfile_path when they
     share a common prefix

2. Add missing `deploy status` command
   - CLI output said "Track progress: sync-ctl deploy status <task-id>"
     but the command didn't exist
   - Added DeployCommand::Status { task_id, watch } subcommand
   - Displays deployment progress, status, errors with colors
   - --watch flag polls every 5 seconds until completion

Fixes cloud runner build error:
  "lstat /workspace/source/Dockerfile: no such file or directory"

Co-Authored-By: Claude <noreply@anthropic.com>
Add verbose logging to help diagnose deployment trigger issues:
- Log trigger request parameters (projectId, configId)
- Log successful trigger response (backstageTaskId, status)
- Make error messages more prominent with colored output

Use -v or -vv flag with sync-ctl deploy to see debug logs.

Co-Authored-By: Claude <noreply@anthropic.com>
Docker's -f flag expects the path relative to where docker is invoked
(repo root), not relative to the build context directory.

Before: dockerfile="Dockerfile", context="services/contact-intelligence"
  -> Docker looks for /workspace/source/Dockerfile (not found)

After: dockerfile="services/contact-intelligence/Dockerfile", context="services/contact-intelligence"
  -> Docker finds /workspace/source/services/contact-intelligence/Dockerfile

Co-Authored-By: Claude <noreply@anthropic.com>
Previous approach using strip_prefix had edge cases with relative vs
absolute paths. New approach constructs dockerfile path by joining
build_context with filename, which is more robust.

For Dockerfile at services/contact-intelligence/Dockerfile:
- build_context = "services/contact-intelligence"
- dockerfile_name = "Dockerfile"
- result = "services/contact-intelligence/Dockerfile"

This ensures Docker's -f flag receives the correct path relative to
repo root where docker is invoked.

Co-Authored-By: Claude <noreply@anthropic.com>
Adds detailed debug logging to show exact request fields being sent
when creating a deployment config. Run with -vv to see:
- All request fields (projectId, serviceName, environmentId, etc.)
- Dockerfile path and build context
- CloudRunnerConfig JSON
- Response confirmation with config ID

Co-Authored-By: Claude <noreply@anthropic.com>
Add PortSource enum to track where ports are detected from:
- Dockerfile, DockerCompose, PackageJson, FrameworkDefault,
  EnvVar, SourceCode, ConfigFile

Update all Port struct usages to include source field.
Backward compatible - source field is optional.

Co-Authored-By: Claude <noreply@anthropic.com>
Add HealthEndpoint and HealthEndpointSource types for deployment
recommendations. Detect health endpoints from:
- Framework conventions (Spring Actuator, Quarkus, etc.)
- Source code patterns (route definitions)

Includes health_endpoints field in ProjectAnalysis.

Fix pre-existing test issue in types.rs.

Co-Authored-By: Claude <noreply@anthropic.com>
Add detection for existing infrastructure configurations:
- Kubernetes manifests (k8s/, deploy/, manifests/ directories)
- Helm charts (Chart.yaml detection)
- Terraform files (*.tf)
- Docker Compose files
- Syncable deployment configs

Includes InfrastructurePresence struct with has_any() and
detected_types() helper methods. Detection is integrated into
analyze_project_with_config.

Co-Authored-By: Claude <noreply@anthropic.com>
Create intelligent deployment recommendation module that:
- Selects provider based on availability and existing infrastructure
- Selects target (Cloud Runner vs K8s) based on project analysis
- Selects machine type based on framework memory requirements
  (JVM=high, Python=medium, Node/Go/Rust=low)
- Selects region with user hint support
- Selects port from best detection source
- Includes health check path when detected
- Calculates confidence score
- Provides alternatives for user customization

Includes 9 comprehensive tests covering Express, Spring Boot,
K8s detection, port fallback, health endpoints, and alternatives.

Co-Authored-By: Claude <noreply@anthropic.com>
Create compound agent tool that enables end-to-end deployment:
- Analyzes project (language, framework, ports, health endpoints)
- Checks available deployment capabilities
- Generates recommendations with reasoning using 11.3-02 engine
- Returns preview with confirmation prompt (preview_only=true)
- Executes deployment when confirmed (preview_only=false)

Features:
- Provider/machine/region/port overrides for customization
- Monorepo support with optional path parameter
- Derives dockerfile path and build context from analysis
- Uses PlatformSession for context, recommendation engine for settings
- Includes alternatives for user customization

5 tests covering tool name, preview mode, service name derivation,
and error handling for nonexistent paths.

Co-Authored-By: Claude <noreply@anthropic.com>
…yServiceTool

Prevents creating duplicate deployment configs by:
- Checking existing configs before deploying
- Routing to redeploy if service already exists
- Showing environment info (name, is_production) in preview
- Adding production deployment warnings
- Showing REDEPLOY vs NEW_DEPLOYMENT mode clearly

Co-Authored-By: Claude <noreply@anthropic.com>
The API wraps all responses in { "data": ... } but check_provider_connection
and get_cluster were not unwrapping this, causing parse errors when the
provider IS connected.

This explains why the agent couldn't detect connected providers.

Co-Authored-By: Claude <noreply@anthropic.com>
The endpoint /api/cloud-credentials/provider/{provider} may not exist.
Changed to use list_cloud_credentials_for_project (which works) and
filter by provider.

This is the same approach the wizard uses via get_provider_deployment_statuses.

Co-Authored-By: Claude <noreply@anthropic.com>
The tool exists but wasn't exported from tools/mod.rs or registered
in the agent. This tool uses the working wizard code to detect
connected providers, which is more reliable than check_provider_connection.

Now the agent has access to list_deployment_capabilities which shows
all connected providers, clusters, and registries at once.

Co-Authored-By: Claude <noreply@anthropic.com>
The agent couldn't create deployments because these tools weren't
registered:
- CreateDeploymentConfigTool - manual config creation
- DeployServiceTool - intelligent deployment with analysis

Now the agent can:
1. Analyze projects and recommend deployment settings
2. Create deployment configs
3. Trigger deployments

Co-Authored-By: Claude <noreply@anthropic.com>
The Backstage task can show "completed" (100%) when infrastructure is
provisioned, but Cloud Runner actual deployment (build + deploy) takes
longer.

Added optional project_id and service_name params that when provided:
- Also check list_deployments for actual service status
- Look for public_url which indicates service is truly ready
- Return service_ready: true only when URL is available
- Show helpful note when task is 100% but service still deploying

Now the agent can accurately report when a Cloud Runner service is
actually ready to serve traffic, not just when infrastructure is ready.

Co-Authored-By: Claude <noreply@anthropic.com>
Added guidelines to not narrate actions like "I'll call X tool" or
"The user wants Y so I'll Z". The agent should take action directly
without announcing what it's about to do.

Users care about results, not internal reasoning.

Co-Authored-By: Claude <noreply@anthropic.com>
…oyments

When deploying a service from a subdirectory (e.g., path: "services/contact-intelligence"),
the dockerfile path and build context must be relative to the repo root, not the
analyzed subdirectory.

Before: dockerfile="Dockerfile", context="." (relative to subdirectory)
After: dockerfile="services/contact-intelligence/Dockerfile", context="services/contact-intelligence"

Changes:
- Extract dockerfile filename, then prepend the subpath to construct repo-relative paths
- Follow the same pattern as orchestrator.rs (commit 3cb8698)
- Add docker_config to deployment response for visibility
- Add debug logging for path derivation troubleshooting

Fixes cloud runner failing with "unable to evaluate symlinks in Dockerfile path:
lstat /workspace/source/Dockerfile: no such file or directory" when deploying
monorepo services.

Co-Authored-By: Claude <noreply@anthropic.com>
For monorepo deployments, the agent now sends the same values as the
manual wizard:
- dockerfile: full path from repo root (e.g., "services/foo/Dockerfile")
- context: the service folder (e.g., "services/foo")

This matches what the user would select in the manual wizard when
choosing the Dockerfile's directory as the build context.

The context is crucial for Docker's COPY commands - if the Dockerfile
has `COPY . .`, it copies from the context directory, not repo root.

Co-Authored-By: Claude <noreply@anthropic.com>
When user specifies path="services/foo" to deploy a subdirectory, the
dockerfile paths should be relative to THAT directory, not the project root.

This matches the manual wizard behavior when you run `sync-ctl deploy`
from within the service directory:
- dockerfile: "Dockerfile"
- context: "."

The GitHub repo structure may differ from the local filesystem structure.
For example, locally you might have:
  /project/services/contact-intelligence/Dockerfile
But the GitHub repo might have:
  /Dockerfile (at root)

Previously we were prepending args.path to make paths "repo-root-relative",
but this broke deployments when the repo structure differed from local.

Co-Authored-By: Claude <noreply@anthropic.com>
… Runner

Cloud Runner clones the GitHub repo and needs paths relative to the repo root,
not relative to the analyzed subdirectory. When deploying from a monorepo
subdirectory (e.g., services/contact-intelligence), the dockerfile_path and
build_context must include the full path from repo root.

Example for path="services/contact-intelligence":
- Before: dockerfile="Dockerfile", context="."
- After: dockerfile="services/contact-intelligence/Dockerfile", context="services/contact-intelligence"

Co-Authored-By: Claude <noreply@anthropic.com>
The agent was picking the first repository from the project's connected
repos, which happened to be the GitOps infrastructure repo instead of
the application repo.

Now the agent:
1. Detects the local git remote URL
2. Parses the repo name from the URL
3. Matches against connected repositories
4. Falls back to non-gitops repo if no match

This matches the manual wizard behavior which shows:
"Using detected repository: syncable-dev/ai-demo-project"

Co-Authored-By: Claude <noreply@anthropic.com>
…e loop

The agent was calling get_deployment_status repeatedly without waiting,
creating an infinite polling loop. Updated the tool to:

1. Add explicit "action" field in response:
   - STOP_POLLING: deployment done (success/failure)
   - INFORM_USER_AND_WAIT: tell user to wait, let them ask for updates

2. Updated tool description with CRITICAL warning about not polling in loop

3. Changed next_steps to explicitly say "DO NOT call again automatically"

The agent should now check status once, inform the user, and wait for
them to request updates.

Co-Authored-By: Claude <noreply@anthropic.com>
The agent was deploying all services as public without asking the user.
Now:

1. Added is_public parameter to DeployServiceArgs (default: false)
2. Preview shows is_public with clear explanation:
   - "Service will be INTERNAL only (not accessible from internet)"
   - "Service will be PUBLICLY accessible from the internet"
3. Uses args.is_public when creating deployment config

This ensures services are internal by default for safety, and the agent
must explicitly show and confirm public access with the user.

Co-Authored-By: Claude <noreply@anthropic.com>
When user requests a change (e.g., "make it public", "use GCP"), the
agent was deploying immediately instead of showing a new preview.

Updated tool description to be explicit:
- A change request is NOT a deployment confirmation
- Must show NEW preview with updated settings
- Only deploy after explicit "yes", "deploy", "confirm"

Flow: request → preview → change request → NEW preview → confirm → deploy

Co-Authored-By: Claude <noreply@anthropic.com>
@Alex793x Alex793x merged commit 9cdfc75 into main Jan 20, 2026
3 of 6 checks passed
Alex793x added a commit that referenced this pull request Mar 28, 2026
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.

1 participant