@kaitranntt/ccs 7.65.2 → 7.65.3-dev.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (227) hide show
  1. package/README.md +69 -3
  2. package/dist/api/services/profile-lifecycle-service.d.ts.map +1 -1
  3. package/dist/api/services/profile-lifecycle-service.js +4 -0
  4. package/dist/api/services/profile-lifecycle-service.js.map +1 -1
  5. package/dist/api/services/profile-writer.d.ts.map +1 -1
  6. package/dist/api/services/profile-writer.js +3 -0
  7. package/dist/api/services/profile-writer.js.map +1 -1
  8. package/dist/auth/auth-commands.d.ts +1 -0
  9. package/dist/auth/auth-commands.d.ts.map +1 -1
  10. package/dist/auth/auth-commands.js +11 -0
  11. package/dist/auth/auth-commands.js.map +1 -1
  12. package/dist/auth/commands/backup-command.d.ts +3 -0
  13. package/dist/auth/commands/backup-command.d.ts.map +1 -0
  14. package/dist/auth/commands/backup-command.js +126 -0
  15. package/dist/auth/commands/backup-command.js.map +1 -0
  16. package/dist/auth/commands/index.d.ts +1 -0
  17. package/dist/auth/commands/index.d.ts.map +1 -1
  18. package/dist/auth/commands/index.js +3 -1
  19. package/dist/auth/commands/index.js.map +1 -1
  20. package/dist/auth/profile-continuity-inheritance.d.ts +1 -0
  21. package/dist/auth/profile-continuity-inheritance.d.ts.map +1 -1
  22. package/dist/auth/profile-continuity-inheritance.js +10 -6
  23. package/dist/auth/profile-continuity-inheritance.js.map +1 -1
  24. package/dist/auth/profile-detector.d.ts +9 -1
  25. package/dist/auth/profile-detector.d.ts.map +1 -1
  26. package/dist/auth/profile-detector.js +35 -0
  27. package/dist/auth/profile-detector.js.map +1 -1
  28. package/dist/auth/resume-lane-diagnostics.d.ts +21 -0
  29. package/dist/auth/resume-lane-diagnostics.d.ts.map +1 -0
  30. package/dist/auth/resume-lane-diagnostics.js +146 -0
  31. package/dist/auth/resume-lane-diagnostics.js.map +1 -0
  32. package/dist/auth/resume-lane-warning.d.ts +9 -0
  33. package/dist/auth/resume-lane-warning.d.ts.map +1 -0
  34. package/dist/auth/resume-lane-warning.js +60 -0
  35. package/dist/auth/resume-lane-warning.js.map +1 -0
  36. package/dist/ccs.js +79 -7
  37. package/dist/ccs.js.map +1 -1
  38. package/dist/cliproxy/executor/env-resolver.d.ts +3 -0
  39. package/dist/cliproxy/executor/env-resolver.d.ts.map +1 -1
  40. package/dist/cliproxy/executor/env-resolver.js +19 -1
  41. package/dist/cliproxy/executor/env-resolver.js.map +1 -1
  42. package/dist/cliproxy/executor/index.d.ts.map +1 -1
  43. package/dist/cliproxy/executor/index.js +24 -5
  44. package/dist/cliproxy/executor/index.js.map +1 -1
  45. package/dist/cliproxy/gemini-cli-quota-normalizer.d.ts +10 -0
  46. package/dist/cliproxy/gemini-cli-quota-normalizer.d.ts.map +1 -0
  47. package/dist/cliproxy/gemini-cli-quota-normalizer.js +122 -0
  48. package/dist/cliproxy/gemini-cli-quota-normalizer.js.map +1 -0
  49. package/dist/cliproxy/quota-fetcher-gemini-cli.d.ts.map +1 -1
  50. package/dist/cliproxy/quota-fetcher-gemini-cli.js +133 -92
  51. package/dist/cliproxy/quota-fetcher-gemini-cli.js.map +1 -1
  52. package/dist/cliproxy/quota-types.d.ts +8 -0
  53. package/dist/cliproxy/quota-types.d.ts.map +1 -1
  54. package/dist/cliproxy/services/variant-settings.d.ts.map +1 -1
  55. package/dist/cliproxy/services/variant-settings.js +11 -0
  56. package/dist/cliproxy/services/variant-settings.js.map +1 -1
  57. package/dist/commands/cliproxy/quota-subcommand.d.ts.map +1 -1
  58. package/dist/commands/cliproxy/quota-subcommand.js +10 -1
  59. package/dist/commands/cliproxy/quota-subcommand.js.map +1 -1
  60. package/dist/commands/command-catalog.d.ts +39 -0
  61. package/dist/commands/command-catalog.d.ts.map +1 -0
  62. package/dist/commands/command-catalog.js +298 -0
  63. package/dist/commands/command-catalog.js.map +1 -0
  64. package/dist/commands/completion-backend.d.ts +14 -0
  65. package/dist/commands/completion-backend.d.ts.map +1 -0
  66. package/dist/commands/completion-backend.js +208 -0
  67. package/dist/commands/completion-backend.js.map +1 -0
  68. package/dist/commands/cursor-command-display.d.ts.map +1 -1
  69. package/dist/commands/cursor-command-display.js +25 -5
  70. package/dist/commands/cursor-command-display.js.map +1 -1
  71. package/dist/commands/cursor-command.d.ts +1 -3
  72. package/dist/commands/cursor-command.d.ts.map +1 -1
  73. package/dist/commands/cursor-command.js +3 -15
  74. package/dist/commands/cursor-command.js.map +1 -1
  75. package/dist/commands/help-command.d.ts +4 -3
  76. package/dist/commands/help-command.d.ts.map +1 -1
  77. package/dist/commands/help-command.js +155 -507
  78. package/dist/commands/help-command.js.map +1 -1
  79. package/dist/commands/install-command.d.ts.map +1 -1
  80. package/dist/commands/install-command.js +16 -3
  81. package/dist/commands/install-command.js.map +1 -1
  82. package/dist/commands/root-command-router.d.ts +2 -0
  83. package/dist/commands/root-command-router.d.ts.map +1 -1
  84. package/dist/commands/root-command-router.js +13 -13
  85. package/dist/commands/root-command-router.js.map +1 -1
  86. package/dist/commands/shell-completion-command.d.ts +1 -0
  87. package/dist/commands/shell-completion-command.d.ts.map +1 -1
  88. package/dist/commands/shell-completion-command.js +27 -11
  89. package/dist/commands/shell-completion-command.js.map +1 -1
  90. package/dist/copilot/copilot-executor.d.ts +2 -0
  91. package/dist/copilot/copilot-executor.d.ts.map +1 -1
  92. package/dist/copilot/copilot-executor.js +36 -4
  93. package/dist/copilot/copilot-executor.js.map +1 -1
  94. package/dist/cursor/constants.d.ts +3 -0
  95. package/dist/cursor/constants.d.ts.map +1 -0
  96. package/dist/cursor/constants.js +20 -0
  97. package/dist/cursor/constants.js.map +1 -0
  98. package/dist/cursor/cursor-models.d.ts.map +1 -1
  99. package/dist/cursor/cursor-models.js +2 -0
  100. package/dist/cursor/cursor-models.js.map +1 -1
  101. package/dist/cursor/cursor-profile-executor.d.ts +10 -0
  102. package/dist/cursor/cursor-profile-executor.d.ts.map +1 -0
  103. package/dist/cursor/cursor-profile-executor.js +158 -0
  104. package/dist/cursor/cursor-profile-executor.js.map +1 -0
  105. package/dist/cursor/cursor-translator.d.ts +22 -11
  106. package/dist/cursor/cursor-translator.d.ts.map +1 -1
  107. package/dist/cursor/cursor-translator.js +254 -75
  108. package/dist/cursor/cursor-translator.js.map +1 -1
  109. package/dist/cursor/index.d.ts +1 -0
  110. package/dist/cursor/index.d.ts.map +1 -1
  111. package/dist/cursor/index.js +4 -1
  112. package/dist/cursor/index.js.map +1 -1
  113. package/dist/delegation/headless-executor.d.ts.map +1 -1
  114. package/dist/delegation/headless-executor.js +79 -2
  115. package/dist/delegation/headless-executor.js.map +1 -1
  116. package/dist/management/checks/image-analysis-check.d.ts.map +1 -1
  117. package/dist/management/checks/image-analysis-check.js +4 -5
  118. package/dist/management/checks/image-analysis-check.js.map +1 -1
  119. package/dist/management/instance-manager.js +1 -1
  120. package/dist/management/instance-manager.js.map +1 -1
  121. package/dist/shared/claude-extension-setup.d.ts.map +1 -1
  122. package/dist/shared/claude-extension-setup.js +36 -16
  123. package/dist/shared/claude-extension-setup.js.map +1 -1
  124. package/dist/targets/target-runtime-compatibility.d.ts.map +1 -1
  125. package/dist/targets/target-runtime-compatibility.js +6 -0
  126. package/dist/targets/target-runtime-compatibility.js.map +1 -1
  127. package/dist/types/profile.d.ts +1 -1
  128. package/dist/types/profile.d.ts.map +1 -1
  129. package/dist/ui/assets/accounts-BjfPKR8m.js +1 -0
  130. package/dist/ui/assets/{alert-dialog-D0EFRcfB.js → alert-dialog-Dh2NUFdm.js} +1 -1
  131. package/dist/ui/assets/{api-DhM3BYXr.js → api-C-3mQCFf.js} +1 -1
  132. package/dist/ui/assets/{auth-section-DVp8FQGm.js → auth-section-Dp10_YyD.js} +1 -1
  133. package/dist/ui/assets/{backups-section-CRo0NZkA.js → backups-section-C0jF8MP1.js} +1 -1
  134. package/dist/ui/assets/{channels-uZ_9CBqO.js → channels-CkXuK5i7.js} +1 -1
  135. package/dist/ui/assets/{checkbox-32DNqW_Q.js → checkbox-tA5FH8Ol.js} +1 -1
  136. package/dist/ui/assets/{claude-extension-BfXlz5gV.js → claude-extension-Bg2ZkzMz.js} +1 -1
  137. package/dist/ui/assets/{cliproxy-DjNY9H-U.js → cliproxy-1qRVSbVC.js} +2 -2
  138. package/dist/ui/assets/{cliproxy-ai-providers-5SHLMHiy.js → cliproxy-ai-providers-DBSXTTyw.js} +1 -1
  139. package/dist/ui/assets/cliproxy-control-panel-Da-sGGyI.js +1 -0
  140. package/dist/ui/assets/{codex-CRUSpjsu.js → codex-ooWKOPa2.js} +1 -1
  141. package/dist/ui/assets/{confirm-dialog-DVf5ZmCZ.js → confirm-dialog-CKjwhn9j.js} +1 -1
  142. package/dist/ui/assets/{copilot-BZrihl_Z.js → copilot-GA7EPiK1.js} +1 -1
  143. package/dist/ui/assets/{cursor-BP4nbEk_.js → cursor-B6c8CyHG.js} +1 -1
  144. package/dist/ui/assets/{droid-BG92rdM2.js → droid-CPRHOIX2.js} +1 -1
  145. package/dist/ui/assets/{globalenv-section-Cf6dKgSf.js → globalenv-section-Czgnw_GV.js} +1 -1
  146. package/dist/ui/assets/{health-BTy1UZs3.js → health-CXLOMk8n.js} +1 -1
  147. package/dist/ui/assets/icons-B9oTjo-t.js +1 -0
  148. package/dist/ui/assets/index-BMHPMj0j.js +69 -0
  149. package/dist/ui/assets/{index-BVeN0dIB.js → index-BceMcbCR.js} +1 -1
  150. package/dist/ui/assets/{index-N2ZSJurX.js → index-Boa5e-GY.js} +1 -1
  151. package/dist/ui/assets/index-CknHGRYp.css +1 -0
  152. package/dist/ui/assets/{index-wg7UtkFv.js → index-CvfzKRSH.js} +1 -1
  153. package/dist/ui/assets/{index-DuRYaONg.js → index-D2v_-6AW.js} +1 -1
  154. package/dist/ui/assets/{index-DHrTq-0n.js → index-v-DY6Zby.js} +1 -1
  155. package/dist/ui/assets/{masked-input-DX9bedLy.js → masked-input-B1_asiUI.js} +1 -1
  156. package/dist/ui/assets/{proxy-status-widget-DVDMuZK5.js → proxy-status-widget-Ci1JpStj.js} +1 -1
  157. package/dist/ui/assets/{radix-ui-C98W0NRG.js → radix-ui-Zb8sVEtn.js} +1 -1
  158. package/dist/ui/assets/{raw-json-settings-editor-panel-Dkt5E6Z_.js → raw-json-settings-editor-panel-DMbTkxWw.js} +1 -1
  159. package/dist/ui/assets/{searchable-select-BP3Q1-Yn.js → searchable-select-HbP2PXl3.js} +1 -1
  160. package/dist/ui/assets/{separator-BLGGUlh9.js → separator-CdaalG0K.js} +1 -1
  161. package/dist/ui/assets/{shared-G0XRyLig.js → shared-BiFB-et0.js} +1 -1
  162. package/dist/ui/assets/{table-B4lRrWC-.js → table-BPwgFXLQ.js} +1 -1
  163. package/dist/ui/assets/{tanstack-CfKik0yL.js → tanstack-DWm6aJ-G.js} +1 -1
  164. package/dist/ui/assets/{updates--A2Sdo7N.js → updates-l8Co9uve.js} +1 -1
  165. package/dist/ui/index.html +5 -5
  166. package/dist/utils/config-manager.d.ts +5 -0
  167. package/dist/utils/config-manager.d.ts.map +1 -1
  168. package/dist/utils/config-manager.js +10 -1
  169. package/dist/utils/config-manager.js.map +1 -1
  170. package/dist/utils/hooks/get-image-analysis-hook-env.d.ts +26 -0
  171. package/dist/utils/hooks/get-image-analysis-hook-env.d.ts.map +1 -1
  172. package/dist/utils/hooks/get-image-analysis-hook-env.js +79 -1
  173. package/dist/utils/hooks/get-image-analysis-hook-env.js.map +1 -1
  174. package/dist/utils/hooks/image-analysis-backend-resolver.d.ts.map +1 -1
  175. package/dist/utils/hooks/image-analysis-backend-resolver.js +13 -5
  176. package/dist/utils/hooks/image-analysis-backend-resolver.js.map +1 -1
  177. package/dist/utils/hooks/image-analysis-runtime-status.d.ts +2 -0
  178. package/dist/utils/hooks/image-analysis-runtime-status.d.ts.map +1 -1
  179. package/dist/utils/hooks/image-analysis-runtime-status.js +15 -11
  180. package/dist/utils/hooks/image-analysis-runtime-status.js.map +1 -1
  181. package/dist/utils/hooks/image-analyzer-hook-installer.d.ts.map +1 -1
  182. package/dist/utils/hooks/image-analyzer-hook-installer.js +60 -27
  183. package/dist/utils/hooks/image-analyzer-hook-installer.js.map +1 -1
  184. package/dist/utils/hooks/image-analyzer-profile-hook-injector.d.ts.map +1 -1
  185. package/dist/utils/hooks/image-analyzer-profile-hook-injector.js +3 -0
  186. package/dist/utils/hooks/image-analyzer-profile-hook-injector.js.map +1 -1
  187. package/dist/utils/hooks/index.d.ts +2 -1
  188. package/dist/utils/hooks/index.d.ts.map +1 -1
  189. package/dist/utils/hooks/index.js +14 -7
  190. package/dist/utils/hooks/index.js.map +1 -1
  191. package/dist/utils/image-analysis/claude-tool-args.d.ts +6 -0
  192. package/dist/utils/image-analysis/claude-tool-args.d.ts.map +1 -0
  193. package/dist/utils/image-analysis/claude-tool-args.js +65 -0
  194. package/dist/utils/image-analysis/claude-tool-args.js.map +1 -0
  195. package/dist/utils/image-analysis/index.d.ts +4 -0
  196. package/dist/utils/image-analysis/index.d.ts.map +1 -1
  197. package/dist/utils/image-analysis/index.js +20 -1
  198. package/dist/utils/image-analysis/index.js.map +1 -1
  199. package/dist/utils/image-analysis/mcp-installer.d.ts +18 -0
  200. package/dist/utils/image-analysis/mcp-installer.d.ts.map +1 -0
  201. package/dist/utils/image-analysis/mcp-installer.js +447 -0
  202. package/dist/utils/image-analysis/mcp-installer.js.map +1 -0
  203. package/dist/web-server/routes/account-routes.d.ts.map +1 -1
  204. package/dist/web-server/routes/account-routes.js +14 -2
  205. package/dist/web-server/routes/account-routes.js.map +1 -1
  206. package/dist/web-server/routes/cliproxy-auth-routes.d.ts.map +1 -1
  207. package/dist/web-server/routes/cliproxy-auth-routes.js +80 -6
  208. package/dist/web-server/routes/cliproxy-auth-routes.js.map +1 -1
  209. package/dist/web-server/routes/image-analysis-routes.d.ts.map +1 -1
  210. package/dist/web-server/routes/image-analysis-routes.js +30 -5
  211. package/dist/web-server/routes/image-analysis-routes.js.map +1 -1
  212. package/lib/hooks/image-analysis-runtime.cjs +469 -0
  213. package/lib/hooks/image-analyzer-transformer.cjs +27 -418
  214. package/lib/hooks/websearch-transformer.cjs +37 -2
  215. package/lib/mcp/ccs-image-analysis-server.cjs +440 -0
  216. package/package.json +1 -1
  217. package/scripts/completion/README.md +55 -131
  218. package/scripts/completion/ccs.bash +22 -190
  219. package/scripts/completion/ccs.fish +19 -245
  220. package/scripts/completion/ccs.ps1 +37 -427
  221. package/scripts/completion/ccs.zsh +27 -305
  222. package/scripts/github/normalize-ai-review-output.mjs +95 -33
  223. package/dist/ui/assets/accounts-BHEYnq6b.js +0 -1
  224. package/dist/ui/assets/cliproxy-control-panel-Zax_m1AC.js +0 -1
  225. package/dist/ui/assets/icons-CeH5899d.js +0 -1
  226. package/dist/ui/assets/index-B6SrL1O-.css +0 -1
  227. package/dist/ui/assets/index-Corv1lSo.js +0 -69
