@fugood/llama.node 0.0.1-alpha.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 (204) hide show
  1. package/CMakeLists.txt +85 -0
  2. package/README.md +56 -0
  3. package/bin/darwin/arm64/llama-node.node +0 -0
  4. package/bin/darwin/x64/llama-node.node +0 -0
  5. package/bin/linux/arm64/llama-node.node +0 -0
  6. package/bin/linux/x64/llama-node.node +0 -0
  7. package/bin/win32/arm64/llama-node.node +0 -0
  8. package/bin/win32/arm64/node.lib +0 -0
  9. package/bin/win32/x64/llama-node.node +0 -0
  10. package/bin/win32/x64/node.lib +0 -0
  11. package/lib/binding.js +13 -0
  12. package/lib/binding.ts +57 -0
  13. package/lib/index.js +24 -0
  14. package/lib/index.ts +13 -0
  15. package/package.json +65 -0
  16. package/src/addons.cpp +506 -0
  17. package/src/llama.cpp/CMakeLists.txt +1320 -0
  18. package/src/llama.cpp/build.zig +172 -0
  19. package/src/llama.cpp/cmake/FindSIMD.cmake +100 -0
  20. package/src/llama.cpp/common/CMakeLists.txt +87 -0
  21. package/src/llama.cpp/common/base64.hpp +392 -0
  22. package/src/llama.cpp/common/common.cpp +2949 -0
  23. package/src/llama.cpp/common/common.h +324 -0
  24. package/src/llama.cpp/common/console.cpp +501 -0
  25. package/src/llama.cpp/common/console.h +19 -0
  26. package/src/llama.cpp/common/grammar-parser.cpp +440 -0
  27. package/src/llama.cpp/common/grammar-parser.h +29 -0
  28. package/src/llama.cpp/common/json-schema-to-grammar.cpp +764 -0
  29. package/src/llama.cpp/common/json-schema-to-grammar.h +4 -0
  30. package/src/llama.cpp/common/json.hpp +24766 -0
  31. package/src/llama.cpp/common/log.h +724 -0
  32. package/src/llama.cpp/common/ngram-cache.cpp +282 -0
  33. package/src/llama.cpp/common/ngram-cache.h +94 -0
  34. package/src/llama.cpp/common/sampling.cpp +353 -0
  35. package/src/llama.cpp/common/sampling.h +147 -0
  36. package/src/llama.cpp/common/stb_image.h +8396 -0
  37. package/src/llama.cpp/common/train.cpp +1513 -0
  38. package/src/llama.cpp/common/train.h +233 -0
  39. package/src/llama.cpp/examples/CMakeLists.txt +52 -0
  40. package/src/llama.cpp/examples/baby-llama/CMakeLists.txt +5 -0
  41. package/src/llama.cpp/examples/baby-llama/baby-llama.cpp +1640 -0
  42. package/src/llama.cpp/examples/batched/CMakeLists.txt +5 -0
  43. package/src/llama.cpp/examples/batched/batched.cpp +262 -0
  44. package/src/llama.cpp/examples/batched-bench/CMakeLists.txt +5 -0
  45. package/src/llama.cpp/examples/batched-bench/batched-bench.cpp +261 -0
  46. package/src/llama.cpp/examples/beam-search/CMakeLists.txt +5 -0
  47. package/src/llama.cpp/examples/beam-search/beam-search.cpp +188 -0
  48. package/src/llama.cpp/examples/benchmark/CMakeLists.txt +6 -0
  49. package/src/llama.cpp/examples/benchmark/benchmark-matmult.cpp +275 -0
  50. package/src/llama.cpp/examples/convert-llama2c-to-ggml/CMakeLists.txt +5 -0
  51. package/src/llama.cpp/examples/convert-llama2c-to-ggml/convert-llama2c-to-ggml.cpp +936 -0
  52. package/src/llama.cpp/examples/embedding/CMakeLists.txt +5 -0
  53. package/src/llama.cpp/examples/embedding/embedding.cpp +211 -0
  54. package/src/llama.cpp/examples/eval-callback/CMakeLists.txt +9 -0
  55. package/src/llama.cpp/examples/eval-callback/eval-callback.cpp +195 -0
  56. package/src/llama.cpp/examples/export-lora/CMakeLists.txt +5 -0
  57. package/src/llama.cpp/examples/export-lora/export-lora.cpp +462 -0
  58. package/src/llama.cpp/examples/finetune/CMakeLists.txt +5 -0
  59. package/src/llama.cpp/examples/finetune/finetune.cpp +1861 -0
  60. package/src/llama.cpp/examples/gbnf-validator/CMakeLists.txt +5 -0
  61. package/src/llama.cpp/examples/gbnf-validator/gbnf-validator.cpp +132 -0
  62. package/src/llama.cpp/examples/gguf/CMakeLists.txt +5 -0
  63. package/src/llama.cpp/examples/gguf/gguf.cpp +256 -0
  64. package/src/llama.cpp/examples/gguf-split/CMakeLists.txt +5 -0
  65. package/src/llama.cpp/examples/gguf-split/gguf-split.cpp +553 -0
  66. package/src/llama.cpp/examples/gritlm/CMakeLists.txt +5 -0
  67. package/src/llama.cpp/examples/gritlm/gritlm.cpp +215 -0
  68. package/src/llama.cpp/examples/imatrix/CMakeLists.txt +5 -0
  69. package/src/llama.cpp/examples/imatrix/imatrix.cpp +655 -0
  70. package/src/llama.cpp/examples/infill/CMakeLists.txt +5 -0
  71. package/src/llama.cpp/examples/infill/infill.cpp +767 -0
  72. package/src/llama.cpp/examples/jeopardy/questions.txt +100 -0
  73. package/src/llama.cpp/examples/llama-bench/CMakeLists.txt +5 -0
  74. package/src/llama.cpp/examples/llama-bench/llama-bench.cpp +1286 -0
  75. package/src/llama.cpp/examples/llama.android/app/src/main/cpp/CMakeLists.txt +50 -0
  76. package/src/llama.cpp/examples/llama.android/app/src/main/cpp/llama-android.cpp +443 -0
  77. package/src/llama.cpp/examples/llava/CMakeLists.txt +37 -0
  78. package/src/llama.cpp/examples/llava/clip.cpp +2027 -0
  79. package/src/llama.cpp/examples/llava/clip.h +85 -0
  80. package/src/llama.cpp/examples/llava/llava-cli.cpp +309 -0
  81. package/src/llama.cpp/examples/llava/llava.cpp +426 -0
  82. package/src/llama.cpp/examples/llava/llava.h +50 -0
  83. package/src/llama.cpp/examples/llava/requirements.txt +3 -0
  84. package/src/llama.cpp/examples/lookahead/CMakeLists.txt +5 -0
  85. package/src/llama.cpp/examples/lookahead/lookahead.cpp +485 -0
  86. package/src/llama.cpp/examples/lookup/CMakeLists.txt +23 -0
  87. package/src/llama.cpp/examples/lookup/lookup-create.cpp +41 -0
  88. package/src/llama.cpp/examples/lookup/lookup-merge.cpp +47 -0
  89. package/src/llama.cpp/examples/lookup/lookup-stats.cpp +160 -0
  90. package/src/llama.cpp/examples/lookup/lookup.cpp +258 -0
  91. package/src/llama.cpp/examples/main/CMakeLists.txt +5 -0
  92. package/src/llama.cpp/examples/main/main.cpp +957 -0
  93. package/src/llama.cpp/examples/main-cmake-pkg/CMakeLists.txt +33 -0
  94. package/src/llama.cpp/examples/parallel/CMakeLists.txt +5 -0
  95. package/src/llama.cpp/examples/parallel/parallel.cpp +427 -0
  96. package/src/llama.cpp/examples/passkey/CMakeLists.txt +5 -0
  97. package/src/llama.cpp/examples/passkey/passkey.cpp +302 -0
  98. package/src/llama.cpp/examples/perplexity/CMakeLists.txt +5 -0
  99. package/src/llama.cpp/examples/perplexity/perplexity.cpp +1943 -0
  100. package/src/llama.cpp/examples/quantize/CMakeLists.txt +6 -0
  101. package/src/llama.cpp/examples/quantize/quantize.cpp +423 -0
  102. package/src/llama.cpp/examples/quantize-stats/CMakeLists.txt +6 -0
  103. package/src/llama.cpp/examples/quantize-stats/quantize-stats.cpp +424 -0
  104. package/src/llama.cpp/examples/retrieval/CMakeLists.txt +5 -0
  105. package/src/llama.cpp/examples/retrieval/retrieval.cpp +350 -0
  106. package/src/llama.cpp/examples/save-load-state/CMakeLists.txt +5 -0
  107. package/src/llama.cpp/examples/save-load-state/save-load-state.cpp +246 -0
  108. package/src/llama.cpp/examples/server/CMakeLists.txt +40 -0
  109. package/src/llama.cpp/examples/server/bench/requirements.txt +2 -0
  110. package/src/llama.cpp/examples/server/httplib.h +9465 -0
  111. package/src/llama.cpp/examples/server/server.cpp +3826 -0
  112. package/src/llama.cpp/examples/server/tests/requirements.txt +6 -0
  113. package/src/llama.cpp/examples/server/utils.hpp +653 -0
  114. package/src/llama.cpp/examples/simple/CMakeLists.txt +5 -0
  115. package/src/llama.cpp/examples/simple/simple.cpp +183 -0
  116. package/src/llama.cpp/examples/speculative/CMakeLists.txt +5 -0
  117. package/src/llama.cpp/examples/speculative/speculative.cpp +614 -0
  118. package/src/llama.cpp/examples/sycl/CMakeLists.txt +9 -0
  119. package/src/llama.cpp/examples/sycl/ls-sycl-device.cpp +13 -0
  120. package/src/llama.cpp/examples/tokenize/CMakeLists.txt +5 -0
  121. package/src/llama.cpp/examples/tokenize/tokenize.cpp +42 -0
  122. package/src/llama.cpp/examples/train-text-from-scratch/CMakeLists.txt +5 -0
  123. package/src/llama.cpp/examples/train-text-from-scratch/train-text-from-scratch.cpp +1252 -0
  124. package/src/llama.cpp/ggml-alloc.c +985 -0
  125. package/src/llama.cpp/ggml-alloc.h +76 -0
  126. package/src/llama.cpp/ggml-backend-impl.h +141 -0
  127. package/src/llama.cpp/ggml-backend.c +2099 -0
  128. package/src/llama.cpp/ggml-backend.h +233 -0
  129. package/src/llama.cpp/ggml-common.h +1853 -0
  130. package/src/llama.cpp/ggml-cuda.h +43 -0
  131. package/src/llama.cpp/ggml-impl.h +265 -0
  132. package/src/llama.cpp/ggml-kompute.cpp +2006 -0
  133. package/src/llama.cpp/ggml-kompute.h +46 -0
  134. package/src/llama.cpp/ggml-metal.h +66 -0
  135. package/src/llama.cpp/ggml-mpi.c +216 -0
  136. package/src/llama.cpp/ggml-mpi.h +39 -0
  137. package/src/llama.cpp/ggml-opencl.cpp +2301 -0
  138. package/src/llama.cpp/ggml-opencl.h +36 -0
  139. package/src/llama.cpp/ggml-quants.c +12678 -0
  140. package/src/llama.cpp/ggml-quants.h +133 -0
  141. package/src/llama.cpp/ggml-sycl.cpp +17882 -0
  142. package/src/llama.cpp/ggml-sycl.h +49 -0
  143. package/src/llama.cpp/ggml-vulkan-shaders.hpp +69849 -0
  144. package/src/llama.cpp/ggml-vulkan.cpp +6442 -0
  145. package/src/llama.cpp/ggml-vulkan.h +29 -0
  146. package/src/llama.cpp/ggml.c +21819 -0
  147. package/src/llama.cpp/ggml.h +2403 -0
  148. package/src/llama.cpp/llama.cpp +17468 -0
  149. package/src/llama.cpp/llama.h +1117 -0
  150. package/src/llama.cpp/pocs/CMakeLists.txt +12 -0
  151. package/src/llama.cpp/pocs/vdot/CMakeLists.txt +9 -0
  152. package/src/llama.cpp/pocs/vdot/q8dot.cpp +172 -0
  153. package/src/llama.cpp/pocs/vdot/vdot.cpp +310 -0
  154. package/src/llama.cpp/prompts/LLM-questions.txt +49 -0
  155. package/src/llama.cpp/prompts/alpaca.txt +1 -0
  156. package/src/llama.cpp/prompts/assistant.txt +31 -0
  157. package/src/llama.cpp/prompts/chat-with-baichuan.txt +4 -0
  158. package/src/llama.cpp/prompts/chat-with-bob.txt +7 -0
  159. package/src/llama.cpp/prompts/chat-with-qwen.txt +1 -0
  160. package/src/llama.cpp/prompts/chat-with-vicuna-v0.txt +7 -0
  161. package/src/llama.cpp/prompts/chat-with-vicuna-v1.txt +7 -0
  162. package/src/llama.cpp/prompts/chat.txt +28 -0
  163. package/src/llama.cpp/prompts/dan-modified.txt +1 -0
  164. package/src/llama.cpp/prompts/dan.txt +1 -0
  165. package/src/llama.cpp/prompts/mnemonics.txt +93 -0
  166. package/src/llama.cpp/prompts/parallel-questions.txt +43 -0
  167. package/src/llama.cpp/prompts/reason-act.txt +18 -0
  168. package/src/llama.cpp/requirements/requirements-convert-hf-to-gguf.txt +3 -0
  169. package/src/llama.cpp/requirements/requirements-convert-llama-ggml-to-gguf.txt +1 -0
  170. package/src/llama.cpp/requirements/requirements-convert-lora-to-ggml.txt +2 -0
  171. package/src/llama.cpp/requirements/requirements-convert-persimmon-to-gguf.txt +2 -0
  172. package/src/llama.cpp/requirements/requirements-convert.txt +5 -0
  173. package/src/llama.cpp/requirements.txt +12 -0
  174. package/src/llama.cpp/scripts/gen-build-info-cpp.cmake +24 -0
  175. package/src/llama.cpp/scripts/xxd.cmake +16 -0
  176. package/src/llama.cpp/sgemm.cpp +999 -0
  177. package/src/llama.cpp/sgemm.h +12 -0
  178. package/src/llama.cpp/tests/CMakeLists.txt +78 -0
  179. package/src/llama.cpp/tests/get-model.cpp +21 -0
  180. package/src/llama.cpp/tests/get-model.h +2 -0
  181. package/src/llama.cpp/tests/test-autorelease.cpp +24 -0
  182. package/src/llama.cpp/tests/test-backend-ops.cpp +2266 -0
  183. package/src/llama.cpp/tests/test-c.c +7 -0
  184. package/src/llama.cpp/tests/test-chat-template.cpp +107 -0
  185. package/src/llama.cpp/tests/test-double-float.cpp +57 -0
  186. package/src/llama.cpp/tests/test-grad0.cpp +1606 -0
  187. package/src/llama.cpp/tests/test-grammar-integration.cpp +243 -0
  188. package/src/llama.cpp/tests/test-grammar-parser.cpp +250 -0
  189. package/src/llama.cpp/tests/test-json-schema-to-grammar.cpp +899 -0
  190. package/src/llama.cpp/tests/test-llama-grammar.cpp +402 -0
  191. package/src/llama.cpp/tests/test-model-load-cancel.cpp +27 -0
  192. package/src/llama.cpp/tests/test-opt.cpp +181 -0
  193. package/src/llama.cpp/tests/test-quantize-fns.cpp +185 -0
  194. package/src/llama.cpp/tests/test-quantize-perf.cpp +363 -0
  195. package/src/llama.cpp/tests/test-rope.cpp +221 -0
  196. package/src/llama.cpp/tests/test-sampling.cpp +301 -0
  197. package/src/llama.cpp/tests/test-tokenizer-0-falcon.cpp +187 -0
  198. package/src/llama.cpp/tests/test-tokenizer-0-llama.cpp +190 -0
  199. package/src/llama.cpp/tests/test-tokenizer-1-bpe.cpp +123 -0
  200. package/src/llama.cpp/tests/test-tokenizer-1-llama.cpp +111 -0
  201. package/src/llama.cpp/unicode-data.cpp +1651 -0
  202. package/src/llama.cpp/unicode-data.h +16 -0
  203. package/src/llama.cpp/unicode.cpp +277 -0
  204. package/src/llama.cpp/unicode.h +28 -0
