Skip to content
Merged
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
46 changes: 46 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ jobs:
runs-on: ubuntu-latest
outputs:
cloud_agent: ${{ steps.filter.outputs.cloud_agent }}
cloud_agent_next: ${{ steps.filter.outputs.cloud_agent_next }}
webhook_agent: ${{ steps.filter.outputs.webhook_agent }}
steps:
- uses: actions/checkout@v4
Expand All @@ -28,6 +29,8 @@ jobs:
filters: |
cloud_agent:
- 'cloud-agent/**'
cloud_agent_next:
- 'cloud-agent-next/**'
webhook_agent:
- 'cloudflare-webhook-agent-ingest/**'

Expand Down Expand Up @@ -216,6 +219,49 @@ jobs:
- name: Run cloud-agent tests
run: pnpm --filter cloud-agent test:all

cloud-agent-next:
needs: changes
if: needs.changes.outputs.cloud_agent_next == 'true'
runs-on: ubuntu-24.04-8core
steps:
- uses: actions/checkout@v4
with:
lfs: true
ref: ${{ github.head_ref }}

- name: Setup pnpm
uses: pnpm/action-setup@v2
with:
version: latest
run_install: false

- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 22
cache: 'pnpm'

- name: Setup Bun
uses: oven-sh/setup-bun@v2
with:
bun-version: latest

- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Build wrapper bundle
working-directory: cloud-agent-next/wrapper
run: bun run build.ts

- name: Typecheck (cloud-agent-next)
run: pnpm --filter cloud-agent-next typecheck

- name: Lint (cloud-agent-next)
run: pnpm --filter cloud-agent-next lint

- name: Run cloud-agent-next tests
run: pnpm --filter cloud-agent-next test:all

webhook-agent:
needs: changes
if: needs.changes.outputs.webhook_agent == 'true'
Expand Down
35 changes: 35 additions & 0 deletions .github/workflows/deploy-cloud-agent-next.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: Deploy Cloud Agent Next

on:
workflow_dispatch:
workflow_call:

jobs:
deploy:
runs-on: ubuntu-latest
name: Deploy Cloud Agent Next

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup pnpm
uses: pnpm/action-setup@v2
with:
version: latest

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 22

- name: Install dependencies
working-directory: cloud-agent-next
run: pnpm install --frozen-lockfile

- name: Deploy to Cloudflare Workers
Comment thread
pandemicsyn marked this conversation as resolved.
uses: cloudflare/wrangler-action@v3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
workingDirectory: cloud-agent-next
command: deploy
72 changes: 72 additions & 0 deletions cloud-agent-next/.dev.vars.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# Shared secret for JWT token validation (same as NextAuth.js secret)
NEXTAUTH_SECRET=your-nextauth-secret-here

# Shared secret for internal API calls, same as .env.development.
INTERNAL_API_SECRET=your-internal-api-secret-here

# Optional: Override Kilocode credentials in session environment variables used during kilocode invocation
# These do NOT affect authentication - authentication always uses the original token from the API request
# Use these to inject test/dev credentials while maintaining proper authentication with credentials sent
# Affects:
# - Session environment variables (KILOCODE_TOKEN and KILOCODE_ORG_ID)
#
# Note: With the introduction of server backed sessionsthese should probably not be used any more,
# you should set KILOCODE_BACKEND_BASE_URL instead and use local dev only.
#KILOCODE_TOKEN_OVERRIDE=your-override-token-here
#KILOCODE_ORG_ID_OVERRIDE=your-override-org-id-here

# Kilocode backend base URL and KILO_OPENROUTER_BASE for API calls and session environment variables
# For local development, point to your local kilocode-backend
# Note: you wanna use your actual privatenet address here and not "localhost"
# pnpm run dev of kilocode-backend usually gives you both addrs on boot.
KILOCODE_BACKEND_BASE_URL=http://192.168.200.70:3000
KILO_OPENROUTER_BASE=http://192.168.200.70:3000/api

# Worker base URL used by the wrapper to connect to /ingest.
# Use a host-reachable IP (not localhost) so sandbox containers can connect back.
WORKER_URL=http://192.168.200.72:8794

# Timeout overrides (optional)
WRAPPER_IDLE_TIMEOUT_MS=120000
CLI_TIMEOUT_SECONDS=700
REAPER_INTERVAL_MS=300000
STALE_THRESHOLD_MS=600000
PENDING_START_TIMEOUT_MS=300000

