@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
package/bin/kubbisec
CHANGED
|
Binary file
|
|
@@ -1,44 +1,57 @@
|
|
|
1
1
|
import type { Api, Model } from "@earendil-works/pi-ai";
|
|
2
2
|
import { Container, Input, type TUI } from "@earendil-works/pi-tui";
|
|
3
|
+
|
|
3
4
|
type KubbisecModel = Model<Api>;
|
|
4
5
|
type KubbisecTheme = {
|
|
5
|
-
|
|
6
|
+
fg: (role: string, text: string) => string;
|
|
6
7
|
};
|
|
7
8
|
export type KubbisecModelGroup = {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
provider: string;
|
|
10
|
+
displayName: string;
|
|
11
|
+
models: KubbisecModel[];
|
|
11
12
|
};
|
|
12
|
-
export type KubbisecModelListItem =
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
13
|
+
export type KubbisecModelListItem =
|
|
14
|
+
| {
|
|
15
|
+
kind: "header";
|
|
16
|
+
provider: string;
|
|
17
|
+
label: string;
|
|
18
|
+
}
|
|
19
|
+
| {
|
|
20
|
+
kind: "model";
|
|
21
|
+
provider: string;
|
|
22
|
+
model: KubbisecModel;
|
|
23
|
+
};
|
|
24
|
+
export declare function groupModelsForSelector(
|
|
25
|
+
models: KubbisecModel[],
|
|
26
|
+
getProviderDisplayName: (provider: string) => string,
|
|
27
|
+
): KubbisecModelGroup[];
|
|
22
28
|
export declare function flattenGroupedModels(groups: KubbisecModelGroup[]): KubbisecModelListItem[];
|
|
23
29
|
export declare class KubbisecModelSelectorComponent extends Container {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
30
|
+
private theme;
|
|
31
|
+
private onSelect;
|
|
32
|
+
private onCancel;
|
|
33
|
+
private searchInput;
|
|
34
|
+
private listContainer;
|
|
35
|
+
private allItems;
|
|
36
|
+
private filteredItems;
|
|
37
|
+
private selectableIndexes;
|
|
38
|
+
private selectedIndex;
|
|
39
|
+
private currentModel?;
|
|
40
|
+
private _focused;
|
|
41
|
+
get focused(): boolean;
|
|
42
|
+
set focused(value: boolean);
|
|
43
|
+
constructor(
|
|
44
|
+
_tui: TUI,
|
|
45
|
+
currentModel: KubbisecModel | undefined,
|
|
46
|
+
groups: KubbisecModelGroup[],
|
|
47
|
+
theme: KubbisecTheme,
|
|
48
|
+
onSelect: (model: KubbisecModel) => void,
|
|
49
|
+
onCancel: () => void,
|
|
50
|
+
initialSearch?: string,
|
|
51
|
+
);
|
|
52
|
+
getSearchInput(): Input;
|
|
53
|
+
private filterModels;
|
|
54
|
+
private renderList;
|
|
55
|
+
handleInput(keyData: string): void;
|
|
42
56
|
}
|
|
43
|
-
|
|
44
|
-
//# sourceMappingURL=kubbisec-model-selector.d.ts.map
|
|
57
|
+
//# sourceMappingURL=kubbisec-model-selector.d.ts.map
|
|
@@ -2,197 +2,207 @@ import { DynamicBorder } from "@earendil-works/pi-coding-agent";
|
|
|
2
2
|
import { Container, getKeybindings, Input, Spacer, Text } from "@earendil-works/pi-tui";
|
|
3
3
|
import { kubbisecBrandFg } from "../theme/kubbisec-brand-fg.js";
|
|
4
4
|
export function groupModelsForSelector(models, getProviderDisplayName) {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
provider,
|
|
28
|
-
displayName: getProviderDisplayName(provider),
|
|
29
|
-
models: (byProvider.get(provider) ?? []).sort((a, b) => a.name.localeCompare(b.name)),
|
|
30
|
-
}));
|
|
5
|
+
const byProvider = new Map();
|
|
6
|
+
for (const model of models) {
|
|
7
|
+
const list = byProvider.get(model.provider) ?? [];
|
|
8
|
+
list.push(model);
|
|
9
|
+
byProvider.set(model.provider, list);
|
|
10
|
+
}
|
|
11
|
+
const providerRank = (provider) => {
|
|
12
|
+
if (provider === "kubbisec") return 0;
|
|
13
|
+
if (provider === "ollama") return 1;
|
|
14
|
+
if (provider === "lmstudio") return 2;
|
|
15
|
+
return 10;
|
|
16
|
+
};
|
|
17
|
+
const providers = [...byProvider.keys()].sort((a, b) => {
|
|
18
|
+
const rankDiff = providerRank(a) - providerRank(b);
|
|
19
|
+
if (rankDiff !== 0) return rankDiff;
|
|
20
|
+
return getProviderDisplayName(a).localeCompare(getProviderDisplayName(b));
|
|
21
|
+
});
|
|
22
|
+
return providers.map((provider) => ({
|
|
23
|
+
provider,
|
|
24
|
+
displayName: getProviderDisplayName(provider),
|
|
25
|
+
models: (byProvider.get(provider) ?? []).sort((a, b) => a.name.localeCompare(b.name)),
|
|
26
|
+
}));
|
|
31
27
|
}
|
|
32
28
|
export function flattenGroupedModels(groups) {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
}
|
|
29
|
+
const items = [];
|
|
30
|
+
for (const group of groups) {
|
|
31
|
+
items.push({ kind: "header", provider: group.provider, label: group.displayName });
|
|
32
|
+
for (const model of group.models) {
|
|
33
|
+
items.push({ kind: "model", provider: group.provider, model });
|
|
39
34
|
}
|
|
40
|
-
|
|
35
|
+
}
|
|
36
|
+
return items;
|
|
41
37
|
}
|
|
42
38
|
function fuzzyMatch(query, model, providerLabel) {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
39
|
+
const haystack = `${model.id} ${model.name} ${model.provider} ${providerLabel}`.toLowerCase();
|
|
40
|
+
const tokens = query.toLowerCase().split(/\s+/).filter(Boolean);
|
|
41
|
+
return tokens.every((token) => haystack.includes(token));
|
|
46
42
|
}
|
|
47
43
|
export class KubbisecModelSelectorComponent extends Container {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
44
|
+
theme;
|
|
45
|
+
onSelect;
|
|
46
|
+
onCancel;
|
|
47
|
+
searchInput;
|
|
48
|
+
listContainer = new Container();
|
|
49
|
+
allItems = [];
|
|
50
|
+
filteredItems = [];
|
|
51
|
+
selectableIndexes = [];
|
|
52
|
+
selectedIndex = 0;
|
|
53
|
+
currentModel;
|
|
54
|
+
_focused = false;
|
|
55
|
+
get focused() {
|
|
56
|
+
return this._focused;
|
|
57
|
+
}
|
|
58
|
+
set focused(value) {
|
|
59
|
+
this._focused = value;
|
|
60
|
+
this.searchInput.focused = value;
|
|
61
|
+
}
|
|
62
|
+
constructor(_tui, currentModel, groups, theme, onSelect, onCancel, initialSearch = "") {
|
|
63
|
+
super();
|
|
64
|
+
this.theme = theme;
|
|
65
|
+
this.onSelect = onSelect;
|
|
66
|
+
this.onCancel = onCancel;
|
|
67
|
+
this.currentModel = currentModel;
|
|
68
|
+
this.allItems = flattenGroupedModels(groups);
|
|
69
|
+
const borderColor = (text) => this.theme.fg("borderAccent", text);
|
|
70
|
+
this.addChild(new DynamicBorder(borderColor));
|
|
71
|
+
this.addChild(new Spacer(1));
|
|
72
|
+
this.addChild(new Text(kubbisecBrandFg("Selecionar modelo"), 0, 0));
|
|
73
|
+
this.addChild(new Spacer(1));
|
|
74
|
+
this.searchInput = new Input();
|
|
75
|
+
if (initialSearch) this.searchInput.setValue(initialSearch);
|
|
76
|
+
this.searchInput.onSubmit = () => {
|
|
77
|
+
const listIndex = this.selectableIndexes[this.selectedIndex];
|
|
78
|
+
const item = listIndex == null ? undefined : this.filteredItems[listIndex];
|
|
79
|
+
if (item?.kind === "model") {
|
|
80
|
+
this.onSelect(item.model);
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
this.addChild(this.searchInput);
|
|
84
|
+
this.addChild(new Spacer(1));
|
|
85
|
+
this.addChild(this.listContainer);
|
|
86
|
+
this.addChild(new Spacer(1));
|
|
87
|
+
this.addChild(new DynamicBorder(borderColor));
|
|
88
|
+
this.filterModels(initialSearch);
|
|
89
|
+
}
|
|
90
|
+
getSearchInput() {
|
|
91
|
+
return this.searchInput;
|
|
92
|
+
}
|
|
93
|
+
filterModels(query) {
|
|
94
|
+
const trimmed = query.trim();
|
|
95
|
+
if (!trimmed) {
|
|
96
|
+
this.filteredItems = this.allItems;
|
|
97
|
+
} else {
|
|
98
|
+
const visibleProviders = new Set();
|
|
99
|
+
const filtered = [];
|
|
100
|
+
for (const item of this.allItems) {
|
|
101
|
+
if (item.kind === "header") continue;
|
|
102
|
+
const header = this.allItems.find(
|
|
103
|
+
(entry) => entry.kind === "header" && entry.provider === item.provider,
|
|
104
|
+
);
|
|
105
|
+
const providerLabel = header?.kind === "header" ? header.label : item.provider;
|
|
106
|
+
if (fuzzyMatch(trimmed, item.model, providerLabel)) {
|
|
107
|
+
if (!visibleProviders.has(item.provider)) {
|
|
108
|
+
visibleProviders.add(item.provider);
|
|
109
|
+
if (header?.kind === "header") filtered.push(header);
|
|
110
|
+
}
|
|
111
|
+
filtered.push(item);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
this.filteredItems = filtered;
|
|
61
115
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
116
|
+
this.selectableIndexes = this.filteredItems
|
|
117
|
+
.map((item, index) => (item.kind === "model" ? index : -1))
|
|
118
|
+
.filter((index) => index >= 0);
|
|
119
|
+
const currentSelectable = this.selectableIndexes.findIndex((index) => {
|
|
120
|
+
const item = this.filteredItems[index];
|
|
121
|
+
return item?.kind === "model" && modelsEqual(this.currentModel, item.model);
|
|
122
|
+
});
|
|
123
|
+
this.selectedIndex = currentSelectable >= 0 ? currentSelectable : 0;
|
|
124
|
+
this.renderList();
|
|
125
|
+
}
|
|
126
|
+
renderList() {
|
|
127
|
+
this.listContainer.clear();
|
|
128
|
+
const maxVisible = 12;
|
|
129
|
+
const start = Math.max(
|
|
130
|
+
0,
|
|
131
|
+
Math.min(
|
|
132
|
+
this.selectedIndex - Math.floor(maxVisible / 2),
|
|
133
|
+
Math.max(0, this.selectableIndexes.length - maxVisible),
|
|
134
|
+
),
|
|
135
|
+
);
|
|
136
|
+
const end = Math.min(start + maxVisible, this.selectableIndexes.length);
|
|
137
|
+
for (let i = start; i < end; i += 1) {
|
|
138
|
+
const listIndex = this.selectableIndexes[i];
|
|
139
|
+
const item = this.filteredItems[listIndex];
|
|
140
|
+
if (item?.kind !== "model") continue;
|
|
141
|
+
const header = this.filteredItems.find(
|
|
142
|
+
(entry, idx) =>
|
|
143
|
+
idx < listIndex && entry.kind === "header" && entry.provider === item.provider,
|
|
144
|
+
);
|
|
145
|
+
if (
|
|
146
|
+
header?.kind === "header" &&
|
|
147
|
+
(i === start || this.selectableIndexes[i - 1] === undefined)
|
|
148
|
+
) {
|
|
149
|
+
this.listContainer.addChild(
|
|
150
|
+
new Text(this.theme.fg("muted", `── ${header.label} ──`), 0, 0),
|
|
151
|
+
);
|
|
152
|
+
} else if (
|
|
153
|
+
header?.kind === "header" &&
|
|
154
|
+
i > start &&
|
|
155
|
+
this.filteredItems[this.selectableIndexes[i - 1]]?.kind === "model" &&
|
|
156
|
+
this.filteredItems[this.selectableIndexes[i - 1]]?.provider !== item.provider
|
|
157
|
+
) {
|
|
158
|
+
this.listContainer.addChild(
|
|
159
|
+
new Text(this.theme.fg("muted", `── ${header.label} ──`), 0, 0),
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
const isSelected = i === this.selectedIndex;
|
|
163
|
+
const isCurrent = modelsEqual(this.currentModel, item.model);
|
|
164
|
+
const prefix = isSelected ? kubbisecBrandFg("→ ") : " ";
|
|
165
|
+
const name = isSelected ? kubbisecBrandFg(item.model.name) : item.model.name;
|
|
166
|
+
const id = this.theme.fg("muted", ` (${item.model.id})`);
|
|
167
|
+
const check = isCurrent ? kubbisecBrandFg(" ✓") : "";
|
|
168
|
+
this.listContainer.addChild(new Text(`${prefix}${name}${id}${check}`, 0, 0));
|
|
65
169
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
this.theme
|
|
69
|
-
|
|
70
|
-
this.onCancel = onCancel;
|
|
71
|
-
this.currentModel = currentModel;
|
|
72
|
-
this.allItems = flattenGroupedModels(groups);
|
|
73
|
-
const borderColor = (text) => this.theme.fg("borderAccent", text);
|
|
74
|
-
this.addChild(new DynamicBorder(borderColor));
|
|
75
|
-
this.addChild(new Spacer(1));
|
|
76
|
-
this.addChild(new Text(kubbisecBrandFg("Selecionar modelo"), 0, 0));
|
|
77
|
-
this.addChild(new Spacer(1));
|
|
78
|
-
this.searchInput = new Input();
|
|
79
|
-
if (initialSearch)
|
|
80
|
-
this.searchInput.setValue(initialSearch);
|
|
81
|
-
this.searchInput.onSubmit = () => {
|
|
82
|
-
const listIndex = this.selectableIndexes[this.selectedIndex];
|
|
83
|
-
const item = listIndex == null ? undefined : this.filteredItems[listIndex];
|
|
84
|
-
if (item?.kind === "model") {
|
|
85
|
-
this.onSelect(item.model);
|
|
86
|
-
}
|
|
87
|
-
};
|
|
88
|
-
this.addChild(this.searchInput);
|
|
89
|
-
this.addChild(new Spacer(1));
|
|
90
|
-
this.addChild(this.listContainer);
|
|
91
|
-
this.addChild(new Spacer(1));
|
|
92
|
-
this.addChild(new DynamicBorder(borderColor));
|
|
93
|
-
this.filterModels(initialSearch);
|
|
170
|
+
if (this.selectableIndexes.length === 0) {
|
|
171
|
+
this.listContainer.addChild(
|
|
172
|
+
new Text(this.theme.fg("muted", " Nenhum modelo encontrado"), 0, 0),
|
|
173
|
+
);
|
|
94
174
|
}
|
|
95
|
-
|
|
96
|
-
|
|
175
|
+
}
|
|
176
|
+
handleInput(keyData) {
|
|
177
|
+
const kb = getKeybindings();
|
|
178
|
+
if (kb.matches(keyData, "tui.select.up")) {
|
|
179
|
+
this.selectedIndex = Math.max(0, this.selectedIndex - 1);
|
|
180
|
+
this.renderList();
|
|
181
|
+
return;
|
|
97
182
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
}
|
|
103
|
-
else {
|
|
104
|
-
const visibleProviders = new Set();
|
|
105
|
-
const filtered = [];
|
|
106
|
-
for (const item of this.allItems) {
|
|
107
|
-
if (item.kind === "header")
|
|
108
|
-
continue;
|
|
109
|
-
const header = this.allItems.find((entry) => entry.kind === "header" && entry.provider === item.provider);
|
|
110
|
-
const providerLabel = header?.kind === "header" ? header.label : item.provider;
|
|
111
|
-
if (fuzzyMatch(trimmed, item.model, providerLabel)) {
|
|
112
|
-
if (!visibleProviders.has(item.provider)) {
|
|
113
|
-
visibleProviders.add(item.provider);
|
|
114
|
-
if (header?.kind === "header")
|
|
115
|
-
filtered.push(header);
|
|
116
|
-
}
|
|
117
|
-
filtered.push(item);
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
this.filteredItems = filtered;
|
|
121
|
-
}
|
|
122
|
-
this.selectableIndexes = this.filteredItems
|
|
123
|
-
.map((item, index) => (item.kind === "model" ? index : -1))
|
|
124
|
-
.filter((index) => index >= 0);
|
|
125
|
-
const currentSelectable = this.selectableIndexes.findIndex((index) => {
|
|
126
|
-
const item = this.filteredItems[index];
|
|
127
|
-
return item?.kind === "model" && modelsEqual(this.currentModel, item.model);
|
|
128
|
-
});
|
|
129
|
-
this.selectedIndex = currentSelectable >= 0 ? currentSelectable : 0;
|
|
130
|
-
this.renderList();
|
|
183
|
+
if (kb.matches(keyData, "tui.select.down")) {
|
|
184
|
+
this.selectedIndex = Math.min(this.selectableIndexes.length - 1, this.selectedIndex + 1);
|
|
185
|
+
this.renderList();
|
|
186
|
+
return;
|
|
131
187
|
}
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
const item = this.filteredItems[listIndex];
|
|
140
|
-
if (item?.kind !== "model")
|
|
141
|
-
continue;
|
|
142
|
-
const header = this.filteredItems.find((entry, idx) => idx < listIndex && entry.kind === "header" && entry.provider === item.provider);
|
|
143
|
-
if (header?.kind === "header" &&
|
|
144
|
-
(i === start || this.selectableIndexes[i - 1] === undefined)) {
|
|
145
|
-
this.listContainer.addChild(new Text(this.theme.fg("muted", `── ${header.label} ──`), 0, 0));
|
|
146
|
-
}
|
|
147
|
-
else if (header?.kind === "header" &&
|
|
148
|
-
i > start &&
|
|
149
|
-
this.filteredItems[this.selectableIndexes[i - 1]]?.kind === "model" &&
|
|
150
|
-
this.filteredItems[this.selectableIndexes[i - 1]]?.provider !== item.provider) {
|
|
151
|
-
this.listContainer.addChild(new Text(this.theme.fg("muted", `── ${header.label} ──`), 0, 0));
|
|
152
|
-
}
|
|
153
|
-
const isSelected = i === this.selectedIndex;
|
|
154
|
-
const isCurrent = modelsEqual(this.currentModel, item.model);
|
|
155
|
-
const prefix = isSelected ? kubbisecBrandFg("→ ") : " ";
|
|
156
|
-
const name = isSelected ? kubbisecBrandFg(item.model.name) : item.model.name;
|
|
157
|
-
const id = this.theme.fg("muted", ` (${item.model.id})`);
|
|
158
|
-
const check = isCurrent ? kubbisecBrandFg(" ✓") : "";
|
|
159
|
-
this.listContainer.addChild(new Text(`${prefix}${name}${id}${check}`, 0, 0));
|
|
160
|
-
}
|
|
161
|
-
if (this.selectableIndexes.length === 0) {
|
|
162
|
-
this.listContainer.addChild(new Text(this.theme.fg("muted", " Nenhum modelo encontrado"), 0, 0));
|
|
163
|
-
}
|
|
188
|
+
if (kb.matches(keyData, "tui.select.confirm")) {
|
|
189
|
+
const listIndex = this.selectableIndexes[this.selectedIndex];
|
|
190
|
+
const item = listIndex == null ? undefined : this.filteredItems[listIndex];
|
|
191
|
+
if (item?.kind === "model") {
|
|
192
|
+
this.onSelect(item.model);
|
|
193
|
+
}
|
|
194
|
+
return;
|
|
164
195
|
}
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
this.selectedIndex = Math.max(0, this.selectedIndex - 1);
|
|
169
|
-
this.renderList();
|
|
170
|
-
return;
|
|
171
|
-
}
|
|
172
|
-
if (kb.matches(keyData, "tui.select.down")) {
|
|
173
|
-
this.selectedIndex = Math.min(this.selectableIndexes.length - 1, this.selectedIndex + 1);
|
|
174
|
-
this.renderList();
|
|
175
|
-
return;
|
|
176
|
-
}
|
|
177
|
-
if (kb.matches(keyData, "tui.select.confirm")) {
|
|
178
|
-
const listIndex = this.selectableIndexes[this.selectedIndex];
|
|
179
|
-
const item = listIndex == null ? undefined : this.filteredItems[listIndex];
|
|
180
|
-
if (item?.kind === "model") {
|
|
181
|
-
this.onSelect(item.model);
|
|
182
|
-
}
|
|
183
|
-
return;
|
|
184
|
-
}
|
|
185
|
-
if (kb.matches(keyData, "tui.select.cancel")) {
|
|
186
|
-
this.onCancel();
|
|
187
|
-
return;
|
|
188
|
-
}
|
|
189
|
-
this.searchInput.handleInput(keyData);
|
|
190
|
-
this.filterModels(this.searchInput.getValue());
|
|
196
|
+
if (kb.matches(keyData, "tui.select.cancel")) {
|
|
197
|
+
this.onCancel();
|
|
198
|
+
return;
|
|
191
199
|
}
|
|
200
|
+
this.searchInput.handleInput(keyData);
|
|
201
|
+
this.filterModels(this.searchInput.getValue());
|
|
202
|
+
}
|
|
192
203
|
}
|
|
193
204
|
function modelsEqual(a, b) {
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
return a.provider === b.provider && a.id === b.id;
|
|
205
|
+
if (!a || !b) return false;
|
|
206
|
+
return a.provider === b.provider && a.id === b.id;
|
|
197
207
|
}
|
|
198
|
-
//# sourceMappingURL=kubbisec-model-selector.js.map
|
|
208
|
+
//# sourceMappingURL=kubbisec-model-selector.js.map
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
export type KubbisecConfig = {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
apiUrl: string;
|
|
3
|
+
apiKey: string;
|
|
4
|
+
orgId?: string;
|
|
5
|
+
defaultProject?: string;
|
|
6
|
+
clientId?: string;
|
|
7
7
|
};
|
|
8
8
|
export declare function getKubbisecStateDir(): string;
|
|
9
9
|
export declare function getConfigPath(): string;
|
|
@@ -11,4 +11,4 @@ export declare function loadConfig(): Partial<KubbisecConfig>;
|
|
|
11
11
|
export declare function saveConfig(partial: Partial<KubbisecConfig>): KubbisecConfig;
|
|
12
12
|
export declare function clearConfig(): void;
|
|
13
13
|
export declare function requireConfig(): KubbisecConfig;
|
|
14
|
-
//# sourceMappingURL=config.d.ts.map
|
|
14
|
+
//# sourceMappingURL=config.d.ts.map
|
package/bundled/config/config.js
CHANGED
|
@@ -1,67 +1,69 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
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
|
-
}
|
|
22
|
-
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 {};
|
|
23
26
|
}
|
|
24
27
|
export function saveConfig(partial) {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
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;
|
|
48
51
|
}
|
|
49
52
|
export function clearConfig() {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
fs.unlinkSync(configFile);
|
|
53
|
+
const configFile = getKubbisecConfigPath();
|
|
54
|
+
if (fs.existsSync(configFile)) fs.unlinkSync(configFile);
|
|
53
55
|
}
|
|
54
56
|
export function requireConfig() {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
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
|
+
};
|
|
66
68
|
}
|
|
67
|
-
//# sourceMappingURL=config.js.map
|
|
69
|
+
//# sourceMappingURL=config.js.map
|