@@ -1,319 +1,41 @@
1
1
  #compdef ccs
2
2
 
3
3
  # Zsh completion for CCS (Claude Code Switch)
4
- # Compatible with zsh 5.0+
5
- #
6
- # Installation:
7
- # Add to ~/.zshrc:
8
- # fpath=(~/.zsh/completion $fpath)
9
- # autoload -Uz compinit && compinit
10
- # source /path/to/ccs/scripts/completion/ccs.zsh
11
- #
12
- # Or install system-wide:
13
- # sudo cp scripts/completion/ccs.zsh /usr/local/share/zsh/site-functions/_ccs
14
-
15
- # Set up completion styles for better formatting and colors
16
- zstyle ':completion:*:*:ccs:*:commands' list-colors '=(#b)(auth|api|cliproxy|doctor|env|sync|update)([[:space:]]#--[[:space:]]#*)==0\;34=2\;37'
17
- zstyle ':completion:*:*:ccs:*:proxy-profiles' list-colors '=(#b)(gemini|codex|agy|qwen)([[:space:]]#--[[:space:]]#*)==0\;35=2\;37'
18
- zstyle ':completion:*:*:ccs:*:model-profiles' list-colors '=(#b)(default|glm|kimi|[^[:space:]]##)([[:space:]]#--[[:space:]]#*)==0\;32=2\;37'
19
- zstyle ':completion:*:*:ccs:*:account-profiles' list-colors '=(#b)([^[:space:]]##)([[:space:]]#--[[:space:]]#*)==0\;33=2\;37'
20
- zstyle ':completion:*:*:ccs:*' group-name ''
21
- zstyle ':completion:*:*:ccs:*:descriptions' format $'\n%B%F{yellow}── %d ──%f%b'
22
- zstyle ':completion:*:*:ccs:*' list-separator ' -- '
23
- zstyle ':completion:*:*:ccs:*' list-rows-first true
24
- zstyle ':completion:*:*:ccs:*' menu select
25
4
 
