@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.
Files changed (109) hide show
  1. package/bin/kubbisec +0 -0
  2. package/bundled/components/kubbisec-model-selector.d.ts +47 -34
  3. package/bundled/components/kubbisec-model-selector.js +187 -177
  4. package/bundled/config/config.d.ts +6 -6
  5. package/bundled/config/config.js +54 -52
  6. package/bundled/config/detect-local-llm-providers.d.ts +26 -16
  7. package/bundled/config/detect-local-llm-providers.js +130 -142
  8. package/bundled/config/ensure-kbs-project-settings.d.ts +8 -8
  9. package/bundled/config/ensure-kbs-project-settings.js +27 -28
  10. package/bundled/config/ensure-kubbisec-project-settings.d.ts +9 -9
  11. package/bundled/config/ensure-kubbisec-project-settings.js +62 -67
  12. package/bundled/config/extended-context.d.ts +5 -6
  13. package/bundled/config/extended-context.js +23 -22
  14. package/bundled/config/feature-flags.d.ts +10 -2
  15. package/bundled/config/feature-flags.js +8 -2
  16. package/bundled/config/format-kubbisec-footer-status.d.ts +1 -1
  17. package/bundled/config/format-kubbisec-footer-status.js +26 -31
  18. package/bundled/config/kubbisec-extension-manifest.d.ts +21 -2
  19. package/bundled/config/kubbisec-extension-manifest.js +19 -19
  20. package/bundled/config/llm-config-mutations.d.ts +51 -25
  21. package/bundled/config/llm-config-mutations.js +173 -182
  22. package/bundled/config/llm-config.d.ts +54 -41
  23. package/bundled/config/llm-config.js +199 -199
  24. package/bundled/config/llm-provider-catalog.d.ts +18 -15
  25. package/bundled/config/llm-provider-catalog.js +45 -46
  26. package/bundled/config/materialize-kubbisec-pi-resources.d.ts +1 -1
  27. package/bundled/config/materialize-kubbisec-pi-resources.js +173 -182
  28. package/bundled/config/register-custom-llm-providers.d.ts +11 -5
  29. package/bundled/config/register-custom-llm-providers.js +17 -15
  30. package/bundled/config/register-kubbisec-llm-provider.d.ts +14 -10
  31. package/bundled/config/register-kubbisec-llm-provider.js +50 -42
  32. package/bundled/config/resolve-agents-context-file.d.ts +1 -1
  33. package/bundled/config/resolve-agents-context-file.js +33 -34
  34. package/bundled/config/resource-budget.d.ts +12 -12
  35. package/bundled/config/resource-budget.js +28 -28
  36. package/bundled/config/sync-kubbisec-pi-models.d.ts +6 -3
  37. package/bundled/config/sync-kubbisec-pi-models.js +58 -58
  38. package/bundled/copy/cli-reference-index.d.ts +1 -1
  39. package/bundled/copy/cli-reference-index.js +1 -1
  40. package/bundled/copy/kubbisec-shell-copy.d.ts +11 -6
  41. package/bundled/copy/kubbisec-shell-copy.js +1 -1
  42. package/bundled/extensions/cli-local-shared.d.ts +56 -32
  43. package/bundled/extensions/cli-local-shared.js +135 -125
  44. package/bundled/extensions/kubbisec-aspm-local.extension.d.ts +18 -15
  45. package/bundled/extensions/kubbisec-aspm-local.extension.js +109 -106
  46. package/bundled/extensions/kubbisec-brand.extension.d.ts +1 -1
  47. package/bundled/extensions/kubbisec-brand.extension.js +25 -25
  48. package/bundled/extensions/kubbisec-byok-provider.extension.d.ts +1 -1
  49. package/bundled/extensions/kubbisec-byok-provider.extension.js +2 -2
  50. package/bundled/extensions/kubbisec-clarify.extension.d.ts +64 -35
  51. package/bundled/extensions/kubbisec-clarify.extension.js +323 -305
  52. package/bundled/extensions/kubbisec-exit.extension.d.ts +1 -1
  53. package/bundled/extensions/kubbisec-exit.extension.js +29 -32
  54. package/bundled/extensions/kubbisec-extended-context.extension.d.ts +1 -1
  55. package/bundled/extensions/kubbisec-extended-context.extension.js +56 -43
  56. package/bundled/extensions/kubbisec-footer.extension.d.ts +14 -14
  57. package/bundled/extensions/kubbisec-footer.extension.js +205 -215
  58. package/bundled/extensions/kubbisec-github-local.extension.d.ts +26 -18
  59. package/bundled/extensions/kubbisec-github-local.extension.js +430 -417
  60. package/bundled/extensions/kubbisec-llm-config.extension.d.ts +1 -1
  61. package/bundled/extensions/kubbisec-llm-config.extension.js +200 -181
  62. package/bundled/extensions/kubbisec-memory.extension.d.ts +9 -7
  63. package/bundled/extensions/kubbisec-memory.extension.js +88 -95
  64. package/bundled/extensions/kubbisec-naus-local.extension.d.ts +18 -15
  65. package/bundled/extensions/kubbisec-naus-local.extension.js +123 -103
  66. package/bundled/extensions/kubbisec-platform-tools.extension.d.ts +31 -21
  67. package/bundled/extensions/kubbisec-platform-tools.extension.js +152 -152
  68. package/bundled/extensions/kubbisec-runtime-status.extension.d.ts +10 -8
  69. package/bundled/extensions/kubbisec-runtime-status.extension.js +15 -13
  70. package/bundled/extensions/kubbisec-scope.extension.d.ts +12 -7
  71. package/bundled/extensions/kubbisec-scope.extension.js +13 -13
  72. package/bundled/extensions/kubbisec-skill-mentions.extension.d.ts +27 -16
  73. package/bundled/extensions/kubbisec-skill-mentions.extension.js +74 -64
  74. package/bundled/extensions/kubbisec-skill-telemetry.extension.d.ts +2 -3
  75. package/bundled/extensions/kubbisec-skill-telemetry.extension.js +59 -64
  76. package/bundled/extensions/kubbisec-theme-lock.extension.d.ts +1 -1
  77. package/bundled/extensions/kubbisec-theme-lock.extension.js +33 -34
  78. package/bundled/extensions/kubbisec-ui.extension.d.ts +1 -1
  79. package/bundled/extensions/kubbisec-ui.extension.js +90 -92
  80. package/bundled/extensions/kubbisec-workflow.extension.d.ts +20 -18
  81. package/bundled/extensions/kubbisec-workflow.extension.js +138 -140
  82. package/bundled/resolve-bundled-dist-root.js +121 -130
  83. package/bundled/skills/at-path-mentions.d.ts +1 -1
  84. package/bundled/skills/at-path-mentions.js +146 -153
  85. package/bundled/skills/chat-mention-render.d.ts +2 -2
  86. package/bundled/skills/chat-mention-render.js +121 -126
  87. package/bundled/skills/chat-mentions.d.ts +17 -8
  88. package/bundled/skills/chat-mentions.js +76 -76
  89. package/bundled/skills/list-bundled-skills.d.ts +3 -3
  90. package/bundled/skills/list-bundled-skills.js +33 -35
  91. package/bundled/skills/skill-mention.d.ts +10 -2
  92. package/bundled/skills/skill-mention.js +10 -2
  93. package/bundled/theme/clear-terminal.d.ts +1 -1
  94. package/bundled/theme/clear-terminal.js +3 -4
  95. package/bundled/theme/footer-render-hook.d.ts +1 -1
  96. package/bundled/theme/footer-render-hook.js +3 -3
  97. package/bundled/theme/kubbisec-brand-fg.d.ts +1 -1
  98. package/bundled/theme/kubbisec-brand-fg.js +2 -2
  99. package/bundled/theme/kubbisec-menu-themes.d.ts +7 -7
  100. package/bundled/theme/kubbisec-menu-themes.js +30 -31
  101. package/bundled/theme/kubbisec-theme-name.d.ts +1 -1
  102. package/bundled/theme/kubbisec-theme-name.js +1 -1
  103. package/bundled/theme/patch-pi-settings-theme.runtime.d.ts +1 -1
  104. package/bundled/theme/patch-pi-settings-theme.runtime.js +11 -10
  105. package/bundled/theme/render-compact-header.d.ts +13 -5
  106. package/bundled/theme/render-compact-header.js +126 -128
  107. package/bundled/workflow/session-workflow-mode.d.ts +1 -1
  108. package/bundled/workflow/session-workflow-mode.js +33 -33
  109. 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
