token-goat 2.9.15 → 2.9.17
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/README.md +2 -5
- package/dist/{token-goat-chunk-IVUQLQWN.mjs → token-goat-chunk-26YUO7MP.mjs} +5 -3
- package/dist/{token-goat-chunk-SZWYESBS.mjs → token-goat-chunk-2M33Q3O4.mjs} +172 -67
- package/dist/{token-goat-chunk-S4XRY446.mjs → token-goat-chunk-2VASS5VR.mjs} +4 -3
- package/dist/{token-goat-chunk-7ZYK25AO.mjs → token-goat-chunk-2XA5ZW4T.mjs} +4 -4
- package/dist/{token-goat-chunk-C5JIO6HK.mjs → token-goat-chunk-5WB7GDH4.mjs} +5 -5
- package/dist/{token-goat-chunk-MZDIJJ3R.mjs → token-goat-chunk-66224KCZ.mjs} +40 -3
- package/dist/{token-goat-chunk-NDRP4KJQ.mjs → token-goat-chunk-73GXYYZR.mjs} +248 -50
- package/dist/{token-goat-chunk-ATIFTMRC.mjs → token-goat-chunk-7EGKXBWT.mjs} +7 -7
- package/dist/{token-goat-chunk-GMQQA7E4.mjs → token-goat-chunk-7VQMOBPQ.mjs} +2453 -722
- package/dist/token-goat-chunk-BGHSSJUA.mjs +102 -0
- package/dist/{token-goat-chunk-2X2EBBC6.mjs → token-goat-chunk-BK3RPPTK.mjs} +2 -2
- package/dist/{token-goat-chunk-YQ7WI2CO.mjs → token-goat-chunk-C26ZBGBC.mjs} +393 -3957
- package/dist/{token-goat-chunk-SFAS46RE.mjs → token-goat-chunk-CICJFVIH.mjs} +2 -2
- package/dist/{token-goat-chunk-6DLVZDB6.mjs → token-goat-chunk-CKIJWTRQ.mjs} +13 -12
- package/dist/{token-goat-chunk-5V7DAC7V.mjs → token-goat-chunk-CPHVXKNU.mjs} +10 -3
- package/dist/{token-goat-chunk-LT7JRU6K.mjs → token-goat-chunk-EKGVCAES.mjs} +4 -4
- package/dist/{token-goat-chunk-Z6UXPYJA.mjs → token-goat-chunk-F2ARFHLJ.mjs} +1 -1
- package/dist/{token-goat-chunk-NDPO7GAH.mjs → token-goat-chunk-G75WIVFM.mjs} +21 -20
- package/dist/{token-goat-chunk-YZX7EFG4.mjs → token-goat-chunk-GLOM5W5C.mjs} +1 -1
- package/dist/{token-goat-chunk-GIIHUSZX.mjs → token-goat-chunk-GPCCYQSS.mjs} +41 -11
- package/dist/{token-goat-chunk-OUGNPMDA.mjs → token-goat-chunk-HRUGS6CO.mjs} +30 -14
- package/dist/{token-goat-chunk-LCZBPOIN.mjs → token-goat-chunk-IDHWKNKZ.mjs} +143 -51
- package/dist/{token-goat-chunk-YKG35VHC.mjs → token-goat-chunk-KZPO4DWC.mjs} +1 -1
- package/dist/{token-goat-chunk-NEI4NC54.mjs → token-goat-chunk-LKSXAMJB.mjs} +7 -2
- package/dist/{token-goat-chunk-K7F2BFIK.mjs → token-goat-chunk-MWSVUKVV.mjs} +1 -1
- package/dist/{token-goat-chunk-BL5LNGBG.mjs → token-goat-chunk-PKNOHVWP.mjs} +2966 -3869
- package/dist/{token-goat-chunk-A4JYKD5H.mjs → token-goat-chunk-RB24DBBS.mjs} +2 -2
- package/dist/{token-goat-chunk-3NSDDTGL.mjs → token-goat-chunk-RFFUCQK7.mjs} +5 -5
- package/dist/token-goat-chunk-RRNZMM3A.mjs +3364 -0
- package/dist/{token-goat-chunk-XEPXYDPI.mjs → token-goat-chunk-SWRKVA3J.mjs} +11 -2
- package/dist/{token-goat-chunk-NU7TLMQK.mjs → token-goat-chunk-THBLW56G.mjs} +10 -7
- package/dist/{token-goat-chunk-PM76YS22.mjs → token-goat-chunk-UBZCON6N.mjs} +1 -1
- package/dist/{token-goat-chunk-ASYEPR3S.mjs → token-goat-chunk-W2GUUQAQ.mjs} +7 -3
- package/dist/{token-goat-chunk-DQ4J5AFF.mjs → token-goat-chunk-YFGEUIEO.mjs} +69 -18
- package/dist/token-goat-hook.mjs +13 -12
- package/dist/token-goat.core.mjs +21 -20
- package/docs/cli.md +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -341,12 +341,9 @@ Per-harness setup for Codex, Gemini, Qwen, Kimi, opencode, OpenClaw, pi, Copilot
|
|
|
341
341
|
|
|
342
342
|
## CLI
|
|
343
343
|
|
|
344
|
-
You rarely type these yourself. Installation writes a routing guide into the agent's instructions, and the agent picks the command that answers its question: a surgical read (`read`, `symbol`, `section`, `skeleton`), a search (`semantic`, `refs`), orientation in an unfamiliar repo (`map`, `arch`, `affected`), recall of output it already has (`bash-output`, `web-output`, `mcp-output`), or a bounded reader for a PDF, Word file, slide deck, workbook, SQLite database, HTML document or image.
|
|
344
|
+
You rarely type these yourself. Installation writes a routing guide into the agent's instructions, and the agent picks the command that answers its question: a surgical read (`read`, `symbol`, `locate`, `section`, `skeleton`), a search (`semantic`, `refs`), orientation in an unfamiliar repo (`map`, `arch`, `affected`), recall of output it already has (`bash-output`, `web-output`, `mcp-output`), or a bounded reader for a PDF, Word file, slide deck, workbook, SQLite database, HTML document or image.
|
|
345
345
|
|
|
346
|
-
One command is for people working on token-goat rather than for agents: `token-goat bench` replays a
|
|
347
|
-
corpus of captured shell output through the real compression path and reports how much smaller the
|
|
348
|
-
result got, alongside a count of the lines each case is not allowed to lose. Deleting output makes
|
|
349
|
-
the first number look better, so the second one is what keeps the first honest.
|
|
346
|
+
One command is for people working on token-goat rather than for agents: `token-goat bench` replays a corpus of captured shell output through the real compression path and reports how much smaller the result got, alongside a count of the lines each case is not allowed to lose. Deleting output makes the first number look better, so the second one is what keeps the first honest.
|
|
350
347
|
|
|
351
348
|
Every command, with its flags, its output, and the comparison workflows that chain them: **[CLI reference](docs/cli.md)**. For architectural analysis, empirical evaluations, and technical answers to common engineering questions: **[Architecture & Technical Q&A](docs/architecture-qa.html)**.
|
|
352
349
|
|
|
@@ -2,11 +2,11 @@ import { createRequire as __cjsRequire } from 'node:module';
|
|
|
2
2
|
const require = __cjsRequire(import.meta.url);
|
|
3
3
|
import {
|
|
4
4
|
getDb
|
|
5
|
-
} from "./token-goat-chunk-
|
|
5
|
+
} from "./token-goat-chunk-MWSVUKVV.mjs";
|
|
6
6
|
import {
|
|
7
7
|
getHarnessName,
|
|
8
8
|
loadConfig
|
|
9
|
-
} from "./token-goat-chunk-
|
|
9
|
+
} from "./token-goat-chunk-2VASS5VR.mjs";
|
|
10
10
|
import {
|
|
11
11
|
registerReset
|
|
12
12
|
} from "./token-goat-chunk-EEIDFMEM.mjs";
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
ensureDirSync,
|
|
20
20
|
sanitizeIdForFilename,
|
|
21
21
|
tokenGoatHome
|
|
22
|
-
} from "./token-goat-chunk-
|
|
22
|
+
} from "./token-goat-chunk-UBZCON6N.mjs";
|
|
23
23
|
import {
|
|
24
24
|
displaySafeText
|
|
25
25
|
} from "./token-goat-chunk-ERTXEKB6.mjs";
|
|
@@ -473,6 +473,7 @@ var _KIND_GROUPS = [
|
|
|
473
473
|
"gdrive_image",
|
|
474
474
|
"webfetch_image",
|
|
475
475
|
"image_shrink_skipped",
|
|
476
|
+
"image_shrink_over_pixel_limit",
|
|
476
477
|
"image_shrink_cache_hit",
|
|
477
478
|
"image_ocr"
|
|
478
479
|
])
|
|
@@ -872,6 +873,7 @@ var KIND_TO_SOURCE = {
|
|
|
872
873
|
image_shrink: SOURCE_IMAGE,
|
|
873
874
|
image_shrink_cache_hit: SOURCE_IMAGE,
|
|
874
875
|
image_shrink_skipped: SOURCE_IMAGE,
|
|
876
|
+
image_shrink_over_pixel_limit: SOURCE_IMAGE,
|
|
875
877
|
image_ocr: SOURCE_IMAGE,
|
|
876
878
|
webfetch_image: SOURCE_IMAGE,
|
|
877
879
|
gdrive_image: SOURCE_IMAGE,
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
canRunWrappedShell,
|
|
5
5
|
clipToDeliveryCap,
|
|
6
6
|
deliveredOutputBytes
|
|
7
|
-
} from "./token-goat-chunk-
|
|
7
|
+
} from "./token-goat-chunk-GLOM5W5C.mjs";
|
|
8
8
|
import {
|
|
9
9
|
DEFAULT_RECONCILE_BUDGET_MS,
|
|
10
10
|
HOOK_EVENTS,
|
|
@@ -17,11 +17,13 @@ import {
|
|
|
17
17
|
readStdinJson,
|
|
18
18
|
reconcileProject,
|
|
19
19
|
storeWebOutput
|
|
20
|
-
} from "./token-goat-chunk-
|
|
20
|
+
} from "./token-goat-chunk-HRUGS6CO.mjs";
|
|
21
21
|
import {
|
|
22
|
+
BODY_FIRST_TOOL_RESPONSE_KEYS,
|
|
22
23
|
GENERIC_SERVED_OUTPUT_KEY,
|
|
23
24
|
OUTLINE_MAX_REPLACEMENT_RATIO,
|
|
24
25
|
OUTLINE_MIN_HEADINGS,
|
|
26
|
+
OUTPUT_FIRST_TOOL_RESPONSE_KEYS,
|
|
25
27
|
WEB_FETCH_KEY_SEP,
|
|
26
28
|
accumulateResidentLines,
|
|
27
29
|
appendDirtyPath,
|
|
@@ -33,9 +35,16 @@ import {
|
|
|
33
35
|
clearCurlDownload,
|
|
34
36
|
compactPathFor,
|
|
35
37
|
computeAdaptiveBudget,
|
|
38
|
+
contextOutput,
|
|
39
|
+
denyOutput,
|
|
40
|
+
emitRewrite,
|
|
41
|
+
emitRewriteIfChanged,
|
|
36
42
|
enqueueDirtyPathSafe,
|
|
37
43
|
ensureWorkerAlive,
|
|
44
|
+
estimateTokens,
|
|
38
45
|
extractCompactFromMarker,
|
|
46
|
+
extractToolResponseField,
|
|
47
|
+
extractToolResultText,
|
|
39
48
|
fenceUntrusted,
|
|
40
49
|
fenceUntrustedSpans,
|
|
41
50
|
fenceWithMatches,
|
|
@@ -47,7 +56,9 @@ import {
|
|
|
47
56
|
getBashOutputId,
|
|
48
57
|
getContextPressure,
|
|
49
58
|
getCurlDownloadPath,
|
|
59
|
+
getCwd,
|
|
50
60
|
getFileLineRanges,
|
|
61
|
+
getFilePath,
|
|
51
62
|
getFileServedOutputs,
|
|
52
63
|
getGlobMatchCount,
|
|
53
64
|
getGrepMatchCount,
|
|
@@ -56,31 +67,41 @@ import {
|
|
|
56
67
|
getSessionBashReruns,
|
|
57
68
|
getSessionFiles,
|
|
58
69
|
getSessionWebFetches,
|
|
70
|
+
getToolInput,
|
|
71
|
+
getToolName,
|
|
72
|
+
getTranscriptPath,
|
|
59
73
|
hasSeenImage,
|
|
60
74
|
hasSessionOutput,
|
|
61
75
|
imageQualifiesForShrink,
|
|
62
76
|
incrementSkillHit,
|
|
63
77
|
indexServedBody,
|
|
64
78
|
installedSkillPath,
|
|
79
|
+
isMcpErrorResponse,
|
|
65
80
|
isStructuralRewriteAccepted,
|
|
81
|
+
isTextualContentBlock,
|
|
66
82
|
lastTabContextMatches,
|
|
67
83
|
lineMayCarryResidentSignal,
|
|
68
84
|
listSiblingSessionStates,
|
|
69
85
|
loadSessionCache,
|
|
70
86
|
loadSessionState,
|
|
87
|
+
makeDedupHintHandlers,
|
|
71
88
|
markCompactStale,
|
|
72
89
|
markCompacted,
|
|
73
90
|
markFileTruncated,
|
|
74
91
|
markHintShown,
|
|
75
92
|
matchesAllowPattern,
|
|
76
93
|
matchesDenyPattern,
|
|
94
|
+
mcpContentBlocks,
|
|
77
95
|
meetsSavingsFloor,
|
|
78
96
|
metadataEndpointRefusal,
|
|
97
|
+
normalizePayload,
|
|
98
|
+
passOutput,
|
|
79
99
|
planMarkdownOutline,
|
|
80
100
|
planServedElisions,
|
|
81
101
|
planSourceSkeleton,
|
|
82
102
|
preToolPathDeclined,
|
|
83
103
|
probeImageMeta,
|
|
104
|
+
readCopilotHooksOwners,
|
|
84
105
|
readTranscriptTail,
|
|
85
106
|
recordBashOutput,
|
|
86
107
|
recordBashRerun,
|
|
@@ -98,13 +119,17 @@ import {
|
|
|
98
119
|
recordSeenImage,
|
|
99
120
|
recordSymbolRead,
|
|
100
121
|
recordWebFetch,
|
|
122
|
+
registerHook,
|
|
101
123
|
removeOutstandingAgentSpawn,
|
|
102
124
|
repeatedSkillBodyHint,
|
|
125
|
+
runHook,
|
|
103
126
|
saveSessionState,
|
|
104
127
|
scanAndRecord,
|
|
128
|
+
serializeOutput,
|
|
105
129
|
servedRunNotice,
|
|
106
130
|
sessionOutputBodyBytes,
|
|
107
131
|
sessionSidecarPath,
|
|
132
|
+
sessionStateKey,
|
|
108
133
|
setLastTabContext,
|
|
109
134
|
setTranscriptPath,
|
|
110
135
|
shrinkImage,
|
|
@@ -117,76 +142,51 @@ import {
|
|
|
117
142
|
vscodePathAllowed,
|
|
118
143
|
wasCliReadThisSession,
|
|
119
144
|
wasFileReadThisSession,
|
|
120
|
-
wasHintShown
|
|
121
|
-
|
|
145
|
+
wasHintShown,
|
|
146
|
+
withPreservedBlocks
|
|
147
|
+
} from "./token-goat-chunk-PKNOHVWP.mjs";
|
|
122
148
|
import {
|
|
123
149
|
BASH_OUTPUT_SUBDIR,
|
|
124
|
-
BODY_FIRST_TOOL_RESPONSE_KEYS,
|
|
125
|
-
OUTPUT_FIRST_TOOL_RESPONSE_KEYS,
|
|
126
150
|
commandHash,
|
|
127
151
|
compressOutput,
|
|
128
|
-
contextOutput,
|
|
129
152
|
dedupeConsecutive,
|
|
130
|
-
denyOutput,
|
|
131
153
|
detectFromCommand,
|
|
132
|
-
emitRewrite,
|
|
133
|
-
emitRewriteIfChanged,
|
|
134
|
-
estimateTokens,
|
|
135
|
-
extractToolResponseField,
|
|
136
|
-
extractToolResultText,
|
|
137
154
|
filterByName,
|
|
138
155
|
getBashOutput,
|
|
139
|
-
getCwd,
|
|
140
|
-
getFilePath,
|
|
141
156
|
getMonitoringRecallHint,
|
|
142
|
-
getToolInput,
|
|
143
|
-
getToolName,
|
|
144
|
-
getTranscriptPath,
|
|
145
157
|
hasBareBackgroundOrNewline,
|
|
146
158
|
hasUnquotedOperator,
|
|
147
159
|
indexRecallEntry,
|
|
148
160
|
isBashEntryStale,
|
|
149
161
|
isBuildCommand,
|
|
150
|
-
isMcpErrorResponse,
|
|
151
162
|
isRewriteWorthwhile,
|
|
152
163
|
isScopedGitStatusOrDiffStatCommand,
|
|
153
164
|
isTestRunnerCommand,
|
|
154
|
-
isTextualContentBlock,
|
|
155
|
-
makeDedupHintHandlers,
|
|
156
|
-
mcpContentBlocks,
|
|
157
|
-
normalizePayload,
|
|
158
|
-
passOutput,
|
|
159
|
-
readCopilotHooksOwners,
|
|
160
|
-
registerHook,
|
|
161
165
|
resolveMinNetSavingsBytes,
|
|
162
|
-
runHook,
|
|
163
|
-
serializeOutput,
|
|
164
|
-
sessionStateKey,
|
|
165
166
|
shlexSplit,
|
|
166
167
|
splitOwnTrailingNotices,
|
|
167
168
|
storeBashOutput,
|
|
168
|
-
summarizeOutputDelta
|
|
169
|
-
|
|
170
|
-
} from "./token-goat-chunk-YQ7WI2CO.mjs";
|
|
171
|
-
import {
|
|
172
|
-
extractMarkdownHeadings,
|
|
173
|
-
formatHeadingTreeParts
|
|
174
|
-
} from "./token-goat-chunk-NDRP4KJQ.mjs";
|
|
175
|
-
import {
|
|
176
|
-
countSymbols
|
|
177
|
-
} from "./token-goat-chunk-2X2EBBC6.mjs";
|
|
169
|
+
summarizeOutputDelta
|
|
170
|
+
} from "./token-goat-chunk-C26ZBGBC.mjs";
|
|
178
171
|
import {
|
|
179
172
|
recordStat,
|
|
180
173
|
redactSecrets,
|
|
181
174
|
savedTokensFromBytes,
|
|
182
175
|
storeBlob,
|
|
183
176
|
stripAnsiEscapes
|
|
184
|
-
} from "./token-goat-chunk-
|
|
177
|
+
} from "./token-goat-chunk-26YUO7MP.mjs";
|
|
178
|
+
import {
|
|
179
|
+
extractMarkdownHeadings,
|
|
180
|
+
formatHeadingTreeParts
|
|
181
|
+
} from "./token-goat-chunk-73GXYYZR.mjs";
|
|
182
|
+
import {
|
|
183
|
+
countSymbols
|
|
184
|
+
} from "./token-goat-chunk-BK3RPPTK.mjs";
|
|
185
185
|
import {
|
|
186
186
|
detectLanguage,
|
|
187
187
|
getDb,
|
|
188
188
|
languageHasFlag
|
|
189
|
-
} from "./token-goat-chunk-
|
|
189
|
+
} from "./token-goat-chunk-MWSVUKVV.mjs";
|
|
190
190
|
import {
|
|
191
191
|
detectHarness,
|
|
192
192
|
envBool,
|
|
@@ -196,7 +196,7 @@ import {
|
|
|
196
196
|
isUnderSystemTemp,
|
|
197
197
|
loadConfig,
|
|
198
198
|
shortFingerprint
|
|
199
|
-
} from "./token-goat-chunk-
|
|
199
|
+
} from "./token-goat-chunk-2VASS5VR.mjs";
|
|
200
200
|
import {
|
|
201
201
|
ENV_KEYS,
|
|
202
202
|
IDENTICAL_READ_MIN_BODY_BYTES,
|
|
@@ -207,6 +207,7 @@ import {
|
|
|
207
207
|
countNoun,
|
|
208
208
|
dataDir,
|
|
209
209
|
ensureDirSync,
|
|
210
|
+
escapeRegExp,
|
|
210
211
|
escapesOntoNetworkThroughLinks,
|
|
211
212
|
extractErrorMessage,
|
|
212
213
|
foldPath,
|
|
@@ -215,7 +216,7 @@ import {
|
|
|
215
216
|
isInsideRoot,
|
|
216
217
|
runGit,
|
|
217
218
|
toKB
|
|
218
|
-
} from "./token-goat-chunk-
|
|
219
|
+
} from "./token-goat-chunk-UBZCON6N.mjs";
|
|
219
220
|
import {
|
|
220
221
|
UNTRUSTED_TOOL_TAG,
|
|
221
222
|
displaySafePath,
|
|
@@ -945,7 +946,7 @@ init_define_import_meta_env();
|
|
|
945
946
|
var TRACKED_SKILL = "token-goat";
|
|
946
947
|
var MAX_COMMANDS_SHOWN = 8;
|
|
947
948
|
async function currentCommandNames() {
|
|
948
|
-
const { buildProgram } = await import("./token-goat-chunk-
|
|
949
|
+
const { buildProgram } = await import("./token-goat-chunk-G75WIVFM.mjs");
|
|
949
950
|
return flattenCommandNames(buildCommandManifest(buildProgram()));
|
|
950
951
|
}
|
|
951
952
|
async function recordSkillVersionSnapshot(sessionId, skillName) {
|
|
@@ -1234,8 +1235,10 @@ function reconcileNote(cwd, indexed) {
|
|
|
1234
1235
|
const budgetMs = envInt(ENV_KEYS.RECONCILE_BUDGET_MS, DEFAULT_RECONCILE_BUDGET_MS, 0, 6e4);
|
|
1235
1236
|
const result = reconcileProject({ cwd, budgetMs });
|
|
1236
1237
|
if (isReconcileClean(result) && !result.budgetExhausted) return null;
|
|
1238
|
+
const upgraded = result.parserStale + result.embedStale;
|
|
1239
|
+
const edited = result.changed.length - upgraded;
|
|
1237
1240
|
const parts = [];
|
|
1238
|
-
if (
|
|
1241
|
+
if (edited > 0) parts.push(`${edited} changed`);
|
|
1239
1242
|
if (result.added.length > 0) parts.push(`${result.added.length} new`);
|
|
1240
1243
|
if (result.removed.length > 0) parts.push(`${result.removed.length} removed`);
|
|
1241
1244
|
const breakdown = parts.length > 1 ? ` (${parts.join(", ")})` : "";
|
|
@@ -1244,7 +1247,11 @@ function reconcileNote(cwd, indexed) {
|
|
|
1244
1247
|
if (total === 0) {
|
|
1245
1248
|
return `token-goat: index drift check${truncated} found nothing in the part it had time to scan. Symbol lookups may be briefly stale.`;
|
|
1246
1249
|
}
|
|
1247
|
-
|
|
1250
|
+
const drifted = total - upgraded;
|
|
1251
|
+
const clauses = [];
|
|
1252
|
+
if (drifted > 0) clauses.push(`${countNoun(drifted, "file")} that changed outside this session${breakdown}`);
|
|
1253
|
+
if (upgraded > 0) clauses.push(`${countNoun(upgraded, "file")} unchanged on disk but indexed by an older version of token-goat`);
|
|
1254
|
+
return `token-goat: reindexing ${clauses.join(" and ")}${truncated}. Symbol lookups may be briefly stale.`;
|
|
1248
1255
|
} catch {
|
|
1249
1256
|
return null;
|
|
1250
1257
|
}
|
|
@@ -1773,11 +1780,11 @@ function toRegExp(r, i) {
|
|
|
1773
1780
|
if (r.str.length === 0) {
|
|
1774
1781
|
throw new Error(`Rule #${i} ("${r.name}") has empty "str" property, which is not allowed.`);
|
|
1775
1782
|
}
|
|
1776
|
-
return new RegExp(
|
|
1783
|
+
return new RegExp(escapeRegExp2(r.str), "y");
|
|
1777
1784
|
}
|
|
1778
|
-
return new RegExp(
|
|
1785
|
+
return new RegExp(escapeRegExp2(r.name), "y");
|
|
1779
1786
|
}
|
|
1780
|
-
function
|
|
1787
|
+
function escapeRegExp2(str) {
|
|
1781
1788
|
return str.replace(/[-[\]{}()*+!<=:?./\\^$|#\s,]/g, "\\$&");
|
|
1782
1789
|
}
|
|
1783
1790
|
function toSticky(re) {
|
|
@@ -7705,10 +7712,7 @@ function splitShellSegments(cmd) {
|
|
|
7705
7712
|
}
|
|
7706
7713
|
function isTempPath(fp) {
|
|
7707
7714
|
const norm = fp.replace(/\\/g, "/");
|
|
7708
|
-
return /^\/tmp\//i.test(norm) || /\/var\/folders\//i.test(norm) || // Anchored to a local drive root on purpose. Unanchored, this clause said yes to
|
|
7709
|
-
// `//host/share/AppData/Local/Temp/x.md`, and the caller's answer to yes is to stat the path --
|
|
7710
|
-
// which on Windows opens an SMB session to whatever host a command named. A temp directory is
|
|
7711
|
-
// somewhere on a local volume; nothing that starts with two separators is one.
|
|
7715
|
+
return /^\/tmp\//i.test(norm) || /\/var\/folders\//i.test(norm) || // Anchored to a local drive root on purpose. Unanchored, this clause said yes to `//host/share/AppData/Local/Temp/x.md`, and the caller's answer to yes is to stat the path -- which on Windows opens an SMB session to whatever host a command named. A temp directory is somewhere on a local volume; nothing that starts with two separators is one.
|
|
7712
7716
|
/^[a-z]:\/(?:[^/]+\/)*AppData\/Local\/Temp\//i.test(norm) || norm.startsWith("/c/Users/") && norm.includes("/AppData/Local/Temp/") || isUnderSystemTemp(fp);
|
|
7713
7717
|
}
|
|
7714
7718
|
function isOrchestratorStateFile(filePath) {
|
|
@@ -7835,12 +7839,77 @@ function extractRgSymbolSearch(cmd) {
|
|
|
7835
7839
|
}
|
|
7836
7840
|
function extractCatJsonPipe(cmd) {
|
|
7837
7841
|
const m = /^cat\s+(?:"([^"]+)"|'([^']+)'|(\S+))\s*\|\s*jq\b/.exec(cmd);
|
|
7838
|
-
if (
|
|
7839
|
-
|
|
7840
|
-
|
|
7841
|
-
|
|
7842
|
-
|
|
7843
|
-
|
|
7842
|
+
if (m) {
|
|
7843
|
+
const filePath = m[1] ?? m[2] ?? m[3];
|
|
7844
|
+
if (filePath && !isTempPath(filePath) && /\.(?:json|yaml|yml|toml)$/i.test(filePath)) {
|
|
7845
|
+
return { filePath, isDirectJq: false };
|
|
7846
|
+
}
|
|
7847
|
+
}
|
|
7848
|
+
const jqDirect = /^jq(?:\s+(?:-[a-zA-Z]+|--[a-zA-Z0-9-]+(?:=\S+)?))*\s+(?:"[^"]*"|'[^']*'|(?:\.[a-zA-Z0-9_.*[\]]+))\s+(?:"([^"]+)"|'([^']+)'|(\S+))\s*$/.exec(cmd);
|
|
7849
|
+
if (jqDirect) {
|
|
7850
|
+
const filePath = jqDirect[1] ?? jqDirect[2] ?? jqDirect[3];
|
|
7851
|
+
if (filePath && !isTempPath(filePath) && /\.(?:json|yaml|yml|toml)$/i.test(filePath)) {
|
|
7852
|
+
return { filePath, isDirectJq: true };
|
|
7853
|
+
}
|
|
7854
|
+
}
|
|
7855
|
+
return null;
|
|
7856
|
+
}
|
|
7857
|
+
function extractPowerShellJsonPipeline(cmd) {
|
|
7858
|
+
let inner = cmd.trim();
|
|
7859
|
+
const w = POWERSHELL_WRAP_RE.exec(inner);
|
|
7860
|
+
if (w) {
|
|
7861
|
+
inner = (w[1] ?? w[2] ?? "").trim();
|
|
7862
|
+
}
|
|
7863
|
+
if (!/\bConvertFrom-Json\b/i.test(inner)) return null;
|
|
7864
|
+
const parseTarget = (segment) => {
|
|
7865
|
+
const readAll = /\[(?:System\.)?IO\.File\]::ReadAllText\(\s*['"]?([^'")\s]+)['"]?\s*\)/i.exec(segment);
|
|
7866
|
+
if (readAll) {
|
|
7867
|
+
const p = readAll[1];
|
|
7868
|
+
return p && /\.(?:json|txt|log|temp)$/i.test(p) ? p : null;
|
|
7869
|
+
}
|
|
7870
|
+
const tokens = segment.trim().split(/\s+/);
|
|
7871
|
+
const cmdlets = /* @__PURE__ */ new Set(["get-content", "gc", "cat", "type"]);
|
|
7872
|
+
const idx = tokens.findIndex((t) => cmdlets.has(t.toLowerCase()));
|
|
7873
|
+
if (idx === -1) return null;
|
|
7874
|
+
let argIdx = idx + 1;
|
|
7875
|
+
while (argIdx < tokens.length) {
|
|
7876
|
+
const tok = tokens[argIdx];
|
|
7877
|
+
if (!tok) break;
|
|
7878
|
+
if (tok.startsWith("-")) {
|
|
7879
|
+
const flag = tok.toLowerCase();
|
|
7880
|
+
if (flag === "-path" && argIdx + 1 < tokens.length) {
|
|
7881
|
+
const next = tokens[argIdx + 1];
|
|
7882
|
+
if (next && !next.startsWith("-")) {
|
|
7883
|
+
const clean2 = next.replace(/^['"]|['"]$/g, "");
|
|
7884
|
+
return /\.(?:json|txt|log|temp)$/i.test(clean2) ? clean2 : null;
|
|
7885
|
+
}
|
|
7886
|
+
}
|
|
7887
|
+
if ((flag === "-encoding" || flag === "-totalcount") && argIdx + 1 < tokens.length) {
|
|
7888
|
+
argIdx += 2;
|
|
7889
|
+
continue;
|
|
7890
|
+
}
|
|
7891
|
+
argIdx++;
|
|
7892
|
+
continue;
|
|
7893
|
+
}
|
|
7894
|
+
const clean = tok.replace(/^['"(]|['")]$/g, "");
|
|
7895
|
+
return /\.(?:json|txt|log|temp)$/i.test(clean) ? clean : null;
|
|
7896
|
+
}
|
|
7897
|
+
return null;
|
|
7898
|
+
};
|
|
7899
|
+
const pipeIdx = inner.search(/\|\s*ConvertFrom-Json\b/i);
|
|
7900
|
+
if (pipeIdx !== -1) {
|
|
7901
|
+
const upstream = inner.slice(0, pipeIdx).trim();
|
|
7902
|
+
return { filePath: parseTarget(upstream) };
|
|
7903
|
+
}
|
|
7904
|
+
const parenMatch = /ConvertFrom-Json\s*\(([^)]+)\)/i.exec(inner);
|
|
7905
|
+
if (parenMatch) {
|
|
7906
|
+
const inside = parenMatch[1] ?? "";
|
|
7907
|
+
return { filePath: parseTarget(inside) };
|
|
7908
|
+
}
|
|
7909
|
+
if (/ConvertFrom-Json\s*\(/i.test(inner)) {
|
|
7910
|
+
return { filePath: null };
|
|
7911
|
+
}
|
|
7912
|
+
return null;
|
|
7844
7913
|
}
|
|
7845
7914
|
function extractWslCatFile(cmd) {
|
|
7846
7915
|
const wslMatch = /^wsl(?:\s+-d\s+\S+)?\s+bash\s+-c\s+"cat(?:\s+(?:-[a-zA-Z]+|--[a-zA-Z-]+))*\s+\/mnt\/([a-z])\/([^"]*)"/.exec(cmd);
|
|
@@ -8191,6 +8260,7 @@ function extractNodeFileRead(cmd) {
|
|
|
8191
8260
|
const filePath = readSync2[1];
|
|
8192
8261
|
if (isOrchestratorStateFile(filePath)) return null;
|
|
8193
8262
|
if (isTempPath(filePath)) return null;
|
|
8263
|
+
if (new RegExp(`(?:writeFileSync|appendFileSync)\\(\\s*['"]${escapeRegExp(filePath)}['"]`).test(cmd)) return null;
|
|
8194
8264
|
const { isDoc, isConfig, isSql } = classifyDocConfig(filePath);
|
|
8195
8265
|
return { filePath, isDoc, isConfig, isSql };
|
|
8196
8266
|
}
|
|
@@ -8456,10 +8526,7 @@ var CURL_VALUE_FLAGS = /* @__PURE__ */ new Set([
|
|
|
8456
8526
|
"--range",
|
|
8457
8527
|
"-r",
|
|
8458
8528
|
"--interface",
|
|
8459
|
-
// Options whose own value is a URL or a host. Leaving these out was the same defect as reading
|
|
8460
|
-
// the first URL in the string: `curl --doh-url https://doh/ -o f https://target` answered with
|
|
8461
|
-
// the DoH resolver rather than the file being fetched. `--url-query` belongs here too -- it
|
|
8462
|
-
// appends query data to the request, it does not name the request target.
|
|
8529
|
+
// Options whose own value is a URL or a host. Leaving these out was the same defect as reading the first URL in the string: `curl --doh-url https://doh/ -o f https://target` answered with the DoH resolver rather than the file being fetched. `--url-query` belongs here too -- it appends query data to the request, it does not name the request target.
|
|
8463
8530
|
"--url-query",
|
|
8464
8531
|
"--doh-url",
|
|
8465
8532
|
"--preproxy",
|
|
@@ -9532,11 +9599,25 @@ function preBashHandlerInner(event) {
|
|
|
9532
9599
|
}
|
|
9533
9600
|
const catJsonPipe = extractCatJsonPipe(cmd);
|
|
9534
9601
|
if (catJsonPipe !== null) {
|
|
9535
|
-
const { filePath } = catJsonPipe;
|
|
9602
|
+
const { filePath, isDirectJq } = catJsonPipe;
|
|
9536
9603
|
const hintPath = displaySafePath(cdStripped ? resolveCdHintPath(rawCmd, filePath, hintCwd) : filePath);
|
|
9537
9604
|
recordStat("session_hint", 0, 0);
|
|
9605
|
+
const label = isDirectJq ? "`jq`" : "`cat | jq`";
|
|
9606
|
+
return contextOutput(
|
|
9607
|
+
label + ' loads the whole file. Use `token-goat json-query "' + hintPath + '" "<key>"` or `token-goat config-get "' + hintPath + '" KEY_NAME` to slice one value.'
|
|
9608
|
+
);
|
|
9609
|
+
}
|
|
9610
|
+
const psJsonPipe = extractPowerShellJsonPipeline(cmd);
|
|
9611
|
+
if (psJsonPipe !== null) {
|
|
9612
|
+
recordStat("session_hint", 0, 0);
|
|
9613
|
+
if (psJsonPipe.filePath) {
|
|
9614
|
+
const hintPath = displaySafePath(cdStripped ? resolveCdHintPath(rawCmd, psJsonPipe.filePath, hintCwd) : psJsonPipe.filePath);
|
|
9615
|
+
return contextOutput(
|
|
9616
|
+
'PowerShell `ConvertFrom-Json` pipeline detected. Use `token-goat json-query "' + hintPath + '" "<selector>"` to extract fields directly without shell conversion scripts.'
|
|
9617
|
+
);
|
|
9618
|
+
}
|
|
9538
9619
|
return contextOutput(
|
|
9539
|
-
'
|
|
9620
|
+
'PowerShell `ConvertFrom-Json` pipeline detected. Use `token-goat json-query <file> "<selector>"` or `token-goat web-output` to extract fields directly.'
|
|
9540
9621
|
);
|
|
9541
9622
|
}
|
|
9542
9623
|
const catResult = extractCatFile(cmd);
|
|
@@ -9907,6 +9988,25 @@ function recordBashFileReadsForSessionCache(cmd, cwd) {
|
|
|
9907
9988
|
return;
|
|
9908
9989
|
}
|
|
9909
9990
|
}
|
|
9991
|
+
async function maybeEmitLargeUncompressedHint(cmd, output, exitCode, cwd, isUnwrapped, event, ansiResult) {
|
|
9992
|
+
const outputBytes = Buffer.byteLength(output, "utf-8");
|
|
9993
|
+
if (outputBytes < 4096 || process.env["TOKEN_GOAT_BASH_COMPRESS"] === "0" || exitCode !== null && exitCode !== 0 || // token-goat's own output is already the narrow form; telling the model to compress it is noise.
|
|
9994
|
+
/^\s*token-goat\s/.test(cmd) || event.raw["_tg_harness"] !== "vscode" && (isCompressibleSingleCommand(cmd) || !isUnwrapped)) {
|
|
9995
|
+
return null;
|
|
9996
|
+
}
|
|
9997
|
+
const key = `bash-uncompressed-4k:${event.sessionId ?? ""}:${shortFingerprint(cmd)}`;
|
|
9998
|
+
if (wasHintShown(key)) return null;
|
|
9999
|
+
markHintShown(key);
|
|
10000
|
+
recordStat("session_hint", 0, 0);
|
|
10001
|
+
const id = await storeBashOutput(cmd, output, exitCode ?? 0, cwd);
|
|
10002
|
+
const kb = Math.round(outputBytes / 1024);
|
|
10003
|
+
const compressable = !/["`$\r\n]/.test(cmd);
|
|
10004
|
+
const msg = `[tg] Output was ${kb}KB uncompressed; \`token-goat bash-output ${id}\` recalls it` + (compressable ? `, and \`token-goat compress -c "${displaySafeText(cmd)}"\` compresses the next run.` : ".");
|
|
10005
|
+
if (ansiResult !== null && ansiResult.hookType === "rewriteOutput") {
|
|
10006
|
+
return emitRewrite(msg + "\n" + fenceUntrusted(ansiResult.updatedOutput, UNTRUSTED_TOOL_TAG), "large uncompressed output hint", void 0, "counted-elsewhere");
|
|
10007
|
+
}
|
|
10008
|
+
return contextOutput(msg);
|
|
10009
|
+
}
|
|
9910
10010
|
async function postBashHandler(event) {
|
|
9911
10011
|
try {
|
|
9912
10012
|
const rawCmdRaw = extractCommand(event);
|
|
@@ -10012,7 +10112,10 @@ async function postBashHandler(event) {
|
|
|
10012
10112
|
const genericElision = await maybeElideServedGenericOutput(cmd, output, exitCode, cwd, cacheMinBytes);
|
|
10013
10113
|
if (genericElision !== null) return genericElision;
|
|
10014
10114
|
}
|
|
10015
|
-
|
|
10115
|
+
const ansiStripped = maybeStripAnsiOnly(output);
|
|
10116
|
+
const largeHint2 = await maybeEmitLargeUncompressedHint(cmd, output, exitCode, cwd, isUnwrapped, event, ansiStripped);
|
|
10117
|
+
if (largeHint2 !== null) return largeHint2;
|
|
10118
|
+
return ansiStripped ?? passOutput();
|
|
10016
10119
|
}
|
|
10017
10120
|
if (Buffer.byteLength(output, "utf-8") < cacheMinBytes) return passOutput();
|
|
10018
10121
|
const cacheKey = isCurlGetCommand(cmd) ? extractCurlUrl(cmd) ?? cmd : stripOutputPipeline(cmd);
|
|
@@ -10032,6 +10135,8 @@ async function postBashHandler(event) {
|
|
|
10032
10135
|
const curlHtmlFold = maybeFoldCurlHtml(cmd, output, id);
|
|
10033
10136
|
if (curlHtmlFold !== null) return curlHtmlFold;
|
|
10034
10137
|
const ansiOnly = maybeStripAnsiOnly(output);
|
|
10138
|
+
const largeHint = await maybeEmitLargeUncompressedHint(cmd, output, exitCode, cwd, isUnwrapped, event, ansiOnly);
|
|
10139
|
+
if (largeHint !== null) return largeHint;
|
|
10035
10140
|
if (ansiOnly !== null) return ansiOnly;
|
|
10036
10141
|
} catch {
|
|
10037
10142
|
}
|
|
@@ -11171,7 +11276,7 @@ function buildSubagentBriefing() {
|
|
|
11171
11276
|
}
|
|
11172
11277
|
const tail = [];
|
|
11173
11278
|
tail.push("");
|
|
11174
|
-
tail.push('Before your first read of any file, check for a token-goat command that returns just what you need and run it instead of a full-file read or wide grep: `token-goat symbol <name>`, `token-goat read "file::symbol"`, `token-goat section "file::<heading>"`. Skipping that check is a violation, not an oversight; the only exemptions are a file under ~200 lines you need whole, a never-indexed file, or an image.');
|
|
11279
|
+
tail.push('Before your first read of any file, check for a token-goat command that returns just what you need and run it instead of a full-file read or wide grep: `token-goat symbol <name>`, `token-goat read "file::symbol"`, `token-goat section "file::<heading>"`, `token-goat json-query file \'a.b.c\'`. Skipping that check is a violation, not an oversight; the only exemptions are a file under ~200 lines you need whole, a never-indexed file, or an image.');
|
|
11175
11280
|
tail.push("");
|
|
11176
11281
|
tail.push('Report contract: cite evidence as `file::symbol` or a token-goat recall id (`token-goat mcp-output <id> --full`) rather than pasting bodies; paste a fenced block only when the exact bytes are load-bearing; state every unverified claim explicitly (e.g. "not verified: ...") rather than omitting it.');
|
|
11177
11282
|
const withCacheIds = head.join("\n") + cacheIdsBlock + "\n" + tail.join("\n");
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
foldPath,
|
|
14
14
|
projectConfigPath,
|
|
15
15
|
runGit
|
|
16
|
-
} from "./token-goat-chunk-
|
|
16
|
+
} from "./token-goat-chunk-UBZCON6N.mjs";
|
|
17
17
|
import {
|
|
18
18
|
normalizeDarwinSystemAlias
|
|
19
19
|
} from "./token-goat-chunk-ERTXEKB6.mjs";
|
|
@@ -1421,7 +1421,8 @@ var CONFIG_DEFAULTS = {
|
|
|
1421
1421
|
image_shrink: {
|
|
1422
1422
|
enabled: true,
|
|
1423
1423
|
jpeg_quality: 75,
|
|
1424
|
-
|
|
1424
|
+
// 16,000,000 used to reject a routine 24MP DSLR/phone photo outright -- the exact input this feature exists to shrink -- while the engine's own decode ceiling (MAX_DECODED_BYTES in image_engine.ts, 256MB at 4 bytes/pixel for a single frame) sits at 67,108,864px. 64,000,000 covers cameras well past 24MP (including 48MP phone sensors) with ~4.9% margin below that hard ceiling, which assertDecodableSize enforces independently of this value on every decode regardless of what this header check allows through. Measured on this engine (2026-09-17): a 24MP PNG decodes+shrinks in ~370ms, 60,000,516px in ~920ms, and 67,108,864px (the ceiling itself) in ~760ms -- all comfortably fast, so the new value is chosen for coverage headroom under the ceiling, not for decode-time cost. Decode time is not the cost that binds, though: memory is. This value is read off a header before anything is decoded, so what it really sets is how large a buffer a file's own declared dimensions may talk this hook into allocating -- at 4 bytes per pixel, raising it from 16,000,000 raised that peak from ~64MB to ~256MB, which is why it now sits flush against MAX_DECODED_BYTES rather than comfortably below it. And on the JPEG path there is no assertDecodableSize call at all: decodeJpeg hands the buffer to jpeg-js, so a JPEG decode is bounded by whatever maxResolutionInMP/maxMemoryUsageInMB that call passes -- a bound this codebase states only because decodeJpeg passes both explicitly rather than inheriting jpeg-js's own 100MP default, which is looser than the 67.1MP MAX_DECODED_BYTES allows.
|
|
1425
|
+
max_image_pixels: 64e6,
|
|
1425
1426
|
screenshot_redirect: true,
|
|
1426
1427
|
ocr_enabled: true,
|
|
1427
1428
|
// Confidence is Tesseract's own 0-100 mean-word-confidence score. 65 is a deliberately
|
|
@@ -1566,7 +1567,7 @@ var CONFIG_DEFAULTS = {
|
|
|
1566
1567
|
offline: false
|
|
1567
1568
|
},
|
|
1568
1569
|
mcp: {
|
|
1569
|
-
confine_reads_to_project_root:
|
|
1570
|
+
confine_reads_to_project_root: false,
|
|
1570
1571
|
allowed_roots: []
|
|
1571
1572
|
},
|
|
1572
1573
|
hint_stats: {
|
|
@@ -6,13 +6,13 @@ import {
|
|
|
6
6
|
pptxOutline,
|
|
7
7
|
pptxSlideText,
|
|
8
8
|
pptxTextGrep
|
|
9
|
-
} from "./token-goat-chunk-
|
|
10
|
-
import "./token-goat-chunk-
|
|
9
|
+
} from "./token-goat-chunk-W2GUUQAQ.mjs";
|
|
10
|
+
import "./token-goat-chunk-66224KCZ.mjs";
|
|
11
11
|
import "./token-goat-chunk-XTQAOTSO.mjs";
|
|
12
12
|
import "./token-goat-chunk-AH6QILZM.mjs";
|
|
13
|
-
import "./token-goat-chunk-
|
|
14
|
-
import "./token-goat-chunk-PM76YS22.mjs";
|
|
13
|
+
import "./token-goat-chunk-UBZCON6N.mjs";
|
|
15
14
|
import "./token-goat-chunk-ERTXEKB6.mjs";
|
|
15
|
+
import "./token-goat-chunk-Y4AFKTHK.mjs";
|
|
16
16
|
import "./token-goat-chunk-GMOUBOX4.mjs";
|
|
17
17
|
import "./token-goat-chunk-A37V4PBF.mjs";
|
|
18
18
|
export {
|
|
@@ -20,17 +20,17 @@ import {
|
|
|
20
20
|
setOcrTimeoutForTesting,
|
|
21
21
|
setTesseractEntryForTesting,
|
|
22
22
|
verifyOcrLangCache
|
|
23
|
-
} from "./token-goat-chunk-
|
|
24
|
-
import "./token-goat-chunk-
|
|
25
|
-
import "./token-goat-chunk-
|
|
23
|
+
} from "./token-goat-chunk-CICJFVIH.mjs";
|
|
24
|
+
import "./token-goat-chunk-26YUO7MP.mjs";
|
|
25
|
+
import "./token-goat-chunk-MWSVUKVV.mjs";
|
|
26
26
|
import {
|
|
27
27
|
DEFAULT_OCR_LANG,
|
|
28
28
|
isSupportedOcrLang,
|
|
29
29
|
resolveOcrLangs
|
|
30
|
-
} from "./token-goat-chunk-
|
|
30
|
+
} from "./token-goat-chunk-2VASS5VR.mjs";
|
|
31
31
|
import "./token-goat-chunk-EEIDFMEM.mjs";
|
|
32
32
|
import "./token-goat-chunk-OSUFN2FV.mjs";
|
|
33
|
-
import "./token-goat-chunk-
|
|
33
|
+
import "./token-goat-chunk-UBZCON6N.mjs";
|
|
34
34
|
import "./token-goat-chunk-ERTXEKB6.mjs";
|
|
35
35
|
import "./token-goat-chunk-GMOUBOX4.mjs";
|
|
36
36
|
import "./token-goat-chunk-A37V4PBF.mjs";
|
|
@@ -10,13 +10,13 @@ import {
|
|
|
10
10
|
import {
|
|
11
11
|
createLazyModuleLoader
|
|
12
12
|
} from "./token-goat-chunk-AH6QILZM.mjs";
|
|
13
|
+
import {
|
|
14
|
+
pushAll
|
|
15
|
+
} from "./token-goat-chunk-UBZCON6N.mjs";
|
|
13
16
|
import {
|
|
14
17
|
DocumentRefusedError,
|
|
15
18
|
MAX_DOCUMENT_WORK_MILLIS
|
|
16
19
|
} from "./token-goat-chunk-Y4AFKTHK.mjs";
|
|
17
|
-
import {
|
|
18
|
-
pushAll
|
|
19
|
-
} from "./token-goat-chunk-PM76YS22.mjs";
|
|
20
20
|
import {
|
|
21
21
|
init_define_import_meta_env
|
|
22
22
|
} from "./token-goat-chunk-A37V4PBF.mjs";
|
|
@@ -332,6 +332,26 @@ function pushTextValue(runs, val) {
|
|
|
332
332
|
runs.push(String(val["#text"]));
|
|
333
333
|
}
|
|
334
334
|
}
|
|
335
|
+
var MATH_PARA_RE = /<m:oMathPara(?:\s[^>]*)?>([\s\S]*?)<\/m:oMathPara>/g;
|
|
336
|
+
var MATH_RE = /<m:oMath(?:\s[^>]*)?>([\s\S]*?)<\/m:oMath>/g;
|
|
337
|
+
var MATH_TEXT_RE = /<m:t(?:\s[^>]*)?>([^<]*)<\/m:t>/g;
|
|
338
|
+
function mathRunText(fragment) {
|
|
339
|
+
let out = "";
|
|
340
|
+
for (const m of fragment.matchAll(MATH_TEXT_RE)) out += m[1];
|
|
341
|
+
return out;
|
|
342
|
+
}
|
|
343
|
+
function inlineMathRuns(xml, openRun, closeRun) {
|
|
344
|
+
const asRun = (text) => text.length > 0 ? `${openRun}${text}${closeRun}` : "";
|
|
345
|
+
const withParas = xml.replace(MATH_PARA_RE, (_whole, inner) => {
|
|
346
|
+
const lines = [];
|
|
347
|
+
for (const m of inner.matchAll(MATH_RE)) {
|
|
348
|
+
const text = mathRunText(m[1]);
|
|
349
|
+
if (text.length > 0) lines.push(text);
|
|
350
|
+
}
|
|
351
|
+
return asRun(lines.length > 0 ? lines.join(" ") : mathRunText(inner));
|
|
352
|
+
});
|
|
353
|
+
return withParas.replace(MATH_RE, (_whole, inner) => asRun(mathRunText(inner)));
|
|
354
|
+
}
|
|
335
355
|
function collectTextRuns(node, tag, skipInside = []) {
|
|
336
356
|
const runs = [];
|
|
337
357
|
function walk(n) {
|
|
@@ -354,6 +374,21 @@ function collectTextRuns(node, tag, skipInside = []) {
|
|
|
354
374
|
walk(node);
|
|
355
375
|
return runs;
|
|
356
376
|
}
|
|
377
|
+
function dropAlternateContentFallbacks(node) {
|
|
378
|
+
if (Array.isArray(node)) {
|
|
379
|
+
node.forEach(dropAlternateContentFallbacks);
|
|
380
|
+
return;
|
|
381
|
+
}
|
|
382
|
+
if (node === null || typeof node !== "object") return;
|
|
383
|
+
for (const [key, val] of Object.entries(node)) {
|
|
384
|
+
if (key === "mc:AlternateContent") {
|
|
385
|
+
for (const alt of Array.isArray(val) ? val : [val]) {
|
|
386
|
+
if (alt !== null && typeof alt === "object" && "mc:Choice" in alt && "mc:Fallback" in alt) delete alt["mc:Fallback"];
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
if (val !== null && typeof val === "object") dropAlternateContentFallbacks(val);
|
|
390
|
+
}
|
|
391
|
+
}
|
|
357
392
|
function collectElements(node, tag, opts = {}) {
|
|
358
393
|
const skip = opts.skipInside;
|
|
359
394
|
const out = [];
|
|
@@ -413,7 +448,9 @@ export {
|
|
|
413
448
|
ooxmlPartBudget,
|
|
414
449
|
decodeZipEntry,
|
|
415
450
|
parseOoxmlPart,
|
|
451
|
+
inlineMathRuns,
|
|
416
452
|
collectTextRuns,
|
|
453
|
+
dropAlternateContentFallbacks,
|
|
417
454
|
collectElements,
|
|
418
455
|
collectParagraphTexts,
|
|
419
456
|
sortNumberedParts
|