26
5
  _ccs() {
27
- local -a commands proxy_profiles settings_profiles_described account_profiles_described cliproxy_variants_described
28
- local curcontext="$curcontext" state line
29
- typeset -A opt_args
30
-
31
- # Define top-level commands
32
- commands=(
33
- 'auth:Manage multiple Claude accounts'
34
- 'api:Manage API profiles (create/remove)'
35
- 'cliproxy:Manage CLIProxy variants and binary'
36
- 'doctor:Run health check and diagnostics'
37
- 'env:Export env vars for third-party tools'
38
- 'sync:Sync delegation commands and skills'
39
- 'update:Update CCS to latest version'
40
- )
41
-
42
- # Define CLIProxy hardcoded profiles (OAuth providers)
43
- proxy_profiles=(
44
- 'gemini:Google Gemini (OAuth)'
45
- 'codex:OpenAI Codex (OAuth)'
46
- 'agy:Antigravity (OAuth)'
47
- 'qwen:Qwen Code (OAuth)'
48
- 'iflow:iFlow (OAuth)'
49
- 'kiro:Kiro (OAuth)'
50
- 'ghcp:GitHub Copilot (OAuth)'
51
- 'claude:Claude Direct (OAuth)'
52
- )
53
-
54
- # Define known settings profiles with descriptions
55
- local -A profile_descriptions
56
- profile_descriptions=(
57
- 'default' 'Default Claude Sonnet 4.5'
58
- 'glm' 'GLM-4.6 (cost-optimized)'
59
- 'kimi' 'Kimi for Coding (long-context)'
60
- )
61
-
62
- # Load settings-based profiles from config.json
63
- if [[ -f ~/.ccs/config.json ]]; then
64
- local -a raw_settings_profiles
65
- raw_settings_profiles=(${(f)"$(jq -r '.profiles | keys[]' ~/.ccs/config.json 2>/dev/null)"})
66
-
67
- for profile in $raw_settings_profiles; do
68
- local desc="${profile_descriptions[$profile]:-Settings-based profile}"
69
- settings_profiles_described+=("${profile}:${desc}")
70
- done
6
+ local current
7
+ current="${words[CURRENT]}"
8
+
9
+ local -a tokens_before_current
10
+ if (( CURRENT > 2 )); then
11
+ tokens_before_current=("${words[@]:2:$((CURRENT-2))}")
12
+ else
13
+ tokens_before_current=()
71
14
  fi
72
15
 
73
- # Load account-based profiles from profiles.json
74
- if [[ -f ~/.ccs/profiles.json ]]; then
75
- local -a raw_account_profiles
76
- raw_account_profiles=(${(f)"$(jq -r '.profiles | keys[]' ~/.ccs/profiles.json 2>/dev/null)"})
77
-
78
- for profile in $raw_account_profiles; do
79
- account_profiles_described+=("${profile}:Account-based profile")
80
- done
81
- fi
82
-
83
- # Load cliproxy variants from config.json
84
- if [[ -f ~/.ccs/config.json ]]; then
85
- local -a raw_cliproxy_variants
86
- raw_cliproxy_variants=(${(f)"$(jq -r '.cliproxy | keys[]' ~/.ccs/config.json 2>/dev/null)"})
87
-
88
- for variant in $raw_cliproxy_variants; do
89
- cliproxy_variants_described+=("${variant}:CLIProxy variant")
90
- done
91
- fi
92
-
93
- _arguments -C \
94
- '(- *)'{-h,--help}'[Show help message]' \
95
- '(- *)'{-v,--version}'[Show version information]' \
96
- '(- *)'{-sc,--shell-completion}'[Install shell completion]' \
97
- '1: :->command' \
98
- '*:: :->args'
99
-
100
- case $state in
101
- command)
102
- _describe -t commands 'commands' commands
103
- _describe -t proxy-profiles 'CLIProxy profiles' proxy_profiles
104
- _describe -t model-profiles 'model profiles' settings_profiles_described
105
- _describe -t account-profiles 'account profiles' account_profiles_described
106
- _describe -t cliproxy-variants 'CLIProxy variants' cliproxy_variants_described
107
- ;;
108
-
109
- args)
110
- case $words[1] in
111
- auth)
112
- _ccs_auth
113
- ;;
114
- api)
115
- _ccs_api
116
- ;;
117
- cliproxy)
118
- _ccs_cliproxy
119
- ;;
120
- update)
121
- _arguments \
122
- '--force[Force reinstall current version]' \
123
- '--beta[Install from dev channel]' \
124
- '--dev[Install from dev channel]' \
125
- '(- *)'{-h,--help}'[Show help]'
126
- ;;
127
- doctor)
128
- _arguments \
129
- '(- *)'{-h,--help}'[Show help for doctor command]'
130
- ;;
131
- env)
132
- _arguments \
133
- '--format[Output format]:format:(openai anthropic raw)' \
134
- '--shell[Shell syntax]:shell:(auto bash zsh fish powershell)' \
135
- '(- *)'{-h,--help}'[Show help]' \
136
- '1:profile:($proxy_profiles ${(k)settings_profiles_described})'
137
- ;;
138
- gemini|codex|agy|qwen)
139
- _arguments \
140
- '--auth[Authenticate only]' \
141
- '--config[Change model configuration]' \
142
- '--logout[Clear authentication]' \
143
- '--headless[Headless auth (for SSH)]' \
144
- '(- *)'{-h,--help}'[Show help]'
145
- ;;
146
- --shell-completion|-sc)
147
- _arguments \
148
- '--bash[Install for bash]' \
149
- '--zsh[Install for zsh]' \
150
- '--fish[Install for fish]' \
151
- '--powershell[Install for PowerShell]'
152
- ;;
153
- *)
154
- _message 'Claude CLI arguments'
155
- ;;
156
- esac
157
- ;;
158
- esac
16
+ local -a suggestions
17
+ suggestions=("${(@f)$(__ccs_completion_run "${current}" "${tokens_before_current[@]}")}")
18
+ compadd -- "${suggestions[@]}"
159
19
  }
