@codemieai/code 0.0.58 → 0.1.0
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 +56 -15
- package/dist/agents/core/BaseAgentAdapter.d.ts.map +1 -1
- package/dist/agents/core/BaseAgentAdapter.js +3 -0
- package/dist/agents/core/BaseAgentAdapter.js.map +1 -1
- package/dist/agents/plugins/claude/claude.plugin.d.ts.map +1 -1
- package/dist/agents/plugins/claude/claude.plugin.js +18 -0
- package/dist/agents/plugins/claude/claude.plugin.js.map +1 -1
- package/dist/agents/plugins/claude/plugin/.claude-plugin/plugin.json +1 -1
- package/dist/agents/plugins/claude/plugin/commands/README.md +2 -31
- package/dist/agents/plugins/claude/plugin/commands/codemie-catchup.md +5 -0
- package/dist/agents/plugins/claude/plugin/commands/codemie-init.md +42 -43
- package/dist/agents/plugins/claude/plugin/commands/codemie-subagents.md +5 -0
- package/dist/agents/plugins/claude/plugin/commands/handoff.md +56 -0
- package/dist/agents/plugins/claude/plugin/commands/memory-refresh.md +5 -0
- package/dist/agents/plugins/claude/plugin/hooks/hooks.json +1 -1
- package/dist/agents/plugins/claude/plugin/scripts/bash/rtk-rewrite.sh +101 -0
- package/dist/agents/plugins/claude/plugin/skills/msgraph/README.md +4 -1
- package/dist/agents/plugins/claude/plugin/skills/msgraph/SKILL.md +27 -8
- package/dist/agents/plugins/claude/plugin/skills/msgraph/scripts/msgraph.js +63 -3
- package/dist/agents/plugins/claude/plugin/skills/report-issue/SKILL.md +1 -0
- package/dist/assets/demo.gif +0 -0
- package/dist/assets/skills-sh-egress-guard.cjs +166 -0
- package/dist/cli/commands/assistants/setup/constants.d.ts +1 -25
- package/dist/cli/commands/assistants/setup/constants.d.ts.map +1 -1
- package/dist/cli/commands/assistants/setup/constants.js +1 -20
- package/dist/cli/commands/assistants/setup/constants.js.map +1 -1
- package/dist/cli/commands/assistants/setup/generators/claude-agent-generator.d.ts +4 -4
- package/dist/cli/commands/assistants/setup/generators/claude-agent-generator.d.ts.map +1 -1
- package/dist/cli/commands/assistants/setup/generators/claude-agent-generator.js +11 -10
- package/dist/cli/commands/assistants/setup/generators/claude-agent-generator.js.map +1 -1
- package/dist/cli/commands/assistants/setup/generators/claude-skill-generator.d.ts +4 -4
- package/dist/cli/commands/assistants/setup/generators/claude-skill-generator.d.ts.map +1 -1
- package/dist/cli/commands/assistants/setup/generators/claude-skill-generator.js +11 -9
- package/dist/cli/commands/assistants/setup/generators/claude-skill-generator.js.map +1 -1
- package/dist/cli/commands/assistants/setup/helpers.d.ts +4 -18
- package/dist/cli/commands/assistants/setup/helpers.d.ts.map +1 -1
- package/dist/cli/commands/assistants/setup/helpers.js +10 -60
- package/dist/cli/commands/assistants/setup/helpers.js.map +1 -1
- package/dist/cli/commands/assistants/setup/index.d.ts +0 -8
- package/dist/cli/commands/assistants/setup/index.d.ts.map +1 -1
- package/dist/cli/commands/assistants/setup/index.js +20 -164
- package/dist/cli/commands/assistants/setup/index.js.map +1 -1
- package/dist/cli/commands/assistants/setup/selection/actions.d.ts +1 -30
- package/dist/cli/commands/assistants/setup/selection/actions.d.ts.map +1 -1
- package/dist/cli/commands/assistants/setup/selection/actions.js +1 -320
- package/dist/cli/commands/assistants/setup/selection/actions.js.map +1 -1
- package/dist/cli/commands/assistants/setup/selection/constants.d.ts +3 -65
- package/dist/cli/commands/assistants/setup/selection/constants.d.ts.map +1 -1
- package/dist/cli/commands/assistants/setup/selection/constants.js +4 -81
- package/dist/cli/commands/assistants/setup/selection/constants.js.map +1 -1
- package/dist/cli/commands/assistants/setup/selection/index.d.ts +1 -9
- package/dist/cli/commands/assistants/setup/selection/index.d.ts.map +1 -1
- package/dist/cli/commands/assistants/setup/selection/index.js +14 -34
- package/dist/cli/commands/assistants/setup/selection/index.js.map +1 -1
- package/dist/cli/commands/assistants/setup/selection/interactive-prompt.d.ts +1 -19
- package/dist/cli/commands/assistants/setup/selection/interactive-prompt.d.ts.map +1 -1
- package/dist/cli/commands/assistants/setup/selection/interactive-prompt.js +1 -338
- package/dist/cli/commands/assistants/setup/selection/interactive-prompt.js.map +1 -1
- package/dist/cli/commands/assistants/setup/selection/types.d.ts +7 -23
- package/dist/cli/commands/assistants/setup/selection/types.d.ts.map +1 -1
- package/dist/cli/commands/assistants/setup/selection/ui.d.ts +0 -8
- package/dist/cli/commands/assistants/setup/selection/ui.d.ts.map +1 -1
- package/dist/cli/commands/assistants/setup/selection/ui.js +7 -123
- package/dist/cli/commands/assistants/setup/selection/ui.js.map +1 -1
- package/dist/cli/commands/doctor/index.d.ts.map +1 -1
- package/dist/cli/commands/doctor/index.js +10 -1
- package/dist/cli/commands/doctor/index.js.map +1 -1
- package/dist/cli/commands/proxy/connectors/desktop-managed-mcp-servers.json +50 -0
- package/dist/cli/commands/proxy/connectors/desktop.d.ts +13 -3
- package/dist/cli/commands/proxy/connectors/desktop.d.ts.map +1 -1
- package/dist/cli/commands/proxy/connectors/desktop.js +47 -4
- package/dist/cli/commands/proxy/connectors/desktop.js.map +1 -1
- package/dist/cli/commands/proxy/index.d.ts.map +1 -1
- package/dist/cli/commands/proxy/index.js +89 -52
- package/dist/cli/commands/proxy/index.js.map +1 -1
- package/dist/cli/commands/setup.d.ts.map +1 -1
- package/dist/cli/commands/setup.js +2 -0
- package/dist/cli/commands/setup.js.map +1 -1
- package/dist/cli/commands/shared/constants.d.ts +15 -0
- package/dist/cli/commands/shared/constants.d.ts.map +1 -0
- package/dist/cli/commands/shared/constants.js +10 -0
- package/dist/cli/commands/shared/constants.js.map +1 -0
- package/dist/cli/commands/shared/helpers.d.ts +12 -0
- package/dist/cli/commands/shared/helpers.d.ts.map +1 -0
- package/dist/cli/commands/shared/helpers.js +54 -0
- package/dist/cli/commands/shared/helpers.js.map +1 -0
- package/dist/cli/commands/shared/prompts/storage-scope.d.ts +6 -0
- package/dist/cli/commands/shared/prompts/storage-scope.d.ts.map +1 -0
- package/dist/cli/commands/shared/prompts/storage-scope.js +84 -0
- package/dist/cli/commands/shared/prompts/storage-scope.js.map +1 -0
- package/dist/cli/commands/shared/selection/actions.d.ts +40 -0
- package/dist/cli/commands/shared/selection/actions.d.ts.map +1 -0
- package/dist/cli/commands/shared/selection/actions.js +264 -0
- package/dist/cli/commands/shared/selection/actions.js.map +1 -0
- package/dist/cli/commands/shared/selection/constants.d.ts +68 -0
- package/dist/cli/commands/shared/selection/constants.d.ts.map +1 -0
- package/dist/cli/commands/shared/selection/constants.js +70 -0
- package/dist/cli/commands/shared/selection/constants.js.map +1 -0
- package/dist/cli/commands/shared/selection/interactive-prompt.d.ts +16 -0
- package/dist/cli/commands/shared/selection/interactive-prompt.d.ts.map +1 -0
- package/dist/cli/commands/shared/selection/interactive-prompt.js +276 -0
- package/dist/cli/commands/shared/selection/interactive-prompt.js.map +1 -0
- package/dist/cli/commands/shared/selection/types.d.ts +31 -0
- package/dist/cli/commands/shared/selection/types.d.ts.map +1 -0
- package/dist/cli/commands/shared/selection/types.js +2 -0
- package/dist/cli/commands/shared/selection/types.js.map +1 -0
- package/dist/cli/commands/shared/selection/ui.d.ts +9 -0
- package/dist/cli/commands/shared/selection/ui.d.ts.map +1 -0
- package/dist/cli/commands/shared/selection/ui.js +92 -0
- package/dist/cli/commands/shared/selection/ui.js.map +1 -0
- package/dist/cli/commands/skills/add.d.ts +9 -0
- package/dist/cli/commands/skills/add.d.ts.map +1 -0
- package/dist/cli/commands/skills/add.js +187 -0
- package/dist/cli/commands/skills/add.js.map +1 -0
- package/dist/cli/commands/skills/find.d.ts +17 -0
- package/dist/cli/commands/skills/find.d.ts.map +1 -0
- package/dist/cli/commands/skills/find.js +94 -0
- package/dist/cli/commands/skills/find.js.map +1 -0
- package/dist/cli/commands/skills/index.d.ts +10 -0
- package/dist/cli/commands/skills/index.d.ts.map +1 -0
- package/dist/cli/commands/skills/index.js +23 -0
- package/dist/cli/commands/skills/index.js.map +1 -0
- package/dist/cli/commands/skills/lib/agent-detection.d.ts +27 -0
- package/dist/cli/commands/skills/lib/agent-detection.d.ts.map +1 -0
- package/dist/cli/commands/skills/lib/agent-detection.js +50 -0
- package/dist/cli/commands/skills/lib/agent-detection.js.map +1 -0
- package/dist/cli/commands/skills/lib/error-classify.d.ts +14 -0
- package/dist/cli/commands/skills/lib/error-classify.d.ts.map +1 -0
- package/dist/cli/commands/skills/lib/error-classify.js +64 -0
- package/dist/cli/commands/skills/lib/error-classify.js.map +1 -0
- package/dist/cli/commands/skills/lib/require-auth.d.ts +17 -0
- package/dist/cli/commands/skills/lib/require-auth.d.ts.map +1 -0
- package/dist/cli/commands/skills/lib/require-auth.js +44 -0
- package/dist/cli/commands/skills/lib/require-auth.js.map +1 -0
- package/dist/cli/commands/skills/lib/result-render.d.ts +26 -0
- package/dist/cli/commands/skills/lib/result-render.d.ts.map +1 -0
- package/dist/cli/commands/skills/lib/result-render.js +77 -0
- package/dist/cli/commands/skills/lib/result-render.js.map +1 -0
- package/dist/cli/commands/skills/lib/run-skills-cli.d.ts +46 -0
- package/dist/cli/commands/skills/lib/run-skills-cli.d.ts.map +1 -0
- package/dist/cli/commands/skills/lib/run-skills-cli.js +217 -0
- package/dist/cli/commands/skills/lib/run-skills-cli.js.map +1 -0
- package/dist/cli/commands/skills/lib/sanitize.d.ts +17 -0
- package/dist/cli/commands/skills/lib/sanitize.d.ts.map +1 -0
- package/dist/cli/commands/skills/lib/sanitize.js +73 -0
- package/dist/cli/commands/skills/lib/sanitize.js.map +1 -0
- package/dist/cli/commands/skills/lib/skills-metrics.d.ts +74 -0
- package/dist/cli/commands/skills/lib/skills-metrics.d.ts.map +1 -0
- package/dist/cli/commands/skills/lib/skills-metrics.js +268 -0
- package/dist/cli/commands/skills/lib/skills-metrics.js.map +1 -0
- package/dist/cli/commands/skills/lib/skills-search-client.d.ts +36 -0
- package/dist/cli/commands/skills/lib/skills-search-client.d.ts.map +1 -0
- package/dist/cli/commands/skills/lib/skills-search-client.js +147 -0
- package/dist/cli/commands/skills/lib/skills-search-client.js.map +1 -0
- package/dist/cli/commands/skills/lib/skills-sh-telemetry.d.ts +10 -0
- package/dist/cli/commands/skills/lib/skills-sh-telemetry.d.ts.map +1 -0
- package/dist/cli/commands/skills/lib/skills-sh-telemetry.js +33 -0
- package/dist/cli/commands/skills/lib/skills-sh-telemetry.js.map +1 -0
- package/dist/cli/commands/skills/list.d.ts +13 -0
- package/dist/cli/commands/skills/list.d.ts.map +1 -0
- package/dist/cli/commands/skills/list.js +55 -0
- package/dist/cli/commands/skills/list.js.map +1 -0
- package/dist/cli/commands/skills/remove.d.ts +11 -0
- package/dist/cli/commands/skills/remove.d.ts.map +1 -0
- package/dist/cli/commands/skills/remove.js +93 -0
- package/dist/cli/commands/skills/remove.js.map +1 -0
- package/dist/cli/commands/skills/setup/constants.d.ts +2 -0
- package/dist/cli/commands/skills/setup/constants.d.ts.map +1 -0
- package/dist/cli/commands/skills/setup/constants.js +2 -0
- package/dist/cli/commands/skills/setup/constants.js.map +1 -0
- package/dist/cli/commands/skills/setup/data.d.ts +28 -0
- package/dist/cli/commands/skills/setup/data.d.ts.map +1 -0
- package/dist/cli/commands/skills/setup/data.js +79 -0
- package/dist/cli/commands/skills/setup/data.js.map +1 -0
- package/dist/cli/commands/skills/setup/generators/claude-skill-generator.d.ts +12 -0
- package/dist/cli/commands/skills/setup/generators/claude-skill-generator.d.ts.map +1 -0
- package/dist/cli/commands/skills/setup/generators/claude-skill-generator.js +94 -0
- package/dist/cli/commands/skills/setup/generators/claude-skill-generator.js.map +1 -0
- package/dist/cli/commands/skills/setup/helpers.d.ts +12 -0
- package/dist/cli/commands/skills/setup/helpers.d.ts.map +1 -0
- package/dist/cli/commands/skills/setup/helpers.js +31 -0
- package/dist/cli/commands/skills/setup/helpers.js.map +1 -0
- package/dist/cli/commands/skills/setup/index.d.ts +5 -0
- package/dist/cli/commands/skills/setup/index.d.ts.map +1 -0
- package/dist/cli/commands/skills/setup/index.js +137 -0
- package/dist/cli/commands/skills/setup/index.js.map +1 -0
- package/dist/cli/commands/skills/setup/selection/actions.d.ts +2 -0
- package/dist/cli/commands/skills/setup/selection/actions.d.ts.map +1 -0
- package/dist/cli/commands/skills/setup/selection/actions.js +2 -0
- package/dist/cli/commands/skills/setup/selection/actions.js.map +1 -0
- package/dist/cli/commands/skills/setup/selection/constants.d.ts +11 -0
- package/dist/cli/commands/skills/setup/selection/constants.d.ts.map +1 -0
- package/dist/cli/commands/skills/setup/selection/constants.js +11 -0
- package/dist/cli/commands/skills/setup/selection/constants.js.map +1 -0
- package/dist/cli/commands/skills/setup/selection/index.d.ts +13 -0
- package/dist/cli/commands/skills/setup/selection/index.d.ts.map +1 -0
- package/dist/cli/commands/skills/setup/selection/index.js +113 -0
- package/dist/cli/commands/skills/setup/selection/index.js.map +1 -0
- package/dist/cli/commands/skills/setup/selection/interactive-prompt.d.ts +2 -0
- package/dist/cli/commands/skills/setup/selection/interactive-prompt.d.ts.map +1 -0
- package/dist/cli/commands/skills/setup/selection/interactive-prompt.js +2 -0
- package/dist/cli/commands/skills/setup/selection/interactive-prompt.js.map +1 -0
- package/dist/cli/commands/skills/setup/selection/types.d.ts +13 -0
- package/dist/cli/commands/skills/setup/selection/types.d.ts.map +1 -0
- package/dist/cli/commands/skills/setup/selection/types.js +2 -0
- package/dist/cli/commands/skills/setup/selection/types.js.map +1 -0
- package/dist/cli/commands/skills/setup/selection/ui.d.ts +3 -0
- package/dist/cli/commands/skills/setup/selection/ui.d.ts.map +1 -0
- package/dist/cli/commands/skills/setup/selection/ui.js +68 -0
- package/dist/cli/commands/skills/setup/selection/ui.js.map +1 -0
- package/dist/cli/commands/skills/setup/sync.d.ts +13 -0
- package/dist/cli/commands/skills/setup/sync.d.ts.map +1 -0
- package/dist/cli/commands/skills/setup/sync.js +46 -0
- package/dist/cli/commands/skills/setup/sync.js.map +1 -0
- package/dist/cli/commands/skills/update.d.ts +7 -0
- package/dist/cli/commands/skills/update.d.ts.map +1 -0
- package/dist/cli/commands/skills/update.js +71 -0
- package/dist/cli/commands/skills/update.js.map +1 -0
- package/dist/cli/first-time.d.ts.map +1 -1
- package/dist/cli/first-time.js +4 -0
- package/dist/cli/first-time.js.map +1 -1
- package/dist/cli/index.js +2 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/env/types.d.ts +14 -0
- package/dist/env/types.d.ts.map +1 -1
- package/dist/env/types.js.map +1 -1
- package/dist/providers/core/types.d.ts +1 -1
- package/dist/providers/core/types.d.ts.map +1 -1
- package/dist/providers/plugins/anthropic-subscription/anthropic-subscription.template.d.ts.map +1 -1
- package/dist/providers/plugins/anthropic-subscription/anthropic-subscription.template.js +26 -2
- package/dist/providers/plugins/anthropic-subscription/anthropic-subscription.template.js.map +1 -1
- package/dist/providers/plugins/sso/proxy/plugins/claude-request-normalizer.plugin.d.ts +31 -0
- package/dist/providers/plugins/sso/proxy/plugins/claude-request-normalizer.plugin.d.ts.map +1 -0
- package/dist/providers/plugins/sso/proxy/plugins/claude-request-normalizer.plugin.js +148 -0
- package/dist/providers/plugins/sso/proxy/plugins/claude-request-normalizer.plugin.js.map +1 -0
- package/dist/providers/plugins/sso/proxy/plugins/index.d.ts +12 -13
- package/dist/providers/plugins/sso/proxy/plugins/index.d.ts.map +1 -1
- package/dist/providers/plugins/sso/proxy/plugins/index.js +15 -17
- package/dist/providers/plugins/sso/proxy/plugins/index.js.map +1 -1
- package/dist/providers/plugins/sso/sso.http-client.d.ts +1 -1
- package/dist/providers/plugins/sso/sso.http-client.js +3 -3
- package/dist/providers/plugins/sso/sso.http-client.js.map +1 -1
- package/dist/providers/plugins/sso/sso.models.js +2 -2
- package/dist/providers/plugins/sso/sso.models.js.map +1 -1
- package/dist/providers/plugins/sso/sso.setup-steps.d.ts.map +1 -1
- package/dist/providers/plugins/sso/sso.setup-steps.js +6 -10
- package/dist/providers/plugins/sso/sso.setup-steps.js.map +1 -1
- package/dist/utils/config.d.ts +14 -3
- package/dist/utils/config.d.ts.map +1 -1
- package/dist/utils/config.js +95 -5
- package/dist/utils/config.js.map +1 -1
- package/package.json +22 -10
- package/scripts/copy-plugins.js +5 -0
- package/scripts/sonar/package.json +3 -0
- package/scripts/sonar/run-local-sonar.js +405 -0
- package/dist/agents/plugins/claude/plugin/commands/codemie-commit.md +0 -31
- package/dist/agents/plugins/claude/plugin/scripts/bash/rtk-auto-wrapper.sh +0 -81
- package/dist/providers/plugins/sso/proxy/plugins/claude-thinking-transformer.plugin.d.ts +0 -30
- package/dist/providers/plugins/sso/proxy/plugins/claude-thinking-transformer.plugin.d.ts.map +0 -1
- package/dist/providers/plugins/sso/proxy/plugins/claude-thinking-transformer.plugin.js +0 -111
- package/dist/providers/plugins/sso/proxy/plugins/claude-thinking-transformer.plugin.js.map +0 -1
|
@@ -0,0 +1,405 @@
|
|
|
1
|
+
// Copyright 2026 EPAM Systems, Inc. (“EPAM”)
|
|
2
|
+
//
|
|
3
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
// you may not use this file except in compliance with the License.
|
|
5
|
+
// You may obtain a copy of the License at
|
|
6
|
+
//
|
|
7
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
//
|
|
9
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
// See the License for the specific language governing permissions and
|
|
13
|
+
// limitations under the License.
|
|
14
|
+
|
|
15
|
+
const { spawn } = require('node:child_process');
|
|
16
|
+
const fs = require('node:fs');
|
|
17
|
+
const http = require('node:http');
|
|
18
|
+
const https = require('node:https');
|
|
19
|
+
const path = require('node:path');
|
|
20
|
+
|
|
21
|
+
const REPOSITORY_ROOT = path.resolve(__dirname, '../..');
|
|
22
|
+
const CONNECTED_MODE_PATH = path.resolve(REPOSITORY_ROOT, '.sonarlint/connectedMode.json');
|
|
23
|
+
const SONAR_PROPERTIES_PATH = path.resolve(REPOSITORY_ROOT, 'sonar-project.properties');
|
|
24
|
+
const SERVER_TIMEOUT_MS = 5000;
|
|
25
|
+
const PAGE_SIZE = 500;
|
|
26
|
+
|
|
27
|
+
function log(message) {
|
|
28
|
+
process.stdout.write(`[sonar-local] ${message}\n`);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function logError(message) {
|
|
32
|
+
process.stderr.write(`[sonar-local] ${message}\n`);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function readConnectedModeConfig() {
|
|
36
|
+
if (!fs.existsSync(CONNECTED_MODE_PATH)) {
|
|
37
|
+
throw new Error(`Missing SonarLint connected mode config: ${CONNECTED_MODE_PATH}`);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const rawContent = fs.readFileSync(CONNECTED_MODE_PATH, 'utf8');
|
|
41
|
+
const parsedConfig = JSON.parse(rawContent);
|
|
42
|
+
const sonarHostUrl = parsedConfig.sonarQubeUri;
|
|
43
|
+
const sonarProjectKey = parsedConfig.projectKey;
|
|
44
|
+
|
|
45
|
+
if (!sonarHostUrl || !sonarProjectKey) {
|
|
46
|
+
throw new Error(
|
|
47
|
+
`SonarLint connected mode config must define both "sonarQubeUri" and "projectKey": ${CONNECTED_MODE_PATH}`,
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return { sonarHostUrl, sonarProjectKey };
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function readSonarProperties() {
|
|
55
|
+
if (!fs.existsSync(SONAR_PROPERTIES_PATH)) {
|
|
56
|
+
throw new Error(`Missing Sonar project configuration: ${SONAR_PROPERTIES_PATH}`);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const properties = {};
|
|
60
|
+
const rawContent = fs.readFileSync(SONAR_PROPERTIES_PATH, 'utf8');
|
|
61
|
+
|
|
62
|
+
for (const rawLine of rawContent.split(/\r?\n/u)) {
|
|
63
|
+
const line = rawLine.trim();
|
|
64
|
+
if (!line || line.startsWith('#')) {
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const separatorIndex = line.indexOf('=');
|
|
69
|
+
if (separatorIndex === -1) {
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const key = line.slice(0, separatorIndex).trim();
|
|
74
|
+
const value = line.slice(separatorIndex + 1).trim();
|
|
75
|
+
properties[key] = value;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return properties;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function createRequestModule(targetUrl) {
|
|
82
|
+
return targetUrl.protocol === 'https:' ? https : http;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function resolveBranchName() {
|
|
86
|
+
const overrideBranchName = process.env.SONAR_BRANCH_NAME?.trim();
|
|
87
|
+
if (overrideBranchName) {
|
|
88
|
+
return overrideBranchName;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const gitEntryPath = path.resolve(REPOSITORY_ROOT, '.git');
|
|
92
|
+
if (!fs.existsSync(gitEntryPath)) {
|
|
93
|
+
throw new Error('Unable to locate .git metadata. Set SONAR_BRANCH_NAME explicitly and retry.');
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
let gitDirPath = gitEntryPath;
|
|
97
|
+
const gitEntryStat = fs.statSync(gitEntryPath);
|
|
98
|
+
if (gitEntryStat.isFile()) {
|
|
99
|
+
const gitPointer = fs.readFileSync(gitEntryPath, 'utf8').trim();
|
|
100
|
+
const gitDirPrefix = 'gitdir:';
|
|
101
|
+
if (!gitPointer.startsWith(gitDirPrefix)) {
|
|
102
|
+
throw new Error('Unable to resolve git metadata directory. Set SONAR_BRANCH_NAME explicitly and retry.');
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
gitDirPath = path.resolve(REPOSITORY_ROOT, gitPointer.slice(gitDirPrefix.length).trim());
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const headPath = path.join(gitDirPath, 'HEAD');
|
|
109
|
+
if (!fs.existsSync(headPath)) {
|
|
110
|
+
throw new Error('Unable to locate git HEAD. Set SONAR_BRANCH_NAME explicitly and retry.');
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const headContents = fs.readFileSync(headPath, 'utf8').trim();
|
|
114
|
+
const refPrefix = 'ref: refs/heads/';
|
|
115
|
+
if (!headContents.startsWith(refPrefix)) {
|
|
116
|
+
throw new Error('Unable to determine the current git branch from HEAD. Set SONAR_BRANCH_NAME explicitly.');
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return headContents.slice(refPrefix.length);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function runCommand(command, args, options = {}) {
|
|
123
|
+
const { env = process.env, description = command } = options;
|
|
124
|
+
|
|
125
|
+
return new Promise((resolve, reject) => {
|
|
126
|
+
const child = spawn(command, args, {
|
|
127
|
+
cwd: REPOSITORY_ROOT,
|
|
128
|
+
env,
|
|
129
|
+
stdio: 'inherit',
|
|
130
|
+
shell: process.platform === 'win32',
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
child.on('error', (error) => {
|
|
134
|
+
reject(new Error(`Failed to start ${description}: ${error.message}`));
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
child.on('exit', (code) => {
|
|
138
|
+
if (code === 0) {
|
|
139
|
+
resolve();
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
reject(new Error(`${description} exited with code ${code}`));
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function resolveScannerCommand() {
|
|
149
|
+
const scannerCommand = process.env.SONAR_SCANNER_PATH?.trim() || 'sonar-scanner';
|
|
150
|
+
|
|
151
|
+
if (scannerCommand === 'sonar-scanner') {
|
|
152
|
+
const pathEntries = (process.env.PATH || '').split(path.delimiter);
|
|
153
|
+
const executableNames =
|
|
154
|
+
process.platform === 'win32'
|
|
155
|
+
? ['sonar-scanner.cmd', 'sonar-scanner.bat', 'sonar-scanner.exe']
|
|
156
|
+
: ['sonar-scanner'];
|
|
157
|
+
|
|
158
|
+
const foundScanner = pathEntries.some((entry) =>
|
|
159
|
+
executableNames.some((name) => fs.existsSync(path.join(entry, name))),
|
|
160
|
+
);
|
|
161
|
+
if (!foundScanner) {
|
|
162
|
+
throw new Error(
|
|
163
|
+
'sonar-scanner was not found. Install the official SonarScanner CLI or set SONAR_SCANNER_PATH.',
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
} else if (!fs.existsSync(scannerCommand)) {
|
|
167
|
+
throw new Error(`SONAR_SCANNER_PATH does not exist: ${scannerCommand}`);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
return scannerCommand;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function sonarRequestJson(sonarHostUrl, sonarToken, endpoint, searchParams = {}) {
|
|
174
|
+
return new Promise((resolve, reject) => {
|
|
175
|
+
const requestUrl = new URL(endpoint, sonarHostUrl);
|
|
176
|
+
for (const [key, value] of Object.entries(searchParams)) {
|
|
177
|
+
if (value !== undefined && value !== null && value !== '') {
|
|
178
|
+
requestUrl.searchParams.set(key, String(value));
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
const request = createRequestModule(requestUrl).request(
|
|
183
|
+
requestUrl,
|
|
184
|
+
{
|
|
185
|
+
method: 'GET',
|
|
186
|
+
timeout: SERVER_TIMEOUT_MS,
|
|
187
|
+
headers: {
|
|
188
|
+
Authorization: `Basic ${Buffer.from(`${sonarToken}:`).toString('base64')}`,
|
|
189
|
+
Accept: 'application/json',
|
|
190
|
+
},
|
|
191
|
+
},
|
|
192
|
+
(response) => {
|
|
193
|
+
const chunks = [];
|
|
194
|
+
response.on('data', (chunk) => chunks.push(chunk));
|
|
195
|
+
response.on('end', () => {
|
|
196
|
+
const rawBody = Buffer.concat(chunks).toString('utf8');
|
|
197
|
+
if (response.statusCode && response.statusCode >= 400) {
|
|
198
|
+
reject(new Error(`Sonar API request failed (${response.statusCode}) for ${requestUrl.pathname}.`));
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
try {
|
|
203
|
+
resolve(JSON.parse(rawBody));
|
|
204
|
+
} catch (error) {
|
|
205
|
+
reject(new Error(`Failed to parse Sonar API response for ${requestUrl.pathname}: ${error.message}`));
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
},
|
|
209
|
+
);
|
|
210
|
+
|
|
211
|
+
request.on('timeout', () => {
|
|
212
|
+
request.destroy(new Error(`Timed out after ${SERVER_TIMEOUT_MS}ms`));
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
request.on('error', (error) => {
|
|
216
|
+
reject(new Error(`Sonar API request failed for ${requestUrl.pathname}: ${error.message}`));
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
request.end();
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
async function fetchPaginatedItems(fetchPage) {
|
|
224
|
+
const items = [];
|
|
225
|
+
let page = 1;
|
|
226
|
+
let total = 0;
|
|
227
|
+
let pageSize = 0;
|
|
228
|
+
|
|
229
|
+
do {
|
|
230
|
+
const response = await fetchPage(page);
|
|
231
|
+
const responseItems = response.issues ?? response.hotspots ?? [];
|
|
232
|
+
items.push(...responseItems);
|
|
233
|
+
total = response.total ?? response.paging?.total ?? responseItems.length;
|
|
234
|
+
pageSize = response.ps ?? response.paging?.pageSize ?? responseItems.length;
|
|
235
|
+
page += 1;
|
|
236
|
+
} while (items.length < total && pageSize > 0);
|
|
237
|
+
|
|
238
|
+
return items;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
function stripProjectKey(component, projectKey) {
|
|
242
|
+
const componentPrefix = `${projectKey}:`;
|
|
243
|
+
if (!component) {
|
|
244
|
+
return '(unknown component)';
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
return component.startsWith(componentPrefix) ? component.slice(componentPrefix.length) : component;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
function formatIssue(issue, projectKey) {
|
|
251
|
+
const location = `${stripProjectKey(issue.component, projectKey)}:${issue.line ?? 1}`;
|
|
252
|
+
return `- [${issue.severity}] [${issue.type}] ${location} ${issue.rule}: ${issue.message}`;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
function formatHotspot(hotspot, projectKey) {
|
|
256
|
+
const location = `${stripProjectKey(hotspot.component, projectKey)}:${hotspot.line ?? 1}`;
|
|
257
|
+
return `- ${location} ${hotspot.ruleKey ?? hotspot.rule ?? 'unknown-rule'}: ${hotspot.message}`;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
async function collectSonarDetails({ sonarHostUrl, sonarProjectKey, branchName, sonarToken }) {
|
|
261
|
+
const qualityGate = await sonarRequestJson(sonarHostUrl, sonarToken, '/api/qualitygates/project_status', {
|
|
262
|
+
projectKey: sonarProjectKey,
|
|
263
|
+
branch: branchName,
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
const issues = await fetchPaginatedItems((page) =>
|
|
267
|
+
sonarRequestJson(sonarHostUrl, sonarToken, '/api/issues/search', {
|
|
268
|
+
componentKeys: sonarProjectKey,
|
|
269
|
+
branch: branchName,
|
|
270
|
+
resolved: 'false',
|
|
271
|
+
p: page,
|
|
272
|
+
ps: PAGE_SIZE,
|
|
273
|
+
s: 'FILE_LINE',
|
|
274
|
+
asc: 'true',
|
|
275
|
+
}),
|
|
276
|
+
);
|
|
277
|
+
|
|
278
|
+
const hotspots = await fetchPaginatedItems((page) =>
|
|
279
|
+
sonarRequestJson(sonarHostUrl, sonarToken, '/api/hotspots/search', {
|
|
280
|
+
projectKey: sonarProjectKey,
|
|
281
|
+
branch: branchName,
|
|
282
|
+
status: 'TO_REVIEW',
|
|
283
|
+
p: page,
|
|
284
|
+
ps: PAGE_SIZE,
|
|
285
|
+
}),
|
|
286
|
+
);
|
|
287
|
+
|
|
288
|
+
return { hotspots, issues, qualityGate };
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
function printSonarDetails(details, context) {
|
|
292
|
+
const { hotspots, issues, qualityGate } = details;
|
|
293
|
+
const { branchName, sonarProjectKey } = context;
|
|
294
|
+
|
|
295
|
+
log(`Project: ${sonarProjectKey}`);
|
|
296
|
+
log(`Branch: ${branchName}`);
|
|
297
|
+
log(`Quality gate: ${qualityGate.projectStatus.status}`);
|
|
298
|
+
|
|
299
|
+
const failedConditions = (qualityGate.projectStatus.conditions ?? []).filter(
|
|
300
|
+
(condition) => condition.status === 'ERROR',
|
|
301
|
+
);
|
|
302
|
+
if (failedConditions.length > 0) {
|
|
303
|
+
log('Failing gate conditions:');
|
|
304
|
+
for (const condition of failedConditions) {
|
|
305
|
+
log(
|
|
306
|
+
`- ${condition.metricKey}: actual=${condition.actualValue ?? 'n/a'}, threshold=${condition.errorThreshold ?? 'n/a'}`,
|
|
307
|
+
);
|
|
308
|
+
}
|
|
309
|
+
} else {
|
|
310
|
+
log('Failing gate conditions: none');
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
log(`Blocking security hotspots: ${hotspots.length}`);
|
|
314
|
+
for (const hotspot of hotspots) {
|
|
315
|
+
log(formatHotspot(hotspot, sonarProjectKey));
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
const bugsAndVulnerabilities = issues.filter((issue) => issue.type === 'BUG' || issue.type === 'VULNERABILITY');
|
|
319
|
+
log(`Bugs and vulnerabilities: ${bugsAndVulnerabilities.length}`);
|
|
320
|
+
for (const issue of bugsAndVulnerabilities) {
|
|
321
|
+
log(formatIssue(issue, sonarProjectKey));
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
log(`All unresolved issues: ${issues.length}`);
|
|
325
|
+
for (const issue of issues) {
|
|
326
|
+
log(formatIssue(issue, sonarProjectKey));
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
async function printFailureDetails(context) {
|
|
331
|
+
try {
|
|
332
|
+
const details = await collectSonarDetails(context);
|
|
333
|
+
printSonarDetails(details, context);
|
|
334
|
+
} catch (detailsError) {
|
|
335
|
+
logError(`Failed to fetch Sonar details after scan failure: ${detailsError.message}`);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
async function main() {
|
|
340
|
+
const { sonarHostUrl, sonarProjectKey } = readConnectedModeConfig();
|
|
341
|
+
const sonarProperties = readSonarProperties();
|
|
342
|
+
const sonarToken = process.env.SONAR_TOKEN?.trim();
|
|
343
|
+
const branchName = resolveBranchName();
|
|
344
|
+
|
|
345
|
+
if (!sonarToken) {
|
|
346
|
+
log('Skipping Sonar scan because SONAR_TOKEN is not set.');
|
|
347
|
+
process.exit(0);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
log(`Using SonarQube project "${sonarProjectKey}" from .sonarlint/connectedMode.json.`);
|
|
351
|
+
log(`Running analysis for branch "${branchName}".`);
|
|
352
|
+
|
|
353
|
+
if (sonarProperties['sonar.projectKey'] && sonarProperties['sonar.projectKey'] !== sonarProjectKey) {
|
|
354
|
+
log(
|
|
355
|
+
`Overriding sonar.projectKey="${sonarProperties['sonar.projectKey']}" with connected-mode project key "${sonarProjectKey}".`,
|
|
356
|
+
);
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
if (process.env.SONAR_SKIP_TESTS?.trim()) {
|
|
360
|
+
log('Skipping test run (SONAR_SKIP_TESTS is set). Using existing coverage.xml.');
|
|
361
|
+
} else {
|
|
362
|
+
log('Generating coverage.xml...');
|
|
363
|
+
await runCommand(
|
|
364
|
+
'poetry',
|
|
365
|
+
['run', 'pytest', 'tests/', '-W', 'ignore::DeprecationWarning', '--cov', '--cov-report=xml:coverage.xml'],
|
|
366
|
+
{ description: 'coverage generation' },
|
|
367
|
+
);
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
const scannerCommand = resolveScannerCommand();
|
|
371
|
+
log(`Running sonar-scanner against ${sonarHostUrl}.`);
|
|
372
|
+
try {
|
|
373
|
+
await runCommand(
|
|
374
|
+
scannerCommand,
|
|
375
|
+
[
|
|
376
|
+
`-Dsonar.projectKey=${sonarProjectKey}`,
|
|
377
|
+
`-Dsonar.branch.name=${branchName}`,
|
|
378
|
+
'-Dsonar.qualitygate.wait=true',
|
|
379
|
+
],
|
|
380
|
+
{
|
|
381
|
+
description: 'sonar-scanner',
|
|
382
|
+
env: {
|
|
383
|
+
...process.env,
|
|
384
|
+
SONAR_HOST_URL: sonarHostUrl,
|
|
385
|
+
SONAR_TOKEN: sonarToken,
|
|
386
|
+
},
|
|
387
|
+
},
|
|
388
|
+
);
|
|
389
|
+
} catch (error) {
|
|
390
|
+
await printFailureDetails({
|
|
391
|
+
branchName,
|
|
392
|
+
sonarHostUrl,
|
|
393
|
+
sonarProjectKey,
|
|
394
|
+
sonarToken,
|
|
395
|
+
});
|
|
396
|
+
throw error;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
log('Sonar scan completed successfully.');
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
main().catch((error) => {
|
|
403
|
+
logError(error.message);
|
|
404
|
+
process.exit(1);
|
|
405
|
+
});
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
allowed-tools: Bash(git add:*), Bash(git commit:*), Bash(git checkout:*)
|
|
3
|
-
description: Create a git commit (not on main branch)
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
## Context
|
|
7
|
-
|
|
8
|
-
- Current branch: !`git branch --show-current`
|
|
9
|
-
- Current git status: !`git status`
|
|
10
|
-
- Current git diff (staged and unstaged changes): !`git diff HEAD`
|
|
11
|
-
- Recent commits: !`git log --oneline -5`
|
|
12
|
-
|
|
13
|
-
## Your task
|
|
14
|
-
|
|
15
|
-
Based on the above changes, create a single git commit.
|
|
16
|
-
|
|
17
|
-
**IMPORTANT**: If the current branch is `main` or `master`:
|
|
18
|
-
1. Analyze the changes to determine the type (feat, fix, refactor, etc.)
|
|
19
|
-
2. Suggest a branch name in format `<type>/<short-description>` (e.g., `feat/add-auth-header-support`, `fix/proxy-timeout-issue`)
|
|
20
|
-
3. Ask user to confirm the branch name or provide an alternative
|
|
21
|
-
4. After confirmation, create the branch with `git checkout -b <branch-name>` and proceed with the commit
|
|
22
|
-
|
|
23
|
-
If on a feature branch:
|
|
24
|
-
1. Stage all relevant changes
|
|
25
|
-
2. Create a commit message following commitlint rules:
|
|
26
|
-
- Format: `<type>(<scope>): <subject>` or `<type>: <subject>`
|
|
27
|
-
- Types: feat, fix, docs, style, refactor, perf, test, chore, ci, revert
|
|
28
|
-
- Scopes (optional): cli, agents, providers, config, proxy, workflows, ci, analytics, utils, deps, tests
|
|
29
|
-
- Subject: max 100 characters, lowercase start, no period at end
|
|
30
|
-
|
|
31
|
-
You have the capability to call multiple tools in a single response. Stage and create the commit using a single message. Do not use any other tools or do anything else. Do not send any other text or messages besides these tool calls.
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# RTK Auto-Wrapper Hook
|
|
3
|
-
# Automatically wraps high-verbosity commands with RTK for token optimization
|
|
4
|
-
#
|
|
5
|
-
# Hook: PreToolUse
|
|
6
|
-
# Matcher: Bash
|
|
7
|
-
# Purpose: Intercept bash commands and suggest RTK wrapper if applicable
|
|
8
|
-
#
|
|
9
|
-
# Installation:
|
|
10
|
-
# 1. Copy to .claude/hooks/bash/rtk-auto-wrapper.sh
|
|
11
|
-
# 2. Make executable: chmod +x .claude/hooks/bash/rtk-auto-wrapper.sh
|
|
12
|
-
# 3. Add to settings.json:
|
|
13
|
-
# {
|
|
14
|
-
# "hooks": {
|
|
15
|
-
# "PreToolUse": [{
|
|
16
|
-
# "matcher": "Bash",
|
|
17
|
-
# "hooks": [".claude/hooks/bash/rtk-auto-wrapper.sh"]
|
|
18
|
-
# }]
|
|
19
|
-
# }
|
|
20
|
-
# }
|
|
21
|
-
#
|
|
22
|
-
# Or use `rtk init` for automatic hook setup.
|
|
23
|
-
|
|
24
|
-
# Check if RTK is installed
|
|
25
|
-
if ! command -v rtk &> /dev/null; then
|
|
26
|
-
# RTK not installed, skip silently
|
|
27
|
-
exit 0
|
|
28
|
-
fi
|
|
29
|
-
|
|
30
|
-
# Parse tool input to get the bash command
|
|
31
|
-
COMMAND=$(echo "$TOOL_INPUT" | jq -r '.command // empty' 2>/dev/null)
|
|
32
|
-
|
|
33
|
-
if [ -z "$COMMAND" ]; then
|
|
34
|
-
# No command found, continue
|
|
35
|
-
exit 0
|
|
36
|
-
fi
|
|
37
|
-
|
|
38
|
-
# Define RTK-optimizable commands with their savings
|
|
39
|
-
declare -A RTK_COMMANDS=(
|
|
40
|
-
["git log"]="92.3"
|
|
41
|
-
["git status"]="76.0"
|
|
42
|
-
["git diff"]="55.9"
|
|
43
|
-
["find"]="76.3"
|
|
44
|
-
["cargo test"]="90.0"
|
|
45
|
-
["cargo build"]="80.0"
|
|
46
|
-
["cargo clippy"]="80.0"
|
|
47
|
-
["pnpm list"]="82.0"
|
|
48
|
-
["pnpm outdated"]="90.0"
|
|
49
|
-
["pnpm test"]="90.0"
|
|
50
|
-
["python pytest"]="90.0"
|
|
51
|
-
["python -m pytest"]="90.0"
|
|
52
|
-
["go test"]="90.0"
|
|
53
|
-
)
|
|
54
|
-
|
|
55
|
-
# Check if command matches RTK-optimizable pattern
|
|
56
|
-
for cmd in "${!RTK_COMMANDS[@]}"; do
|
|
57
|
-
if [[ "$COMMAND" == "$cmd"* ]] && [[ "$COMMAND" != "rtk "* ]]; then
|
|
58
|
-
savings="${RTK_COMMANDS[$cmd]}"
|
|
59
|
-
|
|
60
|
-
# Suggest RTK wrapper
|
|
61
|
-
cat << EOF
|
|
62
|
-
RTK Optimization Available
|
|
63
|
-
|
|
64
|
-
Command: $COMMAND
|
|
65
|
-
Suggested: rtk $COMMAND
|
|
66
|
-
Token Savings: ~${savings}%
|
|
67
|
-
|
|
68
|
-
Using RTK wrapper automatically.
|
|
69
|
-
EOF
|
|
70
|
-
|
|
71
|
-
# Modify command to use RTK
|
|
72
|
-
# Note: This is informational only - actual command modification
|
|
73
|
-
# requires additionalContext return (Claude Code v2.1.9+)
|
|
74
|
-
|
|
75
|
-
# For now, just inform user
|
|
76
|
-
exit 0
|
|
77
|
-
fi
|
|
78
|
-
done
|
|
79
|
-
|
|
80
|
-
# Continue with original command
|
|
81
|
-
exit 0
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Claude Thinking Transformer Plugin
|
|
3
|
-
* Priority: 16 (runs after Request Sanitizer at 15, before header injection at 20)
|
|
4
|
-
*
|
|
5
|
-
* Transforms thinking parameters for Claude models that require the new adaptive
|
|
6
|
-
* thinking API (e.g. claude-opus-4-7).
|
|
7
|
-
*
|
|
8
|
-
* Problem: Claude Code sends `thinking: { type: "enabled", budget_tokens: N }`
|
|
9
|
-
* for Opus models. claude-opus-4-7 rejects this with HTTP 400:
|
|
10
|
-
* "thinking.type.enabled" is not supported for this model. Use
|
|
11
|
-
* "thinking.type.adaptive" and "output_config.effort" instead.
|
|
12
|
-
*
|
|
13
|
-
* Fix: When the request model matches a Claude 4.7+ pattern:
|
|
14
|
-
* - "enabled" → thinking: { type: "adaptive" } + output_config.effort (derived
|
|
15
|
-
* from budget_tokens; only written if not already present)
|
|
16
|
-
* - "disabled" → delete the thinking field entirely (model does not accept this value)
|
|
17
|
-
*
|
|
18
|
-
* Scope: Only enabled for codemie-claude agent (Claude Code via SSO proxy).
|
|
19
|
-
*
|
|
20
|
-
* To add support for a new model: append a pattern to ADAPTIVE_THINKING_MODEL_PATTERNS.
|
|
21
|
-
*/
|
|
22
|
-
import { ProxyPlugin, PluginContext, ProxyInterceptor } from './types.js';
|
|
23
|
-
export declare class ClaudeThinkingTransformerPlugin implements ProxyPlugin {
|
|
24
|
-
id: string;
|
|
25
|
-
name: string;
|
|
26
|
-
version: string;
|
|
27
|
-
priority: number;
|
|
28
|
-
createInterceptor(context: PluginContext): Promise<ProxyInterceptor>;
|
|
29
|
-
}
|
|
30
|
-
//# sourceMappingURL=claude-thinking-transformer.plugin.d.ts.map
|
package/dist/providers/plugins/sso/proxy/plugins/claude-thinking-transformer.plugin.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"claude-thinking-transformer.plugin.d.ts","sourceRoot":"","sources":["../../../../../../src/providers/plugins/sso/proxy/plugins/claude-thinking-transformer.plugin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAiC1E,qBAAa,+BAAgC,YAAW,WAAW;IACjE,EAAE,SAAgD;IAClD,IAAI,SAAiC;IACrC,OAAO,SAAW;IAClB,QAAQ,SAAM;IAER,iBAAiB,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,gBAAgB,CAAC;CAS3E"}
|
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Claude Thinking Transformer Plugin
|
|
3
|
-
* Priority: 16 (runs after Request Sanitizer at 15, before header injection at 20)
|
|
4
|
-
*
|
|
5
|
-
* Transforms thinking parameters for Claude models that require the new adaptive
|
|
6
|
-
* thinking API (e.g. claude-opus-4-7).
|
|
7
|
-
*
|
|
8
|
-
* Problem: Claude Code sends `thinking: { type: "enabled", budget_tokens: N }`
|
|
9
|
-
* for Opus models. claude-opus-4-7 rejects this with HTTP 400:
|
|
10
|
-
* "thinking.type.enabled" is not supported for this model. Use
|
|
11
|
-
* "thinking.type.adaptive" and "output_config.effort" instead.
|
|
12
|
-
*
|
|
13
|
-
* Fix: When the request model matches a Claude 4.7+ pattern:
|
|
14
|
-
* - "enabled" → thinking: { type: "adaptive" } + output_config.effort (derived
|
|
15
|
-
* from budget_tokens; only written if not already present)
|
|
16
|
-
* - "disabled" → delete the thinking field entirely (model does not accept this value)
|
|
17
|
-
*
|
|
18
|
-
* Scope: Only enabled for codemie-claude agent (Claude Code via SSO proxy).
|
|
19
|
-
*
|
|
20
|
-
* To add support for a new model: append a pattern to ADAPTIVE_THINKING_MODEL_PATTERNS.
|
|
21
|
-
*/
|
|
22
|
-
import { logger } from '../../../../../utils/logger.js';
|
|
23
|
-
/**
|
|
24
|
-
* Model name patterns that require the adaptive thinking API.
|
|
25
|
-
* Matches claude-opus-4-7, claude-opus-4-7-20250514, and future date-tagged variants.
|
|
26
|
-
* Extend this list as Anthropic migrates additional models — see EPMCDME-11821.
|
|
27
|
-
*/
|
|
28
|
-
const ADAPTIVE_THINKING_MODEL_PATTERNS = [
|
|
29
|
-
/claude-opus-4-[7-9](?:[^0-9]|$)/i, // claude-opus-4-7/8/9 and date-tagged variants (e.g. claude-opus-4-7-20250514); excludes claude-opus-4-70+
|
|
30
|
-
];
|
|
31
|
-
function modelRequiresAdaptiveThinking(modelName) {
|
|
32
|
-
return ADAPTIVE_THINKING_MODEL_PATTERNS.some(p => p.test(modelName));
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* Map legacy budget_tokens to the closest output_config.effort level.
|
|
36
|
-
*
|
|
37
|
-
* budget_tokens was the maximum token budget for thinking in the old API.
|
|
38
|
-
* effort is a coarser control in the new API: low / medium / high.
|
|
39
|
-
*/
|
|
40
|
-
function budgetTokensToEffort(budgetTokens) {
|
|
41
|
-
const tokens = typeof budgetTokens === 'number' ? budgetTokens : 0;
|
|
42
|
-
if (tokens <= 2048)
|
|
43
|
-
return 'low';
|
|
44
|
-
if (tokens <= 8192)
|
|
45
|
-
return 'medium';
|
|
46
|
-
return 'high';
|
|
47
|
-
}
|
|
48
|
-
/** Agent that sends Claude API requests through the codemie proxy */
|
|
49
|
-
const ALLOWED_AGENT = 'codemie-claude';
|
|
50
|
-
export class ClaudeThinkingTransformerPlugin {
|
|
51
|
-
id = '@codemie/proxy-claude-thinking-transformer';
|
|
52
|
-
name = 'Claude Thinking Transformer';
|
|
53
|
-
version = '1.0.0';
|
|
54
|
-
priority = 16; // After RequestSanitizer (15), before HeaderInjection (20)
|
|
55
|
-
async createInterceptor(context) {
|
|
56
|
-
const clientType = context.config.clientType;
|
|
57
|
-
if (!clientType || clientType !== ALLOWED_AGENT) {
|
|
58
|
-
throw new Error(`Plugin disabled for agent: ${clientType}`);
|
|
59
|
-
}
|
|
60
|
-
// Pass the configured model as a fallback for requests that omit body.model
|
|
61
|
-
const configModel = context.config.model;
|
|
62
|
-
return new ClaudeThinkingTransformerInterceptor(configModel);
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
class ClaudeThinkingTransformerInterceptor {
|
|
66
|
-
configModel;
|
|
67
|
-
name = 'claude-thinking-transformer';
|
|
68
|
-
constructor(configModel) {
|
|
69
|
-
this.configModel = configModel;
|
|
70
|
-
}
|
|
71
|
-
async onRequest(context) {
|
|
72
|
-
if (!context.requestBody || !context.headers['content-type']?.includes('application/json')) {
|
|
73
|
-
return;
|
|
74
|
-
}
|
|
75
|
-
try {
|
|
76
|
-
const bodyStr = context.requestBody.toString('utf-8');
|
|
77
|
-
const body = JSON.parse(bodyStr);
|
|
78
|
-
const thinkingType = body.thinking?.type;
|
|
79
|
-
if (thinkingType !== 'enabled' && thinkingType !== 'disabled') {
|
|
80
|
-
return;
|
|
81
|
-
}
|
|
82
|
-
// Resolve model: prefer request body, fall back to proxy config
|
|
83
|
-
const model = (typeof body.model === 'string' && body.model) || this.configModel || '';
|
|
84
|
-
if (!model || !modelRequiresAdaptiveThinking(model)) {
|
|
85
|
-
return;
|
|
86
|
-
}
|
|
87
|
-
if (thinkingType === 'enabled') {
|
|
88
|
-
const effort = budgetTokensToEffort(body.thinking.budget_tokens);
|
|
89
|
-
// Replace old thinking object with new adaptive format
|
|
90
|
-
body.thinking = { type: 'adaptive' };
|
|
91
|
-
// Set output_config.effort only if the caller hasn't already specified it
|
|
92
|
-
if (!body.output_config?.effort) {
|
|
93
|
-
body.output_config = { ...(body.output_config ?? {}), effort };
|
|
94
|
-
}
|
|
95
|
-
logger.debug(`[${this.name}] Transformed thinking: "enabled" → "adaptive", effort="${effort}" for model: ${model}`);
|
|
96
|
-
}
|
|
97
|
-
else {
|
|
98
|
-
// thinking.type === 'disabled': model does not accept this value — remove the field
|
|
99
|
-
delete body.thinking;
|
|
100
|
-
logger.debug(`[${this.name}] Removed unsupported thinking.type="disabled" for model: ${model}`);
|
|
101
|
-
}
|
|
102
|
-
const newBodyStr = JSON.stringify(body);
|
|
103
|
-
context.requestBody = Buffer.from(newBodyStr, 'utf-8');
|
|
104
|
-
context.headers['content-length'] = String(context.requestBody.length);
|
|
105
|
-
}
|
|
106
|
-
catch {
|
|
107
|
-
// Not valid JSON or unexpected structure — pass through unchanged
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
//# sourceMappingURL=claude-thinking-transformer.plugin.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"claude-thinking-transformer.plugin.js","sourceRoot":"","sources":["../../../../../../src/providers/plugins/sso/proxy/plugins/claude-thinking-transformer.plugin.ts"],"names":[],"mappings":"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"}
|