# GitHub App credentials for git commit attribution
# These identify commits as coming from the Kilo Code GitHub App
# Format for git config:
# user.name: {GITHUB_APP_SLUG}[bot]
# user.email: {GITHUB_APP_BOT_USER_ID}+{GITHUB_APP_SLUG}[bot]@users.noreply.github.com
GITHUB_APP_SLUG=kiloconnect-development
GITHUB_APP_BOT_USER_ID=242397087

# GitHub App credentials for generating installation access tokens
# Used by GitHubTokenService to authenticate with GitHub API on behalf of app installations
# GITHUB_APP_ID: The numeric App ID from GitHub App settings
# GITHUB_APP_PRIVATE_KEY: The raw PKCS#8 private key (use \n for newlines in env var)
# Note that the nextjs app uses PKCS#1 but the worker uses WebCrypto and requires a PKCS#8
GITHUB_APP_ID=2245043
GITHUB_APP_PRIVATE_KEY=

# GitHub Lite App credentials (for OSS organizations with read-only permissions)
# Same format as standard app credentials above
GITHUB_LITE_APP_ID=
GITHUB_LITE_APP_PRIVATE_KEY=

# Agent Environment Profile Secrets Decryption
# Used to decrypt encrypted secrets from agent environment profiles at session execution time.
# This is a RSA private key that pairs with AGENT_ENV_VARS_PUBLIC_KEY in the backend.
#
# The development private key is available in 1pass as 'Agent Env Vars Profile Private key'
AGENT_ENV_VARS_PRIVATE_KEY=""

#
# R2 Attachments Bucket Readonly Access
# 1pass (Cloudflare - R2 Cloud Agents Attachments Read Only)
R2_ENDPOINT=""
R2_ATTACHMENTS_READONLY_ACCESS_KEY_ID=""
R2_ATTACHMENTS_READONLY_SECRET_ACCESS_KEY=""

# Local dev worker origins allowed to connect to /stream
WS_ALLOWED_ORIGINS=http://localhost:3000,http://localhost:8794
7 changes: 7 additions & 0 deletions cloud-agent-next/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.wrangler/
.env*
wrapper/dist/
!.env.example
.dev.vars*
!.dev.vars.example
kilocode-cli.tgz
11 changes: 11 additions & 0 deletions cloud-agent-next/.prettierrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"semi": true,
"singleQuote": true,
"tabWidth": 2,
"useTabs": false,
"printWidth": 100,
"trailingComma": "es5",
"bracketSpacing": true,
"arrowParens": "avoid",
"endOfLine": "lf"
}
5 changes: 5 additions & 0 deletions cloud-agent-next/.vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"files.associations": {
"wrangler.json": "jsonc"
}
}
103 changes: 103 additions & 0 deletions cloud-agent-next/AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
# AGENTS.md

This file provides guidance to AI coding agents working in this repository.

## Project Overview

Cloudflare Worker that powers Kilocode Cloud Agents. It exposes a tRPC API for session preparation and execution, streams output over WebSockets, and runs the Kilocode CLI inside Cloudflare Sandbox containers. Durable Objects track sessions; Hyperdrive is used for Postgres lookups (for example, GitHub App installation IDs). The wrapper in `wrapper/` is a core component that brokers Kilocode CLI events into the worker’s `/ingest` WebSocket and handles job lifecycle.

## Development Commands

### Package Management

- Use pnpm (enforced by preinstall). Never use npm or yarn.
- `pnpm install` - Install dependencies

### Wrapper Build

- `pnpm run build:wrapper` - Build wrapper bundle (uses Bun in `wrapper/`)

### Testing

- `pnpm run test` - Unit tests (Vitest Node)
- `pnpm run test:integration` - Integration tests in Workers runtime (Miniflare)
- `pnpm run test:all` - Unit + integration

### Code Quality

- `pnpm run lint` - ESLint
- `pnpm run lint:fix` - ESLint with auto-fix
- `pnpm run format` - Prettier write (src only)
- `pnpm run format:check` - Prettier check (src only)
- `pnpm run typecheck` - TypeScript (tsgo) + wrapper typecheck

### Deployment

- DO NOT attempt to deploy directly. Always defer to the user.

## Architecture Overview

### Core Worker

- `src/index.ts` - Entry point, request routing
- `src/router/` - tRPC router and handlers
- `src/session-service.ts` - Session lifecycle orchestration
- `src/workspace.ts` - Workspace setup and git operations
- `src/streaming.ts` - WebSocket streaming

### Durable Objects

- `src/persistence/CloudAgentSession.ts` - Session DO storage + lifecycle
- `src/db/` - SQLite table definitions and store helpers for DOs

### Sandbox + Execution