160
20
 
161
- _ccs_api() {
162
- local curcontext="$curcontext" state line
163
- typeset -A opt_args
164
-
165
- local -a api_commands settings_profiles
166
-
167
- api_commands=(
168
- 'create:Create new API profile (interactive)'
169
- 'list:List all API profiles'
170
- 'remove:Remove an API profile'
171
- )
172
-
173
- if [[ -f ~/.ccs/config.json ]]; then
174
- settings_profiles=(${(f)"$(jq -r '.profiles | keys[]' ~/.ccs/config.json 2>/dev/null)"})
21
+ __ccs_completion_run() {
22
+ local current="$1"
23
+ shift || true
24
+
25
+ local script_path script_dir repo_root repo_cli
26
+ script_path="${(%):-%N}"
27
+ script_dir="${script_path:A:h}"
28
+ repo_root="${script_dir:h:h}"
29
+ repo_cli="${repo_root}/dist/ccs.js"
30
+ if [[ ! -f "${repo_cli}" ]]; then
31
+ repo_cli="${repo_root}/bin/ccs.js"
175
32
  fi
176
-
177
- _arguments -C \
178
- '(- *)'{-h,--help}'[Show help for api commands]' \
179
- '1: :->subcommand' \
180
- '*:: :->subargs'
181
-
182
- case $state in
183
- subcommand)
184
- _describe -t api-commands 'api commands' api_commands
185
- ;;
186
-
187
- subargs)
188
- case $words[1] in
189
- create)
190
- _arguments \
191
- '1:profile name:' \
192
- '--base-url[API base URL]:url:' \
193
- '--api-key[API key]:key:' \
194
- '--model[Default model]:model:' \
195
- '--force[Overwrite existing profile]' \
196
- {--yes,-y}'[Skip prompts]'
197
- ;;
198
- list)
199
- ;;
200
- remove|delete|rm)
201
- _arguments \
202
- '1:profile:($settings_profiles)' \
203
- {--yes,-y}'[Skip confirmation]'
204
- ;;
205
- esac
206
- ;;
207
- esac
208
- }
209
-
210
- _ccs_cliproxy() {
211
- local curcontext="$curcontext" state line
212
- typeset -A opt_args
213
-
214
- local -a cliproxy_commands cliproxy_variants providers
215
-
216
- cliproxy_commands=(
217
- 'create:Create new CLIProxy variant profile'
218
- 'list:List all CLIProxy variant profiles'
219
- 'remove:Remove a CLIProxy variant profile'
220
- )
221
-
222
- providers=(gemini codex agy qwen)
223
-
224
- if [[ -f ~/.ccs/config.json ]]; then
225
- cliproxy_variants=(${(f)"$(jq -r '.cliproxy | keys[]' ~/.ccs/config.json 2>/dev/null)"})
33
+ if [[ -f "${repo_cli}" ]]; then
34
+ node "${repo_cli}" __complete --shell zsh --current "${current}" -- "$@" 2>/dev/null
35
+ return 0
226
36
  fi
227
37
 
228
- _arguments -C \
229
- '(- *)'{-h,--help}'[Show help for cliproxy commands]' \
230
- '--install[Install specific version]:version:' \
231
- '--latest[Install latest version]' \
232
- '1: :->subcommand' \
233
- '*:: :->subargs'
234
-
235
- case $state in
236
- subcommand)
237
- _describe -t cliproxy-commands 'cliproxy commands' cliproxy_commands
238
- ;;
239
-
240
- subargs)
241
- case $words[1] in
242
- create)
243
- _arguments \
244
- '1:variant name:' \
245
- '--provider[Provider name]:provider:($providers)' \
246
- '--model[Model name]:model:' \
247
- '--force[Overwrite existing variant]' \
248
- {--yes,-y}'[Skip prompts]'
249
- ;;
250
- list|ls)
251
- ;;
252
- remove|delete|rm)
253
- _arguments \
254
- '1:variant:($cliproxy_variants)' \
255
- {--yes,-y}'[Skip confirmation]'
256
- ;;
257
- esac
258
- ;;
259
- esac
260
- }
261
-
262
- _ccs_auth() {
263
- local curcontext="$curcontext" state line
264
- typeset -A opt_args
265
-
266
- local -a auth_commands account_profiles
267
-
268
- auth_commands=(
269
- 'create:Create new profile and login'
270
- 'list:List all saved profiles'
271
- 'show:Show profile details'
272
- 'remove:Remove saved profile'
273
- 'default:Set default profile'
274
- )
275
-
276
- if [[ -f ~/.ccs/profiles.json ]]; then
277
- account_profiles=(${(f)"$(jq -r '.profiles | keys[]' ~/.ccs/profiles.json 2>/dev/null)"})
38
+ if (( $+commands[ccs] )); then
39
+ ccs __complete --shell zsh --current "${current}" -- "$@" 2>/dev/null
278
40
  fi
279
-
280
- _arguments -C \
281
- '(- *)'{-h,--help}'[Show help for auth commands]' \
282
- '1: :->subcommand' \
283
- '*:: :->subargs'
284
-
285
- case $state in
286
- subcommand)
287
- _describe -t auth-commands 'auth commands' auth_commands
288
- ;;
289
-
290
- subargs)
291
- case $words[1] in
292
- create)
293
- _message 'new profile name'
294
- _arguments '--force[Allow overwriting existing profile]'
295
- ;;
296
- list)
297
- _arguments \
298
- '--verbose[Show additional details]' \
299
- '--json[Output in JSON format]'
300
- ;;
301
- show)
302
- _arguments \
303
- '1:profile:($account_profiles)' \
304
- '--json[Output in JSON format]'
305
- ;;
306
- remove)
307
- _arguments \
308
- '1:profile:($account_profiles)' \
309
- {--yes,-y}'[Skip confirmation prompts]'
310
- ;;
311
- default)
312
- _arguments '1:profile:($account_profiles)'
313
- ;;
314
- esac
315
- ;;
316
- esac
317
41
  }
