Skip to content

feat(providers): add CNB (cnb.cool) git provider#208

Merged
jeff-r2026 merged 1 commit into
Tencent:mainfrom
Eyre921:feat/cnb-provider
Jul 21, 2026
Merged

feat(providers): add CNB (cnb.cool) git provider#208
jeff-r2026 merged 1 commit into
Tencent:mainfrom
Eyre921:feat/cnb-provider

Conversation

@Eyre921

@Eyre921 Eyre921 commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds a third GitProviderCNB (cnb.cool) — alongside github and tgit, using the exact "thin class over a platform CLI" shape the TGit provider established. CNB's official CLI (@cnbcool/cnb-cli) already exposes everything the GitProvider interface needs, so this is mostly mechanical mirroring of the existing pattern.

A question for maintainers, up front: a provider is a permanent maintenance surface (every future interface change now lands in three providers). I'm opening this as a complete, live-tested implementation so the accept/decline decision is concrete rather than hypothetical — but if you'd rather not carry a CNB provider, feel free to close and I'll keep it in my fork. CNB is a Tencent-adjacent platform, so it may or may not be in scope for you.

Type of Change

  • New feature (non-breaking change that adds functionality)

How each interface method maps to the CNB CLI

GitProvider CNB CLI
authenticate / isAuthenticated cnb login (OAuth2 device flow) + cnb status
cloneRepo git clone with token, or cnb git-credential helper
createPullRequest cnb pulls post-pull
createRepo cnb repositories create-repo
username cnb users get-user-info (or CNB_USERNAME)

Auth mirrors the GitHub provider's dual path: interactive cnb login on a dev machine, or a CNB_TOKEN env var for headless/CI use (no login step) — the same idea as GITHUB_TOKEN.

Wiring: registry.ts maps the cnb.cool host to the provider and registers it in the factory. No behavior changes for existing providers. (Scoped to cnb.cool only; the internal cnb.woa.com mirror is a feasible future add but is untested and intentionally left out — see the scope-down comment below.)

Test Plan

  • npx tsc --noEmit, npm run build
  • npx vitest run — 142 files, 1751 tests; 6 new in cnb-provider.test.ts (host detection, factory, repo-input parsing incl. nested group paths)
  • Live end-to-end against real cnb.cool (token in env), driving the wrapper functions: createRepo → cloneRepo → push main + feature → createPullRequest → delete-repo cleanup. The PR URL came back https://cnb.cool/<owner>/<repo>/-/pulls/1.

Two bugs the live run surfaced (and this PR fixes) — build alone didn't catch them:

  • cnbWhoami() returned the CNB_USERNAME credential placeholder ("cnb") instead of the real account; now parses username: from the API first.
  • the CLI prints YAML, not JSON, so username / PR-URL parsing is regex-based rather than JSON.parse.

Notes for Reviewers

  • The live E2E is intentionally not committed as a CI test: it needs a CNB_TOKEN secret and creates/deletes a real repo. Only the pure unit tests run in CI. Happy to add a gated e2e test (behind CNB_TOKEN, self-cleaning) if you want one in the suite.
  • No new runtime dependency — the provider shells out to the cnb CLI, exactly as tgit shells out to gf. ensureInstalled() installs it via npm i -g @cnbcool/cnb-cli when missing.
  • getDefaultProvider() is untouched: CNB is only selected by explicit cnb.cool host, never as a fallback.

@Eyre921
Eyre921 force-pushed the feat/cnb-provider branch from d65f445 to 1273c83 Compare July 18, 2026 10:47
@jeff-r2026

Copy link
Copy Markdown
Collaborator

Thanks for the thorough implementation and the live-tested E2E — the spawnSync-with-args design, the assertCnbApiOk guard for the "CLI exits 0 but API returned 4xx" case, and the cnbWhoami API-first parsing are all solid.