- `src/execution/` - Orchestrator and execution lifecycle
- `src/kilo/` - Kilocode CLI wrapper client and helpers
- `Dockerfile` - Production sandbox image
- `Dockerfile.dev` - Dev sandbox image (local Kilocode CLI)
- `cloud-agent-build.sh` - Builds local Kilocode CLI binary for `Dockerfile.dev`

### Wrapper

- `wrapper/` - Local wrapper bundled into the sandbox image
- `wrapper/src/main.ts` - Wrapper entrypoint
- `src/shared/kilo-types.ts` - Types are a subset copied from `~/kilo/packages/sdk/js/src/v2/gen/types.gen.ts` (kilo repo, generated SDK); keep in sync when wrapper/Kilo API changes

### Configuration

- `wrangler.jsonc` - Worker config, bindings, environments
- `.dev.vars.example` - Local dev env template
- `worker-configuration.d.ts` - Auto-generated types. Do not edit; regenerate with `pnpm run types`.

## Development Guidelines

### Code Style

- Keep streaming payloads and schemas aligned with `src/shared/protocol.ts`

### Runtime Guidelines

- Durable Object calls should be retried using `withDoRetry` in `src/utils/do-retry.ts`
- Execute commands inside a session context (use `session.exec(...)`, not `sandbox.exec(...)`)

### Testing Standards

- Unit tests: `src/**/*.test.ts` (Vitest Node)
- Integration tests: `test/**/*.test.ts` (Workers runtime)
- Use `vitest.workers.config.ts` for Workers runtime tests

### Git Workflow

- Create feature branches; do not commit on main

## Key Locations

- `src/router/handlers/` - API endpoints (prepare, initiate, sendMessage, session management)
- `src/persistence/` - Durable Object schema + migrations
- `src/websocket/` - WebSocket ingest + filters
- `src/utils/` - Shared helpers (encryption, retries, SQL helpers)
- `wrangler.jsonc` - Bindings: R2, Hyperdrive, KV, queues, containers
- `vitest.config.ts` - Unit test config
- `vitest.workers.config.ts` - Integration test config
- `wrapper/` - Wrapper build shipped into the sandbox
49 changes: 49 additions & 0 deletions cloud-agent-next/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
FROM docker.io/cloudflare/sandbox:0.6.7

# Build arguments for metadata (all optional with defaults)
ARG BUILD_DATE=""
ARG VCS_REF=""
ARG KILOCODE_CLI_VERSION="latest"

RUN mkdir -p -m 755 /etc/apt/keyrings \
&& out=$(mktemp) && wget -nv -O$out https://cli.github.com/packages/githubcli-archive-keyring.gpg \
&& cat $out | tee /etc/apt/keyrings/githubcli-archive-keyring.gpg > /dev/null \
&& chmod go+r /etc/apt/keyrings/githubcli-archive-keyring.gpg \
&& mkdir -p -m 755 /etc/apt/sources.list.d \
&& echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | tee /etc/apt/sources.list.d/github-cli.list > /dev/null \
&& apt update \
&& apt install gh -y

# Install GitLab CLI (glab) - download official .deb from GitLab releases
RUN GLAB_VERSION="1.80.4" \
&& wget -nv -O /tmp/glab.deb "https://gitlab.com/gitlab-org/cli/-/releases/v${GLAB_VERSION}/downloads/glab_${GLAB_VERSION}_linux_amd64.deb" \
&& dpkg -i /tmp/glab.deb \
&& rm /tmp/glab.deb

# Generate locales to suppress setlocale warnings
RUN apt-get update && apt-get install -y --no-install-recommends locales && \
sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && \
locale-gen && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
ENV LC_ALL=en_US.UTF-8
ENV LANG=en_US.UTF-8

# Install dependencies globally (accessible to all users)
RUN npm install -g pnpm @kilocode/cli@${KILOCODE_CLI_VERSION}

# === Build wrapper bundle inside container ===
# This ensures the wrapper is built with the same Bun version that will run it,
# avoiding any compatibility issues between build and runtime environments.
# The wrapper imports from ../../src/shared/protocol.js, so we maintain that structure.
COPY wrapper /tmp/wrapper-build/wrapper
COPY src/shared /tmp/wrapper-build/src/shared

# Build the wrapper bundle
RUN cd /tmp/wrapper-build/wrapper && \
bun build src/main.ts --outfile=/usr/local/bin/kilocode-wrapper.js --target=bun --minify && \
rm -rf /tmp/wrapper-build

# DO NOT override USER, WORKDIR, or ENTRYPOINT from the base image
# The Cloudflare sandbox base image has its own startup.sh script that must run
# Installing packages globally makes them accessible regardless of the user
Loading