{"id":47790683,"url":"https://github.com/deadronos/copilot-chat-playground","last_synced_at":"2026-04-03T15:36:32.145Z","repository":{"id":334134552,"uuid":"1140171193","full_name":"deadronos/copilot-chat-playground","owner":"deadronos","description":"a \"playground\" to learn running the Copilot CLI and SDK isolated in Docker","archived":false,"fork":false,"pushed_at":"2026-03-16T00:57:54.000Z","size":27850,"stargazers_count":0,"open_issues_count":4,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-16T03:48:08.241Z","etag":null,"topics":["copilot-cli","copilot-sdk","docker","react","shadcn-ui","vite"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/deadronos.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-01-22T23:17:01.000Z","updated_at":"2026-03-16T00:57:59.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/deadronos/copilot-chat-playground","commit_stats":null,"previous_names":["deadronos/copilot-chat-playground"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/deadronos/copilot-chat-playground","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/deadronos%2Fcopilot-chat-playground","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/deadronos%2Fcopilot-chat-playground/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/deadronos%2Fcopilot-chat-playground/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/deadronos%2Fcopilot-chat-playground/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/deadronos","download_url":"https://codeload.github.com/deadronos/copilot-chat-playground/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/deadronos%2Fcopilot-chat-playground/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31360807,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-03T15:19:21.178Z","status":"ssl_error","status_checked_at":"2026-04-03T15:19:20.670Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["copilot-cli","copilot-sdk","docker","react","shadcn-ui","vite"],"created_at":"2026-04-03T15:36:31.671Z","updated_at":"2026-04-03T15:36:32.132Z","avatar_url":"https://github.com/deadronos.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Copilot Chat Playground\n\nA local playground for experimenting with a chat UI + backend + Copilot integration. The Docker Compose stack works locally (frontend, backend, and copilot services), and the Copilot service supports both the **Copilot SDK (default)** and the **Copilot CLI (fallback)**.\n\nThis repo is a **pnpm workspace** with separate packages under `src/`.\n\n## Demo Screenshot\n![Copilot Chat Playground Screenshot](image.png)\nFrontend ran a prompt against the Copilot service using the SDK mode.\n\n![Docker Compose Stack Screenshot](dockerup.png)\nDocker up and running\n\nYouTube Demo Video:\n[YouTube Demo Video](https://www.youtube.com/watch?v=ycVCQS6mjZg)\nDemo Video downscaled here:\n[Demo Video in Repo](./Copilot_Chat_PlayGround_Docker.mp4)\n\n## Packages\n\n- `src/frontend` — Vite + React + shadcn/ui UI\n- `src/backend` — Node.js API gateway for streaming chat, request validation, and RedVsBlue orchestration\n- `src/copilot` — **Copilot SDK** / Copilot CLI wrapper service (uses SDK by default)\n- `src/shared` — shared types/utilities (LogEvent, EventBus, NDJSON helper)\n\n## Module layout (post-refactor)\n\n- Backend routing stays thin in `src/backend/src/app.ts`; controllers validate/stream in `src/backend/src/controllers/*`, and reusable helpers (including chat-context shaping) live in `src/backend/src/services/*`.\n- ChatPlayground UI is split into a container (`src/frontend/src/components/chat-playground.tsx`) and presentational components (`src/frontend/src/components/chat-playground/*`).\n- RedVsBlue engine core + entities live under `src/frontend/src/redvsblue/engine/*`, with higher-level orchestration in `src/frontend/src/redvsblue/*`.\n\n## Easter egg: RedVsBlue\n\nThere’s an “eastergg” in the playground: **RedVsBlue**, a mini game orchestrated and mediated by Copilot. It lives in the frontend and uses the backend’s RedVsBlue endpoints for match lifecycle, snapshots, and AI commentary.\n\n## CI guardrails\n\n- Coverage thresholds are enforced per package (backend/frontend/copilot) via `vitest` coverage settings.\n- Router thinness is enforced by a simple line-count guard: `pnpm ci:guardrails` (see `scripts/ci/check-router-thin.mjs`).\n\n## Getting started\n\n1. Enable pnpm via Corepack (recommended)\n\n   - `corepack enable`\n\n2. Install deps\n\n   - `pnpm install`\n\n3. Run everything in dev\n\n   - `pnpm dev`\n\n### Run just one service\n\n- `pnpm dev:frontend`\n- `pnpm dev:backend`\n- `pnpm dev:copilot`\n\n### Copilot Service Modes\n\nThe copilot service supports two modes:\n\n1. **SDK Mode** (default): Uses `@github/copilot-sdk` for structured streaming with full event support\n2. **CLI Mode**: Direct CLI spawning for simpler use cases\n\nSet `USE_COPILOT_SDK=false` in your environment to use CLI mode.\n\n#### Patch required: `vscode-jsonrpc/node` import\n\nNewer `@github/copilot-sdk` versions import `vscode-jsonrpc/node`, which is not provided by `vscode-jsonrpc` by default. This repo includes a small `pnpm patch` that adds a `node` entry point to `vscode-jsonrpc` so the SDK can run correctly. When running `pnpm install`, the patch is applied automatically.\n\n### Chat UX enhancements\n\n- End-to-end streaming supports cancel + retry controls in the main chat UI.\n- Conversation history is persisted locally so the latest session can be resumed after refresh; storage failures degrade gracefully instead of breaking the UI.\n- Follow-up turns send optional `sessionId` + prior `messages` to the backend, which folds that history into the contextual prompt used for the next Copilot request.\n- An observability panel exposes Copilot health/models/metrics and backend observability summary from the frontend.\n\n## Secrets \u0026 dotenvx\n\nFor Docker/Compose usage with encrypted `.env` files, see the repo guidance in [`docs/library/dotenvx/README.md`](docs/library/dotenvx/README.md). It documents safe-by-default key handling, recommended secret injection patterns, and install options.\n\n**Tip:** Commit a `.env.example` or `.env.sample` (without secrets) that documents required environment variables and example shapes. Do not commit actual `.env` files or any real secrets — use `.env.example` solely as a reference for developers.\n\n### Docker / Compose\n\nFor running containers (including Milestone E workspace mounts) prefer a **secrets-first** approach:\n\n- Keep `.env.keys` out of source control (it contains `DOTENV_PRIVATE_KEY_*`). The repo already ignores it via `.gitignore` and keeps it out of the Docker build context via `.dockerignore`.\n- Inject secrets at **runtime** (Docker secrets / orchestrator secrets / mounted secret file). Do **not** bake secrets into images.\n- Avoid passing secrets on the CLI (e.g., `docker run -e ...` or `DOTENV_PRIVATE_KEY_*=... docker compose up`) except as a small **dev-only** convenience.\n\nThis repo’s `src/copilot/entrypoint.sh` supports reading secrets from `/run/secrets/` and exporting them into env at container start:\n\n- `DOTENV_PRIVATE_KEY_*` (for `dotenvx` runtime decryption)\n- `GH_TOKEN` / `GITHUB_TOKEN` (Copilot auth)\n\nSee [`docs/milestone-e-workspace-mount.md`](docs/milestone-e-workspace-mount.md) for workspace-mount specific guidance and warnings. For an end-to-end quick start and troubleshooting steps, see the Docker setup guide: [`docs/docker-setup-guide.md`](docs/docker-setup-guide.md).\n\n**Docker build tip:** When installing dependencies inside Docker, prefer deterministic installs by using a frozen lockfile. Example in a Dockerfile:\n\n```dockerfile\nRUN corepack enable \u0026\u0026 pnpm install --frozen-lockfile --prod\n```\n\nKeeping `pnpm-lock.yaml` available to Docker builds helps ensure reproducible images (do not add it to `.dockerignore` if you expect it to be used during image builds).\n\nQuick verification — Docker \u0026 Copilot ✅\n\n- Build \u0026 run the full stack:\n  - `docker compose up --build`\n  - Or run detached: `docker compose up -d --build`\n- Verify running services:\n  - `docker compose ps`\n  - `docker compose logs -f copilot`\n- Check Copilot health and mode (works for SDK and CLI):\n  - `curl -s http://localhost:3210/health | jq .` (inspect `mode`, `tokenConfigured`, `binaryAvailable`)\n- Quick API test (requires `GH_TOKEN` configured):\n  - `curl -X POST http://localhost:3210/chat -H 'Content-Type: application/json' -d '{\"prompt\":\"What is GitHub Copilot?\"}'`\n\nNote: The Copilot service uses the **SDK by default**. To force the CLI fallback set `USE_COPILOT_SDK=false` (env or Compose override).\n\n## Workspace mount (read-only default)\n\n- The Compose stack mounts the host `./workspace` into the `copilot` container as a **read-only** bind mount by default (e.g. `./workspace:/workspace:ro`) to avoid accidental modification of your working tree or host secrets.\n- If you need write access for builds or tests, prefer a **named volume** or a dedicated writable path instead of making the entire repo writable.\n- To enable writable access in a dev-only override, create a `docker-compose.override.yml` and adjust the `volumes` entry for `copilot`, for example:\n\n```yaml\nservices:\n  copilot:\n    volumes:\n      - ./workspace:/workspace:rw\n```\n\n- Quick verification inside a running container:\n\n```bash\n# Should print \"read-only mount\" when mount is read-only\ndocker compose exec copilot sh -c 'touch /workspace/should_fail 2\u003e/dev/null || echo \"read-only mount\"'\n# Inspect mount options on Linux\ndocker compose exec copilot sh -c 'grep /workspace /proc/mounts || mount | grep /workspace'\n```\n\nSee `docs/milestone-e-workspace-mount.md` for additional checks and safety guidance.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdeadronos%2Fcopilot-chat-playground","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdeadronos%2Fcopilot-chat-playground","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdeadronos%2Fcopilot-chat-playground/lists"}