@kubbisec/ai-linux-x64 0.1.22 → 0.1.23
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/bin/kubbisec +0 -0
- package/bundled/components/kubbisec-model-selector.d.ts +47 -34
- package/bundled/components/kubbisec-model-selector.js +187 -177
- package/bundled/config/config.d.ts +6 -6
- package/bundled/config/config.js +54 -52
- package/bundled/config/detect-local-llm-providers.d.ts +26 -16
- package/bundled/config/detect-local-llm-providers.js +130 -142
- package/bundled/config/ensure-kbs-project-settings.d.ts +8 -8
- package/bundled/config/ensure-kbs-project-settings.js +27 -28
- package/bundled/config/ensure-kubbisec-project-settings.d.ts +9 -9
- package/bundled/config/ensure-kubbisec-project-settings.js +62 -67
- package/bundled/config/extended-context.d.ts +5 -6
- package/bundled/config/extended-context.js +23 -22
- package/bundled/config/feature-flags.d.ts +10 -2
- package/bundled/config/feature-flags.js +8 -2
- package/bundled/config/format-kubbisec-footer-status.d.ts +1 -1
- package/bundled/config/format-kubbisec-footer-status.js +26 -31
- package/bundled/config/kubbisec-extension-manifest.d.ts +21 -2
- package/bundled/config/kubbisec-extension-manifest.js +19 -19
- package/bundled/config/llm-config-mutations.d.ts +51 -25
- package/bundled/config/llm-config-mutations.js +173 -182
- package/bundled/config/llm-config.d.ts +54 -41
- package/bundled/config/llm-config.js +199 -199
- package/bundled/config/llm-provider-catalog.d.ts +18 -15
- package/bundled/config/llm-provider-catalog.js +45 -46
- package/bundled/config/materialize-kubbisec-pi-resources.d.ts +1 -1
- package/bundled/config/materialize-kubbisec-pi-resources.js +173 -182
- package/bundled/config/register-custom-llm-providers.d.ts +11 -5
- package/bundled/config/register-custom-llm-providers.js +17 -15
- package/bundled/config/register-kubbisec-llm-provider.d.ts +14 -10
- package/bundled/config/register-kubbisec-llm-provider.js +50 -42
- package/bundled/config/resolve-agents-context-file.d.ts +1 -1
- package/bundled/config/resolve-agents-context-file.js +33 -34
- package/bundled/config/resource-budget.d.ts +12 -12
- package/bundled/config/resource-budget.js +28 -28
- package/bundled/config/sync-kubbisec-pi-models.d.ts +6 -3
- package/bundled/config/sync-kubbisec-pi-models.js +58 -58
- package/bundled/copy/cli-reference-index.d.ts +1 -1
- package/bundled/copy/cli-reference-index.js +1 -1
- package/bundled/copy/kubbisec-shell-copy.d.ts +11 -6
- package/bundled/copy/kubbisec-shell-copy.js +1 -1
- package/bundled/extensions/cli-local-shared.d.ts +56 -32
- package/bundled/extensions/cli-local-shared.js +135 -125
- package/bundled/extensions/kubbisec-aspm-local.extension.d.ts +18 -15
- package/bundled/extensions/kubbisec-aspm-local.extension.js +109 -106
- package/bundled/extensions/kubbisec-brand.extension.d.ts +1 -1
- package/bundled/extensions/kubbisec-brand.extension.js +25 -25
- package/bundled/extensions/kubbisec-byok-provider.extension.d.ts +1 -1
- package/bundled/extensions/kubbisec-byok-provider.extension.js +2 -2
- package/bundled/extensions/kubbisec-clarify.extension.d.ts +64 -35
- package/bundled/extensions/kubbisec-clarify.extension.js +323 -305
- package/bundled/extensions/kubbisec-exit.extension.d.ts +1 -1
- package/bundled/extensions/kubbisec-exit.extension.js +29 -32
- package/bundled/extensions/kubbisec-extended-context.extension.d.ts +1 -1
- package/bundled/extensions/kubbisec-extended-context.extension.js +56 -43
- package/bundled/extensions/kubbisec-footer.extension.d.ts +14 -14
- package/bundled/extensions/kubbisec-footer.extension.js +205 -215
- package/bundled/extensions/kubbisec-github-local.extension.d.ts +26 -18
- package/bundled/extensions/kubbisec-github-local.extension.js +430 -417
- package/bundled/extensions/kubbisec-llm-config.extension.d.ts +1 -1
- package/bundled/extensions/kubbisec-llm-config.extension.js +200 -181
- package/bundled/extensions/kubbisec-memory.extension.d.ts +9 -7
- package/bundled/extensions/kubbisec-memory.extension.js +88 -95
- package/bundled/extensions/kubbisec-naus-local.extension.d.ts +18 -15
- package/bundled/extensions/kubbisec-naus-local.extension.js +123 -103
- package/bundled/extensions/kubbisec-platform-tools.extension.d.ts +31 -21
- package/bundled/extensions/kubbisec-platform-tools.extension.js +152 -152
- package/bundled/extensions/kubbisec-runtime-status.extension.d.ts +10 -8
- package/bundled/extensions/kubbisec-runtime-status.extension.js +15 -13
- package/bundled/extensions/kubbisec-scope.extension.d.ts +12 -7
- package/bundled/extensions/kubbisec-scope.extension.js +13 -13
- package/bundled/extensions/kubbisec-skill-mentions.extension.d.ts +27 -16
- package/bundled/extensions/kubbisec-skill-mentions.extension.js +74 -64
- package/bundled/extensions/kubbisec-skill-telemetry.extension.d.ts +2 -3
- package/bundled/extensions/kubbisec-skill-telemetry.extension.js +59 -64
- package/bundled/extensions/kubbisec-theme-lock.extension.d.ts +1 -1
- package/bundled/extensions/kubbisec-theme-lock.extension.js +33 -34
- package/bundled/extensions/kubbisec-ui.extension.d.ts +1 -1
- package/bundled/extensions/kubbisec-ui.extension.js +90 -92
- package/bundled/extensions/kubbisec-workflow.extension.d.ts +20 -18
- package/bundled/extensions/kubbisec-workflow.extension.js +138 -140
- package/bundled/resolve-bundled-dist-root.js +121 -130
- package/bundled/skills/at-path-mentions.d.ts +1 -1
- package/bundled/skills/at-path-mentions.js +146 -153
- package/bundled/skills/chat-mention-render.d.ts +2 -2
- package/bundled/skills/chat-mention-render.js +121 -126
- package/bundled/skills/chat-mentions.d.ts +17 -8
- package/bundled/skills/chat-mentions.js +76 -76
- package/bundled/skills/list-bundled-skills.d.ts +3 -3
- package/bundled/skills/list-bundled-skills.js +33 -35
- package/bundled/skills/skill-mention.d.ts +10 -2
- package/bundled/skills/skill-mention.js +10 -2
- package/bundled/theme/clear-terminal.d.ts +1 -1
- package/bundled/theme/clear-terminal.js +3 -4
- package/bundled/theme/footer-render-hook.d.ts +1 -1
- package/bundled/theme/footer-render-hook.js +3 -3
- package/bundled/theme/kubbisec-brand-fg.d.ts +1 -1
- package/bundled/theme/kubbisec-brand-fg.js +2 -2
- package/bundled/theme/kubbisec-menu-themes.d.ts +7 -7
- package/bundled/theme/kubbisec-menu-themes.js +30 -31
- package/bundled/theme/kubbisec-theme-name.d.ts +1 -1
- package/bundled/theme/kubbisec-theme-name.js +1 -1
- package/bundled/theme/patch-pi-settings-theme.runtime.d.ts +1 -1
- package/bundled/theme/patch-pi-settings-theme.runtime.js +11 -10
- package/bundled/theme/render-compact-header.d.ts +13 -5
- package/bundled/theme/render-compact-header.js +126 -128
- package/bundled/workflow/session-workflow-mode.d.ts +1 -1
- package/bundled/workflow/session-workflow-mode.js +33 -33
- package/package.json +1 -1
|
@@ -3,468 +3,481 @@ import * as fs from "node:fs";
|
|
|
3
3
|
import * as path from "node:path";
|
|
4
4
|
import { summarizeSubprocessFailure, toUserError } from "@aspm/shared/cli-user-error";
|
|
5
5
|
import { Type } from "@earendil-works/pi-ai";
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
buildAuthenticatedGitRemoteUrl,
|
|
8
|
+
buildGitGhSubprocessEnv,
|
|
9
|
+
resolveHostGitAuth,
|
|
10
|
+
} from "@kubbisec/remediation";
|
|
7
11
|
import { resolveExtendedWorkspace } from "../config/extended-context.js";
|
|
8
12
|
import { resolvePathInWorkspace } from "./cli-local-shared.js";
|
|
13
|
+
|
|
9
14
|
function resolveWorkspace() {
|
|
10
|
-
|
|
15
|
+
return resolveExtendedWorkspace();
|
|
11
16
|
}
|
|
12
17
|
function resolveWorkspacePath() {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}
|
|
18
|
+
const candidates = [
|
|
19
|
+
process.env.KUBBISEC_LOCAL_WORKSPACE,
|
|
20
|
+
process.env.KUBBISEC_AI_WORKSPACE,
|
|
21
|
+
].filter((value) => typeof value === "string" && value.trim().length > 0);
|
|
22
|
+
for (const candidate of candidates) {
|
|
23
|
+
const segments = candidate.split(/[\\/]+/).filter(Boolean);
|
|
24
|
+
if (segments.includes("..")) {
|
|
25
|
+
throw new Error("workspace path traversal is not allowed");
|
|
22
26
|
}
|
|
23
|
-
|
|
27
|
+
}
|
|
28
|
+
return resolveWorkspace();
|
|
24
29
|
}
|
|
25
30
|
function execCapture(bin, args, cwd, options) {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
});
|
|
41
|
-
child.stderr?.on("data", (c) => {
|
|
42
|
-
stderr += String(c);
|
|
43
|
-
});
|
|
44
|
-
child.on("error", (err) => {
|
|
45
|
-
resolve({ code: 127, stdout: "", stderr: toUserError(err).detail });
|
|
46
|
-
});
|
|
47
|
-
child.on("close", (code) => resolve({ code: code ?? 1, stdout, stderr }));
|
|
31
|
+
return new Promise((resolve) => {
|
|
32
|
+
const child = spawn(bin, args, {
|
|
33
|
+
cwd,
|
|
34
|
+
env: options?.env ?? {
|
|
35
|
+
...process.env,
|
|
36
|
+
GIT_TERMINAL_PROMPT: "0",
|
|
37
|
+
GH_PROMPT_DISABLED: "1",
|
|
38
|
+
},
|
|
39
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
40
|
+
});
|
|
41
|
+
let stdout = "";
|
|
42
|
+
let stderr = "";
|
|
43
|
+
child.stdout?.on("data", (c) => {
|
|
44
|
+
stdout += String(c);
|
|
48
45
|
});
|
|
46
|
+
child.stderr?.on("data", (c) => {
|
|
47
|
+
stderr += String(c);
|
|
48
|
+
});
|
|
49
|
+
child.on("error", (err) => {
|
|
50
|
+
resolve({ code: 127, stdout: "", stderr: toUserError(err).detail });
|
|
51
|
+
});
|
|
52
|
+
child.on("close", (code) => resolve({ code: code ?? 1, stdout, stderr }));
|
|
53
|
+
});
|
|
49
54
|
}
|
|
50
55
|
function redactGithubSecrets(text) {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
56
|
+
return text
|
|
57
|
+
.replace(/https:\/\/([^/\s:@]+):([^@\s]+)@/gi, (_match, user) => `https://${String(user)}:***@`)
|
|
58
|
+
.replace(/\b(gh[pousr]_[A-Za-z0-9_]+)\b/g, "***");
|
|
54
59
|
}
|
|
55
60
|
function formatGitSummary(bin, label, result) {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
61
|
+
const stdout = redactGithubSecrets(result.stdout.trim());
|
|
62
|
+
const stderr = redactGithubSecrets(result.stderr.trim());
|
|
63
|
+
if (result.code === 0 && stdout) {
|
|
64
|
+
return `${label}:\n${stdout}`;
|
|
65
|
+
}
|
|
66
|
+
if (result.code === 0) {
|
|
67
|
+
return `${label}: (sem saída)`;
|
|
68
|
+
}
|
|
69
|
+
return summarizeSubprocessFailure({
|
|
70
|
+
bin,
|
|
71
|
+
code: result.code,
|
|
72
|
+
stderr,
|
|
73
|
+
stdout,
|
|
74
|
+
});
|
|
70
75
|
}
|
|
71
76
|
function resolvePlatformToken() {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
77
|
+
const candidate =
|
|
78
|
+
process.env.KUBBISEC_GIT_TOKEN?.trim() ||
|
|
79
|
+
process.env.GITHUB_TOKEN?.trim() ||
|
|
80
|
+
process.env.GH_TOKEN?.trim();
|
|
81
|
+
return candidate || null;
|
|
76
82
|
}
|
|
77
83
|
function buildTextResult(text) {
|
|
78
|
-
|
|
84
|
+
return { content: [{ type: "text", text }] };
|
|
79
85
|
}
|
|
80
86
|
function buildErrorResult(error) {
|
|
81
|
-
|
|
87
|
+
return buildTextResult(toUserError(error, "Falha ao executar github local").detail);
|
|
82
88
|
}
|
|
83
89
|
function isGitWorkspace(cwd) {
|
|
84
|
-
|
|
90
|
+
return fs.existsSync(path.join(cwd, ".git"));
|
|
85
91
|
}
|
|
86
92
|
async function resolveRemoteUrl(cwd) {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
return null;
|
|
92
|
-
return remoteUrlResult.stdout.trim() || null;
|
|
93
|
+
if (!isGitWorkspace(cwd)) return null;
|
|
94
|
+
const remoteUrlResult = await execCapture("git", ["remote", "get-url", "origin"], cwd);
|
|
95
|
+
if (remoteUrlResult.code !== 0) return null;
|
|
96
|
+
return remoteUrlResult.stdout.trim() || null;
|
|
93
97
|
}
|
|
94
98
|
async function resolveWorkspaceAuth(cwd) {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
99
|
+
const remoteUrl = await resolveRemoteUrl(cwd);
|
|
100
|
+
const platformToken = resolvePlatformToken();
|
|
101
|
+
const auth = await resolveHostGitAuth({
|
|
102
|
+
cwd,
|
|
103
|
+
remoteUrl,
|
|
104
|
+
platformToken,
|
|
105
|
+
});
|
|
106
|
+
const env = buildGitGhSubprocessEnv(auth, process.env);
|
|
107
|
+
return { auth, env, remoteUrl, platformToken };
|
|
104
108
|
}
|
|
105
109
|
function requireGitWorkspace(cwd) {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
110
|
+
if (isGitWorkspace(cwd)) {
|
|
111
|
+
return { ok: true };
|
|
112
|
+
}
|
|
113
|
+
return {
|
|
114
|
+
ok: false,
|
|
115
|
+
result: buildTextResult(
|
|
116
|
+
"git: no .git in workspace (clone via kubsec_github_repository + remediation flow)",
|
|
117
|
+
),
|
|
118
|
+
};
|
|
113
119
|
}
|
|
114
120
|
async function runAuthenticatedCommand(bin, args, cwd) {
|
|
115
|
-
|
|
116
|
-
|
|
121
|
+
const { env } = await resolveWorkspaceAuth(cwd);
|
|
122
|
+
return execCapture(bin, args, cwd, { env });
|
|
117
123
|
}
|
|
118
124
|
function isGitAuthFailure(stderr, stdout) {
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
+
const detail = `${stderr}\n${stdout}`.toLowerCase();
|
|
126
|
+
return (
|
|
127
|
+
detail.includes("invalid credentials") ||
|
|
128
|
+
detail.includes("authentication failed") ||
|
|
129
|
+
detail.includes("403") ||
|
|
130
|
+
detail.includes("401") ||
|
|
131
|
+
detail.includes("unauthorized")
|
|
132
|
+
);
|
|
125
133
|
}
|
|
126
134
|
function buildRetryAuth(platformToken) {
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
135
|
+
return {
|
|
136
|
+
source: "platform-token",
|
|
137
|
+
mode: "embedded-token",
|
|
138
|
+
token: platformToken,
|
|
139
|
+
detail: "retry after native auth failure",
|
|
140
|
+
};
|
|
133
141
|
}
|
|
134
142
|
async function prepareRemoteForAuth(cwd, remoteUrl, auth) {
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
return env;
|
|
138
|
-
}
|
|
139
|
-
const nextRemoteUrl = auth.mode === "embedded-token"
|
|
140
|
-
? buildAuthenticatedGitRemoteUrl(remoteUrl, auth.token)
|
|
141
|
-
: remoteUrl;
|
|
142
|
-
const setUrl = await execCapture("git", ["remote", "set-url", "origin", nextRemoteUrl], cwd, {
|
|
143
|
-
env,
|
|
144
|
-
});
|
|
145
|
-
if (setUrl.code !== 0) {
|
|
146
|
-
throw new Error(formatGitSummary("git", "git remote set-url", setUrl));
|
|
147
|
-
}
|
|
143
|
+
const env = buildGitGhSubprocessEnv(auth, process.env);
|
|
144
|
+
if (!remoteUrl) {
|
|
148
145
|
return env;
|
|
146
|
+
}
|
|
147
|
+
const nextRemoteUrl =
|
|
148
|
+
auth.mode === "embedded-token"
|
|
149
|
+
? buildAuthenticatedGitRemoteUrl(remoteUrl, auth.token)
|
|
150
|
+
: remoteUrl;
|
|
151
|
+
const setUrl = await execCapture("git", ["remote", "set-url", "origin", nextRemoteUrl], cwd, {
|
|
152
|
+
env,
|
|
153
|
+
});
|
|
154
|
+
if (setUrl.code !== 0) {
|
|
155
|
+
throw new Error(formatGitSummary("git", "git remote set-url", setUrl));
|
|
156
|
+
}
|
|
157
|
+
return env;
|
|
149
158
|
}
|
|
150
159
|
function normalizeCloneRemote(params) {
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
+
const remoteUrl = typeof params.remoteUrl === "string" ? params.remoteUrl.trim() : "";
|
|
161
|
+
if (remoteUrl) {
|
|
162
|
+
return remoteUrl;
|
|
163
|
+
}
|
|
164
|
+
const repo = typeof params.repo === "string" ? params.repo.trim().replace(/^\/+|\/+$/g, "") : "";
|
|
165
|
+
if (!repo) {
|
|
166
|
+
return null;
|
|
167
|
+
}
|
|
168
|
+
return `https://github.com/${repo.endsWith(".git") ? repo : `${repo}.git`}`;
|
|
160
169
|
}
|
|
161
170
|
function inferCloneDirectory(params, remoteUrl) {
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
?.replace(/\.git$/i, "") || "repo");
|
|
173
|
-
}
|
|
174
|
-
const normalized = remoteUrl.replace(/[\\/]+$/, "");
|
|
175
|
-
const basename = normalized
|
|
176
|
-
.split(/[/:]/)
|
|
171
|
+
const explicit = typeof params.directory === "string" ? params.directory.trim() : "";
|
|
172
|
+
if (explicit) {
|
|
173
|
+
return explicit;
|
|
174
|
+
}
|
|
175
|
+
const repo = typeof params.repo === "string" ? params.repo.trim() : "";
|
|
176
|
+
if (repo) {
|
|
177
|
+
return (
|
|
178
|
+
repo
|
|
179
|
+
.split("/")
|
|
180
|
+
.filter(Boolean)
|
|
177
181
|
.pop()
|
|
178
|
-
?.replace(/\.git$/i, "")
|
|
179
|
-
|
|
182
|
+
?.replace(/\.git$/i, "") || "repo"
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
const normalized = remoteUrl.replace(/[\\/]+$/, "");
|
|
186
|
+
const basename = normalized
|
|
187
|
+
.split(/[/:]/)
|
|
188
|
+
.pop()
|
|
189
|
+
?.replace(/\.git$/i, "");
|
|
190
|
+
return basename || "repo";
|
|
180
191
|
}
|
|
181
192
|
async function sanitizeClonedRemote(cwd, remoteUrl, auth) {
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
193
|
+
if (auth.mode !== "embedded-token") {
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
const sanitizedEnv = buildGitGhSubprocessEnv(auth, process.env);
|
|
197
|
+
const sanitized = await execCapture("git", ["remote", "set-url", "origin", remoteUrl], cwd, {
|
|
198
|
+
env: sanitizedEnv,
|
|
199
|
+
});
|
|
200
|
+
if (sanitized.code !== 0) {
|
|
201
|
+
throw new Error(formatGitSummary("git", "git remote set-url", sanitized));
|
|
202
|
+
}
|
|
192
203
|
}
|
|
193
204
|
async function resolveCurrentBranch(cwd) {
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
205
|
+
const branch = await execCapture("git", ["branch", "--show-current"], cwd);
|
|
206
|
+
const branchName = branch.stdout.trim();
|
|
207
|
+
return branch.code === 0 && branchName ? branchName : null;
|
|
197
208
|
}
|
|
198
209
|
export default function kubbisecGithubLocal(api) {
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
210
|
+
api.registerTool({
|
|
211
|
+
name: "github_local_status",
|
|
212
|
+
label: "GitHub local status",
|
|
213
|
+
description: "Reports host GitHub auth and git remote details for this machine.",
|
|
214
|
+
parameters: Type.Object({}),
|
|
215
|
+
async execute() {
|
|
216
|
+
try {
|
|
217
|
+
const cwd = resolveWorkspacePath();
|
|
218
|
+
const parts = [`workspace: ${cwd}`];
|
|
219
|
+
const hasGit = isGitWorkspace(cwd);
|
|
220
|
+
const remoteUrl = await resolveRemoteUrl(cwd);
|
|
221
|
+
const auth = await resolveHostGitAuth({
|
|
222
|
+
cwd,
|
|
223
|
+
remoteUrl,
|
|
224
|
+
platformToken: resolvePlatformToken(),
|
|
225
|
+
});
|
|
226
|
+
parts.push(`auth source: ${auth.source}`);
|
|
227
|
+
parts.push(`auth detail: ${auth.detail}`);
|
|
228
|
+
if (hasGit) {
|
|
229
|
+
const remote = await execCapture("git", ["remote", "-v"], cwd);
|
|
230
|
+
const branch = await execCapture("git", ["branch", "--show-current"], cwd);
|
|
231
|
+
parts.push(formatGitSummary("git", "git remote", remote));
|
|
232
|
+
const branchName = branch.stdout.trim();
|
|
233
|
+
parts.push(
|
|
234
|
+
`git branch: ${branchName || (branch.code === 0 ? "(detached)" : "indisponível")}`,
|
|
235
|
+
);
|
|
236
|
+
} else {
|
|
237
|
+
parts.push(
|
|
238
|
+
"git: no .git in workspace (clone via kubsec_github_repository + remediation flow)",
|
|
239
|
+
);
|
|
240
|
+
}
|
|
241
|
+
return buildTextResult(parts.join("\n\n"));
|
|
242
|
+
} catch (error) {
|
|
243
|
+
return buildErrorResult(error);
|
|
244
|
+
}
|
|
245
|
+
},
|
|
246
|
+
});
|
|
247
|
+
api.registerTool({
|
|
248
|
+
name: "github_local_repo_summary",
|
|
249
|
+
label: "GitHub local repo summary",
|
|
250
|
+
description: "Lists top-level files and recent git log in the workspace.",
|
|
251
|
+
parameters: Type.Object({}),
|
|
252
|
+
async execute() {
|
|
253
|
+
try {
|
|
254
|
+
const cwd = resolveWorkspacePath();
|
|
255
|
+
const entries = fs.existsSync(cwd)
|
|
256
|
+
? fs
|
|
257
|
+
.readdirSync(cwd, { withFileTypes: true })
|
|
258
|
+
.slice(0, 40)
|
|
259
|
+
.map((e) => (e.isDirectory() ? `${e.name}/` : e.name))
|
|
260
|
+
: [];
|
|
261
|
+
let logOut = "";
|
|
262
|
+
if (isGitWorkspace(cwd)) {
|
|
263
|
+
const log = await execCapture("git", ["log", "-5", "--oneline"], cwd);
|
|
264
|
+
if (log.code === 0 && log.stdout.trim()) {
|
|
265
|
+
logOut = redactGithubSecrets(log.stdout.trim());
|
|
266
|
+
} else if (log.code !== 0) {
|
|
267
|
+
logOut = summarizeSubprocessFailure({
|
|
268
|
+
bin: "git",
|
|
269
|
+
code: log.code,
|
|
270
|
+
stderr: redactGithubSecrets(log.stderr),
|
|
271
|
+
stdout: redactGithubSecrets(log.stdout),
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
const text = [
|
|
276
|
+
`workspace: ${cwd}`,
|
|
277
|
+
`entries: ${entries.join(", ") || "(empty)"}`,
|
|
278
|
+
logOut ? `recent commits:\n${logOut}` : "no git history",
|
|
279
|
+
].join("\n\n");
|
|
280
|
+
return buildTextResult(text);
|
|
281
|
+
} catch (error) {
|
|
282
|
+
return buildErrorResult(error);
|
|
283
|
+
}
|
|
284
|
+
},
|
|
285
|
+
});
|
|
286
|
+
api.registerTool({
|
|
287
|
+
name: "github_local_clone",
|
|
288
|
+
label: "GitHub local clone",
|
|
289
|
+
description: "Clones a repository into a workspace-safe local directory.",
|
|
290
|
+
parameters: Type.Object({
|
|
291
|
+
remoteUrl: Type.Optional(Type.String({ description: "Full Git remote URL." })),
|
|
292
|
+
repo: Type.Optional(Type.String({ description: "GitHub repo in owner/name format." })),
|
|
293
|
+
directory: Type.Optional(
|
|
294
|
+
Type.String({ description: "Optional target directory inside the workspace." }),
|
|
295
|
+
),
|
|
296
|
+
branch: Type.Optional(Type.String({ description: "Optional branch to clone." })),
|
|
297
|
+
}),
|
|
298
|
+
async execute(_toolCallId, params) {
|
|
299
|
+
try {
|
|
300
|
+
const cwd = resolveWorkspacePath();
|
|
301
|
+
const remoteUrl = normalizeCloneRemote(params);
|
|
302
|
+
if (!remoteUrl) {
|
|
303
|
+
return buildTextResult("remoteUrl or repo is required");
|
|
304
|
+
}
|
|
305
|
+
const targetDir = resolvePathInWorkspace(inferCloneDirectory(params, remoteUrl), cwd);
|
|
306
|
+
if (path.resolve(targetDir) === path.resolve(cwd)) {
|
|
307
|
+
return buildTextResult("clone target must be a child path inside the workspace");
|
|
308
|
+
}
|
|
309
|
+
const branch = typeof params.branch === "string" ? params.branch.trim() : "";
|
|
310
|
+
const platformToken = resolvePlatformToken();
|
|
311
|
+
let auth = await resolveHostGitAuth({
|
|
312
|
+
cwd,
|
|
313
|
+
remoteUrl,
|
|
314
|
+
platformToken,
|
|
315
|
+
});
|
|
316
|
+
const buildCloneArgs = (currentAuth) => {
|
|
317
|
+
const cloneRemoteUrl =
|
|
318
|
+
currentAuth.mode === "embedded-token"
|
|
319
|
+
? buildAuthenticatedGitRemoteUrl(remoteUrl, currentAuth.token)
|
|
320
|
+
: remoteUrl;
|
|
321
|
+
const args = ["clone"];
|
|
322
|
+
if (branch) {
|
|
323
|
+
args.push("--branch", branch);
|
|
324
|
+
}
|
|
325
|
+
args.push(cloneRemoteUrl, targetDir);
|
|
326
|
+
return { args, cloneRemoteUrl };
|
|
327
|
+
};
|
|
328
|
+
const runClone = async (currentAuth) => {
|
|
329
|
+
const { args, cloneRemoteUrl } = buildCloneArgs(currentAuth);
|
|
330
|
+
const env = buildGitGhSubprocessEnv(currentAuth, process.env);
|
|
331
|
+
const result = await execCapture("git", args, cwd, { env });
|
|
332
|
+
return { result, cloneRemoteUrl };
|
|
333
|
+
};
|
|
334
|
+
let clone = await runClone(auth);
|
|
335
|
+
if (
|
|
336
|
+
clone.result.code !== 0 &&
|
|
337
|
+
auth.mode === "native" &&
|
|
338
|
+
platformToken &&
|
|
339
|
+
isGitAuthFailure(clone.result.stderr, clone.result.stdout)
|
|
340
|
+
) {
|
|
341
|
+
fs.rmSync(targetDir, { recursive: true, force: true });
|
|
342
|
+
auth = buildRetryAuth(platformToken);
|
|
343
|
+
clone = await runClone(auth);
|
|
344
|
+
}
|
|
345
|
+
if (clone.result.code === 0) {
|
|
346
|
+
await sanitizeClonedRemote(targetDir, remoteUrl, auth);
|
|
347
|
+
}
|
|
348
|
+
const relativeTarget = path.relative(cwd, targetDir) || ".";
|
|
349
|
+
return buildTextResult(
|
|
350
|
+
`${formatGitSummary("git", "git clone", clone.result)}\n\ntarget: ${relativeTarget}`,
|
|
351
|
+
);
|
|
352
|
+
} catch (error) {
|
|
353
|
+
return buildErrorResult(error);
|
|
354
|
+
}
|
|
355
|
+
},
|
|
356
|
+
});
|
|
357
|
+
api.registerTool({
|
|
358
|
+
name: "github_local_fetch",
|
|
359
|
+
label: "GitHub local fetch",
|
|
360
|
+
description: "Runs `git fetch` in the workspace using host or fallback auth.",
|
|
361
|
+
parameters: Type.Object({}),
|
|
362
|
+
async execute() {
|
|
363
|
+
try {
|
|
364
|
+
const cwd = resolveWorkspacePath();
|
|
365
|
+
const gitWorkspace = requireGitWorkspace(cwd);
|
|
366
|
+
if (!gitWorkspace.ok) return gitWorkspace.result;
|
|
367
|
+
const result = await runAuthenticatedCommand("git", ["fetch"], cwd);
|
|
368
|
+
return buildTextResult(formatGitSummary("git", "git fetch", result));
|
|
369
|
+
} catch (error) {
|
|
370
|
+
return buildErrorResult(error);
|
|
371
|
+
}
|
|
372
|
+
},
|
|
373
|
+
});
|
|
374
|
+
api.registerTool({
|
|
375
|
+
name: "github_local_commit",
|
|
376
|
+
label: "GitHub local commit",
|
|
377
|
+
description: "Stages all changes and creates a git commit in the workspace.",
|
|
378
|
+
parameters: Type.Object({
|
|
379
|
+
message: Type.String({ description: "Commit message passed to `git commit -m`." }),
|
|
380
|
+
}),
|
|
381
|
+
async execute(_toolCallId, params) {
|
|
382
|
+
try {
|
|
383
|
+
const message = String(params.message ?? "").trim();
|
|
384
|
+
if (!message) {
|
|
385
|
+
return buildTextResult("commit message is required");
|
|
386
|
+
}
|
|
387
|
+
const cwd = resolveWorkspacePath();
|
|
388
|
+
const gitWorkspace = requireGitWorkspace(cwd);
|
|
389
|
+
if (!gitWorkspace.ok) return gitWorkspace.result;
|
|
390
|
+
const { env } = await resolveWorkspaceAuth(cwd);
|
|
391
|
+
const addResult = await execCapture("git", ["add", "-A"], cwd, { env });
|
|
392
|
+
if (addResult.code !== 0) {
|
|
393
|
+
return buildTextResult(formatGitSummary("git", "git add", addResult));
|
|
394
|
+
}
|
|
395
|
+
const commitResult = await execCapture("git", ["commit", "-m", message], cwd, { env });
|
|
396
|
+
return buildTextResult(formatGitSummary("git", "git commit", commitResult));
|
|
397
|
+
} catch (error) {
|
|
398
|
+
return buildErrorResult(error);
|
|
399
|
+
}
|
|
400
|
+
},
|
|
401
|
+
});
|
|
402
|
+
api.registerTool({
|
|
403
|
+
name: "github_local_push",
|
|
404
|
+
label: "GitHub local push",
|
|
405
|
+
description: "Pushes the current branch to origin using host or fallback auth.",
|
|
406
|
+
parameters: Type.Object({}),
|
|
407
|
+
async execute() {
|
|
408
|
+
try {
|
|
409
|
+
const cwd = resolveWorkspacePath();
|
|
410
|
+
const gitWorkspace = requireGitWorkspace(cwd);
|
|
411
|
+
if (!gitWorkspace.ok) return gitWorkspace.result;
|
|
412
|
+
const branch = await resolveCurrentBranch(cwd);
|
|
413
|
+
const args = branch ? ["push", "-u", "origin", branch] : ["push"];
|
|
414
|
+
const { auth, remoteUrl, platformToken } = await resolveWorkspaceAuth(cwd);
|
|
415
|
+
const runPush = async (currentAuth) => {
|
|
416
|
+
const env = await prepareRemoteForAuth(cwd, remoteUrl, currentAuth);
|
|
417
|
+
return execCapture("git", args, cwd, { env });
|
|
418
|
+
};
|
|
419
|
+
let result = await runPush(auth);
|
|
420
|
+
if (
|
|
421
|
+
result.code !== 0 &&
|
|
422
|
+
auth.mode === "native" &&
|
|
423
|
+
platformToken &&
|
|
424
|
+
isGitAuthFailure(result.stderr, result.stdout)
|
|
425
|
+
) {
|
|
426
|
+
result = await runPush(buildRetryAuth(platformToken));
|
|
427
|
+
}
|
|
428
|
+
return buildTextResult(formatGitSummary("git", "git push", result));
|
|
429
|
+
} catch (error) {
|
|
430
|
+
return buildErrorResult(error);
|
|
431
|
+
}
|
|
432
|
+
},
|
|
433
|
+
});
|
|
434
|
+
api.registerTool({
|
|
435
|
+
name: "github_local_pr_create",
|
|
436
|
+
label: "GitHub local PR create",
|
|
437
|
+
description: "Creates a pull request with `gh pr create` from the current branch.",
|
|
438
|
+
parameters: Type.Object({
|
|
439
|
+
title: Type.String({ description: "Pull request title." }),
|
|
440
|
+
body: Type.String({ description: "Pull request body." }),
|
|
441
|
+
base: Type.Optional(Type.String({ description: "Optional base branch name." })),
|
|
442
|
+
}),
|
|
443
|
+
async execute(_toolCallId, params) {
|
|
444
|
+
try {
|
|
445
|
+
const title = String(params.title ?? "").trim();
|
|
446
|
+
const body = String(params.body ?? "").trim();
|
|
447
|
+
const base = typeof params.base === "string" ? params.base.trim() : "";
|
|
448
|
+
if (!title) {
|
|
449
|
+
return buildTextResult("pull request title is required");
|
|
450
|
+
}
|
|
451
|
+
if (!body) {
|
|
452
|
+
return buildTextResult("pull request body is required");
|
|
453
|
+
}
|
|
454
|
+
const cwd = resolveWorkspacePath();
|
|
455
|
+
const gitWorkspace = requireGitWorkspace(cwd);
|
|
456
|
+
if (!gitWorkspace.ok) return gitWorkspace.result;
|
|
457
|
+
const branch = await resolveCurrentBranch(cwd);
|
|
458
|
+
const args = ["pr", "create", "--title", title, "--body", body];
|
|
459
|
+
if (base) {
|
|
460
|
+
args.push("--base", base);
|
|
461
|
+
}
|
|
462
|
+
if (branch) {
|
|
463
|
+
args.push("--head", branch);
|
|
464
|
+
}
|
|
465
|
+
const { auth, env, platformToken } = await resolveWorkspaceAuth(cwd);
|
|
466
|
+
let result = await execCapture("gh", args, cwd, { env });
|
|
467
|
+
if (
|
|
468
|
+
result.code !== 0 &&
|
|
469
|
+
auth.mode === "native" &&
|
|
470
|
+
platformToken &&
|
|
471
|
+
isGitAuthFailure(result.stderr, result.stdout)
|
|
472
|
+
) {
|
|
473
|
+
const retryEnv = buildGitGhSubprocessEnv(buildRetryAuth(platformToken), process.env);
|
|
474
|
+
result = await execCapture("gh", args, cwd, { env: retryEnv });
|
|
475
|
+
}
|
|
476
|
+
return buildTextResult(formatGitSummary("gh", "gh pr create", result));
|
|
477
|
+
} catch (error) {
|
|
478
|
+
return buildErrorResult(error);
|
|
479
|
+
}
|
|
480
|
+
},
|
|
481
|
+
});
|
|
469
482
|
}
|
|
470
|
-
//# sourceMappingURL=kubbisec-github-local.extension.js.map
|
|
483
|
+
//# sourceMappingURL=kubbisec-github-local.extension.js.map
|