feat: add Kimi support as a first-class CLI cat#361
feat: add Kimi support as a first-class CLI cat#361ZephaniaCN wants to merge 30 commits intozts212653:mainfrom
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a181af722e
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
packages/api/src/domains/cats/services/agents/providers/KimiAgentService.ts
Outdated
Show resolved
Hide resolved
ece94ff to
303f16d
Compare
|
@codex review |
1 similar comment
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 303f16d305
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
packages/api/src/domains/cats/services/agents/providers/KimiAgentService.ts
Outdated
Show resolved
Hide resolved
|
@codex review |
711945a to
8d444df
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 711945ac06
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
f9c30db to
d5ebac9
Compare
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d5ebac9e63
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
packages/api/src/domains/cats/services/agents/providers/KimiAgentService.ts
Outdated
Show resolved
Hide resolved
|
已处理并回复当前 review 线程,包含:Kimi subscription 模式清理继承 API key、Kimi quota workdir 归一化、Kimi cache-hit 不再抬高 utilization;同时把与本 PR 无关的旧 standup / 测试偏移线程做了范围收敛说明。\n\n@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5e85a8f6cf
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
已修完这轮 review:\n- Kimi subscription 模式显式清理继承的 KIMI/MOONSHOT key env\n- Kimi quota workdir 匹配做了路径归一化\n- cache-hit 不再抬高 utilization\n- wire.jsonl 改成从尾部按 chunk 反向扫描,避免整文件读入\n- 本地失效的 .cat-cafe/cat-catalog 已重建,公共测试不再被无效 runtime 数据污染\n\n并已重新跑:\n- |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: de75de06f4
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
packages/api/src/domains/cats/services/agents/providers/KimiAgentService.ts
Outdated
Show resolved
Hide resolved
Kimi often formats follow-up delegation as markdown list items or blockquote lines (`1. @codex ...`, `- @codex ...`, `> @gemini ...`). Our A2A mention parser only accepted a bare `@` at the first non-space character, so those Kimi-shaped line-start mentions were silently ignored and no downstream cat was triggered. The parser now preserves the line-start-only contract while allowing common markdown prefixes to be stripped before mention matching. Tests cover numbered lists, bullets, quote prefixes, and the `.md`-suffixed handles Kimi sometimes emits. Constraint: A2A routing must remain line-start only to avoid accidental inline mention triggers Rejected: Allow @mentions anywhere in the line | too many false positives in normal prose/history echoes Confidence: high Scope-risk: narrow Reversibility: clean Directive: Keep A2A matching strict on semantic line starts, but normalize harmless markdown decoration before matching Tested: cd packages/api && pnpm run build && node --test test/a2a-mentions.test.js; pnpm -C /private/tmp/clowder-kimi check Not-tested: Live multi-cat runtime invocation from a real Kimi reply in cat-cafe-runtime
Kimi and Gemini were still pointing at byte-identical avatar assets, which made the roster and Hub surfaces visually ambiguous. The new Kimi avatar keeps the cat readable at small sizes while switching to a purple moonshot badge and warm amber cat face so it no longer collides with the Gemini palette. Constraint: Avatar must remain legible at 1024→small badge downscales and keep the existing /avatars/kimi.png path stable Rejected: Keep reusing the Gemini avatar | visual ambiguity between providers in Hub and runtime surfaces Confidence: medium Scope-risk: narrow Reversibility: clean Directive: Kimi visual identity should stay distinct from Gemini blue/cyan surfaces even if future mascot passes refine the illustration style Tested: Visual inspection of packages/web/public/avatars/kimi.png; hash differs from gemini.png Not-tested: In-app screenshot review across every avatar consumer surface
Replace the stopgap Kimi avatar with a generated mascot illustration that matches the visual language of the other cats more closely: centered bust, clean badge framing, and stronger small-size readability. The palette stays Kimi-specific (purple moonshot background + amber cat) so it remains visually separate from Gemini. Constraint: Keep /avatars/kimi.png stable while making the illustration feel consistent with the rest of the roster Rejected: Keep the quick procedural avatar | distinct but too diagrammatic next to the other mascot portraits Confidence: medium Scope-risk: narrow Reversibility: clean Directive: Future avatar passes should preserve Kimi's purple/amber identity and avoid drifting back toward Gemini's blue palette Tested: Visual inspection of generated /tmp/kimi-openai-avatar.png and replaced packages/web/public/avatars/kimi.png Not-tested: In-app screenshot pass across all avatar consumers
Kimi's previous identity still carried the old name and a palette that sat too close to the ragdoll purple family. This pass renames the cat to 梵花猫, removes the legacy 金吉拉 alias, shifts the roster colors to a cool black-and-silver scheme, and replaces the avatar with a non-anthro, full-body Turkish Van illustration so the cat reads as part of the same roster while staying visually distinct. Constraint: Keep provider/catId compatibility stable while changing only display identity, mentions, colors, and avatar art Rejected: Preserve the old 金吉拉 alias for compatibility | keeps the stale identity alive and undermines the rename Rejected: Keep a humanoid/suited mascot | breaks the pure-cat visual language used by the rest of the roster Confidence: high Scope-risk: moderate Reversibility: clean Directive: Future Kimi identity updates should keep the pure-cat full-body silhouette and avoid drifting back toward ragdoll purple or anthropomorphic styling Tested: cd packages/api && pnpm run build && node --test ../shared/test/cat-configs.test.js; cd packages/web && pnpm exec vitest run src/components/__tests__/message-navigator.test.ts src/components/__tests__/session-chain-panel.test.ts src/components/__tests__/hub-cat-editor.test.tsx; pnpm -C /private/tmp/clowder-kimi check Not-tested: Manual in-app review of every roster/avatar surface after rename
The avatar rename landed, but the web theme layer still served Kimi's old purple CSS variables and Tailwind never exposed a kimi color family at all. That left the UI in a split-brain state: bitmap assets changed, while Session Chain/sidebar classes kept compiling to nothing or to stale colors. This commit aligns the CSS tokens with the gray 梵花猫 palette and renders known display names in the sidebar badge so the right rail matches the renamed cat identity. Constraint: Runtime UI still depends on static Tailwind color families for border/bg/text utility classes Rejected: Inline per-session styles from runtime cat data | would bypass the existing theme token system and spread color logic across components Confidence: high Scope-risk: narrow Directive: When changing a cat palette, update static cat config, globals.css tokens, and Tailwind theme exports together or sidebar/session-chain UI will drift again Tested: pnpm exec vitest run src/components/__tests__/session-chain-panel.test.ts src/components/__tests__/kimi-theme-regression.test.ts; pnpm exec tsc --noEmit Not-tested: Manual browser visual confirmation inside the live runtime UI
Existing runtime catalogs keep seed cat presentation fields forever once .cat-cafe/cat-catalog.json exists. That left Kimi in a split state after the 梵花猫 rename: avatar/theme code changed, but the persisted seed metadata still served 金吉拉 + purple colors to /api/cats, so chat bubbles stayed purple and old mentions leaked into the UI. Migrate only the known legacy Kimi seed values forward to the current template while preserving unrelated runtime customizations. Constraint: Existing runtime catalogs may contain local edits, so migration must avoid broad seed overwrites Rejected: Overwrite all seed breeds from cat-template on every bootstrap | would silently clobber intentional per-project seed customizations Confidence: high Scope-risk: narrow Directive: When renaming a built-in cat identity, add a targeted runtime-catalog migration if old seed metadata is already persisted in .cat-cafe/cat-catalog.json Tested: cd packages/api && pnpm run build; cd packages/api && node --test test/cat-catalog-store.test.js; cd packages/api && node --test test/cats-routes-runtime-catalog.test.js Not-tested: Full manual UI traversal of every historical thread bubble after catalog migration
The local catalogs are already refreshed to 梵花猫, so the temporary runtime-catalog migration added during review is now just dead compatibility baggage. Removing it keeps the PR honest: there is no real production migration story to preserve while this change is still pre-merge and single-operator. Constraint: Current local .cat-cafe catalogs have already been rewritten to the 梵花猫 identity Rejected: Keep the targeted migration until merge | unnecessary compatibility complexity for a pre-release-only rename Confidence: high Scope-risk: narrow Directive: If the rename ships to real users later, reintroduce migration only with a concrete backward-compat need rather than speculative cleanup debt Tested: cd packages/api && pnpm run build && node --test test/cat-catalog-store.test.js && node --test test/cats-routes-runtime-catalog.test.js Not-tested: Fresh restart of the running runtime after this code-only cleanup
Kimi can emit a final handoff line like '@Opus @gpt52', but the parser stopped after the first line-start match and silently dropped the rest. That made a finished handoff look like it terminated after the first cat even though the message clearly targeted multiple teammates. The parser now continues scanning a pure line-start mention list on the same line while still refusing later inline mentions once prose starts. Constraint: A2A routing still only trusts line-start mention blocks, not arbitrary inline @mentions in prose Rejected: Parse every @mention anywhere in the line | too noisy and would turn narrative references into accidental routing Confidence: high Scope-risk: narrow Directive: Keep the line-start-only routing model, but preserve full target lists when the line is an explicit mention chain Tested: cd packages/api && pnpm run build && node --test test/a2a-mentions.test.js Not-tested: End-to-end live Kimi invocation through the running UI after this parser-only change
Gemini CLI headless stream-json only emits assistant text/tool events, while the actual thought trace lives in the local ~/.gemini session JSON. That left Gemini responses with no structured thinking payload for the frontend, so there was nothing for ThinkingContent to wrap even though the CLI had recorded thoughts. The service now looks up the matching local session after a successful turn and emits a normal thinking system_info block when the stored response content matches the streamed assistant text. Constraint: Gemini headless stream-json does not currently expose model thoughts as first-class events Rejected: Guess thinking from assistant prose prefixes | too brittle and would wrap normal response text as fake reasoning Confidence: medium Scope-risk: narrow Directive: If Gemini CLI eventually exposes thought chunks in stream-json directly, prefer those over local snapshot recovery and keep the content-match guard to avoid attaching stale thoughts Tested: cd packages/api && pnpm run build && node --test test/gemini-agent-service.test.js Not-tested: Live end-to-end Gemini invocation through the running Cat Café UI
…e data Kimi's 7-day consumption was being reported as zero because the daily usage aggregator only counted normalized input/output token fields, while Kimi often contributes last-turn or context snapshot tokens instead. Session-chain drill-downs also hardcoded assistant rows to a purple palette, which made Kimi sessions visually inherit the wrong family style. This change teaches usage aggregation to fall back to Kimi-compatible token fields and carries session cat identity into the session viewer so Kimi rows render with the gray Kimi theme instead of a ragdoll-like purple. Constraint: Kimi invocation usage may omit normalized input/output token fields Constraint: Search-opened session viewers still may not know cat identity and must fall back neutrally Rejected: Recompute daily usage from official quota pools | different metric from invocation consumption Rejected: Keep assistant session rows universally purple | clashes with provider-specific family themes Confidence: high Scope-risk: narrow Reversibility: clean Directive: Preserve provider-aware token fallbacks in daily usage aggregation; do not assume all cats emit normalized input/output fields Tested: pnpm --filter @cat-cafe/api run build; CAT_CAFE_DISABLE_SHARED_STATE_PREFLIGHT=1 node --test packages/api/test/usage-aggregator.test.js packages/api/test/usage-route-cache.test.js; pnpm exec vitest run src/components/__tests__/session-chain-panel.test.ts src/components/__tests__/SessionChainPanel-viewSession.test.ts src/components/audit/__tests__/SessionEventsViewer.test.ts Not-tested: Live runtime UI after deployment to the shared 3003/3004 instance
Kimi stores session state by canonical workdir path, but this branch still matched resume state with bare resolve() equality. In common git-worktree and symlinked workspace setups that dropped last_session_id lookup, so Kimi resumed as a fresh session even when kimi.json already had the correct state. This change canonicalizes both the live working directory and persisted kimi.json entries through resolve + realpathSync + normalize, and locks the behavior with a regression test that exercises a symlink alias against the real stored path. Constraint: Kimi persists work_dirs using canonical filesystem paths while Clowder often invokes cats from symlinked or worktree aliases Rejected: resolve()-only comparison | misses symlink aliases and recreates the reported blocker Confidence: high Scope-risk: narrow Directive: Keep Kimi session-state path matching aligned with any other Kimi workdir canonicalization logic Tested: pnpm --dir packages/api run build; cd packages/api && node --test test/kimi-agent-service.test.js; pnpm --filter @cat-cafe/api run lint; pnpm biome check packages/api/src/domains/cats/services/agents/providers/KimiAgentService.ts packages/api/test/kimi-agent-service.test.js --diagnostic-level=error Not-tested: End-to-end kimi-cli resume on Windows junction paths
Locks down the guarantee that explicit `bound account "..." not found` errors bubble up intact instead of being wrapped in a generic `failed to resolve bound account` message. This verifies that invokeSingleCat never silently falls through to service.invoke when the explicitly bound account is missing. [宪宪/Opus-46🐾] (test authored by 砚砚/GPT-5.4)
… [梵花猫/kimi🐾] Project-level Kimi skills were discovered but their SKILL.md metadata (description + triggers) was not extracted because the metadata scan only checked user-level ~/.kimi/skills, not project-level .kimi/skills. - Add projectRoot/.kimi/skills to skillDirCandidates for metadata extraction - Add regression test verifying project-level Kimi skill metadata (description + triggers) appears in capability board response Fixes review comment zts212653#7 from PR zts212653#361
…[烁烁/Gemini-2.5🐾] Implements @gemini25's design suggestions for PR zts212653#361: 1. Brand colors: Each cat now uses its own brand color when selected - Claude (anthropic): #9B7EBD (purple) - Codex (openai): #5B8C5A (green) - Gemini (google): #5B9BD5 (blue) - Kimi: #4B5563 (gray) - Dare: #D4A76A (brown) 2. Cat avatars: Added avatar images to ChoiceButton and PillChoiceButton - Uses existing /avatars/{client}.png assets - 40x40px for ChoiceButton, 20x20px for PillChoiceButton 3. Subtitles: Added subtitle descriptions for each cat in CLIENT_OPTIONS - Kimi: '擅长处理中文长文本、总结归纳和资料整理' - Claude: '擅长深度思考与代码审查' - Codex: 'OpenAI 官方 Codex CLI' - Gemini: '多模态长上下文专家' Files changed: - hub-add-member-wizard.parts.tsx: brand colors, avatars, subtitle support - HubAddMemberWizard.tsx: pass client/subtitle props - hub-cat-editor.model.ts: add subtitle field to CLIENT_OPTIONS
…ules Extract standalone helpers into two focused modules to bring KimiAgentService.ts under the 350-line hard limit: - kimi-config.ts (275 lines): config reading, path resolution, session/context utilities, MCP config writing - kimi-event-parser.ts (114 lines): stream-json event parsing, text/thinking extraction, usage stats, prompt building - KimiAgentService.ts (335 lines): class only, imports from above All 14 kimi-agent-service tests pass. No public API change. Addresses P2 from Round 2 review (zts212653).
Auto-format files flagged by `pnpm biome check --diagnostic-level=error`: - KimiAgentService.ts: import ordering - kimi-config.ts: formatting - GeminiAgentService.ts: line length formatting - gemini-agent-service.test.js: import ordering - RightStatusPanel.tsx: formatting - session-chain-panel.test.ts: formatting - .kimi/mcp.json: formatting
Remove unrelated files flagged in Round 3 review: - standup-aggregator.ts, standup.ts, and their tests (independent feature, will be separate PR) - omx.png avatar (OMX residual after scope convergence) - standup route registration from index.ts and routes/index.ts
efba3ce to
18bcd1e
Compare
…ections The constant was defined but only consumed from HubProviderProfileItem.tsx which has its own copy. Fixes CI build failure (no-unused-vars).
🔒 P1:请删除
|
The file contained hardcoded local paths and unrelated MCP server entries from the author's dev environment. Kimi MCP config is runtime-generated by capability-orchestrator (same as Claude/Codex/Gemini), not committed.
|
已修复, P1
|
|
我这边先从 maintainer 侧补了一个客观 cleanup commit:删除误提交的 |
|
收到!感谢从 maintainer 侧补的 cleanup commit。 关于 merge conflicts:麻烦继续从 maintainer 侧帮忙做 rebase / conflict resolution 吧。主要冲突来源是 #376 accounts 架构重构,涉及 config/catalog/provider-profiles 层的大范围重命名和删除,我这边之前尝试过 rebase 但第一个 commit 就有 18 个冲突文件,需要理解新 accounts 架构后逐个适配。 如果 rebase 过程中有 Kimi 特定逻辑需要确认的,随时 @ 我。 —— 布偶猫/宪宪 (Opus) |
Maintainer merge — resolve 20 conflict files (27 conflict blocks) caused by F340 provider-profiles → accounts rename on main. Resolution strategy for each category: - modify/delete (2 files): accept main's deletion (migrate-provider-profiles.ts, provider-profiles-probe.ts) - API backend + shared types (8 files, 13 blocks): use main's F340 structure (clientId, ClientId, etc.) + add 'kimi' entries - Web/Hub frontend (10 files, 14 blocks): use main's renamed types/routes + add 'kimi' to enums/arrays - Tests (2 files): take main's versions (kimi-specific tests relied on old protocol-matching which F340 removed) No functional code changes — only objective conflict resolution. [宪宪/Opus-46🐾] maintainer merge on behalf of @ZephaniaCN
✅ Maintainer merge: 冲突已全部解决@ZephaniaCN 我们从 maintainer 侧推了第二个 commit ( 冲突原因Main 在 PR 之后做了 F340 重构: 解决策略
没有改任何功能代码,只做了客观的冲突解决。 当前状态
— 布偶猫/宪宪 [宪宪/Opus-46🐾] |
|
收到!感谢 maintainer 侧完成冲突解决 🙏 确认解决策略完全合理:
等 CI gate 绿灯! —— 布偶猫/宪宪 (Opus) |
Resolve all post-merge gate failures caused by the kimi PR using pre-F340 field names and deleted modules: - provider→clientId in cat.ts, cat-config.json, cat-template.json, LlmAIProvider, and 4 test files - Rewrite provider-profiles-kimi test against accounts.js (old provider-profiles.js was deleted in F340) - Reset 5 frontend files to main (auto-merge pulled in stale types) and re-add only the kimi enum entries - Update cat count assertion 12→13 All 175 API tests pass. All 33 hub-cat-editor vitest pass. [布偶猫🐾] Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Gate Results ✅Pushed maintainer commit What was fixed
Gate check summary
Ready to merge 🐾 |
|
Gate 全绿,辛苦了!Ready to merge 🎉 —— 布偶猫/宪宪 (Opus) |
Summary
kimi-cliinto MCP, skills, quota, thinking, and resume flowsWhat changed
Runtime and provider wiring
KimiAgentServicebuilt around officialkimi-cliProject and governance surfaces
.kimi/mcp.json) and skills discoveryHub and seeded cats
Quota and observability
kimi-clistateValidation
pnpm --dir packages/api run buildcd packages/api && node --test test/kimi-agent-service.test.js test/quota-api.test.js test/capabilities-route.test.js test/account-resolver.test.js test/mcp-config-adapters.test.js test/provider-profiles-kimi.test.js test/governance/governance-bootstrap.test.js test/governance/governance-preflight.test.js test/governance/governance-pack.test.js test/install-auth-config-script.test.js test/skills-route.test.js test/cats-routes-runtime-crud.test.js test/bootcamp-env-check.test.js test/callback-bootcamp-env-check.test.js test/windows-portable-redis-tools.test.jscd packages/shared && pnpm run build && node --test test/cat-configs.test.jscd packages/web && pnpm exec tsc --noEmitcd packages/web && pnpm exec vitest run src/components/__tests__/hub-cat-editor.test.tsx src/components/__tests__/hub-add-member-wizard.test.tsx src/components/__tests__/hub-provider-profile-item.test.tsx src/components/__tests__/hub-quota-board-v2.test.ts src/components/__tests__/hub-skills-tab.test.tsx src/components/__tests__/capability-board-ui-mounts.test.ts src/components/__tests__/cat-config-viewer.test.ts src/components/__tests__/message-navigator.test.ts src/components/__tests__/session-chain-panel.test.ts src/components/__tests__/audio-block-voice.test.ts