@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,177 +3,175 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import * as fs from "node:fs";
|
|
5
5
|
import * as path from "node:path";
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
getSessionWorkflowFooterBadge,
|
|
8
|
+
getSessionWorkflowMode,
|
|
9
|
+
setSessionSpecApproved,
|
|
10
|
+
setSessionWorkflowMode,
|
|
11
|
+
} from "../workflow/session-workflow-mode.js";
|
|
12
|
+
|
|
7
13
|
const MUTATION_TOOLS = new Set([
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
14
|
+
"edit",
|
|
15
|
+
"write",
|
|
16
|
+
"set_pipeline_yaml",
|
|
17
|
+
"bash",
|
|
18
|
+
"delete",
|
|
19
|
+
"patch",
|
|
20
|
+
"apply_patch",
|
|
15
21
|
]);
|
|
16
22
|
const READ_ONLY_TOOLS = new Set(["read", "grep", "find", "ls", "glob", "questionnaire"]);
|
|
17
23
|
export function isMutationTool(toolName) {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
return MUTATION_TOOLS.has(toolName);
|
|
24
|
+
if (READ_ONLY_TOOLS.has(toolName)) return false;
|
|
25
|
+
return MUTATION_TOOLS.has(toolName);
|
|
21
26
|
}
|
|
22
27
|
export function detectModeFromPrompt(prompt, envMode) {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
28
|
+
const trimmed = prompt.trim();
|
|
29
|
+
if (
|
|
30
|
+
trimmed.startsWith("/mode:plan") ||
|
|
31
|
+
/^@plan\b/i.test(trimmed) ||
|
|
32
|
+
/^@planejar\b/i.test(trimmed)
|
|
33
|
+
) {
|
|
34
|
+
return "plan";
|
|
35
|
+
}
|
|
36
|
+
if (trimmed.startsWith("/mode:review")) return "review";
|
|
37
|
+
const fromEnv = envMode?.trim().toLowerCase();
|
|
38
|
+
if (fromEnv === "plan" || fromEnv === "review") return fromEnv;
|
|
39
|
+
return "default";
|
|
35
40
|
}
|
|
36
41
|
export function parseRuntimeSpecStatus(content) {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
return statusMatch?.[1]?.trim() ?? null;
|
|
42
|
+
const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
43
|
+
if (!match?.[1]) return null;
|
|
44
|
+
const statusMatch = match[1].match(/^status:\s*(\S+)/m);
|
|
45
|
+
return statusMatch?.[1]?.trim() ?? null;
|
|
42
46
|
}
|
|
43
47
|
export function findApprovedSpec(cwd) {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
return { approved: false };
|
|
47
|
-
}
|
|
48
|
-
for (const entry of fs.readdirSync(specsDir, { withFileTypes: true })) {
|
|
49
|
-
if (!entry.isFile() || !entry.name.endsWith(".md"))
|
|
50
|
-
continue;
|
|
51
|
-
const specPath = path.join(specsDir, entry.name);
|
|
52
|
-
try {
|
|
53
|
-
const content = fs.readFileSync(specPath, "utf8");
|
|
54
|
-
if (parseRuntimeSpecStatus(content) === "approved") {
|
|
55
|
-
return { approved: true, specPath };
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
catch {
|
|
59
|
-
/* skip unreadable spec */
|
|
60
|
-
}
|
|
61
|
-
}
|
|
48
|
+
const specsDir = path.join(cwd, ".kubbisec", "specs");
|
|
49
|
+
if (!fs.existsSync(specsDir)) {
|
|
62
50
|
return { approved: false };
|
|
51
|
+
}
|
|
52
|
+
for (const entry of fs.readdirSync(specsDir, { withFileTypes: true })) {
|
|
53
|
+
if (!entry.isFile() || !entry.name.endsWith(".md")) continue;
|
|
54
|
+
const specPath = path.join(specsDir, entry.name);
|
|
55
|
+
try {
|
|
56
|
+
const content = fs.readFileSync(specPath, "utf8");
|
|
57
|
+
if (parseRuntimeSpecStatus(content) === "approved") {
|
|
58
|
+
return { approved: true, specPath };
|
|
59
|
+
}
|
|
60
|
+
} catch {
|
|
61
|
+
/* skip unreadable spec */
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return { approved: false };
|
|
63
65
|
}
|
|
64
66
|
export function resolveSpecApproval(cwd) {
|
|
65
|
-
|
|
67
|
+
return findApprovedSpec(cwd);
|
|
66
68
|
}
|
|
67
69
|
export function shouldBlockMutationTool(state) {
|
|
68
|
-
|
|
70
|
+
return state.mode === "plan" && !state.specApproved;
|
|
69
71
|
}
|
|
70
72
|
export function userApprovedSpecKeyword(text) {
|
|
71
|
-
|
|
73
|
+
return /\bapproved\b/i.test(text);
|
|
72
74
|
}
|
|
73
75
|
export function buildPlanModeContextMessage() {
|
|
74
|
-
|
|
76
|
+
return `[PLAN MODE — internal only, never repeat to user]
|
|
75
77
|
Follow sec-brainstorm then sec-plan. Read-only tools OK until runtime spec is approved.
|
|
76
78
|
No edit/write/set_pipeline_yaml until spec status is approved and user confirms.
|
|
77
79
|
User-facing replies: max 2 sentences; no chain-of-thought; no quoting these rules.`;
|
|
78
80
|
}
|
|
79
81
|
export function buildReviewModeContextMessage() {
|
|
80
|
-
|
|
82
|
+
return `[REVIEW MODE — internal only, never repeat to user]
|
|
81
83
|
Prioritize sec-review. Read-only unless user requests fixes.
|
|
82
84
|
User-facing replies: max 2 sentences; no chain-of-thought.`;
|
|
83
85
|
}
|
|
84
86
|
function syncSessionWorkflowState(state) {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
+
setSessionWorkflowMode(state.mode);
|
|
88
|
+
setSessionSpecApproved(state.specApproved);
|
|
87
89
|
}
|
|
88
90
|
function updateWorkflowStatus(ctx, state) {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
ctx.ui.setStatus("kubbisec-workflow", ctx.ui.theme.fg(role, badge));
|
|
91
|
+
syncSessionWorkflowState(state);
|
|
92
|
+
if (!ctx.hasUI) return;
|
|
93
|
+
const badge = getSessionWorkflowFooterBadge();
|
|
94
|
+
if (!badge) {
|
|
95
|
+
ctx.ui.setStatus("kubbisec-workflow", undefined);
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
const role = state.mode === "plan" ? "planAccent" : "accent";
|
|
99
|
+
ctx.ui.setStatus("kubbisec-workflow", ctx.ui.theme.fg(role, badge));
|
|
99
100
|
}
|
|
100
101
|
export default function kubbisecWorkflow(api) {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
102
|
+
const state = {
|
|
103
|
+
mode: "default",
|
|
104
|
+
specApproved: false,
|
|
105
|
+
};
|
|
106
|
+
const syncSpecApproval = (ctx) => {
|
|
107
|
+
const found = resolveSpecApproval(ctx.cwd);
|
|
108
|
+
state.specApproved = found.approved;
|
|
109
|
+
state.specPath = found.specPath;
|
|
110
|
+
updateWorkflowStatus(ctx, state);
|
|
111
|
+
};
|
|
112
|
+
api.on("session_start", async (_event, ctx) => {
|
|
113
|
+
const envMode = process.env.KUBBISEC_CHAT_MODE;
|
|
114
|
+
if (envMode === "plan" || envMode === "review") {
|
|
115
|
+
state.mode = envMode;
|
|
116
|
+
} else if (getSessionWorkflowMode() !== "default") {
|
|
117
|
+
state.mode = getSessionWorkflowMode();
|
|
118
|
+
}
|
|
119
|
+
syncSpecApproval(ctx);
|
|
120
|
+
if (ctx.hasUI && state.mode === "plan") {
|
|
121
|
+
ctx.ui.notify("Plan mode: describe scope with @plan or @skill …", "info");
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
api.on("before_agent_start", async (event, ctx) => {
|
|
125
|
+
const { prompt } = event;
|
|
126
|
+
const detected = detectModeFromPrompt(prompt, process.env.KUBBISEC_CHAT_MODE);
|
|
127
|
+
if (detected !== "default") {
|
|
128
|
+
state.mode = detected;
|
|
129
|
+
} else if (state.mode !== "default") {
|
|
130
|
+
/* keep plan/review active across follow-up turns without /mode: prefix */
|
|
131
|
+
} else if (getSessionWorkflowMode() !== "default") {
|
|
132
|
+
state.mode = getSessionWorkflowMode();
|
|
133
|
+
}
|
|
134
|
+
if (userApprovedSpecKeyword(prompt)) {
|
|
135
|
+
syncSpecApproval(ctx);
|
|
136
|
+
if (!state.specApproved) {
|
|
137
|
+
state.specApproved = true;
|
|
138
|
+
}
|
|
139
|
+
} else {
|
|
140
|
+
syncSpecApproval(ctx);
|
|
141
|
+
}
|
|
142
|
+
updateWorkflowStatus(ctx, state);
|
|
143
|
+
if (state.mode === "plan") {
|
|
144
|
+
return {
|
|
145
|
+
message: {
|
|
146
|
+
customType: "kubbisec-plan-mode",
|
|
147
|
+
content: buildPlanModeContextMessage(),
|
|
148
|
+
display: false,
|
|
149
|
+
},
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
if (state.mode === "review") {
|
|
153
|
+
return {
|
|
154
|
+
message: {
|
|
155
|
+
customType: "kubbisec-review-mode",
|
|
156
|
+
content: buildReviewModeContextMessage(),
|
|
157
|
+
display: false,
|
|
158
|
+
},
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
return undefined;
|
|
162
|
+
});
|
|
163
|
+
api.on("tool_call", async (event, ctx) => {
|
|
164
|
+
syncSpecApproval(ctx);
|
|
165
|
+
const { toolName } = event;
|
|
166
|
+
if (!shouldBlockMutationTool(state) || !isMutationTool(toolName)) {
|
|
167
|
+
return undefined;
|
|
168
|
+
}
|
|
169
|
+
return {
|
|
170
|
+
block: true,
|
|
171
|
+
reason:
|
|
172
|
+
`Plan mode HARD-GATE: mutation tool "${toolName}" blocked until a runtime spec is approved.\n` +
|
|
173
|
+
`Create or update \`.kubbisec/specs/<slug>.md\` with \`status: approved\` in frontmatter, then confirm with "approved".`,
|
|
110
174
|
};
|
|
111
|
-
|
|
112
|
-
const envMode = process.env.KUBBISEC_CHAT_MODE;
|
|
113
|
-
if (envMode === "plan" || envMode === "review") {
|
|
114
|
-
state.mode = envMode;
|
|
115
|
-
}
|
|
116
|
-
else if (getSessionWorkflowMode() !== "default") {
|
|
117
|
-
state.mode = getSessionWorkflowMode();
|
|
118
|
-
}
|
|
119
|
-
syncSpecApproval(ctx);
|
|
120
|
-
if (ctx.hasUI && state.mode === "plan") {
|
|
121
|
-
ctx.ui.notify("Plan mode: describe scope with @plan or @skill …", "info");
|
|
122
|
-
}
|
|
123
|
-
});
|
|
124
|
-
api.on("before_agent_start", async (event, ctx) => {
|
|
125
|
-
const { prompt } = event;
|
|
126
|
-
const detected = detectModeFromPrompt(prompt, process.env.KUBBISEC_CHAT_MODE);
|
|
127
|
-
if (detected !== "default") {
|
|
128
|
-
state.mode = detected;
|
|
129
|
-
}
|
|
130
|
-
else if (state.mode !== "default") {
|
|
131
|
-
/* keep plan/review active across follow-up turns without /mode: prefix */
|
|
132
|
-
}
|
|
133
|
-
else if (getSessionWorkflowMode() !== "default") {
|
|
134
|
-
state.mode = getSessionWorkflowMode();
|
|
135
|
-
}
|
|
136
|
-
if (userApprovedSpecKeyword(prompt)) {
|
|
137
|
-
syncSpecApproval(ctx);
|
|
138
|
-
if (!state.specApproved) {
|
|
139
|
-
state.specApproved = true;
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
else {
|
|
143
|
-
syncSpecApproval(ctx);
|
|
144
|
-
}
|
|
145
|
-
updateWorkflowStatus(ctx, state);
|
|
146
|
-
if (state.mode === "plan") {
|
|
147
|
-
return {
|
|
148
|
-
message: {
|
|
149
|
-
customType: "kubbisec-plan-mode",
|
|
150
|
-
content: buildPlanModeContextMessage(),
|
|
151
|
-
display: false,
|
|
152
|
-
},
|
|
153
|
-
};
|
|
154
|
-
}
|
|
155
|
-
if (state.mode === "review") {
|
|
156
|
-
return {
|
|
157
|
-
message: {
|
|
158
|
-
customType: "kubbisec-review-mode",
|
|
159
|
-
content: buildReviewModeContextMessage(),
|
|
160
|
-
display: false,
|
|
161
|
-
},
|
|
162
|
-
};
|
|
163
|
-
}
|
|
164
|
-
return undefined;
|
|
165
|
-
});
|
|
166
|
-
api.on("tool_call", async (event, ctx) => {
|
|
167
|
-
syncSpecApproval(ctx);
|
|
168
|
-
const { toolName } = event;
|
|
169
|
-
if (!shouldBlockMutationTool(state) || !isMutationTool(toolName)) {
|
|
170
|
-
return undefined;
|
|
171
|
-
}
|
|
172
|
-
return {
|
|
173
|
-
block: true,
|
|
174
|
-
reason: `Plan mode HARD-GATE: mutation tool "${toolName}" blocked until a runtime spec is approved.\n` +
|
|
175
|
-
`Create or update \`.kubbisec/specs/<slug>.md\` with \`status: approved\` in frontmatter, then confirm with "approved".`,
|
|
176
|
-
};
|
|
177
|
-
});
|
|
175
|
+
});
|
|
178
176
|
}
|
|
179
|
-
//# sourceMappingURL=kubbisec-workflow.extension.js.map
|
|
177
|
+
//# sourceMappingURL=kubbisec-workflow.extension.js.map
|
|
@@ -3,164 +3,155 @@ import * as fs from "node:fs";
|
|
|
3
3
|
import * as path from "node:path";
|
|
4
4
|
import { fileURLToPath } from "node:url";
|
|
5
5
|
import { getAiStateDir } from "@kubbisec/home";
|
|
6
|
+
|
|
6
7
|
const BUNDLED_ASSET_DIRS = [
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
8
|
+
"extensions",
|
|
9
|
+
"skills",
|
|
10
|
+
"theme",
|
|
11
|
+
"assets",
|
|
12
|
+
"copy",
|
|
13
|
+
"config",
|
|
14
|
+
"components",
|
|
15
|
+
"workflow",
|
|
15
16
|
];
|
|
16
17
|
const BUNDLED_ROOT_FILES = ["resolve-bundled-dist-root.js"];
|
|
17
18
|
const MARKER_EXTENSION = "kubbisec-brand.extension.js";
|
|
18
19
|
/** True when this process runs from a pkg / @yao-pkg/pkg native binary. */
|
|
19
20
|
export function isPkgBundledCli() {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
return false;
|
|
28
|
-
}
|
|
21
|
+
if (process.pkg) return true;
|
|
22
|
+
try {
|
|
23
|
+
const selfPath = fileURLToPath(import.meta.url);
|
|
24
|
+
return selfPath.includes("/snapshot/") || selfPath.includes("\\snapshot\\");
|
|
25
|
+
} catch {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
29
28
|
}
|
|
30
29
|
function hasCompiledBundledAssets(distDir) {
|
|
31
|
-
|
|
30
|
+
return fs.existsSync(path.join(distDir, "extensions", MARKER_EXTENSION));
|
|
32
31
|
}
|
|
33
32
|
/** Dist directory inside the bundle (extensions/, skills/, …). */
|
|
34
33
|
export function resolveSnapshotBundledDistDir() {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
return packageDist;
|
|
42
|
-
}
|
|
34
|
+
const entryDir = path.dirname(fileURLToPath(import.meta.url));
|
|
35
|
+
if (hasCompiledBundledAssets(entryDir)) {
|
|
36
|
+
return entryDir;
|
|
37
|
+
}
|
|
38
|
+
const packageDist = path.join(entryDir, "..", "dist");
|
|
39
|
+
if (hasCompiledBundledAssets(packageDist)) {
|
|
43
40
|
return packageDist;
|
|
41
|
+
}
|
|
42
|
+
return packageDist;
|
|
44
43
|
}
|
|
45
44
|
function fingerprintBundledDist(distDir) {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
hash.update(name);
|
|
76
|
-
hash.update(fs.readFileSync(path.join(distDir, name)));
|
|
77
|
-
}
|
|
78
|
-
return hash.digest("hex").slice(0, 16);
|
|
45
|
+
const hash = crypto.createHash("sha256");
|
|
46
|
+
for (const dir of BUNDLED_ASSET_DIRS) {
|
|
47
|
+
const base = path.join(distDir, dir);
|
|
48
|
+
if (!fs.existsSync(base)) continue;
|
|
49
|
+
for (const rel of listFilesRecursive(base)) {
|
|
50
|
+
hash.update(rel);
|
|
51
|
+
hash.update(fs.readFileSync(path.join(base, rel)));
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
for (const file of BUNDLED_ROOT_FILES) {
|
|
55
|
+
const full = path.join(distDir, file);
|
|
56
|
+
if (!fs.existsSync(full)) continue;
|
|
57
|
+
hash.update(file);
|
|
58
|
+
hash.update(fs.readFileSync(full));
|
|
59
|
+
}
|
|
60
|
+
for (const scope of ["@kubbisec", "@aspm"]) {
|
|
61
|
+
const scopeModules = path.join(distDir, "node_modules", scope);
|
|
62
|
+
if (!fs.existsSync(scopeModules)) continue;
|
|
63
|
+
for (const rel of listFilesRecursive(scopeModules)) {
|
|
64
|
+
hash.update(`${scope}/${rel}`);
|
|
65
|
+
hash.update(fs.readFileSync(path.join(scopeModules, rel)));
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
for (const name of fs.readdirSync(distDir)) {
|
|
69
|
+
if (!name.endsWith(".md")) continue;
|
|
70
|
+
hash.update(name);
|
|
71
|
+
hash.update(fs.readFileSync(path.join(distDir, name)));
|
|
72
|
+
}
|
|
73
|
+
return hash.digest("hex").slice(0, 16);
|
|
79
74
|
}
|
|
80
75
|
function listFilesRecursive(root, prefix = "") {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
return out;
|
|
76
|
+
const out = [];
|
|
77
|
+
for (const entry of fs.readdirSync(path.join(root, prefix), { withFileTypes: true })) {
|
|
78
|
+
const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
79
|
+
if (entry.isDirectory()) {
|
|
80
|
+
out.push(...listFilesRecursive(root, rel));
|
|
81
|
+
} else {
|
|
82
|
+
out.push(rel);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return out;
|
|
92
86
|
}
|
|
93
87
|
function copyBundledDist(sourceDist, targetDist) {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
continue;
|
|
114
|
-
fs.copyFileSync(path.join(sourceDist, name), path.join(targetDist, name));
|
|
115
|
-
}
|
|
88
|
+
fs.mkdirSync(targetDist, { recursive: true, mode: 0o755 });
|
|
89
|
+
for (const dir of BUNDLED_ASSET_DIRS) {
|
|
90
|
+
const src = path.join(sourceDist, dir);
|
|
91
|
+
if (!fs.existsSync(src)) continue;
|
|
92
|
+
fs.cpSync(src, path.join(targetDist, dir), { recursive: true });
|
|
93
|
+
}
|
|
94
|
+
for (const file of BUNDLED_ROOT_FILES) {
|
|
95
|
+
const src = path.join(sourceDist, file);
|
|
96
|
+
if (!fs.existsSync(src)) continue;
|
|
97
|
+
fs.copyFileSync(src, path.join(targetDist, file));
|
|
98
|
+
}
|
|
99
|
+
const modulesSrc = path.join(sourceDist, "node_modules");
|
|
100
|
+
if (fs.existsSync(modulesSrc)) {
|
|
101
|
+
fs.cpSync(modulesSrc, path.join(targetDist, "node_modules"), { recursive: true });
|
|
102
|
+
}
|
|
103
|
+
for (const name of fs.readdirSync(sourceDist)) {
|
|
104
|
+
if (!name.endsWith(".md")) continue;
|
|
105
|
+
fs.copyFileSync(path.join(sourceDist, name), path.join(targetDist, name));
|
|
106
|
+
}
|
|
116
107
|
}
|
|
117
108
|
export function materializeBundledDistForHost(snapshotDist) {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
109
|
+
const version =
|
|
110
|
+
process.env.KUBBISEC_AI_VERSION?.trim() || process.env.npm_package_version?.trim() || "bundled";
|
|
111
|
+
const fingerprint = fingerprintBundledDist(snapshotDist);
|
|
112
|
+
const targetDist = path.join(getAiStateDir(), "bundled", version, fingerprint);
|
|
113
|
+
const marker = path.join(targetDist, "extensions", MARKER_EXTENSION);
|
|
114
|
+
const stampPath = path.join(targetDist, ".fingerprint");
|
|
115
|
+
if (fs.existsSync(marker)) {
|
|
116
|
+
try {
|
|
117
|
+
if (fs.readFileSync(stampPath, "utf8").trim() === fingerprint) {
|
|
118
|
+
return targetDist;
|
|
119
|
+
}
|
|
120
|
+
} catch {
|
|
121
|
+
/* re-materialize */
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
if (fs.existsSync(targetDist)) {
|
|
125
|
+
fs.rmSync(targetDist, { recursive: true, force: true });
|
|
126
|
+
}
|
|
127
|
+
copyBundledDist(snapshotDist, targetDist);
|
|
128
|
+
fs.writeFileSync(stampPath, `${fingerprint}\n`, "utf8");
|
|
129
|
+
return targetDist;
|
|
139
130
|
}
|
|
140
131
|
/** Assets shipped next to the platform npm binary (`../bundled` from `bin/kubbisec`). */
|
|
141
132
|
export function resolvePackagedBundledDistDir() {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
133
|
+
const packaged = path.join(path.dirname(process.execPath), "..", "bundled");
|
|
134
|
+
if (hasCompiledBundledAssets(packaged)) {
|
|
135
|
+
return packaged;
|
|
136
|
+
}
|
|
137
|
+
return null;
|
|
147
138
|
}
|
|
148
139
|
/**
|
|
149
140
|
* Directory containing extensions/, skills/, theme/, assets/ for Pi `-e` / `--skill`.
|
|
150
141
|
* Native CLI: prefer `../bundled` beside the executable; else copy pkg snapshot assets to ~/.kubbisec/ai/bundled/.
|
|
151
142
|
*/
|
|
152
143
|
export function resolveBundledDistRoot() {
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
return snapshotDist;
|
|
160
|
-
}
|
|
161
|
-
if (hasCompiledBundledAssets(snapshotDist)) {
|
|
162
|
-
return materializeBundledDistForHost(snapshotDist);
|
|
163
|
-
}
|
|
144
|
+
const packaged = resolvePackagedBundledDistDir();
|
|
145
|
+
if (packaged) {
|
|
146
|
+
return packaged;
|
|
147
|
+
}
|
|
148
|
+
const snapshotDist = resolveSnapshotBundledDistDir();
|
|
149
|
+
if (!isPkgBundledCli()) {
|
|
164
150
|
return snapshotDist;
|
|
151
|
+
}
|
|
152
|
+
if (hasCompiledBundledAssets(snapshotDist)) {
|
|
153
|
+
return materializeBundledDistForHost(snapshotDist);
|
|
154
|
+
}
|
|
155
|
+
return snapshotDist;
|
|
165
156
|
}
|
|
166
|
-
//# sourceMappingURL=resolve-bundled-dist-root.js.map
|
|
157
|
+
//# sourceMappingURL=resolve-bundled-dist-root.js.map
|
|
@@ -4,4 +4,4 @@ export declare function isAtFileAttachmentPrefix(atPrefix: string | null): boole
|
|
|
4
4
|
/** List cwd-scoped entries for `@` / `@path` (Pi getFileSuggestions semantics). */
|
|
5
5
|
export declare function getAtPathFileSuggestions(cwd: string, atPrefix: string): AutocompleteItem[];
|
|
6
6
|
export declare function extractAtFilePrefix(textBeforeCursor: string): string | null;
|
|
7
|
-
//# sourceMappingURL=at-path-mentions.d.ts.map
|
|
7
|
+
//# sourceMappingURL=at-path-mentions.d.ts.map
|