@sheepbun/yips 0.1.1

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 (99) hide show
  1. package/dist/agent/commands/command-catalog.js +243 -0
  2. package/dist/agent/commands/commands.js +418 -0
  3. package/dist/agent/conductor.js +118 -0
  4. package/dist/agent/context/code-context.js +68 -0
  5. package/dist/agent/context/memory-store.js +159 -0
  6. package/dist/agent/context/session-store.js +211 -0
  7. package/dist/agent/protocol/tool-protocol.js +160 -0
  8. package/dist/agent/skills/skills.js +327 -0
  9. package/dist/agent/tools/tool-executor.js +415 -0
  10. package/dist/agent/tools/tool-safety.js +52 -0
  11. package/dist/app/index.js +35 -0
  12. package/dist/app/repl.js +105 -0
  13. package/dist/app/update-check.js +132 -0
  14. package/dist/app/version.js +51 -0
  15. package/dist/code-context.js +68 -0
  16. package/dist/colors.js +204 -0
  17. package/dist/command-catalog.js +242 -0
  18. package/dist/commands.js +350 -0
  19. package/dist/conductor.js +94 -0
  20. package/dist/config/config.js +335 -0
  21. package/dist/config/hooks.js +187 -0
  22. package/dist/config.js +335 -0
  23. package/dist/downloader-state.js +302 -0
  24. package/dist/downloader-ui.js +289 -0
  25. package/dist/gateway/adapters/discord.js +108 -0
  26. package/dist/gateway/adapters/formatting.js +96 -0
  27. package/dist/gateway/adapters/telegram.js +106 -0
  28. package/dist/gateway/adapters/types.js +2 -0
  29. package/dist/gateway/adapters/whatsapp.js +124 -0
  30. package/dist/gateway/auth-policy.js +66 -0
  31. package/dist/gateway/core.js +87 -0
  32. package/dist/gateway/headless-conductor.js +328 -0
  33. package/dist/gateway/message-router.js +23 -0
  34. package/dist/gateway/rate-limiter.js +48 -0
  35. package/dist/gateway/runtime/backend-policy.js +18 -0
  36. package/dist/gateway/runtime/discord-bot.js +104 -0
  37. package/dist/gateway/runtime/discord-main.js +69 -0
  38. package/dist/gateway/session-manager.js +77 -0
  39. package/dist/gateway/types.js +2 -0
  40. package/dist/hardware.js +92 -0
  41. package/dist/hooks.js +187 -0
  42. package/dist/index.js +34 -0
  43. package/dist/input-engine.js +250 -0
  44. package/dist/llama-client.js +227 -0
  45. package/dist/llama-server.js +620 -0
  46. package/dist/llm/llama-client.js +227 -0
  47. package/dist/llm/llama-server.js +620 -0
  48. package/dist/llm/token-counter.js +47 -0
  49. package/dist/memory-store.js +159 -0
  50. package/dist/messages.js +59 -0
  51. package/dist/model-downloader.js +382 -0
  52. package/dist/model-manager-state.js +118 -0
  53. package/dist/model-manager-ui.js +194 -0
  54. package/dist/model-manager.js +190 -0
  55. package/dist/models/hardware.js +92 -0
  56. package/dist/models/model-downloader.js +382 -0
  57. package/dist/models/model-manager.js +190 -0
  58. package/dist/prompt-box.js +78 -0
  59. package/dist/prompt-composer.js +498 -0
  60. package/dist/repl.js +105 -0
  61. package/dist/session-store.js +211 -0
  62. package/dist/spinner.js +76 -0
  63. package/dist/title-box.js +388 -0
  64. package/dist/token-counter.js +47 -0
  65. package/dist/tool-executor.js +415 -0
  66. package/dist/tool-protocol.js +121 -0
  67. package/dist/tool-safety.js +52 -0
  68. package/dist/tui/app.js +2553 -0
  69. package/dist/tui/startup.js +56 -0
  70. package/dist/tui-input-routing.js +53 -0
  71. package/dist/tui.js +51 -0
  72. package/dist/types/app-types.js +2 -0
  73. package/dist/types.js +2 -0
  74. package/dist/ui/colors.js +204 -0
  75. package/dist/ui/downloader/downloader-state.js +302 -0
  76. package/dist/ui/downloader/downloader-ui.js +289 -0
  77. package/dist/ui/input/input-engine.js +250 -0
  78. package/dist/ui/input/tui-input-routing.js +53 -0
  79. package/dist/ui/input/vt-session.js +168 -0
  80. package/dist/ui/messages.js +59 -0
  81. package/dist/ui/model-manager/model-manager-state.js +118 -0
  82. package/dist/ui/model-manager/model-manager-ui.js +194 -0
  83. package/dist/ui/prompt/prompt-box.js +78 -0
  84. package/dist/ui/prompt/prompt-composer.js +498 -0
  85. package/dist/ui/spinner.js +76 -0
  86. package/dist/ui/title-box.js +388 -0
  87. package/dist/ui/tui/app.js +6 -0
  88. package/dist/ui/tui/autocomplete.js +85 -0
  89. package/dist/ui/tui/constants.js +18 -0
  90. package/dist/ui/tui/history.js +29 -0
  91. package/dist/ui/tui/layout.js +341 -0
  92. package/dist/ui/tui/runtime-core.js +2584 -0
  93. package/dist/ui/tui/runtime-utils.js +53 -0
  94. package/dist/ui/tui/start-tui.js +54 -0
  95. package/dist/ui/tui/startup.js +56 -0
  96. package/dist/version.js +51 -0
  97. package/dist/vt-session.js +168 -0
  98. package/install.sh +457 -0
  99. package/package.json +128 -0
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.applyHardwareAwareStartupModelSelection = applyHardwareAwareStartupModelSelection;
4
+ exports.ensureFreshLlamaSessionOnStartup = ensureFreshLlamaSessionOnStartup;
5
+ const config_1 = require("../config");
6
+ const hardware_1 = require("../hardware");
7
+ const llama_server_1 = require("../llama-server");
8
+ const model_manager_1 = require("../model-manager");
9
+ function resolveLoadedModel(model) {
10
+ const trimmed = model.trim();
11
+ if (trimmed.length === 0) {
12
+ return null;
13
+ }
14
+ if (trimmed.toLowerCase() === "default") {
15
+ return null;
16
+ }
17
+ return trimmed;
18
+ }
19
+ async function applyHardwareAwareStartupModelSelection(options, deps = {
20
+ getSpecs: hardware_1.getSystemSpecs,
21
+ listModels: model_manager_1.listLocalModels,
22
+ selectModel: model_manager_1.selectBestModelForHardware,
23
+ save: config_1.saveConfig
24
+ }) {
25
+ if (options.config.backend !== "llamacpp") {
26
+ return null;
27
+ }
28
+ if (resolveLoadedModel(options.config.model)) {
29
+ return null;
30
+ }
31
+ const specs = deps.getSpecs();
32
+ const models = await deps.listModels({
33
+ totalMemoryGb: specs.totalMemoryGb,
34
+ nicknames: options.config.nicknames
35
+ });
36
+ const selected = deps.selectModel(models, specs);
37
+ if (!selected) {
38
+ return null;
39
+ }
40
+ options.config.model = selected.id;
41
+ await deps.save(options.config);
42
+ return selected.id;
43
+ }
44
+ async function ensureFreshLlamaSessionOnStartup(options, deps = { reset: llama_server_1.resetLlamaForFreshSession }) {
45
+ if (options.config.backend !== "llamacpp") {
46
+ return;
47
+ }
48
+ const configuredModel = options.config.model.trim().toLowerCase();
49
+ if (configuredModel.length === 0 || configuredModel === "default") {
50
+ return;
51
+ }
52
+ const resetResult = await deps.reset(options.config);
53
+ if (resetResult.failure) {
54
+ throw new Error((0, llama_server_1.formatLlamaStartupFailure)(resetResult.failure, options.config));
55
+ }
56
+ }
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.decideConfirmationAction = decideConfirmationAction;
4
+ exports.routeVtInput = routeVtInput;
5
+ function decideConfirmationAction(actions) {
6
+ for (const action of actions) {
7
+ if (action.type === "cancel") {
8
+ return "deny";
9
+ }
10
+ if (action.type === "submit") {
11
+ return "approve";
12
+ }
13
+ if (action.type === "insert") {
14
+ const normalized = action.text.trim().toLowerCase();
15
+ if (normalized === "y" || normalized === "yes") {
16
+ return "approve";
17
+ }
18
+ if (normalized === "n" || normalized === "no") {
19
+ return "deny";
20
+ }
21
+ }
22
+ }
23
+ return null;
24
+ }
25
+ function routeVtInput(sequence, escapePending) {
26
+ const bytes = Buffer.from(sequence, "latin1");
27
+ if (bytes.includes(0x11)) {
28
+ return {
29
+ exitToChat: true,
30
+ nextEscapePending: false,
31
+ passthrough: null
32
+ };
33
+ }
34
+ if (sequence === "\u001b") {
35
+ if (escapePending) {
36
+ return {
37
+ exitToChat: true,
38
+ nextEscapePending: false,
39
+ passthrough: null
40
+ };
41
+ }
42
+ return {
43
+ exitToChat: false,
44
+ nextEscapePending: true,
45
+ passthrough: null
46
+ };
47
+ }
48
+ return {
49
+ exitToChat: false,
50
+ nextEscapePending: false,
51
+ passthrough: sequence
52
+ };
53
+ }
package/dist/tui.js ADDED
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ /** Main TUI entrypoint and compatibility exports. */
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.ensureFreshLlamaSessionOnStartup = exports.applyHardwareAwareStartupModelSelection = exports.shouldConsumeSubmitForAutocomplete = exports.runOnceGuarded = exports.resolveModelLoadTarget = exports.renderHistoryLines = exports.formatTokensPerSecond = exports.formatTitleCwd = exports.formatModelLoadingLabel = exports.computeVisibleLayoutSlices = exports.computeTokensPerSecond = exports.computeTitleVisibleScrollCap = exports.composeOutputLines = exports.composeChatRequestMessages = exports.buildPromptStatusText = exports.buildPromptRenderLines = exports.buildModelAutocompleteCandidates = exports.buildAutocompleteOverlayLines = void 0;
8
+ exports.startTui = startTui;
9
+ const react_1 = __importDefault(require("react"));
10
+ const version_1 = require("./version");
11
+ const app_1 = require("./tui/app");
12
+ const startup_1 = require("./tui/startup");
13
+ var app_2 = require("./tui/app");
14
+ Object.defineProperty(exports, "buildAutocompleteOverlayLines", { enumerable: true, get: function () { return app_2.buildAutocompleteOverlayLines; } });
15
+ Object.defineProperty(exports, "buildModelAutocompleteCandidates", { enumerable: true, get: function () { return app_2.buildModelAutocompleteCandidates; } });
16
+ Object.defineProperty(exports, "buildPromptRenderLines", { enumerable: true, get: function () { return app_2.buildPromptRenderLines; } });
17
+ Object.defineProperty(exports, "buildPromptStatusText", { enumerable: true, get: function () { return app_2.buildPromptStatusText; } });
18
+ Object.defineProperty(exports, "composeChatRequestMessages", { enumerable: true, get: function () { return app_2.composeChatRequestMessages; } });
19
+ Object.defineProperty(exports, "composeOutputLines", { enumerable: true, get: function () { return app_2.composeOutputLines; } });
20
+ Object.defineProperty(exports, "computeTitleVisibleScrollCap", { enumerable: true, get: function () { return app_2.computeTitleVisibleScrollCap; } });
21
+ Object.defineProperty(exports, "computeTokensPerSecond", { enumerable: true, get: function () { return app_2.computeTokensPerSecond; } });
22
+ Object.defineProperty(exports, "computeVisibleLayoutSlices", { enumerable: true, get: function () { return app_2.computeVisibleLayoutSlices; } });
23
+ Object.defineProperty(exports, "formatModelLoadingLabel", { enumerable: true, get: function () { return app_2.formatModelLoadingLabel; } });
24
+ Object.defineProperty(exports, "formatTitleCwd", { enumerable: true, get: function () { return app_2.formatTitleCwd; } });
25
+ Object.defineProperty(exports, "formatTokensPerSecond", { enumerable: true, get: function () { return app_2.formatTokensPerSecond; } });
26
+ Object.defineProperty(exports, "renderHistoryLines", { enumerable: true, get: function () { return app_2.renderHistoryLines; } });
27
+ Object.defineProperty(exports, "resolveModelLoadTarget", { enumerable: true, get: function () { return app_2.resolveModelLoadTarget; } });
28
+ Object.defineProperty(exports, "runOnceGuarded", { enumerable: true, get: function () { return app_2.runOnceGuarded; } });
29
+ Object.defineProperty(exports, "shouldConsumeSubmitForAutocomplete", { enumerable: true, get: function () { return app_2.shouldConsumeSubmitForAutocomplete; } });
30
+ var startup_2 = require("./tui/startup");
31
+ Object.defineProperty(exports, "applyHardwareAwareStartupModelSelection", { enumerable: true, get: function () { return startup_2.applyHardwareAwareStartupModelSelection; } });
32
+ Object.defineProperty(exports, "ensureFreshLlamaSessionOnStartup", { enumerable: true, get: function () { return startup_2.ensureFreshLlamaSessionOnStartup; } });
33
+ async function startTui(options) {
34
+ let restartRequested = false;
35
+ await (0, startup_1.applyHardwareAwareStartupModelSelection)(options);
36
+ await (0, startup_1.ensureFreshLlamaSessionOnStartup)(options);
37
+ const version = await (0, version_1.getVersion)();
38
+ const ink = (await import("ink"));
39
+ const App = (0, app_1.createInkApp)(ink);
40
+ const instance = ink.render(react_1.default.createElement(App, {
41
+ options,
42
+ version,
43
+ onRestartRequested: () => {
44
+ restartRequested = true;
45
+ }
46
+ }), {
47
+ exitOnCtrlC: false
48
+ });
49
+ await instance.waitUntilExit();
50
+ return restartRequested ? "restart" : "exit";
51
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,204 @@
1
+ "use strict";
2
+ /** Color palette and gradient utilities for ANSI truecolor output. */
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.DIM_GRAY = exports.SUCCESS_GREEN = exports.WARNING_YELLOW = exports.ERROR_RED = exports.VT_GREEN = exports.INPUT_PINK = exports.DARK_BLUE = exports.GRADIENT_BLUE = exports.GRADIENT_YELLOW = exports.GRADIENT_PINK = void 0;
5
+ exports.parseHex = parseHex;
6
+ exports.toHex = toHex;
7
+ exports.interpolateColor = interpolateColor;
8
+ exports.stripAnsi = stripAnsi;
9
+ exports.colorChar = colorChar;
10
+ exports.colorText = colorText;
11
+ exports.bgColorText = bgColorText;
12
+ exports.horizontalGradient = horizontalGradient;
13
+ exports.horizontalGradientAtOffset = horizontalGradientAtOffset;
14
+ exports.horizontalGradientBackground = horizontalGradientBackground;
15
+ exports.diagonalGradient = diagonalGradient;
16
+ exports.rowMajorGradient = rowMajorGradient;
17
+ // --- Palette constants ---
18
+ exports.GRADIENT_PINK = { r: 0xff, g: 0x14, b: 0x93 };
19
+ exports.GRADIENT_YELLOW = { r: 0xff, g: 0xe1, b: 0x35 };
20
+ exports.GRADIENT_BLUE = { r: 0x89, g: 0xcf, b: 0xf0 };
21
+ exports.DARK_BLUE = { r: 0x00, g: 0x66, b: 0xcc };
22
+ exports.INPUT_PINK = { r: 0xff, g: 0xcc, b: 0xff };
23
+ exports.VT_GREEN = { r: 0x00, g: 0xff, b: 0x00 };
24
+ exports.ERROR_RED = { r: 0xff, g: 0x44, b: 0x44 };
25
+ exports.WARNING_YELLOW = { r: 0xff, g: 0xcc, b: 0x00 };
26
+ exports.SUCCESS_GREEN = { r: 0x44, g: 0xff, b: 0x44 };
27
+ exports.DIM_GRAY = { r: 0x88, g: 0x88, b: 0x88 };
28
+ const ANSI_RESET_FOREGROUND = "\u001b[39m";
29
+ const ANSI_RESET_ALL = "\u001b[0m";
30
+ // --- Color utilities ---
31
+ function parseHex(hex) {
32
+ const cleaned = hex.replace(/^#/, "");
33
+ return {
34
+ r: parseInt(cleaned.slice(0, 2), 16),
35
+ g: parseInt(cleaned.slice(2, 4), 16),
36
+ b: parseInt(cleaned.slice(4, 6), 16)
37
+ };
38
+ }
39
+ function toHex(color) {
40
+ const r = Math.round(Math.max(0, Math.min(255, color.r)));
41
+ const g = Math.round(Math.max(0, Math.min(255, color.g)));
42
+ const b = Math.round(Math.max(0, Math.min(255, color.b)));
43
+ return `#${r.toString(16).padStart(2, "0")}${g.toString(16).padStart(2, "0")}${b.toString(16).padStart(2, "0")}`;
44
+ }
45
+ function interpolateColor(start, end, t) {
46
+ const clamped = Math.max(0, Math.min(1, t));
47
+ return {
48
+ r: start.r + (end.r - start.r) * clamped,
49
+ g: start.g + (end.g - start.g) * clamped,
50
+ b: start.b + (end.b - start.b) * clamped
51
+ };
52
+ }
53
+ function toAnsiColor(color) {
54
+ const r = Math.round(Math.max(0, Math.min(255, color.r)));
55
+ const g = Math.round(Math.max(0, Math.min(255, color.g)));
56
+ const b = Math.round(Math.max(0, Math.min(255, color.b)));
57
+ return `\u001b[38;2;${r};${g};${b}m`;
58
+ }
59
+ function toAnsiBackground(color) {
60
+ const r = Math.round(Math.max(0, Math.min(255, color.r)));
61
+ const g = Math.round(Math.max(0, Math.min(255, color.g)));
62
+ const b = Math.round(Math.max(0, Math.min(255, color.b)));
63
+ return `\u001b[48;2;${r};${g};${b}m`;
64
+ }
65
+ function stripAnsi(text) {
66
+ let output = "";
67
+ for (let i = 0; i < text.length; i++) {
68
+ if (text[i] === "\u001b" && text[i + 1] === "[") {
69
+ i += 2;
70
+ while (i < text.length && text[i] !== "m") {
71
+ i += 1;
72
+ }
73
+ continue;
74
+ }
75
+ output += text[i] ?? "";
76
+ }
77
+ return output;
78
+ }
79
+ /** Wrap a single character with ANSI truecolor sequence. */
80
+ function colorChar(char, color) {
81
+ return `${toAnsiColor(color)}${char}`;
82
+ }
83
+ /** Apply a solid color to an entire string using ANSI truecolor. */
84
+ function colorText(text, color) {
85
+ if (text.length === 0)
86
+ return "";
87
+ return `${toAnsiColor(color)}${text}${ANSI_RESET_FOREGROUND}`;
88
+ }
89
+ /** Apply background (+ optional foreground) color to a string. */
90
+ function bgColorText(text, bgColor, fgColor) {
91
+ if (text.length === 0)
92
+ return "";
93
+ const fg = fgColor ? toAnsiColor(fgColor) : "";
94
+ return `${toAnsiBackground(bgColor)}${fg}${text}${ANSI_RESET_ALL}`;
95
+ }
96
+ /**
97
+ * Apply a horizontal gradient across a string.
98
+ * Each visible character gets its own color interpolated between start and end.
99
+ */
100
+ function horizontalGradient(text, startColor, endColor) {
101
+ const chars = Array.from(text);
102
+ if (chars.length === 0)
103
+ return "";
104
+ if (chars.length === 1) {
105
+ return `${colorChar(chars[0] ?? "", startColor)}${ANSI_RESET_FOREGROUND}`;
106
+ }
107
+ const gradientChars = [];
108
+ for (let i = 0; i < chars.length; i++) {
109
+ const t = i / (chars.length - 1);
110
+ const color = interpolateColor(startColor, endColor, t);
111
+ gradientChars.push(colorChar(chars[i] ?? "", color));
112
+ }
113
+ gradientChars.push(ANSI_RESET_FOREGROUND);
114
+ return gradientChars.join("");
115
+ }
116
+ /**
117
+ * Apply a horizontal gradient to a string using an absolute offset in a larger line.
118
+ * Useful when rendering segmented strings that should share one continuous gradient.
119
+ */
120
+ function horizontalGradientAtOffset(text, startColor, endColor, offset, totalWidth) {
121
+ const chars = Array.from(text);
122
+ if (chars.length === 0)
123
+ return "";
124
+ const safeTotalWidth = Math.max(1, totalWidth);
125
+ const denominator = Math.max(1, safeTotalWidth - 1);
126
+ const baseOffset = Math.max(0, offset);
127
+ const gradientChars = [];
128
+ for (let i = 0; i < chars.length; i++) {
129
+ const t = Math.max(0, Math.min(1, (baseOffset + i) / denominator));
130
+ const color = interpolateColor(startColor, endColor, t);
131
+ gradientChars.push(colorChar(chars[i] ?? "", color));
132
+ }
133
+ gradientChars.push(ANSI_RESET_FOREGROUND);
134
+ return gradientChars.join("");
135
+ }
136
+ /** Apply a left-to-right background gradient across a string. */
137
+ function horizontalGradientBackground(text, startColor, endColor, fgColor) {
138
+ const chars = Array.from(text);
139
+ if (chars.length === 0)
140
+ return "";
141
+ const fg = fgColor ? toAnsiColor(fgColor) : "";
142
+ if (chars.length === 1) {
143
+ return `${toAnsiBackground(startColor)}${fg}${chars[0] ?? ""}${ANSI_RESET_ALL}`;
144
+ }
145
+ const gradientChars = [];
146
+ for (let i = 0; i < chars.length; i++) {
147
+ const t = i / (chars.length - 1);
148
+ const color = interpolateColor(startColor, endColor, t);
149
+ gradientChars.push(`${toAnsiBackground(color)}${fg}${chars[i] ?? ""}`);
150
+ }
151
+ gradientChars.push(ANSI_RESET_ALL);
152
+ return gradientChars.join("");
153
+ }
154
+ /**
155
+ * Apply a diagonal gradient across multiple lines.
156
+ * Each character's color is based on (row + col) / (totalRows + totalCols).
157
+ */
158
+ function diagonalGradient(lines, startColor, endColor) {
159
+ if (lines.length === 0)
160
+ return [];
161
+ const splitLines = lines.map((line) => Array.from(line));
162
+ const maxLen = Math.max(...splitLines.map((lineChars) => lineChars.length));
163
+ if (maxLen === 0)
164
+ return lines.map(() => "");
165
+ const totalSteps = lines.length - 1 + maxLen - 1;
166
+ return splitLines.map((lineChars, row) => {
167
+ if (lineChars.length === 0)
168
+ return "";
169
+ const gradientChars = [];
170
+ for (let col = 0; col < lineChars.length; col++) {
171
+ const t = totalSteps > 0 ? (row + col) / totalSteps : 0;
172
+ const color = interpolateColor(startColor, endColor, t);
173
+ gradientChars.push(colorChar(lineChars[col] ?? "", color));
174
+ }
175
+ gradientChars.push(ANSI_RESET_FOREGROUND);
176
+ return gradientChars.join("");
177
+ });
178
+ }
179
+ /**
180
+ * Apply a multiline gradient by scanning cells row-by-row.
181
+ * Progress advances left-to-right per row, then continues on the next row.
182
+ */
183
+ function rowMajorGradient(lines, startColor, endColor) {
184
+ if (lines.length === 0)
185
+ return [];
186
+ const splitLines = lines.map((line) => Array.from(line));
187
+ const maxLen = Math.max(...splitLines.map((lineChars) => lineChars.length));
188
+ if (maxLen === 0)
189
+ return lines.map(() => "");
190
+ const totalCells = lines.length * maxLen;
191
+ return splitLines.map((lineChars, row) => {
192
+ if (lineChars.length === 0)
193
+ return "";
194
+ const gradientChars = [];
195
+ for (let col = 0; col < lineChars.length; col++) {
196
+ const cellIndex = row * maxLen + col;
197
+ const t = totalCells > 1 ? cellIndex / (totalCells - 1) : 0;
198
+ const color = interpolateColor(startColor, endColor, t);
199
+ gradientChars.push(colorChar(lineChars[col] ?? "", color));
200
+ }
201
+ gradientChars.push(ANSI_RESET_FOREGROUND);
202
+ return gradientChars.join("");
203
+ });
204
+ }
@@ -0,0 +1,302 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DOWNLOADER_TABS = void 0;
4
+ exports.tabToSort = tabToSort;
5
+ exports.createDownloaderState = createDownloaderState;
6
+ exports.cycleTab = cycleTab;
7
+ exports.setModels = setModels;
8
+ exports.setFiles = setFiles;
9
+ exports.setLoading = setLoading;
10
+ exports.setLoadingModels = setLoadingModels;
11
+ exports.setLoadingFiles = setLoadingFiles;
12
+ exports.startDownload = startDownload;
13
+ exports.updateDownloadProgress = updateDownloadProgress;
14
+ exports.finishDownload = finishDownload;
15
+ exports.setPreloadingTabs = setPreloadingTabs;
16
+ exports.setCachedModels = setCachedModels;
17
+ exports.getCachedModels = getCachedModels;
18
+ exports.resetModelCache = resetModelCache;
19
+ exports.setError = setError;
20
+ exports.setDownloaderError = setDownloaderError;
21
+ exports.closeFileView = closeFileView;
22
+ exports.openCancelConfirm = openCancelConfirm;
23
+ exports.closeCancelConfirm = closeCancelConfirm;
24
+ exports.moveModelSelection = moveModelSelection;
25
+ exports.moveFileSelection = moveFileSelection;
26
+ exports.DOWNLOADER_TABS = ["Most Downloaded", "Top Rated", "Newest"];
27
+ function tabToSort(tab) {
28
+ if (tab === "Top Rated") {
29
+ return "trendingScore";
30
+ }
31
+ if (tab === "Newest") {
32
+ return "lastModified";
33
+ }
34
+ return "downloads";
35
+ }
36
+ function createDownloaderState(memory) {
37
+ return {
38
+ isOpen: true,
39
+ view: "models",
40
+ tab: "Most Downloaded",
41
+ searchQuery: "",
42
+ models: [],
43
+ files: [],
44
+ selectedModelIndex: 0,
45
+ selectedFileIndex: 0,
46
+ modelScrollOffset: 0,
47
+ fileScrollOffset: 0,
48
+ phase: "idle",
49
+ loading: false,
50
+ loadingMessage: "Loading models...",
51
+ errorMessage: "",
52
+ download: null,
53
+ selectedRepoId: "",
54
+ ramGb: memory.ramGb,
55
+ vramGb: memory.vramGb,
56
+ totalMemoryGb: memory.totalMemoryGb,
57
+ diskFreeGb: memory.diskFreeGb ?? 0,
58
+ cacheQuery: "",
59
+ modelCacheByTab: {},
60
+ preloadingTabs: false,
61
+ cancelConfirmOpen: false
62
+ };
63
+ }
64
+ function cycleTab(state, direction) {
65
+ const currentIndex = exports.DOWNLOADER_TABS.indexOf(state.tab);
66
+ const nextIndex = (currentIndex + direction + exports.DOWNLOADER_TABS.length) % exports.DOWNLOADER_TABS.length;
67
+ return {
68
+ ...state,
69
+ tab: exports.DOWNLOADER_TABS[nextIndex] ?? "Most Downloaded",
70
+ selectedModelIndex: 0,
71
+ modelScrollOffset: 0
72
+ };
73
+ }
74
+ function setModels(state, models) {
75
+ return {
76
+ ...state,
77
+ models,
78
+ selectedModelIndex: models.length > 0 ? Math.min(state.selectedModelIndex, models.length - 1) : 0,
79
+ modelScrollOffset: 0,
80
+ phase: "idle",
81
+ loading: false,
82
+ errorMessage: "",
83
+ download: null,
84
+ cancelConfirmOpen: false
85
+ };
86
+ }
87
+ function setFiles(state, repoId, files) {
88
+ return {
89
+ ...state,
90
+ selectedRepoId: repoId,
91
+ view: "files",
92
+ files,
93
+ selectedFileIndex: 0,
94
+ fileScrollOffset: 0,
95
+ phase: "idle",
96
+ loading: false,
97
+ errorMessage: "",
98
+ download: null,
99
+ cancelConfirmOpen: false
100
+ };
101
+ }
102
+ function setLoading(state, message) {
103
+ return {
104
+ ...state,
105
+ phase: "loading-models",
106
+ loading: true,
107
+ loadingMessage: message,
108
+ errorMessage: "",
109
+ download: null,
110
+ cancelConfirmOpen: false
111
+ };
112
+ }
113
+ function setLoadingModels(state, message) {
114
+ return {
115
+ ...state,
116
+ phase: "loading-models",
117
+ loading: true,
118
+ loadingMessage: message,
119
+ errorMessage: "",
120
+ download: null,
121
+ cancelConfirmOpen: false
122
+ };
123
+ }
124
+ function setLoadingFiles(state, message) {
125
+ return {
126
+ ...state,
127
+ phase: "loading-files",
128
+ loading: true,
129
+ loadingMessage: message,
130
+ errorMessage: "",
131
+ download: null,
132
+ cancelConfirmOpen: false
133
+ };
134
+ }
135
+ function startDownload(state, repoId, filename, statusText) {
136
+ const now = Date.now();
137
+ return {
138
+ ...state,
139
+ phase: "downloading",
140
+ loading: true,
141
+ loadingMessage: statusText,
142
+ errorMessage: "",
143
+ download: {
144
+ repoId,
145
+ filename,
146
+ bytesDownloaded: 0,
147
+ totalBytes: null,
148
+ startedAtMs: now,
149
+ lastUpdateAtMs: now,
150
+ statusText
151
+ },
152
+ cancelConfirmOpen: false
153
+ };
154
+ }
155
+ function updateDownloadProgress(state, update) {
156
+ if (state.phase !== "downloading" || !state.download) {
157
+ return state;
158
+ }
159
+ return {
160
+ ...state,
161
+ loadingMessage: update.statusText,
162
+ download: {
163
+ ...state.download,
164
+ bytesDownloaded: Math.max(0, update.bytesDownloaded),
165
+ totalBytes: update.totalBytes,
166
+ lastUpdateAtMs: Date.now(),
167
+ statusText: update.statusText
168
+ }
169
+ };
170
+ }
171
+ function finishDownload(state) {
172
+ return {
173
+ ...state,
174
+ phase: "idle",
175
+ loading: false,
176
+ loadingMessage: "",
177
+ errorMessage: "",
178
+ download: null,
179
+ cancelConfirmOpen: false
180
+ };
181
+ }
182
+ function setPreloadingTabs(state, preloadingTabs) {
183
+ return {
184
+ ...state,
185
+ preloadingTabs
186
+ };
187
+ }
188
+ function setCachedModels(state, tab, query, models) {
189
+ const normalizedQuery = query.trim();
190
+ const cache = state.cacheQuery === normalizedQuery ? state.modelCacheByTab : {};
191
+ return {
192
+ ...state,
193
+ cacheQuery: normalizedQuery,
194
+ modelCacheByTab: {
195
+ ...cache,
196
+ [tab]: models
197
+ }
198
+ };
199
+ }
200
+ function getCachedModels(state, tab, query) {
201
+ if (state.cacheQuery !== query.trim()) {
202
+ return null;
203
+ }
204
+ return state.modelCacheByTab[tab] ?? null;
205
+ }
206
+ function resetModelCache(state, query) {
207
+ return {
208
+ ...state,
209
+ cacheQuery: query.trim(),
210
+ modelCacheByTab: {}
211
+ };
212
+ }
213
+ function setError(state, message) {
214
+ return {
215
+ ...state,
216
+ phase: "error",
217
+ loading: false,
218
+ errorMessage: message,
219
+ download: null,
220
+ cancelConfirmOpen: false
221
+ };
222
+ }
223
+ function setDownloaderError(state, message) {
224
+ return {
225
+ ...state,
226
+ phase: "error",
227
+ loading: false,
228
+ errorMessage: message,
229
+ download: null,
230
+ cancelConfirmOpen: false
231
+ };
232
+ }
233
+ function closeFileView(state) {
234
+ return {
235
+ ...state,
236
+ view: "models",
237
+ files: [],
238
+ selectedFileIndex: 0,
239
+ fileScrollOffset: 0,
240
+ phase: "idle",
241
+ loading: false,
242
+ errorMessage: "",
243
+ download: null,
244
+ cancelConfirmOpen: false
245
+ };
246
+ }
247
+ function openCancelConfirm(state) {
248
+ if (state.phase !== "downloading" || !state.download) {
249
+ return state;
250
+ }
251
+ return {
252
+ ...state,
253
+ cancelConfirmOpen: true
254
+ };
255
+ }
256
+ function closeCancelConfirm(state) {
257
+ if (!state.cancelConfirmOpen) {
258
+ return state;
259
+ }
260
+ return {
261
+ ...state,
262
+ cancelConfirmOpen: false
263
+ };
264
+ }
265
+ function moveModelSelection(state, delta, windowSize) {
266
+ if (state.models.length === 0) {
267
+ return state;
268
+ }
269
+ const max = state.models.length - 1;
270
+ const nextIndex = Math.max(0, Math.min(max, state.selectedModelIndex + delta));
271
+ let nextOffset = state.modelScrollOffset;
272
+ if (nextIndex < nextOffset) {
273
+ nextOffset = nextIndex;
274
+ }
275
+ if (nextIndex >= nextOffset + windowSize) {
276
+ nextOffset = nextIndex - windowSize + 1;
277
+ }
278
+ return {
279
+ ...state,
280
+ selectedModelIndex: nextIndex,
281
+ modelScrollOffset: Math.max(0, nextOffset)
282
+ };
283
+ }
284
+ function moveFileSelection(state, delta, windowSize) {
285
+ if (state.files.length === 0) {
286
+ return state;
287
+ }
288
+ const max = state.files.length - 1;
289
+ const nextIndex = Math.max(0, Math.min(max, state.selectedFileIndex + delta));
290
+ let nextOffset = state.fileScrollOffset;
291
+ if (nextIndex < nextOffset) {
292
+ nextOffset = nextIndex;
293
+ }
294
+ if (nextIndex >= nextOffset + windowSize) {
295
+ nextOffset = nextIndex - windowSize + 1;
296
+ }
297
+ return {
298
+ ...state,
299
+ selectedFileIndex: nextIndex,
300
+ fileScrollOffset: Math.max(0, nextOffset)
301
+ };
302
+ }