- fg: (role: string, text: string) => string;
6
+ fg: (role: string, text: string) => string;
6
7
  };
7
8
  export type KubbisecModelGroup = {
8
- provider: string;
9
- displayName: string;
10
- models: KubbisecModel[];
9
+ provider: string;
10
+ displayName: string;
11
+ models: KubbisecModel[];
11
12
  };
12
- export type KubbisecModelListItem = {
13
- kind: "header";
14
- provider: string;
15
- label: string;
16
- } | {
17
- kind: "model";
18
- provider: string;
19
- model: KubbisecModel;
20
- };
21
- export declare function groupModelsForSelector(models: KubbisecModel[], getProviderDisplayName: (provider: string) => string): KubbisecModelGroup[];
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
- private theme;
25
- private onSelect;
26
- private onCancel;
27
- private searchInput;
28
- private listContainer;
29
- private allItems;
30
- private filteredItems;
31
- private selectableIndexes;
32
- private selectedIndex;
33
- private currentModel?;
34
- private _focused;
35
- get focused(): boolean;
36
- set focused(value: boolean);
37
- constructor(_tui: TUI, currentModel: KubbisecModel | undefined, groups: KubbisecModelGroup[], theme: KubbisecTheme, onSelect: (model: KubbisecModel) => void, onCancel: () => void, initialSearch?: string);
38
- getSearchInput(): Input;
39
- private filterModels;
40
- private renderList;
41
- handleInput(keyData: string): void;
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
- export {};
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
- 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")
13
- return 0;
14
- if (provider === "ollama")
15
- return 1;
16
- if (provider === "lmstudio")
17
- return 2;
18
- return 10;
19
- };
20
- const providers = [...byProvider.keys()].sort((a, b) => {
21
- const rankDiff = providerRank(a) - providerRank(b);
22
- if (rankDiff !== 0)
23
- return rankDiff;
24
- return getProviderDisplayName(a).localeCompare(getProviderDisplayName(b));
25
- });
26
- return providers.map((provider) => ({
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
- const items = [];
34
- for (const group of groups) {
35
- items.push({ kind: "header", provider: group.provider, label: group.displayName });
36
- for (const model of group.models) {
37
- items.push({ kind: "model", provider: group.provider, model });
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
- return items;
35
+ }
36
+ return items;
41
37
  }
42
38
  function fuzzyMatch(query, model, providerLabel) {
43
- const haystack = `${model.id} ${model.name} ${model.provider} ${providerLabel}`.toLowerCase();
44
- const tokens = query.toLowerCase().split(/\s+/).filter(Boolean);
45
- return tokens.every((token) => haystack.includes(token));
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
- theme;
49
- onSelect;
50
- onCancel;
51
- searchInput;
52
- listContainer = new Container();
53
- allItems = [];
54
- filteredItems = [];
55
- selectableIndexes = [];
56
- selectedIndex = 0;
57
- currentModel;
58
- _focused = false;
59
- get focused() {
60
- return this._focused;
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
- set focused(value) {
63
- this._focused = value;
64
- this.searchInput.focused = value;
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
- constructor(_tui, currentModel, groups, theme, onSelect, onCancel, initialSearch = "") {
67
- super();
68
- this.theme = theme;
69
- this.onSelect = onSelect;
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
- getSearchInput() {
96
- return this.searchInput;
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
- filterModels(query) {
99
- const trimmed = query.trim();
100
- if (!trimmed) {
101
- this.filteredItems = this.allItems;
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
- renderList() {
133
- this.listContainer.clear();
134
- const maxVisible = 12;
135
- const start = Math.max(0, Math.min(this.selectedIndex - Math.floor(maxVisible / 2), Math.max(0, this.selectableIndexes.length - maxVisible)));
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")
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
- handleInput(keyData) {
166
- const kb = getKeybindings();
167
- if (kb.matches(keyData, "tui.select.up")) {
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
- if (!a || !b)
195
- return false;
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
- apiUrl: string;
3
- apiKey: string;
4
- orgId?: string;
5
- defaultProject?: string;
6
- clientId?: string;
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
@@ -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 { DEFAULT_KUBBISEC_API_URL, getAiStateDir, getKubbisecConfigPath, resolveKubbisecApiUrl, } from "@kubbisec/home";
4
+ import {
5
+ DEFAULT_KUBBISEC_API_URL,
6
+ getAiStateDir,
7
+ getKubbisecConfigPath,
8
+ resolveKubbisecApiUrl,
9
+ } from "@kubbisec/home";
5
10
  export function getKubbisecStateDir() {
6
- return getAiStateDir();
11
+ return getAiStateDir();
7
12
  }
8
13
  export function getConfigPath() {
9
- return getKubbisecConfigPath();
14
+ return getKubbisecConfigPath();
10
15
  }
11
16
  export function loadConfig() {
12
- const stateDir = getAiStateDir();
13
- const candidates = [getKubbisecConfigPath(), path.join(stateDir, "kbs.json")];
14
- for (const configFile of candidates) {
15
- try {
16
- if (!fs.existsSync(configFile))
17
- continue;
18
- return JSON.parse(fs.readFileSync(configFile, "utf8"));
19
- }
20
- catch { }
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
- const prev = loadConfig();
26
- const next = {
27
- apiUrl: resolveKubbisecApiUrl(partial.apiUrl ?? prev.apiUrl),
28
- apiKey: partial.apiKey ?? prev.apiKey ?? "",
29
- orgId: partial.orgId ?? prev.orgId,
30
- defaultProject: partial.defaultProject ?? prev.defaultProject,
31
- clientId: partial.clientId ?? prev.clientId ?? `kubbisec-${os.hostname()}`,
32
- };
33
- const stateDir = getAiStateDir();
34
- fs.mkdirSync(stateDir, { recursive: true, mode: 0o700 });
35
- const persisted = {
36
- apiKey: next.apiKey,
37
- orgId: next.orgId,
38
- defaultProject: next.defaultProject,
39
- clientId: next.clientId,
40
- };
41
- if (next.apiUrl !== DEFAULT_KUBBISEC_API_URL) {
42
- persisted.apiUrl = next.apiUrl;
43
- }
44
- fs.writeFileSync(getKubbisecConfigPath(), `${JSON.stringify(persisted, null, 2)}\n`, {
45
- mode: 0o600,
46
- });
47
- return next;
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
- const configFile = getKubbisecConfigPath();
51
- if (fs.existsSync(configFile))
52
- fs.unlinkSync(configFile);
53
+ const configFile = getKubbisecConfigPath();
54
+ if (fs.existsSync(configFile)) fs.unlinkSync(configFile);
53
55
  }
54
56
  export function requireConfig() {
55
- const cfg = loadConfig();
56
- if (!cfg.apiKey?.trim()) {
57
- throw new Error("Not logged in. Run: kubbisec login");
58
- }
59
- return {
60
- apiUrl: resolveKubbisecApiUrl(cfg.apiUrl),
61
- apiKey: cfg.apiKey.trim(),
62
- orgId: cfg.orgId?.trim() || undefined,
63
- defaultProject: cfg.defaultProject?.trim() || undefined,
64
- clientId: cfg.clientId?.trim() || `kubbisec-${os.hostname()}`,
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