@@ -0,0 +1,501 @@
1
+ #include "console.h"
2
+ #include <vector>
3
+ #include <iostream>
4
+
5
+ #if defined(_WIN32)
6
+ #define WIN32_LEAN_AND_MEAN
7
+ #ifndef NOMINMAX
8
+ #define NOMINMAX
9
+ #endif
10
+ #include <windows.h>
11
+ #include <fcntl.h>
12
+ #include <io.h>
13
+ #ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
14
+ #define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
15
+ #endif
16
+ #else
17
+ #include <climits>
18
+ #include <sys/ioctl.h>
19
+ #include <unistd.h>
20
+ #include <wchar.h>
21
+ #include <stdio.h>
22
+ #include <stdlib.h>
23
+ #include <signal.h>
24
+ #include <termios.h>
25
+ #endif
26
+
27
+ #define ANSI_COLOR_RED "\x1b[31m"
28
+ #define ANSI_COLOR_GREEN "\x1b[32m"
29
+ #define ANSI_COLOR_YELLOW "\x1b[33m"
30
+ #define ANSI_COLOR_BLUE "\x1b[34m"
31
+ #define ANSI_COLOR_MAGENTA "\x1b[35m"
32
+ #define ANSI_COLOR_CYAN "\x1b[36m"
33
+ #define ANSI_COLOR_RESET "\x1b[0m"
34
+ #define ANSI_BOLD "\x1b[1m"
35
+
36
+ namespace console {
37
+
38
+ //
39
+ // Console state
40
+ //
41
+
42
+ static bool advanced_display = false;
43
+ static bool simple_io = true;
44
+ static display_t current_display = reset;
45
+
46
+ static FILE* out = stdout;
47
+
48
+ #if defined (_WIN32)
49
+ static void* hConsole;
50
+ #else
51
+ static FILE* tty = nullptr;
52
+ static termios initial_state;
53
+ #endif
54
+
55
+ //
56
+ // Init and cleanup
57
+ //
58
+
59
+ void init(bool use_simple_io, bool use_advanced_display) {
60
+ advanced_display = use_advanced_display;
61
+ simple_io = use_simple_io;
62
+ #if defined(_WIN32)
63
+ // Windows-specific console initialization
64
+ DWORD dwMode = 0;
65
+ hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
66
+ if (hConsole == INVALID_HANDLE_VALUE || !GetConsoleMode(hConsole, &dwMode)) {
67
+ hConsole = GetStdHandle(STD_ERROR_HANDLE);
68
+ if (hConsole != INVALID_HANDLE_VALUE && (!GetConsoleMode(hConsole, &dwMode))) {
69
+ hConsole = nullptr;
70
+ simple_io = true;
71
+ }
72
+ }
73
+ if (hConsole) {
74
+ // Check conditions combined to reduce nesting
75
+ if (advanced_display && !(dwMode & ENABLE_VIRTUAL_TERMINAL_PROCESSING) &&
76
+ !SetConsoleMode(hConsole, dwMode | ENABLE_VIRTUAL_TERMINAL_PROCESSING)) {
77
+ advanced_display = false;
78
+ }
79
+ // Set console output codepage to UTF8
80
+ SetConsoleOutputCP(CP_UTF8);
81
+ }
82
+ HANDLE hConIn = GetStdHandle(STD_INPUT_HANDLE);
83
+ if (hConIn != INVALID_HANDLE_VALUE && GetConsoleMode(hConIn, &dwMode)) {
84
+ // Set console input codepage to UTF16
85
+ _setmode(_fileno(stdin), _O_WTEXT);
86
+
87
+ // Set ICANON (ENABLE_LINE_INPUT) and ECHO (ENABLE_ECHO_INPUT)
88
+ if (simple_io) {
89
+ dwMode |= ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT;
90
+ } else {
91
+ dwMode &= ~(ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT);
92
+ }
93
+ if (!SetConsoleMode(hConIn, dwMode)) {
94
+ simple_io = true;
95
+ }
96
+ }
97
+ #else
98
+ // POSIX-specific console initialization
99
+ if (!simple_io) {
100
+ struct termios new_termios;
101
+ tcgetattr(STDIN_FILENO, &initial_state);
102
+ new_termios = initial_state;
103
+ new_termios.c_lflag &= ~(ICANON | ECHO);
104
+ new_termios.c_cc[VMIN] = 1;
105
+ new_termios.c_cc[VTIME] = 0;
106
+ tcsetattr(STDIN_FILENO, TCSANOW, &new_termios);
107
+
108
+ tty = fopen("/dev/tty", "w+");
109
+ if (tty != nullptr) {
110
+ out = tty;
111
+ }
112
+ }
113
+
114
+ setlocale(LC_ALL, "");
115
+ #endif
116
+ }
117
+
118
+ void cleanup() {
119
+ // Reset console display
120
+ set_display(reset);
121
+
122
+ #if !defined(_WIN32)
123
+ // Restore settings on POSIX systems
124
+ if (!simple_io) {
125
+ if (tty != nullptr) {
126
+ out = stdout;
127
+ fclose(tty);
128
+ tty = nullptr;
129
+ }
130
+ tcsetattr(STDIN_FILENO, TCSANOW, &initial_state);
131
+ }
132
+ #endif
133
+ }
134
+
135
+ //
136
+ // Display and IO
137
+ //
138
+
139
+ // Keep track of current display and only emit ANSI code if it changes
140
+ void set_display(display_t display) {
141
+ if (advanced_display && current_display != display) {
142
+ fflush(stdout);
143
+ switch(display) {
144
+ case reset:
145
+ fprintf(out, ANSI_COLOR_RESET);
146
+ break;
147
+ case prompt:
148
+ fprintf(out, ANSI_COLOR_YELLOW);
149
+ break;
150
+ case user_input:
151
+ fprintf(out, ANSI_BOLD ANSI_COLOR_GREEN);
152
+ break;
153
+ case error:
154
+ fprintf(out, ANSI_BOLD ANSI_COLOR_RED);
155
+ }
156
+ current_display = display;
157
+ fflush(out);
158
+ }
159
+ }
160
+
161
+ static char32_t getchar32() {
162
+ #if defined(_WIN32)
163
+ HANDLE hConsole = GetStdHandle(STD_INPUT_HANDLE);
164
+ wchar_t high_surrogate = 0;
165
+
166
+ while (true) {
167
+ INPUT_RECORD record;
168
+ DWORD count;
169
+ if (!ReadConsoleInputW(hConsole, &record, 1, &count) || count == 0) {
170
+ return WEOF;
171
+ }
172
+
173
+ if (record.EventType == KEY_EVENT && record.Event.KeyEvent.bKeyDown) {
174
+ wchar_t wc = record.Event.KeyEvent.uChar.UnicodeChar;
175
+ if (wc == 0) {
176
+ continue;
177
+ }
178
+
179
+ if ((wc >= 0xD800) && (wc <= 0xDBFF)) { // Check if wc is a high surrogate
180
+ high_surrogate = wc;
181
+ continue;
182
+ }
183
+ if ((wc >= 0xDC00) && (wc <= 0xDFFF)) { // Check if wc is a low surrogate
184
+ if (high_surrogate != 0) { // Check if we have a high surrogate
185
+ return ((high_surrogate - 0xD800) << 10) + (wc - 0xDC00) + 0x10000;
186
+ }
187
+ }
188
+
189
+ high_surrogate = 0; // Reset the high surrogate
190
+ return static_cast<char32_t>(wc);
191
+ }
192
+ }
193
+ #else
194
+ wchar_t wc = getwchar();
195
+ if (static_cast<wint_t>(wc) == WEOF) {
196
+ return WEOF;
197
+ }
198
+
199
+ #if WCHAR_MAX == 0xFFFF
200
+ if ((wc >= 0xD800) && (wc <= 0xDBFF)) { // Check if wc is a high surrogate
201
+ wchar_t low_surrogate = getwchar();
202
+ if ((low_surrogate >= 0xDC00) && (low_surrogate <= 0xDFFF)) { // Check if the next wchar is a low surrogate
203
+ return (static_cast<char32_t>(wc & 0x03FF) << 10) + (low_surrogate & 0x03FF) + 0x10000;
204
+ }
205
+ }
206
+ if ((wc >= 0xD800) && (wc <= 0xDFFF)) { // Invalid surrogate pair
207
+ return 0xFFFD; // Return the replacement character U+FFFD
208
+ }
209
+ #endif
210
+
211
+ return static_cast<char32_t>(wc);
212
+ #endif
213
+ }
214
+
215
+ static void pop_cursor() {
216
+ #if defined(_WIN32)
217
+ if (hConsole != NULL) {
218
+ CONSOLE_SCREEN_BUFFER_INFO bufferInfo;
219
+ GetConsoleScreenBufferInfo(hConsole, &bufferInfo);
220
+
221
+ COORD newCursorPosition = bufferInfo.dwCursorPosition;
222
+ if (newCursorPosition.X == 0) {
223
+ newCursorPosition.X = bufferInfo.dwSize.X - 1;
224
+ newCursorPosition.Y -= 1;
225
+ } else {
226
+ newCursorPosition.X -= 1;
227
+ }
228
+
229
+ SetConsoleCursorPosition(hConsole, newCursorPosition);
230
+ return;
231
+ }
232
+ #endif
233
+ putc('\b', out);
234
+ }
235
+
236
+ static int estimateWidth(char32_t codepoint) {
237
+ #if defined(_WIN32)
238
+ (void)codepoint;
239
+ return 1;
240
+ #else
241
+ return wcwidth(codepoint);
242
+ #endif
243
+ }
244
+
245
+ static int put_codepoint(const char* utf8_codepoint, size_t length, int expectedWidth) {
246
+ #if defined(_WIN32)
247
+ CONSOLE_SCREEN_BUFFER_INFO bufferInfo;
248
+ if (!GetConsoleScreenBufferInfo(hConsole, &bufferInfo)) {
249
+ // go with the default
250
+ return expectedWidth;
251
+ }
252
+ COORD initialPosition = bufferInfo.dwCursorPosition;
253
+ DWORD nNumberOfChars = length;
254
+ WriteConsole(hConsole, utf8_codepoint, nNumberOfChars, &nNumberOfChars, NULL);
255
+
256
+ CONSOLE_SCREEN_BUFFER_INFO newBufferInfo;
257
+ GetConsoleScreenBufferInfo(hConsole, &newBufferInfo);
258
+
259
+ // Figure out our real position if we're in the last column
260
+ if (utf8_codepoint[0] != 0x09 && initialPosition.X == newBufferInfo.dwSize.X - 1) {
261
+ DWORD nNumberOfChars;
262
+ WriteConsole(hConsole, &" \b", 2, &nNumberOfChars, NULL);
263
+ GetConsoleScreenBufferInfo(hConsole, &newBufferInfo);
264
+ }
265
+
266
+ int width = newBufferInfo.dwCursorPosition.X - initialPosition.X;
267
+ if (width < 0) {
268
+ width += newBufferInfo.dwSize.X;
269
+ }
270
+ return width;
271
+ #else
272
+ // We can trust expectedWidth if we've got one
273
+ if (expectedWidth >= 0 || tty == nullptr) {
274
+ fwrite(utf8_codepoint, length, 1, out);
275
+ return expectedWidth;
276
+ }
277
+
278
+ fputs("\033[6n", tty); // Query cursor position
279
+ int x1;
280
+ int y1;
281
+ int x2;
282
+ int y2;
283
+ int results = 0;
284
+ results = fscanf(tty, "\033[%d;%dR", &y1, &x1);
285
+
286
+ fwrite(utf8_codepoint, length, 1, tty);
287
+
288
+ fputs("\033[6n", tty); // Query cursor position
289
+ results += fscanf(tty, "\033[%d;%dR", &y2, &x2);
290
+
291
+ if (results != 4) {
292
+ return expectedWidth;
293
+ }
294
+
295
+ int width = x2 - x1;
296
+ if (width < 0) {
297
+ // Calculate the width considering text wrapping
298
+ struct winsize w;
299
+ ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
300
+ width += w.ws_col;
301
+ }
302
+ return width;
303
+ #endif
304
+ }
305
+
306
+ static void replace_last(char ch) {
307
+ #if defined(_WIN32)
308
+ pop_cursor();
309
+ put_codepoint(&ch, 1, 1);
310
+ #else
311
+ fprintf(out, "\b%c", ch);
312
+ #endif
313
+ }
314
+
315
+ static void append_utf8(char32_t ch, std::string & out) {
316
+ if (ch <= 0x7F) {
317
+ out.push_back(static_cast<unsigned char>(ch));
318
+ } else if (ch <= 0x7FF) {
319
+ out.push_back(static_cast<unsigned char>(0xC0 | ((ch >> 6) & 0x1F)));
320
+ out.push_back(static_cast<unsigned char>(0x80 | (ch & 0x3F)));
321
+ } else if (ch <= 0xFFFF) {
322
+ out.push_back(static_cast<unsigned char>(0xE0 | ((ch >> 12) & 0x0F)));
323
+ out.push_back(static_cast<unsigned char>(0x80 | ((ch >> 6) & 0x3F)));
324
+ out.push_back(static_cast<unsigned char>(0x80 | (ch & 0x3F)));
325
+ } else if (ch <= 0x10FFFF) {
326
+ out.push_back(static_cast<unsigned char>(0xF0 | ((ch >> 18) & 0x07)));
327
+ out.push_back(static_cast<unsigned char>(0x80 | ((ch >> 12) & 0x3F)));
328
+ out.push_back(static_cast<unsigned char>(0x80 | ((ch >> 6) & 0x3F)));
329
+ out.push_back(static_cast<unsigned char>(0x80 | (ch & 0x3F)));
330
+ } else {
331
+ // Invalid Unicode code point
332
+ }
333
+ }
334
+
335
+ // Helper function to remove the last UTF-8 character from a string
336
+ static void pop_back_utf8_char(std::string & line) {
337
+ if (line.empty()) {
338
+ return;
339
+ }
340
+
341
+ size_t pos = line.length() - 1;
342
+
343
+ // Find the start of the last UTF-8 character (checking up to 4 bytes back)
344
+ for (size_t i = 0; i < 3 && pos > 0; ++i, --pos) {
345
+ if ((line[pos] & 0xC0) != 0x80) {
346
+ break; // Found the start of the character
347
+ }
348
+ }
349
+ line.erase(pos);
350
+ }
351
+
352
+ static bool readline_advanced(std::string & line, bool multiline_input) {
353
+ if (out != stdout) {
354
+ fflush(stdout);
355
+ }
356
+
357
+ line.clear();
358
+ std::vector<int> widths;
359
+ bool is_special_char = false;
360
+ bool end_of_stream = false;
361
+
362
+ char32_t input_char;
363
+ while (true) {
364
+ fflush(out); // Ensure all output is displayed before waiting for input
365
+ input_char = getchar32();
366
+
367
+ if (input_char == '\r' || input_char == '\n') {
368
+ break;
369
+ }
370
+
371
+ if (input_char == (char32_t) WEOF || input_char == 0x04 /* Ctrl+D*/) {
372
+ end_of_stream = true;
373
+ break;
374
+ }
375
+
376
+ if (is_special_char) {
377
+ set_display(user_input);
378
+ replace_last(line.back());
379
+ is_special_char = false;
380
+ }
381
+
382
+ if (input_char == '\033') { // Escape sequence
383
+ char32_t code = getchar32();
384
+ if (code == '[' || code == 0x1B) {
385
+ // Discard the rest of the escape sequence
386
+ while ((code = getchar32()) != (char32_t) WEOF) {
387
+ if ((code >= 'A' && code <= 'Z') || (code >= 'a' && code <= 'z') || code == '~') {
388
+ break;
389
+ }
390
+ }
391
+ }
392
+ } else if (input_char == 0x08 || input_char == 0x7F) { // Backspace
393
+ if (!widths.empty()) {
394
+ int count;
395
+ do {
396
+ count = widths.back();
397
+ widths.pop_back();
398
+ // Move cursor back, print space, and move cursor back again
399
+ for (int i = 0; i < count; i++) {
400
+ replace_last(' ');
401
+ pop_cursor();
402
+ }
403
+ pop_back_utf8_char(line);
404
+ } while (count == 0 && !widths.empty());
405
+ }
406
+ } else {
407
+ int offset = line.length();
408
+ append_utf8(input_char, line);
409
+ int width = put_codepoint(line.c_str() + offset, line.length() - offset, estimateWidth(input_char));
410
+ if (width < 0) {
411
+ width = 0;
412
+ }
413
+ widths.push_back(width);
414
+ }
415
+
416
+ if (!line.empty() && (line.back() == '\\' || line.back() == '/')) {
417
+ set_display(prompt);
418
+ replace_last(line.back());
419
+ is_special_char = true;
420
+ }
421
+ }
422
+
423
+ bool has_more = multiline_input;
424
+ if (is_special_char) {
425
+ replace_last(' ');
426
+ pop_cursor();
427
+
428
+ char last = line.back();
429
+ line.pop_back();
430
+ if (last == '\\') {
431
+ line += '\n';
432
+ fputc('\n', out);
433
+ has_more = !has_more;
434
+ } else {
435
+ // llama will just eat the single space, it won't act as a space
436
+ if (line.length() == 1 && line.back() == ' ') {
437
+ line.clear();
438
+ pop_cursor();
439
+ }
440
+ has_more = false;
441
+ }
442
+ } else {
443
+ if (end_of_stream) {
444
+ has_more = false;
445
+ } else {
446
+ line += '\n';
447
+ fputc('\n', out);
448
+ }
449
+ }
450
+
451
+ fflush(out);
452
+ return has_more;
453
+ }
454
+
455
+ static bool readline_simple(std::string & line, bool multiline_input) {
456
+ #if defined(_WIN32)
457
+ std::wstring wline;
458
+ if (!std::getline(std::wcin, wline)) {
459
+ // Input stream is bad or EOF received
460
+ line.clear();
461
+ GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0);
462
+ return false;
463
+ }
464
+
465
+ int size_needed = WideCharToMultiByte(CP_UTF8, 0, &wline[0], (int)wline.size(), NULL, 0, NULL, NULL);
466
+ line.resize(size_needed);
467
+ WideCharToMultiByte(CP_UTF8, 0, &wline[0], (int)wline.size(), &line[0], size_needed, NULL, NULL);
468
+ #else
469
+ if (!std::getline(std::cin, line)) {
470
+ // Input stream is bad or EOF received
471
+ line.clear();
472
+ return false;
473
+ }
474
+ #endif
475
+ if (!line.empty()) {
476
+ char last = line.back();
477
+ if (last == '/') { // Always return control on '/' symbol
478
+ line.pop_back();
479
+ return false;
480
+ }
481
+ if (last == '\\') { // '\\' changes the default action
482
+ line.pop_back();
483
+ multiline_input = !multiline_input;
484
+ }
485
+ }
486
+ line += '\n';
487
+
488
+ // By default, continue input if multiline_input is set
489
+ return multiline_input;
490
+ }
491
+
492
+ bool readline(std::string & line, bool multiline_input) {
493
+ set_display(user_input);
494
+
495
+ if (simple_io) {
496
+ return readline_simple(line, multiline_input);
497
+ }
498
+ return readline_advanced(line, multiline_input);
499
+ }
500
+
501
+ }
@@ -0,0 +1,19 @@
1
+ // Console functions
2
+
3
+ #pragma once
4
+
5
+ #include <string>
6
+
7
+ namespace console {
8
+ enum display_t {
9
+ reset = 0,
10
+ prompt,
11
+ user_input,
12
+ error
13
+ };
14
+
15
+ void init(bool use_simple_io, bool use_advanced_display);
16
+ void cleanup();
17
+ void set_display(display_t display);
18
+ bool readline(std::string & line, bool multiline_input);
19
+ }