@kubbisec/ai-linux-arm64 0.1.21 → 0.1.22
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/bundled/clarify/clarify-gate-state.d.ts +1 -1
- package/bundled/clarify/clarify-gate-state.js +3 -3
- package/bundled/clarify/clarify-gate.d.ts +21 -14
- package/bundled/clarify/clarify-gate.js +118 -111
- package/bundled/clarify/clarify-select-panel.d.ts +16 -9
- package/bundled/clarify/clarify-select-panel.js +65 -67
- package/bundled/clarify/clarify-ui-state.d.ts +12 -10
- package/bundled/clarify/clarify-ui-state.js +26 -26
- package/bundled/clarify/parse-clarify-answer.d.ts +29 -18
- package/bundled/clarify/parse-clarify-answer.js +39 -45
- package/bundled/clarify/question-format.d.ts +34 -23
- package/bundled/clarify/question-format.js +112 -119
- package/bundled/clarify/questionnaire-tool.d.ts +28 -17
- package/bundled/clarify/questionnaire-tool.js +180 -144
- package/bundled/clarify/scope-discovery.d.ts +8 -5
- package/bundled/clarify/scope-discovery.js +102 -110
- package/bundled/clarify/session-questionnaire.d.ts +48 -13
- package/bundled/clarify/session-questionnaire.js +304 -312
- package/bundled/clarify/session-questionnaire.types.d.ts +29 -27
- package/bundled/clarify/session-questionnaire.types.js +10 -10
- 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 +55 -55
- 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-kubbisec-project-settings.d.ts +9 -9
- package/bundled/config/ensure-kubbisec-project-settings.js +44 -48
- 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 +22 -2
- package/bundled/config/kubbisec-extension-manifest.js +20 -20
- 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 +174 -183
- 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 +3 -2
- 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 +45 -26
- package/bundled/extensions/cli-local-shared.js +128 -118
- package/bundled/extensions/kubbisec-aspm-local.extension.d.ts +18 -15
- package/bundled/extensions/kubbisec-aspm-local.extension.js +118 -114
- 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 +123 -116
- 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 +132 -111
- 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 +73 -63
- 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 +114 -109
- package/bundled/extensions/kubbisec-workflow.extension.d.ts +20 -18
- package/bundled/extensions/kubbisec-workflow.extension.js +138 -140
- package/bundled/node_modules/@aspm/shared/dist/redaction.test.d.ts +2 -0
- package/bundled/node_modules/@aspm/shared/dist/redaction.test.d.ts.map +1 -0
- package/bundled/node_modules/@aspm/shared/dist/redaction.test.js +626 -0
- package/bundled/node_modules/@aspm/shared/dist/redaction.test.js.map +1 -0
- package/bundled/resolve-bundled-dist-root.js +122 -131
- 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 +127 -129
- package/bundled/workflow/session-workflow-mode.d.ts +1 -1
- package/bundled/workflow/session-workflow-mode.js +33 -33
- package/package.json +1 -1
package/bundled/config/config.js
CHANGED
|
@@ -1,69 +1,69 @@
|
|
|
1
|
-
import * as os from "node:os";
|
|
2
1
|
import * as fs from "node:fs";
|
|
2
|
+
import * as os from "node:os";
|
|
3
3
|
import * as path from "node:path";
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
DEFAULT_KUBBISEC_API_URL,
|
|
6
|
+
getAiStateDir,
|
|
7
|
+
getKubbisecConfigPath,
|
|
8
|
+
resolveKubbisecApiUrl,
|
|
9
|
+
} from "@kubbisec/home";
|
|
5
10
|
export function getKubbisecStateDir() {
|
|
6
|
-
|
|
11
|
+
return getAiStateDir();
|
|
7
12
|
}
|
|
8
13
|
export function getConfigPath() {
|
|
9
|
-
|
|
14
|
+
return getKubbisecConfigPath();
|
|
10
15
|
}
|
|
11
16
|
export function loadConfig() {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
continue;
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
return {};
|
|
17
|
+
const stateDir = getAiStateDir();
|
|
18
|
+
const candidates = [getKubbisecConfigPath(), path.join(stateDir, "kbs.json")];
|
|
19
|
+
for (const configFile of candidates) {
|
|
20
|
+
try {
|
|
21
|
+
if (!fs.existsSync(configFile)) continue;
|
|
22
|
+
return JSON.parse(fs.readFileSync(configFile, "utf8"));
|
|
23
|
+
} catch {}
|
|
24
|
+
}
|
|
25
|
+
return {};
|
|
25
26
|
}
|
|
26
27
|
export function saveConfig(partial) {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
28
|
+
const prev = loadConfig();
|
|
29
|
+
const next = {
|
|
30
|
+
apiUrl: resolveKubbisecApiUrl(partial.apiUrl ?? prev.apiUrl),
|
|
31
|
+
apiKey: partial.apiKey ?? prev.apiKey ?? "",
|
|
32
|
+
orgId: partial.orgId ?? prev.orgId,
|
|
33
|
+
defaultProject: partial.defaultProject ?? prev.defaultProject,
|
|
34
|
+
clientId: partial.clientId ?? prev.clientId ?? `kubbisec-${os.hostname()}`,
|
|
35
|
+
};
|
|
36
|
+
const stateDir = getAiStateDir();
|
|
37
|
+
fs.mkdirSync(stateDir, { recursive: true, mode: 0o700 });
|
|
38
|
+
const persisted = {
|
|
39
|
+
apiKey: next.apiKey,
|
|
40
|
+
orgId: next.orgId,
|
|
41
|
+
defaultProject: next.defaultProject,
|
|
42
|
+
clientId: next.clientId,
|
|
43
|
+
};
|
|
44
|
+
if (next.apiUrl !== DEFAULT_KUBBISEC_API_URL) {
|
|
45
|
+
persisted.apiUrl = next.apiUrl;
|
|
46
|
+
}
|
|
47
|
+
fs.writeFileSync(getKubbisecConfigPath(), `${JSON.stringify(persisted, null, 2)}\n`, {
|
|
48
|
+
mode: 0o600,
|
|
49
|
+
});
|
|
50
|
+
return next;
|
|
50
51
|
}
|
|
51
52
|
export function clearConfig() {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
fs.unlinkSync(configFile);
|
|
53
|
+
const configFile = getKubbisecConfigPath();
|
|
54
|
+
if (fs.existsSync(configFile)) fs.unlinkSync(configFile);
|
|
55
55
|
}
|
|
56
56
|
export function requireConfig() {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
57
|
+
const cfg = loadConfig();
|
|
58
|
+
if (!cfg.apiKey?.trim()) {
|
|
59
|
+
throw new Error("Not logged in. Run: kubbisec login");
|
|
60
|
+
}
|
|
61
|
+
return {
|
|
62
|
+
apiUrl: resolveKubbisecApiUrl(cfg.apiUrl),
|
|
63
|
+
apiKey: cfg.apiKey.trim(),
|
|
64
|
+
orgId: cfg.orgId?.trim() || undefined,
|
|
65
|
+
defaultProject: cfg.defaultProject?.trim() || undefined,
|
|
66
|
+
clientId: cfg.clientId?.trim() || `kubbisec-${os.hostname()}`,
|
|
67
|
+
};
|
|
68
68
|
}
|
|
69
|
-
//# sourceMappingURL=config.js.map
|
|
69
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -6,28 +6,38 @@ export declare const LM_STUDIO_PROVIDER_NAME = "LM Studio";
|
|
|
6
6
|
export declare const OLLAMA_DEFAULT_HOST = "http://127.0.0.1:11434";
|
|
7
7
|
export declare const LM_STUDIO_DEFAULT_HOST = "http://127.0.0.1:1234";
|
|
8
8
|
export type LocalLlmDetectOptions = {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
9
|
+
timeoutMs?: number;
|
|
10
|
+
ollamaBaseUrl?: string;
|
|
11
|
+
lmStudioBaseUrl?: string;
|
|
12
|
+
detectOllama?: boolean;
|
|
13
|
+
detectLmStudio?: boolean;
|
|
14
14
|
};
|
|
15
15
|
export type LocalLlmDetectResult = {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
detected: KubbisecCustomProviderDef[];
|
|
17
|
+
ollama: KubbisecCustomProviderDef | null;
|
|
18
|
+
lmstudio: KubbisecCustomProviderDef | null;
|
|
19
|
+
removedProviderIds: string[];
|
|
20
20
|
};
|
|
21
21
|
export declare function resolveOllamaHost(config?: KubbisecLlmConfig["localLlm"]): string;
|
|
22
22
|
export declare function resolveLmStudioOpenAiBase(config?: KubbisecLlmConfig["localLlm"]): string;
|
|
23
23
|
export declare function inferLocalModelReasoning(modelId: string): boolean;
|
|
24
24
|
export declare function formatLocalModelName(modelId: string): string;
|
|
25
|
-
export declare function detectOllamaProvider(
|
|
26
|
-
|
|
25
|
+
export declare function detectOllamaProvider(
|
|
26
|
+
options?: LocalLlmDetectOptions,
|
|
27
|
+
): Promise<KubbisecCustomProviderDef | null>;
|
|
28
|
+
export declare function detectLmStudioProvider(
|
|
29
|
+
options?: LocalLlmDetectOptions,
|
|
30
|
+
): Promise<KubbisecCustomProviderDef | null>;
|
|
27
31
|
export declare function isLocalLlmAutodetectEnabled(config?: KubbisecLlmConfig): boolean;
|
|
28
|
-
export declare function detectLocalLlmProviders(
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
+
export declare function detectLocalLlmProviders(
|
|
33
|
+
config?: KubbisecLlmConfig,
|
|
34
|
+
overrides?: LocalLlmDetectOptions,
|
|
35
|
+
): Promise<KubbisecCustomProviderDef[]>;
|
|
36
|
+
export declare function syncAutodetectedLocalProviders(
|
|
37
|
+
cwd?: string,
|
|
38
|
+
options?: LocalLlmDetectOptions,
|
|
39
|
+
): Promise<{
|
|
40
|
+
config: KubbisecLlmConfig;
|
|
41
|
+
result: LocalLlmDetectResult;
|
|
32
42
|
}>;
|
|
33
|
-
//# sourceMappingURL=detect-local-llm-providers.d.ts.map
|
|
43
|
+
//# sourceMappingURL=detect-local-llm-providers.d.ts.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { applyLlmConfigToPiSettings, readLlmConfig, writeLlmConfig
|
|
1
|
+
import { applyLlmConfigToPiSettings, readLlmConfig, writeLlmConfig } from "./llm-config.js";
|
|
2
2
|
export const OLLAMA_PROVIDER_ID = "ollama";
|
|
3
3
|
export const LM_STUDIO_PROVIDER_ID = "lmstudio";
|
|
4
4
|
export const OLLAMA_PROVIDER_NAME = "Ollama";
|
|
@@ -6,167 +6,155 @@ export const LM_STUDIO_PROVIDER_NAME = "LM Studio";
|
|
|
6
6
|
export const OLLAMA_DEFAULT_HOST = "http://127.0.0.1:11434";
|
|
7
7
|
export const LM_STUDIO_DEFAULT_HOST = "http://127.0.0.1:1234";
|
|
8
8
|
export function resolveOllamaHost(config) {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
const fromEnv = process.env.OLLAMA_HOST?.trim();
|
|
10
|
+
const fromConfig = config?.ollama?.baseUrl?.trim();
|
|
11
|
+
const raw = fromConfig || fromEnv || OLLAMA_DEFAULT_HOST;
|
|
12
|
+
return raw.replace(/\/+$/, "");
|
|
13
13
|
}
|
|
14
14
|
export function resolveLmStudioOpenAiBase(config) {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
15
|
+
const fromEnv = process.env.LM_STUDIO_BASE_URL?.trim() || process.env.LMSTUDIO_BASE_URL?.trim();
|
|
16
|
+
const fromConfig = config?.lmstudio?.baseUrl?.trim();
|
|
17
|
+
const raw = fromConfig || fromEnv || LM_STUDIO_DEFAULT_HOST;
|
|
18
|
+
const trimmed = raw.replace(/\/+$/, "");
|
|
19
|
+
return trimmed.endsWith("/v1") ? trimmed : `${trimmed}/v1`;
|
|
20
20
|
}
|
|
21
21
|
export function inferLocalModelReasoning(modelId) {
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
const lower = modelId.toLowerCase();
|
|
23
|
+
return /(?:^|[-_/])(o1|o3|qwq|deepseek-r1|r1|reasoning|think)/.test(lower);
|
|
24
24
|
}
|
|
25
25
|
export function formatLocalModelName(modelId) {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
26
|
+
const base = modelId.split(":")[0] ?? modelId;
|
|
27
|
+
return base
|
|
28
|
+
.split(/[-_/]/)
|
|
29
|
+
.filter(Boolean)
|
|
30
|
+
.map((part) => part.charAt(0).toUpperCase() + part.slice(1))
|
|
31
|
+
.join(" ");
|
|
32
32
|
}
|
|
33
33
|
async function fetchJson(url, timeoutMs) {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
finally {
|
|
49
|
-
clearTimeout(timer);
|
|
50
|
-
}
|
|
34
|
+
const controller = new AbortController();
|
|
35
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
36
|
+
try {
|
|
37
|
+
const response = await fetch(url, {
|
|
38
|
+
signal: controller.signal,
|
|
39
|
+
headers: { Accept: "application/json" },
|
|
40
|
+
});
|
|
41
|
+
if (!response.ok) return null;
|
|
42
|
+
return await response.json();
|
|
43
|
+
} catch {
|
|
44
|
+
return null;
|
|
45
|
+
} finally {
|
|
46
|
+
clearTimeout(timer);
|
|
47
|
+
}
|
|
51
48
|
}
|
|
52
49
|
function toLocalModelDef(modelId) {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
50
|
+
const id = modelId.trim();
|
|
51
|
+
return {
|
|
52
|
+
id,
|
|
53
|
+
name: formatLocalModelName(id),
|
|
54
|
+
reasoning: inferLocalModelReasoning(id),
|
|
55
|
+
contextWindow: 128_000,
|
|
56
|
+
maxTokens: 8_192,
|
|
57
|
+
};
|
|
61
58
|
}
|
|
62
59
|
export async function detectOllamaProvider(options = {}) {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
detectSource: "ollama",
|
|
83
|
-
};
|
|
60
|
+
if (options.detectOllama === false) return null;
|
|
61
|
+
const host = (options.ollamaBaseUrl ?? resolveOllamaHost()).replace(/\/+$/, "");
|
|
62
|
+
const timeoutMs = options.timeoutMs ?? 900;
|
|
63
|
+
const tags = await fetchJson(`${host}/api/tags`, timeoutMs);
|
|
64
|
+
const models = (tags?.models ?? [])
|
|
65
|
+
.map((entry) => entry.name?.trim() || entry.model?.trim())
|
|
66
|
+
.filter((name) => Boolean(name));
|
|
67
|
+
if (models.length === 0) return null;
|
|
68
|
+
const uniqueModels = [...new Set(models)].map(toLocalModelDef);
|
|
69
|
+
return {
|
|
70
|
+
id: OLLAMA_PROVIDER_ID,
|
|
71
|
+
name: OLLAMA_PROVIDER_NAME,
|
|
72
|
+
baseUrl: `${host}/v1`,
|
|
73
|
+
apiKey: "ollama",
|
|
74
|
+
api: "openai-completions",
|
|
75
|
+
models: uniqueModels,
|
|
76
|
+
autodetected: true,
|
|
77
|
+
detectSource: "ollama",
|
|
78
|
+
};
|
|
84
79
|
}
|
|
85
80
|
export async function detectLmStudioProvider(options = {}) {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
models: uniqueModels,
|
|
104
|
-
autodetected: true,
|
|
105
|
-
detectSource: "lmstudio",
|
|
106
|
-
};
|
|
81
|
+
if (options.detectLmStudio === false) return null;
|
|
82
|
+
const baseUrl = (options.lmStudioBaseUrl ?? resolveLmStudioOpenAiBase()).replace(/\/+$/, "");
|
|
83
|
+
const timeoutMs = options.timeoutMs ?? 900;
|
|
84
|
+
const listing = await fetchJson(`${baseUrl}/models`, timeoutMs);
|
|
85
|
+
const models = (listing?.data ?? []).map((entry) => entry.id?.trim()).filter((id) => Boolean(id));
|
|
86
|
+
if (models.length === 0) return null;
|
|
87
|
+
const uniqueModels = [...new Set(models)].map(toLocalModelDef);
|
|
88
|
+
return {
|
|
89
|
+
id: LM_STUDIO_PROVIDER_ID,
|
|
90
|
+
name: LM_STUDIO_PROVIDER_NAME,
|
|
91
|
+
baseUrl,
|
|
92
|
+
apiKey: "lm-studio",
|
|
93
|
+
api: "openai-completions",
|
|
94
|
+
models: uniqueModels,
|
|
95
|
+
autodetected: true,
|
|
96
|
+
detectSource: "lmstudio",
|
|
97
|
+
};
|
|
107
98
|
}
|
|
108
99
|
export function isLocalLlmAutodetectEnabled(config = readLlmConfig()) {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
return true;
|
|
113
|
-
return config.localLlm?.autoDetect !== false;
|
|
100
|
+
if (process.env.KUBBISEC_LLM_AUTODETECT === "0") return false;
|
|
101
|
+
if (process.env.KUBBISEC_LLM_AUTODETECT === "1") return true;
|
|
102
|
+
return config.localLlm?.autoDetect !== false;
|
|
114
103
|
}
|
|
115
104
|
export async function detectLocalLlmProviders(config = readLlmConfig(), overrides = {}) {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
return [ollama, lmstudio].filter((provider) => provider != null);
|
|
105
|
+
if (!isLocalLlmAutodetectEnabled(config)) return [];
|
|
106
|
+
const local = config.localLlm;
|
|
107
|
+
const timeoutMs = overrides.timeoutMs ?? 900;
|
|
108
|
+
const [ollama, lmstudio] = await Promise.all([
|
|
109
|
+
detectOllamaProvider({
|
|
110
|
+
timeoutMs,
|
|
111
|
+
ollamaBaseUrl: overrides.ollamaBaseUrl ?? local?.ollama?.baseUrl,
|
|
112
|
+
detectOllama: local?.ollama?.enabled !== false && overrides.detectOllama !== false,
|
|
113
|
+
}),
|
|
114
|
+
detectLmStudioProvider({
|
|
115
|
+
timeoutMs,
|
|
116
|
+
lmStudioBaseUrl: overrides.lmStudioBaseUrl ?? local?.lmstudio?.baseUrl,
|
|
117
|
+
detectLmStudio: local?.lmstudio?.enabled !== false && overrides.detectLmStudio !== false,
|
|
118
|
+
}),
|
|
119
|
+
]);
|
|
120
|
+
return [ollama, lmstudio].filter((provider) => provider != null);
|
|
133
121
|
}
|
|
134
122
|
function mergeDetectedProviders(current, detected) {
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
next.push(provider);
|
|
150
|
-
}
|
|
151
|
-
return { providers: next, removedProviderIds };
|
|
123
|
+
const manual = current.filter((provider) => !provider.autodetected);
|
|
124
|
+
const manualIds = new Set(manual.map((provider) => provider.id));
|
|
125
|
+
const detectedIds = new Set(detected.map((provider) => provider.id));
|
|
126
|
+
const removedProviderIds = current
|
|
127
|
+
.filter((provider) => provider.autodetected && !detectedIds.has(provider.id))
|
|
128
|
+
.map((provider) => provider.id);
|
|
129
|
+
const next = [...manual];
|
|
130
|
+
for (const provider of detected) {
|
|
131
|
+
if (manualIds.has(provider.id)) continue;
|
|
132
|
+
const index = next.findIndex((entry) => entry.id === provider.id && entry.autodetected);
|
|
133
|
+
if (index >= 0) next[index] = provider;
|
|
134
|
+
else next.push(provider);
|
|
135
|
+
}
|
|
136
|
+
return { providers: next, removedProviderIds };
|
|
152
137
|
}
|
|
153
138
|
export async function syncAutodetectedLocalProviders(cwd = process.cwd(), options = {}) {
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
139
|
+
const current = readLlmConfig(cwd);
|
|
140
|
+
const detected = await detectLocalLlmProviders(current, options);
|
|
141
|
+
const { providers, removedProviderIds } = mergeDetectedProviders(
|
|
142
|
+
current.providers ?? [],
|
|
143
|
+
detected,
|
|
144
|
+
);
|
|
145
|
+
const next = { ...current, providers };
|
|
146
|
+
writeLlmConfig(cwd, next);
|
|
147
|
+
applyLlmConfigToPiSettings(cwd, next);
|
|
148
|
+
const ollama = detected.find((provider) => provider.id === OLLAMA_PROVIDER_ID) ?? null;
|
|
149
|
+
const lmstudio = detected.find((provider) => provider.id === LM_STUDIO_PROVIDER_ID) ?? null;
|
|
150
|
+
return {
|
|
151
|
+
config: next,
|
|
152
|
+
result: {
|
|
153
|
+
detected,
|
|
154
|
+
ollama,
|
|
155
|
+
lmstudio,
|
|
156
|
+
removedProviderIds,
|
|
157
|
+
},
|
|
158
|
+
};
|
|
171
159
|
}
|
|
172
|
-
//# sourceMappingURL=detect-local-llm-providers.js.map
|
|
160
|
+
//# sourceMappingURL=detect-local-llm-providers.js.map
|
|
@@ -6,14 +6,14 @@ export declare const KUBBISEC_SPECS_DIR = "specs";
|
|
|
6
6
|
export declare const KUBBISEC_PLANS_DIR = "plans";
|
|
7
7
|
export declare const KUBBISEC_CONTEXT_DIR = "context";
|
|
8
8
|
export type KubbisecProjectSettings = {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
9
|
+
theme?: string;
|
|
10
|
+
quietStartup?: boolean;
|
|
11
|
+
enableSkillCommands?: boolean;
|
|
12
|
+
workflow?: {
|
|
13
|
+
lastSpecSlug?: string;
|
|
14
|
+
lastPlanSlug?: string;
|
|
15
|
+
};
|
|
16
|
+
[key: string]: unknown;
|
|
17
17
|
};
|
|
18
18
|
/** Create `.kubbisec/specs`, `.kubbisec/plans`, `.kubbisec/context` (ART-003). */
|
|
19
19
|
export declare function ensureKubbisecProjectLayout(cwd: string): void;
|
|
@@ -26,4 +26,4 @@ export declare function ensurePiProjectSettings(cwd?: string): string;
|
|
|
26
26
|
export declare function ensurePiProjectTheme(cwd?: string): string;
|
|
27
27
|
/** KubbiSec project settings used when starting the chat runtime. */
|
|
28
28
|
export declare function ensureKubbisecChatProjectSettings(cwd?: string): void;
|
|
29
|
-
//# sourceMappingURL=ensure-kubbisec-project-settings.d.ts.map
|
|
29
|
+
//# sourceMappingURL=ensure-kubbisec-project-settings.d.ts.map
|
|
@@ -10,74 +10,70 @@ export const KUBBISEC_SPECS_DIR = "specs";
|
|
|
10
10
|
export const KUBBISEC_PLANS_DIR = "plans";
|
|
11
11
|
export const KUBBISEC_CONTEXT_DIR = "context";
|
|
12
12
|
function migrateLegacyProjectConfigDir(cwd) {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
return;
|
|
19
|
-
fs.renameSync(legacy, next);
|
|
13
|
+
const legacy = path.join(cwd, ".kubbisec");
|
|
14
|
+
const next = path.join(cwd, KUBBISEC_PROJECT_CONFIG_DIR);
|
|
15
|
+
if (!pathExists(legacy)) return;
|
|
16
|
+
if (pathExists(next)) return;
|
|
17
|
+
fs.renameSync(legacy, next);
|
|
20
18
|
}
|
|
21
19
|
function pathExists(p) {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
}
|
|
20
|
+
try {
|
|
21
|
+
fs.accessSync(p);
|
|
22
|
+
return true;
|
|
23
|
+
} catch {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
29
26
|
}
|
|
30
27
|
/** Create `.kubbisec/specs`, `.kubbisec/plans`, `.kubbisec/context` (ART-003). */
|
|
31
28
|
export function ensureKubbisecProjectLayout(cwd) {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
29
|
+
const base = path.join(cwd, KUBBISEC_PROJECT_CONFIG_DIR);
|
|
30
|
+
for (const sub of [KUBBISEC_SPECS_DIR, KUBBISEC_PLANS_DIR, KUBBISEC_CONTEXT_DIR]) {
|
|
31
|
+
fs.mkdirSync(path.join(base, sub), { recursive: true, mode: 0o755 });
|
|
32
|
+
}
|
|
36
33
|
}
|
|
37
34
|
export function resolveKubbisecProjectSettingsPath(cwd) {
|
|
38
|
-
|
|
35
|
+
return path.join(cwd, KUBBISEC_PROJECT_CONFIG_DIR, KUBBISEC_PROJECT_SETTINGS_FILE);
|
|
39
36
|
}
|
|
40
37
|
function readExistingSettings(filePath) {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
catch {
|
|
49
|
-
/* missing or invalid — start fresh */
|
|
38
|
+
try {
|
|
39
|
+
const raw = fs.readFileSync(filePath, "utf8");
|
|
40
|
+
const parsed = JSON.parse(raw);
|
|
41
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
42
|
+
return parsed;
|
|
50
43
|
}
|
|
51
|
-
|
|
44
|
+
} catch {
|
|
45
|
+
/* missing or invalid — start fresh */
|
|
46
|
+
}
|
|
47
|
+
return {};
|
|
52
48
|
}
|
|
53
49
|
/** Merge KubbiSec defaults into `<cwd>/.kubbisec/settings.json` without removing user keys. */
|
|
54
50
|
export function ensureKubbisecProjectSettings(cwd = process.cwd()) {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
51
|
+
migrateLegacyProjectConfigDir(cwd);
|
|
52
|
+
const dir = path.join(cwd, KUBBISEC_PROJECT_CONFIG_DIR);
|
|
53
|
+
const filePath = resolveKubbisecProjectSettingsPath(cwd);
|
|
54
|
+
fs.mkdirSync(dir, { recursive: true, mode: 0o755 });
|
|
55
|
+
ensureKubbisecProjectLayout(cwd);
|
|
56
|
+
const existing = readExistingSettings(filePath);
|
|
57
|
+
const merged = {
|
|
58
|
+
...existing,
|
|
59
|
+
theme: KUBBISEC_THEME_NAME,
|
|
60
|
+
quietStartup: true,
|
|
61
|
+
enableSkillCommands: false,
|
|
62
|
+
};
|
|
63
|
+
fs.writeFileSync(filePath, `${JSON.stringify(merged, null, 2)}\n`, "utf8");
|
|
64
|
+
return filePath;
|
|
69
65
|
}
|
|
70
66
|
/** @deprecated Use ensureKubbisecProjectSettings */
|
|
71
67
|
export function ensurePiProjectSettings(cwd = process.cwd()) {
|
|
72
|
-
|
|
68
|
+
return ensureKubbisecProjectSettings(cwd);
|
|
73
69
|
}
|
|
74
70
|
/** @deprecated Use ensureKubbisecProjectSettings */
|
|
75
71
|
export function ensurePiProjectTheme(cwd = process.cwd()) {
|
|
76
|
-
|
|
72
|
+
return ensureKubbisecProjectSettings(cwd);
|
|
77
73
|
}
|
|
78
74
|
/** KubbiSec project settings used when starting the chat runtime. */
|
|
79
75
|
export function ensureKubbisecChatProjectSettings(cwd = process.cwd()) {
|
|
80
|
-
|
|
81
|
-
|
|
76
|
+
ensureKubbisecProjectSettings(cwd);
|
|
77
|
+
applyLlmConfigToAgentSettings(cwd);
|
|
82
78
|
}
|
|
83
|
-
//# sourceMappingURL=ensure-kubbisec-project-settings.js.map
|
|
79
|
+
//# sourceMappingURL=ensure-kubbisec-project-settings.js.map
|