318
-
319
- _ccs "$@"
@@ -65,7 +65,9 @@ function cleanMultilineText(value) {
65
65
  }
66
66
 
67
67
  function escapeMarkdown(value) {
68
- return String(value).replace(/\\/g, '\\\\').replace(/([`*_{}[\]<>|])/g, '\\$1');
68
+ return String(value)
69
+ .replace(/\\/g, '\\\\')
70
+ .replace(/([`*_{}[\]<>|])/g, '\\$1');
69
71
  }
70
72
 
71
73
  function escapeMarkdownText(value) {
@@ -155,7 +157,8 @@ function normalizeRenderingMetadata(raw) {
155
157
  if (packetIncludedFiles !== null) metadata.packetIncludedFiles = packetIncludedFiles;
156
158
  if (packetTotalFiles !== null) metadata.packetTotalFiles = packetTotalFiles;
157
159
  if (packetOmittedFiles !== null) metadata.packetOmittedFiles = packetOmittedFiles;
158
- if (scopeLabel === 'reviewable files' || scopeLabel === 'changed files') metadata.scopeLabel = scopeLabel;
160
+ if (scopeLabel === 'reviewable files' || scopeLabel === 'changed files')
161
+ metadata.scopeLabel = scopeLabel;
159
162
 
160
163
  return metadata;
161
164
  }
@@ -203,7 +206,8 @@ function formatScopeSummary(rendering) {
203
206
  typeof rendering.selectedChanges === 'number' &&
204
207
  typeof rendering.reviewableChanges === 'number'
205
208
  ) {
206
- const changeLabel = scopeLabel === 'reviewable files' ? 'reviewable changed lines' : 'changed lines';
209
+ const changeLabel =
210
+ scopeLabel === 'reviewable files' ? 'reviewable changed lines' : 'changed lines';
207
211
  return `${fileScope}; ${rendering.selectedChanges}/${rendering.reviewableChanges} ${changeLabel}`;
208
212
  }
209
213
 
@@ -254,7 +258,8 @@ function formatReviewContext(rendering) {
254
258
  parts.push(`packet ${rendering.packetIncludedFiles}/${rendering.packetTotalFiles}`);
255
259
  }
256
260
 
257
- const runtimeBudget = formatCombinedBudget(rendering) || formatTimeBudget(rendering) || formatTurnBudget(rendering);
261
+ const runtimeBudget =
262
+ formatCombinedBudget(rendering) || formatTimeBudget(rendering) || formatTurnBudget(rendering);
258
263
  if (runtimeBudget) {
259
264
  parts.push(runtimeBudget);
260
265
  }
@@ -301,7 +306,10 @@ function describeIncompleteOutcome({ reason, rendering, turnsUsed, status }) {
301
306
  return `The ${reviewLabel} ended before it could produce validated structured output within the available ${combinedBudget} runtime budget.`;
302
307
  }
303
308
 
304
- if (classifyFallbackReason(reason) === 'missing' || classifyFallbackReason(reason) === 'invalid_json') {
309
+ if (
310
+ classifyFallbackReason(reason) === 'missing' ||
311
+ classifyFallbackReason(reason) === 'invalid_json'
312
+ ) {
305
313
  return `The ${reviewLabel} ended without validated structured output, so the normalizer published the safe fallback comment instead.`;
306
314
  }
307
315
 
@@ -344,7 +352,10 @@ function normalizeChecklistRows(fieldName, labelField, raw) {
344
352
 
345
353
  const rows = [];
346
354
  for (const [index, item] of raw.entries()) {
347
- const label = validatePlainTextField(`${fieldName}[${index}].${labelField}`, item?.[labelField]);
355
+ const label = validatePlainTextField(
356
+ `${fieldName}[${index}].${labelField}`,
357
+ item?.[labelField]
358
+ );
348
359
  if (!label.ok) return label;
349
360
 
350
361
  const notes = validatePlainTextField(`${fieldName}[${index}].notes`, item?.notes);
@@ -479,16 +490,19 @@ function formatHotspotFiles(files) {
479
490
  function formatRemainingCoverage(rendering) {
480
491
  if (
481
492
  typeof rendering.reviewableFiles !== 'number' ||
482
- (typeof rendering.packetIncludedFiles !== 'number' && typeof rendering.selectedFiles !== 'number')
493
+ (typeof rendering.packetIncludedFiles !== 'number' &&
494
+ typeof rendering.selectedFiles !== 'number')
483
495
  ) {
484
496
  return null;
485
497
  }
486
498
 
487
- const coveredFiles = typeof rendering.packetIncludedFiles === 'number'
488
- ? rendering.packetIncludedFiles
489
- : rendering.selectedFiles;
499
+ const coveredFiles =
500
+ typeof rendering.packetIncludedFiles === 'number'
501
+ ? rendering.packetIncludedFiles
502
+ : rendering.selectedFiles;
490
503
  const remainingFiles = Math.max(rendering.reviewableFiles - coveredFiles, 0);
491
- const packetOmittedFiles = typeof rendering.packetOmittedFiles === 'number' ? rendering.packetOmittedFiles : 0;
504
+ const packetOmittedFiles =
505
+ typeof rendering.packetOmittedFiles === 'number' ? rendering.packetOmittedFiles : 0;
492
506
  const hasChangeCounts =
493
507
  packetOmittedFiles === 0 &&
494
508
  typeof rendering.selectedChanges === 'number' &&
@@ -540,7 +554,11 @@ export function normalizeStructuredOutput(raw) {
540
554
  if (!overallRationale.ok) return overallRationale;
541
555
 
542
556
  const findings = Array.isArray(parsed.findings) ? parsed.findings : null;
543
- const securityChecklist = normalizeChecklistRows('securityChecklist', 'check', parsed.securityChecklist);
557
+ const securityChecklist = normalizeChecklistRows(
558
+ 'securityChecklist',
559
+ 'check',
560
+ parsed.securityChecklist
561
+ );
544
562
  if (!securityChecklist.ok) return securityChecklist;
545
563
 
546
564
  const ccsCompliance = normalizeChecklistRows('ccsCompliance', 'rule', parsed.ccsCompliance);
@@ -582,7 +600,11 @@ export function normalizeStructuredOutput(raw) {
582
600
  if (finding && Object.hasOwn(finding, 'line')) {
583
601
  if (finding.line === null) {
584
602
  line = null;
585
- } else if (typeof finding.line === 'number' && Number.isInteger(finding.line) && finding.line > 0) {
603
+ } else if (
604
+ typeof finding.line === 'number' &&
605
+ Number.isInteger(finding.line) &&
606
+ finding.line > 0
607
+ ) {
586
608
  line = finding.line;
587
609
  } else {
588
610
  return { ok: false, reason: `findings[${index}].line is invalid` };
@@ -668,7 +690,9 @@ function renderFindingReference(finding) {
668
690
  }
669
691
 
670
692
  function getOrderedFindings(findings) {
671
- return SEVERITY_ORDER.flatMap((severity) => findings.filter((finding) => finding.severity === severity));
693
+ return SEVERITY_ORDER.flatMap((severity) =>
694
+ findings.filter((finding) => finding.severity === severity)
695
+ );
672
696
  }
673
697
 
674
698
  function renderTopFindings(findings) {
@@ -726,37 +750,65 @@ function renderDetailedFindings(findings) {
726
750
 
727
751
  export function renderStructuredReview(review, { model, rendering: renderOptions } = {}) {
728
752
  const rendering = mergeRenderingMetadata(review?.rendering, renderOptions);
729
- const lines = [
730
- '### Verdict',
731
- '',
732
- `**${ASSESSMENTS[review.overallAssessment]}** — ${renderInlineText(review.overallRationale)}`,
733
- '',
734
- renderInlineText(review.summary),
735
- ];
753
+ const lines = ['### 📋 Summary', '', renderInlineText(review.summary)];
736
754
  const reviewContext = formatReviewContext(rendering);
737
755
 
738
756
  if (reviewContext) {
739
757
  lines.push('', reviewContext);
740
758
  }
741
759
 
742
- lines.push('', '### Top Findings', '', ...renderTopFindings(review.findings));
743
- lines.push(...renderSection(`### Detailed Findings (${review.findings.length})`, renderDetailedFindings(review.findings)));
760
+ lines.push('', '### 🔍 Findings');
761
+ if (review.findings.length === 0) {
762
+ lines.push('', 'No confirmed issues found after reviewing the diff and surrounding code.');
763
+ } else {
764
+ for (const severity of SEVERITY_ORDER) {
765
+ const scopedFindings = review.findings.filter((finding) => finding.severity === severity);
766
+ if (scopedFindings.length === 0) continue;
767
+
768
+ lines.push('', SEVERITY_HEADERS[severity], '');
769
+ for (const finding of scopedFindings) {
770
+ const snippets = Array.isArray(finding.snippets) ? finding.snippets : [];
771
+ lines.push(
772
+ `- **${renderCode(renderFindingReference(finding))} — ${renderInlineText(finding.title)}**`
773
+ );
774
+ lines.push(` Problem: ${renderInlineText(finding.what)}`);
775
+ lines.push(` Why it matters: ${renderInlineText(finding.why)}`);
776
+ lines.push(` Suggested fix: ${renderInlineText(finding.fix)}`);
777
+
778
+ if (snippets.length > 0) {
779
+ lines.push('');
780
+ lines.push(...renderFindingSnippets(snippets));
781
+ }
782
+
783
+ lines.push('');
784
+ }
785
+ }
786
+
787
+ if (lines[lines.length - 1] === '') {
788
+ lines.pop();
789
+ }
790
+ }
791
+
744
792
  lines.push(
745
793
  ...renderSection(
746
- `### Security Checklist (${review.securityChecklist.length})`,
794
+ '### 🔒 Security Checklist',
747
795
  renderChecklistTable('Check', 'check', review.securityChecklist)
748
796
  )
749
797
  );
750
798
  lines.push(
751
799
  ...renderSection(
752
- `### CCS Compliance (${review.ccsCompliance.length})`,
800
+ '### 📊 CCS Compliance',
753
801
  renderChecklistTable('Rule', 'rule', review.ccsCompliance)
754
802
  )
755
803
  );
756
- lines.push(...renderSection(`### Informational (${review.informational.length})`, renderBulletSection(review.informational)));
757
- lines.push(...renderSection(`### What's Done Well (${review.strengths.length})`, renderBulletSection(review.strengths)));
804
+ lines.push(...renderSection('### 💡 Informational', renderBulletSection(review.informational)));
805
+ lines.push(...renderSection("### What's Done Well", renderBulletSection(review.strengths)));
758
806
 
759
807
  lines.push(
808
+ '',
809
+ '### 🎯 Overall Assessment',
810
+ '',
811
+ `**${ASSESSMENTS[review.overallAssessment]}** — ${renderInlineText(review.overallRationale)}`,
760
812
  '',
761
813
  `> 🤖 Reviewed by \`${model}\``
762
814
  );
@@ -784,7 +836,9 @@ export function renderIncompleteReview({
784
836
  ];
785
837
 
786
838
  if (rendering.mode) {
787
- lines.push(`- Review mode: ${renderCode(rendering.mode)} (${escapeMarkdownText(REVIEW_MODE_DETAILS[rendering.mode])})`);
839
+ lines.push(
840
+ `- Review mode: ${renderCode(rendering.mode)} (${escapeMarkdownText(REVIEW_MODE_DETAILS[rendering.mode])})`
841
+ );
788
842
  }
789
843
  const scopeSummary = formatScopeSummary(rendering);
790
844
  if (scopeSummary) {
@@ -804,7 +858,9 @@ export function renderIncompleteReview({
804
858
  }
805
859
  const remainingCoverage = formatRemainingCoverage(rendering);
806
860
  if (remainingCoverage) {
807
- lines.push(`- Remaining reviewable scope not fully covered: ${escapeMarkdownText(remainingCoverage)}`);
861
+ lines.push(
862
+ `- Remaining reviewable scope not fully covered: ${escapeMarkdownText(remainingCoverage)}`
863
+ );
808
864
  }
809
865
  lines.push(`- Manual follow-up: ${escapeMarkdownText(formatFallbackFollowUp(rendering))}`);
810
866
  if (runtimeTools?.length) {
@@ -814,7 +870,12 @@ export function renderIncompleteReview({
814
870
  lines.push(`- Turns used: ${turnsUsed}`);
815
871
  }
816
872
 
817
- lines.push('', `Re-run \`/review\` or inspect [the workflow run](${runUrl}).`, '', `> 🤖 Reviewed by \`${model}\``);
873
+ lines.push(
874
+ '',
875
+ `Re-run \`/review\` or inspect [the workflow run](${runUrl}).`,
876
+ '',
877
+ `> 🤖 Reviewed by \`${model}\``
878
+ );
818
879
  return lines.join('\n');
819
880
  }
820
881
 
@@ -857,15 +918,16 @@ export function writeReviewFromEnv(env = process.env) {
857
918
  fs.writeFileSync(outputFile, `${content}\n`, 'utf8');
858
919
 
859
920
  if (!validation.ok) {
860
- console.warn(`::warning::AI review output normalization fell back to incomplete comment: ${validation.reason}`);
921
+ console.warn(
922
+ `::warning::AI review output normalization fell back to incomplete comment: ${validation.reason}`
923
+ );
861
924
  }
862
925
 
863
926
  return { usedFallback: !validation.ok, content };
864
927
  }
865
928
 
866
929
  const isMain =
867
- process.argv[1] &&
868
- path.resolve(process.argv[1]) === path.resolve(fileURLToPath(import.meta.url));
930
+ process.argv[1] && path.resolve(process.argv[1]) === path.resolve(fileURLToPath(import.meta.url));
869
931
 
870
932
  if (isMain) {
871
933
  writeReviewFromEnv();