Files
copilotkit__copilotkit/lefthook.yml
T

131 lines
5.7 KiB
YAML
Raw Normal View History

2026-03-02 14:59:16 +01:00
output:
- meta
- summary
- success
- failure
- execution
- execution_out
- execution_info
- skips
pre-commit:
2026-03-02 16:41:23 +01:00
parallel: true
commands:
check-binaries:
tags: binaries
run: bash scripts/hooks/check-binaries.sh
sync-promote-dropdown:
tags: promote-dropdown
# Regenerate the showcase_promote.yml `service` dropdown from the
# railway-envs.ts SSOT and re-stage it so the option list can never
# drift from the set of promotable services. Plain regenerate + git add
# (no stash) — keep this hook worktree-safe; lefthook's shared
# refs/stash is not safe across concurrent worktree commits.
2026-06-02 19:51:29 +00:00
glob: "{showcase/scripts/railway-envs.ts,showcase/scripts/sync-promote-service-options.ts,.github/workflows/showcase_promote.yml}"
run: |
set -euo pipefail
pnpm exec tsx showcase/scripts/sync-promote-service-options.ts \
&& git add .github/workflows/showcase_promote.yml
sync-lockfile:
tags: lockfile
glob: "{packages,examples,showcase/scripts}/**/package.json"
run: pnpm i --lockfile-only
stage_fixed: true
lint-fix:
2026-03-02 15:56:37 +01:00
tags: lint
# Scope oxlint and oxfmt to just the files staged for commit — running
# `--fix .` / `--write .` across the whole monorepo on every commit is
# both slow and blurs the hook's purpose (touch files that aren't part
# of this change). Guard against empty `{staged_files}` expansion: when
# a commit touches only non-matching files (markdown, YAML), lefthook
# still invokes this hook with an empty expansion, and oxlint/oxfmt
# would default to operating on the current directory, defeating the
# scoping entirely. stage_fixed re-stages whatever the hooks modify.
fix(lefthook): exclude json/jsonc/json5 from oxlint/oxfmt to prevent JSON5 mangling The lint-fix pre-commit step runs `oxlint --fix` + `oxfmt --write` over staged files. When `package.json` is part of the staged set, oxfmt rewrites the file into JSON5 syntax (4-space indent, trailing commas after the last key in every object, compacted single-line objects). The result is invalid strict JSON that pnpm rejects with `ERR_PNPM_JSON_PARSE` at line 8 column 5, blocking every commit that touches any `package.json`. This was bypassed in PRs #5054 and #5055 via `LEFTHOOK_EXCLUDE=lint-fix`; this commit fixes it at the source by removing `json,jsonc,json5` from the lint-fix glob. Reproduction (with the buggy glob): - Apply PR #5055's edit to packages/voice/package.json - git add + run `lefthook run pre-commit --command lint-fix` - oxfmt logs "1 file reformatted" - JSON.parse / pnpm install now fail on the rewritten file After the fix: - JSON-only staged sets cause lefthook to skip lint-fix ("no files for inspection") rather than mangle the JSON - TS/JS/etc. continue to flow through oxlint --fix + oxfmt --write unchanged - JSON formatting is left to pnpm and manual editing, both of which produce strict 2-space JSON oxfmt 0.36.0 exposes no per-file-type knob (printWidth/proseWrap/ ignorePatterns only); excluding json/jsonc/json5 from the glob is the minimal correct fix. A future oxfmt upgrade that ships a json formatter configurable via `.oxfmtrc.json` can re-add these extensions. This commit itself is being landed with `LEFTHOOK_EXCLUDE=lint-fix` because the bug being fixed currently blocks any path that exercises the lint-fix hook. The change touches only `lefthook.yml`, which is not a JSON file and would not be mangled — the exclude is purely defensive.
2026-05-27 13:49:31 -07:00
# Intentionally excludes json/jsonc/json5: oxfmt --write rewrites JSON
# files into JSON5 syntax (4-space indent, trailing commas, compact
# objects) when invoked via lefthook with staged file paths. The result
# is invalid strict JSON that pnpm rejects with ERR_PNPM_JSON_PARSE,
# blocking every commit that touches a package.json (see PRs #5054,
# #5055). JSON formatting is owned by pnpm/manual editing; oxfmt has
# no per-file knobs to keep package.json valid, so the only safe fix
# is to keep .json* out of this hook entirely.
glob: "*.{js,jsx,ts,tsx,mjs,cjs,md,css,yml,yaml,html,vue,py}"
2026-06-18 10:54:16 -07:00
# Mirror the generated-data ignorePatterns in .oxlintrc.json /
# .oxfmtrc.json at the hook layer.
exclude:
- "showcase/aimock/shared/**"
- "showcase/aimock/d4/**"
- "showcase/aimock/d6/**"
# Use `set --` so the staged files become positional args; this is the
# only shell-portable way to test "are there any" without breaking on
# multi-file expansion. The old `[ -n "{staged_files}" ]` form failed
# with `sh: 1: [: <path>: unexpected operator` because lefthook
# interpolates the file list as space-separated words, not a single
# quoted string, so [ saw 3+ args and tried to parse a binary op.
# IMPORTANT: keep this script DOUBLE-QUOTE-FREE. lefthook invokes a
# multi-line `run` as `sh -c "<script>"` and (in some versions / on
# Windows git-sh) does not escape embedded double quotes, so any `"$@"`
# / `[ "$#" ]` / `x=""` prematurely closes the `-c "…"` string and the
# shell aborts with `unexpected EOF`. Use unquoted `$@`/`$#` — staged
# paths in this monorepo never contain spaces. JSON is excluded from the
# glob above, so oxfmt never receives package.json (the old explicit
# package.json filter is unnecessary). ruff is scoped to .py via `case`.
run: |
2026-06-18 10:54:16 -07:00
files=
for f in {staged_files}; do
[ -f $f ] && files=$files' '$f
done
set -- $files
if [ $# -gt 0 ]; then
pnpm exec oxlint --fix $@
pnpm exec oxfmt --write $@
for f in $@; do
case $f in *.py) ruff format $f 2>/dev/null || true ;; esac
done
fi
stage_fixed: true
2026-03-02 16:09:55 +01:00
test-and-check-packages:
tags: test-packages
env:
NX_TUI: "false"
2026-06-01 16:28:19 +02:00
run: |
2026-06-18 10:54:16 -07:00
files=
for f in {staged_files}; do
case $f in
packages/*|package.json|pnpm-lock.yaml|pnpm-workspace.yaml|nx.json|tsconfig*.json) files=$files' '$f ;;
esac
done
set -- $files
2026-06-01 16:28:19 +02:00
if [ "$#" -gt 0 ]; then
projects=$(printf '%s\n' "$@" | pnpm nx show projects --affected --projects 'packages/*' --stdin --sep=,)
if [ -n "$projects" ]; then
pnpm nx run-many -t test,publint,attw --projects="$projects" --outputStyle=static
fi
fi
fix(runtime): unify the Intelligence key name and publish the wiring (refs OSS-881) Three names for one value were live in CopilotKit's own documentation, and following the wrong one with a CLI-provisioned project yields an undefined key: - `INTELLIGENCE_API_KEY` — what `copilotkit project select` writes, used by all 34 integration examples and the docs site. - `COPILOTKIT_INTELLIGENCE_API_KEY` — the seven Channels package READMEs and the packaged skills. Nothing ever read it. - `COPILOTKIT_API_KEY` — the Slack and Teams examples, and the TSDoc on `CopilotKitIntelligence` itself, which is what an IDE shows on hover. `INTELLIGENCE_API_KEY` wins, because it is the name the CLI provisions and changing it would break every scaffolded project in the wild. `COPILOTKIT_INTELLIGENCE_API_KEY` is retired outright — no code read it. `COPILOTKIT_API_KEY` stays readable as a deprecated alias in the two examples that consume it, so an existing `.env` keeps working, and is documented as deprecated everywhere it appears. The skills reference also documented `organizationId`, sourced from a fourth and fifth env name, as a `CopilotKitIntelligence` option. It is not one: `CopilotKitIntelligenceConfig` has no such field, so the copy-pasteable sample it appeared in would not compile. Removed from the samples, and the prose that told readers to fetch a value for it corrected. The Intelligence wiring itself was published only inside `node_modules/@copilotkit/runtime/skills/`, and the only docs pages showing `CopilotKitIntelligence` were the two Channels frontends — so a developer on the plain web path had no page to reach it from. Adds `/premium/connect-your-runtime`, which covers the wiring, how to confirm the credential is actually consumed, and the self-hosted two-URL rule. `scripts/validate-intelligence-env-names.ts` keeps this from drifting back. It runs unfiltered in CI on purpose: the two workflows that would otherwise cover it filter paths, and static/quality ignores `examples/**` — exactly where the deprecated alias lives.
2026-08-19 17:50:09 -05:00
check-intelligence-env-names:
tags: intelligence-env-names
fix(docs): stop shipping stale Intelligence config claims, and gate the dead hosts (refs OSS-961) The packaged runtime skill up to v1.62.2 prescribed `api.copilotkit.ai` / `realtime.copilotkit.ai`. The first host is a CNAME onto the legacy Copilot Cloud ALB, where no listener rule matches it, so every request gets the ALB default action: a 404 with an empty body. The second has no DNS record at all. A reader who followed that page converted a working OSS install into a 502. The hosts themselves were corrected in v1.64.0, but two shipped surfaces still carried stale claims about the same step, and nothing stopped the hosts from coming back a third time: - The debug skill said Intelligence "requires ... `apiUrl`, `wsUrl`, `apiKey`, `tenantId`". Three errors in one line: `apiUrl`/`wsUrl` have been optional with managed defaults since v1.64.0, and `tenantId` has never existed on `CopilotKitIntelligenceConfig` — the API key carries the project (its token format is `cpk-{projectId}_...`) and the platform resolves the organization server-side, so there is no org or tenant field for a caller to pass. - `CopilotKitIntelligence`'s own TSDoc showed only `*.internal` placeholders, so the class's hover docs never named the pair that actually serves prod. `validate-intelligence-env-names` — already the unfiltered guard for this same config surface (OSS-881) — now also fails on either dead host. The channels-intelligence realtime test is allowlisted: it needs a hostname that genuinely does not resolve, since `getaddrinfo ENOTFOUND` is the condition under test. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-25 15:35:55 -05:00
# No glob: a retired name or a dead host can reappear in any doc, README,
# example, or skill, so this runs on every commit rather than a path subset.
fix(runtime): unify the Intelligence key name and publish the wiring (refs OSS-881) Three names for one value were live in CopilotKit's own documentation, and following the wrong one with a CLI-provisioned project yields an undefined key: - `INTELLIGENCE_API_KEY` — what `copilotkit project select` writes, used by all 34 integration examples and the docs site. - `COPILOTKIT_INTELLIGENCE_API_KEY` — the seven Channels package READMEs and the packaged skills. Nothing ever read it. - `COPILOTKIT_API_KEY` — the Slack and Teams examples, and the TSDoc on `CopilotKitIntelligence` itself, which is what an IDE shows on hover. `INTELLIGENCE_API_KEY` wins, because it is the name the CLI provisions and changing it would break every scaffolded project in the wild. `COPILOTKIT_INTELLIGENCE_API_KEY` is retired outright — no code read it. `COPILOTKIT_API_KEY` stays readable as a deprecated alias in the two examples that consume it, so an existing `.env` keeps working, and is documented as deprecated everywhere it appears. The skills reference also documented `organizationId`, sourced from a fourth and fifth env name, as a `CopilotKitIntelligence` option. It is not one: `CopilotKitIntelligenceConfig` has no such field, so the copy-pasteable sample it appeared in would not compile. Removed from the samples, and the prose that told readers to fetch a value for it corrected. The Intelligence wiring itself was published only inside `node_modules/@copilotkit/runtime/skills/`, and the only docs pages showing `CopilotKitIntelligence` were the two Channels frontends — so a developer on the plain web path had no page to reach it from. Adds `/premium/connect-your-runtime`, which covers the wiring, how to confirm the credential is actually consumed, and the self-hosted two-URL rule. `scripts/validate-intelligence-env-names.ts` keeps this from drifting back. It runs unfiltered in CI on purpose: the two workflows that would otherwise cover it filter paths, and static/quality ignores `examples/**` — exactly where the deprecated alias lives.
2026-08-19 17:50:09 -05:00
run: pnpm check:intelligence-env-names
fail_text: |
fix(docs): stop shipping stale Intelligence config claims, and gate the dead hosts (refs OSS-961) The packaged runtime skill up to v1.62.2 prescribed `api.copilotkit.ai` / `realtime.copilotkit.ai`. The first host is a CNAME onto the legacy Copilot Cloud ALB, where no listener rule matches it, so every request gets the ALB default action: a 404 with an empty body. The second has no DNS record at all. A reader who followed that page converted a working OSS install into a 502. The hosts themselves were corrected in v1.64.0, but two shipped surfaces still carried stale claims about the same step, and nothing stopped the hosts from coming back a third time: - The debug skill said Intelligence "requires ... `apiUrl`, `wsUrl`, `apiKey`, `tenantId`". Three errors in one line: `apiUrl`/`wsUrl` have been optional with managed defaults since v1.64.0, and `tenantId` has never existed on `CopilotKitIntelligenceConfig` — the API key carries the project (its token format is `cpk-{projectId}_...`) and the platform resolves the organization server-side, so there is no org or tenant field for a caller to pass. - `CopilotKitIntelligence`'s own TSDoc showed only `*.internal` placeholders, so the class's hover docs never named the pair that actually serves prod. `validate-intelligence-env-names` — already the unfiltered guard for this same config surface (OSS-881) — now also fails on either dead host. The channels-intelligence realtime test is allowlisted: it needs a hostname that genuinely does not resolve, since `getaddrinfo ENOTFOUND` is the condition under test. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-25 15:35:55 -05:00
A non-canonical Intelligence env var name or hostname was found.
The canonical name is CPK_INTELLIGENCE_API_KEY; the canonical hosts are
fix(docs): stop shipping stale Intelligence config claims, and gate the dead hosts (refs OSS-961) The packaged runtime skill up to v1.62.2 prescribed `api.copilotkit.ai` / `realtime.copilotkit.ai`. The first host is a CNAME onto the legacy Copilot Cloud ALB, where no listener rule matches it, so every request gets the ALB default action: a 404 with an empty body. The second has no DNS record at all. A reader who followed that page converted a working OSS install into a 502. The hosts themselves were corrected in v1.64.0, but two shipped surfaces still carried stale claims about the same step, and nothing stopped the hosts from coming back a third time: - The debug skill said Intelligence "requires ... `apiUrl`, `wsUrl`, `apiKey`, `tenantId`". Three errors in one line: `apiUrl`/`wsUrl` have been optional with managed defaults since v1.64.0, and `tenantId` has never existed on `CopilotKitIntelligenceConfig` — the API key carries the project (its token format is `cpk-{projectId}_...`) and the platform resolves the organization server-side, so there is no org or tenant field for a caller to pass. - `CopilotKitIntelligence`'s own TSDoc showed only `*.internal` placeholders, so the class's hover docs never named the pair that actually serves prod. `validate-intelligence-env-names` — already the unfiltered guard for this same config surface (OSS-881) — now also fails on either dead host. The channels-intelligence realtime test is allowlisted: it needs a hostname that genuinely does not resolve, since `getaddrinfo ENOTFOUND` is the condition under test. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-25 15:35:55 -05:00
api.intelligence.copilotkit.ai and realtime.intelligence.copilotkit.ai.
See scripts/validate-intelligence-env-names.ts for the allowlists.
fix(runtime): unify the Intelligence key name and publish the wiring (refs OSS-881) Three names for one value were live in CopilotKit's own documentation, and following the wrong one with a CLI-provisioned project yields an undefined key: - `INTELLIGENCE_API_KEY` — what `copilotkit project select` writes, used by all 34 integration examples and the docs site. - `COPILOTKIT_INTELLIGENCE_API_KEY` — the seven Channels package READMEs and the packaged skills. Nothing ever read it. - `COPILOTKIT_API_KEY` — the Slack and Teams examples, and the TSDoc on `CopilotKitIntelligence` itself, which is what an IDE shows on hover. `INTELLIGENCE_API_KEY` wins, because it is the name the CLI provisions and changing it would break every scaffolded project in the wild. `COPILOTKIT_INTELLIGENCE_API_KEY` is retired outright — no code read it. `COPILOTKIT_API_KEY` stays readable as a deprecated alias in the two examples that consume it, so an existing `.env` keeps working, and is documented as deprecated everywhere it appears. The skills reference also documented `organizationId`, sourced from a fourth and fifth env name, as a `CopilotKitIntelligence` option. It is not one: `CopilotKitIntelligenceConfig` has no such field, so the copy-pasteable sample it appeared in would not compile. Removed from the samples, and the prose that told readers to fetch a value for it corrected. The Intelligence wiring itself was published only inside `node_modules/@copilotkit/runtime/skills/`, and the only docs pages showing `CopilotKitIntelligence` were the two Channels frontends — so a developer on the plain web path had no page to reach it from. Adds `/premium/connect-your-runtime`, which covers the wiring, how to confirm the credential is actually consumed, and the self-hosted two-URL rule. `scripts/validate-intelligence-env-names.ts` keeps this from drifting back. It runs unfiltered in CI on purpose: the two workflows that would otherwise cover it filter paths, and static/quality ignores `examples/**` — exactly where the deprecated alias lives.
2026-08-19 17:50:09 -05:00
check-plugin-skills:
tags: plugin-skills
fix(skills): correct claims the audit found wrong in the two entry points Verified every factual claim in both new skills against the current source rather than against my own draft. Six were wrong or incomplete. `copilotkit`: - The MCP server does not arrive with the skills. `.mcp.json` lives at the repository root, outside `skills/`, so a `npx skills add` install — which is what /build-with-agents tells a reader to run — registered no server, and the skill said "Nothing to do". It now gives the `claude mcp add` and `codex mcp add` commands, which is what the docs' own MCP page does. - The Codex block named a project-local `.codex/config.toml` and a `type` key that the documented configuration does not use. - "eleven things" was the ceiling, not the count. `frontendAssetChecks`, `corsChecks` and `packageVersionChecks` each return an empty list when nothing could be read, so an Intelligence-mode run settles eight to eleven, and `--expect-runtime oss` is a smaller set again. - Dropped the claim that a v1/v2 import mismatch "shows up as routes that 404". The subpaths and the still-resolving package root are verified in the exports; that specific symptom was not, and this skill's whole premise is not to state unverified API detail. `copilotkit-cli`: - `login --json` was missing. It is the flag that streams agent-readable JSON without launching a browser, so it is the one a coding agent needs, and this skill exists for coding agents. - `create` was described as the canonical command with `init` as its alias. The CLI's own help has it the other way round. - Added the provenance verdict rule, which is the actionable half of the feature the skill already praised: nothing answering at a URL the project named is a FAIL, nothing answering at an assumed default is UNKNOWN. - Added `--runtime-url`, `--header` and `--timeout`, the `--expect-runtime oss` exit-zero condition, and a `skills install` row — the command the README tells readers to run. - Replaced "it does not detect or convert an app you already have" with what is supported, since I never proved that absence. Claims that checked out and are unchanged: the four corpora and their boundaries (the tool descriptions state "library/package source only — NOT example or showcase apps"), the round trip sending `tools: []` and `context: []` ("Deliberately trivial and answerable without tools or context"), `whoami` printing the organization, `project select` writing `CPK_INTELLIGENCE_API_KEY` to `.env`, `import --dry-run`, both telemetry opt-out variables, and all 21 docs links, each of which returns 200 live. Also fixes the `check-plugin-skills` glob in `lefthook.yml`, which still enumerated `skills/runtime/**`, `skills/react-core/**` and `skills/a2ui-renderer/**`. All three are deleted, so editing either new skill triggered no local mirror check. `plugin-skills-check.yml` already uses `skills/**` and carries a comment about this exact mistake. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-10 11:34:39 -05:00
glob: "{packages/*/skills/**,skills/**,scripts/sync-plugin-skills.ts,.claude-plugin/**,packages/runtime/package.json}"
run: pnpm check:plugin-skills
fail_text: |
Plugin skill mirror is out of sync with the Intent source.
Run: pnpm sync:plugin-skills
Then stage the changes and re-commit.
commit-msg:
commands:
commitlint:
2026-03-02 15:56:37 +01:00
tags: commitlint
run: pnpm commitlint --edit {1}