One blocker before this can merge, per our docs-sync convention (see CLAUDE.md): adding a user-selectable provider is an observable behavior change, so the docs need to be updated in the same PR. Right now the PR touches no documentation. Please update:

  • docs/providers.md — add a cnb row to the platform table (host cnb.cool / cnb.woa.com, auth via cnb login or CNB_TOKEN), and add the detection rules (https://cnb.cool/o/r → cnb, git@cnb.cool:o/r.git → cnb).
  • docs/usage-guide.md — the provider: field in the teamai.yaml section currently only documents github/tgit; please mention cnb as a valid value.
  • Keep the bilingual pair in sync: mirror the same changes into docs/usage-guide.zh-CN.md (and any zh-CN counterpart of providers.md if one exists).

While updating the guide, please also call out the current capability gap: fetchMergeRequest and listOrgRepos are not implemented for CNB, so a CNB repo can be cloned / created / opened-as-PR but can't yet drive teamai ci extract-mr or org-repo listing. Documenting this avoids users assuming CNB is at full parity with tgit.

The accept/decline call on carrying a third provider is for the maintainers, but getting the docs in now makes it a complete, mergeable PR either way. Thanks!

@Eyre921
Eyre921 force-pushed the feat/cnb-provider branch from 1273c83 to 6f704aa Compare July 21, 2026 11:38
@Eyre921

Eyre921 commented Jul 21, 2026

Copy link
Copy Markdown
Contributor Author

Friendly nudge on this one — it's been green and mergeable since opening, live-tested end-to-end against real cnb.cool, and I've just rebased it onto current main so it's still conflict-free (verified: tsc --noEmit, npm run build, and the full unit suite pass on the new base; the provider layer merged cleanly against the recent tgit changes in #210/#212).

The only thing blocking it is the scope call I flagged up top: do you want a CNB provider in-tree or not? Totally fine either way — I just don't want it to sit in limbo. To make the decision cheap:

  • If yes: it's ready to merge as-is. Happy to also add a CNB_TOKEN-gated, self-cleaning e2e test to the CI suite if you'd like one before or after merging.
  • If it's out of scope (CNB being Tencent-adjacent may not fit your roadmap): just say the word and I'll close it and keep it in my fork — no hard feelings.

Could you give it a 👍/👎 on direction when you have a moment? That's all it needs.

Adds a third GitProvider alongside github and tgit, following the same
"thin class over a platform CLI" shape as the TGit provider. CNB's official CLI
(`@cnbcool/cnb-cli`) exposes everything the GitProvider interface needs:

- `cnb login` (OAuth2 device flow) + `cnb status`  → authenticate / isAuthenticated
- git clone with token / `cnb git-credential`       → cloneRepo
- `cnb pulls post-pull`                             → createPullRequest
- `cnb repositories create-repo`                    → createRepo
- `cnb users get-user-info`                         → username

Auth mirrors the GitHub provider's dual path: interactive `cnb login`, or a
`CNB_TOKEN` env var for headless/CI use — the same pattern as GITHUB_TOKEN.

registry.ts maps `cnb.cool` / `cnb.woa.com` to this provider and registers it.

Three robustness issues surfaced by live testing against real cnb.cool and fixed
here (none were caught by a build-only check):
- cnbWhoami() returned the CNB_USERNAME credential placeholder ("cnb") instead
  of the real account; now parses the API's `username:` first.
- the CLI prints YAML, not JSON, so username / PR-URL parsing is regex-based.
- the CLI exits 0 even on a 4xx API response, so a non-zero exit code is not
  enough to detect failure; `assertCnbApiOk()` now also checks the printed
  `status:` and throws on >= 400 (with the API's errmsg).

Test Plan:
- npx tsc --noEmit ; npm run build
- npx vitest run — 142 files, 1754 tests; 9 new in cnb-provider.test.ts (host
  detection, factory, repo-input parsing incl. nested groups, assertCnbApiOk).
- Opt-in live smoke in src/__tests__/e2e/cnb-provider-live.test.ts (skipped
  without CNB_TOKEN): asserts isAuthenticated() + a real account username.
  Read-only by design — some CNB namespaces block Open-API resource deletion, so
  a create/delete test would orphan repos.
- The full mutating flow (createRepo → cloneRepo → push → createPullRequest) was
  verified manually against real cnb.cool; PR URL came back
  https://cnb.cool/<owner>/<repo>/-/pulls/1.

Claude-Session: https://claude.ai/code/session_01GEV81Xj6mhPzSPsyBrDPSd
@Eyre921
Eyre921 force-pushed the feat/cnb-provider branch from 6f704aa to 884d7b6 Compare July 21, 2026 12:00
@Eyre921

Eyre921 commented Jul 21, 2026

Copy link
Copy Markdown
Contributor Author

Follow-up: I've scoped this down to cnb.cool only, so the PR now matches what's actually been tested.

Why: cnb.cool is the public community platform; cnb.woa.com is the internal (enterprise) mirror. The previous revision registered cnb.woa.com in the host map, but the operations wouldn't have honored it: cnbParseRepoInput strips the input URL's host and rebuilds every git URL from a single global CNB_HOST, and the API calls shell out to cnb <cmd> with no endpoint override. So a cnb.woa.com URL would have been detected as cnb but then cloned/pushed against cnb.cool. The live E2E also only ever exercised cnb.cool.

I confirmed the internal path is feasible for a future PR — @cnbcool/cnb-cli takes a CNB_API_ENDPOINT (and CNB_WEB_ENDPOINT) env var for the API host, and git auth is per-host via cnb git-credential — but doing it right means threading the repo's host through both the git URL and the CLI endpoint, and testing it on a real internal instance. That's out of scope here and I can't test it, so I'd rather not ship a half-wired second host.

Changes in this revision:

  • Removed cnb.woa.com from the registry host map (and its detection assertion).
  • Reworded the CNB_HOST doc comment: default cnb.cool (the only tested host); TEAMAI_CNB_HOST remains as an advanced override for a self-hosted deployment, with a note that such setups must also set the CLI's CNB_API_ENDPOINT.

Re-verified on current main: tsc --noEmit, npm run build, full unit suite (145 files / 1795 tests) all green. Single commit, still conflict-free.

@jeff-r2026
jeff-r2026 merged commit d2bc494 into Tencent:main Jul 21, 2026
7 checks passed
@Eyre921
Eyre921 deleted the feat/cnb-provider branch July 21, 2026 13:22
jeff-r2026 pushed a commit that referenced this pull request Jul 22, 2026
Follow-up doc pass for #208 (CNB provider) and #192 (session save), which
shipped without doc coverage.

- docs/providers.md: provider count 两个 → 三个; add `cnb` to the table and the
  auto-detection block; new "CNB Provider(cnb.cool)" section — auth via
  `cnb login` / `CNB_TOKEN`, operations delegated to @cnbcool/cnb-cli, nested
  paths, and the cnb.cool-only scope + TEAMAI_CNB_HOST/CNB_API_ENDPOINT note.
- README.md / README.zh-CN.md: add CNB to the git-host list.
- docs/usage-guide.md / .zh-CN.md: add CNB to the create-repo step and
  prerequisites; new "Session Save" section for `teamai session save`
  (--push / --force / --include-prompt, local ~/.teamai/session-logs path,
  90-day retention, "valuable" heuristic, digest Session Highlights, privacy).

Docs-only, bilingual kept in sync. Built and verified the documented surface:
`session save --help` shows the flags; the cnb.cool host mapping is in the build.

Co-authored-by: Eyre921 <Eyre921@users.noreply.github.com>
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.

2 participants