@kaitranntt/ccs 7.79.1 → 8.0.0-dev.1
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.
- package/README.md +29 -11
- package/dist/bin/ccsxp-runtime.d.ts.map +1 -1
- package/dist/bin/ccsxp-runtime.js +8 -0
- package/dist/bin/ccsxp-runtime.js.map +1 -1
- package/dist/bin/codex-runtime-router.d.ts +24 -0
- package/dist/bin/codex-runtime-router.d.ts.map +1 -0
- package/dist/bin/codex-runtime-router.js +117 -0
- package/dist/bin/codex-runtime-router.js.map +1 -0
- package/dist/bin/codex-runtime.d.ts +1 -0
- package/dist/bin/codex-runtime.js +7 -2
- package/dist/bin/codex-runtime.js.map +1 -1
- package/dist/ccs.js +2 -1
- package/dist/ccs.js.map +1 -1
- package/dist/cliproxy/ai-providers/codex-plan-compatibility.js +2 -2
- package/dist/cliproxy/ai-providers/codex-plan-compatibility.js.map +1 -1
- package/dist/cliproxy/ai-providers/codex-reasoning-proxy.d.ts +2 -2
- package/dist/cliproxy/ai-providers/codex-reasoning-proxy.d.ts.map +1 -1
- package/dist/cliproxy/ai-providers/codex-reasoning-proxy.js +16 -8
- package/dist/cliproxy/ai-providers/codex-reasoning-proxy.js.map +1 -1
- package/dist/cliproxy/ai-providers/model-id-normalizer.d.ts +8 -0
- package/dist/cliproxy/ai-providers/model-id-normalizer.d.ts.map +1 -1
- package/dist/cliproxy/ai-providers/model-id-normalizer.js +19 -2
- package/dist/cliproxy/ai-providers/model-id-normalizer.js.map +1 -1
- package/dist/cliproxy/ai-providers/service.d.ts.map +1 -1
- package/dist/cliproxy/ai-providers/service.js +39 -12
- package/dist/cliproxy/ai-providers/service.js.map +1 -1
- package/dist/cliproxy/auth/oauth-handler.d.ts +13 -1
- package/dist/cliproxy/auth/oauth-handler.d.ts.map +1 -1
- package/dist/cliproxy/auth/oauth-handler.js +111 -34
- package/dist/cliproxy/auth/oauth-handler.js.map +1 -1
- package/dist/cliproxy/auth/oauth-trace/redactor.d.ts.map +1 -1
- package/dist/cliproxy/auth/oauth-trace/redactor.js +9 -1
- package/dist/cliproxy/auth/oauth-trace/redactor.js.map +1 -1
- package/dist/cliproxy/config/generator.d.ts.map +1 -1
- package/dist/cliproxy/config/generator.js +5 -2
- package/dist/cliproxy/config/generator.js.map +1 -1
- package/dist/cliproxy/config/thinking-config.js +6 -6
- package/dist/cliproxy/config/thinking-config.js.map +1 -1
- package/dist/cliproxy/executor/env-resolver.js +1 -1
- package/dist/cliproxy/executor/env-resolver.js.map +1 -1
- package/dist/cliproxy/executor/session-bridge.d.ts.map +1 -1
- package/dist/cliproxy/executor/session-bridge.js +11 -8
- package/dist/cliproxy/executor/session-bridge.js.map +1 -1
- package/dist/cliproxy/quota/quota-fetcher-claude.d.ts.map +1 -1
- package/dist/cliproxy/quota/quota-fetcher-claude.js +35 -4
- package/dist/cliproxy/quota/quota-fetcher-claude.js.map +1 -1
- package/dist/cliproxy/quota/quota-manager.d.ts +1 -0
- package/dist/cliproxy/quota/quota-manager.d.ts.map +1 -1
- package/dist/cliproxy/quota/quota-manager.js +53 -2
- package/dist/cliproxy/quota/quota-manager.js.map +1 -1
- package/dist/cliproxy/services/oauth-usage-log-transformer.d.ts.map +1 -1
- package/dist/cliproxy/services/oauth-usage-log-transformer.js +5 -0
- package/dist/cliproxy/services/oauth-usage-log-transformer.js.map +1 -1
- package/dist/codex-auth/codex-account-identity.d.ts +8 -0
- package/dist/codex-auth/codex-account-identity.d.ts.map +1 -0
- package/dist/codex-auth/codex-account-identity.js +53 -0
- package/dist/codex-auth/codex-account-identity.js.map +1 -0
- package/dist/codex-auth/codex-auth-dashboard-service.d.ts +46 -0
- package/dist/codex-auth/codex-auth-dashboard-service.d.ts.map +1 -0
- package/dist/codex-auth/codex-auth-dashboard-service.js +228 -0
- package/dist/codex-auth/codex-auth-dashboard-service.js.map +1 -0
- package/dist/codex-auth/codex-auth-help.d.ts +7 -0
- package/dist/codex-auth/codex-auth-help.d.ts.map +1 -0
- package/dist/codex-auth/codex-auth-help.js +87 -0
- package/dist/codex-auth/codex-auth-help.js.map +1 -0
- package/dist/codex-auth/codex-auth-router.d.ts +16 -0
- package/dist/codex-auth/codex-auth-router.d.ts.map +1 -0
- package/dist/codex-auth/codex-auth-router.js +77 -0
- package/dist/codex-auth/codex-auth-router.js.map +1 -0
- package/dist/codex-auth/codex-config-symlink.d.ts +14 -0
- package/dist/codex-auth/codex-config-symlink.d.ts.map +1 -0
- package/dist/codex-auth/codex-config-symlink.js +128 -0
- package/dist/codex-auth/codex-config-symlink.js.map +1 -0
- package/dist/codex-auth/codex-profile-paths.d.ts +5 -0
- package/dist/codex-auth/codex-profile-paths.d.ts.map +1 -0
- package/dist/codex-auth/codex-profile-paths.js +58 -0
- package/dist/codex-auth/codex-profile-paths.js.map +1 -0
- package/dist/codex-auth/codex-profile-registry.d.ts +34 -0
- package/dist/codex-auth/codex-profile-registry.d.ts.map +1 -0
- package/dist/codex-auth/codex-profile-registry.js +360 -0
- package/dist/codex-auth/codex-profile-registry.js.map +1 -0
- package/dist/codex-auth/codex-profile-resources.d.ts +6 -0
- package/dist/codex-auth/codex-profile-resources.d.ts.map +1 -0
- package/dist/codex-auth/codex-profile-resources.js +119 -0
- package/dist/codex-auth/codex-profile-resources.js.map +1 -0
- package/dist/codex-auth/commands/create-command.d.ts +9 -0
- package/dist/codex-auth/commands/create-command.d.ts.map +1 -0
- package/dist/codex-auth/commands/create-command.js +203 -0
- package/dist/codex-auth/commands/create-command.js.map +1 -0
- package/dist/codex-auth/commands/import-default-command.d.ts +18 -0
- package/dist/codex-auth/commands/import-default-command.d.ts.map +1 -0
- package/dist/codex-auth/commands/import-default-command.js +385 -0
- package/dist/codex-auth/commands/import-default-command.js.map +1 -0
- package/dist/codex-auth/commands/index.d.ts +13 -0
- package/dist/codex-auth/commands/index.d.ts.map +1 -0
- package/dist/codex-auth/commands/index.js +27 -0
- package/dist/codex-auth/commands/index.js.map +1 -0
- package/dist/codex-auth/commands/login-command.d.ts +9 -0
- package/dist/codex-auth/commands/login-command.d.ts.map +1 -0
- package/dist/codex-auth/commands/login-command.js +152 -0
- package/dist/codex-auth/commands/login-command.js.map +1 -0
- package/dist/codex-auth/commands/remove-command.d.ts +10 -0
- package/dist/codex-auth/commands/remove-command.d.ts.map +1 -0
- package/dist/codex-auth/commands/remove-command.js +230 -0
- package/dist/codex-auth/commands/remove-command.js.map +1 -0
- package/dist/codex-auth/commands/show-command.d.ts +10 -0
- package/dist/codex-auth/commands/show-command.d.ts.map +1 -0
- package/dist/codex-auth/commands/show-command.js +127 -0
- package/dist/codex-auth/commands/show-command.js.map +1 -0
- package/dist/codex-auth/commands/show-detail-view.d.ts +7 -0
- package/dist/codex-auth/commands/show-detail-view.d.ts.map +1 -0
- package/dist/codex-auth/commands/show-detail-view.js +134 -0
- package/dist/codex-auth/commands/show-detail-view.js.map +1 -0
- package/dist/codex-auth/commands/switch-command.d.ts +7 -0
- package/dist/codex-auth/commands/switch-command.d.ts.map +1 -0
- package/dist/codex-auth/commands/switch-command.js +48 -0
- package/dist/codex-auth/commands/switch-command.js.map +1 -0
- package/dist/codex-auth/commands/types.d.ts +45 -0
- package/dist/codex-auth/commands/types.d.ts.map +1 -0
- package/dist/codex-auth/commands/types.js +85 -0
- package/dist/codex-auth/commands/types.js.map +1 -0
- package/dist/codex-auth/commands/use-command.d.ts +16 -0
- package/dist/codex-auth/commands/use-command.d.ts.map +1 -0
- package/dist/codex-auth/commands/use-command.js +86 -0
- package/dist/codex-auth/commands/use-command.js.map +1 -0
- package/dist/codex-auth/decode-id-token.d.ts +12 -0
- package/dist/codex-auth/decode-id-token.d.ts.map +1 -0
- package/dist/codex-auth/decode-id-token.js +83 -0
- package/dist/codex-auth/decode-id-token.js.map +1 -0
- package/dist/codex-auth/index.d.ts +9 -0
- package/dist/codex-auth/index.d.ts.map +1 -0
- package/dist/codex-auth/index.js +22 -0
- package/dist/codex-auth/index.js.map +1 -0
- package/dist/codex-auth/resolve-active-profile.d.ts +13 -0
- package/dist/codex-auth/resolve-active-profile.d.ts.map +1 -0
- package/dist/codex-auth/resolve-active-profile.js +161 -0
- package/dist/codex-auth/resolve-active-profile.js.map +1 -0
- package/dist/codex-auth/shell-detect.d.ts +19 -0
- package/dist/codex-auth/shell-detect.d.ts.map +1 -0
- package/dist/codex-auth/shell-detect.js +129 -0
- package/dist/codex-auth/shell-detect.js.map +1 -0
- package/dist/codex-auth/types.d.ts +26 -0
- package/dist/codex-auth/types.d.ts.map +1 -0
- package/dist/codex-auth/types.js +34 -0
- package/dist/codex-auth/types.js.map +1 -0
- package/dist/commands/cliproxy/variant-subcommand.js +1 -1
- package/dist/commands/cliproxy/variant-subcommand.js.map +1 -1
- package/dist/commands/command-catalog.d.ts +1 -1
- package/dist/commands/command-catalog.d.ts.map +1 -1
- package/dist/commands/command-catalog.js +10 -1
- package/dist/commands/command-catalog.js.map +1 -1
- package/dist/commands/completion-backend.d.ts.map +1 -1
- package/dist/commands/completion-backend.js +2 -0
- package/dist/commands/completion-backend.js.map +1 -1
- package/dist/commands/config-command.d.ts +2 -0
- package/dist/commands/config-command.d.ts.map +1 -1
- package/dist/commands/config-command.js +31 -20
- package/dist/commands/config-command.js.map +1 -1
- package/dist/commands/docker/finalize-key-rotation-subcommand.d.ts +2 -0
- package/dist/commands/docker/finalize-key-rotation-subcommand.d.ts.map +1 -0
- package/dist/commands/docker/finalize-key-rotation-subcommand.js +79 -0
- package/dist/commands/docker/finalize-key-rotation-subcommand.js.map +1 -0
- package/dist/commands/docker/help-subcommand.d.ts.map +1 -1
- package/dist/commands/docker/help-subcommand.js +6 -0
- package/dist/commands/docker/help-subcommand.js.map +1 -1
- package/dist/commands/docker/index.d.ts.map +1 -1
- package/dist/commands/docker/index.js +4 -0
- package/dist/commands/docker/index.js.map +1 -1
- package/dist/commands/docker/show-key-subcommand.d.ts +2 -0
- package/dist/commands/docker/show-key-subcommand.d.ts.map +1 -0
- package/dist/commands/docker/show-key-subcommand.js +96 -0
- package/dist/commands/docker/show-key-subcommand.js.map +1 -0
- package/dist/commands/docker/up-subcommand.d.ts.map +1 -1
- package/dist/commands/docker/up-subcommand.js +4 -0
- package/dist/commands/docker/up-subcommand.js.map +1 -1
- package/dist/commands/persist-command.d.ts.map +1 -1
- package/dist/commands/persist-command.js +77 -5
- package/dist/commands/persist-command.js.map +1 -1
- package/dist/dispatcher/cli-argument-parser.d.ts +3 -2
- package/dist/dispatcher/cli-argument-parser.d.ts.map +1 -1
- package/dist/dispatcher/cli-argument-parser.js +37 -7
- package/dist/dispatcher/cli-argument-parser.js.map +1 -1
- package/dist/dispatcher/pre-dispatch.d.ts.map +1 -1
- package/dist/dispatcher/pre-dispatch.js +7 -0
- package/dist/dispatcher/pre-dispatch.js.map +1 -1
- package/dist/dispatcher/target-executor.d.ts +2 -2
- package/dist/dispatcher/target-executor.d.ts.map +1 -1
- package/dist/dispatcher/target-executor.js +5 -5
- package/dist/dispatcher/target-executor.js.map +1 -1
- package/dist/docker/docker-bootstrap.d.ts +1 -1
- package/dist/docker/docker-bootstrap.d.ts.map +1 -1
- package/dist/docker/docker-bootstrap.js +99 -3
- package/dist/docker/docker-bootstrap.js.map +1 -1
- package/dist/docker/docker-executor.d.ts +3 -0
- package/dist/docker/docker-executor.d.ts.map +1 -1
- package/dist/docker/docker-executor.js +53 -0
- package/dist/docker/docker-executor.js.map +1 -1
- package/dist/docker/docker-key-rotation.d.ts +48 -0
- package/dist/docker/docker-key-rotation.d.ts.map +1 -0
- package/dist/docker/docker-key-rotation.js +179 -0
- package/dist/docker/docker-key-rotation.js.map +1 -0
- package/dist/management/checks/config-check.d.ts.map +1 -1
- package/dist/management/checks/config-check.js +10 -1
- package/dist/management/checks/config-check.js.map +1 -1
- package/dist/management/doctor.d.ts +1 -0
- package/dist/management/doctor.d.ts.map +1 -1
- package/dist/management/doctor.js +23 -0
- package/dist/management/doctor.js.map +1 -1
- package/dist/proxy/proxy-daemon.d.ts.map +1 -1
- package/dist/proxy/proxy-daemon.js +15 -3
- package/dist/proxy/proxy-daemon.js.map +1 -1
- package/dist/proxy/server/messages-route.d.ts.map +1 -1
- package/dist/proxy/server/messages-route.js +27 -1
- package/dist/proxy/server/messages-route.js.map +1 -1
- package/dist/shared/claude-extension-setup.d.ts.map +1 -1
- package/dist/shared/claude-extension-setup.js +21 -1
- package/dist/shared/claude-extension-setup.js.map +1 -1
- package/dist/shared/stale-codex-translator-settings.d.ts +4 -0
- package/dist/shared/stale-codex-translator-settings.d.ts.map +1 -0
- package/dist/shared/stale-codex-translator-settings.js +35 -0
- package/dist/shared/stale-codex-translator-settings.js.map +1 -0
- package/dist/targets/codex-adapter.d.ts.map +1 -1
- package/dist/targets/codex-adapter.js +64 -5
- package/dist/targets/codex-adapter.js.map +1 -1
- package/dist/targets/codex-cliproxy-provider-config.d.ts.map +1 -1
- package/dist/targets/codex-cliproxy-provider-config.js +56 -24
- package/dist/targets/codex-cliproxy-provider-config.js.map +1 -1
- package/dist/ui/assets/Trans-dEd8UC39.js +1 -0
- package/dist/ui/assets/accounts-B2THsSu_.js +1 -0
- package/dist/ui/assets/{alert-dialog-DC1l1GRX.js → alert-dialog-Vurq1xzV.js} +1 -1
- package/dist/ui/assets/api-CjLfG9mL.js +4 -0
- package/dist/ui/assets/auth-section-iGkrMaT4.js +1 -0
- package/dist/ui/assets/backups-section-DUGG_4KP.js +1 -0
- package/dist/ui/assets/channels-CimlCc2d.js +1 -0
- package/dist/ui/assets/{charts-CeK2xCSo.js → charts-eIPy2oG6.js} +34 -34
- package/dist/ui/assets/{checkbox-Dgd2ucy2.js → checkbox-HiMHasEB.js} +1 -1
- package/dist/ui/assets/claude-extension-B2v9bsN9.js +1 -0
- package/dist/ui/assets/{cliproxy-ai-providers-DxoCNEaQ.js → cliproxy-ai-providers-2lI5jSHb.js} +6 -6
- package/dist/ui/assets/cliproxy-control-panel-63gDI-e5.js +1 -0
- package/dist/ui/assets/cliproxy-fai69Vyd.js +4 -0
- package/dist/ui/assets/code-highlight-ClSMkeL5.js +1 -0
- package/dist/ui/assets/codex-i_hfI4Tv.js +30 -0
- package/dist/ui/assets/{confirm-dialog-nDFNrH0F.js → confirm-dialog-B_6SrSxL.js} +1 -1
- package/dist/ui/assets/copilot-BgG5x_X6.js +3 -0
- package/dist/ui/assets/cursor-DF63lFcy.js +1 -0
- package/dist/ui/assets/droid-CqlQmFtN.js +2 -0
- package/dist/ui/assets/globalenv-section-CYNmD12i.js +1 -0
- package/dist/ui/assets/health-7ZO5PEm9.js +1 -0
- package/dist/ui/assets/index-BC5ssPfF.js +1 -0
- package/dist/ui/assets/index-BMoGhs28.css +1 -0
- package/dist/ui/assets/index-Bgcd4FYK.js +1 -0
- package/dist/ui/assets/index-CFu0saCM.js +1 -0
- package/dist/ui/assets/index-CqsmdQoA.js +1 -0
- package/dist/ui/assets/index-D3kxCuJ7.js +1 -0
- package/dist/ui/assets/index-DmV9wJET.js +56 -0
- package/dist/ui/assets/index-hHb9o079.js +1 -0
- package/dist/ui/assets/logs-Dy-yZhIK.js +1 -0
- package/dist/ui/assets/{masked-input-5TJ4LSuz.js → masked-input-BSLeznEs.js} +1 -1
- package/dist/ui/assets/proxy-status-widget-hRH1agF9.js +1 -0
- package/dist/ui/assets/{raw-json-settings-editor-panel-Fg4WMiuD.js → raw-json-settings-editor-panel-Bs83yILR.js} +1 -1
- package/dist/ui/assets/{searchable-select-CPJn5vA1.js → searchable-select-pXUC_0Ih.js} +1 -1
- package/dist/ui/assets/{separator-BrQkfpAp.js → separator-FZR_61I9.js} +1 -1
- package/dist/ui/assets/shared-BiIwM7--.js +8 -0
- package/dist/ui/assets/{table-DRzNRkpJ.js → table-_9IusQ8G.js} +1 -1
- package/dist/ui/assets/updates-ButNfJqt.js +1 -0
- package/dist/ui/assets/{use-accounts-B6AXtlfF.js → use-accounts-BdtI0lBv.js} +1 -1
- package/dist/ui/index.html +3 -3
- package/dist/utils/claude-subcommand-detector.d.ts +12 -3
- package/dist/utils/claude-subcommand-detector.d.ts.map +1 -1
- package/dist/utils/claude-subcommand-detector.js +59 -12
- package/dist/utils/claude-subcommand-detector.js.map +1 -1
- package/dist/web-server/middleware/auth-middleware.d.ts.map +1 -1
- package/dist/web-server/middleware/auth-middleware.js +25 -1
- package/dist/web-server/middleware/auth-middleware.js.map +1 -1
- package/dist/web-server/routes/claude-extension-routes.d.ts.map +1 -1
- package/dist/web-server/routes/claude-extension-routes.js +5 -0
- package/dist/web-server/routes/claude-extension-routes.js.map +1 -1
- package/dist/web-server/routes/cliproxy-stats-routes.d.ts +8 -0
- package/dist/web-server/routes/cliproxy-stats-routes.d.ts.map +1 -1
- package/dist/web-server/routes/cliproxy-stats-routes.js +13 -26
- package/dist/web-server/routes/cliproxy-stats-routes.js.map +1 -1
- package/dist/web-server/routes/codex-routes.d.ts.map +1 -1
- package/dist/web-server/routes/codex-routes.js +14 -0
- package/dist/web-server/routes/codex-routes.js.map +1 -1
- package/dist/web-server/services/cliproxy-dashboard-restart-service.d.ts +21 -0
- package/dist/web-server/services/cliproxy-dashboard-restart-service.d.ts.map +1 -0
- package/dist/web-server/services/cliproxy-dashboard-restart-service.js +49 -0
- package/dist/web-server/services/cliproxy-dashboard-restart-service.js.map +1 -0
- package/dist/web-server/services/codex-dashboard-service.d.ts.map +1 -1
- package/dist/web-server/services/codex-dashboard-service.js +30 -3
- package/dist/web-server/services/codex-dashboard-service.js.map +1 -1
- package/dist/web-server/usage/aggregator.d.ts +13 -7
- package/dist/web-server/usage/aggregator.d.ts.map +1 -1
- package/dist/web-server/usage/aggregator.js +37 -22
- package/dist/web-server/usage/aggregator.js.map +1 -1
- package/dist/web-server/usage/handlers.d.ts +1 -0
- package/dist/web-server/usage/handlers.d.ts.map +1 -1
- package/dist/web-server/usage/handlers.js +16 -8
- package/dist/web-server/usage/handlers.js.map +1 -1
- package/dist/web-server/usage/profile-filter.d.ts +13 -0
- package/dist/web-server/usage/profile-filter.d.ts.map +1 -0
- package/dist/web-server/usage/profile-filter.js +30 -0
- package/dist/web-server/usage/profile-filter.js.map +1 -0
- package/dist/web-server/usage/types.d.ts +8 -0
- package/dist/web-server/usage/types.d.ts.map +1 -1
- package/lib/hooks/websearch-transformer.cjs +12 -3
- package/lib/mcp/ccs-browser-server.cjs +217 -12
- package/package.json +1 -1
- package/scripts/docker-dashboard-sunset-guard.js +171 -0
- package/scripts/run-test-bucket.js +1 -0
- package/scripts/verify-bundle.js +4 -1
- package/dist/ui/assets/accounts-BQu3Aeey.js +0 -1
- package/dist/ui/assets/api-BTbrbjic.js +0 -4
- package/dist/ui/assets/auth-section-BsSVWOMp.js +0 -1
- package/dist/ui/assets/backups-section-BGHYHASS.js +0 -1
- package/dist/ui/assets/channels-vJ8L4j-z.js +0 -1
- package/dist/ui/assets/claude-extension-B3ern4Ad.js +0 -1
- package/dist/ui/assets/cliproxy-CGljI0Or.js +0 -4
- package/dist/ui/assets/cliproxy-control-panel-BJ3Mliy1.js +0 -1
- package/dist/ui/assets/code-highlight-D4E79GKQ.js +0 -3
- package/dist/ui/assets/codex-DBGHPn0v.js +0 -30
- package/dist/ui/assets/copilot-CE_Z3NB0.js +0 -3
- package/dist/ui/assets/cursor-YzGsSR_d.js +0 -1
- package/dist/ui/assets/droid-C-ItViCi.js +0 -2
- package/dist/ui/assets/globalenv-section-C9gSGyZ8.js +0 -1
- package/dist/ui/assets/health-DEeA97sQ.js +0 -1
- package/dist/ui/assets/index-B71yJlMj.css +0 -1
- package/dist/ui/assets/index-BPVO-QAw.js +0 -1
- package/dist/ui/assets/index-BRZp_Csi.js +0 -72
- package/dist/ui/assets/index-BYUwpOeA.js +0 -1
- package/dist/ui/assets/index-D2r_fAW5.js +0 -1
- package/dist/ui/assets/index-DGiziSVQ.js +0 -1
- package/dist/ui/assets/index-DwG6bbUr.js +0 -1
- package/dist/ui/assets/index-Dwtj4wGT.js +0 -1
- package/dist/ui/assets/logs-Mt2W7M3G.js +0 -1
- package/dist/ui/assets/proxy-status-widget-BQOAlYsb.js +0 -1
- package/dist/ui/assets/shared-BlkDl2HF.js +0 -8
- package/dist/ui/assets/updates-BQNeSzLj.js +0 -1
|
@@ -874,7 +874,10 @@ function runGeminiCommand(args, timeoutMs) {
|
|
|
874
874
|
timeout: timeoutMs,
|
|
875
875
|
maxBuffer: 1024 * 1024 * 2,
|
|
876
876
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
877
|
-
shell
|
|
877
|
+
// Never route query-derived prompts through a shell. Node concatenates
|
|
878
|
+
// arguments for shell-backed Windows spawns, which lets shell metacharacters
|
|
879
|
+
// in WebSearch queries escape the intended CLI invocation.
|
|
880
|
+
shell: false,
|
|
878
881
|
});
|
|
879
882
|
|
|
880
883
|
if (result.error) {
|
|
@@ -929,7 +932,10 @@ function tryOpenCodeSearch(query, timeoutSec = DEFAULT_TIMEOUT_SEC) {
|
|
|
929
932
|
timeout: timeoutSec * 1000,
|
|
930
933
|
maxBuffer: 1024 * 1024 * 2,
|
|
931
934
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
932
|
-
shell
|
|
935
|
+
// Never route query-derived prompts through a shell. Node concatenates
|
|
936
|
+
// arguments for shell-backed Windows spawns, which lets shell metacharacters
|
|
937
|
+
// in WebSearch queries escape the intended CLI invocation.
|
|
938
|
+
shell: false,
|
|
933
939
|
}
|
|
934
940
|
);
|
|
935
941
|
|
|
@@ -965,7 +971,10 @@ function tryGrokSearch(query, timeoutSec = DEFAULT_TIMEOUT_SEC) {
|
|
|
965
971
|
timeout: timeoutSec * 1000,
|
|
966
972
|
maxBuffer: 1024 * 1024 * 2,
|
|
967
973
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
968
|
-
shell
|
|
974
|
+
// Never route query-derived prompts through a shell. Node concatenates
|
|
975
|
+
// arguments for shell-backed Windows spawns, which lets shell metacharacters
|
|
976
|
+
// in WebSearch queries escape the intended CLI invocation.
|
|
977
|
+
shell: false,
|
|
969
978
|
});
|
|
970
979
|
|
|
971
980
|
if (result.error) {
|
|
@@ -83,6 +83,16 @@ const TOOL_HOVER = 'browser_hover';
|
|
|
83
83
|
const TOOL_QUERY = 'browser_query';
|
|
84
84
|
const TOOL_TAKE_ELEMENT_SCREENSHOT = 'browser_take_element_screenshot';
|
|
85
85
|
const TOOL_WAIT_FOR_EVENT = 'browser_wait_for_event';
|
|
86
|
+
const SENSITIVE_INTERCEPT_HEADER_NAMES = new Set([
|
|
87
|
+
'authorization',
|
|
88
|
+
'cookie',
|
|
89
|
+
'cookie2',
|
|
90
|
+
'proxy-authorization',
|
|
91
|
+
'x-api-key',
|
|
92
|
+
'x-api-token',
|
|
93
|
+
'x-auth-token',
|
|
94
|
+
]);
|
|
95
|
+
|
|
86
96
|
const TOOL_NAMES = [
|
|
87
97
|
TOOL_SESSION_INFO,
|
|
88
98
|
TOOL_URL_TITLE,
|
|
@@ -612,10 +622,15 @@ function getTools() {
|
|
|
612
622
|
urlRegex: { type: 'string' },
|
|
613
623
|
headerMatchers: {
|
|
614
624
|
type: 'array',
|
|
625
|
+
description:
|
|
626
|
+
'Match non-sensitive request headers. Cookie, Authorization, and token headers are not allowed.',
|
|
615
627
|
items: {
|
|
616
628
|
type: 'object',
|
|
617
629
|
properties: {
|
|
618
|
-
name: {
|
|
630
|
+
name: {
|
|
631
|
+
type: 'string',
|
|
632
|
+
description: 'Non-sensitive request header name to match.',
|
|
633
|
+
},
|
|
619
634
|
valueIncludes: { type: 'string' },
|
|
620
635
|
valueRegex: { type: 'string' },
|
|
621
636
|
},
|
|
@@ -624,7 +639,7 @@ function getTools() {
|
|
|
624
639
|
},
|
|
625
640
|
},
|
|
626
641
|
priority: { type: 'integer' },
|
|
627
|
-
action: { type: 'string', enum:
|
|
642
|
+
action: { type: 'string', enum: getInterceptActionEnum() },
|
|
628
643
|
statusCode: { type: 'integer', minimum: 100, maximum: 599 },
|
|
629
644
|
responseHeaders: {
|
|
630
645
|
type: 'array',
|
|
@@ -1194,7 +1209,18 @@ function getTools() {
|
|
|
1194
1209
|
},
|
|
1195
1210
|
event: {
|
|
1196
1211
|
type: 'object',
|
|
1197
|
-
description:
|
|
1212
|
+
description:
|
|
1213
|
+
'Required event selector. request events require urlIncludes; download events require urlIncludes or suggestedFilenameIncludes. URLs in returned details are redacted.',
|
|
1214
|
+
properties: {
|
|
1215
|
+
kind: { type: 'string', enum: ['dialog', 'navigation', 'request', 'download'] },
|
|
1216
|
+
dialogType: { type: 'string' },
|
|
1217
|
+
messageIncludes: { type: 'string' },
|
|
1218
|
+
urlIncludes: { type: 'string' },
|
|
1219
|
+
method: { type: 'string' },
|
|
1220
|
+
suggestedFilenameIncludes: { type: 'string' },
|
|
1221
|
+
},
|
|
1222
|
+
required: ['kind'],
|
|
1223
|
+
additionalProperties: false,
|
|
1198
1224
|
},
|
|
1199
1225
|
},
|
|
1200
1226
|
required: ['event'],
|
|
@@ -1277,9 +1303,30 @@ function parseOptionalPageId(toolArgs) {
|
|
|
1277
1303
|
: '';
|
|
1278
1304
|
}
|
|
1279
1305
|
|
|
1306
|
+
function getBrowserInterceptFulfillMode() {
|
|
1307
|
+
return String(process.env.CCS_BROWSER_INTERCEPT_FULFILL_MODE || 'disabled').trim() === 'enabled'
|
|
1308
|
+
? 'enabled'
|
|
1309
|
+
: 'disabled';
|
|
1310
|
+
}
|
|
1311
|
+
|
|
1312
|
+
function isBrowserInterceptFulfillEnabled() {
|
|
1313
|
+
return getBrowserInterceptFulfillMode() === 'enabled';
|
|
1314
|
+
}
|
|
1315
|
+
|
|
1316
|
+
function getInterceptActionEnum() {
|
|
1317
|
+
return isBrowserInterceptFulfillEnabled()
|
|
1318
|
+
? ['continue', 'fail', 'fulfill']
|
|
1319
|
+
: ['continue', 'fail'];
|
|
1320
|
+
}
|
|
1321
|
+
|
|
1280
1322
|
function parseInterceptAction(value) {
|
|
1323
|
+
if (value === 'fulfill' && !isBrowserInterceptFulfillEnabled()) {
|
|
1324
|
+
throw new Error(
|
|
1325
|
+
'action fulfill is disabled by CCS_BROWSER_INTERCEPT_FULFILL_MODE=disabled; set it to enabled only for trusted local testing'
|
|
1326
|
+
);
|
|
1327
|
+
}
|
|
1281
1328
|
if (value !== 'continue' && value !== 'fail' && value !== 'fulfill') {
|
|
1282
|
-
throw new Error(
|
|
1329
|
+
throw new Error(`action must be one of: ${getInterceptActionEnum().join(', ')}`);
|
|
1283
1330
|
}
|
|
1284
1331
|
return value;
|
|
1285
1332
|
}
|
|
@@ -1379,6 +1426,10 @@ function parseOptionalPriority(value) {
|
|
|
1379
1426
|
return value;
|
|
1380
1427
|
}
|
|
1381
1428
|
|
|
1429
|
+
function isSensitiveInterceptHeaderName(name) {
|
|
1430
|
+
return SENSITIVE_INTERCEPT_HEADER_NAMES.has(name.toLowerCase());
|
|
1431
|
+
}
|
|
1432
|
+
|
|
1382
1433
|
function parseOptionalHeaderMatchers(value) {
|
|
1383
1434
|
if (value === undefined) {
|
|
1384
1435
|
return [];
|
|
@@ -1391,6 +1442,9 @@ function parseOptionalHeaderMatchers(value) {
|
|
|
1391
1442
|
throw new Error('headerMatchers entries must be objects');
|
|
1392
1443
|
}
|
|
1393
1444
|
const name = requireNonEmptyString(entry.name, 'headerMatchers.name');
|
|
1445
|
+
if (isSensitiveInterceptHeaderName(name)) {
|
|
1446
|
+
throw new Error(`headerMatchers.name cannot target sensitive request header: ${name}`);
|
|
1447
|
+
}
|
|
1394
1448
|
const valueIncludes =
|
|
1395
1449
|
entry.valueIncludes === undefined
|
|
1396
1450
|
? ''
|
|
@@ -3305,24 +3359,80 @@ function parseEventCondition(value) {
|
|
|
3305
3359
|
};
|
|
3306
3360
|
}
|
|
3307
3361
|
if (value.kind === 'request') {
|
|
3362
|
+
const urlIncludes = value.urlIncludes ? String(value.urlIncludes) : undefined;
|
|
3363
|
+
if (!urlIncludes) {
|
|
3364
|
+
throw new Error('request events require urlIncludes to limit network metadata exposure');
|
|
3365
|
+
}
|
|
3308
3366
|
return {
|
|
3309
3367
|
kind: 'request',
|
|
3310
|
-
urlIncludes
|
|
3368
|
+
urlIncludes,
|
|
3311
3369
|
method: value.method ? String(value.method) : undefined,
|
|
3312
3370
|
};
|
|
3313
3371
|
}
|
|
3314
3372
|
if (value.kind === 'download') {
|
|
3373
|
+
const urlIncludes = value.urlIncludes ? String(value.urlIncludes) : undefined;
|
|
3374
|
+
const suggestedFilenameIncludes = value.suggestedFilenameIncludes
|
|
3375
|
+
? String(value.suggestedFilenameIncludes)
|
|
3376
|
+
: undefined;
|
|
3377
|
+
if (!urlIncludes && !suggestedFilenameIncludes) {
|
|
3378
|
+
throw new Error(
|
|
3379
|
+
'download events require urlIncludes or suggestedFilenameIncludes to limit metadata exposure'
|
|
3380
|
+
);
|
|
3381
|
+
}
|
|
3315
3382
|
return {
|
|
3316
3383
|
kind: 'download',
|
|
3317
|
-
urlIncludes
|
|
3318
|
-
suggestedFilenameIncludes
|
|
3319
|
-
? String(value.suggestedFilenameIncludes)
|
|
3320
|
-
: undefined,
|
|
3384
|
+
urlIncludes,
|
|
3385
|
+
suggestedFilenameIncludes,
|
|
3321
3386
|
};
|
|
3322
3387
|
}
|
|
3323
3388
|
throw new Error(`unknown event kind: ${String(value.kind || '')}`);
|
|
3324
3389
|
}
|
|
3325
3390
|
|
|
3391
|
+
function redactUrlForModel(value, options = {}) {
|
|
3392
|
+
const rawUrl = String(value || '');
|
|
3393
|
+
if (!rawUrl) {
|
|
3394
|
+
return '';
|
|
3395
|
+
}
|
|
3396
|
+
try {
|
|
3397
|
+
const url = new URL(rawUrl);
|
|
3398
|
+
if (options.originOnly) {
|
|
3399
|
+
return url.origin;
|
|
3400
|
+
}
|
|
3401
|
+
url.username = '';
|
|
3402
|
+
url.password = '';
|
|
3403
|
+
url.search = '';
|
|
3404
|
+
url.hash = '';
|
|
3405
|
+
return url.toString();
|
|
3406
|
+
} catch {
|
|
3407
|
+
return '[redacted-url]';
|
|
3408
|
+
}
|
|
3409
|
+
}
|
|
3410
|
+
|
|
3411
|
+
function redactObservedEvent(event, observed) {
|
|
3412
|
+
if (!observed || typeof observed !== 'object') {
|
|
3413
|
+
return observed;
|
|
3414
|
+
}
|
|
3415
|
+
if (event.kind === 'request') {
|
|
3416
|
+
return {
|
|
3417
|
+
url: redactUrlForModel(observed.url, { originOnly: true }),
|
|
3418
|
+
method: observed.method || '',
|
|
3419
|
+
};
|
|
3420
|
+
}
|
|
3421
|
+
if (event.kind === 'download') {
|
|
3422
|
+
return {
|
|
3423
|
+
url: redactUrlForModel(observed.url, { originOnly: true }),
|
|
3424
|
+
suggestedFilename: observed.suggestedFilename || '',
|
|
3425
|
+
};
|
|
3426
|
+
}
|
|
3427
|
+
if (event.kind === 'navigation' && Object.prototype.hasOwnProperty.call(observed, 'url')) {
|
|
3428
|
+
return {
|
|
3429
|
+
...observed,
|
|
3430
|
+
url: redactUrlForModel(observed.url, { originOnly: true }),
|
|
3431
|
+
};
|
|
3432
|
+
}
|
|
3433
|
+
return observed;
|
|
3434
|
+
}
|
|
3435
|
+
|
|
3326
3436
|
function matchesObservedEvent(event, observed) {
|
|
3327
3437
|
if (event.kind === 'dialog') {
|
|
3328
3438
|
return (
|
|
@@ -4776,7 +4886,8 @@ async function handleWaitForEvent(toolArgs) {
|
|
|
4776
4886
|
);
|
|
4777
4887
|
const event = parseEventCondition(toolArgs.event);
|
|
4778
4888
|
const observed = await waitForMatchingEvent({ page, pageIndex, timeoutMs, event });
|
|
4779
|
-
|
|
4889
|
+
const safeObserved = redactObservedEvent(event, observed);
|
|
4890
|
+
return `pageIndex: ${pageIndex}\nevent: ${event.kind}\nstatus: observed\ndetail: ${JSON.stringify(safeObserved)}`;
|
|
4780
4891
|
}
|
|
4781
4892
|
|
|
4782
4893
|
function findInterceptRuleIndex(ruleId) {
|
|
@@ -5381,7 +5492,10 @@ function buildRecordingInstallExpression(recordingPayload) {
|
|
|
5381
5492
|
const recordingPayload = JSON.parse(${JSON.stringify(JSON.stringify(recordingPayload))});
|
|
5382
5493
|
const existing = globalThis.__CCS_BROWSER_RECORDING_RECORDER__;
|
|
5383
5494
|
if (existing && existing.installed === true) {
|
|
5384
|
-
|
|
5495
|
+
if (typeof existing.teardown === 'function') {
|
|
5496
|
+
existing.teardown();
|
|
5497
|
+
}
|
|
5498
|
+
delete globalThis.__CCS_BROWSER_RECORDING_RECORDER__;
|
|
5385
5499
|
}
|
|
5386
5500
|
|
|
5387
5501
|
const events = Array.isArray(recordingPayload.events) ? [...recordingPayload.events] : [];
|
|
@@ -5413,8 +5527,42 @@ function buildRecordingInstallExpression(recordingPayload) {
|
|
|
5413
5527
|
timestamp: Date.now(),
|
|
5414
5528
|
});
|
|
5415
5529
|
};
|
|
5530
|
+
const sensitiveInputTypes = new Set(['password', 'hidden']);
|
|
5531
|
+
const sensitiveAttributePattern = /(?:pass(?:word|code|phrase)?|pwd|secret|token|api[-_ ]?key|access[-_ ]?key|private[-_ ]?key|credential|otp|one[-_ ]?time[-_ ]?(?:code|password)|verif(?:ication)?[-_ ]?code|security[-_ ]?code|pin|auth(?:orization)?[-_ ]?(?:code|token)|mfa|2fa)/i;
|
|
5532
|
+
const sensitiveAutocompleteValues = new Set([
|
|
5533
|
+
'current-password',
|
|
5534
|
+
'new-password',
|
|
5535
|
+
'one-time-code',
|
|
5536
|
+
'cc-number',
|
|
5537
|
+
'cc-csc',
|
|
5538
|
+
]);
|
|
5539
|
+
const isSensitiveTextTarget = (target) => {
|
|
5540
|
+
if (!target || !(target instanceof Element)) {
|
|
5541
|
+
return false;
|
|
5542
|
+
}
|
|
5543
|
+
if (target instanceof HTMLInputElement) {
|
|
5544
|
+
const inputType = String(target.type || '').toLowerCase();
|
|
5545
|
+
if (sensitiveInputTypes.has(inputType)) {
|
|
5546
|
+
return true;
|
|
5547
|
+
}
|
|
5548
|
+
}
|
|
5549
|
+
const autocompleteTokens = String(target.getAttribute('autocomplete') || '')
|
|
5550
|
+
.toLowerCase()
|
|
5551
|
+
.split(/\s+/)
|
|
5552
|
+
.filter(Boolean);
|
|
5553
|
+
if (autocompleteTokens.some((token) => sensitiveAutocompleteValues.has(token))) {
|
|
5554
|
+
return true;
|
|
5555
|
+
}
|
|
5556
|
+
const attributesToInspect = ['id', 'name', 'placeholder', 'aria-label', 'data-testid'];
|
|
5557
|
+
return attributesToInspect.some((attributeName) =>
|
|
5558
|
+
sensitiveAttributePattern.test(String(target.getAttribute(attributeName) || ''))
|
|
5559
|
+
);
|
|
5560
|
+
};
|
|
5416
5561
|
const onInput = (event) => {
|
|
5417
5562
|
const target = event.target;
|
|
5563
|
+
if (isSensitiveTextTarget(target)) {
|
|
5564
|
+
return;
|
|
5565
|
+
}
|
|
5418
5566
|
let text = '';
|
|
5419
5567
|
if (target instanceof HTMLInputElement || target instanceof HTMLTextAreaElement) {
|
|
5420
5568
|
text = target.value;
|
|
@@ -5425,7 +5573,19 @@ function buildRecordingInstallExpression(recordingPayload) {
|
|
|
5425
5573
|
}
|
|
5426
5574
|
pushEvent({ kind: 'type', selector: getSelector(target), text, timestamp: Date.now() });
|
|
5427
5575
|
};
|
|
5576
|
+
const isRecordableKey = (event) => {
|
|
5577
|
+
if (isSensitiveTextTarget(event.target)) {
|
|
5578
|
+
return false;
|
|
5579
|
+
}
|
|
5580
|
+
if (typeof event.key !== 'string' || event.key.length !== 1) {
|
|
5581
|
+
return true;
|
|
5582
|
+
}
|
|
5583
|
+
return event.altKey === true || event.ctrlKey === true || event.metaKey === true;
|
|
5584
|
+
};
|
|
5428
5585
|
const onKeyDown = (event) => {
|
|
5586
|
+
if (!isRecordableKey(event)) {
|
|
5587
|
+
return;
|
|
5588
|
+
}
|
|
5429
5589
|
const modifiers = [];
|
|
5430
5590
|
if (event.altKey) modifiers.push('Alt');
|
|
5431
5591
|
if (event.ctrlKey) modifiers.push('Control');
|
|
@@ -5493,7 +5653,19 @@ async function finalizeRecordingCapture(session) {
|
|
|
5493
5653
|
};
|
|
5494
5654
|
|
|
5495
5655
|
const response = await sendCdpCommand(page, 'Runtime.evaluate', {
|
|
5496
|
-
expression: `(() =>
|
|
5656
|
+
expression: `(() => {
|
|
5657
|
+
const recorder = globalThis.__CCS_BROWSER_RECORDING_RECORDER__;
|
|
5658
|
+
if (!recorder) {
|
|
5659
|
+
return { events: [], warnings: [] };
|
|
5660
|
+
}
|
|
5661
|
+
const events = Array.isArray(recorder.events) ? [...recorder.events] : [];
|
|
5662
|
+
const warnings = Array.isArray(recorder.warnings) ? [...recorder.warnings] : [];
|
|
5663
|
+
if (typeof recorder.teardown === 'function') {
|
|
5664
|
+
recorder.teardown();
|
|
5665
|
+
}
|
|
5666
|
+
delete globalThis.__CCS_BROWSER_RECORDING_RECORDER__;
|
|
5667
|
+
return { events, warnings };
|
|
5668
|
+
})()`,
|
|
5497
5669
|
returnByValue: true,
|
|
5498
5670
|
awaitPromise: true,
|
|
5499
5671
|
});
|
|
@@ -5513,6 +5685,28 @@ async function finalizeRecordingCapture(session) {
|
|
|
5513
5685
|
session.warnings = warnings.map((warning) => String(warning.message || warning));
|
|
5514
5686
|
}
|
|
5515
5687
|
|
|
5688
|
+
async function teardownRecordingCapture(session) {
|
|
5689
|
+
if (!session || !session.pageWebSocketDebuggerUrl) {
|
|
5690
|
+
return;
|
|
5691
|
+
}
|
|
5692
|
+
const page = {
|
|
5693
|
+
id: session.pageId,
|
|
5694
|
+
webSocketDebuggerUrl: session.pageWebSocketDebuggerUrl,
|
|
5695
|
+
};
|
|
5696
|
+
await sendCdpCommand(page, 'Runtime.evaluate', {
|
|
5697
|
+
expression: `(() => {
|
|
5698
|
+
const recorder = globalThis.__CCS_BROWSER_RECORDING_RECORDER__;
|
|
5699
|
+
if (recorder && typeof recorder.teardown === 'function') {
|
|
5700
|
+
recorder.teardown();
|
|
5701
|
+
}
|
|
5702
|
+
delete globalThis.__CCS_BROWSER_RECORDING_RECORDER__;
|
|
5703
|
+
return { installed: false };
|
|
5704
|
+
})()`,
|
|
5705
|
+
returnByValue: true,
|
|
5706
|
+
awaitPromise: true,
|
|
5707
|
+
});
|
|
5708
|
+
}
|
|
5709
|
+
|
|
5516
5710
|
async function handleStartRecording(toolArgs) {
|
|
5517
5711
|
if (activeRecordingSession) {
|
|
5518
5712
|
throw new Error('recording already active');
|
|
@@ -5563,6 +5757,11 @@ async function handleStopRecording() {
|
|
|
5563
5757
|
} catch (error) {
|
|
5564
5758
|
finalizeError = error instanceof Error ? error : new Error(String(error));
|
|
5565
5759
|
session.warnings.push(`recording capture finalization failed: ${finalizeError.message}`);
|
|
5760
|
+
try {
|
|
5761
|
+
await teardownRecordingCapture(session);
|
|
5762
|
+
} catch {
|
|
5763
|
+
// Preserve the original finalization failure for the caller.
|
|
5764
|
+
}
|
|
5566
5765
|
}
|
|
5567
5766
|
session.status = 'stopped';
|
|
5568
5767
|
session.stoppedAt = new Date().toISOString();
|
|
@@ -5583,6 +5782,12 @@ async function handleClearRecording() {
|
|
|
5583
5782
|
if (!latestRecordingSession && !activeRecordingSession) {
|
|
5584
5783
|
throw new Error('no recording available');
|
|
5585
5784
|
}
|
|
5785
|
+
const session = activeRecordingSession || latestRecordingSession;
|
|
5786
|
+
try {
|
|
5787
|
+
await teardownRecordingCapture(session);
|
|
5788
|
+
} catch {
|
|
5789
|
+
// Clearing session-local recording state should still succeed if the page is already gone.
|
|
5790
|
+
}
|
|
5586
5791
|
activeRecordingSession = null;
|
|
5587
5792
|
latestRecordingSession = null;
|
|
5588
5793
|
return 'status: cleared';
|
package/package.json
CHANGED
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const fs = require('node:fs');
|
|
5
|
+
const { execFileSync } = require('node:child_process');
|
|
6
|
+
|
|
7
|
+
function parseStableVersion(value) {
|
|
8
|
+
const match = String(value || '').match(/^v?([0-9]+)\.([0-9]+)\.([0-9]+)$/);
|
|
9
|
+
if (!match) {
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
return {
|
|
13
|
+
major: Number(match[1]),
|
|
14
|
+
minor: Number(match[2]),
|
|
15
|
+
patch: Number(match[3]),
|
|
16
|
+
raw: `v${Number(match[1])}.${Number(match[2])}.${Number(match[3])}`,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function compareVersions(left, right) {
|
|
21
|
+
for (const key of ['major', 'minor', 'patch']) {
|
|
22
|
+
if (left[key] !== right[key]) {
|
|
23
|
+
return left[key] - right[key];
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return 0;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function stableVersionKey(version) {
|
|
30
|
+
return `${version.major}.${version.minor}.${version.patch}`;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function parseArgs(argv) {
|
|
34
|
+
const args = {};
|
|
35
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
36
|
+
const arg = argv[i];
|
|
37
|
+
if (!arg.startsWith('--')) {
|
|
38
|
+
throw new Error(`Unexpected argument: ${arg}`);
|
|
39
|
+
}
|
|
40
|
+
const key = arg.slice(2);
|
|
41
|
+
if (key === 'tags-stdin') {
|
|
42
|
+
args.tagsStdin = true;
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
const value = argv[i + 1];
|
|
46
|
+
if (!value || value.startsWith('--')) {
|
|
47
|
+
throw new Error(`Missing value for --${key}`);
|
|
48
|
+
}
|
|
49
|
+
args[key] = value;
|
|
50
|
+
i += 1;
|
|
51
|
+
}
|
|
52
|
+
return args;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function readStableTagsFromGit() {
|
|
56
|
+
const output = execFileSync('git', ['tag', '--list', 'v*'], {
|
|
57
|
+
encoding: 'utf8',
|
|
58
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
59
|
+
});
|
|
60
|
+
return output.split(/\r?\n/).filter(Boolean);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function parseStableTags(tags) {
|
|
64
|
+
const byKey = new Map();
|
|
65
|
+
for (const tag of tags) {
|
|
66
|
+
const version = parseStableVersion(tag.trim());
|
|
67
|
+
if (version) {
|
|
68
|
+
byKey.set(stableVersionKey(version), version);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return Array.from(byKey.values()).sort(compareVersions);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function evaluateDashboardSunset({ targetTag, baselineVersion, releaseWindow, stableTags }) {
|
|
75
|
+
const target = parseStableVersion(targetTag);
|
|
76
|
+
if (!target) {
|
|
77
|
+
throw new Error(`Target tag must be stable semver like v1.2.3, got: ${targetTag}`);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const baseline = parseStableVersion(baselineVersion);
|
|
81
|
+
if (!baseline) {
|
|
82
|
+
throw new Error(`DEPRECATION_BASELINE_VERSION must be stable semver, got: ${baselineVersion}`);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (!Number.isInteger(releaseWindow) || releaseWindow < 1) {
|
|
86
|
+
throw new Error(`STABLE_RELEASE_WINDOW must be a positive integer, got: ${releaseWindow}`);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (compareVersions(target, baseline) < 0) {
|
|
90
|
+
return {
|
|
91
|
+
publish: true,
|
|
92
|
+
elapsed: 0,
|
|
93
|
+
reason: `${target.raw} is before dashboard deprecation baseline ${baseline.raw}`,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const versions = parseStableTags(stableTags);
|
|
98
|
+
const hasBaseline = versions.some((version) => compareVersions(version, baseline) === 0);
|
|
99
|
+
if (compareVersions(target, baseline) > 0 && !hasBaseline) {
|
|
100
|
+
throw new Error(
|
|
101
|
+
`Cannot count dashboard sunset releases: baseline tag ${baseline.raw} is missing from git tags`,
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (!versions.some((version) => compareVersions(version, target) === 0)) {
|
|
106
|
+
versions.push(target);
|
|
107
|
+
versions.sort(compareVersions);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const elapsed = versions.filter(
|
|
111
|
+
(version) => compareVersions(version, baseline) > 0 && compareVersions(version, target) <= 0,
|
|
112
|
+
).length;
|
|
113
|
+
const publish = elapsed < releaseWindow;
|
|
114
|
+
const reason = publish
|
|
115
|
+
? `legacy dashboard publish is still inside sunset window (${elapsed}/${releaseWindow} stable releases elapsed since ${baseline.raw})`
|
|
116
|
+
: `legacy dashboard sunset reached (${elapsed}/${releaseWindow} stable releases elapsed since ${baseline.raw})`;
|
|
117
|
+
|
|
118
|
+
return { publish, elapsed, reason };
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function appendGithubOutput(values) {
|
|
122
|
+
if (!process.env.GITHUB_OUTPUT) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
const lines = Object.entries(values).map(([key, value]) => `${key}=${String(value)}`);
|
|
126
|
+
fs.appendFileSync(process.env.GITHUB_OUTPUT, `${lines.join('\n')}\n`);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function main() {
|
|
130
|
+
const args = parseArgs(process.argv.slice(2));
|
|
131
|
+
const targetTag = args.target || process.env.TARGET_TAG;
|
|
132
|
+
const baselineVersion = args.baseline || process.env.DEPRECATION_BASELINE_VERSION;
|
|
133
|
+
const windowValue = args.window || process.env.STABLE_RELEASE_WINDOW || '2';
|
|
134
|
+
const releaseWindow = Number(windowValue);
|
|
135
|
+
const stableTags = args.tagsStdin
|
|
136
|
+
? fs.readFileSync(0, 'utf8').split(/\r?\n/).filter(Boolean)
|
|
137
|
+
: readStableTagsFromGit();
|
|
138
|
+
|
|
139
|
+
const result = evaluateDashboardSunset({
|
|
140
|
+
targetTag,
|
|
141
|
+
baselineVersion,
|
|
142
|
+
releaseWindow,
|
|
143
|
+
stableTags,
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
appendGithubOutput({
|
|
147
|
+
publish: result.publish ? 'true' : 'false',
|
|
148
|
+
elapsed: result.elapsed,
|
|
149
|
+
reason: result.reason,
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
const status = result.publish ? '[OK]' : '[i]';
|
|
153
|
+
console.log(`${status} ${result.reason}`);
|
|
154
|
+
if (!result.publish) {
|
|
155
|
+
console.log('[i] Skipping ghcr.io/kaitranntt/ccs-dashboard publish; use ghcr.io/kaitranntt/ccs.');
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
if (require.main === module) {
|
|
160
|
+
try {
|
|
161
|
+
main();
|
|
162
|
+
} catch (error) {
|
|
163
|
+
console.error(`[X] ${error.message}`);
|
|
164
|
+
process.exit(1);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
module.exports = {
|
|
169
|
+
evaluateDashboardSunset,
|
|
170
|
+
parseStableVersion,
|
|
171
|
+
};
|
|
@@ -22,6 +22,7 @@ const slowTests = [
|
|
|
22
22
|
'tests/integration/cursor-daemon-lifecycle.test.ts',
|
|
23
23
|
'tests/integration/logging-request-context.test.ts',
|
|
24
24
|
'tests/integration/proxy/daemon-lifecycle.test.ts',
|
|
25
|
+
'tests/integration/web-server/codex-profiles-endpoint.test.ts',
|
|
25
26
|
'tests/unit/commands/persist-command-handler.test.ts',
|
|
26
27
|
'tests/unit/hooks/browser-mcp-advanced-interactions.test.ts',
|
|
27
28
|
'tests/unit/hooks/browser-mcp-downloads-and-files.test.ts',
|
package/scripts/verify-bundle.js
CHANGED
|
@@ -16,7 +16,10 @@ const path = require('path');
|
|
|
16
16
|
const zlib = require('zlib');
|
|
17
17
|
|
|
18
18
|
const UI_DIR = path.join(__dirname, '../dist/ui');
|
|
19
|
-
|
|
19
|
+
// 1.75MB - bumped from 1.5MB when the code editor moved from
|
|
20
|
+
// react-simple-code-editor + prism-react-renderer (~18KB) to CodeMirror 6
|
|
21
|
+
// (~80KB gzipped) to restore native selection/copy in the raw config viewers.
|
|
22
|
+
const MAX_SIZE = 1.75 * 1024 * 1024;
|
|
20
23
|
|
|
21
24
|
function getGzipSize(filePath) {
|
|
22
25
|
const content = fs.readFileSync(filePath);
|