refactor(providers): unify Git/HTTP resource backends, ClawPro as HTTP adapter (#404) - #780
jeff-r2026 wants to merge 14 commits into
Conversation
) Add a resource-sync-mechanism layer above the existing GitProvider host adapters, so a `git` backend and one or more `http` backends can be mounted side by side under one registry. This is phase 1 of Tencent#404: purely additive, with zero behavior change — nothing consumes the abstraction yet. - `ResourceProvider` (name/type/priority/capabilities + sync/describe/ teardown) and its capability model in providers/types.ts, alongside the HttpBackendAdapter contract for phase 2. - `ResourceProviderRegistry` with duplicate-name rejection and priority-ordered listing; `syncResourceProviders` runs providers with per-provider failure isolation so one backend cannot abort the others. - `GitResourceProvider`, a thin shell that wraps the existing team-repo pull/teardown as injected closures (no git behavior is reimplemented). Ownership arbitration, primary-write selection and cross-provider failover are deferred to a later phase; `priority` is carried on the interface now so those phases need no type change.
…#404) Move src/local-agent.ts to src/providers/http/adapters/clawpro/client.ts unchanged (only the relative import prefixes are re-rooted one level deeper), and leave src/local-agent.ts as a 5-line @deprecated re-export so every existing importer — production and tests — keeps working with no edit. This is a pure relocation: no logic changes, and all 140 local-agent regression tests pass from the new location. The HTTP provider wrapper, named state directories and adapter wiring land in the next commit.
…encent#404) Build the HTTP side of the ResourceProvider abstraction on top of the relocated ClawPro client, so multiple HTTP backends can be mounted side by side, each fully isolated, without the old global local-agent singleton. Phase 2 of Tencent#404; backward compatible. - HttpResourceProvider delegates to a protocol HttpBackendAdapter; ClawProAdapter maps the report/sync/ack wire format onto the client, running each call inside the provider's own execution context. The wire format (routes, local_agent_id) is unchanged. - An AsyncLocalStorage seam in the client redirects state to ~/.teamai/providers/http/<name>/ for a named provider and keeps the legacy ~/.teamai/local-agent/ location when no context is active, so every pre-Tencent#404 path behaves exactly as before. - Per-provider store: config in the provider home + a registry in ~/.teamai/providers/settings.json; the credential lives in a separate 0600 ~/.teamai/credentials/<name> file and is never written into config.json. - `migrateLegacyHttpProvider` promotes the legacy singleton with a staged atomic copy, extracts the credential to the isolated file, and keeps the old dir as a rollback snapshot behind a migrated-to marker (idempotent). - `teamai provider add http | list | sync | remove | migrate-legacy` CLI; the hook dispatcher syncs every named provider once with failure isolation, then falls back to the legacy singleton only while it is still active. `teamai uninstall` tears down every named provider too. Git provider management, cross-provider ownership arbitration, priority failover and primary-write selection remain later phases.
Tencent#404) Add a "Multiple HTTP providers" section to the bilingual usage guide covering `teamai provider add http | list | sync | remove | migrate-legacy`, per-provider isolation and the 0600 credential layout.
88efcf5 to
9427794
Compare
|
审查结论
PR 描述包含单测、e2e 套件和真实 ClawPro CLI 验证记录,因此未单独提出测试记录缺失问题。 |
Respond to the review on PR Tencent#780. Findings #1/#2 (config.ts / usage-tracker.ts "regressions") were false positives from a pre-rebase diff — this branch does not touch those files. The rest are fixed: - Gate to a single HTTP provider (review Tencent#9/Tencent#10). Running multiple HTTP providers concurrently is unsafe until the ownership ledger arbitrates same-name resources (issue Tencent#404 phase 4) and can blow the foreground hook budget. `provider add http` now refuses a second provider (and one while the legacy singleton is active); migrate-legacy still works. - `provider sync` reports honest results (review Tencent#5): the ClawPro client swallows network/command errors, so it now fills a SyncOutcome the adapter reads — a backend failure surfaces as `ok:false` and a non-zero exit, never a false success. - Publish the registry record only after adapter init succeeds, rolling back partial state on failure (review #3). - Make legacy migration retriable (review Tencent#4): conflict is decided by the registry, not the home dir, so a home left by a crashed run is discarded and rebuilt (legacy stays authoritative until the marker). - `uninstall` runs each named provider's full teardown() — resources, agent hooks and plugins — not just plugin cleanup, so a provider's skills/rules/CLAUDE.md/hooks are not orphaned (review Tencent#7). - bind-project runs inside the named provider's context instead of the legacy singleton (review Tencent#6). - Reject provider names that collide case-insensitively or hit Windows path hazards (trailing dot, reserved device names) (review Tencent#8). - Drop the no-op `provider sync --force` flag (review Tencent#12). Docs: document the single-provider limit and migration in the bilingual usage guide and join-member skill-data (review Tencent#11). Tests: add provider-command gate/rollback coverage, case-collision + retriable migration + honest-failure cases.
|
感谢详细 review。已按结论逐条处理并 push(commit a3bd495)。 #1 / #2(config.ts / usage-tracker.ts 回退)— 误报:本 PR 未改动这两个文件( #9 / #10(多 provider 无 ownership 仲裁 → 资源互删;串行 sync 超前台预算):采纳根因判断——按设计文档 §8,仲裁层落地前不开放多 provider 并发。本 PR 收窄为单个 HTTP provider: #5(sync 把后端失败报成成功): #3(registry 先于 init 写入):改为 init 成功后才发布 registry 记录,init/写入任一失败则回滚 state + registry。 #4(迁移非原子/不可重试):冲突判定改为看 registry 而非 home 目录——崩溃后遗留的 home(无 registry 记录、无 marker)被视为可丢弃残留,直接清掉重建;legacy 在 marker 写入前始终权威。新增可重试回归测试。 #7(uninstall 只清插件、遗留具名 provider 资源):改为对每个具名 provider 在其 context 内调用完整 #6(bind-project 未进 provider context): #8(名称校验不足以保证跨平台路径安全):拒绝大小写冲突( #12( #11(skill-data 未同步): 验证: |
|
审查结论
已解决
|
…#404) Second review round on PR Tencent#780. Findings on config.ts / usage-tracker.ts remain false positives — this branch's diff does not touch either file (git blame attributes those lines to upstream Tencent#775). The rest are fixed: - Close the single-provider gate on the compat entry points too (review Tencent#5): `source add-http` and `init --http` now refuse to stand up the legacy singleton when a named HTTP provider exists, and `provider migrate-legacy` refuses when one already exists — so a named provider and a legacy singleton can never be dispatched together. - `provider sync` reports a failed remote command as a failure (review Tencent#5-cmd): processCommands now records a per-command failure into the SyncOutcome (still isolated — it neither throws nor aborts the loop), so the adapter returns ok:false instead of a false success. - Roll back injected hooks on a failed `provider add` (review #3): the rollback now runs the adapter's full teardown(), not just state + registry removal, so hooks init already wrote are not orphaned. - Make legacy migration genuinely resumable (review Tencent#4): a registry entry whose endpoint matches the legacy one is treated as this same interrupted migration and resumed (legacy stays authoritative until the marker); only a different-endpoint entry is a foreign conflict. - Reject Windows reserved names with an extension too — CON.txt, LPT1.foo (review Tencent#8) — and surface every invalid name as a clean error + exit, never an uncaught throw. Tests: reserved-name-with-extension, resumable migration after a registry write, migrate-legacy gate, and clean-exit on invalid name.
|
第二轮 review 已处理(commit f431ce9)。感谢确认前 4 条已解决。 #1 / #2(config.ts:350 / usage-tracker.ts:25)— 仍为误报,附证据:本 PR 对这两个文件的 diff 为空: 这些行由上游 #5(source add-http / init --http 绕过单-provider 闸门):已在两个兼容入口补闸门——存在具名 provider 时 #5-cmd(单条命令执行/ack 失败被吞、sync 仍报成功): #3(回滚遗留 init 已注入的 hook): #4(迁移不可重试):崩溃在 upsert(写 registry)之后、marker 之前时,legacy 仍 active;重试时若 registry 记录的 endpoint 与 legacy 一致,判定为同一次中断的迁移并续做(而非 "already exists");仅 endpoint 不同才是真正的外部 #6(migrate-legacy 未挡 named+legacy → 两个具名 provider): #8(CON.txt / LPT1.foo 等保留名带扩展):正则改为匹配保留名后接 P2(GitResourceProvider / ResourceProviderRegistry 类 / adapter routes 未进生产路径):这三者是 #404 阶段1 明确定义的抽象契约—— 验证:tsc 0 错、build 成功、全量 302 文件 4542 通过/1 skip、真实 ClawPro 后端 e2e(单-provider 闸门在 add/source add-http/init --http/migrate-legacy 四处均拒绝、CON.txt clean exit、report/sync 200)通过。 |
|
审查结论
已解决
|
) Third review round on PR Tencent#780. config.ts / usage-tracker.ts findings remain false positives (git blame attributes those lines to upstream Tencent#775; this branch's diff for both files is empty). The rest are fixed: - Restore migrate-legacy idempotency (review #3, a regression from the round-2 gate): the single-provider gate now rejects only a DIFFERENTLY-named provider, so re-running after a completed migration is a clean no-op and a crash-interrupted migration can still resume through the store's recovery path. - Fail `provider add` when init injected zero hooks (review Tencent#4): injectHooksToAllTools now returns an attempted/succeeded tally, and a named-provider init throws when hooks were attempted but none landed, so the add rolls back instead of reporting a false success. - teardown removes the built-in teamai hooks too (review Tencent#5): a named provider's removeLocalAgentHttp now clears the dispatch hooks its own init injected (via reconcileHooksToAllTools removeAll), gated on no other teamai install still needing them — so `provider remove` and failed-add rollback leave no orphaned hooks. - Serialize `provider add` under a machine lock (review Tencent#6): the single-provider check-and-write now holds ~/.teamai/providers/.add.lock so two concurrent adds cannot both pass the empty-registry gate. - Sync the bilingual management-backend design doc (review Tencent#7): it now points at providers/http/adapters/clawpro/client.ts and states the Tencent#404 phase 1-2 abstraction has landed. P2 (unused GitResourceProvider / registry class / adapter routes) is kept as the phase-1 abstraction contract by maintainer preference. Tests: migrate idempotency-after-success, init-injected-no-hooks rollback.
|
第三轮 review 已处理(commit 3de4713)。感谢确认 5 条已解决。 #1 / #2(config.ts:350 / usage-tracker.ts:25)— 第三次说明,仍为误报:本 PR 对这两个文件的改动为空,行由上游 #775 引入: 第 350-351 行按顺序是"命中 project 才返回、否则 #3(migrate-legacy 幂等性回归):确认是我上一轮加闸门时引入的 regression。已修:闸门只拒绝名称不同的具名 provider;同名记录(已完成迁移 or 崩溃后待恢复)交给 store 的恢复逻辑。成功迁移后再跑 → 干净 no-op("already migrated");崩溃后重试 → 续做。已加回归测试 + 真机验证。 #4(init 注入 hook 全失败仍报成功): #5(teardown 不删内置 hook): #6(单-provider 检查 TOCTOU): #7(design 文档未同步): P2(未用抽象):按 maintainer 倾向保留 验证:tsc 0 错、build 成功、全量 302 文件 4544 通过/1 skip、真实 ClawPro 后端 e2e(remove 清内置 hook / migrate 幂等 / 四处单-provider 闸门 / report+sync 200)通过。 |
|
审查结论
已解决
|
|
审查结论
已解决
|
…#404) Fourth review round on PR Tencent#780. config.ts / usage-tracker.ts findings stay false positives (empty diff vs origin/main; upstream Tencent#775 owns those lines). The rest are fixed: - Don't count an uninstalled adapter tool as a successful hook injection (review #3): injectHooksToAllTools now gates the pi/openclaw/hermes/ opencode/omp branches on the tool actually being installed, so a named-provider init that lands zero real hooks is detected and fails (was masked by adapter no-op "successes"). - teardown's built-in-hook removal now checks for ANY other teamai install — user scope AND every project-scope partition — not just the user config (review Tencent#4), so removing a named provider never strips hooks a project-only Git install still needs. - A re-written legacy singleton clears the stale migrated-to marker (review Tencent#5): initLocalAgentHttp (legacy path) calls clearLegacyMigrationMarker, so migrate → remove → source add-http / init --http reactivates the singleton instead of leaving it dormant. - teardown keeps the provider home + manifest when any resource uninstall fails (review Tencent#6), throwing so cleanup can be retried rather than orphaning resources with a destroyed ownership manifest. - Serialize migrate-legacy under the same machine lock as provider add via a shared withProviderLock helper (review P3). - source list no longer shows a migrated legacy snapshot as an active HTTP source (review P2). P2 (unused GitResourceProvider / registry class) kept as the phase-1 abstraction contract by maintainer preference. Tests: injection tally excludes uninstalled tools, marker reactivation.
|
第四轮 review 已处理(commit 41aa3b8)。 #1 / #2(config.ts:350 / usage-tracker.ts:25)— 第四次说明,仍为误报: #3(Pi/adapter no-op 计成功 → init 零 hook 仍报成功): #4(teardown 只查 user-scope):新增 #5(marker 永久停用 legacy): #6(卸载失败仍删 home → 资源遗留 + manifest 销毁):资源卸载有任一失败时,保留 home + manifest 并抛错,提示可重试;不再删除,避免孤儿资源无法清理。 P3(锁只覆盖 add):提取 P2(source list 显示已迁移快照为活动源): P2(未用抽象 GitResourceProvider/registry 类):按 maintainer 倾向保留为阶段1 抽象契约;如需阶段3 再引入,可另开 PR 移除,不阻断本 PR。 验证:tsc 0 错、build 成功、全量 302 文件 4546 通过/1 skip、真实 ClawPro 后端 e2e(#5 marker 重激活 / #3 未装工具不虚报 / report+sync 200)通过。 |
|
审查结论
已解决
|
) Fifth review round on PR Tencent#780. config.ts / usage-tracker.ts stay false positives (empty diff vs origin/main). The rest are fixed: - Propagate the named-provider context to the detached plugin-reconcile worker (review #3): AsyncLocalStorage does not cross a process boundary, so maybeReconcilePlugins passes the provider name via TEAMAI_HTTP_PROVIDER_NAME and runPluginReconcileWorker re-enters the context — a named provider's backend plugins now install/update instead of the worker silently reading the legacy dir. - `source remove-http` refuses when the legacy singleton has been migrated (review Tencent#4): the retained rollback snapshot's copied manifest would otherwise uninstall resources the named provider is actively using; it now points at `provider remove` instead. - Teardown keeps state on ANY partial failure, not just resource uninstall (reviews Tencent#5/Tencent#6): removeAllAgentHooks reports failure and keeps its manifest; plugin teardown and built-in hook removal failures now also set the keep-state flag, so hooks/plugins are never orphaned with their ownership records destroyed. - teardown's other-install check also covers a legacy in-tree <project>/.teamai/config.yaml governing the cwd (review Tencent#7), not only user config and partitions, so removing a provider never strips shared built-in hooks a project-only Git install still needs. P2 (unused GitResourceProvider / registry class) kept as the phase-1 abstraction contract by maintainer preference. P3 (source add-http / init --http not under the provider lock) — those compat entries already refuse when a named provider exists; the lock covers the provider-native add/migrate paths. Tests: plugin-reconcile worker re-enters provider context from env.
|
第五轮 review 已处理(commit e39751b)。感谢确认多条已解决。 #1 / #2(config.ts:350 / usage-tracker.ts:25)— 第五次说明,仍为误报: #3(plugin reconcile 子进程丢 provider context):确认——AsyncLocalStorage 不跨进程边界。已修: #4(source remove-http 卸载已迁移快照 manifest → 误删 named provider 在用资源):已修—— #5 / #6(agent-hook / 内置 hook / plugin 删除吞错仍清 manifest + 删 home):已把所有teardown 失败模式纳入"保留状态": #7(teardown 漏查 legacy P2(未用抽象):按 maintainer 倾向保留 P3(source add-http / init --http 未走 provider 锁):这两个兼容入口在存在 named provider 时已直接拒绝(不会创建第二个后端),因此不依赖锁来防并发建双后端;provider-native 的 add/migrate 路径则持共享锁。可接受的现状。 验证:tsc 0 错、build 成功、全量 302 文件 4547 通过/1 skip、真实 ClawPro 后端 e2e(#3 worker 命中 named endpoint / #4 remove-http 拒绝 / report+sync 200)通过。 |
|
审查结论
已解决
|
…nt#404) Sixth review round on PR Tencent#780. config.ts / usage-tracker.ts stay false positives (empty diff vs origin/main; upstream Tencent#775 owns those lines). The rest: - Redact the migration token in staging BEFORE publishing the provider home (review #3): the credential is written to its isolated 0600 file and stripped from the staged config.json, then the dir is atomically moved — so the published config.json never contains the token, even in a crash window. - teardownAllPlugins reports an aggregate success flag (review Tencent#4): it swallowed each plugin's uninstall error and returned void, so the caller's uninstallFailed never tripped. removeLocalAgentHttp now checks the return value and keeps state (plugins.json) on failure. - provider-add rollback keeps state when its teardown could not fully clean up (review Tencent#5): it drops only the registry entry (so dispatch won't load a broken provider) and preserves the home for a retriable `provider remove`, instead of destroying the ownership manifest. - `teamai uninstall` warns when a named provider's teardown was incomplete before deleting ~/.teamai (review Tencent#6), so orphaned external hooks/plugins are surfaced rather than silently stranded. - teardown's other-install check now also detects a legacy in-tree <project>/.teamai config governing the cwd (review Tencent#7 residual). - Fix the credential path in join-member.md — it is ~/.teamai/credentials/<name>, not the provider home (review P2 doc). P2 (source list showing a migrated snapshot) was already fixed in the prior round and is verified hidden; P2 (unused abstraction) and P3 (compat entries not under the provider lock) are as previously decided.
|
第六轮 review 已处理(commit fe47f50)。 #1 / #2(config.ts:350 / usage-tracker.ts:25)— 第六次确认为误报(请 maintainer 关注):本 PR 从未改动这两个文件。可复核:
#3(migration token 泄漏窗口):已改为在 staging 阶段脱敏:先把 token 写入隔离 0600 凭据文件、从 staged config.json 删除 token,再原子 move 发布 home。发布后的 config.json 任何时刻都不含 token。真机验证:migrate 后 provider config.json 无 token 字段、凭据在 #4(teardownAllPlugins 吞错→uninstallFailed 设不上):确认修错了层。已让 #5(provider add rollback 无条件删状态):rollback 现在区分 teardown 是否成功——成功才删 state+registry;teardown 不完整时只删 registry 记录(避免 hook dispatch 加载坏 provider)、保留 home+manifest,并提示用户 resolve 后 #6(uninstall teardown 失败仍删 ~/.teamai): #7 residual(漏其它工作区 in-tree config): P2(join-member.md 凭据路径错):已修正为 P2(source list 显示已迁移快照):上一轮的 P2(未用抽象)/ P3(兼容入口未走锁):按前述 maintainer 倾向与可接受性判定保留。 验证:tsc 0 错、build 成功、全量 302 文件 4547 通过/1 skip、真实 ClawPro 后端 e2e(#3 config 无 token / P2 source list 隐藏 / report+sync 200)通过。 |
|
审查结论
已解决
|
…t#404) Seventh review round on PR Tencent#780. config.ts / usage-tracker.ts remain false positives (empty diff vs origin/main — upstream Tencent#775 owns those lines; asked maintainer to dismiss). The genuinely new findings — all flaws in the previous round's own fixes — are addressed: - Give the kept-on-failure state a real CLI retry path (review #3): a failed add that keeps its home now also writes provider.json there, and `provider remove` recovers a provider from its home config when the registry entry is gone, then keeps the home again if teardown still can't finish. The retry `provider remove <name>` the message promises now actually works. - `teamai uninstall` no longer deletes ~/.teamai when a provider teardown was incomplete (review Tencent#4): it keeps the dir (and its ownership manifests) and tells the user to resolve the issue and re-run, so the leftover external hooks/plugins stay recoverable instead of stranded. - Stop stripping the SHARED built-in dispatch hooks on a plain `provider remove` (reviews Tencent#5/Tencent#7): they serve every teamai install and no-op without config, so a leftover is harmless while an erroneous removal breaks a coexisting install — and another install can't be enumerated reliably (in-tree <project>/.teamai lives anywhere). Full built-in-hook removal now happens only under `teamai uninstall` (TEAMAI_UNINSTALL=1) when no other install remains. Tests: clean rollback vs. keep-on-teardown-failure, and provider remove recovering a registry-less home.
|
第七轮 review 已处理(commit bb05600)。确认 6 条已解决。 #1 / #2(config.ts:350 / usage-tracker.ts:25)— 第七次误报: 本轮 3 条真实 P1(均为上一轮修复自身的缺陷,已修): #3(保留 manifest 但 provider remove 找不到入口):确认矛盾。已修:①失败 add 保留 home 时,额外写入自描述 #4(uninstall teardown 失败仍删 ~/.teamai):已改为——provider teardown 未完成时不删 ~/.teamai,保留其 ownership manifest,提示用户 resolve 后重跑 #5 / #7(provider remove 误删共享内置 hook):采纳根本性判断。内置 dispatch hook 是共享基础设施(服务所有 teamai 安装,无 config 时优雅 no-op)——remove 它是不对称风险:leftover 无害,误删则破坏共存安装,且"是否有其它安装"无法可靠判定(in-tree P2(未用抽象)/ P3(兼容入口未走锁):如前,按 maintainer 倾向与可接受性判定保留。 验证:tsc 0 错、build 成功、全量 302 文件 4548 通过/1 skip。 |
|
审查结论
已解决
|
…cent#404) Eighth review round on PR Tencent#780, resolved per maintainer decisions: - Delete the unused speculative abstraction (review P2): remove GitResourceProvider (no production consumer), the ResourceProviderRegistry class (only syncResourceProviders is used — kept), and the HttpBackendAdapter.routes()/HttpRoutes API (no caller). The live contract (ResourceProvider, syncResourceProviders, HttpResourceProvider, HttpBackendAdapter) stays. - Migration no longer keeps a rollback snapshot (reviews Tencent#6/Tencent#7): it now DELETES ~/.teamai/local-agent/ after publishing the provider. This removes an entire class of snapshot bugs — no stale bindings/manifest to revive on a later `source add-http`, no double plugin uninstall on `teamai uninstall`. The migrated signal is the dir's absence, so the `migrated-to` marker and clearLegacyMigrationMarker are gone and legacySingletonActive is just "does the legacy config exist". - `provider remove` resolves the name case-insensitively and acts on the canonical registered name (review #3), so on a case-insensitive FS `remove Foo` can't delete `foo`'s state while stranding its registry entry. - `provider remove` deactivates first (drops the registry entry) then tears down (review Tencent#4), under the provider lock, so a concurrent hook can't reinstall mid-teardown and a teardown failure can't leave the registry pointing at deleted state. - `provider remove` did NOT strip shared built-in hooks — kept per the round-7 decision (maintainer confirmed): those serve every install and no-op without config; removal stays with `teamai uninstall`. config.ts / usage-tracker.ts remain false positives (not in this PR's diff); asked the maintainer to dismiss.
|
第八轮 review 已处理(commit aa127fb),按 maintainer 决策落地。 #1 / #2(config.ts / usage-tracker.ts)— 误报:不在本 PR diff 内( P2(未用抽象)→ 删除:移除 #6 / #7(迁移快照复活 / 双重卸载)→ 砍掉快照机制: #3(provider remove 大小写不敏感撞库): #4(remove 先 teardown 后停用的时序问题): #5(provider remove 该不该删共享内置 hook)→ 维持"不删"(maintainer 确认):共享 dispatch hook 服务所有安装、无 config 优雅 no-op; P3(兼容入口未走锁): 验证:tsc 0 错、build 成功、全量 302 文件 4543 通过/1 skip、真实 ClawPro 后端 e2e(迁移删快照 / 大小写 remove / 重新激活)通过。 |
|
审查结论
已解决
|
…over (Tencent#404) Ninth review round on PR Tencent#780. - Run the legacy singleton fallback ONLY when no named provider is configured (review #3): once a named provider exists it owns delivery, so during the migration window (registry entry published, legacy dir not yet deleted) the hook dispatcher no longer runs both — which had caused duplicate report / command execution / resource writes. - Migration removes the shared legacy ~/.teamai/token when it was the credential source (review P2): the token now lives only in the isolated 0600 credential file, so the old plaintext copy is deleted instead of stranded after a later `provider remove`. Not changed: - Tencent#4 (provider remove leaving shared built-in dispatch hooks): kept per the maintainer's explicit decision — those hooks serve every install and no-op without config; full removal stays with `teamai uninstall`. - #1/#2 (config.ts / usage-tracker.ts): false positives, not in this PR's diff (upstream Tencent#775); asked the maintainer to dismiss. - P3 (compat entries not under the provider lock): they refuse when a named provider exists, so they cannot create a second active backend. Tests: legacy ~/.teamai/token removed on migration.
|
第九轮 review 已处理(commit e718b4a)。确认多条已解决。 #3(迁移窗口 named+legacy 双调度):已修——hook dispatcher 的 legacy 兜底现在仅在无任何 named provider 时才运行。named provider 一旦存在即接管交付,故迁移窗口(registry 已发布、legacy 目录尚未删)不再同时跑两者,消除重复 report / 命令执行 / 资源写入。 P2(旧 ~/.teamai/token 残留):迁移在以 #4(provider remove 不清共享内置 dispatch hook)— 维持现状(maintainer 已决策):这条上一轮已由 maintainer 明确定为"不该删"。理由:内置 dispatch hook 是服务所有 teamai 安装的共享基础设施,无 config 时优雅 no-op; #1 / #2(config.ts / usage-tracker.ts)— 误报:不在本 PR diff 内( P3(兼容入口未走 provider 锁): 验证:tsc 0 错、build 成功、全量 302 文件 4543 通过/1 skip。 |
|
审查结论
已解决
|
Tenth review round on PR Tencent#780 (P2 cleanup). - Remove the `--priority` flag from `provider add http` and `provider migrate-legacy`, and the parsePriority helper. With a single provider it never affects behavior, so exposing and persisting it is the unused/speculative config the review rules warn against. The `priority` data-model field stays (defaulted to 50, reserved for the later arbitration phase) but is no longer user-configurable. Docs and the generated command reference updated to match. Not changed (as previously decided): #1/#2 config.ts/usage-tracker.ts are false positives outside this PR's diff (upstream Tencent#775); provider remove intentionally leaves the shared built-in dispatch hooks (maintainer decision); the compat entries refuse a second backend so they need no shared lock.
|
第十轮 review 已处理(commit 6dfc672)。本轮无新的真实 P1——两条 P2 已修,其余为已知误报 / 已决策点。 P2( P2(PR 描述陈旧)→ 更新:PR description 已刷新,去掉"保留 rollback snapshot / migrated-to marker / GitResourceProvider"等已不成立的描述,准确反映最终行为(迁移删除 legacy 目录、单 provider 闸门、命令参考等)。 #3(provider remove 跳过内置 hook)— 维持现状(maintainer 已决策,第三次说明):内置 dispatch hook 是共享基础设施、无 config 时 no-op; #1 / #2(config.ts / usage-tracker.ts)— 误报:不在本 PR diff( P3(remove 时序 / 兼容入口锁):均为极窄竞态且 non-blocking——remove 已持 provider 锁并先停用;兼容入口在已有 named provider 时直接拒绝,不会建第二个后端。判定可接受。 至此,除两条无法由代码修复的上游误报(#1/#2)和一个已由 maintainer 决策的设计点(#3)外,没有需要改动的真实 P1。验证:tsc 0 错、build 成功、全量 302 文件 4543 通过/1 skip。恳请 @jeff-r2026 复核并 dismiss #1/#2 后合入。 |
|
审查结论
已解决
|
统一 Git/HTTP 资源后端抽象的阶段 1+2(issue #404)。把 3437 行的全局
local-agent单例 + 遍布全库的repo.kind: http分支,收敛到一个ResourceProvider抽象之下,并把 ClawPro 协议实现降为 HTTP provider 的一个 adapter。行为向后兼容:repo.kind: http/init --http/source add-http全部保留可用。改动
阶段 1 — 抽象层(纯新增,零行为变更)
src/providers/types.ts:ResourceProvider(name/type/priority/capabilities + sync/describe/teardown)、capability 模型、HttpBackendAdapter契约,与既有GitProvider(git host 层)并存。src/providers/resource-registry.ts:syncResourceProviders—— 逐 provider 失败隔离的同步驱动。阶段 2 — HTTP/ClawPro(向后兼容)
local-agent.ts→providers/http/adapters/clawpro/client.ts纯搬迁(仅 reroot import),原文件留 5 行@deprecatedre-export,所有既有 importer 零改动。HttpResourceProvider委托ClawProAdapter;wire format(/api/local-agent/*路由、local_agent_id)逐字保留。~/.teamai/providers/http/<name>/;无 context 时保持 legacy~/.teamai/local-agent/完全不变。detached 子进程(plugin reconcile)经 env 显式传递并重建 context。~/.teamai/credentials/<name>(0600),绝不写入 config.json。migrateLegacyHttpProvider:staging 原子拷贝 + 抽取凭据脱敏 + 发布 provider + 删除 legacy 目录(不留快照,无 marker——迁移信号即目录不存在)。幂等、可重试。provider add http/migrate-legacy/source add-http/init --http在已有 provider 时拒绝建第二个。teamai provider add http | list | sync | remove | migrate-legacy(均持机器锁;remove 大小写归一、先停用再 teardown、失败保留状态可重试)。hook dispatch:有命名 provider 则只调度它、否则回退 legacy,避免迁移窗口双调度;teamai uninstall完整 teardown 命名 provider。不在本 PR(后续阶段):多 provider 列表、ownership ledger、priority 真正仲裁、failover、
primaryProvider/set-primary、push --provider、废弃repo.kind:http/add-http。config schema 未改动。Test Plan
npx tsc --noEmitnpm run buildnpx vitest runnpm run test:e2e真实 ClawPro 后端 e2e(隔离 HOME):
provider add/list/sync/remove、migrate-legacy(删快照、脱敏、幂等)、单 provider 闸门、大小写 remove、迁移后source add-http重新激活 —— report/sync/ack 均 200 OK。Refs #404