synabun 1.3.0

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 (187) hide show
  1. package/CHANGELOG.md +665 -0
  2. package/LICENSE +191 -0
  3. package/README.md +853 -0
  4. package/hooks/claude-code/post-plan.mjs +391 -0
  5. package/hooks/claude-code/post-remember.mjs +239 -0
  6. package/hooks/claude-code/pre-compact.mjs +241 -0
  7. package/hooks/claude-code/pre-websearch.mjs +90 -0
  8. package/hooks/claude-code/prompt-submit.mjs +861 -0
  9. package/hooks/claude-code/session-start.mjs +494 -0
  10. package/hooks/claude-code/shared.mjs +368 -0
  11. package/hooks/claude-code/stop.mjs +646 -0
  12. package/hooks/claude-code/test-user-learning.mjs +531 -0
  13. package/mcp-server/package.json +38 -0
  14. package/mcp-server/run.mjs +10 -0
  15. package/mcp-server/src/config.ts +70 -0
  16. package/mcp-server/src/http.ts +93 -0
  17. package/mcp-server/src/index.ts +203 -0
  18. package/mcp-server/src/preload-http.ts +25 -0
  19. package/mcp-server/src/preload.ts +29 -0
  20. package/mcp-server/src/scripts/migrate-qdrant-to-sqlite.ts +506 -0
  21. package/mcp-server/src/services/categories.ts +429 -0
  22. package/mcp-server/src/services/discord.ts +702 -0
  23. package/mcp-server/src/services/file-checksums.ts +33 -0
  24. package/mcp-server/src/services/local-embeddings.ts +77 -0
  25. package/mcp-server/src/services/neural-interface.ts +344 -0
  26. package/mcp-server/src/services/sqlite.ts +823 -0
  27. package/mcp-server/src/tools/browser-advanced.ts +123 -0
  28. package/mcp-server/src/tools/browser-interact.ts +255 -0
  29. package/mcp-server/src/tools/browser-navigate.ts +77 -0
  30. package/mcp-server/src/tools/browser-observe.ts +1330 -0
  31. package/mcp-server/src/tools/browser.ts +107 -0
  32. package/mcp-server/src/tools/card-tools.ts +193 -0
  33. package/mcp-server/src/tools/card.ts +22 -0
  34. package/mcp-server/src/tools/category.ts +379 -0
  35. package/mcp-server/src/tools/discord-channel.ts +274 -0
  36. package/mcp-server/src/tools/discord-guild.ts +188 -0
  37. package/mcp-server/src/tools/discord-member.ts +158 -0
  38. package/mcp-server/src/tools/discord-message.ts +231 -0
  39. package/mcp-server/src/tools/discord-onboarding.ts +228 -0
  40. package/mcp-server/src/tools/discord-role.ts +209 -0
  41. package/mcp-server/src/tools/discord-thread.ts +110 -0
  42. package/mcp-server/src/tools/discord-webhook.ts +176 -0
  43. package/mcp-server/src/tools/discord.ts +40 -0
  44. package/mcp-server/src/tools/forget.ts +38 -0
  45. package/mcp-server/src/tools/git-tools.ts +141 -0
  46. package/mcp-server/src/tools/git.ts +13 -0
  47. package/mcp-server/src/tools/image-tools.ts +98 -0
  48. package/mcp-server/src/tools/image.ts +17 -0
  49. package/mcp-server/src/tools/leonardo-browser-tools.ts +281 -0
  50. package/mcp-server/src/tools/leonardo.ts +28 -0
  51. package/mcp-server/src/tools/loop.ts +348 -0
  52. package/mcp-server/src/tools/memories.ts +118 -0
  53. package/mcp-server/src/tools/recall.ts +323 -0
  54. package/mcp-server/src/tools/reflect.ts +145 -0
  55. package/mcp-server/src/tools/remember.ts +115 -0
  56. package/mcp-server/src/tools/response.ts +26 -0
  57. package/mcp-server/src/tools/restore.ts +34 -0
  58. package/mcp-server/src/tools/sync.ts +114 -0
  59. package/mcp-server/src/tools/tictactoe-tools.ts +98 -0
  60. package/mcp-server/src/tools/tictactoe.ts +13 -0
  61. package/mcp-server/src/tools/utils.ts +25 -0
  62. package/mcp-server/src/tools/whiteboard-tools.ts +260 -0
  63. package/mcp-server/src/tools/whiteboard.ts +22 -0
  64. package/mcp-server/src/tui.ts +940 -0
  65. package/mcp-server/src/types.ts +85 -0
  66. package/mcp-server/tsconfig.json +19 -0
  67. package/neural-interface/package.json +27 -0
  68. package/neural-interface/public/apple-touch-icon.png +0 -0
  69. package/neural-interface/public/category-logos/claude.svg +1 -0
  70. package/neural-interface/public/category-logos/gemini-color.svg +1 -0
  71. package/neural-interface/public/category-logos/openai.svg +1 -0
  72. package/neural-interface/public/category-logos/synabun.png +0 -0
  73. package/neural-interface/public/claude-chat.css +878 -0
  74. package/neural-interface/public/claude-chat.html +92 -0
  75. package/neural-interface/public/claude-chat.js +1168 -0
  76. package/neural-interface/public/favicon-16x16.png +0 -0
  77. package/neural-interface/public/favicon-32x32.png +0 -0
  78. package/neural-interface/public/gallery.svg +6 -0
  79. package/neural-interface/public/icon-192.png +0 -0
  80. package/neural-interface/public/icon-512.png +0 -0
  81. package/neural-interface/public/index-legacy.html +14677 -0
  82. package/neural-interface/public/index.html +212 -0
  83. package/neural-interface/public/index2d-legacy.html +8193 -0
  84. package/neural-interface/public/index2d.html +127 -0
  85. package/neural-interface/public/invite.html +351 -0
  86. package/neural-interface/public/leonardoai.svg +1 -0
  87. package/neural-interface/public/logo-synabun.png +0 -0
  88. package/neural-interface/public/logoHD.png +0 -0
  89. package/neural-interface/public/manifest.json +14 -0
  90. package/neural-interface/public/offline.html +299 -0
  91. package/neural-interface/public/onboarding.html +2335 -0
  92. package/neural-interface/public/openclaw-logo-text.png +0 -0
  93. package/neural-interface/public/pin-svgrepo-com.svg +25 -0
  94. package/neural-interface/public/sessionicon.svg +8 -0
  95. package/neural-interface/public/shared/ansi-parser.js +305 -0
  96. package/neural-interface/public/shared/api.js +1043 -0
  97. package/neural-interface/public/shared/colors.js +153 -0
  98. package/neural-interface/public/shared/constants.js +141 -0
  99. package/neural-interface/public/shared/html-shell.js +777 -0
  100. package/neural-interface/public/shared/html-term-renderer.js +1022 -0
  101. package/neural-interface/public/shared/i18n.js +147 -0
  102. package/neural-interface/public/shared/registry.js +82 -0
  103. package/neural-interface/public/shared/state.js +86 -0
  104. package/neural-interface/public/shared/storage.js +150 -0
  105. package/neural-interface/public/shared/styles.css +21212 -0
  106. package/neural-interface/public/shared/ui-automation-studio.js +3573 -0
  107. package/neural-interface/public/shared/ui-bookmarks.js +231 -0
  108. package/neural-interface/public/shared/ui-claude-panel.js +6333 -0
  109. package/neural-interface/public/shared/ui-command-runner.js +534 -0
  110. package/neural-interface/public/shared/ui-cost-widget.js +602 -0
  111. package/neural-interface/public/shared/ui-detail.js +1454 -0
  112. package/neural-interface/public/shared/ui-explorer.js +1356 -0
  113. package/neural-interface/public/shared/ui-file-explorer.js +2750 -0
  114. package/neural-interface/public/shared/ui-games.js +411 -0
  115. package/neural-interface/public/shared/ui-help.js +107 -0
  116. package/neural-interface/public/shared/ui-image-gallery.js +461 -0
  117. package/neural-interface/public/shared/ui-invite.js +519 -0
  118. package/neural-interface/public/shared/ui-keybinds.js +452 -0
  119. package/neural-interface/public/shared/ui-layouts.js +297 -0
  120. package/neural-interface/public/shared/ui-link.js +731 -0
  121. package/neural-interface/public/shared/ui-loading.js +255 -0
  122. package/neural-interface/public/shared/ui-menubar.js +499 -0
  123. package/neural-interface/public/shared/ui-multiselect.js +93 -0
  124. package/neural-interface/public/shared/ui-navbar.js +222 -0
  125. package/neural-interface/public/shared/ui-notifications.js +287 -0
  126. package/neural-interface/public/shared/ui-panels.js +309 -0
  127. package/neural-interface/public/shared/ui-resume.js +653 -0
  128. package/neural-interface/public/shared/ui-search.js +145 -0
  129. package/neural-interface/public/shared/ui-sessions.js +531 -0
  130. package/neural-interface/public/shared/ui-settings.js +5987 -0
  131. package/neural-interface/public/shared/ui-sidebar.js +1905 -0
  132. package/neural-interface/public/shared/ui-skills.js +2805 -0
  133. package/neural-interface/public/shared/ui-stats.js +38 -0
  134. package/neural-interface/public/shared/ui-sync.js +201 -0
  135. package/neural-interface/public/shared/ui-terminal.js +6385 -0
  136. package/neural-interface/public/shared/ui-tooltip.js +123 -0
  137. package/neural-interface/public/shared/ui-trash.js +439 -0
  138. package/neural-interface/public/shared/ui-tutorial-draw.js +875 -0
  139. package/neural-interface/public/shared/ui-tutorial-steps.js +2276 -0
  140. package/neural-interface/public/shared/ui-tutorial.js +1117 -0
  141. package/neural-interface/public/shared/ui-update.js +244 -0
  142. package/neural-interface/public/shared/ui-whiteboard.js +3262 -0
  143. package/neural-interface/public/shared/ui-workspaces.js +722 -0
  144. package/neural-interface/public/shared/utils.js +360 -0
  145. package/neural-interface/public/shared/vterm-buffer.js +1102 -0
  146. package/neural-interface/public/sw.js +52 -0
  147. package/neural-interface/public/synabun.png +0 -0
  148. package/neural-interface/public/toolbar-album.svg +8 -0
  149. package/neural-interface/public/toolbar-question.svg +6 -0
  150. package/neural-interface/public/toolbar-sessions.svg +6 -0
  151. package/neural-interface/public/variant/2d/background.js +113 -0
  152. package/neural-interface/public/variant/2d/context-menu.js +133 -0
  153. package/neural-interface/public/variant/2d/gfx.js +45 -0
  154. package/neural-interface/public/variant/2d/graph.js +1635 -0
  155. package/neural-interface/public/variant/2d/hulls.js +207 -0
  156. package/neural-interface/public/variant/2d/lasso.js +135 -0
  157. package/neural-interface/public/variant/2d/layout.js +594 -0
  158. package/neural-interface/public/variant/2d/main.js +521 -0
  159. package/neural-interface/public/variant/2d/minimap.js +312 -0
  160. package/neural-interface/public/variant/2d/settings-gfx.js +98 -0
  161. package/neural-interface/public/variant/3d/background.js +884 -0
  162. package/neural-interface/public/variant/3d/camera.js +661 -0
  163. package/neural-interface/public/variant/3d/gfx.js +116 -0
  164. package/neural-interface/public/variant/3d/graph.js +2399 -0
  165. package/neural-interface/public/variant/3d/main.js +500 -0
  166. package/neural-interface/public/variant/3d/settings-gfx.js +228 -0
  167. package/neural-interface/scripts/rebuild-pty.js +100 -0
  168. package/neural-interface/server.js +15000 -0
  169. package/neural-interface/templates/CLAUDE-template.md +211 -0
  170. package/package.json +53 -0
  171. package/postinstall.js +135 -0
  172. package/setup.js +260 -0
  173. package/skills/leonardo/SKILL.md +159 -0
  174. package/skills/leonardo/icon.svg +1 -0
  175. package/skills/leonardo/modules/browser-guide.md +378 -0
  176. package/skills/leonardo/modules/image-prompter.md +277 -0
  177. package/skills/leonardo/modules/model-advisor.md +100 -0
  178. package/skills/leonardo/modules/prompt-library.md +110 -0
  179. package/skills/leonardo/modules/style-guide.md +186 -0
  180. package/skills/leonardo/modules/video-prompter.md +311 -0
  181. package/skills/synabun/SKILL.md +185 -0
  182. package/skills/synabun/icon.png +0 -0
  183. package/skills/synabun/modules/audit.md +374 -0
  184. package/skills/synabun/modules/changelog.md +194 -0
  185. package/skills/synabun/modules/idea.md +144 -0
  186. package/skills/synabun/modules/memorize.md +188 -0
  187. package/skills/synabun/synabunicon.png +0 -0
