mixdog 0.9.2 → 0.9.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -1
- package/scripts/anthropic-maxtokens-test.mjs +119 -0
- package/scripts/build-tui.mjs +13 -1
- package/scripts/explore-bench.mjs +124 -0
- package/scripts/hook-bus-test.mjs +191 -0
- package/scripts/path-suffix-test.mjs +57 -0
- package/scripts/recall-bench.mjs +207 -0
- package/scripts/tool-smoke.mjs +7 -4
- package/src/agents/debugger/AGENT.md +2 -2
- package/src/agents/heavy-worker/AGENT.md +20 -11
- package/src/agents/reviewer/AGENT.md +2 -2
- package/src/agents/worker/AGENT.md +17 -11
- package/src/mixdog-session-runtime.mjs +424 -1812
- package/src/repl.mjs +5 -5
- package/src/rules/agent/30-explorer.md +8 -11
- package/src/rules/lead/lead-tool.md +9 -5
- package/src/rules/shared/01-tool.md +11 -5
- package/src/runtime/agent/orchestrator/context/collect.mjs +51 -0
- package/src/runtime/agent/orchestrator/mcp/client.mjs +6 -2
- package/src/runtime/agent/orchestrator/providers/anthropic-effort.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens.mjs +93 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +22 -68
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +46 -7
- package/src/runtime/agent/orchestrator/providers/api-usage.mjs +1 -13
- package/src/runtime/agent/orchestrator/providers/gemini.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/grok-oauth.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/lib/usage-primitives.mjs +32 -0
- package/src/runtime/agent/orchestrator/providers/oauth-usage.mjs +54 -20
- package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +19 -12
- package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +7 -5
- package/src/runtime/agent/orchestrator/providers/openai-oauth-ws.mjs +33 -23
- package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +31 -14
- package/src/runtime/agent/orchestrator/providers/opencode-go-usage.mjs +38 -12
- package/src/runtime/agent/orchestrator/providers/retry-classifier.mjs +7 -8
- package/src/runtime/agent/orchestrator/session/loop/compact-debug.mjs +28 -0
- package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +262 -0
- package/src/runtime/agent/orchestrator/session/loop/context-overflow.mjs +38 -0
- package/src/runtime/agent/orchestrator/session/loop/env.mjs +14 -0
- package/src/runtime/agent/orchestrator/session/loop/hidden-agents.mjs +21 -0
- package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +49 -0
- package/src/runtime/agent/orchestrator/session/loop/steering.mjs +63 -0
- package/src/runtime/agent/orchestrator/session/loop/stored-tool-args.mjs +100 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-classify.mjs +52 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +218 -0
- package/src/runtime/agent/orchestrator/session/loop/transcript-repair.mjs +101 -0
- package/src/runtime/agent/orchestrator/session/loop/usage.mjs +35 -0
- package/src/runtime/agent/orchestrator/session/loop.mjs +169 -918
- package/src/runtime/agent/orchestrator/session/manager/context-meta.mjs +227 -0
- package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +235 -0
- package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +137 -0
- package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +155 -0
- package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +303 -0
- package/src/runtime/agent/orchestrator/session/manager.mjs +65 -1032
- package/src/runtime/agent/orchestrator/stall-policy.mjs +3 -3
- package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.mjs +241 -0
- package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.test.mjs +162 -0
- package/src/runtime/agent/orchestrator/tools/builtin/fuzzy-match.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/path-diagnostics.mjs +42 -2
- package/src/runtime/agent/orchestrator/tools/builtin/read-formatting.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-tool.mjs +11 -4
- package/src/runtime/agent/orchestrator/tools/builtin/search-tool.mjs +5 -0
- package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +50 -39
- package/src/runtime/agent/orchestrator/tools/builtin.mjs +11 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/build.mjs +303 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/constants.mjs +43 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/disk-cache.mjs +382 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/dispatch.mjs +497 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/graph-binary.mjs +295 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/graph-model.mjs +158 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/lang-predicates.mjs +128 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/memory-cache.mjs +66 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/project-root.mjs +44 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/search.mjs +1192 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/source-access.mjs +81 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/span.mjs +19 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/symbol-index.mjs +280 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/text-mask.mjs +347 -0
- package/src/runtime/agent/orchestrator/tools/code-graph.mjs +36 -4277
- package/src/runtime/agent/orchestrator/tools/patch.mjs +3 -3
- package/src/runtime/agent/orchestrator/tools/progress-message.mjs +1 -2
- package/src/runtime/agent/orchestrator/tools/shell-command.mjs +1 -2
- package/src/runtime/agent/orchestrator/tools/shell-snapshot.mjs +2 -4
- package/src/runtime/channels/index.mjs +14 -233
- package/src/runtime/channels/lib/boot-profile.mjs +23 -0
- package/src/runtime/channels/lib/crash-log.mjs +106 -0
- package/src/runtime/channels/lib/index-drop-trace.mjs +72 -0
- package/src/runtime/channels/lib/output-forwarder.mjs +8 -0
- package/src/runtime/channels/lib/telegram-format.mjs +19 -22
- package/src/runtime/channels/lib/whisper-language.mjs +42 -0
- package/src/runtime/memory/index.mjs +314 -359
- package/src/runtime/memory/lib/core-memory-store.mjs +351 -1
- package/src/runtime/memory/lib/cycle-signatures.mjs +34 -0
- package/src/runtime/memory/lib/http-wire.mjs +57 -0
- package/src/runtime/memory/lib/memory-cycle2.mjs +56 -3
- package/src/runtime/memory/lib/memory-recall-scope-filter.mjs +24 -0
- package/src/runtime/memory/lib/memory-retrievers.mjs +8 -0
- package/src/runtime/memory/lib/memory.mjs +20 -0
- package/src/runtime/memory/lib/promotion-fingerprint.mjs +50 -0
- package/src/runtime/memory/lib/recall-format.mjs +183 -0
- package/src/runtime/memory/tool-defs.mjs +4 -4
- package/src/runtime/shared/abort-controller.mjs +1 -1
- package/src/runtime/shared/background-tasks.mjs +2 -3
- package/src/runtime/shared/buffered-appender.mjs +149 -0
- package/src/runtime/shared/task-notification-envelope.mjs +98 -0
- package/src/runtime/shared/task-notification-envelope.test.mjs +107 -0
- package/src/runtime/shared/tool-execution-contract.mjs +2 -2
- package/src/runtime/shared/transcript-writer.mjs +29 -2
- package/src/session-runtime/config-helpers.mjs +209 -0
- package/src/session-runtime/effort.mjs +128 -0
- package/src/session-runtime/fs-utils.mjs +10 -0
- package/src/session-runtime/model-capabilities.mjs +130 -0
- package/src/session-runtime/output-styles.mjs +124 -0
- package/src/session-runtime/plugin-mcp.mjs +114 -0
- package/src/session-runtime/session-text.mjs +100 -0
- package/src/session-runtime/statusline-route.mjs +35 -0
- package/src/session-runtime/tool-catalog.mjs +720 -0
- package/src/session-runtime/workflow.mjs +358 -0
- package/src/standalone/agent-tool.mjs +49 -10
- package/src/standalone/channel-worker.mjs +3 -2
- package/src/standalone/explore-tool.mjs +10 -3
- package/src/standalone/hook-bus.mjs +165 -8
- package/src/standalone/opencode-go-login.mjs +121 -0
- package/src/standalone/provider-admin.mjs +14 -3
- package/src/tui/App.jsx +884 -143
- package/src/tui/components/PromptInput.jsx +272 -15
- package/src/tui/components/ToolExecution.jsx +20 -10
- package/src/tui/components/tool-output-format.mjs +2 -2
- package/src/tui/dist/index.mjs +1771 -1947
- package/src/tui/engine/agent-envelope.mjs +296 -0
- package/src/tui/engine/boot-profile.mjs +21 -0
- package/src/tui/engine/labels.mjs +67 -0
- package/src/tui/engine/notice-text.mjs +112 -0
- package/src/tui/engine/queue-helpers.mjs +161 -0
- package/src/tui/engine/session-stats.mjs +46 -0
- package/src/tui/engine/tool-call-fields.mjs +23 -0
- package/src/tui/engine/tool-result-text.mjs +126 -0
- package/src/tui/engine.mjs +311 -851
- package/src/tui/input-editing.mjs +58 -8
- package/src/tui/input-editing.selection.test.mjs +75 -0
- package/src/tui/keyboard-protocol.mjs +2 -2
- package/src/tui/lib/voice-recorder.mjs +35 -19
- package/src/tui/markdown/format-token.mjs +7 -8
- package/src/tui/markdown/format-token.test.mjs +3 -3
- package/src/tui/paste-attachments.mjs +38 -0
- package/src/tui/paste-fix.test.mjs +119 -0
- package/src/tui/themes/base.mjs +2 -2
- package/src/tui/themes/kanagawa.mjs +4 -4
- package/src/tui/themes/teal.mjs +4 -5
- package/src/tui/themes/utils.mjs +1 -1
- package/src/ui/statusline.mjs +49 -0
- package/src/workflows/default/WORKFLOW.md +16 -9
- package/src/workflows/sequential/WORKFLOW.md +16 -11
- package/src/workflows/solo/WORKFLOW.md +5 -1
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
// Non-code text masker: blanks comment/string/regex bytes so downstream
|
|
2
|
+
// identifier scans never match inside them. Byte-offset preserving (fills
|
|
3
|
+
// with spaces, keeps newlines) so match.index maps back to the raw source.
|
|
4
|
+
// Extracted verbatim from code-graph.mjs.
|
|
5
|
+
import {
|
|
6
|
+
_supportsHashComments,
|
|
7
|
+
_supportsSlashComments,
|
|
8
|
+
_supportsSingleQuoteStrings,
|
|
9
|
+
_supportsBacktickStrings,
|
|
10
|
+
_supportsTripleSingleQuoteStrings,
|
|
11
|
+
_supportsTripleDoubleQuoteStrings,
|
|
12
|
+
_isJsLike,
|
|
13
|
+
_isWordStartChar,
|
|
14
|
+
_isWordChar,
|
|
15
|
+
REGEX_PRECEDENT_KEYWORDS,
|
|
16
|
+
REGEX_PRECEDENT_CHARS,
|
|
17
|
+
} from './lang-predicates.mjs';
|
|
18
|
+
|
|
19
|
+
// Mask a JS regex literal body starting at `start` (which points at `/`).
|
|
20
|
+
// Handles `\` escapes and `[...]` character classes per ECMAScript spec.
|
|
21
|
+
// Returns the index just past the closing `/flags`. Bytes between the
|
|
22
|
+
// delimiters are replaced with spaces in `out` so downstream identifier
|
|
23
|
+
// searches do not see them.
|
|
24
|
+
export function _maskJsRegexLiteral(src, out, start) {
|
|
25
|
+
if (src[start] !== '\n') out[start] = ' ';
|
|
26
|
+
let j = start + 1;
|
|
27
|
+
let inCharClass = false;
|
|
28
|
+
while (j < src.length) {
|
|
29
|
+
const c = src[j];
|
|
30
|
+
if (c === '\n') return j;
|
|
31
|
+
if (c === '\\') {
|
|
32
|
+
if (src[j] !== '\n') out[j] = ' ';
|
|
33
|
+
if (j + 1 < src.length && src[j + 1] !== '\n') out[j + 1] = ' ';
|
|
34
|
+
j += 2;
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
if (c === '[' && !inCharClass) {
|
|
38
|
+
inCharClass = true;
|
|
39
|
+
if (src[j] !== '\n') out[j] = ' ';
|
|
40
|
+
j++;
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
if (c === ']' && inCharClass) {
|
|
44
|
+
inCharClass = false;
|
|
45
|
+
if (src[j] !== '\n') out[j] = ' ';
|
|
46
|
+
j++;
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
if (c === '/' && !inCharClass) {
|
|
50
|
+
if (src[j] !== '\n') out[j] = ' ';
|
|
51
|
+
j++;
|
|
52
|
+
while (j < src.length && src[j] >= 'a' && src[j] <= 'z') {
|
|
53
|
+
if (src[j] !== '\n') out[j] = ' ';
|
|
54
|
+
j++;
|
|
55
|
+
}
|
|
56
|
+
return j;
|
|
57
|
+
}
|
|
58
|
+
if (src[j] !== '\n') out[j] = ' ';
|
|
59
|
+
j++;
|
|
60
|
+
}
|
|
61
|
+
return j;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function _maskNonCodeText(text, lang) {
|
|
65
|
+
const src = String(text || '');
|
|
66
|
+
const out = src.split('');
|
|
67
|
+
let i = 0;
|
|
68
|
+
let blockComment = false;
|
|
69
|
+
// Stack of scanner frames. Top describes current state:
|
|
70
|
+
// { kind: 'string', delim } — inside single-line string literal (mask body)
|
|
71
|
+
// { kind: 'triple', delim } — inside triple-quote string (mask body)
|
|
72
|
+
// { kind: 'interp', braceDepth } — inside backtick `${...}` interpolation
|
|
73
|
+
// (code mode; bytes preserved so callers
|
|
74
|
+
// analysis can see fn-calls inside)
|
|
75
|
+
// Empty stack = top-level code.
|
|
76
|
+
const stack = [];
|
|
77
|
+
const top = () => (stack.length ? stack[stack.length - 1] : null);
|
|
78
|
+
// prevToken tracks ECMAScript token context for the `/`-disambiguation:
|
|
79
|
+
// 'expr' = expression-start (regex literal may follow)
|
|
80
|
+
// 'value' = value/operand (`/` is division)
|
|
81
|
+
// Start of file = expression context.
|
|
82
|
+
let prevToken = 'expr';
|
|
83
|
+
while (i < src.length) {
|
|
84
|
+
if (blockComment) {
|
|
85
|
+
if (src.startsWith('*/', i)) {
|
|
86
|
+
out[i] = ' ';
|
|
87
|
+
if (i + 1 < out.length) out[i + 1] = ' ';
|
|
88
|
+
i += 2;
|
|
89
|
+
blockComment = false;
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
if (src[i] !== '\n') out[i] = ' ';
|
|
93
|
+
i++;
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
const t = top();
|
|
97
|
+
if (t && t.kind === 'triple') {
|
|
98
|
+
if (src.startsWith(t.delim, i)) {
|
|
99
|
+
for (let j = 0; j < t.delim.length; j++) {
|
|
100
|
+
if (src[i + j] !== '\n') out[i + j] = ' ';
|
|
101
|
+
}
|
|
102
|
+
i += t.delim.length;
|
|
103
|
+
stack.pop();
|
|
104
|
+
prevToken = 'value';
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
if (src[i] !== '\n') out[i] = ' ';
|
|
108
|
+
i++;
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
if (t && t.kind === 'luablock') {
|
|
112
|
+
// Lua long-bracket comment `--[=*[ ... ]=*]` — mask until the EXACT
|
|
113
|
+
// matching close delimiter (`]` + same number of `=` + `]`) recorded
|
|
114
|
+
// on the frame, so `--[==[ ]] ]==]` closes only at `]==]`.
|
|
115
|
+
if (t.close && src.startsWith(t.close, i)) {
|
|
116
|
+
for (let j = 0; j < t.close.length; j++) {
|
|
117
|
+
if (src[i + j] !== '\n') out[i + j] = ' ';
|
|
118
|
+
}
|
|
119
|
+
i += t.close.length;
|
|
120
|
+
stack.pop();
|
|
121
|
+
prevToken = 'value';
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
if (src[i] !== '\n') out[i] = ' ';
|
|
125
|
+
i++;
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
if (t && t.kind === 'string') {
|
|
129
|
+
const d = t.delim;
|
|
130
|
+
if (d === '`' && src.startsWith('${', i)) {
|
|
131
|
+
// Enter interpolation. `${` itself is code-relevant — leave bytes intact.
|
|
132
|
+
stack.push({ kind: 'interp', braceDepth: 1 });
|
|
133
|
+
i += 2;
|
|
134
|
+
prevToken = 'expr';
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
// In bash single-quotes `'...'`, backslash is literal (no escape) — the
|
|
138
|
+
// string closes at the first `'`. Skip the escape consumption there so
|
|
139
|
+
// `'\'` is not mis-read as an escaped quote. bash `"..."` and all other
|
|
140
|
+
// langs keep backslash-escape handling.
|
|
141
|
+
const bashLiteralSingle = t.lang === 'bash' && d === '\'';
|
|
142
|
+
if (!bashLiteralSingle && src[i] === '\\' && (d === '\'' || d === '"' || d === '`')) {
|
|
143
|
+
if (src[i] !== '\n') out[i] = ' ';
|
|
144
|
+
if (i + 1 < src.length && src[i + 1] !== '\n') out[i + 1] = ' ';
|
|
145
|
+
i += 2;
|
|
146
|
+
continue;
|
|
147
|
+
}
|
|
148
|
+
if (src[i] === d) {
|
|
149
|
+
if (src[i] !== '\n') out[i] = ' ';
|
|
150
|
+
i++;
|
|
151
|
+
stack.pop();
|
|
152
|
+
prevToken = 'value';
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
// JS forbids a raw newline inside '...' or "..." — defensive reset. bash
|
|
156
|
+
// quoted strings legally span newlines, so do NOT reset bash frames.
|
|
157
|
+
if (src[i] === '\n' && t.lang !== 'bash' && (d === '\'' || d === '"')) {
|
|
158
|
+
stack.pop();
|
|
159
|
+
prevToken = 'value';
|
|
160
|
+
i++;
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
if (src[i] !== '\n') out[i] = ' ';
|
|
164
|
+
i++;
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
167
|
+
if (t && t.kind === 'interp') {
|
|
168
|
+
// Code mode inside `${...}`. Bytes preserved; track brace depth and
|
|
169
|
+
// nested constructs so masking resumes once interpolation closes.
|
|
170
|
+
if (src[i] === '{') {
|
|
171
|
+
t.braceDepth++;
|
|
172
|
+
prevToken = 'expr';
|
|
173
|
+
i++;
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
if (src[i] === '}') {
|
|
177
|
+
t.braceDepth--;
|
|
178
|
+
i++;
|
|
179
|
+
if (t.braceDepth === 0) {
|
|
180
|
+
stack.pop();
|
|
181
|
+
prevToken = 'value';
|
|
182
|
+
} else {
|
|
183
|
+
prevToken = 'value';
|
|
184
|
+
}
|
|
185
|
+
continue;
|
|
186
|
+
}
|
|
187
|
+
if (_supportsSlashComments(lang) && src.startsWith('/*', i)) {
|
|
188
|
+
out[i] = ' ';
|
|
189
|
+
if (i + 1 < out.length) out[i + 1] = ' ';
|
|
190
|
+
i += 2;
|
|
191
|
+
blockComment = true;
|
|
192
|
+
continue;
|
|
193
|
+
}
|
|
194
|
+
if (_supportsSlashComments(lang) && src.startsWith('//', i)) {
|
|
195
|
+
while (i < src.length && src[i] !== '\n') {
|
|
196
|
+
out[i] = ' ';
|
|
197
|
+
i++;
|
|
198
|
+
}
|
|
199
|
+
continue;
|
|
200
|
+
}
|
|
201
|
+
if (src[i] === '/' && _isJsLike(lang) && prevToken === 'expr') {
|
|
202
|
+
i = _maskJsRegexLiteral(src, out, i);
|
|
203
|
+
prevToken = 'value';
|
|
204
|
+
continue;
|
|
205
|
+
}
|
|
206
|
+
if (src[i] === '"' || (_supportsSingleQuoteStrings(lang) && src[i] === '\'') || (_supportsBacktickStrings(lang) && src[i] === '`')) {
|
|
207
|
+
if (src[i] !== '\n') out[i] = ' ';
|
|
208
|
+
stack.push({ kind: 'string', delim: src[i], lang });
|
|
209
|
+
i++;
|
|
210
|
+
continue;
|
|
211
|
+
}
|
|
212
|
+
if (_isWordStartChar(src[i])) {
|
|
213
|
+
const start = i;
|
|
214
|
+
while (i < src.length && _isWordChar(src[i])) i++;
|
|
215
|
+
const word = src.substring(start, i);
|
|
216
|
+
prevToken = REGEX_PRECEDENT_KEYWORDS.has(word) ? 'expr' : 'value';
|
|
217
|
+
continue;
|
|
218
|
+
}
|
|
219
|
+
if (src[i] >= '0' && src[i] <= '9') {
|
|
220
|
+
while (i < src.length && (src[i] === '.' || (src[i] >= '0' && src[i] <= '9'))) i++;
|
|
221
|
+
prevToken = 'value';
|
|
222
|
+
continue;
|
|
223
|
+
}
|
|
224
|
+
if (src[i] === ' ' || src[i] === '\t' || src[i] === '\r' || src[i] === '\n') {
|
|
225
|
+
i++;
|
|
226
|
+
continue;
|
|
227
|
+
}
|
|
228
|
+
if (REGEX_PRECEDENT_CHARS.has(src[i])) {
|
|
229
|
+
prevToken = 'expr';
|
|
230
|
+
} else {
|
|
231
|
+
prevToken = 'value';
|
|
232
|
+
}
|
|
233
|
+
i++;
|
|
234
|
+
continue;
|
|
235
|
+
}
|
|
236
|
+
// Top-level code.
|
|
237
|
+
if (_supportsSlashComments(lang) && src.startsWith('/*', i)) {
|
|
238
|
+
out[i] = ' ';
|
|
239
|
+
if (i + 1 < out.length) out[i + 1] = ' ';
|
|
240
|
+
i += 2;
|
|
241
|
+
blockComment = true;
|
|
242
|
+
continue;
|
|
243
|
+
}
|
|
244
|
+
if (_supportsSlashComments(lang) && src.startsWith('//', i)) {
|
|
245
|
+
while (i < src.length && src[i] !== '\n') {
|
|
246
|
+
out[i] = ' ';
|
|
247
|
+
i++;
|
|
248
|
+
}
|
|
249
|
+
continue;
|
|
250
|
+
}
|
|
251
|
+
if (_supportsHashComments(lang) && src[i] === '#') {
|
|
252
|
+
// Bash `#` is a comment ONLY at line start or after whitespace. When it
|
|
253
|
+
// follows a non-space char it is part of `${var#pat}` / `${var##pat}`
|
|
254
|
+
// parameter expansion (or `$#`, `arr[#]`, etc.), NOT a comment — masking
|
|
255
|
+
// there would erase the rest of the line. `#!` shebang sits at file
|
|
256
|
+
// start (a line start) so it is still masked.
|
|
257
|
+
if (lang === 'bash') {
|
|
258
|
+
const prev = i > 0 ? src[i - 1] : '\n';
|
|
259
|
+
const atCommentPos = prev === '\n' || prev === ' ' || prev === '\t' || prev === '\r';
|
|
260
|
+
if (!atCommentPos) {
|
|
261
|
+
prevToken = 'value';
|
|
262
|
+
i++;
|
|
263
|
+
continue;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
while (i < src.length && src[i] !== '\n') {
|
|
267
|
+
out[i] = ' ';
|
|
268
|
+
i++;
|
|
269
|
+
}
|
|
270
|
+
continue;
|
|
271
|
+
}
|
|
272
|
+
// Lua comments: `--[=*[ ... ]=*]` long-bracket block and `--` line. Lua is
|
|
273
|
+
// neither slash nor hash (see comment predicates), so it needs this
|
|
274
|
+
// dedicated branch. Checked before number/operator handling so the leading
|
|
275
|
+
// `--` is consumed as a comment, not as two minus operators.
|
|
276
|
+
if (lang === 'lua' && src.startsWith('--', i)) {
|
|
277
|
+
// Long-bracket opener: `--` then `[` + zero-or-more `=` + `[`. The level
|
|
278
|
+
// (`=` count) selects the matching close `]` + same `=` + `]`.
|
|
279
|
+
const lb = /^--\[(=*)\[/.exec(src.slice(i, i + 64));
|
|
280
|
+
if (lb) {
|
|
281
|
+
const open = lb[0];
|
|
282
|
+
for (let j = 0; j < open.length; j++) {
|
|
283
|
+
if (src[i + j] !== '\n') out[i + j] = ' ';
|
|
284
|
+
}
|
|
285
|
+
i += open.length;
|
|
286
|
+
stack.push({ kind: 'luablock', close: `]${lb[1]}]` });
|
|
287
|
+
continue;
|
|
288
|
+
}
|
|
289
|
+
// Plain `--` line comment (no long-bracket opener follows).
|
|
290
|
+
while (i < src.length && src[i] !== '\n') {
|
|
291
|
+
out[i] = ' ';
|
|
292
|
+
i++;
|
|
293
|
+
}
|
|
294
|
+
continue;
|
|
295
|
+
}
|
|
296
|
+
if (_supportsTripleSingleQuoteStrings(lang) && src.startsWith("'''", i)) {
|
|
297
|
+
out[i] = ' ';
|
|
298
|
+
if (i + 1 < out.length) out[i + 1] = ' ';
|
|
299
|
+
if (i + 2 < out.length) out[i + 2] = ' ';
|
|
300
|
+
i += 3;
|
|
301
|
+
stack.push({ kind: 'triple', delim: "'''" });
|
|
302
|
+
continue;
|
|
303
|
+
}
|
|
304
|
+
if (_supportsTripleDoubleQuoteStrings(lang) && src.startsWith('"""', i)) {
|
|
305
|
+
out[i] = ' ';
|
|
306
|
+
if (i + 1 < out.length) out[i + 1] = ' ';
|
|
307
|
+
if (i + 2 < out.length) out[i + 2] = ' ';
|
|
308
|
+
i += 3;
|
|
309
|
+
stack.push({ kind: 'triple', delim: '"""' });
|
|
310
|
+
continue;
|
|
311
|
+
}
|
|
312
|
+
if (src[i] === '/' && _isJsLike(lang) && prevToken === 'expr') {
|
|
313
|
+
i = _maskJsRegexLiteral(src, out, i);
|
|
314
|
+
prevToken = 'value';
|
|
315
|
+
continue;
|
|
316
|
+
}
|
|
317
|
+
if (src[i] === '"' || (_supportsSingleQuoteStrings(lang) && src[i] === '\'') || (_supportsBacktickStrings(lang) && src[i] === '`')) {
|
|
318
|
+
if (src[i] !== '\n') out[i] = ' ';
|
|
319
|
+
stack.push({ kind: 'string', delim: src[i], lang });
|
|
320
|
+
i++;
|
|
321
|
+
continue;
|
|
322
|
+
}
|
|
323
|
+
if (_isWordStartChar(src[i])) {
|
|
324
|
+
const start = i;
|
|
325
|
+
while (i < src.length && _isWordChar(src[i])) i++;
|
|
326
|
+
const word = src.substring(start, i);
|
|
327
|
+
prevToken = REGEX_PRECEDENT_KEYWORDS.has(word) ? 'expr' : 'value';
|
|
328
|
+
continue;
|
|
329
|
+
}
|
|
330
|
+
if (src[i] >= '0' && src[i] <= '9') {
|
|
331
|
+
while (i < src.length && (src[i] === '.' || (src[i] >= '0' && src[i] <= '9'))) i++;
|
|
332
|
+
prevToken = 'value';
|
|
333
|
+
continue;
|
|
334
|
+
}
|
|
335
|
+
if (src[i] === ' ' || src[i] === '\t' || src[i] === '\r' || src[i] === '\n') {
|
|
336
|
+
i++;
|
|
337
|
+
continue;
|
|
338
|
+
}
|
|
339
|
+
if (REGEX_PRECEDENT_CHARS.has(src[i])) {
|
|
340
|
+
prevToken = 'expr';
|
|
341
|
+
} else {
|
|
342
|
+
prevToken = 'value';
|
|
343
|
+
}
|
|
344
|
+
i++;
|
|
345
|
+
}
|
|
346
|
+
return out.join('');
|
|
347
|
+
}
|