Skip to content

feat(registry/coder-labs/modules/copilot): migrate off AgentAPI and Tasks - #1117

Merged
DevelopmentCats merged 25 commits into
mainfrom
35C4n0r/copilot-remove-tasks
Oct 14, 2026
Merged

DevelopmentCats merged 25 commits into
mainfrom
35C4n0r/copilot-remove-tasks

Conversation

@35C4n0r

@35C4n0r 35C4n0r commented Sep 16, 2026 •

Copy link
Copy Markdown
Collaborator

Closes REG-83

Refactor coder-labs/copilot to install and configure GitHub Copilot CLI only, matching the claude-code and codex v5 migrations. Bump to 1.0.0.

  • Replace the agentapi module with coder-utils; drop the Tasks, web/CLI app, and AgentAPI inputs, the start script, the task_app_id output, and the task-reporting coder MCP server.
  • Install with the official installer (https://gh.io/copilot-install, temp file + bash -n, VERSION from copilot_version) instead of npm, so Node.js is no longer required. Skipped when copilot is already on PATH; with install_copilot = false, copilot must be on PATH.
  • workdir is optional; when set it is created and added to trustedFolders in ~/.copilot/config.json (Copilot's // header is stripped before parsing; the file is left unchanged if it cannot be parsed).
  • Rename copilot_config to base_copilot_config; when set it overwrites ~/.copilot/settings.json on every start.
  • Rename mcp_config to mcp; merged into ~/.copilot/mcp-config.json with servers already on disk winning. A JSONC or invalid file is skipped with a warning.
  • managed_settings is written to /etc/github-copilot/managed-settings.json.
  • github_token is exported as COPILOT_GITHUB_TOKEN and copilot_model as COPILOT_MODEL via coder_env.
  • Rename enable_aibridge_proxy / aibridge_proxy_* to enable_ai_gateway / ai_gateway_proxy_auth_url / ai_gateway_proxy_cert_path; when enabled, HTTPS_PROXY and NODE_EXTRA_CA_CERTS are set via coder_env.
  • Launch-only inputs (allow_all_tools, allow_tools, deny_tools, resume_session, ai_prompt, system_prompt) become flags in the user's coder_app.
  • Add scripts output; README reduced to examples and doc links; rewrite tests.

Testing

  • terraform test, bun test main.test.ts (container-based), terraform fmt, terraform validate, prettier, shellcheck
  • Dogfood workspace from a test template: JSON base_copilot_config overwrites settings.json, JSONC is written as is, and mcp is merged into mcp-config.json in both cases

Generated with Coder Agents.

…oder Tasks

Refactor the copilot module to install and configure Copilot only, matching the claude-code and codex v5 migrations:

- Replace the agentapi module with coder-utils; drop Tasks/web-app/CLI-app and AgentAPI variables and the start script.
- Install Copilot via the official install script (temp file + bash -n validation) instead of npm; no Node.js prerequisite.
- Make workdir optional; write config.json and merge mcp_config into ~/.copilot; pass copilot_model through as given.
- Add enable_ai_gateway using Copilot BYOK provider env vars; keep github_token (GITHUB_TOKEN + GH_TOKEN).
- Output scripts; rewrite README and tests.

Generated with Coder Agents.
@github-actions

github-actions Bot commented Sep 16, 2026 •

Copy link
Copy Markdown
Contributor

Module Scorecard Check

coder-labs/copilot: first scorecard, 68 / 100

No specific score is required to contribute, but modules with higher scores are more likely to be approved by the Coder team and widely used.

Full scorecard for this PR
Presentation & Onboarding Agent Integration Credential Hygiene Restricted-Environment Readiness Engineering Quality Overall
12 / 17 15 / 25 20 / 20 6 / 20 10 / 10 68 / 100
Drilldown

Presentation & Onboarding — 12 / 17

Criterion Max Score Notes
Configuration-mode examples 12 12 README documents each major mode: external auth, direct token, AI Gateway proxy, advanced config (managed_settings, base_copilot_config, mcp, pre_install_script), and downstream script serialization. Sensible defaults are shown in the basic example.
Visual preview 5 0 No image, GIF, or video embedded in the README. The frontmatter icon field and the coder_app icon reference are not visual previews of the module in action.

Agent Integration — 15 / 25

Criterion Max Score Notes
AI governance 10 5 AI Gateway Proxy is documented with a full example (enable_ai_gateway, ai_gateway_proxy_auth_url, ai_gateway_proxy_cert_path). No mention of Agent Firewall anywhere in the README or code. Exactly one of two required → half.
Dashboard entry point 5 5 The "Launcher app with GitHub external auth" example includes a complete coder_app resource with slug, display_name, icon, open_in = "slim-window", and a launch command.
Session continuity 5 0 No documentation of session resumption, session IDs, or persistent session managers (tmux, screen, boo). The coder_app command launches copilot --allow-all-tools fresh each time with no resume mechanism.
Managed configuration 5 5 Three documented managed-config inputs: managed_settings (written to /etc/github-copilot/managed-settings.json), base_copilot_config (overwrites ~/.copilot/settings.json), and mcp (merged into ~/.copilot/mcp-config.json). The "Advanced configuration" example exercises all three.

Credential Hygiene — 20 / 20

Criterion Max Score Notes
Secrets marked sensitive 16 16 github_token and ai_gateway_proxy_auth_url both have sensitive = true in main.tf. README examples use var.github_token, data.coder_external_auth.github.access_token, and module.aibridge-proxy.proxy_auth_url—no inline literal or placeholder secrets.
Non-hardcoded auth path 4 4 Two documented non-hardcoded paths: (1) Coder external auth via data "coder_external_auth" "github", and (2) AI Gateway Proxy via the aibridge-proxy module. Both avoid pasting raw keys into templates.

Restricted-Environment Readiness — 6 / 20

Criterion Max Score Notes
Mirrorable artifact source 5 0 The install script hardcodes https://gh.io/copilot-install. No module input variable overrides this download URL. copilot_version pins the version but does not change the source URL.
Bring-your-own binary 10 5 install_copilot = false skips the download and validates an existing copilot on PATH (install.sh.tftpl lines 79–85). The variable is defined in main.tf with a description, but the README has no section or example documenting this "already baked into the image" path. Implemented but under-documented → half.
Egress transparency 3 0 No dedicated README section enumerating external endpoints (e.g., gh.io, AI Gateway proxy URL). Endpoints are only visible in the install script source and the AI Gateway example.
Runs without sudo 2 1 write_managed_settings() invokes sudo to write to /etc/github-copilot/ but includes a non-sudo fallback (else branch). Sudo is used only for the optional managed-settings feature with a working fallback → half. All other script functions (install, workdir, base config, trusted folders, MCP) run without sudo.

Engineering Quality — 10 / 10

Criterion Max Score Notes
Input quality 6 6 All 14 variables have type and description. Sensible defaults (install_copilot = true, copilot_version = "latest", workdir = null). enable_ai_gateway has two validation blocks enforcing required companion variables. github_token and ai_gateway_proxy_auth_url are marked sensitive.
Test coverage 4 4 main.tftest.hcl (12 test runs) covers defaults, env-var creation/absence, workdir trimming, script output ordering, AI Gateway proxy env vars, and validation failures. main.test.ts (9 tests) covers end-to-end behavior: install skip, workdir trust, trusted-folders union, base-config overwrite, managed-settings write/absence, MCP server write/merge, and token env var. Clear separation of plan-level and container-level tests.

Overall — 68 / 100

Raw 63 / 92 → round(63 / 92 × 100) = 68

Tip

You can run this locally by telling your agent: "review this module against .github/scorecard/SCORECARD.md".


Scored against SCORECARD.md with solstice-1. Language-model scores are advisory.

Drop the enable_ai_gateway variable, its validation, and the COPILOT_PROVIDER_* env resources, along with the now-unused coder_workspace/coder_workspace_owner data sources. Update README, variable docs, and tests accordingly.

Generated with Coder Agents.
…existing entries winning

Always merge mcp_config into ~/.copilot/mcp-config.json via jq; on duplicate server names the existing on-disk entry takes precedence. Require jq (drop the verbatim-overwrite fallback) and add a test that seeds a conflicting server.

Generated with Coder Agents.
…nfig and mcp merges

Make module inputs authoritative for the keys/servers the module owns while preserving runtime state:

- config.json: module keys win, trusted_folders is a union of existing and module lists, other on-disk keys (model, reasoning_effort, ...) are preserved.
- mcp-config.json: module-provided servers win on duplicate names; unrelated on-disk servers are preserved.
- Route mcpServers from copilot_config into mcp-config.json (mcp_config wins); never write mcpServers into config.json.
- Update variable docs, README, and tests.

Generated with Coder Agents.
…rvers routing from config

config.json has no mcpServers key (Copilot reads MCP only from mcp-config.json), so a well-formed copilot_config never carries it. Remove the strip/route handling: copilot_config feeds config.json as-is, mcp_config feeds mcp-config.json.

Generated with Coder Agents.
… ai_gateway

Renames the pre-v1 enable_aibridge_proxy feature to ai_gateway. Sets HTTPS_PROXY and NODE_EXTRA_CA_CERTS via agent-level coder_env with variable validation, plus tests and README docs.
…e-tasks

# Conflicts:
#	registry/coder-labs/modules/copilot/README.md
#	registry/coder-labs/modules/copilot/copilot.tftest.hcl
#	registry/coder-labs/modules/copilot/main.tf
#	registry/coder-labs/modules/copilot/scripts/install.sh
#	registry/coder-labs/modules/copilot/scripts/start.sh
…nd align with claude-code

Replace copilot_settings/copilot_config with a managed_settings policy input written to /etc/github-copilot/managed-settings.json, keep workdir auto-trust, make MCP merge existing-wins, and rename mcp_config to mcp for claude-code parity.
…g model' call

'copilot config' is not a command; the model is set via the COPILOT_MODEL env var. Remove the dead configure_copilot_model function and the now-unused ARG_COPILOT_MODEL script argument.
@35C4n0r 35C4n0r self-assigned this Sep 27, 2026
@35C4n0r
35C4n0r marked this pull request as ready for review September 27, 2026 18:10
Comment thread registry/coder-labs/modules/copilot/main.tf Outdated
Comment thread registry/coder-labs/modules/copilot/main.tf Outdated
Comment thread registry/coder-labs/modules/copilot/main.tf Outdated
Use /icon/github-copilot.svg default and rename ai_gateway_auth_url to
ai_gateway_proxy_auth_url and ai_gateway_cert_path to
ai_gateway_proxy_cert_path.
@linear-code

linear-code Bot commented Oct 7, 2026

Copy link
Copy Markdown

REG-83

@matifali
matifali self-requested a review October 7, 2026 13:38
Restore copilot_config as base_copilot_config. When set it overwrites ~/.copilot/settings.json, the current user settings file, on every start. MCP servers stay in mcp-config.json.
@coder

coder Bot commented Oct 14, 2026

Copy link
Copy Markdown
Contributor

Automated review requested by @matifali. Please sanity-check before acting on it.

CI and existing reviews

  • CI on the head sha is green: TS tests, Terraform tests, validate, ShellCheck, set -u ordering, fmt/typos, README validation, lint and golangci-lint all passed. The Compare module scores against main check run still shows in_progress, but the Module Scorecard Check workflow finished (68/100).
  • matifali's 3 suggestions (icon default, rename to ai_gateway_proxy_auth_url / _cert_path) were applied in 1874ad9. Nothing is left unresolved.

Correctness

The Terraform is coherent: there are no dangling variable references, task_app_id was removed, and a scripts output was added. The flow is coder-utils pre_install → install → post_install.

[BLOCKER] The install script wipes ~/.copilot/config.json (auth and plugin state) on restart
scripts/install.sh.tftpl:193-198:

local existing='{}'
if [ -f "$${config_file}" ] && jq empty "$${config_file}" > /dev/null 2>&1; then
  existing=$(cat "$${config_file}")
fi
echo "$${existing}" | jq ... '.trustedFolders = ...' > "$${config_file}"

Since Copilot CLI 1.0.35, config.json starts with two // comment lines (the file is JSONC). jq rejects the comments, so the script falls back to {} and overwrites the file with only trustedFolders. GitHub's docs say config.json holds authentication and plugin state, and deleting it "Resets application state including authentication" (docs). On a persistent home, every start after Copilot's first run logs the user out and drops plugins.

setup_mcp_config (lines 214-216) already handles JSONC by skipping, so the two functions are inconsistent.

Fix: strip the comment header before parsing, never fall back to {}, and write atomically with mode 0600:

local existing='{}'
if [ -f "$${config_file}" ]; then
  if ! existing=$(sed -E '/^[[:space:]]*\/\//d' "$${config_file}" | jq -c .); then
    echo "Warning: could not parse $${config_file}; skipping workdir trust" >&2; return
  fi
fi
local tmp; tmp=$(mktemp "$${config_file}.XXXXXX"); chmod 600 "$${tmp}"
echo "$${existing}" | jq --argjson folders "$${ARG_TRUSTED_FOLDERS}" \
  '.trustedFolders = (((.trustedFolders // []) + $folders) | unique)' > "$${tmp}" && mv "$${tmp}" "$${config_file}"

Also add a test that seeds the // header plus a copilotTokens key. The current test (main.test.ts:214-233) seeds plain JSON, so it misses this. The camelCase trustedFolders key itself is correct.

[SHOULD-FIX] enable_ai_gateway sets HTTPS_PROXY / NODE_EXTRA_CA_CERTS for the whole workspace
main.tf:126-140 uses coder_env, so every process inherits these: git, npm, curl, other agents, and other modules' scripts. v0 scoped them to the Copilot process. The aibridge-proxy README says that module "does not set proxy environment variables globally" and recommends tool modules "scope the proxy environment variables to their own process". As written, the credential-bearing proxy URL goes out with all HTTPS traffic, and workspace egress depends on the proxy being up. The only acknowledgement is a code comment; the README says nothing.

Fix: remove these coder_envs. Instead, ship a copilot wrapper in $CODER_SCRIPT_BIN_DIR that exports the variables and execs the real binary, or show HTTPS_PROXY=... NODE_EXTRA_CA_CERTS=... exec copilot in the README coder_app. If the global behaviour is intentional, add a README warning.

Follow-up: registry/coder/modules/aibridge-proxy/README.md still cites Copilot as its integration and startup-coordination example, and nothing waits for the aibridge-proxy sync any more.

[SHOULD-FIX] The stale task-reporting coder MCP server survives the upgrade
v0 wrote mcpServers.coder into ~/.copilot/mcp-config.json, pointing at /tmp/coder-mcp-server.sh (which ran coder exp mcp server with CODER_MCP_APP_STATUS_SLUG). v1's merge lets existing entries win (install.sh.tftpl:218), so the entry stays, and Copilot tries to start a missing script on every launch.

Fix: jq 'if .mcpServers.coder.command == "/tmp/coder-mcp-server.sh" then del(.mcpServers.coder) else . end', and/or a migration note.

[SHOULD-FIX] GitHub external-auth regression
v0 fetched coder external-auth access-token ${external_auth_id} at launch (old start.sh:102-105). The v1 README (README.md:36-46) passes data.coder_external_auth.github.access_token, which is fixed at build time, so expiring GitHub App user tokens (8h) go stale. Without optional = true it also makes external auth mandatory.

Fix: export COPILOT_GITHUB_TOKEN="$(coder external-auth access-token github)" in the launcher command, or keep external_auth_id and use a wrapper.

Leftovers

  • None remain in main.tf, the script or the README: no report_tasks, agentapi module, coder_ai_task, CODER_MCP_*, 3284, coder exp mcp, ai_prompt or system_prompt.
  • [NIT] main.test.ts:21 imports from ../../../coder/modules/agentapi/test-util. claude-code and codex on main do the same. This breaks once the agentapi module is deleted, so move test-util into the shared test/ helpers (series follow-up).
  • The stale coder MCP entry is covered above. ~/.copilot-module/ and the old snake_case keys in config.json are harmless.

Breaking changes and migration

  • The major bump is correct.
  • [SHOULD-FIX] The migration notes are thin. The README warning (README.md:22-23) only mentions Tasks/AgentAPI and copilot_config. Unlike the claude-code and codex v5 READMEs, it has no "keep using v0.x" line and no link to a migration guide, and the PR body has no old→new mapping. Missing items:
    • Removed: external_auth_id, ai_prompt, system_prompt, report_tasks, install_agentapi, agentapi_version, subdomain, order, group, web_app_display_name, cli_app, cli_app_display_name, resume_session, trusted_directories.
    • Now launcher flags: allow_all_tools, allow_tools, deny_tools.
    • Renamed: mcp_config→mcp; enable_aibridge_proxy/aibridge_proxy_*→enable_ai_gateway/ai_gateway_proxy_*; copilot_config→base_copilot_config. The last one used to be merged into config.json and now overwrites settings.json on every start.
    • workdir is now optional, and the task_app_id output is removed.
    • Behaviour: GITHUB_TOKEN/GH_TOKEN became COPILOT_GITHUB_TOKEN only (affects gh users). The copilot_model default changed from claude-sonnet-4.5 to "". Install moved from npm to the official installer.
  • [SHOULD-FIX] The PR body contradicts the code. It claims GITHUB_TOKEN + GH_TOKEN, but the code sets only COPILOT_GITHUB_TOKEN (main.tf:119-124). It claims "Copilot BYOK provider env vars", but the code sets HTTPS_PROXY/NODE_EXTRA_CA_CERTS. The PR template is unfilled (breaking-change box unchecked, placeholder path/version).
  • [NIT] The title is feat(...) without !. refactor(registry/coder-labs/modules/cursor-cli)!: remove agentapi, tasks and start logic #1152 uses refactor(...)!:.
  • [NIT] trusted_directories was dropped with no replacement, and base_copilot_config can't cover it because trustedFolders lives in config.json. Keeping it is cheap: concat([local.workdir], var.trusted_directories).

Tests

  • copilot.tftest.hcl was renamed to main.tftest.hcl (13 runs: defaults, token/model env, workdir trim/trust/optional, scripts ordering, AI gateway env and validations). main.test.ts was rewritten (10 container tests: skip install, trust union, base config overwrite, managed settings, MCP write/merge, token env). These are real rewrites, not deletions.
  • Gaps:

Other nits

  • install.sh.tftpl:152-160: without sudo, a non-root user fails on mkdir /etc/github-copilot under set -e, and the whole install fails. Use sudo -n, check id -u, and print a warning. claude-code has the same pattern, so this could be a series-wide fix.
  • install.sh.tftpl:108-112: a pinned copilot_version is ignored when copilot is already on PATH, and install-script installs auto-update. Document this.
  • ensure_copilot_in_path doesn't run copilot --version; cursor-cli does.
  • testdata/copilot-mock.sh:1 uses #!/bin/bash; AGENTS.md requires #!/usr/bin/env bash.
  • Here enable_ai_gateway means the AI Gateway Proxy, but in claude-code and codex it means the direct base URL. Consider enable_ai_gateway_proxy.
  • claude-code and codex have mcp_config_remote_path; neither of these PRs adds it.
  • The README advanced example runs npm install in pre_install_script, but Node is no longer guaranteed. Say it's required.
  • The AI footer doesn't name the model (AGENTS.md checklist).

Comment thread registry/coder-labs/modules/copilot/main.tf
…as configuring Copilot

install_copilot can be false, in which case the module only configures Copilot.
…rusting workdir

Copilot writes config.json with a // comment header, which jq rejected, so
the script fell back to {} and overwrote auth and plugin state on every start.
Strip comments before parsing, skip when the workdir is already trusted or the
file cannot be parsed, and write atomically with mode 0600.
@DevelopmentCats
DevelopmentCats merged commit 2689268 into main Oct 14, 2026
5 checks passed
@DevelopmentCats
DevelopmentCats deleted the 35C4n0r/copilot-remove-tasks branch October 14, 2026 21:08
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.

3 participants