@@ -0,0 +1,25 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+
3
+ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
4
+ <!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
5
+ <svg height="800px" width="800px" version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
6
+ viewBox="0 0 40 40" enable-background="new 0 0 40 40" xml:space="preserve">
7
+ <g>
8
+ <g>
9
+ <g>
10
+ <g>
11
+ <path fill="#231815" d="M19.9,28.2c-0.1,0-0.3-0.1-0.4-0.1l-7.6-7.6c-0.2-0.2-0.2-0.5,0-0.7c1.2-1.2,3.1-1.5,4.6-0.8l4-4l0,0
12
+ c-0.3-0.3-0.5-0.8-0.5-1.2s0.2-0.9,0.5-1.2l0.2-0.2c0.7-0.7,1.8-0.7,2.4,0l4.6,4.6c0.3,0.3,0.5,0.8,0.5,1.2S28,19,27.7,19.3
13
+ l-0.2,0.2c-0.7,0.7-1.8,0.7-2.4,0l0,0l-4,4c0.7,1.5,0.4,3.4-0.8,4.6C20.1,28.2,20,28.2,19.9,28.2z M13,20.2l6.8,6.8
14
+ c0.7-1,0.8-2.3,0.1-3.3c-0.1-0.2-0.1-0.4,0.1-0.6l4.7-4.7c0.2-0.2,0.5-0.2,0.7,0l0.4,0.4c0.3,0.3,0.8,0.3,1,0l0.2-0.2
15
+ c0.1-0.1,0.2-0.3,0.2-0.5s-0.1-0.4-0.2-0.5L22.4,13c-0.3-0.3-0.8-0.3-1,0l-0.2,0.2c-0.1,0.1-0.2,0.3-0.2,0.5s0.1,0.4,0.2,0.5
16
+ l0.4,0.4c0.2,0.2,0.2,0.5,0,0.7L17,19.9c-0.2,0.2-0.4,0.2-0.6,0.1C15.3,19.4,14,19.5,13,20.2z"/>
17
+ </g>
18
+ <g>
19
+ <path fill="#231815" d="M16.4,24.3l-3.3,3.3c-0.1,0.1-0.2,0.1-0.4,0.1s-0.3,0-0.4-0.1c-0.2-0.2-0.2-0.5,0-0.7l3.3-3.3L16.4,24.3
20
+ z"/>
21
+ </g>
22
+ </g>
23
+ </g>
24
+ </g>
25
+ </svg>
@@ -0,0 +1,8 @@
1
+ <?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
2
+ <svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
3
+ <path d="M3 10V18C3 19.1046 3.89543 20 5 20H9M3 10V6C3 4.89543 3.89543 4 5 4H19C20.1046 4 21 4.89543 21 6V10M3 10H21M21 10V13" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
4
+ <path d="M15 16L13 18L15 20" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
5
+ <path d="M19 16L21 18L19 20" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
6
+ <circle cx="6" cy="7" r="1" fill="#000000"/>
7
+ <circle cx="9" cy="7" r="1" fill="#000000"/>
8
+ </svg>
@@ -0,0 +1,305 @@
1
+ /**
2
+ * ansi-parser.js — Streaming ANSI escape code state machine
3
+ *
4
+ * Parses raw PTY output into structured handler calls. Designed for
5
+ * pairing with VTermBuffer but any object implementing the handler
6
+ * interface will work.
7
+ *
8
+ * Handler interface:
9
+ * print(text) — printable characters
10
+ * execute(code) — C0 control codes (BS, TAB, CR, LF, etc.)
11
+ * csiDispatch(params, intermediates, final) — CSI sequences
12
+ * escDispatch(intermediates, final) — simple ESC sequences
13
+ * oscDispatch(data) — OSC strings (title, hyperlinks)
14
+ */
15
+
16
+ // C0 control codes that get dispatched via execute()
17
+ const C0_EXECUTE = new Set([
18
+ 0x07, // BEL
19
+ 0x08, // BS
20
+ 0x09, // HT (tab)
21
+ 0x0a, // LF
22
+ 0x0b, // VT (treat as LF)
23
+ 0x0c, // FF (treat as LF)
24
+ 0x0d, // CR
25
+ ]);
26
+
27
+ // Parser states
28
+ const S_GROUND = 0;
29
+ const S_ESCAPE = 1;
30
+ const S_ESCAPE_INTER = 2;
31
+ const S_CSI_ENTRY = 3;
32
+ const S_CSI_PARAM = 4;
33
+ const S_CSI_INTER = 5;
34
+ const S_OSC_STRING = 6;
35
+ const S_DCS_PASSTHRU = 7; // we mostly ignore DCS but need to consume it
36
+
37
+ export class AnsiParser {
38
+ /**
39
+ * @param {object} handler — object implementing print/execute/csiDispatch/escDispatch/oscDispatch
40
+ */
41
+ constructor(handler) {
42
+ this._handler = handler;
43
+ this._state = S_GROUND;
44
+
45
+ // CSI accumulators
46
+ this._params = '';
47
+ this._intermediates = '';
48
+
49
+ // OSC accumulator
50
+ this._oscData = '';
51
+
52
+ // Printable text batch buffer
53
+ this._printBuf = '';
54
+ }
55
+
56
+ /** Flush any accumulated printable text to the handler */
57
+ _flushPrint() {
58
+ if (this._printBuf.length > 0) {
59
+ this._handler.print(this._printBuf);
60
+ this._printBuf = '';
61
+ }
62
+ }
63
+
64
+ /**
65
+ * Feed raw PTY data. Handles partial sequences across calls.
66
+ * @param {string} data
67
+ */
68
+ parse(data) {
69
+ const len = data.length;
70
+
71
+ for (let i = 0; i < len; i++) {
72
+ const ch = data.charCodeAt(i);
73
+
74
+ switch (this._state) {
75
+
76
+ // ─── GROUND ────────────────────────────────────────
77
+ case S_GROUND:
78
+ if (ch === 0x1b) {
79
+ // ESC — start escape sequence
80
+ this._flushPrint();
81
+ this._state = S_ESCAPE;
82
+ } else if (C0_EXECUTE.has(ch)) {
83
+ this._flushPrint();
84
+ this._handler.execute(ch);
85
+ } else if (ch >= 0x20) {
86
+ // Printable — batch consecutive chars for efficiency
87
+ // Scan ahead for more printable chars
88
+ let end = i + 1;
89
+ while (end < len) {
90
+ const c = data.charCodeAt(end);
91
+ if (c < 0x20 || c === 0x1b) break;
92
+ end++;
93
+ }
94
+ this._printBuf += data.substring(i, end);
95
+ i = end - 1; // -1 because loop increments
96
+ }
97
+ // else: ignore other C0 codes (NUL, etc.)
98
+ break;
99
+
100
+ // ─── ESCAPE ────────────────────────────────────────
101
+ case S_ESCAPE:
102
+ if (ch === 0x5b) {
103
+ // ESC [ → CSI
104
+ this._state = S_CSI_ENTRY;
105
+ this._params = '';
106
+ this._intermediates = '';
107
+ } else if (ch === 0x5d) {
108
+ // ESC ] → OSC
109
+ this._state = S_OSC_STRING;
110
+ this._oscData = '';
111
+ } else if (ch === 0x50) {
112
+ // ESC P → DCS (consume until ST)
113
+ this._state = S_DCS_PASSTHRU;
114
+ } else if (ch >= 0x20 && ch <= 0x2f) {
115
+ // Intermediate bytes → ESC intermediate
116
+ this._intermediates = String.fromCharCode(ch);
117
+ this._state = S_ESCAPE_INTER;
118
+ } else if (ch >= 0x30 && ch <= 0x7e) {
119
+ // Final byte — dispatch simple ESC sequence
120
+ this._handler.escDispatch(this._intermediates, String.fromCharCode(ch));
121
+ this._intermediates = '';
122
+ this._state = S_GROUND;
123
+ } else if (ch === 0x1b) {
124
+ // Double ESC — stay in escape state
125
+ } else {
126
+ // Invalid — return to ground
127
+ this._state = S_GROUND;
128
+ }
129
+ break;
130
+
131
+ // ─── ESCAPE INTERMEDIATE ───────────────────────────
132
+ case S_ESCAPE_INTER:
133
+ if (ch >= 0x20 && ch <= 0x2f) {
134
+ this._intermediates += String.fromCharCode(ch);
135
+ } else if (ch >= 0x30 && ch <= 0x7e) {
136
+ this._handler.escDispatch(this._intermediates, String.fromCharCode(ch));
137
+ this._intermediates = '';
138
+ this._state = S_GROUND;
139
+ } else {
140
+ // Invalid → ground
141
+ this._intermediates = '';
142
+ this._state = S_GROUND;
143
+ }
144
+ break;
145
+
146
+ // ─── CSI ENTRY ─────────────────────────────────────
147
+ case S_CSI_ENTRY:
148
+ if (ch >= 0x30 && ch <= 0x3f) {
149
+ // Parameter byte (0-9, ;, <, =, >, ?)
150
+ this._params += String.fromCharCode(ch);
151
+ this._state = S_CSI_PARAM;
152
+ } else if (ch >= 0x20 && ch <= 0x2f) {
153
+ // Intermediate byte
154
+ this._intermediates += String.fromCharCode(ch);
155
+ this._state = S_CSI_INTER;
156
+ } else if (ch >= 0x40 && ch <= 0x7e) {
157
+ // Final byte — dispatch immediately (no params)
158
+ this._dispatchCSI(String.fromCharCode(ch));
159
+ this._state = S_GROUND;
160
+ } else if (ch === 0x1b) {
161
+ // ESC inside CSI — abort and restart
162
+ this._state = S_ESCAPE;
163
+ } else {
164
+ // Ignore other
165
+ }
166
+ break;
167
+
168
+ // ─── CSI PARAM ─────────────────────────────────────
169
+ case S_CSI_PARAM:
170
+ if (ch >= 0x30 && ch <= 0x3f) {
171
+ // More parameter bytes
172
+ this._params += String.fromCharCode(ch);
173
+ } else if (ch >= 0x20 && ch <= 0x2f) {
174
+ // Intermediate
175
+ this._intermediates += String.fromCharCode(ch);
176
+ this._state = S_CSI_INTER;
177
+ } else if (ch >= 0x40 && ch <= 0x7e) {
178
+ // Final byte
179
+ this._dispatchCSI(String.fromCharCode(ch));
180
+ this._state = S_GROUND;
181
+ } else if (ch === 0x1b) {
182
+ this._state = S_ESCAPE;
183
+ } else {
184
+ // Ignore
185
+ }
186
+ break;
187
+
188
+ // ─── CSI INTERMEDIATE ──────────────────────────────
189
+ case S_CSI_INTER:
190
+ if (ch >= 0x20 && ch <= 0x2f) {
191
+ this._intermediates += String.fromCharCode(ch);
192
+ } else if (ch >= 0x40 && ch <= 0x7e) {
193
+ this._dispatchCSI(String.fromCharCode(ch));
194
+ this._state = S_GROUND;
195
+ } else if (ch === 0x1b) {
196
+ this._state = S_ESCAPE;
197
+ } else {
198
+ // Ignore
199
+ }
200
+ break;
201
+
202
+ // ─── OSC STRING ────────────────────────────────────
203
+ case S_OSC_STRING:
204
+ if (ch === 0x07) {
205
+ // BEL terminates OSC
206
+ this._handler.oscDispatch(this._oscData);
207
+ this._oscData = '';
208
+ this._state = S_GROUND;
209
+ } else if (ch === 0x1b) {
210
+ // Check for ST (ESC \)
211
+ if (i + 1 < len && data.charCodeAt(i + 1) === 0x5c) {
212
+ // ESC \ = ST
213
+ this._handler.oscDispatch(this._oscData);
214
+ this._oscData = '';
215
+ this._state = S_GROUND;
216
+ i++; // skip the backslash
217
+ } else {
218
+ // Bare ESC inside OSC — terminate OSC, reprocess ESC
219
+ this._handler.oscDispatch(this._oscData);
220
+ this._oscData = '';
221
+ this._state = S_ESCAPE;
222
+ }
223
+ } else if (ch === 0x9c) {
224
+ // ST (C1) terminates OSC
225
+ this._handler.oscDispatch(this._oscData);
226
+ this._oscData = '';
227
+ this._state = S_GROUND;
228
+ } else {
229
+ this._oscData += String.fromCharCode(ch);
230
+ }
231
+ break;
232
+
233
+ // ─── DCS PASSTHROUGH ───────────────────────────────
234
+ case S_DCS_PASSTHRU:
235
+ // Consume until ST (ESC \) or BEL
236
+ if (ch === 0x1b) {
237
+ if (i + 1 < len && data.charCodeAt(i + 1) === 0x5c) {
238
+ this._state = S_GROUND;
239
+ i++; // skip backslash
240
+ }
241
+ } else if (ch === 0x07 || ch === 0x9c) {
242
+ this._state = S_GROUND;
243
+ }
244
+ break;
245
+ }
246
+ }
247
+
248
+ // Flush any remaining printable text
249
+ this._flushPrint();
250
+ }
251
+
252
+ /**
253
+ * Parse CSI params string and dispatch to handler.
254
+ * Params format: "?25" or "1;2" or "38;2;255;128;0" or "" etc.
255
+ */
256
+ _dispatchCSI(final) {
257
+ // Extract private marker (?, >, !) if present
258
+ let privateMarker = '';
259
+ let paramStr = this._params;
260
+ if (paramStr.length > 0) {
261
+ const first = paramStr.charCodeAt(0);
262
+ if (first === 0x3f || first === 0x3e || first === 0x21) {
263
+ // ? > ! are private markers
264
+ privateMarker = paramStr[0];
265
+ paramStr = paramStr.substring(1);
266
+ }
267
+ }
268
+
269
+ // Parse semicolon-separated numeric params
270
+ // Supports colon sub-params (e.g., 38:2:255:128:0 for truecolor)
271
+ const params = [];
272
+ if (paramStr.length > 0) {
273
+ const parts = paramStr.split(';');
274
+ for (let p = 0; p < parts.length; p++) {
275
+ const part = parts[p];
276
+ if (part.indexOf(':') !== -1) {
277
+ // Sub-params — store as array within params
278
+ const subParts = part.split(':');
279
+ const subNums = [];
280
+ for (let s = 0; s < subParts.length; s++) {
281
+ subNums.push(subParts[s] === '' ? 0 : parseInt(subParts[s], 10));
282
+ }
283
+ params.push(subNums);
284
+ } else {
285
+ params.push(part === '' ? 0 : parseInt(part, 10));
286
+ }
287
+ }
288
+ }
289
+
290
+ this._handler.csiDispatch(params, privateMarker, this._intermediates, final);
291
+
292
+ // Reset
293
+ this._params = '';
294
+ this._intermediates = '';
295
+ }
296
+
297
+ /** Reset parser to ground state (e.g., on RIS) */
298
+ reset() {
299
+ this._state = S_GROUND;
300
+ this._params = '';
301
+ this._intermediates = '';
302
+ this._oscData = '';
303
+ this._printBuf = '';
304
+ }
305
+ }