token-goat 2.6.19 → 2.6.21
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 +65 -4
- package/dist/token-goat-hook.mjs +991 -547
- package/dist/token-goat.mjs +1660 -1214
- package/package.json +4 -2
package/dist/token-goat-hook.mjs
CHANGED
|
@@ -49,7 +49,7 @@ var init_define_import_meta_env = __esm({
|
|
|
49
49
|
import { createRequire } from "node:module";
|
|
50
50
|
function resolveVersion() {
|
|
51
51
|
if (true) {
|
|
52
|
-
return "2.6.
|
|
52
|
+
return "2.6.21";
|
|
53
53
|
}
|
|
54
54
|
const require2 = createRequire(import.meta.url);
|
|
55
55
|
const pkg = require2("../package.json");
|
|
@@ -286,6 +286,7 @@ const VALID_HOOK_EVENTS = new Set([
|
|
|
286
286
|
'pre_compact',
|
|
287
287
|
'user_prompt_submit',
|
|
288
288
|
'subagent_stop',
|
|
289
|
+
'session_start',
|
|
289
290
|
])
|
|
290
291
|
|
|
291
292
|
// Keep in sync with CLAUDE_CODE_EVENT_NAMES in src/hook_registry.ts -- the
|
|
@@ -300,6 +301,7 @@ const HOOK_EVENT_NAME_MAP = {
|
|
|
300
301
|
pre_compact: 'PreCompact',
|
|
301
302
|
user_prompt_submit: 'UserPromptSubmit',
|
|
302
303
|
subagent_stop: 'SubagentStop',
|
|
304
|
+
session_start: 'SessionStart',
|
|
303
305
|
}
|
|
304
306
|
|
|
305
307
|
function stripTg(value) {
|
|
@@ -1368,8 +1370,8 @@ function normalizeDarwinSystemAlias(p) {
|
|
|
1368
1370
|
}
|
|
1369
1371
|
function resolveIndexPath(file2, base = process.cwd()) {
|
|
1370
1372
|
const isWindowsAbsolute = (s) => /^[a-zA-Z]:[/\\]/.test(s);
|
|
1371
|
-
const
|
|
1372
|
-
return normalizePath(
|
|
1373
|
+
const resolve21 = isWindowsAbsolute(file2) || isWindowsAbsolute(base) ? path2.win32.resolve : path2.resolve;
|
|
1374
|
+
return normalizePath(resolve21(base, file2));
|
|
1373
1375
|
}
|
|
1374
1376
|
function safeJoin(base, ...parts) {
|
|
1375
1377
|
for (const part of parts) {
|
|
@@ -1896,6 +1898,43 @@ setInterval(tick, Number(ms))
|
|
|
1896
1898
|
}
|
|
1897
1899
|
});
|
|
1898
1900
|
|
|
1901
|
+
// src/bridges/guidance_block.ts
|
|
1902
|
+
function buildGuidanceBody(fallbackToolClause) {
|
|
1903
|
+
return [
|
|
1904
|
+
"## token-goat",
|
|
1905
|
+
"",
|
|
1906
|
+
"**Gate \u2014 before every file read, answer one question first: is there a token-goat command that returns just what I need?** If yes, run it. A read tool invoked without answering the gate is a violation, not an oversight. The gate is per file: batched or parallel reads do not exempt it.",
|
|
1907
|
+
"",
|
|
1908
|
+
`This gate decides *whether* to reach for a read tool at all. ${fallbackToolClause} only pick the *fallback* once token-goat has been ruled out for this read \u2014 they never authorize skipping the gate.`,
|
|
1909
|
+
"",
|
|
1910
|
+
"Exemptions (gate passes, read directly): the file is under ~200 lines and you need all of it; it was never indexed (new, untracked, or generated this turn); it is binary or an image; the target has no symbol handle (e.g. a literal mid-function).",
|
|
1911
|
+
"",
|
|
1912
|
+
"Failure shapes to catch yourself in, and the command that replaces each:",
|
|
1913
|
+
'- grep/search with context flags to find a function body \u2192 `read "file::symbol"`',
|
|
1914
|
+
'- paging one function with view/view_range \u2192 `read "file::symbol"`',
|
|
1915
|
+
'- reading one heading of a large doc \u2192 `section "file::Heading"`',
|
|
1916
|
+
"- searching for a symbol's callers \u2192 `refs file::symbol --callers`",
|
|
1917
|
+
'- searching for a *concept* rather than a literal string \u2192 `semantic "description"`',
|
|
1918
|
+
"- re-reading output you already captured \u2192 `bash-output`/`web-output` by ID",
|
|
1919
|
+
"- `glob`/`ls **/*` to orient in an unfamiliar repo \u2192 `map --compact`",
|
|
1920
|
+
"",
|
|
1921
|
+
'Commands: `symbol NAME`, `read "file::symbol"`, `section "file::Heading"`, `semantic "description"`, `outline file`/`skeleton file`, `map --compact`, `refs file::symbol --callers`, `changed --symbol`, `config-get file KEY`, `bash-output`/`web-output`, `gdrive-sections <file-id>`.',
|
|
1922
|
+
"",
|
|
1923
|
+
"Sub-agent briefs must carry this gate verbatim: a sub-agent inherits none of this context and its reads spend the same token budget.",
|
|
1924
|
+
"",
|
|
1925
|
+
"`token-goat stats` \u2014 self-check. Flat counts during code work mean the gate is being skipped."
|
|
1926
|
+
].join("\n");
|
|
1927
|
+
}
|
|
1928
|
+
function buildGuidanceBlock(h) {
|
|
1929
|
+
return [h.beginMarker, buildGuidanceBody(h.fallbackToolClause), h.endMarker].join("\n");
|
|
1930
|
+
}
|
|
1931
|
+
var init_guidance_block = __esm({
|
|
1932
|
+
"src/bridges/guidance_block.ts"() {
|
|
1933
|
+
"use strict";
|
|
1934
|
+
init_define_import_meta_env();
|
|
1935
|
+
}
|
|
1936
|
+
});
|
|
1937
|
+
|
|
1899
1938
|
// src/install.ts
|
|
1900
1939
|
import * as fs2 from "node:fs";
|
|
1901
1940
|
import * as os2 from "node:os";
|
|
@@ -2022,28 +2061,11 @@ function claudeMdPath() {
|
|
|
2022
2061
|
return path4.join(os2.homedir(), ".claude", "CLAUDE.md");
|
|
2023
2062
|
}
|
|
2024
2063
|
function buildClaudeMdBlock() {
|
|
2025
|
-
return
|
|
2026
|
-
CLAUDE_MD_BEGIN,
|
|
2027
|
-
|
|
2028
|
-
""
|
|
2029
|
-
|
|
2030
|
-
"- `token-goat symbol NAME` -- find a function/class/type",
|
|
2031
|
-
'- `token-goat read "file::symbol"` -- one function/method body',
|
|
2032
|
-
'- `token-goat section "file::Heading"` -- one doc or config section',
|
|
2033
|
-
'- `token-goat semantic "description"` -- find code by meaning',
|
|
2034
|
-
"- `token-goat outline file` / `token-goat skeleton file` -- signatures without bodies",
|
|
2035
|
-
"- `token-goat map --compact` -- project overview (low-token summary)",
|
|
2036
|
-
"- `token-goat refs file::symbol --callers` -- find callers of a symbol",
|
|
2037
|
-
"- `token-goat changed --symbol` -- symbols changed since a git ref",
|
|
2038
|
-
"- `token-goat config-get file KEY` -- read one config value",
|
|
2039
|
-
"- `token-goat bash-output` / `token-goat web-output` -- re-inspect cached output by ID",
|
|
2040
|
-
"- `token-goat gdrive-sections <file-id>` -- outline a Google Doc by ID",
|
|
2041
|
-
"",
|
|
2042
|
-
"Use this before a full-file `Read` or wide `Grep`, and before opening a large image",
|
|
2043
|
-
"(token-goat hooks shrink oversized images automatically). token-goat commands return",
|
|
2044
|
-
"narrow slices, typically 85-97% smaller than the full file.",
|
|
2045
|
-
CLAUDE_MD_END
|
|
2046
|
-
].join("\n");
|
|
2064
|
+
return buildGuidanceBlock({
|
|
2065
|
+
beginMarker: CLAUDE_MD_BEGIN,
|
|
2066
|
+
endMarker: CLAUDE_MD_END,
|
|
2067
|
+
fallbackToolClause: "Claude Code's own Read, Grep, and Glob preference rules"
|
|
2068
|
+
});
|
|
2047
2069
|
}
|
|
2048
2070
|
function writeClaudeMdBlock(p) {
|
|
2049
2071
|
return upsertDelimitedBlock(p, CLAUDE_MD_BEGIN, CLAUDE_MD_END, buildClaudeMdBlock());
|
|
@@ -2059,6 +2081,50 @@ function installClaudeMd() {
|
|
|
2059
2081
|
function uninstallClaudeMd() {
|
|
2060
2082
|
return stripClaudeMdBlock(claudeMdPath());
|
|
2061
2083
|
}
|
|
2084
|
+
function findStrayClaudeMdBlocks(searchRoot) {
|
|
2085
|
+
const root = searchRoot ?? path4.join(os2.homedir(), ".claude");
|
|
2086
|
+
const canonical = path4.resolve(claudeMdPath());
|
|
2087
|
+
const found = [];
|
|
2088
|
+
if (!fs2.existsSync(root)) return found;
|
|
2089
|
+
const SKIP_DIRS2 = /* @__PURE__ */ new Set(["node_modules", ".git"]);
|
|
2090
|
+
const MAX_DEPTH = 6;
|
|
2091
|
+
const hasRealBlock = (text) => {
|
|
2092
|
+
let sawBegin = false;
|
|
2093
|
+
for (const line of text.split(/\r?\n/)) {
|
|
2094
|
+
const trimmed = line.trim();
|
|
2095
|
+
if (trimmed === CLAUDE_MD_BEGIN) sawBegin = true;
|
|
2096
|
+
else if (sawBegin && trimmed === CLAUDE_MD_END) return true;
|
|
2097
|
+
}
|
|
2098
|
+
return false;
|
|
2099
|
+
};
|
|
2100
|
+
const walk = (dir, depth) => {
|
|
2101
|
+
if (depth > MAX_DEPTH) return;
|
|
2102
|
+
let entries;
|
|
2103
|
+
try {
|
|
2104
|
+
entries = fs2.readdirSync(dir, { withFileTypes: true });
|
|
2105
|
+
} catch {
|
|
2106
|
+
return;
|
|
2107
|
+
}
|
|
2108
|
+
for (const entry of entries) {
|
|
2109
|
+
const full = path4.join(dir, entry.name);
|
|
2110
|
+
if (entry.isDirectory()) {
|
|
2111
|
+
if (!SKIP_DIRS2.has(entry.name)) walk(full, depth + 1);
|
|
2112
|
+
continue;
|
|
2113
|
+
}
|
|
2114
|
+
if (!entry.isFile() || !entry.name.toLowerCase().endsWith(".md")) continue;
|
|
2115
|
+
if (path4.resolve(full) === canonical) continue;
|
|
2116
|
+
let text;
|
|
2117
|
+
try {
|
|
2118
|
+
text = fs2.readFileSync(full, "utf8");
|
|
2119
|
+
} catch {
|
|
2120
|
+
continue;
|
|
2121
|
+
}
|
|
2122
|
+
if (hasRealBlock(text)) found.push(full);
|
|
2123
|
+
}
|
|
2124
|
+
};
|
|
2125
|
+
walk(root, 0);
|
|
2126
|
+
return found.sort();
|
|
2127
|
+
}
|
|
2062
2128
|
function skillDir() {
|
|
2063
2129
|
return path4.join(os2.homedir(), ".claude", "skills", "token-goat");
|
|
2064
2130
|
}
|
|
@@ -2083,11 +2149,12 @@ function uninstallSkill() {
|
|
|
2083
2149
|
fs2.rmSync(dir, { recursive: true, force: true });
|
|
2084
2150
|
return true;
|
|
2085
2151
|
}
|
|
2086
|
-
var HOOK_EVENT_MAP, COMMAND_MARKER, LEGACY_COMMAND_MARKERS, HOOK_MARKER_PATTERNS, CURRENT_MARKER_PATTERN, SettingsParseError, CLAUDE_MD_BEGIN, CLAUDE_MD_END, SKILL_MD_CONTENT;
|
|
2152
|
+
var HOOK_EVENT_MAP, COMMAND_MARKER, LEGACY_COMMAND_MARKERS, HOOK_MARKER_PATTERNS, CURRENT_MARKER_PATTERN, SettingsParseError, CLAUDE_MD_BEGIN, CLAUDE_MD_END, SKILL_MD_FRONTMATTER, SKILL_MD_CONTENT;
|
|
2087
2153
|
var init_install = __esm({
|
|
2088
2154
|
"src/install.ts"() {
|
|
2089
2155
|
"use strict";
|
|
2090
2156
|
init_define_import_meta_env();
|
|
2157
|
+
init_guidance_block();
|
|
2091
2158
|
init_paths();
|
|
2092
2159
|
init_util2();
|
|
2093
2160
|
HOOK_EVENT_MAP = [
|
|
@@ -2095,7 +2162,8 @@ var init_install = __esm({
|
|
|
2095
2162
|
["PostToolUse", "post_tool_use"],
|
|
2096
2163
|
["PreCompact", "pre_compact"],
|
|
2097
2164
|
["UserPromptSubmit", "user_prompt_submit"],
|
|
2098
|
-
["SubagentStop", "subagent_stop"]
|
|
2165
|
+
["SubagentStop", "subagent_stop"],
|
|
2166
|
+
["SessionStart", "session_start"]
|
|
2099
2167
|
];
|
|
2100
2168
|
COMMAND_MARKER = "token-goat hook";
|
|
2101
2169
|
LEGACY_COMMAND_MARKERS = ["tokenwise", "token_goat", "tg-hook", "token-goat-hook"];
|
|
@@ -2105,31 +2173,13 @@ var init_install = __esm({
|
|
|
2105
2173
|
};
|
|
2106
2174
|
CLAUDE_MD_BEGIN = "<!-- token-goat-begin -->";
|
|
2107
2175
|
CLAUDE_MD_END = "<!-- token-goat-end -->";
|
|
2108
|
-
|
|
2176
|
+
SKILL_MD_FRONTMATTER = `---
|
|
2109
2177
|
name: token-goat
|
|
2110
2178
|
description: Use before reading whole files or grepping wide. token-goat commands (symbol, read, section, semantic, outline, skeleton, map, refs, changed, config-get, bash-output, web-output, gdrive-sections) return narrow slices of code and docs at a fraction of the token cost.
|
|
2111
|
-
|
|
2179
|
+
---`;
|
|
2180
|
+
SKILL_MD_CONTENT = `${SKILL_MD_FRONTMATTER}
|
|
2112
2181
|
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
Prefer token-goat commands over reading whole files:
|
|
2116
|
-
- \`token-goat symbol NAME\` -- find a function/class/type
|
|
2117
|
-
- \`token-goat read "file::symbol"\` -- one function/method body
|
|
2118
|
-
- \`token-goat section "file::Heading"\` -- one doc or config section
|
|
2119
|
-
- \`token-goat semantic "description"\` -- find code by meaning
|
|
2120
|
-
- \`token-goat outline file\` / \`token-goat skeleton file\` -- signatures without bodies
|
|
2121
|
-
- \`token-goat map --compact\` -- project overview (low-token summary)
|
|
2122
|
-
- \`token-goat refs file::symbol --callers\` -- find callers of a symbol
|
|
2123
|
-
- \`token-goat changed --symbol\` -- symbols changed since a git ref
|
|
2124
|
-
- \`token-goat config-get file KEY\` -- read one config value
|
|
2125
|
-
- \`token-goat bash-output\` / \`token-goat web-output\` -- re-inspect cached output by ID
|
|
2126
|
-
- \`token-goat gdrive-sections <file-id>\` -- outline a Google Doc by ID
|
|
2127
|
-
|
|
2128
|
-
Read is the right call when the file is under about 200 lines, was never indexed (new or
|
|
2129
|
-
untracked), or is an image (token-goat's hooks shrink oversized images automatically).
|
|
2130
|
-
|
|
2131
|
-
Image shrinking and repeat-read hints run on their own via hooks -- you do not call those
|
|
2132
|
-
directly.
|
|
2182
|
+
${buildGuidanceBody("Claude Code's own Read, Grep, and Glob preference rules")}
|
|
2133
2183
|
`;
|
|
2134
2184
|
}
|
|
2135
2185
|
});
|
|
@@ -2277,23 +2327,11 @@ function uninstallCodex() {
|
|
|
2277
2327
|
return removedAny;
|
|
2278
2328
|
}
|
|
2279
2329
|
function buildAgentsBlock() {
|
|
2280
|
-
return
|
|
2281
|
-
AGENTS_BEGIN,
|
|
2282
|
-
|
|
2283
|
-
""
|
|
2284
|
-
|
|
2285
|
-
"- `token-goat symbol NAME` -- find a function/class/type",
|
|
2286
|
-
'- `token-goat read "file::symbol"` -- one function/method body',
|
|
2287
|
-
'- `token-goat section "file::Heading"` -- one doc or config section',
|
|
2288
|
-
'- `token-goat semantic "description"` -- find code by meaning',
|
|
2289
|
-
"- `token-goat outline file` / `token-goat skeleton file` -- signatures without bodies",
|
|
2290
|
-
"",
|
|
2291
|
-
"Use this before a full-file read via `shell` (cat/type), before previewing a diff with",
|
|
2292
|
-
"`apply_patch`, and before a `view_image` on a large screenshot (token-goat hooks shrink",
|
|
2293
|
-
"oversized images automatically). token-goat commands return narrow slices, typically",
|
|
2294
|
-
"85-97% smaller than the full file.",
|
|
2295
|
-
AGENTS_END
|
|
2296
|
-
].join("\n");
|
|
2330
|
+
return buildGuidanceBlock({
|
|
2331
|
+
beginMarker: AGENTS_BEGIN,
|
|
2332
|
+
endMarker: AGENTS_END,
|
|
2333
|
+
fallbackToolClause: "Codex's own `shell` (cat/type), `apply_patch` preview, and `view_image` preferences"
|
|
2334
|
+
});
|
|
2297
2335
|
}
|
|
2298
2336
|
function writeAgentsBlock(p) {
|
|
2299
2337
|
return upsertDelimitedBlock(p, AGENTS_BEGIN, AGENTS_END, buildAgentsBlock());
|
|
@@ -2310,6 +2348,7 @@ var init_codex_install = __esm({
|
|
|
2310
2348
|
init_util2();
|
|
2311
2349
|
init_install();
|
|
2312
2350
|
init_codex();
|
|
2351
|
+
init_guidance_block();
|
|
2313
2352
|
init_matcher_group();
|
|
2314
2353
|
CODEX_COMMAND_MARKER = "token-goat-shim";
|
|
2315
2354
|
CODEX_MATCHERS = ["view_image|Bash", "apply_patch", "web_search"];
|
|
@@ -2677,6 +2716,22 @@ function copilotCliConfigPath(opts = {}) {
|
|
|
2677
2716
|
function copilotCliScriptPath(opts = {}) {
|
|
2678
2717
|
return path6.join(copilotCliHooksDir(opts), "token-goat-shim.js");
|
|
2679
2718
|
}
|
|
2719
|
+
function copilotCliInstructionsPath(opts = {}) {
|
|
2720
|
+
return path6.join(path6.dirname(copilotCliHooksDir(opts)), "copilot-instructions.md");
|
|
2721
|
+
}
|
|
2722
|
+
function buildCopilotInstructionsBlock() {
|
|
2723
|
+
return buildGuidanceBlock({
|
|
2724
|
+
beginMarker: COPILOT_INSTRUCTIONS_BEGIN,
|
|
2725
|
+
endMarker: COPILOT_INSTRUCTIONS_END,
|
|
2726
|
+
fallbackToolClause: "Copilot CLI's own `view`, `grep`, and `glob` tool-preference rules (and `Get-Content`/`Select-String`)"
|
|
2727
|
+
});
|
|
2728
|
+
}
|
|
2729
|
+
function writeCopilotInstructionsBlock(p) {
|
|
2730
|
+
return upsertDelimitedBlock(p, COPILOT_INSTRUCTIONS_BEGIN, COPILOT_INSTRUCTIONS_END, buildCopilotInstructionsBlock());
|
|
2731
|
+
}
|
|
2732
|
+
function stripCopilotInstructionsBlock(p) {
|
|
2733
|
+
return stripDelimitedBlock(p, COPILOT_INSTRUCTIONS_BEGIN, COPILOT_INSTRUCTIONS_END);
|
|
2734
|
+
}
|
|
2680
2735
|
function hookPowershellCommandFor(scriptPath, event) {
|
|
2681
2736
|
return `& ${hookCommandFor(scriptPath, event)}`;
|
|
2682
2737
|
}
|
|
@@ -2698,14 +2753,22 @@ function buildConfig(scriptPath) {
|
|
|
2698
2753
|
function installCopilotCli(opts = {}) {
|
|
2699
2754
|
const configPath2 = copilotCliConfigPath(opts);
|
|
2700
2755
|
const scriptPath = copilotCliScriptPath(opts);
|
|
2756
|
+
const instructionsPath = copilotCliInstructionsPath(opts);
|
|
2701
2757
|
const scriptChanged = writeIfDifferent(scriptPath, COPILOT_CLI_HOOK_SCRIPT);
|
|
2702
2758
|
const desiredText = JSON.stringify(buildConfig(scriptPath), null, 2) + "\n";
|
|
2703
2759
|
const configChanged = writeIfDifferent(configPath2, desiredText, true);
|
|
2704
|
-
|
|
2760
|
+
const instructionsChanged = writeCopilotInstructionsBlock(instructionsPath);
|
|
2761
|
+
return {
|
|
2762
|
+
configPath: configPath2,
|
|
2763
|
+
scriptPath,
|
|
2764
|
+
instructionsPath,
|
|
2765
|
+
alreadyInstalled: !scriptChanged && !configChanged && !instructionsChanged
|
|
2766
|
+
};
|
|
2705
2767
|
}
|
|
2706
2768
|
function uninstallCopilotCliScope(opts) {
|
|
2707
2769
|
const configPath2 = copilotCliConfigPath(opts);
|
|
2708
2770
|
const scriptPath = copilotCliScriptPath(opts);
|
|
2771
|
+
const instructionsPath = copilotCliInstructionsPath(opts);
|
|
2709
2772
|
let removedAny = false;
|
|
2710
2773
|
try {
|
|
2711
2774
|
fs4.unlinkSync(configPath2);
|
|
@@ -2717,6 +2780,9 @@ function uninstallCopilotCliScope(opts) {
|
|
|
2717
2780
|
removedAny = true;
|
|
2718
2781
|
} catch {
|
|
2719
2782
|
}
|
|
2783
|
+
if (stripCopilotInstructionsBlock(instructionsPath)) {
|
|
2784
|
+
removedAny = true;
|
|
2785
|
+
}
|
|
2720
2786
|
return removedAny;
|
|
2721
2787
|
}
|
|
2722
2788
|
function uninstallCopilotCli(opts = {}) {
|
|
@@ -2727,13 +2793,14 @@ function uninstallCopilotCli(opts = {}) {
|
|
|
2727
2793
|
const localRemoved = uninstallCopilotCliScope({ local: true });
|
|
2728
2794
|
return userRemoved || localRemoved;
|
|
2729
2795
|
}
|
|
2730
|
-
var COPILOT_CLI_HOOK_EVENTS, HOOK_TIMEOUT_SEC;
|
|
2796
|
+
var COPILOT_CLI_HOOK_EVENTS, COPILOT_INSTRUCTIONS_BEGIN, COPILOT_INSTRUCTIONS_END, HOOK_TIMEOUT_SEC;
|
|
2731
2797
|
var init_copilot_cli_install = __esm({
|
|
2732
2798
|
"src/bridges/copilot_cli_install.ts"() {
|
|
2733
2799
|
"use strict";
|
|
2734
2800
|
init_define_import_meta_env();
|
|
2735
2801
|
init_util2();
|
|
2736
2802
|
init_copilot_cli();
|
|
2803
|
+
init_guidance_block();
|
|
2737
2804
|
COPILOT_CLI_HOOK_EVENTS = [
|
|
2738
2805
|
"preToolUse",
|
|
2739
2806
|
"postToolUse",
|
|
@@ -2742,6 +2809,8 @@ var init_copilot_cli_install = __esm({
|
|
|
2742
2809
|
"subagentStop",
|
|
2743
2810
|
"userPromptSubmitted"
|
|
2744
2811
|
];
|
|
2812
|
+
COPILOT_INSTRUCTIONS_BEGIN = "<!-- token-goat-begin -->";
|
|
2813
|
+
COPILOT_INSTRUCTIONS_END = "<!-- token-goat-end -->";
|
|
2745
2814
|
HOOK_TIMEOUT_SEC = 60;
|
|
2746
2815
|
}
|
|
2747
2816
|
});
|
|
@@ -3032,7 +3101,8 @@ var init_hook_registry = __esm({
|
|
|
3032
3101
|
stop: "Stop",
|
|
3033
3102
|
pre_compact: "PreCompact",
|
|
3034
3103
|
user_prompt_submit: "UserPromptSubmit",
|
|
3035
|
-
subagent_stop: "SubagentStop"
|
|
3104
|
+
subagent_stop: "SubagentStop",
|
|
3105
|
+
session_start: "SessionStart"
|
|
3036
3106
|
};
|
|
3037
3107
|
EVENTS_WITHOUT_ADDITIONAL_CONTEXT = /* @__PURE__ */ new Set([
|
|
3038
3108
|
"notification",
|
|
@@ -3709,6 +3779,8 @@ function _buildConfig(raw, projectRaw = {}) {
|
|
|
3709
3779
|
hi.cross_session_read_dedup_ttl_secs = envInt("TOKEN_GOAT_CROSS_SESSION_READ_DEDUP_TTL_SECS", hi.cross_session_read_dedup_ttl_secs, ...boundsOf("hints.cross_session_read_dedup_ttl_secs"));
|
|
3710
3780
|
hi.mcp_dedup_ttl_secs = validatedInt(hi_raw["mcp_dedup_ttl_secs"], hi.mcp_dedup_ttl_secs, ...boundsOf("hints.mcp_dedup_ttl_secs"));
|
|
3711
3781
|
hi.mcp_dedup_ttl_secs = envInt("TOKEN_GOAT_MCP_DEDUP_TTL_SECS", hi.mcp_dedup_ttl_secs, ...boundsOf("hints.mcp_dedup_ttl_secs"));
|
|
3782
|
+
hi.session_start_reminder = validatedBool(hi_raw["session_start_reminder"], hi.session_start_reminder);
|
|
3783
|
+
hi.session_start_reminder = envBool("TOKEN_GOAT_SESSION_START_REMINDER", hi.session_start_reminder);
|
|
3712
3784
|
hi.min_session_hint_savings_bytes = envInt("TOKEN_GOAT_SESSION_HINT_MIN_BYTES", hi.min_session_hint_savings_bytes, ...boundsOf("hints.min_session_hint_savings_bytes"));
|
|
3713
3785
|
const triggers_raw = hi_raw["prompt_triggers"];
|
|
3714
3786
|
if (Array.isArray(triggers_raw)) {
|
|
@@ -3896,7 +3968,8 @@ function saveConfig(config2) {
|
|
|
3896
3968
|
log_large_file_hint_outcomes: config2.hints.log_large_file_hint_outcomes,
|
|
3897
3969
|
cross_session_read_dedup: config2.hints.cross_session_read_dedup,
|
|
3898
3970
|
cross_session_read_dedup_ttl_secs: config2.hints.cross_session_read_dedup_ttl_secs,
|
|
3899
|
-
mcp_dedup_ttl_secs: config2.hints.mcp_dedup_ttl_secs
|
|
3971
|
+
mcp_dedup_ttl_secs: config2.hints.mcp_dedup_ttl_secs,
|
|
3972
|
+
session_start_reminder: config2.hints.session_start_reminder
|
|
3900
3973
|
},
|
|
3901
3974
|
hooks: {
|
|
3902
3975
|
watchdog_ms: config2.hooks.watchdog_ms
|
|
@@ -4074,7 +4147,8 @@ var init_config = __esm({
|
|
|
4074
4147
|
log_large_file_hint_outcomes: false,
|
|
4075
4148
|
cross_session_read_dedup: false,
|
|
4076
4149
|
cross_session_read_dedup_ttl_secs: 2700,
|
|
4077
|
-
mcp_dedup_ttl_secs: 45
|
|
4150
|
+
mcp_dedup_ttl_secs: 45,
|
|
4151
|
+
session_start_reminder: true
|
|
4078
4152
|
},
|
|
4079
4153
|
hooks: {
|
|
4080
4154
|
watchdog_ms: 700
|
|
@@ -4254,6 +4328,7 @@ var init_config = __esm({
|
|
|
4254
4328
|
"hints.cross_session_read_dedup": ["TOKEN_GOAT_CROSS_SESSION_READ_DEDUP"],
|
|
4255
4329
|
"hints.cross_session_read_dedup_ttl_secs": ["TOKEN_GOAT_CROSS_SESSION_READ_DEDUP_TTL_SECS"],
|
|
4256
4330
|
"hints.mcp_dedup_ttl_secs": ["TOKEN_GOAT_MCP_DEDUP_TTL_SECS"],
|
|
4331
|
+
"hints.session_start_reminder": ["TOKEN_GOAT_SESSION_START_REMINDER"],
|
|
4257
4332
|
"hints.min_session_hint_savings_bytes": ["TOKEN_GOAT_SESSION_HINT_MIN_BYTES"],
|
|
4258
4333
|
"hooks.watchdog_ms": ["TOKEN_GOAT_HOOK_WATCHDOG_MS"],
|
|
4259
4334
|
"webfetch.max_file_count": ["TOKEN_GOAT_WEB_CACHE_MAX_FILES"],
|
|
@@ -5763,6 +5838,7 @@ var init_stats = __esm({
|
|
|
5763
5838
|
session_slice: SOURCE_READ,
|
|
5764
5839
|
gdrive_sections: SOURCE_READ,
|
|
5765
5840
|
pr_slice: SOURCE_READ,
|
|
5841
|
+
compact_doc: SOURCE_READ,
|
|
5766
5842
|
note_read: SOURCE_READ,
|
|
5767
5843
|
note_list: SOURCE_READ,
|
|
5768
5844
|
// note-add is a write (like insert-section/replace, which record no stat at all -- neither
|
|
@@ -5833,6 +5909,7 @@ var init_stats = __esm({
|
|
|
5833
5909
|
"session-slice": /* @__PURE__ */ new Set(["session_slice"]),
|
|
5834
5910
|
"gdrive-sections": /* @__PURE__ */ new Set(["gdrive_sections"]),
|
|
5835
5911
|
"pr-slice": /* @__PURE__ */ new Set(["pr_slice"]),
|
|
5912
|
+
"compact-doc": /* @__PURE__ */ new Set(["compact_doc"]),
|
|
5836
5913
|
"note-add": /* @__PURE__ */ new Set(["note_write"]),
|
|
5837
5914
|
"note-get": /* @__PURE__ */ new Set(["note_read"]),
|
|
5838
5915
|
"note-list": /* @__PURE__ */ new Set(["note_list"]),
|
|
@@ -7343,23 +7420,23 @@ function isNoisePath(inputPath) {
|
|
|
7343
7420
|
}
|
|
7344
7421
|
}
|
|
7345
7422
|
const slashIdx = p.lastIndexOf("/");
|
|
7346
|
-
const
|
|
7347
|
-
if (NOISE_BASENAMES.has(
|
|
7423
|
+
const basename20 = slashIdx >= 0 ? p.slice(slashIdx + 1) : p;
|
|
7424
|
+
if (NOISE_BASENAMES.has(basename20)) {
|
|
7348
7425
|
return true;
|
|
7349
7426
|
}
|
|
7350
|
-
if (
|
|
7427
|
+
if (basename20.startsWith(".improve-state-") || basename20.startsWith("improve_commit_msg_")) {
|
|
7351
7428
|
return true;
|
|
7352
7429
|
}
|
|
7353
|
-
const dotIdx =
|
|
7430
|
+
const dotIdx = basename20.lastIndexOf(".");
|
|
7354
7431
|
if (dotIdx >= 0) {
|
|
7355
|
-
const ext2 =
|
|
7432
|
+
const ext2 = basename20.slice(dotIdx);
|
|
7356
7433
|
if (NOISE_EXTS.has(ext2)) {
|
|
7357
7434
|
return true;
|
|
7358
7435
|
}
|
|
7359
7436
|
}
|
|
7360
7437
|
for (const ext2 of NOISE_EXTS) {
|
|
7361
7438
|
if (ext2.includes(".") && ext2.split(".").length > 2) {
|
|
7362
|
-
if (
|
|
7439
|
+
if (basename20.endsWith(ext2)) {
|
|
7363
7440
|
return true;
|
|
7364
7441
|
}
|
|
7365
7442
|
}
|
|
@@ -7931,11 +8008,11 @@ function buildPackageManifestHint(options) {
|
|
|
7931
8008
|
return null;
|
|
7932
8009
|
}
|
|
7933
8010
|
}
|
|
7934
|
-
function _sanitizeHintPath(
|
|
7935
|
-
if (typeof
|
|
8011
|
+
function _sanitizeHintPath(path64) {
|
|
8012
|
+
if (typeof path64 !== "string") {
|
|
7936
8013
|
return "???";
|
|
7937
8014
|
}
|
|
7938
|
-
return
|
|
8015
|
+
return path64.replace(/[\x00]/g, "").slice(0, 200);
|
|
7939
8016
|
}
|
|
7940
8017
|
var HINT_PRIORITY_MEDIUM;
|
|
7941
8018
|
var init_hints = __esm({
|
|
@@ -7947,15 +8024,15 @@ var init_hints = __esm({
|
|
|
7947
8024
|
});
|
|
7948
8025
|
|
|
7949
8026
|
// src/hints/lang_patterns.ts
|
|
7950
|
-
function isLockFile(
|
|
7951
|
-
return LOCK_FILE_NAMES.has(
|
|
8027
|
+
function isLockFile(basename20) {
|
|
8028
|
+
return LOCK_FILE_NAMES.has(basename20.toLowerCase());
|
|
7952
8029
|
}
|
|
7953
|
-
function isManifestFile(
|
|
7954
|
-
const lower =
|
|
8030
|
+
function isManifestFile(basename20) {
|
|
8031
|
+
const lower = basename20.toLowerCase();
|
|
7955
8032
|
if (MANIFEST_FILE_NAMES.has(lower)) return true;
|
|
7956
8033
|
const dot = lower.lastIndexOf(".");
|
|
7957
8034
|
if (dot !== -1 && MANIFEST_EXTENSIONS.has(lower.slice(dot))) return true;
|
|
7958
|
-
if (MANIFEST_BASENAME_PATTERNS.some((re) => re.test(
|
|
8035
|
+
if (MANIFEST_BASENAME_PATTERNS.some((re) => re.test(basename20))) return true;
|
|
7959
8036
|
return false;
|
|
7960
8037
|
}
|
|
7961
8038
|
function pathSegments(filePath) {
|
|
@@ -8294,8 +8371,8 @@ function formatHeadingTree(headings, filePath) {
|
|
|
8294
8371
|
}
|
|
8295
8372
|
return lines2.join("\n");
|
|
8296
8373
|
}
|
|
8297
|
-
function getWellKnownSections(
|
|
8298
|
-
return WELL_KNOWN_SECTIONS[
|
|
8374
|
+
function getWellKnownSections(basename20) {
|
|
8375
|
+
return WELL_KNOWN_SECTIONS[basename20] ?? [];
|
|
8299
8376
|
}
|
|
8300
8377
|
function extractChangelogVersionHint(content, filePath) {
|
|
8301
8378
|
const lines2 = content.split("\n");
|
|
@@ -11006,16 +11083,16 @@ var init_file_type_handler = __esm({
|
|
|
11006
11083
|
|
|
11007
11084
|
// src/skill_cache.ts
|
|
11008
11085
|
import * as fs15 from "fs/promises";
|
|
11009
|
-
import { resolve as
|
|
11086
|
+
import { resolve as resolve6 } from "path";
|
|
11010
11087
|
import { homedir as homedir7 } from "os";
|
|
11011
|
-
import { readdirSync as
|
|
11088
|
+
import { readdirSync as readdirSync8, readFileSync as readFileSync11, existsSync as existsSync13, statSync as statSync7, unlinkSync as unlinkSync8 } from "node:fs";
|
|
11012
11089
|
function skillOutputsDir() {
|
|
11013
11090
|
if (_skillOutputsDirOverride) return _skillOutputsDirOverride;
|
|
11014
|
-
return
|
|
11091
|
+
return resolve6(dataDir(), SKILLS_OUTPUT_SUBDIR);
|
|
11015
11092
|
}
|
|
11016
11093
|
function skillsSourceDir() {
|
|
11017
11094
|
if (_skillsSourceDirOverride) return _skillsSourceDirOverride;
|
|
11018
|
-
return
|
|
11095
|
+
return resolve6(homedir7(), ".claude", "skills");
|
|
11019
11096
|
}
|
|
11020
11097
|
async function ensureSkillsDir() {
|
|
11021
11098
|
try {
|
|
@@ -11158,7 +11235,7 @@ async function listOutputs() {
|
|
|
11158
11235
|
continue;
|
|
11159
11236
|
}
|
|
11160
11237
|
try {
|
|
11161
|
-
const content = await fs15.readFile(
|
|
11238
|
+
const content = await fs15.readFile(resolve6(dir, entry.name), "utf-8");
|
|
11162
11239
|
const meta3 = JSON.parse(content);
|
|
11163
11240
|
metas.push(meta3);
|
|
11164
11241
|
} catch {
|
|
@@ -11192,7 +11269,7 @@ async function findCrossSessionEntry(skillName, contentSha) {
|
|
|
11192
11269
|
continue;
|
|
11193
11270
|
}
|
|
11194
11271
|
const dir = skillOutputsDir();
|
|
11195
|
-
const bodyPath =
|
|
11272
|
+
const bodyPath = resolve6(dir, `${meta3.outputId}.txt`);
|
|
11196
11273
|
try {
|
|
11197
11274
|
const bodyExists = await fs15.access(bodyPath).then(() => true).catch(() => false);
|
|
11198
11275
|
if (bodyExists) {
|
|
@@ -11247,7 +11324,7 @@ async function storeOutput(sessionId, skillName, body, opts) {
|
|
|
11247
11324
|
const truncBuf = buf.slice(truncStart);
|
|
11248
11325
|
storedBody = truncBuf.toString("utf-8");
|
|
11249
11326
|
}
|
|
11250
|
-
await atomicWriteText(
|
|
11327
|
+
await atomicWriteText(resolve6(dir, `${outId}.txt`), storedBody);
|
|
11251
11328
|
const meta3 = {
|
|
11252
11329
|
outputId: outId,
|
|
11253
11330
|
skillName: name2,
|
|
@@ -11257,7 +11334,7 @@ async function storeOutput(sessionId, skillName, body, opts) {
|
|
|
11257
11334
|
truncated,
|
|
11258
11335
|
sourcePath: opts?.sourcePath || ""
|
|
11259
11336
|
};
|
|
11260
|
-
await atomicWriteText(
|
|
11337
|
+
await atomicWriteText(resolve6(dir, `${outId}.meta`), JSON.stringify(meta3, null, 2));
|
|
11261
11338
|
pruneSkillOutputs();
|
|
11262
11339
|
return meta3;
|
|
11263
11340
|
} catch {
|
|
@@ -11277,7 +11354,7 @@ async function storeCompact(sessionId, skillName, compactText, sourceSha) {
|
|
|
11277
11354
|
text = `<!-- source_sha: ${sourceSha.slice(0, 12)} -->
|
|
11278
11355
|
${text}`;
|
|
11279
11356
|
}
|
|
11280
|
-
await atomicWriteText(
|
|
11357
|
+
await atomicWriteText(resolve6(dir, fileId), text);
|
|
11281
11358
|
} catch {
|
|
11282
11359
|
}
|
|
11283
11360
|
}
|
|
@@ -11293,11 +11370,11 @@ function getCompactAnySessionSync(skillName) {
|
|
|
11293
11370
|
const suffix = compactSessionSuffix(skillName);
|
|
11294
11371
|
if (!suffix) return null;
|
|
11295
11372
|
const dir = skillOutputsDir();
|
|
11296
|
-
const entries =
|
|
11373
|
+
const entries = readdirSync8(dir, { withFileTypes: true });
|
|
11297
11374
|
for (const entry of entries) {
|
|
11298
11375
|
if (!matchesCompactSuffix(entry.name, entry.isFile(), suffix)) continue;
|
|
11299
11376
|
try {
|
|
11300
|
-
const text =
|
|
11377
|
+
const text = readFileSync11(resolve6(dir, entry.name), "utf-8");
|
|
11301
11378
|
if (text.trim()) return text;
|
|
11302
11379
|
} catch {
|
|
11303
11380
|
continue;
|
|
@@ -11325,7 +11402,7 @@ async function readSkillHits(skillName) {
|
|
|
11325
11402
|
const name2 = safeSkillName(skillName);
|
|
11326
11403
|
if (!name2) return { count: 0, lastTs: 0 };
|
|
11327
11404
|
const dir = skillOutputsDir();
|
|
11328
|
-
const hitsFile =
|
|
11405
|
+
const hitsFile = resolve6(dir, `${sanitizeSkillId(name2)}.hits`);
|
|
11329
11406
|
const content = await fs15.readFile(hitsFile, "utf-8").catch(() => null);
|
|
11330
11407
|
if (content) {
|
|
11331
11408
|
const parsed = JSON.parse(content);
|
|
@@ -11375,7 +11452,7 @@ async function incrementSkillHit(skillName) {
|
|
|
11375
11452
|
if (!name2) return;
|
|
11376
11453
|
await ensureSkillsDir();
|
|
11377
11454
|
const dir = skillOutputsDir();
|
|
11378
|
-
const hitsFile =
|
|
11455
|
+
const hitsFile = resolve6(dir, `${sanitizeSkillId(name2)}.hits`);
|
|
11379
11456
|
const lockPath = `${hitsFile}.lock`;
|
|
11380
11457
|
await runExclusiveInProcess(lockPath, async () => {
|
|
11381
11458
|
const locked = await acquireSkillHitLock(lockPath);
|
|
@@ -11422,14 +11499,14 @@ async function listSkills(sessionId) {
|
|
|
11422
11499
|
let compactLen = 0;
|
|
11423
11500
|
let compactText = "";
|
|
11424
11501
|
try {
|
|
11425
|
-
const stat2 = await fs15.stat(
|
|
11502
|
+
const stat2 = await fs15.stat(resolve6(dir, compactFileId));
|
|
11426
11503
|
compactLen = stat2.size;
|
|
11427
|
-
compactText = await fs15.readFile(
|
|
11504
|
+
compactText = await fs15.readFile(resolve6(dir, compactFileId), "utf-8").catch(() => "");
|
|
11428
11505
|
} catch {
|
|
11429
11506
|
compactLen = 0;
|
|
11430
11507
|
}
|
|
11431
11508
|
const hasMarker = extractCompactFromMarker(
|
|
11432
|
-
await fs15.readFile(
|
|
11509
|
+
await fs15.readFile(resolve6(dir, `${meta3.outputId}.txt`), "utf-8").catch(() => "")
|
|
11433
11510
|
) !== null;
|
|
11434
11511
|
const compactStale = isCompactStale(compactText, meta3.skillName, meta3.contentSha);
|
|
11435
11512
|
const { count: hitCount } = await readSkillHits(meta3.skillName);
|
|
@@ -11465,7 +11542,7 @@ async function getSkillFilePath(skillName) {
|
|
|
11465
11542
|
}
|
|
11466
11543
|
}
|
|
11467
11544
|
async function resolvePluginSkillPath(pluginName, skillSlug) {
|
|
11468
|
-
const manifestPath = _pluginsManifestPathOverride ??
|
|
11545
|
+
const manifestPath = _pluginsManifestPathOverride ?? resolve6(homedir7(), ".claude", "plugins", "installed_plugins.json");
|
|
11469
11546
|
let raw;
|
|
11470
11547
|
try {
|
|
11471
11548
|
raw = await fs15.readFile(manifestPath, "utf8");
|
|
@@ -11488,7 +11565,7 @@ async function resolvePluginSkillPath(pluginName, skillSlug) {
|
|
|
11488
11565
|
if (typeof entry !== "object" || entry === null) continue;
|
|
11489
11566
|
const installPath = entry["installPath"];
|
|
11490
11567
|
if (typeof installPath !== "string" || installPath === "") continue;
|
|
11491
|
-
const diskPath =
|
|
11568
|
+
const diskPath = resolve6(installPath, "skills", skillSlug, "SKILL.md");
|
|
11492
11569
|
try {
|
|
11493
11570
|
await fs15.access(diskPath);
|
|
11494
11571
|
return diskPath;
|
|
@@ -11507,7 +11584,7 @@ async function installedSkillPath(skillName) {
|
|
|
11507
11584
|
const pluginPath = await resolvePluginSkillPath(name2.slice(0, colonIdx), name2.slice(colonIdx + 1));
|
|
11508
11585
|
if (pluginPath !== null) return pluginPath;
|
|
11509
11586
|
}
|
|
11510
|
-
const diskPath =
|
|
11587
|
+
const diskPath = resolve6(skillsSourceDir(), name2, "SKILL.md");
|
|
11511
11588
|
try {
|
|
11512
11589
|
await fs15.access(diskPath);
|
|
11513
11590
|
return diskPath;
|
|
@@ -11522,16 +11599,16 @@ function pruneSkillOutputs(maxCount = DEFAULT_MAX_COUNT, maxAgeMs = DEFAULT_MAX_
|
|
|
11522
11599
|
if (!existsSync13(dir)) return 0;
|
|
11523
11600
|
const cutoff = Date.now() - maxAgeMs;
|
|
11524
11601
|
const entries = [];
|
|
11525
|
-
for (const file2 of
|
|
11602
|
+
for (const file2 of readdirSync8(dir)) {
|
|
11526
11603
|
if (!file2.endsWith(".meta")) continue;
|
|
11527
11604
|
const outputId = file2.slice(0, -".meta".length);
|
|
11528
11605
|
let ts;
|
|
11529
11606
|
try {
|
|
11530
|
-
const parsed = JSON.parse(
|
|
11607
|
+
const parsed = JSON.parse(readFileSync11(resolve6(dir, file2), "utf-8"));
|
|
11531
11608
|
ts = parsed.ts;
|
|
11532
11609
|
} catch {
|
|
11533
11610
|
try {
|
|
11534
|
-
ts = statSync7(
|
|
11611
|
+
ts = statSync7(resolve6(dir, file2)).mtimeMs;
|
|
11535
11612
|
} catch {
|
|
11536
11613
|
continue;
|
|
11537
11614
|
}
|
|
@@ -11541,7 +11618,7 @@ function pruneSkillOutputs(maxCount = DEFAULT_MAX_COUNT, maxAgeMs = DEFAULT_MAX_
|
|
|
11541
11618
|
const removeEntry = (outputId) => {
|
|
11542
11619
|
for (const ext2 of [".meta", ".txt"]) {
|
|
11543
11620
|
try {
|
|
11544
|
-
unlinkSync8(
|
|
11621
|
+
unlinkSync8(resolve6(dir, `${outputId}${ext2}`));
|
|
11545
11622
|
} catch {
|
|
11546
11623
|
}
|
|
11547
11624
|
}
|
|
@@ -11655,7 +11732,7 @@ async function ocrImage(input) {
|
|
|
11655
11732
|
if (_ocrUnavailableThisProcess) return null;
|
|
11656
11733
|
const entryPath = resolveTesseractEntry();
|
|
11657
11734
|
if (entryPath === null) return null;
|
|
11658
|
-
return new Promise((
|
|
11735
|
+
return new Promise((resolve21) => {
|
|
11659
11736
|
let settled = false;
|
|
11660
11737
|
let child;
|
|
11661
11738
|
try {
|
|
@@ -11664,7 +11741,7 @@ async function ocrImage(input) {
|
|
|
11664
11741
|
});
|
|
11665
11742
|
} catch {
|
|
11666
11743
|
_ocrUnavailableThisProcess = true;
|
|
11667
|
-
|
|
11744
|
+
resolve21(null);
|
|
11668
11745
|
return;
|
|
11669
11746
|
}
|
|
11670
11747
|
const chunks = [];
|
|
@@ -11677,7 +11754,7 @@ async function ocrImage(input) {
|
|
|
11677
11754
|
child.kill();
|
|
11678
11755
|
} catch {
|
|
11679
11756
|
}
|
|
11680
|
-
|
|
11757
|
+
resolve21(result);
|
|
11681
11758
|
};
|
|
11682
11759
|
const timer = setTimeout(() => finish(null, true), _ocrTimeoutMs);
|
|
11683
11760
|
child.stdout?.on("data", (c) => chunks.push(c));
|
|
@@ -11813,19 +11890,19 @@ async function preReadImageHandler(event) {
|
|
|
11813
11890
|
}
|
|
11814
11891
|
const result = await shrinkImage(input, { sizeThresholdBytes: 0 });
|
|
11815
11892
|
if (result === null) return passOutput();
|
|
11816
|
-
const
|
|
11893
|
+
const basename20 = path16.basename(filePath);
|
|
11817
11894
|
if (loadConfig().image_shrink.ocr_enabled) {
|
|
11818
11895
|
const ocr = await ocrImage(result.data);
|
|
11819
11896
|
if (ocr !== null && isTextHeavy(ocr, loadConfig().image_shrink.ocr_min_confidence)) {
|
|
11820
11897
|
const textBytes = Buffer.byteLength(ocr.text, "utf8");
|
|
11821
11898
|
const saved2 = Math.max(0, result.shrunkBytes - textBytes);
|
|
11822
|
-
recordStat("image_ocr", saved2, Math.round(saved2 / 4), void 0,
|
|
11823
|
-
return contextOutput(formatOcrSummary(ocr,
|
|
11899
|
+
recordStat("image_ocr", saved2, Math.round(saved2 / 4), void 0, basename20);
|
|
11900
|
+
return contextOutput(formatOcrSummary(ocr, basename20, result.originalBytes));
|
|
11824
11901
|
}
|
|
11825
11902
|
}
|
|
11826
11903
|
const saved = result.originalBytes - result.shrunkBytes;
|
|
11827
|
-
const { summary, dataUrl } = formatShrinkSummary(result,
|
|
11828
|
-
recordStat("image_shrink", saved, Math.round(saved / 4), void 0,
|
|
11904
|
+
const { summary, dataUrl } = formatShrinkSummary(result, basename20);
|
|
11905
|
+
recordStat("image_shrink", saved, Math.round(saved / 4), void 0, basename20);
|
|
11829
11906
|
return contextOutput(`${summary}
|
|
11830
11907
|
${dataUrl}`);
|
|
11831
11908
|
}
|
|
@@ -12354,8 +12431,8 @@ var init_parser_types = __esm({
|
|
|
12354
12431
|
// src/hooks_read.ts
|
|
12355
12432
|
import * as fs19 from "node:fs";
|
|
12356
12433
|
import * as path20 from "node:path";
|
|
12357
|
-
function isTsConfigFile(
|
|
12358
|
-
const lower =
|
|
12434
|
+
function isTsConfigFile(basename20) {
|
|
12435
|
+
const lower = basename20.toLowerCase();
|
|
12359
12436
|
return /^tsconfig(\..+)?\.json$/i.test(lower) || lower === "jsconfig.json";
|
|
12360
12437
|
}
|
|
12361
12438
|
function largeFileDenyBytes() {
|
|
@@ -12455,18 +12532,18 @@ function describeSliceAdvice(slice, absPath) {
|
|
|
12455
12532
|
}
|
|
12456
12533
|
return "Use Read with offset/limit to sample specific sections.";
|
|
12457
12534
|
}
|
|
12458
|
-
function isSourceExtension(
|
|
12459
|
-
if (SOURCE_EXT_RE.test(
|
|
12460
|
-
const language = detectLanguage(
|
|
12535
|
+
function isSourceExtension(basename20) {
|
|
12536
|
+
if (SOURCE_EXT_RE.test(basename20)) return true;
|
|
12537
|
+
const language = detectLanguage(basename20);
|
|
12461
12538
|
return language === "apex" || language === "salesforce_metadata" || language === "salesforce_markup";
|
|
12462
12539
|
}
|
|
12463
|
-
function isDispatchedFileType(
|
|
12464
|
-
return DISPATCHED_FILE_TYPE_EXTS.has(path20.extname(
|
|
12540
|
+
function isDispatchedFileType(basename20) {
|
|
12541
|
+
return DISPATCHED_FILE_TYPE_EXTS.has(path20.extname(basename20).slice(1).toLowerCase());
|
|
12465
12542
|
}
|
|
12466
|
-
function surgicalHint(filePath,
|
|
12543
|
+
function surgicalHint(filePath, basename20, lineCount) {
|
|
12467
12544
|
if (lineCount < loadConfig().hints.min_file_lines_for_hint) return "";
|
|
12468
|
-
const isDocFile = /\.(md|mdx|rst|txt)$/i.test(
|
|
12469
|
-
const isSectionFile = /\.(json|jsonc|css|scss|sass|less|yaml|yml|toml)$/i.test(
|
|
12545
|
+
const isDocFile = /\.(md|mdx|rst|txt)$/i.test(basename20);
|
|
12546
|
+
const isSectionFile = /\.(json|jsonc|css|scss|sass|less|yaml|yml|toml)$/i.test(basename20);
|
|
12470
12547
|
if (isDocFile) {
|
|
12471
12548
|
return 'Use `token-goat section "' + filePath + '::HeadingName"` to extract a part.';
|
|
12472
12549
|
} else if (isSectionFile) {
|
|
@@ -12514,7 +12591,7 @@ function buildLineDiff(oldContent, newContent, label) {
|
|
|
12514
12591
|
}
|
|
12515
12592
|
return out2.join("\n");
|
|
12516
12593
|
}
|
|
12517
|
-
function loadSnapshotDiff(sessionId, normalized,
|
|
12594
|
+
function loadSnapshotDiff(sessionId, normalized, basename20) {
|
|
12518
12595
|
const oldSnap = load(sessionId, normalized);
|
|
12519
12596
|
if (oldSnap === null) return { kind: "none" };
|
|
12520
12597
|
try {
|
|
@@ -12526,7 +12603,7 @@ function loadSnapshotDiff(sessionId, normalized, basename19) {
|
|
|
12526
12603
|
const truncIdx = oldRaw.indexOf(TRUNC_MARKER);
|
|
12527
12604
|
const oldContent = truncIdx >= 0 ? oldRaw.slice(0, truncIdx) : oldRaw;
|
|
12528
12605
|
if (oldContent === currentContent) return { kind: "unchanged", currentContent };
|
|
12529
|
-
const diff = buildLineDiff(oldContent, currentContent,
|
|
12606
|
+
const diff = buildLineDiff(oldContent, currentContent, basename20);
|
|
12530
12607
|
if (diff === "") return { kind: "none" };
|
|
12531
12608
|
const savedBytes = Math.max(0, currentContent.length - diff.length);
|
|
12532
12609
|
return { kind: "diff", diff, savedBytes, currentContent };
|
|
@@ -12599,8 +12676,8 @@ function preReadHandlerInner(event) {
|
|
|
12599
12676
|
"node_modules is typically noise; use npm ls, npm outdated, or npm audit instead for dependency info. To force access, use: token-goat read node_modules/package/file.js::symbol-name or token-goat section node_modules/package/file.js::heading"
|
|
12600
12677
|
);
|
|
12601
12678
|
}
|
|
12602
|
-
const
|
|
12603
|
-
if (isLockFile(
|
|
12679
|
+
const basename20 = path20.basename(normalized);
|
|
12680
|
+
if (isLockFile(basename20)) {
|
|
12604
12681
|
return denyOutput(
|
|
12605
12682
|
'Lock files are rarely useful to read in full. Use `token-goat section "' + normalized + '::<section>"` to extract a specific dependency, or read the relevant manifest instead.'
|
|
12606
12683
|
);
|
|
@@ -12623,20 +12700,20 @@ function preReadHandlerInner(event) {
|
|
|
12623
12700
|
return quietContextOutput(manifestHint.text);
|
|
12624
12701
|
}
|
|
12625
12702
|
}
|
|
12626
|
-
if (isTsConfigFile(
|
|
12703
|
+
if (isTsConfigFile(basename20) && wasFileReadThisSession(normalized)) {
|
|
12627
12704
|
recordActualRead(event, normalized);
|
|
12628
12705
|
return quietContextOutput(
|
|
12629
|
-
"Already read " +
|
|
12706
|
+
"Already read " + basename20 + '. Use `token-goat section "' + normalized + '::compilerOptions"` to extract compiler options, or `token-goat config-get ' + normalized + " compilerOptions.target` for a single value."
|
|
12630
12707
|
);
|
|
12631
12708
|
}
|
|
12632
|
-
if (isManifestFile(
|
|
12709
|
+
if (isManifestFile(basename20) && wasFileReadThisSession(normalized)) {
|
|
12633
12710
|
recordActualRead(event, normalized);
|
|
12634
12711
|
return quietContextOutput(
|
|
12635
|
-
"You've already read " +
|
|
12712
|
+
"You've already read " + basename20 + '. Use `token-goat section "' + normalized + '::<field>"` or `token-goat config-get ' + normalized + " <key>` to extract just the value you need."
|
|
12636
12713
|
);
|
|
12637
12714
|
}
|
|
12638
12715
|
const skillName = detectSkillFile(normalized);
|
|
12639
|
-
if (skillName &&
|
|
12716
|
+
if (skillName && basename20 === "SKILL.md") {
|
|
12640
12717
|
try {
|
|
12641
12718
|
const body = fs19.readFileSync(normalized, "utf-8");
|
|
12642
12719
|
const bodySha = contentHash(body);
|
|
@@ -12666,7 +12743,7 @@ function preReadHandlerInner(event) {
|
|
|
12666
12743
|
}
|
|
12667
12744
|
}
|
|
12668
12745
|
}
|
|
12669
|
-
const isNotebook = /\.ipynb$/i.test(
|
|
12746
|
+
const isNotebook = /\.ipynb$/i.test(basename20);
|
|
12670
12747
|
if (event.toolName !== "Grep" && isNotebook) {
|
|
12671
12748
|
try {
|
|
12672
12749
|
const rawBytes = fs19.readFileSync(normalized);
|
|
@@ -12683,7 +12760,7 @@ function preReadHandlerInner(event) {
|
|
|
12683
12760
|
} catch {
|
|
12684
12761
|
}
|
|
12685
12762
|
}
|
|
12686
|
-
const isMarkdown = /\.(md|mdx|markdown|rst)$/i.test(
|
|
12763
|
+
const isMarkdown = /\.(md|mdx|markdown|rst)$/i.test(basename20);
|
|
12687
12764
|
if (event.toolName !== "Grep" && isMarkdown) {
|
|
12688
12765
|
let fileContent = null;
|
|
12689
12766
|
let markdownSize = null;
|
|
@@ -12701,9 +12778,9 @@ function preReadHandlerInner(event) {
|
|
|
12701
12778
|
const alreadyRead = wasFileReadThisSession(normalized);
|
|
12702
12779
|
const hintText = formatHeadingTree(headings, normalized);
|
|
12703
12780
|
const headingTextsLower = new Set(headings.map((h) => h.text.trim().toLowerCase()));
|
|
12704
|
-
const wellKnown = getWellKnownSections(
|
|
12781
|
+
const wellKnown = getWellKnownSections(basename20).filter((s) => headingTextsLower.has(s.trim().toLowerCase()));
|
|
12705
12782
|
const wellKnownText = wellKnown.length > 0 ? "\nQuick access: " + wellKnown.map((s) => 'token-goat section "' + normalized + "::" + s + '"').join(" | ") : "";
|
|
12706
|
-
const changelogExtra =
|
|
12783
|
+
const changelogExtra = basename20.toLowerCase() === "changelog.md" ? extractChangelogVersionHint(fileContent, normalized) : "";
|
|
12707
12784
|
let message = hintText + wellKnownText + changelogExtra;
|
|
12708
12785
|
const slice = estimateRequestedSlice(event, normalized);
|
|
12709
12786
|
const gateSize = slice.kind === "bytes" && markdownSize !== null ? Math.min(slice.bytes, markdownSize) : markdownSize;
|
|
@@ -12724,19 +12801,19 @@ function preReadHandlerInner(event) {
|
|
|
12724
12801
|
if (isMemoryMd && wasFileReadThisSession(normalized)) {
|
|
12725
12802
|
recordActualRead(event, normalized);
|
|
12726
12803
|
recordStat("session_hint", 0, 0);
|
|
12727
|
-
const isMainMemory =
|
|
12804
|
+
const isMainMemory = basename20.toLowerCase() === "memory.md";
|
|
12728
12805
|
return denyOutput(
|
|
12729
12806
|
isMainMemory ? "MEMORY.md was read this session. Its content is in the compact manifest as 'session memory'." : normalized + ' was already read this session. Memory files rarely change mid-session. Use `token-goat section "' + normalized + '::SectionHeading"` to extract one section.'
|
|
12730
12807
|
);
|
|
12731
12808
|
}
|
|
12732
|
-
if (/^\.improve-state-.*\.json$/.test(
|
|
12809
|
+
if (/^\.improve-state-.*\.json$/.test(basename20) && wasFileReadThisSession(normalized)) {
|
|
12733
12810
|
recordActualRead(event, normalized);
|
|
12734
12811
|
recordStat("session_hint", 0, 0);
|
|
12735
12812
|
return denyOutput(
|
|
12736
12813
|
"Orchestrator state already read this session. " + sessionArtifactRecall(normalized)
|
|
12737
12814
|
);
|
|
12738
12815
|
}
|
|
12739
|
-
if (/^\.env(\.\w+)?$/.test(
|
|
12816
|
+
if (/^\.env(\.\w+)?$/.test(basename20) && wasFileReadThisSession(normalized)) {
|
|
12740
12817
|
recordActualRead(event, normalized);
|
|
12741
12818
|
recordStat("session_hint", 0, 0);
|
|
12742
12819
|
return denyOutput(
|
|
@@ -12753,19 +12830,19 @@ function preReadHandlerInner(event) {
|
|
|
12753
12830
|
);
|
|
12754
12831
|
}
|
|
12755
12832
|
const artifactSessionId = getSessionId();
|
|
12756
|
-
const snapDiff = loadSnapshotDiff(artifactSessionId, normalized,
|
|
12833
|
+
const snapDiff = loadSnapshotDiff(artifactSessionId, normalized, basename20);
|
|
12757
12834
|
if (snapDiff.kind === "unchanged") {
|
|
12758
12835
|
recordActualRead(event, normalized);
|
|
12759
12836
|
recordStat("session_hint", 0, 0);
|
|
12760
12837
|
return denyOutput(
|
|
12761
|
-
|
|
12838
|
+
basename20 + " is unchanged since last read. " + sessionArtifactRecall(normalized)
|
|
12762
12839
|
);
|
|
12763
12840
|
}
|
|
12764
12841
|
if (snapDiff.kind === "diff") {
|
|
12765
12842
|
recordActualRead(event, normalized);
|
|
12766
12843
|
recordStat("session_hint", snapDiff.savedBytes, Math.round(snapDiff.savedBytes / 4));
|
|
12767
12844
|
return denyOutput(
|
|
12768
|
-
"Content changed since last read of " +
|
|
12845
|
+
"Content changed since last read of " + basename20 + ". Here is what changed:\n\n```diff\n" + snapDiff.diff + "\n```\n\n" + sessionArtifactRecall(normalized)
|
|
12769
12846
|
);
|
|
12770
12847
|
}
|
|
12771
12848
|
recordActualRead(event, normalized);
|
|
@@ -12788,8 +12865,8 @@ function preReadHandlerInner(event) {
|
|
|
12788
12865
|
return quietContextOutput(label + ": " + sessionArtifactRecall(normalized));
|
|
12789
12866
|
}
|
|
12790
12867
|
}
|
|
12791
|
-
const isDocDiffable = /\.(md|mdx|markdown|rst|txt)$/i.test(
|
|
12792
|
-
const isSourceDiffable = loadConfig().hints.serve_diff_on_reread && DIFFABLE_SOURCE_RE.test(
|
|
12868
|
+
const isDocDiffable = /\.(md|mdx|markdown|rst|txt)$/i.test(basename20);
|
|
12869
|
+
const isSourceDiffable = loadConfig().hints.serve_diff_on_reread && DIFFABLE_SOURCE_RE.test(basename20);
|
|
12793
12870
|
if ((isDocDiffable || isSourceDiffable) && wasFileReadThisSession(normalized) && !isProtectedRecentRead(normalized, loadConfig().hints.protect_recent_reads)) {
|
|
12794
12871
|
if (wasFileTruncatedThisSession(normalized)) {
|
|
12795
12872
|
if (estimateTruncatedLineCount(normalized) >= loadConfig().hints.truncated_read_min_lines) {
|
|
@@ -12799,12 +12876,12 @@ function preReadHandlerInner(event) {
|
|
|
12799
12876
|
}
|
|
12800
12877
|
}
|
|
12801
12878
|
const sessionId = getSessionId();
|
|
12802
|
-
const snapDiff = loadSnapshotDiff(sessionId, normalized,
|
|
12879
|
+
const snapDiff = loadSnapshotDiff(sessionId, normalized, basename20);
|
|
12803
12880
|
if (snapDiff.kind === "unchanged") {
|
|
12804
12881
|
recordActualRead(event, normalized);
|
|
12805
12882
|
recordStat("session_hint", 0, 0);
|
|
12806
12883
|
return denyOutput(
|
|
12807
|
-
(
|
|
12884
|
+
(basename20 + " is unchanged since last read. " + surgicalHint(normalized, basename20, countTextLines(snapDiff.currentContent))).trimEnd()
|
|
12808
12885
|
);
|
|
12809
12886
|
}
|
|
12810
12887
|
if (snapDiff.kind === "diff") {
|
|
@@ -12812,7 +12889,7 @@ function preReadHandlerInner(event) {
|
|
|
12812
12889
|
recordActualRead(event, normalized);
|
|
12813
12890
|
recordStat("diff_hint", snapDiff.savedBytes, Math.round(snapDiff.savedBytes / 4));
|
|
12814
12891
|
return denyOutput(
|
|
12815
|
-
("Content changed since last read of " +
|
|
12892
|
+
("Content changed since last read of " + basename20 + ". Here is what changed:\n\n```diff\n" + snapDiff.diff + "\n```\n\n" + surgicalHint(normalized, basename20, countTextLines(snapDiff.currentContent))).trimEnd()
|
|
12816
12893
|
);
|
|
12817
12894
|
}
|
|
12818
12895
|
}
|
|
@@ -12858,13 +12935,13 @@ function preReadHandlerInner(event) {
|
|
|
12858
12935
|
return denyOutput(truncatedReadDenyMessage(normalized));
|
|
12859
12936
|
}
|
|
12860
12937
|
}
|
|
12861
|
-
if (/\.(md|mdx|markdown|rst)$/i.test(
|
|
12938
|
+
if (/\.(md|mdx|markdown|rst)$/i.test(basename20)) {
|
|
12862
12939
|
recordStat("session_hint", rereadBytes, Math.round(rereadBytes / 4));
|
|
12863
12940
|
return denyOutput(
|
|
12864
12941
|
'Markdown file already read this session. Use `token-goat section "' + normalized + '::HeadingName"` to read one section. ' + editAnywayHint(normalized)
|
|
12865
12942
|
);
|
|
12866
12943
|
}
|
|
12867
|
-
const isSourceExt = isSourceExtension(
|
|
12944
|
+
const isSourceExt = isSourceExtension(basename20);
|
|
12868
12945
|
if (isSourceExt && reads >= 2) {
|
|
12869
12946
|
recordStat("read_count_deny", rereadBytes, Math.round(rereadBytes / 4));
|
|
12870
12947
|
recordStat("session_hint", rereadBytes, Math.round(rereadBytes / 4));
|
|
@@ -13115,7 +13192,7 @@ function ensureTransformerLoaded() {
|
|
|
13115
13192
|
}
|
|
13116
13193
|
}
|
|
13117
13194
|
function sleep(ms) {
|
|
13118
|
-
return new Promise((
|
|
13195
|
+
return new Promise((resolve21) => setTimeout(resolve21, ms));
|
|
13119
13196
|
}
|
|
13120
13197
|
async function buildExtractorWithRetry(pipelineFn, modelName) {
|
|
13121
13198
|
let lastError;
|
|
@@ -13799,8 +13876,8 @@ async function readOoxmlZip(filePath) {
|
|
|
13799
13876
|
const data = fs20.readFileSync(filePath);
|
|
13800
13877
|
return fflate.unzipSync(new Uint8Array(data));
|
|
13801
13878
|
}
|
|
13802
|
-
function decodeZipEntry(entries,
|
|
13803
|
-
const bytes = entries[
|
|
13879
|
+
function decodeZipEntry(entries, path64) {
|
|
13880
|
+
const bytes = entries[path64];
|
|
13804
13881
|
if (bytes === void 0) return null;
|
|
13805
13882
|
return new TextDecoder("utf-8").decode(bytes);
|
|
13806
13883
|
}
|
|
@@ -14010,9 +14087,9 @@ async function notesPathFor(entries, slidePath) {
|
|
|
14010
14087
|
}
|
|
14011
14088
|
return null;
|
|
14012
14089
|
}
|
|
14013
|
-
async function parseSlide(entries,
|
|
14014
|
-
const xml = decodeZipEntry(entries,
|
|
14015
|
-
if (xml === null) throw new Error(`missing part: ${
|
|
14090
|
+
async function parseSlide(entries, path64) {
|
|
14091
|
+
const xml = decodeZipEntry(entries, path64);
|
|
14092
|
+
if (xml === null) throw new Error(`missing part: ${path64}`);
|
|
14016
14093
|
return parseOoxmlPart(xml);
|
|
14017
14094
|
}
|
|
14018
14095
|
async function notesTextFor(entries, notesPath) {
|
|
@@ -14028,8 +14105,8 @@ async function pptxOutline(filePath) {
|
|
|
14028
14105
|
const { entries, slidePaths } = await listSlideParts(filePath);
|
|
14029
14106
|
const out2 = [];
|
|
14030
14107
|
for (let i = 0; i < slidePaths.length; i++) {
|
|
14031
|
-
const
|
|
14032
|
-
const parsed = await parseSlide(entries,
|
|
14108
|
+
const path64 = slidePaths[i];
|
|
14109
|
+
const parsed = await parseSlide(entries, path64);
|
|
14033
14110
|
const shapes = slideShapes(parsed);
|
|
14034
14111
|
const titleShape = shapes.find((s) => {
|
|
14035
14112
|
const t = shapePlaceholderType(s);
|
|
@@ -14038,7 +14115,7 @@ async function pptxOutline(filePath) {
|
|
|
14038
14115
|
const title = titleShape !== void 0 ? shapeText(titleShape) : "";
|
|
14039
14116
|
const allText = collectTextRuns(parsed, "a:t").join(" ");
|
|
14040
14117
|
const bodyChars = Math.max(0, allText.length - title.length);
|
|
14041
|
-
const hasNotes = (await notesTextFor(entries, await notesPathFor(entries,
|
|
14118
|
+
const hasNotes = (await notesTextFor(entries, await notesPathFor(entries, path64))).length > 0;
|
|
14042
14119
|
out2.push({ slide: i + 1, title, bodyChars, hasNotes });
|
|
14043
14120
|
}
|
|
14044
14121
|
return out2;
|
|
@@ -14048,13 +14125,13 @@ async function pptxSlideText(filePath, slideNumber, includeNotes) {
|
|
|
14048
14125
|
if (slideNumber < 1 || slideNumber > slidePaths.length) {
|
|
14049
14126
|
throw new Error(`slide ${slideNumber} out of range (this deck has ${slidePaths.length} slides)`);
|
|
14050
14127
|
}
|
|
14051
|
-
const
|
|
14052
|
-
const parsed = await parseSlide(entries,
|
|
14128
|
+
const path64 = slidePaths[slideNumber - 1];
|
|
14129
|
+
const parsed = await parseSlide(entries, path64);
|
|
14053
14130
|
const shapes = slideShapes(parsed);
|
|
14054
14131
|
const blocks = [...shapes.map(shapeText).filter((t) => t.length > 0), ...tableRowBlocks(parsed)];
|
|
14055
14132
|
const lines2 = [`# Slide ${slideNumber}`, ...blocks];
|
|
14056
14133
|
if (includeNotes) {
|
|
14057
|
-
const notes = await notesTextFor(entries, await notesPathFor(entries,
|
|
14134
|
+
const notes = await notesTextFor(entries, await notesPathFor(entries, path64));
|
|
14058
14135
|
if (notes.length > 0) lines2.push("", "## Speaker notes", notes);
|
|
14059
14136
|
}
|
|
14060
14137
|
return lines2.join("\n\n");
|
|
@@ -18160,6 +18237,77 @@ function loadParserCtor() {
|
|
|
18160
18237
|
}
|
|
18161
18238
|
return _parserCtor;
|
|
18162
18239
|
}
|
|
18240
|
+
function boundSymbolBody(body) {
|
|
18241
|
+
return body.length > MAX_SYMBOL_BODY_CHARS ? "" : body;
|
|
18242
|
+
}
|
|
18243
|
+
function boundSymbolDocstring(docstring) {
|
|
18244
|
+
if (docstring.length <= MAX_SYMBOL_DOCSTRING_CHARS) return docstring;
|
|
18245
|
+
let end = MAX_SYMBOL_DOCSTRING_CHARS - DOCSTRING_TRUNCATION_MARKER.length;
|
|
18246
|
+
const cutsSurrogatePair = end > 0 && docstring.charCodeAt(end - 1) >= 55296 && docstring.charCodeAt(end - 1) <= 56319;
|
|
18247
|
+
if (cutsSurrogatePair) end -= 1;
|
|
18248
|
+
return docstring.slice(0, Math.max(0, end)) + DOCSTRING_TRUNCATION_MARKER;
|
|
18249
|
+
}
|
|
18250
|
+
function scanJsonValueEnd(content, start) {
|
|
18251
|
+
const first2 = content[start];
|
|
18252
|
+
if (first2 === void 0) return content.length;
|
|
18253
|
+
if (first2 === '"') {
|
|
18254
|
+
let escaping = false;
|
|
18255
|
+
for (let j = start + 1; j < content.length; j++) {
|
|
18256
|
+
const c = content[j];
|
|
18257
|
+
if (escaping) {
|
|
18258
|
+
escaping = false;
|
|
18259
|
+
continue;
|
|
18260
|
+
}
|
|
18261
|
+
if (c === "\\") {
|
|
18262
|
+
escaping = true;
|
|
18263
|
+
continue;
|
|
18264
|
+
}
|
|
18265
|
+
if (c === '"') return j + 1;
|
|
18266
|
+
}
|
|
18267
|
+
return content.length;
|
|
18268
|
+
}
|
|
18269
|
+
if (first2 === "{" || first2 === "[") {
|
|
18270
|
+
const stack = [];
|
|
18271
|
+
let inStr = false;
|
|
18272
|
+
let escaping = false;
|
|
18273
|
+
for (let j = start; j < content.length; j++) {
|
|
18274
|
+
const c = content[j];
|
|
18275
|
+
if (inStr) {
|
|
18276
|
+
if (escaping) {
|
|
18277
|
+
escaping = false;
|
|
18278
|
+
continue;
|
|
18279
|
+
}
|
|
18280
|
+
if (c === "\\") {
|
|
18281
|
+
escaping = true;
|
|
18282
|
+
continue;
|
|
18283
|
+
}
|
|
18284
|
+
if (c === '"') inStr = false;
|
|
18285
|
+
continue;
|
|
18286
|
+
}
|
|
18287
|
+
if (c === '"') {
|
|
18288
|
+
inStr = true;
|
|
18289
|
+
continue;
|
|
18290
|
+
}
|
|
18291
|
+
if (c === "{" || c === "[") stack.push(c);
|
|
18292
|
+
else if (c === "}" || c === "]") {
|
|
18293
|
+
const open = stack.pop();
|
|
18294
|
+
if (open !== (c === "}" ? "{" : "[")) return j;
|
|
18295
|
+
if (stack.length === 0) return j + 1;
|
|
18296
|
+
}
|
|
18297
|
+
}
|
|
18298
|
+
return content.length;
|
|
18299
|
+
}
|
|
18300
|
+
for (let j = start; j < content.length; j++) {
|
|
18301
|
+
const c = content[j];
|
|
18302
|
+
if (c === "," || c === "}" || c === "]" || c === "\n" || c === "\r") return j;
|
|
18303
|
+
}
|
|
18304
|
+
return content.length;
|
|
18305
|
+
}
|
|
18306
|
+
function countNewlines(s) {
|
|
18307
|
+
let n = 0;
|
|
18308
|
+
for (let i = 0; i < s.length; i++) if (s[i] === "\n") n++;
|
|
18309
|
+
return n;
|
|
18310
|
+
}
|
|
18163
18311
|
function loadGrammar(lang, filePath, content) {
|
|
18164
18312
|
const useTsx = lang === "typescript" && filePath !== void 0 && path26.extname(filePath).toLowerCase() === ".tsx";
|
|
18165
18313
|
const useCppHeader = lang === "c" && filePath !== void 0 && path26.extname(filePath).toLowerCase() === ".h" && content !== void 0 && CPP_HEADER_SNIFF_RE.test(content);
|
|
@@ -18701,12 +18849,12 @@ function extractMarkdownSymbols(content, filePath) {
|
|
|
18701
18849
|
function extractJsonSymbols(content, filePath) {
|
|
18702
18850
|
const out2 = [];
|
|
18703
18851
|
try {
|
|
18704
|
-
const lines2 = content.split(/\r?\n/);
|
|
18705
18852
|
let depth = 0;
|
|
18706
18853
|
let inString = false;
|
|
18707
18854
|
let escaping = false;
|
|
18708
18855
|
let strChars = [];
|
|
18709
18856
|
let strStartLine = 1;
|
|
18857
|
+
let strStartOffset = 0;
|
|
18710
18858
|
let depthWhenStringOpened = 0;
|
|
18711
18859
|
let line = 1;
|
|
18712
18860
|
for (let i = 0; i < content.length; i++) {
|
|
@@ -18727,45 +18875,22 @@ function extractJsonSymbols(content, filePath) {
|
|
|
18727
18875
|
inString = true;
|
|
18728
18876
|
strChars = [];
|
|
18729
18877
|
strStartLine = line;
|
|
18878
|
+
strStartOffset = i;
|
|
18730
18879
|
depthWhenStringOpened = depth;
|
|
18731
18880
|
} else {
|
|
18732
18881
|
inString = false;
|
|
18733
18882
|
let k = i + 1;
|
|
18734
|
-
let keyToColonNewlines = 0;
|
|
18735
18883
|
while (k < content.length && /\s/.test(content[k] ?? "")) {
|
|
18736
|
-
if (content[k] === "\n") keyToColonNewlines++;
|
|
18737
18884
|
k++;
|
|
18738
18885
|
}
|
|
18739
18886
|
if (content[k] === ":" && depthWhenStringOpened === 1) {
|
|
18740
18887
|
let v = k + 1;
|
|
18741
|
-
let gapNewlines = 0;
|
|
18742
18888
|
while (v < content.length && /\s/.test(content[v] ?? "")) {
|
|
18743
|
-
if (content[v] === "\n") gapNewlines++;
|
|
18744
18889
|
v++;
|
|
18745
18890
|
}
|
|
18746
|
-
|
|
18747
|
-
|
|
18748
|
-
|
|
18749
|
-
let valueLine = line + keyToColonNewlines + gapNewlines;
|
|
18750
|
-
let valueEscaping = false;
|
|
18751
|
-
for (let j = v + 1; j < content.length; j++) {
|
|
18752
|
-
const vch = content[j];
|
|
18753
|
-
if (vch === "\n") valueLine++;
|
|
18754
|
-
if (valueEscaping) {
|
|
18755
|
-
valueEscaping = false;
|
|
18756
|
-
continue;
|
|
18757
|
-
}
|
|
18758
|
-
if (vch === "\\") {
|
|
18759
|
-
valueEscaping = true;
|
|
18760
|
-
continue;
|
|
18761
|
-
}
|
|
18762
|
-
if (vch === '"') break;
|
|
18763
|
-
}
|
|
18764
|
-
lineEnd = valueLine;
|
|
18765
|
-
if (lineEnd > strStartLine) {
|
|
18766
|
-
body = lines2.slice(strStartLine - 1, lineEnd).join("\n").trim();
|
|
18767
|
-
}
|
|
18768
|
-
}
|
|
18891
|
+
const valueEnd = scanJsonValueEnd(content, v);
|
|
18892
|
+
const body = content.slice(strStartOffset, valueEnd);
|
|
18893
|
+
const lineEnd = strStartLine + countNewlines(body);
|
|
18769
18894
|
out2.push({
|
|
18770
18895
|
filePath,
|
|
18771
18896
|
name: strChars.join(""),
|
|
@@ -19237,7 +19362,7 @@ function writeParseResult(filePath, content, result, dbPath) {
|
|
|
19237
19362
|
);
|
|
19238
19363
|
for (const s of result.symbols) {
|
|
19239
19364
|
if (s.name === "" || s.kind === "") continue;
|
|
19240
|
-
insSym.run(s.filePath, s.name, s.kind, s.lineStart, s.lineEnd, s.body, s.docstring);
|
|
19365
|
+
insSym.run(s.filePath, s.name, s.kind, s.lineStart, s.lineEnd, boundSymbolBody(s.body), boundSymbolDocstring(s.docstring));
|
|
19241
19366
|
}
|
|
19242
19367
|
const insRef = db.prepare(
|
|
19243
19368
|
"INSERT INTO refs (file_path, name, line, col, context) VALUES (?, ?, ?, ?, ?)"
|
|
@@ -19382,7 +19507,7 @@ function safeMtime(filePath) {
|
|
|
19382
19507
|
return 0;
|
|
19383
19508
|
}
|
|
19384
19509
|
}
|
|
19385
|
-
var _require4, _parserCtor, _grammarCache, CPP_HEADER_SNIFF_RE, TSJS_KIND_BY_TYPE, TSJS_FN_SCOPE_TYPES, PY_KIND_BY_TYPE, GO_KIND_BY_TYPE, GO_FN_SCOPE_TYPES, GO_LOCAL_KINDS, RUST_KIND_BY_TYPE, RUST_FN_SCOPE_TYPES, RUST_LOCAL_KINDS, RUBY_KIND_BY_TYPE, JAVA_KIND_BY_TYPE, CPP_KIND_BY_TYPE, REF_LANGUAGES, SCOPE_TYPES_BY_LANG, CALL_TYPES_BY_LANG, REF_NOISE_BY_LANG, JS_NOISE, EMPTY_STRING_SET, FALLBACK_PATTERNS, NO_TREE_SITTER_EXTRACTORS, DISABLED_EMBED_SHA_PREFIX, UNAVAILABLE_EMBED_SHA_PREFIX;
|
|
19510
|
+
var _require4, _parserCtor, _grammarCache, CPP_HEADER_SNIFF_RE, MAX_SYMBOL_BODY_CHARS, MAX_SYMBOL_DOCSTRING_CHARS, DOCSTRING_TRUNCATION_MARKER, TSJS_KIND_BY_TYPE, TSJS_FN_SCOPE_TYPES, PY_KIND_BY_TYPE, GO_KIND_BY_TYPE, GO_FN_SCOPE_TYPES, GO_LOCAL_KINDS, RUST_KIND_BY_TYPE, RUST_FN_SCOPE_TYPES, RUST_LOCAL_KINDS, RUBY_KIND_BY_TYPE, JAVA_KIND_BY_TYPE, CPP_KIND_BY_TYPE, REF_LANGUAGES, SCOPE_TYPES_BY_LANG, CALL_TYPES_BY_LANG, REF_NOISE_BY_LANG, JS_NOISE, EMPTY_STRING_SET, FALLBACK_PATTERNS, NO_TREE_SITTER_EXTRACTORS, DISABLED_EMBED_SHA_PREFIX, UNAVAILABLE_EMBED_SHA_PREFIX;
|
|
19386
19511
|
var init_parser = __esm({
|
|
19387
19512
|
"src/parser.ts"() {
|
|
19388
19513
|
"use strict";
|
|
@@ -19428,6 +19553,9 @@ var init_parser = __esm({
|
|
|
19428
19553
|
_require4 = createRequire5(import.meta.url);
|
|
19429
19554
|
_grammarCache = /* @__PURE__ */ new Map();
|
|
19430
19555
|
CPP_HEADER_SNIFF_RE = /\bclass\s+\w|\bnamespace\s+\w|\btemplate\s*<|::\s*\w|\b(?:public|private|protected)\s*:/;
|
|
19556
|
+
MAX_SYMBOL_BODY_CHARS = 128 * 1024;
|
|
19557
|
+
MAX_SYMBOL_DOCSTRING_CHARS = 16 * 1024;
|
|
19558
|
+
DOCSTRING_TRUNCATION_MARKER = "\n[... docstring truncated by token-goat ...]";
|
|
19431
19559
|
TSJS_KIND_BY_TYPE = /* @__PURE__ */ new Map([
|
|
19432
19560
|
["function_declaration", "function"],
|
|
19433
19561
|
["generator_function_declaration", "function"],
|
|
@@ -21275,8 +21403,8 @@ var require_command = __commonJS({
|
|
|
21275
21403
|
init_define_import_meta_env();
|
|
21276
21404
|
var EventEmitter = __require("node:events").EventEmitter;
|
|
21277
21405
|
var childProcess = __require("node:child_process");
|
|
21278
|
-
var
|
|
21279
|
-
var
|
|
21406
|
+
var path64 = __require("node:path");
|
|
21407
|
+
var fs56 = __require("node:fs");
|
|
21280
21408
|
var process4 = __require("node:process");
|
|
21281
21409
|
var { Argument: Argument2, humanReadableArgName } = require_argument();
|
|
21282
21410
|
var { CommanderError: CommanderError2 } = require_error();
|
|
@@ -22208,11 +22336,11 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
22208
22336
|
let launchWithNode = false;
|
|
22209
22337
|
const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
|
|
22210
22338
|
function findFile(baseDir, baseName) {
|
|
22211
|
-
const localBin =
|
|
22212
|
-
if (
|
|
22213
|
-
if (sourceExt.includes(
|
|
22339
|
+
const localBin = path64.resolve(baseDir, baseName);
|
|
22340
|
+
if (fs56.existsSync(localBin)) return localBin;
|
|
22341
|
+
if (sourceExt.includes(path64.extname(baseName))) return void 0;
|
|
22214
22342
|
const foundExt = sourceExt.find(
|
|
22215
|
-
(ext2) =>
|
|
22343
|
+
(ext2) => fs56.existsSync(`${localBin}${ext2}`)
|
|
22216
22344
|
);
|
|
22217
22345
|
if (foundExt) return `${localBin}${foundExt}`;
|
|
22218
22346
|
return void 0;
|
|
@@ -22224,21 +22352,21 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
22224
22352
|
if (this._scriptPath) {
|
|
22225
22353
|
let resolvedScriptPath;
|
|
22226
22354
|
try {
|
|
22227
|
-
resolvedScriptPath =
|
|
22355
|
+
resolvedScriptPath = fs56.realpathSync(this._scriptPath);
|
|
22228
22356
|
} catch (err2) {
|
|
22229
22357
|
resolvedScriptPath = this._scriptPath;
|
|
22230
22358
|
}
|
|
22231
|
-
executableDir =
|
|
22232
|
-
|
|
22359
|
+
executableDir = path64.resolve(
|
|
22360
|
+
path64.dirname(resolvedScriptPath),
|
|
22233
22361
|
executableDir
|
|
22234
22362
|
);
|
|
22235
22363
|
}
|
|
22236
22364
|
if (executableDir) {
|
|
22237
22365
|
let localFile = findFile(executableDir, executableFile);
|
|
22238
22366
|
if (!localFile && !subcommand._executableFile && this._scriptPath) {
|
|
22239
|
-
const legacyName =
|
|
22367
|
+
const legacyName = path64.basename(
|
|
22240
22368
|
this._scriptPath,
|
|
22241
|
-
|
|
22369
|
+
path64.extname(this._scriptPath)
|
|
22242
22370
|
);
|
|
22243
22371
|
if (legacyName !== this._name) {
|
|
22244
22372
|
localFile = findFile(
|
|
@@ -22249,7 +22377,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
22249
22377
|
}
|
|
22250
22378
|
executableFile = localFile || executableFile;
|
|
22251
22379
|
}
|
|
22252
|
-
launchWithNode = sourceExt.includes(
|
|
22380
|
+
launchWithNode = sourceExt.includes(path64.extname(executableFile));
|
|
22253
22381
|
let proc;
|
|
22254
22382
|
if (process4.platform !== "win32") {
|
|
22255
22383
|
if (launchWithNode) {
|
|
@@ -23089,7 +23217,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
23089
23217
|
* @return {Command}
|
|
23090
23218
|
*/
|
|
23091
23219
|
nameFromFilename(filename) {
|
|
23092
|
-
this._name =
|
|
23220
|
+
this._name = path64.basename(filename, path64.extname(filename));
|
|
23093
23221
|
return this;
|
|
23094
23222
|
}
|
|
23095
23223
|
/**
|
|
@@ -23103,9 +23231,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
23103
23231
|
* @param {string} [path]
|
|
23104
23232
|
* @return {(string|null|Command)}
|
|
23105
23233
|
*/
|
|
23106
|
-
executableDir(
|
|
23107
|
-
if (
|
|
23108
|
-
this._executableDir =
|
|
23234
|
+
executableDir(path65) {
|
|
23235
|
+
if (path65 === void 0) return this._executableDir;
|
|
23236
|
+
this._executableDir = path65;
|
|
23109
23237
|
return this;
|
|
23110
23238
|
}
|
|
23111
23239
|
/**
|
|
@@ -23341,7 +23469,7 @@ import * as readline from "node:readline";
|
|
|
23341
23469
|
async function defaultConfirm(question) {
|
|
23342
23470
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
23343
23471
|
try {
|
|
23344
|
-
const answer = await new Promise((
|
|
23472
|
+
const answer = await new Promise((resolve21) => rl.question(question, resolve21));
|
|
23345
23473
|
return /^y(es)?$/i.test(answer.trim());
|
|
23346
23474
|
} finally {
|
|
23347
23475
|
rl.close();
|
|
@@ -23880,7 +24008,8 @@ function walkProject(rootDir, opts = {}) {
|
|
|
23880
24008
|
const excludeTests = opts.excludeTests === true;
|
|
23881
24009
|
const includeEmbeddableDocuments = opts.includeEmbeddableDocuments === true;
|
|
23882
24010
|
const extraSkipDirs = loadConfig().indexing.skip_dirs;
|
|
23883
|
-
|
|
24011
|
+
const maxFiles = opts.maxFiles ?? MAX_FILES_SCANNED;
|
|
24012
|
+
while (stack.length > 0 && files.length < maxFiles) {
|
|
23884
24013
|
const dir = stack.pop();
|
|
23885
24014
|
if (dir === void 0) break;
|
|
23886
24015
|
let entries;
|
|
@@ -23903,7 +24032,7 @@ function walkProject(rootDir, opts = {}) {
|
|
|
23903
24032
|
if (excludeTests && isTestFile(full)) continue;
|
|
23904
24033
|
files.push(full);
|
|
23905
24034
|
languages[lang] = (languages[lang] ?? 0) + 1;
|
|
23906
|
-
if (files.length >=
|
|
24035
|
+
if (files.length >= maxFiles) break;
|
|
23907
24036
|
}
|
|
23908
24037
|
}
|
|
23909
24038
|
}
|
|
@@ -24043,9 +24172,9 @@ function formatMemSuggestions(projectRoot) {
|
|
|
24043
24172
|
if (suggestions.length === 0) return "";
|
|
24044
24173
|
const lines2 = ["", "## mem suggestions"];
|
|
24045
24174
|
for (const s of suggestions) {
|
|
24046
|
-
const
|
|
24175
|
+
const basename20 = path33.basename(s.path);
|
|
24047
24176
|
lines2.push(
|
|
24048
|
-
"Consider: mem import --from-md " + s.path + " # migrates " + s.count + " preference-shaped lines from " +
|
|
24177
|
+
"Consider: mem import --from-md " + s.path + " # migrates " + s.count + " preference-shaped lines from " + basename20 + " as pending facts for review"
|
|
24049
24178
|
);
|
|
24050
24179
|
}
|
|
24051
24180
|
return lines2.join(String.fromCharCode(10));
|
|
@@ -24116,7 +24245,7 @@ var init_repomap = __esm({
|
|
|
24116
24245
|
});
|
|
24117
24246
|
|
|
24118
24247
|
// src/section_reader.ts
|
|
24119
|
-
import { readFileSync as
|
|
24248
|
+
import { readFileSync as readFileSync27 } from "node:fs";
|
|
24120
24249
|
function parseHeadingSpec(spec, headers) {
|
|
24121
24250
|
const m = /^(.*?)#(\d+)$/.exec(spec);
|
|
24122
24251
|
if (m !== null && m[1] !== void 0 && m[2] !== void 0) {
|
|
@@ -24349,7 +24478,7 @@ function extractSection(text, headingSpec) {
|
|
|
24349
24478
|
function readTextForSections(filePath) {
|
|
24350
24479
|
let text;
|
|
24351
24480
|
try {
|
|
24352
|
-
text =
|
|
24481
|
+
text = readFileSync27(filePath, "utf-8");
|
|
24353
24482
|
} catch {
|
|
24354
24483
|
return null;
|
|
24355
24484
|
}
|
|
@@ -24413,7 +24542,7 @@ var init_section_reader = __esm({
|
|
|
24413
24542
|
});
|
|
24414
24543
|
|
|
24415
24544
|
// src/graph_commands.ts
|
|
24416
|
-
import * as
|
|
24545
|
+
import * as fs34 from "node:fs";
|
|
24417
24546
|
import * as os16 from "node:os";
|
|
24418
24547
|
import * as path42 from "node:path";
|
|
24419
24548
|
import { execFileSync, spawnSync as spawnSync4 } from "node:child_process";
|
|
@@ -24680,7 +24809,7 @@ function runDead(opts) {
|
|
|
24680
24809
|
function runDeps(opts) {
|
|
24681
24810
|
let text;
|
|
24682
24811
|
try {
|
|
24683
|
-
text =
|
|
24812
|
+
text = fs34.readFileSync(opts.file, "utf-8");
|
|
24684
24813
|
} catch {
|
|
24685
24814
|
emitErr(`Could not read: ${opts.file}`);
|
|
24686
24815
|
return 1;
|
|
@@ -24694,22 +24823,22 @@ function runDeps(opts) {
|
|
|
24694
24823
|
if (imp.startsWith("./") || imp.startsWith("../")) {
|
|
24695
24824
|
const base = path42.resolve(dir, imp);
|
|
24696
24825
|
let resolved = imp;
|
|
24697
|
-
if (
|
|
24826
|
+
if (fs34.existsSync(base) && fs34.statSync(base).isFile()) {
|
|
24698
24827
|
resolved = base;
|
|
24699
24828
|
} else {
|
|
24700
24829
|
const baseExt = path42.extname(base);
|
|
24701
24830
|
const bareBase = SOURCE_EXTENSIONS.includes(baseExt) ? base.slice(0, -baseExt.length) : base;
|
|
24702
24831
|
for (const srcExt of SOURCE_EXTENSIONS) {
|
|
24703
24832
|
const candidate = bareBase + srcExt;
|
|
24704
|
-
if (
|
|
24833
|
+
if (fs34.existsSync(candidate)) {
|
|
24705
24834
|
resolved = candidate;
|
|
24706
24835
|
break;
|
|
24707
24836
|
}
|
|
24708
24837
|
}
|
|
24709
|
-
if (resolved === imp &&
|
|
24838
|
+
if (resolved === imp && fs34.existsSync(base) && fs34.statSync(base).isDirectory()) {
|
|
24710
24839
|
for (const srcExt of SOURCE_EXTENSIONS) {
|
|
24711
24840
|
const candidate = path42.join(base, "index" + srcExt);
|
|
24712
|
-
if (
|
|
24841
|
+
if (fs34.existsSync(candidate)) {
|
|
24713
24842
|
resolved = candidate;
|
|
24714
24843
|
break;
|
|
24715
24844
|
}
|
|
@@ -25070,7 +25199,7 @@ function runArch(opts) {
|
|
|
25070
25199
|
for (const file2 of files) {
|
|
25071
25200
|
let text;
|
|
25072
25201
|
try {
|
|
25073
|
-
text =
|
|
25202
|
+
text = fs34.readFileSync(file2, "utf8");
|
|
25074
25203
|
} catch {
|
|
25075
25204
|
continue;
|
|
25076
25205
|
}
|
|
@@ -25202,7 +25331,7 @@ ANSWER:`;
|
|
|
25202
25331
|
if (result.status === 0) {
|
|
25203
25332
|
if (codexOutPath) {
|
|
25204
25333
|
try {
|
|
25205
|
-
answer =
|
|
25334
|
+
answer = fs34.readFileSync(codexOutPath, "utf8").trim();
|
|
25206
25335
|
} catch {
|
|
25207
25336
|
}
|
|
25208
25337
|
} else {
|
|
@@ -25221,7 +25350,7 @@ ANSWER:`;
|
|
|
25221
25350
|
} finally {
|
|
25222
25351
|
if (codexOutPath) {
|
|
25223
25352
|
try {
|
|
25224
|
-
|
|
25353
|
+
fs34.unlinkSync(codexOutPath);
|
|
25225
25354
|
} catch {
|
|
25226
25355
|
}
|
|
25227
25356
|
}
|
|
@@ -28076,23 +28205,23 @@ var init_pr_slice = __esm({
|
|
|
28076
28205
|
});
|
|
28077
28206
|
|
|
28078
28207
|
// src/sqlite_query.ts
|
|
28079
|
-
import * as
|
|
28208
|
+
import * as fs35 from "node:fs";
|
|
28080
28209
|
import Database2 from "better-sqlite3";
|
|
28081
28210
|
function readMagicBytes(filePath) {
|
|
28082
28211
|
let fd;
|
|
28083
28212
|
try {
|
|
28084
|
-
fd =
|
|
28213
|
+
fd = fs35.openSync(filePath, "r");
|
|
28085
28214
|
} catch {
|
|
28086
28215
|
return null;
|
|
28087
28216
|
}
|
|
28088
28217
|
try {
|
|
28089
28218
|
const buf = Buffer.alloc(SQLITE_MAGIC.length);
|
|
28090
|
-
const bytesRead =
|
|
28219
|
+
const bytesRead = fs35.readSync(fd, buf, 0, buf.length, 0);
|
|
28091
28220
|
return bytesRead === buf.length ? buf : null;
|
|
28092
28221
|
} catch {
|
|
28093
28222
|
return null;
|
|
28094
28223
|
} finally {
|
|
28095
|
-
|
|
28224
|
+
fs35.closeSync(fd);
|
|
28096
28225
|
}
|
|
28097
28226
|
}
|
|
28098
28227
|
function isSqliteFile(filePath) {
|
|
@@ -28100,7 +28229,7 @@ function isSqliteFile(filePath) {
|
|
|
28100
28229
|
return magic !== null && magic.equals(SQLITE_MAGIC);
|
|
28101
28230
|
}
|
|
28102
28231
|
function openReadonlySqlite(filePath) {
|
|
28103
|
-
if (!
|
|
28232
|
+
if (!fs35.existsSync(filePath)) {
|
|
28104
28233
|
throw new Error(`file not found: ${filePath}`);
|
|
28105
28234
|
}
|
|
28106
28235
|
if (!isSqliteFile(filePath)) {
|
|
@@ -28821,12 +28950,12 @@ var init_conflict_query = __esm({
|
|
|
28821
28950
|
});
|
|
28822
28951
|
|
|
28823
28952
|
// src/screenshot.ts
|
|
28824
|
-
import
|
|
28953
|
+
import fs36 from "node:fs";
|
|
28825
28954
|
import path44 from "node:path";
|
|
28826
28955
|
function findPlaywrightChromium(msPlaywrightDir) {
|
|
28827
28956
|
let entries;
|
|
28828
28957
|
try {
|
|
28829
|
-
entries =
|
|
28958
|
+
entries = fs36.readdirSync(msPlaywrightDir);
|
|
28830
28959
|
} catch {
|
|
28831
28960
|
return [];
|
|
28832
28961
|
}
|
|
@@ -28865,13 +28994,13 @@ function platformCandidatePaths() {
|
|
|
28865
28994
|
return candidates;
|
|
28866
28995
|
}
|
|
28867
28996
|
function resolveBrowserExecutablePath(explicit) {
|
|
28868
|
-
if (explicit &&
|
|
28997
|
+
if (explicit && fs36.existsSync(explicit)) return explicit;
|
|
28869
28998
|
const cfgPath = loadConfig().screenshot.chrome_path;
|
|
28870
|
-
if (cfgPath &&
|
|
28999
|
+
if (cfgPath && fs36.existsSync(cfgPath)) return cfgPath;
|
|
28871
29000
|
const envPath = process.env["TOKEN_GOAT_CHROME_PATH"];
|
|
28872
|
-
if (envPath &&
|
|
29001
|
+
if (envPath && fs36.existsSync(envPath)) return envPath;
|
|
28873
29002
|
for (const candidate of platformCandidatePaths()) {
|
|
28874
|
-
if (
|
|
29003
|
+
if (fs36.existsSync(candidate)) return candidate;
|
|
28875
29004
|
}
|
|
28876
29005
|
return null;
|
|
28877
29006
|
}
|
|
@@ -28919,6 +29048,7 @@ var init_screenshot = __esm({
|
|
|
28919
29048
|
});
|
|
28920
29049
|
|
|
28921
29050
|
// src/notes.ts
|
|
29051
|
+
import * as fs37 from "node:fs";
|
|
28922
29052
|
function toNoteRow(row) {
|
|
28923
29053
|
return {
|
|
28924
29054
|
id: row.id,
|
|
@@ -28935,7 +29065,17 @@ function pickEarliest(matches2) {
|
|
|
28935
29065
|
}
|
|
28936
29066
|
function resolveSymbolMatch(filePath, symbolName, dbPath = globalDbPath()) {
|
|
28937
29067
|
const matches2 = querySymbols({ filePath, name: symbolName }, dbPath);
|
|
28938
|
-
|
|
29068
|
+
if (matches2.length === 0) return null;
|
|
29069
|
+
const match2 = pickEarliest(matches2);
|
|
29070
|
+
if (match2.body !== "") return match2;
|
|
29071
|
+
return { ...match2, body: bodyFromSource(match2) };
|
|
29072
|
+
}
|
|
29073
|
+
function bodyFromSource(entry) {
|
|
29074
|
+
try {
|
|
29075
|
+
return fs37.readFileSync(entry.filePath, "utf8").split(/\r?\n/).slice(Math.max(0, entry.lineStart - 1), entry.lineEnd).join("\n");
|
|
29076
|
+
} catch {
|
|
29077
|
+
return "";
|
|
29078
|
+
}
|
|
28939
29079
|
}
|
|
28940
29080
|
function symbolNamesInFile(filePath, dbPath = globalDbPath()) {
|
|
28941
29081
|
const symbols = querySymbols({ filePath, limit: 1e5 }, dbPath);
|
|
@@ -29181,11 +29321,11 @@ var init_ts_refs = __esm({
|
|
|
29181
29321
|
});
|
|
29182
29322
|
|
|
29183
29323
|
// src/read_commands.ts
|
|
29184
|
-
import * as
|
|
29324
|
+
import * as fs38 from "node:fs";
|
|
29185
29325
|
import * as path46 from "node:path";
|
|
29186
29326
|
function fileExists(p) {
|
|
29187
29327
|
try {
|
|
29188
|
-
|
|
29328
|
+
fs38.statSync(p);
|
|
29189
29329
|
return true;
|
|
29190
29330
|
} catch {
|
|
29191
29331
|
return false;
|
|
@@ -29193,14 +29333,14 @@ function fileExists(p) {
|
|
|
29193
29333
|
}
|
|
29194
29334
|
function readFileText(p) {
|
|
29195
29335
|
try {
|
|
29196
|
-
return
|
|
29336
|
+
return fs38.readFileSync(p, "utf-8");
|
|
29197
29337
|
} catch {
|
|
29198
29338
|
return null;
|
|
29199
29339
|
}
|
|
29200
29340
|
}
|
|
29201
29341
|
function readFileBytes(p) {
|
|
29202
29342
|
try {
|
|
29203
|
-
return
|
|
29343
|
+
return fs38.readFileSync(p);
|
|
29204
29344
|
} catch {
|
|
29205
29345
|
return null;
|
|
29206
29346
|
}
|
|
@@ -29265,7 +29405,7 @@ function sumFileSizes(filePaths) {
|
|
|
29265
29405
|
let total = 0;
|
|
29266
29406
|
for (const fp of new Set(filePaths)) {
|
|
29267
29407
|
try {
|
|
29268
|
-
total +=
|
|
29408
|
+
total += fs38.statSync(fp).size;
|
|
29269
29409
|
} catch {
|
|
29270
29410
|
}
|
|
29271
29411
|
}
|
|
@@ -29522,7 +29662,7 @@ function runRead(opts) {
|
|
|
29522
29662
|
const match2 = resolution.entry;
|
|
29523
29663
|
const fullSourceBytes = sumFileSizes([match2.filePath]);
|
|
29524
29664
|
if (opts.json === true) {
|
|
29525
|
-
const text2 = JSON.stringify(match2, null, 2);
|
|
29665
|
+
const text2 = JSON.stringify({ ...match2, body: resolveBody(match2) }, null, 2);
|
|
29526
29666
|
recordReadStat("read_replacement", fullSourceBytes, text2, opts.spec);
|
|
29527
29667
|
return { text: text2, code: 0 };
|
|
29528
29668
|
}
|
|
@@ -29547,7 +29687,7 @@ function runSection(opts) {
|
|
|
29547
29687
|
const heading = opts.spec.slice(colonIdx + 2);
|
|
29548
29688
|
const result = readSection(filePath, heading);
|
|
29549
29689
|
if (result === null) {
|
|
29550
|
-
if (!
|
|
29690
|
+
if (!fs38.existsSync(filePath)) {
|
|
29551
29691
|
return { text: `File not found: '${filePath}'`, code: 1 };
|
|
29552
29692
|
}
|
|
29553
29693
|
const messages = [`Section '${heading}' not found in '${filePath}'`];
|
|
@@ -30303,7 +30443,7 @@ function runConflicts(opts) {
|
|
|
30303
30443
|
const abs = path46.resolve(opts.path);
|
|
30304
30444
|
let stat2;
|
|
30305
30445
|
try {
|
|
30306
|
-
stat2 =
|
|
30446
|
+
stat2 = fs38.statSync(abs);
|
|
30307
30447
|
} catch {
|
|
30308
30448
|
emitErr2(`Could not read: ${opts.path}`);
|
|
30309
30449
|
return 1;
|
|
@@ -30338,7 +30478,7 @@ async function runPdfExtractText(file2, pagesSpec, layout = false) {
|
|
|
30338
30478
|
if (!fileExists(file2)) {
|
|
30339
30479
|
throw new Error(`Could not read: ${file2}`);
|
|
30340
30480
|
}
|
|
30341
|
-
const data =
|
|
30481
|
+
const data = fs38.readFileSync(file2);
|
|
30342
30482
|
const result = await extractPdfText(new Uint8Array(data), pagesSpec, layout);
|
|
30343
30483
|
return result.text;
|
|
30344
30484
|
}
|
|
@@ -30346,14 +30486,14 @@ async function runPdfOutline(file2) {
|
|
|
30346
30486
|
if (!fileExists(file2)) {
|
|
30347
30487
|
throw new Error(`Could not read: ${file2}`);
|
|
30348
30488
|
}
|
|
30349
|
-
const data =
|
|
30489
|
+
const data = fs38.readFileSync(file2);
|
|
30350
30490
|
return extractPdfOutline(new Uint8Array(data));
|
|
30351
30491
|
}
|
|
30352
30492
|
async function runPdfMeta(file2) {
|
|
30353
30493
|
if (!fileExists(file2)) {
|
|
30354
30494
|
throw new Error(`Could not read: ${file2}`);
|
|
30355
30495
|
}
|
|
30356
|
-
const data =
|
|
30496
|
+
const data = fs38.readFileSync(file2);
|
|
30357
30497
|
return extractPdfMeta(new Uint8Array(data));
|
|
30358
30498
|
}
|
|
30359
30499
|
async function runScreenshot(url2, destPath, opts) {
|
|
@@ -30771,7 +30911,7 @@ function runGrep(opts) {
|
|
|
30771
30911
|
const hits = [];
|
|
30772
30912
|
function searchFile(filePath) {
|
|
30773
30913
|
try {
|
|
30774
|
-
const text =
|
|
30914
|
+
const text = fs38.readFileSync(filePath, "utf-8");
|
|
30775
30915
|
const lines2 = text.split(/\r?\n/);
|
|
30776
30916
|
lines2.forEach((lineText, idx) => {
|
|
30777
30917
|
if (regex.test(lineText)) {
|
|
@@ -30792,10 +30932,10 @@ function runGrep(opts) {
|
|
|
30792
30932
|
}
|
|
30793
30933
|
function searchDir(dir) {
|
|
30794
30934
|
try {
|
|
30795
|
-
for (const entry of
|
|
30935
|
+
for (const entry of fs38.readdirSync(dir)) {
|
|
30796
30936
|
if (entry.startsWith(".")) continue;
|
|
30797
30937
|
const full = path46.join(dir, entry);
|
|
30798
|
-
const stat2 =
|
|
30938
|
+
const stat2 = fs38.statSync(full);
|
|
30799
30939
|
if (stat2.isDirectory()) {
|
|
30800
30940
|
if (SKIP_DIRS.has(entry)) continue;
|
|
30801
30941
|
if (opts.recursive !== false) searchDir(full);
|
|
@@ -30811,7 +30951,7 @@ function runGrep(opts) {
|
|
|
30811
30951
|
emitErr2(`Path not found: ${searchPath}`);
|
|
30812
30952
|
return 1;
|
|
30813
30953
|
}
|
|
30814
|
-
const stat2 =
|
|
30954
|
+
const stat2 = fs38.statSync(searchPath);
|
|
30815
30955
|
if (stat2.isDirectory()) {
|
|
30816
30956
|
searchDir(searchPath);
|
|
30817
30957
|
} else {
|
|
@@ -31408,15 +31548,20 @@ function symbolHeader(s) {
|
|
|
31408
31548
|
}
|
|
31409
31549
|
async function runSemantic(query, opts) {
|
|
31410
31550
|
if (opts.limit !== void 0 && opts.limit <= 0) {
|
|
31411
|
-
|
|
31551
|
+
const message = `--limit must be a positive number, got: ${opts.limit}`;
|
|
31552
|
+
if (opts.json === true) {
|
|
31553
|
+
return { text: JSON.stringify({ error: message }, null, 2), code: 1 };
|
|
31554
|
+
}
|
|
31555
|
+
return { text: message, code: 1 };
|
|
31412
31556
|
}
|
|
31413
31557
|
const n = opts.limit !== void 0 && Number.isFinite(opts.limit) ? opts.limit : 20;
|
|
31414
31558
|
if (opts.projectRoot !== void 0) {
|
|
31415
|
-
if (!path46.isAbsolute(opts.projectRoot) || !
|
|
31416
|
-
|
|
31417
|
-
|
|
31418
|
-
code: 1
|
|
31419
|
-
}
|
|
31559
|
+
if (!path46.isAbsolute(opts.projectRoot) || !fs38.existsSync(opts.projectRoot) || !fs38.statSync(opts.projectRoot).isDirectory()) {
|
|
31560
|
+
const message = `token-goat: projectRoot must be an absolute, existing directory, got '${opts.projectRoot}'`;
|
|
31561
|
+
if (opts.json === true) {
|
|
31562
|
+
return { text: JSON.stringify({ error: message }, null, 2), code: 1 };
|
|
31563
|
+
}
|
|
31564
|
+
return { text: message, code: 1 };
|
|
31420
31565
|
}
|
|
31421
31566
|
}
|
|
31422
31567
|
const rootDir = opts.projectRoot ?? resolveProjectRoot({ project: process.cwd() });
|
|
@@ -31431,6 +31576,21 @@ async function runSemantic(query, opts) {
|
|
|
31431
31576
|
);
|
|
31432
31577
|
const hits = mergeNearbyHits(rawHits).slice(0, n);
|
|
31433
31578
|
if (hits.length > 0) {
|
|
31579
|
+
if (opts.json === true) {
|
|
31580
|
+
const items = hits.map((h) => ({
|
|
31581
|
+
filePath: h.filePath,
|
|
31582
|
+
name: null,
|
|
31583
|
+
kind: null,
|
|
31584
|
+
startLine: h.startLine,
|
|
31585
|
+
endLine: h.endLine,
|
|
31586
|
+
distance: h.distance,
|
|
31587
|
+
preview: previewLines(h.text, 3)
|
|
31588
|
+
}));
|
|
31589
|
+
const capped = guardJsonRows(items);
|
|
31590
|
+
const text3 = JSON.stringify({ source: "embeddings", ...capped }, null, 2);
|
|
31591
|
+
recordReadStat("semantic_search", sumFileSizes(hits.map((h) => h.filePath)), text3, query);
|
|
31592
|
+
return { text: text3, code: 0 };
|
|
31593
|
+
}
|
|
31434
31594
|
const blocks2 = hits.map(
|
|
31435
31595
|
(h) => `# ${h.filePath}:${h.startLine}-${h.endLine} (distance ${h.distance.toFixed(3)})
|
|
31436
31596
|
${previewLines(h.text, 3)}`
|
|
@@ -31441,8 +31601,27 @@ ${previewLines(h.text, 3)}`
|
|
|
31441
31601
|
}
|
|
31442
31602
|
const results = searchSymbolsFts(query, n, void 0, rootDir);
|
|
31443
31603
|
if (results.length === 0) {
|
|
31604
|
+
if (opts.json === true) {
|
|
31605
|
+
const text2 = JSON.stringify({ source: "fts", items: [], truncated: false, totalCount: 0 }, null, 2);
|
|
31606
|
+
return { text: text2, code: 1 };
|
|
31607
|
+
}
|
|
31444
31608
|
return { text: `token-goat: no matches for '${query}'`, code: 1 };
|
|
31445
31609
|
}
|
|
31610
|
+
if (opts.json === true) {
|
|
31611
|
+
const items = results.map((s) => ({
|
|
31612
|
+
filePath: s.filePath,
|
|
31613
|
+
name: s.name,
|
|
31614
|
+
kind: s.kind,
|
|
31615
|
+
startLine: s.lineStart,
|
|
31616
|
+
endLine: s.lineEnd,
|
|
31617
|
+
distance: null,
|
|
31618
|
+
preview: previewLines(s.body, 3)
|
|
31619
|
+
}));
|
|
31620
|
+
const capped = guardJsonRows(items);
|
|
31621
|
+
const text2 = JSON.stringify({ source: "fts", ...capped }, null, 2);
|
|
31622
|
+
recordReadStat("semantic_search", sumFileSizes(results.map((s) => s.filePath)), text2, query);
|
|
31623
|
+
return { text: text2, code: 0 };
|
|
31624
|
+
}
|
|
31446
31625
|
const blocks = results.map((s) => `${symbolHeader(s)}
|
|
31447
31626
|
${previewLines(s.body, 3)}`);
|
|
31448
31627
|
const text = guardText(blocks.join("\n\n"), "semantic");
|
|
@@ -31798,10 +31977,10 @@ function mergeDefs(...defs) {
|
|
|
31798
31977
|
function cloneDef(schema) {
|
|
31799
31978
|
return mergeDefs(schema._zod.def);
|
|
31800
31979
|
}
|
|
31801
|
-
function getElementAtPath(obj,
|
|
31802
|
-
if (!
|
|
31980
|
+
function getElementAtPath(obj, path64) {
|
|
31981
|
+
if (!path64)
|
|
31803
31982
|
return obj;
|
|
31804
|
-
return
|
|
31983
|
+
return path64.reduce((acc, key) => acc?.[key], obj);
|
|
31805
31984
|
}
|
|
31806
31985
|
function promiseAllObject(promisesObj) {
|
|
31807
31986
|
const keys = Object.keys(promisesObj);
|
|
@@ -32129,11 +32308,11 @@ function explicitlyAborted(x, startIndex = 0) {
|
|
|
32129
32308
|
}
|
|
32130
32309
|
return false;
|
|
32131
32310
|
}
|
|
32132
|
-
function prefixIssues(
|
|
32311
|
+
function prefixIssues(path64, issues) {
|
|
32133
32312
|
return issues.map((iss) => {
|
|
32134
32313
|
var _a6;
|
|
32135
32314
|
(_a6 = iss).path ?? (_a6.path = []);
|
|
32136
|
-
iss.path.unshift(
|
|
32315
|
+
iss.path.unshift(path64);
|
|
32137
32316
|
return iss;
|
|
32138
32317
|
});
|
|
32139
32318
|
}
|
|
@@ -32351,16 +32530,16 @@ function flattenError(error52, mapper = (issue2) => issue2.message) {
|
|
|
32351
32530
|
}
|
|
32352
32531
|
function formatError2(error52, mapper = (issue2) => issue2.message) {
|
|
32353
32532
|
const fieldErrors = { _errors: [] };
|
|
32354
|
-
const processError = (error53,
|
|
32533
|
+
const processError = (error53, path64 = []) => {
|
|
32355
32534
|
for (const issue2 of error53.issues) {
|
|
32356
32535
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
32357
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
32536
|
+
issue2.errors.map((issues) => processError({ issues }, [...path64, ...issue2.path]));
|
|
32358
32537
|
} else if (issue2.code === "invalid_key") {
|
|
32359
|
-
processError({ issues: issue2.issues }, [...
|
|
32538
|
+
processError({ issues: issue2.issues }, [...path64, ...issue2.path]);
|
|
32360
32539
|
} else if (issue2.code === "invalid_element") {
|
|
32361
|
-
processError({ issues: issue2.issues }, [...
|
|
32540
|
+
processError({ issues: issue2.issues }, [...path64, ...issue2.path]);
|
|
32362
32541
|
} else {
|
|
32363
|
-
const fullpath = [...
|
|
32542
|
+
const fullpath = [...path64, ...issue2.path];
|
|
32364
32543
|
if (fullpath.length === 0) {
|
|
32365
32544
|
fieldErrors._errors.push(mapper(issue2));
|
|
32366
32545
|
} else {
|
|
@@ -32387,17 +32566,17 @@ function formatError2(error52, mapper = (issue2) => issue2.message) {
|
|
|
32387
32566
|
}
|
|
32388
32567
|
function treeifyError(error52, mapper = (issue2) => issue2.message) {
|
|
32389
32568
|
const result = { errors: [] };
|
|
32390
|
-
const processError = (error53,
|
|
32569
|
+
const processError = (error53, path64 = []) => {
|
|
32391
32570
|
var _a6, _b;
|
|
32392
32571
|
for (const issue2 of error53.issues) {
|
|
32393
32572
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
32394
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
32573
|
+
issue2.errors.map((issues) => processError({ issues }, [...path64, ...issue2.path]));
|
|
32395
32574
|
} else if (issue2.code === "invalid_key") {
|
|
32396
|
-
processError({ issues: issue2.issues }, [...
|
|
32575
|
+
processError({ issues: issue2.issues }, [...path64, ...issue2.path]);
|
|
32397
32576
|
} else if (issue2.code === "invalid_element") {
|
|
32398
|
-
processError({ issues: issue2.issues }, [...
|
|
32577
|
+
processError({ issues: issue2.issues }, [...path64, ...issue2.path]);
|
|
32399
32578
|
} else {
|
|
32400
|
-
const fullpath = [...
|
|
32579
|
+
const fullpath = [...path64, ...issue2.path];
|
|
32401
32580
|
if (fullpath.length === 0) {
|
|
32402
32581
|
result.errors.push(mapper(issue2));
|
|
32403
32582
|
continue;
|
|
@@ -32429,8 +32608,8 @@ function treeifyError(error52, mapper = (issue2) => issue2.message) {
|
|
|
32429
32608
|
}
|
|
32430
32609
|
function toDotPath(_path) {
|
|
32431
32610
|
const segs = [];
|
|
32432
|
-
const
|
|
32433
|
-
for (const seg of
|
|
32611
|
+
const path64 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
32612
|
+
for (const seg of path64) {
|
|
32434
32613
|
if (typeof seg === "number")
|
|
32435
32614
|
segs.push(`[${seg}]`);
|
|
32436
32615
|
else if (typeof seg === "symbol")
|
|
@@ -45933,13 +46112,13 @@ function resolveRef(ref2, ctx) {
|
|
|
45933
46112
|
if (!ref2.startsWith("#")) {
|
|
45934
46113
|
throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
|
|
45935
46114
|
}
|
|
45936
|
-
const
|
|
45937
|
-
if (
|
|
46115
|
+
const path64 = ref2.slice(1).split("/").filter(Boolean);
|
|
46116
|
+
if (path64.length === 0) {
|
|
45938
46117
|
return ctx.rootSchema;
|
|
45939
46118
|
}
|
|
45940
46119
|
const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
|
|
45941
|
-
if (
|
|
45942
|
-
const key =
|
|
46120
|
+
if (path64[0] === defsKey) {
|
|
46121
|
+
const key = path64[1];
|
|
45943
46122
|
if (!key || !ctx.defs[key]) {
|
|
45944
46123
|
throw new Error(`Reference not found: ${ref2}`);
|
|
45945
46124
|
}
|
|
@@ -47210,7 +47389,8 @@ var HOOK_EVENTS = [
|
|
|
47210
47389
|
"stop",
|
|
47211
47390
|
"pre_compact",
|
|
47212
47391
|
"user_prompt_submit",
|
|
47213
|
-
"subagent_stop"
|
|
47392
|
+
"subagent_stop",
|
|
47393
|
+
"session_start"
|
|
47214
47394
|
];
|
|
47215
47395
|
|
|
47216
47396
|
// src/relay.ts
|
|
@@ -47234,7 +47414,7 @@ function grepIntInput(toolInput, key) {
|
|
|
47234
47414
|
function grepSignature(toolInput) {
|
|
47235
47415
|
const pattern = toolInput["pattern"];
|
|
47236
47416
|
if (typeof pattern !== "string" || pattern === "") return null;
|
|
47237
|
-
const
|
|
47417
|
+
const path64 = typeof toolInput["path"] === "string" ? toolInput["path"] : "";
|
|
47238
47418
|
const outputMode = typeof toolInput["output_mode"] === "string" ? toolInput["output_mode"] : "files_with_matches";
|
|
47239
47419
|
const glob = typeof toolInput["glob"] === "string" ? toolInput["glob"] : "";
|
|
47240
47420
|
const type = typeof toolInput["type"] === "string" ? toolInput["type"] : "";
|
|
@@ -47249,7 +47429,7 @@ function grepSignature(toolInput) {
|
|
|
47249
47429
|
const offset = grepIntInput(toolInput, "offset");
|
|
47250
47430
|
return JSON.stringify([
|
|
47251
47431
|
pattern,
|
|
47252
|
-
|
|
47432
|
+
path64,
|
|
47253
47433
|
outputMode,
|
|
47254
47434
|
glob,
|
|
47255
47435
|
type,
|
|
@@ -47283,8 +47463,8 @@ init_session();
|
|
|
47283
47463
|
function globSignature(toolInput) {
|
|
47284
47464
|
const pattern = toolInput["pattern"];
|
|
47285
47465
|
if (typeof pattern !== "string" || pattern === "") return null;
|
|
47286
|
-
const
|
|
47287
|
-
return JSON.stringify([pattern,
|
|
47466
|
+
const path64 = typeof toolInput["path"] === "string" ? toolInput["path"] : "";
|
|
47467
|
+
return JSON.stringify([pattern, path64]);
|
|
47288
47468
|
}
|
|
47289
47469
|
var { post: postGlobHandler, pre: preGlobDedupHandler } = makeDedupHintHandlers({
|
|
47290
47470
|
toolName: "Glob",
|
|
@@ -47371,7 +47551,7 @@ init_hook_registry();
|
|
|
47371
47551
|
init_hooks_common();
|
|
47372
47552
|
init_stats();
|
|
47373
47553
|
init_config();
|
|
47374
|
-
import { readFileSync as
|
|
47554
|
+
import { readFileSync as readFileSync19, statSync as statSync14 } from "node:fs";
|
|
47375
47555
|
var MAX_LINES_FOR_DIFF = 4e3;
|
|
47376
47556
|
var MAX_OLD_FILE_BYTES_FOR_DIFF = 4 * 1024 * 1024;
|
|
47377
47557
|
function splitLines(text) {
|
|
@@ -47409,7 +47589,7 @@ function preWriteRewriteHandler(event) {
|
|
|
47409
47589
|
if (stat2.size > MAX_OLD_FILE_BYTES_FOR_DIFF) return passOutput();
|
|
47410
47590
|
let oldContent;
|
|
47411
47591
|
try {
|
|
47412
|
-
oldContent =
|
|
47592
|
+
oldContent = readFileSync19(filePath, "utf-8");
|
|
47413
47593
|
} catch {
|
|
47414
47594
|
return passOutput();
|
|
47415
47595
|
}
|
|
@@ -47453,8 +47633,8 @@ init_reset();
|
|
|
47453
47633
|
init_util2();
|
|
47454
47634
|
init_disk_cache();
|
|
47455
47635
|
init_lang_patterns();
|
|
47456
|
-
import { readdirSync as
|
|
47457
|
-
import { resolve as
|
|
47636
|
+
import { readdirSync as readdirSync11, readFileSync as readFileSync20, statSync as statSync15 } from "fs";
|
|
47637
|
+
import { resolve as resolve8 } from "path";
|
|
47458
47638
|
|
|
47459
47639
|
// src/recall_index.ts
|
|
47460
47640
|
init_define_import_meta_env();
|
|
@@ -47652,11 +47832,11 @@ function gitStateFingerprintSync(cwd) {
|
|
|
47652
47832
|
}
|
|
47653
47833
|
}
|
|
47654
47834
|
var DIR_FINGERPRINT_LISTING_CAP_ENTRIES = 1e4;
|
|
47655
|
-
function dirStateFingerprintSync(
|
|
47835
|
+
function dirStateFingerprintSync(path64) {
|
|
47656
47836
|
try {
|
|
47657
|
-
const stat2 = statSync15(
|
|
47837
|
+
const stat2 = statSync15(path64);
|
|
47658
47838
|
if (!stat2.isDirectory()) return null;
|
|
47659
|
-
const entries =
|
|
47839
|
+
const entries = readdirSync11(path64);
|
|
47660
47840
|
if (entries.length <= DIR_FINGERPRINT_LISTING_CAP_ENTRIES) {
|
|
47661
47841
|
return shortFingerprint(entries.slice().sort().join("\0"));
|
|
47662
47842
|
}
|
|
@@ -47666,12 +47846,12 @@ function dirStateFingerprintSync(path63) {
|
|
|
47666
47846
|
}
|
|
47667
47847
|
}
|
|
47668
47848
|
var FILE_FINGERPRINT_CONTENT_CAP_BYTES = 2 * 1024 * 1024;
|
|
47669
|
-
function fileStateFingerprintSync(
|
|
47849
|
+
function fileStateFingerprintSync(path64) {
|
|
47670
47850
|
try {
|
|
47671
|
-
const stat2 = statSync15(
|
|
47851
|
+
const stat2 = statSync15(path64);
|
|
47672
47852
|
if (!stat2.isFile()) return null;
|
|
47673
47853
|
if (stat2.size <= FILE_FINGERPRINT_CONTENT_CAP_BYTES) {
|
|
47674
|
-
return shortFingerprint(
|
|
47854
|
+
return shortFingerprint(readFileSync20(path64));
|
|
47675
47855
|
}
|
|
47676
47856
|
return shortFingerprint(`${stat2.mtimeMs}\0${stat2.size}`);
|
|
47677
47857
|
} catch {
|
|
@@ -47687,7 +47867,7 @@ function depLockfileFingerprintSync(cmd, cwd) {
|
|
|
47687
47867
|
if (!candidates) return null;
|
|
47688
47868
|
for (const lockfile of candidates) {
|
|
47689
47869
|
try {
|
|
47690
|
-
const content =
|
|
47870
|
+
const content = readFileSync20(resolve8(cwd, lockfile));
|
|
47691
47871
|
return shortFingerprint(content);
|
|
47692
47872
|
} catch {
|
|
47693
47873
|
continue;
|
|
@@ -47840,7 +48020,7 @@ function extractFirstPathArg(cmd, cwd, fallback) {
|
|
|
47840
48020
|
const token2 = tokens[i];
|
|
47841
48021
|
if (!token2.startsWith("-")) {
|
|
47842
48022
|
if (!token2.startsWith("/")) {
|
|
47843
|
-
return
|
|
48023
|
+
return resolve8(cwd, token2);
|
|
47844
48024
|
}
|
|
47845
48025
|
return token2;
|
|
47846
48026
|
}
|
|
@@ -47854,10 +48034,20 @@ function summarizeOutputDelta(oldOutput, newOutput) {
|
|
|
47854
48034
|
const newLines = newOutput.split("\n");
|
|
47855
48035
|
const oldIssueLines = oldLines.filter((l) => ISSUE_LINE_PATTERN.test(l));
|
|
47856
48036
|
if (oldIssueLines.length > 0) {
|
|
47857
|
-
const
|
|
48037
|
+
const newIssueLines = newLines.filter((l) => ISSUE_LINE_PATTERN.test(l));
|
|
47858
48038
|
const priorTotal = oldIssueLines.length;
|
|
47859
|
-
const
|
|
47860
|
-
const
|
|
48039
|
+
const availableCounts = /* @__PURE__ */ new Map();
|
|
48040
|
+
for (const l of newIssueLines) availableCounts.set(l, (availableCounts.get(l) ?? 0) + 1);
|
|
48041
|
+
let resolved = 0;
|
|
48042
|
+
for (const l of oldIssueLines) {
|
|
48043
|
+
const avail = availableCounts.get(l) ?? 0;
|
|
48044
|
+
if (avail > 0) {
|
|
48045
|
+
availableCounts.set(l, avail - 1);
|
|
48046
|
+
} else {
|
|
48047
|
+
resolved++;
|
|
48048
|
+
}
|
|
48049
|
+
}
|
|
48050
|
+
const remaining = newIssueLines.length;
|
|
47861
48051
|
return `[token-goat: delta] ${resolved} of ${priorTotal} prior issues resolved; remaining: ${remaining}`;
|
|
47862
48052
|
}
|
|
47863
48053
|
return `[token-goat: delta] output changed: ${oldLines.length} -> ${newLines.length} lines`;
|
|
@@ -48134,14 +48324,15 @@ var {
|
|
|
48134
48324
|
init_baseline();
|
|
48135
48325
|
init_stats();
|
|
48136
48326
|
init_repomap();
|
|
48137
|
-
import * as
|
|
48138
|
-
import * as
|
|
48327
|
+
import * as fs55 from "fs";
|
|
48328
|
+
import * as path63 from "path";
|
|
48139
48329
|
import { homedir as homedir17 } from "os";
|
|
48140
48330
|
|
|
48141
48331
|
// src/walk_index.ts
|
|
48142
48332
|
init_define_import_meta_env();
|
|
48143
48333
|
init_baseline();
|
|
48144
48334
|
init_util2();
|
|
48335
|
+
import * as fs29 from "node:fs";
|
|
48145
48336
|
import * as os9 from "node:os";
|
|
48146
48337
|
import * as path35 from "node:path";
|
|
48147
48338
|
function isWalkExcluded(file2) {
|
|
@@ -48151,7 +48342,11 @@ function isWalkExcluded(file2) {
|
|
|
48151
48342
|
return false;
|
|
48152
48343
|
}
|
|
48153
48344
|
function assertWalkableRoot(root) {
|
|
48154
|
-
|
|
48345
|
+
let resolved = path35.resolve(root);
|
|
48346
|
+
try {
|
|
48347
|
+
resolved = fs29.realpathSync.native(resolved);
|
|
48348
|
+
} catch {
|
|
48349
|
+
}
|
|
48155
48350
|
const norm = foldPath(normalizePath(resolved));
|
|
48156
48351
|
const fsRoot = foldPath(normalizePath(path35.parse(resolved).root));
|
|
48157
48352
|
if (norm === fsRoot) {
|
|
@@ -48169,13 +48364,16 @@ function assertWalkableRoot(root) {
|
|
|
48169
48364
|
}
|
|
48170
48365
|
}
|
|
48171
48366
|
}
|
|
48172
|
-
|
|
48367
|
+
var MAX_FILES_SCANNED_FORCED = 5e5;
|
|
48368
|
+
function collectWalkIndexFiles(root, opts = {}) {
|
|
48173
48369
|
const resolved = path35.resolve(root);
|
|
48174
48370
|
assertWalkableRoot(resolved);
|
|
48175
|
-
const
|
|
48176
|
-
|
|
48371
|
+
const force = opts.force === true;
|
|
48372
|
+
const ceiling = force ? MAX_FILES_SCANNED_FORCED : MAX_FILES_SCANNED;
|
|
48373
|
+
const { files } = walkProject(resolved, { includeEmbeddableDocuments: true, maxFiles: ceiling });
|
|
48374
|
+
if (files.length >= ceiling) {
|
|
48177
48375
|
throw new Error(
|
|
48178
|
-
`'${resolved}' has too many source files (
|
|
48376
|
+
`'${resolved}' has too many source files (walk stopped at ${ceiling}; the real total is at least that). ` + (force ? "Even --force-walk will not walk a tree this large \u2014 point at a narrower path." : `Index a git repo, point at a narrower path, or pass --force-walk to raise the cap to ${MAX_FILES_SCANNED_FORCED}.`)
|
|
48179
48377
|
);
|
|
48180
48378
|
}
|
|
48181
48379
|
return files.filter((f) => !isWalkExcluded(f));
|
|
@@ -48199,7 +48397,7 @@ init_codex_install();
|
|
|
48199
48397
|
|
|
48200
48398
|
// src/bridges/gemini_install.ts
|
|
48201
48399
|
init_define_import_meta_env();
|
|
48202
|
-
import * as
|
|
48400
|
+
import * as fs30 from "node:fs";
|
|
48203
48401
|
import * as os10 from "node:os";
|
|
48204
48402
|
import * as path36 from "node:path";
|
|
48205
48403
|
init_install();
|
|
@@ -48222,7 +48420,7 @@ function geminiSettingsPath() {
|
|
|
48222
48420
|
function readGeminiSettings(p, opts = {}) {
|
|
48223
48421
|
let raw;
|
|
48224
48422
|
try {
|
|
48225
|
-
raw =
|
|
48423
|
+
raw = fs30.readFileSync(p, "utf8");
|
|
48226
48424
|
} catch {
|
|
48227
48425
|
return {};
|
|
48228
48426
|
}
|
|
@@ -48336,7 +48534,7 @@ function uninstallGemini() {
|
|
|
48336
48534
|
init_define_import_meta_env();
|
|
48337
48535
|
init_install();
|
|
48338
48536
|
init_util2();
|
|
48339
|
-
import * as
|
|
48537
|
+
import * as fs31 from "node:fs";
|
|
48340
48538
|
import * as os11 from "node:os";
|
|
48341
48539
|
import * as path37 from "node:path";
|
|
48342
48540
|
var QWEN_HOOK_EVENTS = ["PreToolUse", "PostToolUse", "PreCompact", "UserPromptSubmit", "SubagentStop"];
|
|
@@ -48355,7 +48553,7 @@ function qwenSettingsPath() {
|
|
|
48355
48553
|
function readQwenSettings(p, opts = {}) {
|
|
48356
48554
|
let raw;
|
|
48357
48555
|
try {
|
|
48358
|
-
raw =
|
|
48556
|
+
raw = fs31.readFileSync(p, "utf8");
|
|
48359
48557
|
} catch {
|
|
48360
48558
|
return {};
|
|
48361
48559
|
}
|
|
@@ -49103,7 +49301,7 @@ function uninstallOpencode() {
|
|
|
49103
49301
|
// src/bridges/openclaw_install.ts
|
|
49104
49302
|
init_define_import_meta_env();
|
|
49105
49303
|
init_util2();
|
|
49106
|
-
import * as
|
|
49304
|
+
import * as fs32 from "node:fs";
|
|
49107
49305
|
import * as os14 from "node:os";
|
|
49108
49306
|
import * as path40 from "node:path";
|
|
49109
49307
|
|
|
@@ -49255,7 +49453,7 @@ function openclawEntrySidecarPath() {
|
|
|
49255
49453
|
function readOpenclawConfig(p, opts = {}) {
|
|
49256
49454
|
let raw;
|
|
49257
49455
|
try {
|
|
49258
|
-
raw =
|
|
49456
|
+
raw = fs32.readFileSync(p, "utf8");
|
|
49259
49457
|
} catch {
|
|
49260
49458
|
return {};
|
|
49261
49459
|
}
|
|
@@ -49295,7 +49493,7 @@ function installOpenclaw() {
|
|
|
49295
49493
|
const pluginPath = openclawPluginPath();
|
|
49296
49494
|
let existingPlugin;
|
|
49297
49495
|
try {
|
|
49298
|
-
existingPlugin =
|
|
49496
|
+
existingPlugin = fs32.readFileSync(pluginPath, "utf8");
|
|
49299
49497
|
} catch {
|
|
49300
49498
|
existingPlugin = void 0;
|
|
49301
49499
|
}
|
|
@@ -49336,12 +49534,12 @@ function uninstallOpenclaw() {
|
|
|
49336
49534
|
const pluginPath = openclawPluginPath();
|
|
49337
49535
|
let removed = false;
|
|
49338
49536
|
try {
|
|
49339
|
-
|
|
49537
|
+
fs32.unlinkSync(pluginPath);
|
|
49340
49538
|
removed = true;
|
|
49341
49539
|
} catch {
|
|
49342
49540
|
}
|
|
49343
49541
|
try {
|
|
49344
|
-
|
|
49542
|
+
fs32.unlinkSync(openclawEntrySidecarPath());
|
|
49345
49543
|
} catch {
|
|
49346
49544
|
}
|
|
49347
49545
|
const settings = readOpenclawConfig(configPath2);
|
|
@@ -49442,12 +49640,12 @@ import * as os15 from "node:os";
|
|
|
49442
49640
|
|
|
49443
49641
|
// src/shell.ts
|
|
49444
49642
|
init_define_import_meta_env();
|
|
49445
|
-
import * as
|
|
49643
|
+
import * as fs33 from "node:fs";
|
|
49446
49644
|
import * as path41 from "node:path";
|
|
49447
49645
|
var WSL_LAUNCHER_SEGMENTS = /* @__PURE__ */ new Set(["system32", "syswow64", "windowsapps"]);
|
|
49448
49646
|
function isExecutable(p) {
|
|
49449
49647
|
try {
|
|
49450
|
-
return
|
|
49648
|
+
return fs33.statSync(p).isFile();
|
|
49451
49649
|
} catch {
|
|
49452
49650
|
return false;
|
|
49453
49651
|
}
|
|
@@ -63073,7 +63271,7 @@ var BRIDGE_CAPABILITY_MATRIX = [
|
|
|
63073
63271
|
harness: "claudecode",
|
|
63074
63272
|
label: "Claude Code",
|
|
63075
63273
|
sourceFile: "src/install.ts (HOOK_EVENT_MAP)",
|
|
63076
|
-
implemented: /* @__PURE__ */ new Set(["pre_tool_use", "post_tool_use", "pre_compact", "user_prompt_submit", "subagent_stop"]),
|
|
63274
|
+
implemented: /* @__PURE__ */ new Set(["pre_tool_use", "post_tool_use", "pre_compact", "user_prompt_submit", "subagent_stop", "session_start"]),
|
|
63077
63275
|
reasons: [{ events: ["notification", "stop"], reason: NO_SERVER_HANDLER_REASON }]
|
|
63078
63276
|
},
|
|
63079
63277
|
{
|
|
@@ -63081,14 +63279,26 @@ var BRIDGE_CAPABILITY_MATRIX = [
|
|
|
63081
63279
|
label: "Codex CLI",
|
|
63082
63280
|
sourceFile: "src/bridges/codex_install.ts (CODEX_HOOK_EVENTS, CODEX_GLOBAL_HOOK_EVENTS)",
|
|
63083
63281
|
implemented: /* @__PURE__ */ new Set(["pre_tool_use", "post_tool_use", "pre_compact", "user_prompt_submit", "subagent_stop"]),
|
|
63084
|
-
reasons: [
|
|
63282
|
+
reasons: [
|
|
63283
|
+
{ events: ["notification", "stop"], reason: NO_SERVER_HANDLER_REASON },
|
|
63284
|
+
{
|
|
63285
|
+
events: ["session_start"],
|
|
63286
|
+
reason: "Codex CLI's hook config schema (CODEX_EVENT_ARG) has no session-start-equivalent event to map onto token-goat's session_start -- unlike Claude Code's real SessionStart hook"
|
|
63287
|
+
}
|
|
63288
|
+
]
|
|
63085
63289
|
},
|
|
63086
63290
|
{
|
|
63087
63291
|
harness: "grok",
|
|
63088
63292
|
label: "Grok CLI",
|
|
63089
63293
|
sourceFile: "src/bridges/grok_install.ts (GROK_HOOK_EVENTS)",
|
|
63090
63294
|
implemented: /* @__PURE__ */ new Set(["pre_tool_use", "post_tool_use", "pre_compact", "user_prompt_submit", "subagent_stop"]),
|
|
63091
|
-
reasons: [
|
|
63295
|
+
reasons: [
|
|
63296
|
+
{ events: ["notification", "stop"], reason: NO_SERVER_HANDLER_REASON },
|
|
63297
|
+
{
|
|
63298
|
+
events: ["session_start"],
|
|
63299
|
+
reason: "GROK_HOOK_EVENTS (this row's explicit `install --grok` writer) mirrors install.ts's HOOK_EVENT_MAP as of the doc verification date -- Grok's real hooks doc has not been re-checked for SessionStart support since, so it is left unwired rather than guessed at (Grok's *default*, non---grok path still rides Claude Code's own settings.json directly and does receive session_start there, same as claudecode)"
|
|
63300
|
+
}
|
|
63301
|
+
]
|
|
63092
63302
|
},
|
|
63093
63303
|
{
|
|
63094
63304
|
harness: "copilot_cli",
|
|
@@ -63099,6 +63309,10 @@ var BRIDGE_CAPABILITY_MATRIX = [
|
|
|
63099
63309
|
{
|
|
63100
63310
|
events: ["notification"],
|
|
63101
63311
|
reason: "Copilot CLI has a real 'notification' hook event, but copilot_cli.ts's COPILOT_TO_TG_EVENT deliberately leaves it (and sessionEnd/postToolUseFailure/subagentStart/errorOccurred/permissionRequest) unimplemented rather than guessed at"
|
|
63312
|
+
},
|
|
63313
|
+
{
|
|
63314
|
+
events: ["session_start"],
|
|
63315
|
+
reason: "COPILOT_TO_TG_EVENT has no session-start mapping wired yet -- left unimplemented rather than guessed at"
|
|
63102
63316
|
}
|
|
63103
63317
|
]
|
|
63104
63318
|
},
|
|
@@ -63109,7 +63323,7 @@ var BRIDGE_CAPABILITY_MATRIX = [
|
|
|
63109
63323
|
implemented: /* @__PURE__ */ new Set(["pre_tool_use", "post_tool_use", "pre_compact"]),
|
|
63110
63324
|
reasons: [
|
|
63111
63325
|
{
|
|
63112
|
-
events: ["notification", "stop", "user_prompt_submit", "subagent_stop"],
|
|
63326
|
+
events: ["notification", "stop", "user_prompt_submit", "subagent_stop", "session_start"],
|
|
63113
63327
|
reason: `Gemini CLI's hooks integration only wires BeforeTool/AfterTool/PreCompress (README "Gemini CLI users")`
|
|
63114
63328
|
}
|
|
63115
63329
|
]
|
|
@@ -63124,7 +63338,11 @@ var BRIDGE_CAPABILITY_MATRIX = [
|
|
|
63124
63338
|
events: ["notification"],
|
|
63125
63339
|
reason: "Only five Qwen Code events have a token-goat handler; every other real event (Notification, SessionEnd, PostToolUseFailure, StopFailure, SubagentStart, PermissionRequest, TodoCreated, TodoCompleted) is left unimplemented rather than guessed at (qwen_install.ts)"
|
|
63126
63340
|
},
|
|
63127
|
-
{ events: ["stop"], reason: NO_SERVER_HANDLER_REASON }
|
|
63341
|
+
{ events: ["stop"], reason: NO_SERVER_HANDLER_REASON },
|
|
63342
|
+
{
|
|
63343
|
+
events: ["session_start"],
|
|
63344
|
+
reason: "QWEN_EVENT_ARG has no session-start mapping wired yet -- left unimplemented rather than guessed at"
|
|
63345
|
+
}
|
|
63128
63346
|
]
|
|
63129
63347
|
},
|
|
63130
63348
|
{
|
|
@@ -63134,7 +63352,7 @@ var BRIDGE_CAPABILITY_MATRIX = [
|
|
|
63134
63352
|
implemented: /* @__PURE__ */ new Set(["pre_tool_use", "post_tool_use", "pre_compact"]),
|
|
63135
63353
|
reasons: [
|
|
63136
63354
|
{
|
|
63137
|
-
events: ["notification", "stop", "user_prompt_submit", "subagent_stop"],
|
|
63355
|
+
events: ["notification", "stop", "user_prompt_submit", "subagent_stop", "session_start"],
|
|
63138
63356
|
reason: "opencode's plugin API only exposes three relevant hooks -- tool.execute.before, tool.execute.after, experimental.session.compacting (opencode.ts module docstring, verified against opencode's real source)"
|
|
63139
63357
|
}
|
|
63140
63358
|
]
|
|
@@ -63146,7 +63364,7 @@ var BRIDGE_CAPABILITY_MATRIX = [
|
|
|
63146
63364
|
implemented: /* @__PURE__ */ new Set(["pre_tool_use", "post_tool_use", "pre_compact"]),
|
|
63147
63365
|
reasons: [
|
|
63148
63366
|
{
|
|
63149
|
-
events: ["notification", "stop", "user_prompt_submit", "subagent_stop"],
|
|
63367
|
+
events: ["notification", "stop", "user_prompt_submit", "subagent_stop", "session_start"],
|
|
63150
63368
|
reason: "OpenClaw's in-process plugin API only exposes before_tool_call/after_tool_call/before_compaction as api.on() handlers relevant here"
|
|
63151
63369
|
}
|
|
63152
63370
|
]
|
|
@@ -63158,8 +63376,8 @@ var BRIDGE_CAPABILITY_MATRIX = [
|
|
|
63158
63376
|
implemented: /* @__PURE__ */ new Set(["pre_tool_use", "post_tool_use", "pre_compact"]),
|
|
63159
63377
|
reasons: [
|
|
63160
63378
|
{
|
|
63161
|
-
events: ["notification", "stop", "user_prompt_submit", "subagent_stop"],
|
|
63162
|
-
reason: "pi's extension API subscribes to session_start/tool_call/tool_result/session_before_compact/session_compact, of which only tool_call/tool_result/session_before_compact map onto real HOOK_EVENTS names (pre_tool_use/post_tool_use/pre_compact)"
|
|
63379
|
+
events: ["notification", "stop", "user_prompt_submit", "subagent_stop", "session_start"],
|
|
63380
|
+
reason: "pi's extension API subscribes to session_start/tool_call/tool_result/session_before_compact/session_compact, of which only tool_call/tool_result/session_before_compact map onto real HOOK_EVENTS names (pre_tool_use/post_tool_use/pre_compact) -- pi's own session_start event is never forwarded to token-goat's callHook()"
|
|
63163
63381
|
}
|
|
63164
63382
|
]
|
|
63165
63383
|
}
|
|
@@ -63262,7 +63480,7 @@ init_csv_query();
|
|
|
63262
63480
|
|
|
63263
63481
|
// src/sharepoint_resolve.ts
|
|
63264
63482
|
init_define_import_meta_env();
|
|
63265
|
-
import * as
|
|
63483
|
+
import * as fs39 from "node:fs";
|
|
63266
63484
|
import * as os17 from "node:os";
|
|
63267
63485
|
import * as path47 from "node:path";
|
|
63268
63486
|
var TENANT_HOST_RE = /^([a-z0-9-]+?)(-my)?\.sharepoint\.com$/i;
|
|
@@ -63311,7 +63529,7 @@ function candidateRoots(env, home) {
|
|
|
63311
63529
|
if (commercial !== void 0) roots.push(commercial);
|
|
63312
63530
|
if (personal !== void 0 && personal !== commercial) roots.push(personal);
|
|
63313
63531
|
try {
|
|
63314
|
-
for (const entry of
|
|
63532
|
+
for (const entry of fs39.readdirSync(home, { withFileTypes: true })) {
|
|
63315
63533
|
if (entry.isDirectory() && /onedrive/i.test(entry.name)) {
|
|
63316
63534
|
const full = path47.join(home, entry.name);
|
|
63317
63535
|
if (!roots.includes(full)) roots.push(full);
|
|
@@ -63324,13 +63542,13 @@ function candidateRoots(env, home) {
|
|
|
63324
63542
|
function tryLibraryPaths(root, libSegments, triedPaths) {
|
|
63325
63543
|
const rawJoined = path47.join(root, ...libSegments);
|
|
63326
63544
|
triedPaths.push(rawJoined);
|
|
63327
|
-
if (
|
|
63545
|
+
if (fs39.existsSync(rawJoined)) return rawJoined;
|
|
63328
63546
|
if (libSegments.length > 0) {
|
|
63329
63547
|
const aliasedFirst = normalizeLibrarySegment(libSegments[0]);
|
|
63330
63548
|
if (aliasedFirst !== libSegments[0]) {
|
|
63331
63549
|
const aliasedJoined = path47.join(root, aliasedFirst, ...libSegments.slice(1));
|
|
63332
63550
|
triedPaths.push(aliasedJoined);
|
|
63333
|
-
if (
|
|
63551
|
+
if (fs39.existsSync(aliasedJoined)) return aliasedJoined;
|
|
63334
63552
|
}
|
|
63335
63553
|
}
|
|
63336
63554
|
return null;
|
|
@@ -63344,7 +63562,7 @@ function resolveLocalPath(parsed, env = process.env, home = os17.homedir()) {
|
|
|
63344
63562
|
if (found !== null) return { resolvedPath: found, triedPaths };
|
|
63345
63563
|
if (parsed.siteType === "site" && parsed.siteName.length > 0) {
|
|
63346
63564
|
try {
|
|
63347
|
-
for (const entry of
|
|
63565
|
+
for (const entry of fs39.readdirSync(root, { withFileTypes: true })) {
|
|
63348
63566
|
if (!entry.isDirectory() || !entry.name.toLowerCase().includes(parsed.siteName.toLowerCase())) continue;
|
|
63349
63567
|
const siteRoot = path47.join(root, entry.name);
|
|
63350
63568
|
const siteFound = tryLibraryPaths(siteRoot, libSegments, triedPaths);
|
|
@@ -63407,7 +63625,7 @@ function extractVideoChapters(file2) {
|
|
|
63407
63625
|
|
|
63408
63626
|
// src/transcript_extract.ts
|
|
63409
63627
|
init_define_import_meta_env();
|
|
63410
|
-
import * as
|
|
63628
|
+
import * as fs40 from "node:fs";
|
|
63411
63629
|
var TIMESTAMP_RE = /(\d{1,2}:)?(\d{2}):(\d{2})[.,](\d{1,3})/;
|
|
63412
63630
|
var CUE_LINE_RE = new RegExp(`^\\s*${TIMESTAMP_RE.source}\\s*-->\\s*${TIMESTAMP_RE.source}`);
|
|
63413
63631
|
var V_TAG_RE = /^<v(?:\.\w+)?\s+([^>]+)>\s*(.*)$/;
|
|
@@ -63459,7 +63677,7 @@ function parseTranscript(content) {
|
|
|
63459
63677
|
return cues;
|
|
63460
63678
|
}
|
|
63461
63679
|
function readTranscript(filePath) {
|
|
63462
|
-
const content =
|
|
63680
|
+
const content = fs40.readFileSync(filePath, "utf8");
|
|
63463
63681
|
return parseTranscript(content);
|
|
63464
63682
|
}
|
|
63465
63683
|
function formatTimestamp(seconds) {
|
|
@@ -63535,7 +63753,7 @@ init_constants();
|
|
|
63535
63753
|
init_session();
|
|
63536
63754
|
init_util2();
|
|
63537
63755
|
init_ansi();
|
|
63538
|
-
import * as
|
|
63756
|
+
import * as fs41 from "node:fs";
|
|
63539
63757
|
import * as path48 from "node:path";
|
|
63540
63758
|
function writeRaw(text) {
|
|
63541
63759
|
const payload = colorStdout() ? text : stripAnsi(text);
|
|
@@ -63548,8 +63766,8 @@ function formatTopFiles(ranked) {
|
|
|
63548
63766
|
if (ranked.length === 0) return "";
|
|
63549
63767
|
const lines2 = ["Top files this session:"];
|
|
63550
63768
|
for (const { path: filePath, count } of ranked) {
|
|
63551
|
-
const
|
|
63552
|
-
lines2.push(` ${count.toString().padStart(3)}x ${
|
|
63769
|
+
const basename20 = path48.basename(filePath);
|
|
63770
|
+
lines2.push(` ${count.toString().padStart(3)}x ${basename20} (${filePath})`);
|
|
63553
63771
|
}
|
|
63554
63772
|
return lines2.join("\n");
|
|
63555
63773
|
}
|
|
@@ -63566,11 +63784,11 @@ function renderTopSessionFiles(topN = 5) {
|
|
|
63566
63784
|
function renderTopSessionFilesFromDisk(topN = 5, overrideSessionsDir) {
|
|
63567
63785
|
try {
|
|
63568
63786
|
const sessionsDir = overrideSessionsDir ?? path48.join(dataDir(), "sessions");
|
|
63569
|
-
if (!
|
|
63570
|
-
const files =
|
|
63787
|
+
if (!fs41.existsSync(sessionsDir)) return "";
|
|
63788
|
+
const files = fs41.readdirSync(sessionsDir).filter((f) => f.endsWith(".json")).map((f) => ({ name: f, mtime: fs41.statSync(path48.join(sessionsDir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime).slice(0, 3);
|
|
63571
63789
|
for (const { name: name2 } of files) {
|
|
63572
63790
|
try {
|
|
63573
|
-
const raw =
|
|
63791
|
+
const raw = fs41.readFileSync(path48.join(sessionsDir, name2), "utf-8");
|
|
63574
63792
|
const data = JSON.parse(raw);
|
|
63575
63793
|
const filesList = data["files"];
|
|
63576
63794
|
if (!Array.isArray(filesList)) continue;
|
|
@@ -63633,33 +63851,36 @@ init_constants();
|
|
|
63633
63851
|
init_cli_context_stats();
|
|
63634
63852
|
init_skill_cache();
|
|
63635
63853
|
init_copilot_cli_install();
|
|
63854
|
+
init_install();
|
|
63636
63855
|
init_ts_refs();
|
|
63637
|
-
|
|
63856
|
+
init_parser();
|
|
63857
|
+
import * as fs42 from "fs";
|
|
63638
63858
|
import * as path49 from "path";
|
|
63639
63859
|
import { execSync, spawnSync as spawnSync7 } from "child_process";
|
|
63640
63860
|
function checkWorkerRunning(dataDir2) {
|
|
63641
63861
|
return dataDir2 !== void 0 ? isWorkerRunning(dataDir2) : isWorkerRunning();
|
|
63642
63862
|
}
|
|
63863
|
+
var DB_SIZE_WARN_BYTES = 1024 * 1024 * 1024;
|
|
63643
63864
|
function checkDbExists(dataDir2) {
|
|
63644
63865
|
const dbPath = path49.join(dataDir2, "global.db");
|
|
63645
|
-
if (!
|
|
63866
|
+
if (!fs42.existsSync(dbPath)) {
|
|
63646
63867
|
return {
|
|
63647
63868
|
name: "Database",
|
|
63648
63869
|
status: "warn",
|
|
63649
63870
|
message: `global.db not found at ${dbPath}`
|
|
63650
63871
|
};
|
|
63651
63872
|
}
|
|
63652
|
-
const sizeBytes =
|
|
63873
|
+
const sizeBytes = fs42.statSync(dbPath).size;
|
|
63653
63874
|
const SQLITE_HEADER = "SQLite format 3\0";
|
|
63654
63875
|
let header = "";
|
|
63655
63876
|
try {
|
|
63656
|
-
const fd =
|
|
63877
|
+
const fd = fs42.openSync(dbPath, "r");
|
|
63657
63878
|
try {
|
|
63658
63879
|
const buf = Buffer.alloc(SQLITE_HEADER.length);
|
|
63659
|
-
const bytesRead =
|
|
63880
|
+
const bytesRead = fs42.readSync(fd, buf, 0, buf.length, 0);
|
|
63660
63881
|
header = buf.toString("latin1", 0, bytesRead);
|
|
63661
63882
|
} finally {
|
|
63662
|
-
|
|
63883
|
+
fs42.closeSync(fd);
|
|
63663
63884
|
}
|
|
63664
63885
|
} catch {
|
|
63665
63886
|
}
|
|
@@ -63670,14 +63891,44 @@ function checkDbExists(dataDir2) {
|
|
|
63670
63891
|
message: `global.db at ${dbPath} is not a valid SQLite file (${sizeBytes} bytes) \u2014 likely truncated or corrupt`
|
|
63671
63892
|
};
|
|
63672
63893
|
}
|
|
63894
|
+
if (sizeBytes > DB_SIZE_WARN_BYTES) {
|
|
63895
|
+
return {
|
|
63896
|
+
name: "Database",
|
|
63897
|
+
status: "warn",
|
|
63898
|
+
message: `global.db is ${Math.round(sizeBytes / (1024 * 1024))} MB at ${dbPath} \u2014 far larger than a healthy index. Large writes against it can exceed the 15s busy_timeout and appear as "database is locked". Try 'token-goat reclaim-index' first (a plain VACUUM, cheap, can recover a useful amount on its own); only reach for 'token-goat reclaim-index --rebuild' if that isn't enough, since --rebuild reparses and re-embeds every indexed file across every project and can take a long time on a large multi-project index`
|
|
63899
|
+
};
|
|
63900
|
+
}
|
|
63673
63901
|
return {
|
|
63674
63902
|
name: "Database",
|
|
63675
63903
|
status: "ok",
|
|
63676
63904
|
message: `global.db exists (${toKB(sizeBytes)} KB)`
|
|
63677
63905
|
};
|
|
63678
63906
|
}
|
|
63907
|
+
function checkSymbolBodySize(dbPath) {
|
|
63908
|
+
if (!fs42.existsSync(dbPath)) {
|
|
63909
|
+
return { name: "Symbol body size", status: "ok", message: "no database yet" };
|
|
63910
|
+
}
|
|
63911
|
+
try {
|
|
63912
|
+
const db = getDb(dbPath);
|
|
63913
|
+
const row = db.prepare("SELECT LENGTH(body) as len, file_path as filePath FROM symbols WHERE LENGTH(body) > ? LIMIT 1").get(MAX_SYMBOL_BODY_CHARS);
|
|
63914
|
+
if (row !== void 0) {
|
|
63915
|
+
return {
|
|
63916
|
+
name: "Symbol body size",
|
|
63917
|
+
status: "warn",
|
|
63918
|
+
message: `a stored symbol body in ${row.filePath} is ${row.len} chars, above the ${MAX_SYMBOL_BODY_CHARS}-char cap enforced by boundSymbolBody -- likely a pre-fix leftover from a minified/generated file. A plain 'token-goat reclaim-index' (VACUUM only) CANNOT remove these rows -- it only reclaims freed pages, it never deletes row content. Only 'token-goat reclaim-index --rebuild' drops and re-derives them under the cap (stop the worker first with 'token-goat worker stop', since reclaim-index refuses to run while it's live); --rebuild reparses and re-embeds every indexed file across every project and can take a long time on a large multi-project index`
|
|
63919
|
+
};
|
|
63920
|
+
}
|
|
63921
|
+
return { name: "Symbol body size", status: "ok", message: "no stored symbol body exceeds the cap" };
|
|
63922
|
+
} catch (err2) {
|
|
63923
|
+
return {
|
|
63924
|
+
name: "Symbol body size",
|
|
63925
|
+
status: "warn",
|
|
63926
|
+
message: `could not query symbol body size: ${extractErrorMessage(err2)}`
|
|
63927
|
+
};
|
|
63928
|
+
}
|
|
63929
|
+
}
|
|
63679
63930
|
function checkSymbolCount(dbPath, rootDir) {
|
|
63680
|
-
if (!
|
|
63931
|
+
if (!fs42.existsSync(dbPath)) {
|
|
63681
63932
|
return { name: "Symbols", status: "ok", message: "no database yet" };
|
|
63682
63933
|
}
|
|
63683
63934
|
try {
|
|
@@ -63716,7 +63967,7 @@ var DRAIN_HEARTBEAT_STALE_MS = 6e4;
|
|
|
63716
63967
|
function checkDirtyQueueHealth(dataDir2) {
|
|
63717
63968
|
let pendingCount = 0;
|
|
63718
63969
|
try {
|
|
63719
|
-
const raw =
|
|
63970
|
+
const raw = fs42.readFileSync(dirtyQueuePathFor(dataDir2), "utf8");
|
|
63720
63971
|
pendingCount = raw.split("\n").map((line) => line.trim()).filter((line) => line.length > 0).length;
|
|
63721
63972
|
} catch {
|
|
63722
63973
|
}
|
|
@@ -63732,7 +63983,7 @@ function checkDirtyQueueHealth(dataDir2) {
|
|
|
63732
63983
|
}
|
|
63733
63984
|
let heartbeatAgeMs = null;
|
|
63734
63985
|
try {
|
|
63735
|
-
heartbeatAgeMs = Date.now() -
|
|
63986
|
+
heartbeatAgeMs = Date.now() - fs42.statSync(drainHeartbeatPathFor(dataDir2)).mtimeMs;
|
|
63736
63987
|
} catch {
|
|
63737
63988
|
}
|
|
63738
63989
|
if (heartbeatAgeMs !== null && heartbeatAgeMs > DRAIN_HEARTBEAT_STALE_MS) {
|
|
@@ -63772,7 +64023,7 @@ function checkTsCompiler() {
|
|
|
63772
64023
|
};
|
|
63773
64024
|
}
|
|
63774
64025
|
function checkConfigValid(configPath2) {
|
|
63775
|
-
if (!
|
|
64026
|
+
if (!fs42.existsSync(configPath2)) {
|
|
63776
64027
|
return {
|
|
63777
64028
|
name: "Config",
|
|
63778
64029
|
status: "warn",
|
|
@@ -63780,7 +64031,7 @@ function checkConfigValid(configPath2) {
|
|
|
63780
64031
|
};
|
|
63781
64032
|
}
|
|
63782
64033
|
try {
|
|
63783
|
-
const content =
|
|
64034
|
+
const content = fs42.readFileSync(configPath2, "utf-8");
|
|
63784
64035
|
parse(content);
|
|
63785
64036
|
return {
|
|
63786
64037
|
name: "Config",
|
|
@@ -63807,9 +64058,9 @@ function formatDiskSpace(bytes) {
|
|
|
63807
64058
|
}
|
|
63808
64059
|
var LOW_DISK_WARN_BYTES = 1024 * 1024 * 1024;
|
|
63809
64060
|
function checkDiskSpace(dataDir2) {
|
|
63810
|
-
if (typeof
|
|
64061
|
+
if (typeof fs42.statfsSync === "function") {
|
|
63811
64062
|
try {
|
|
63812
|
-
const stats =
|
|
64063
|
+
const stats = fs42.statfsSync(dataDir2);
|
|
63813
64064
|
const availableBytes = stats.bavail * stats.bsize;
|
|
63814
64065
|
const status = availableBytes < LOW_DISK_WARN_BYTES ? "warn" : "ok";
|
|
63815
64066
|
const suffix = status === "warn" ? " \u2014 running low, indexing/embeddings writes may start failing" : "";
|
|
@@ -63840,12 +64091,12 @@ function checkDiskSpace(dataDir2) {
|
|
|
63840
64091
|
return { name: "Disk Space", status: "warn", message: "disk space check unavailable on this platform" };
|
|
63841
64092
|
}
|
|
63842
64093
|
function checkCopilotCli(configPath2, scriptPath) {
|
|
63843
|
-
if (!
|
|
64094
|
+
if (!fs42.existsSync(configPath2) || !fs42.existsSync(scriptPath)) {
|
|
63844
64095
|
return null;
|
|
63845
64096
|
}
|
|
63846
64097
|
let config2;
|
|
63847
64098
|
try {
|
|
63848
|
-
config2 = JSON.parse(
|
|
64099
|
+
config2 = JSON.parse(fs42.readFileSync(configPath2, "utf-8"));
|
|
63849
64100
|
} catch (err2) {
|
|
63850
64101
|
return {
|
|
63851
64102
|
name: "Copilot CLI",
|
|
@@ -63862,7 +64113,7 @@ function checkCopilotCli(configPath2, scriptPath) {
|
|
|
63862
64113
|
};
|
|
63863
64114
|
}
|
|
63864
64115
|
const bakedExecPath = /^"([^"]+)"/.exec(preToolUseCommand)?.[1];
|
|
63865
|
-
if (bakedExecPath !== void 0 && !
|
|
64116
|
+
if (bakedExecPath !== void 0 && !fs42.existsSync(bakedExecPath)) {
|
|
63866
64117
|
return {
|
|
63867
64118
|
name: "Copilot CLI",
|
|
63868
64119
|
status: "fail",
|
|
@@ -63907,13 +64158,26 @@ function checkCopilotCli(configPath2, scriptPath) {
|
|
|
63907
64158
|
}
|
|
63908
64159
|
return { name: "Copilot CLI", status: "ok", message: "preToolUse hook invokes cleanly and returns valid JSON" };
|
|
63909
64160
|
}
|
|
64161
|
+
function checkStrayClaudeMdBlocks(searchRoot) {
|
|
64162
|
+
const strays = findStrayClaudeMdBlocks(searchRoot);
|
|
64163
|
+
if (strays.length === 0) {
|
|
64164
|
+
return { name: "CLAUDE.md block", status: "ok", message: "no stray copies outside CLAUDE.md" };
|
|
64165
|
+
}
|
|
64166
|
+
return {
|
|
64167
|
+
name: "CLAUDE.md block",
|
|
64168
|
+
status: "warn",
|
|
64169
|
+
message: `${strays.length} stray cop${strays.length === 1 ? "y" : "ies"} outside CLAUDE.md (never refreshed by install, never removed by uninstall, will go stale): ${strays.join(", ")}`
|
|
64170
|
+
};
|
|
64171
|
+
}
|
|
63910
64172
|
function runDoctor(dataDir2, configPath2, rootDir) {
|
|
63911
64173
|
const results = [];
|
|
63912
64174
|
const actualDataDir = dataDir2 || dataDir();
|
|
63913
64175
|
results.push(checkInstall());
|
|
63914
64176
|
results.push(checkTsCompiler());
|
|
64177
|
+
results.push(checkStrayClaudeMdBlocks());
|
|
63915
64178
|
results.push(checkWorkerRunning(actualDataDir) ? { name: "Worker", status: "ok", message: "running" } : { name: "Worker", status: "warn", message: "not running" });
|
|
63916
64179
|
results.push(checkDbExists(actualDataDir));
|
|
64180
|
+
results.push(checkSymbolBodySize(path49.join(actualDataDir, "global.db")));
|
|
63917
64181
|
results.push(checkSymbolCount(path49.join(actualDataDir, "global.db"), rootDir));
|
|
63918
64182
|
results.push(checkDirtyQueueHealth(actualDataDir));
|
|
63919
64183
|
const actualConfigPath = configPath2 || configPath();
|
|
@@ -63953,16 +64217,16 @@ async function runDoctorAndExit(opts) {
|
|
|
63953
64217
|
try {
|
|
63954
64218
|
const dir = skillOutputsDir();
|
|
63955
64219
|
const pregenPath = path49.join(dir, "pregen.json");
|
|
63956
|
-
if (
|
|
63957
|
-
const content = JSON.parse(
|
|
64220
|
+
if (fs42.existsSync(pregenPath)) {
|
|
64221
|
+
const content = JSON.parse(fs42.readFileSync(pregenPath, "utf-8"));
|
|
63958
64222
|
const pregenNames = new Set(content.names || []);
|
|
63959
64223
|
const skillsSeen = /* @__PURE__ */ new Set();
|
|
63960
64224
|
try {
|
|
63961
|
-
const entries =
|
|
64225
|
+
const entries = fs42.readdirSync(dir, { withFileTypes: true });
|
|
63962
64226
|
for (const entry of entries) {
|
|
63963
64227
|
if (!entry.isFile() || !entry.name.endsWith(".meta")) continue;
|
|
63964
64228
|
try {
|
|
63965
|
-
const meta3 = JSON.parse(
|
|
64229
|
+
const meta3 = JSON.parse(fs42.readFileSync(path49.join(dir, entry.name), "utf-8"));
|
|
63966
64230
|
if (meta3.skillName && !pregenNames.has(meta3.skillName)) {
|
|
63967
64231
|
skillsSeen.add(meta3.skillName);
|
|
63968
64232
|
}
|
|
@@ -64109,7 +64373,7 @@ async function getSectionContent(fileId, heading, opts = {}) {
|
|
|
64109
64373
|
|
|
64110
64374
|
// src/pack.ts
|
|
64111
64375
|
init_define_import_meta_env();
|
|
64112
|
-
import * as
|
|
64376
|
+
import * as fs43 from "node:fs";
|
|
64113
64377
|
import * as path51 from "node:path";
|
|
64114
64378
|
|
|
64115
64379
|
// node_modules/minimatch/dist/esm/index.js
|
|
@@ -64137,14 +64401,14 @@ init_define_import_meta_env();
|
|
|
64137
64401
|
init_define_import_meta_env();
|
|
64138
64402
|
var balanced = (a, b, str) => {
|
|
64139
64403
|
const ma = a instanceof RegExp ? maybeMatch(a, str) : a;
|
|
64140
|
-
const
|
|
64141
|
-
const r = ma !== null &&
|
|
64404
|
+
const mb2 = b instanceof RegExp ? maybeMatch(b, str) : b;
|
|
64405
|
+
const r = ma !== null && mb2 != null && range(ma, mb2, str);
|
|
64142
64406
|
return r && {
|
|
64143
64407
|
start: r[0],
|
|
64144
64408
|
end: r[1],
|
|
64145
64409
|
pre: str.slice(0, r[0]),
|
|
64146
64410
|
body: str.slice(r[0] + ma.length, r[1]),
|
|
64147
|
-
post: str.slice(r[1] +
|
|
64411
|
+
post: str.slice(r[1] + mb2.length)
|
|
64148
64412
|
};
|
|
64149
64413
|
};
|
|
64150
64414
|
var maybeMatch = (reg, str) => {
|
|
@@ -65999,24 +66263,24 @@ function isPathWithinRoot(rootReal, resolvedPath) {
|
|
|
65999
66263
|
function openWithinRoot(rootReal, p) {
|
|
66000
66264
|
let fd;
|
|
66001
66265
|
try {
|
|
66002
|
-
fd =
|
|
66266
|
+
fd = fs43.openSync(p, "r");
|
|
66003
66267
|
} catch {
|
|
66004
66268
|
return null;
|
|
66005
66269
|
}
|
|
66006
66270
|
let ownershipTransferred = false;
|
|
66007
66271
|
try {
|
|
66008
|
-
const stat2 =
|
|
66272
|
+
const stat2 = fs43.fstatSync(fd);
|
|
66009
66273
|
if (!stat2.isFile()) return null;
|
|
66010
66274
|
let realPath;
|
|
66011
66275
|
try {
|
|
66012
|
-
realPath =
|
|
66276
|
+
realPath = fs43.realpathSync(p);
|
|
66013
66277
|
} catch {
|
|
66014
66278
|
return "outside-root";
|
|
66015
66279
|
}
|
|
66016
66280
|
if (!isPathWithinRoot(rootReal, realPath)) return "outside-root";
|
|
66017
66281
|
let realStat;
|
|
66018
66282
|
try {
|
|
66019
|
-
realStat =
|
|
66283
|
+
realStat = fs43.statSync(realPath);
|
|
66020
66284
|
} catch {
|
|
66021
66285
|
return "outside-root";
|
|
66022
66286
|
}
|
|
@@ -66026,7 +66290,7 @@ function openWithinRoot(rootReal, p) {
|
|
|
66026
66290
|
} finally {
|
|
66027
66291
|
if (!ownershipTransferred) {
|
|
66028
66292
|
try {
|
|
66029
|
-
|
|
66293
|
+
fs43.closeSync(fd);
|
|
66030
66294
|
} catch {
|
|
66031
66295
|
}
|
|
66032
66296
|
}
|
|
@@ -66050,7 +66314,7 @@ function* resolveOpenCandidates(projectRoot, patterns, rootReal, ignorePatterns,
|
|
|
66050
66314
|
continue;
|
|
66051
66315
|
}
|
|
66052
66316
|
if (ignorePatterns && matches(rel, ignorePatterns)) {
|
|
66053
|
-
|
|
66317
|
+
fs43.closeSync(opened.fd);
|
|
66054
66318
|
continue;
|
|
66055
66319
|
}
|
|
66056
66320
|
yield { p, rel, fd: opened.fd, stat: opened.stat };
|
|
@@ -66071,18 +66335,17 @@ function advanceQuoteState(text, from, to, state) {
|
|
|
66071
66335
|
backslashes++;
|
|
66072
66336
|
continue;
|
|
66073
66337
|
}
|
|
66074
|
-
if (backslashes % 2 === 0) {
|
|
66075
|
-
if (
|
|
66076
|
-
else if (
|
|
66077
|
-
else if (ch === "`") state.bt = !state.bt;
|
|
66338
|
+
if (backslashes % 2 === 0 && (ch === '"' || ch === "'" || ch === "`")) {
|
|
66339
|
+
if (state.open === null) state.open = ch;
|
|
66340
|
+
else if (state.open === ch) state.open = null;
|
|
66078
66341
|
}
|
|
66079
66342
|
backslashes = 0;
|
|
66080
66343
|
}
|
|
66081
66344
|
return state;
|
|
66082
66345
|
}
|
|
66083
66346
|
function computeLineStartQuoteStates(content) {
|
|
66084
|
-
const states = [{
|
|
66085
|
-
let state = {
|
|
66347
|
+
const states = [{ open: null }];
|
|
66348
|
+
let state = { open: null };
|
|
66086
66349
|
let lineStart = 0;
|
|
66087
66350
|
for (let i = 0; i < content.length; i++) {
|
|
66088
66351
|
if (content[i] === "\n") {
|
|
@@ -66096,9 +66359,9 @@ function computeLineStartQuoteStates(content) {
|
|
|
66096
66359
|
function isInsideStringLiteral2(text, index, lineStates) {
|
|
66097
66360
|
const lineStart = text.lastIndexOf("\n", index - 1) + 1;
|
|
66098
66361
|
const lineNum = text.slice(0, lineStart).split("\n").length - 1;
|
|
66099
|
-
const startState = lineStates[lineNum] ?? {
|
|
66362
|
+
const startState = lineStates[lineNum] ?? { open: null };
|
|
66100
66363
|
const state = advanceQuoteState(text, lineStart, index, { ...startState });
|
|
66101
|
-
return state.
|
|
66364
|
+
return state.open !== null;
|
|
66102
66365
|
}
|
|
66103
66366
|
function stripLineComments(content, pattern, lineStates) {
|
|
66104
66367
|
return content.replace(
|
|
@@ -66177,7 +66440,7 @@ function collectFiles(projectRoot, patterns, opts = {}) {
|
|
|
66177
66440
|
const rootResolved = path51.resolve(projectRoot);
|
|
66178
66441
|
let rootReal;
|
|
66179
66442
|
try {
|
|
66180
|
-
rootReal =
|
|
66443
|
+
rootReal = fs43.realpathSync(rootResolved);
|
|
66181
66444
|
} catch {
|
|
66182
66445
|
rootReal = rootResolved;
|
|
66183
66446
|
}
|
|
@@ -66191,7 +66454,7 @@ function collectFiles(projectRoot, patterns, opts = {}) {
|
|
|
66191
66454
|
}
|
|
66192
66455
|
let content;
|
|
66193
66456
|
try {
|
|
66194
|
-
content =
|
|
66457
|
+
content = fs43.readFileSync(fd, "utf8");
|
|
66195
66458
|
} catch {
|
|
66196
66459
|
result.skipped.push(`${rel} (unreadable)`);
|
|
66197
66460
|
continue;
|
|
@@ -66213,13 +66476,13 @@ function collectFiles(projectRoot, patterns, opts = {}) {
|
|
|
66213
66476
|
result.total_lines += lines2;
|
|
66214
66477
|
result.total_tokens += tokens;
|
|
66215
66478
|
} finally {
|
|
66216
|
-
|
|
66479
|
+
fs43.closeSync(fd);
|
|
66217
66480
|
}
|
|
66218
66481
|
}
|
|
66219
66482
|
return result;
|
|
66220
66483
|
}
|
|
66221
66484
|
function collectFromStdin(projectRoot, opts = {}) {
|
|
66222
|
-
const input =
|
|
66485
|
+
const input = fs43.readFileSync(0, "utf8");
|
|
66223
66486
|
const paths = input.split("\n").map((ln) => ln.trim()).filter((ln) => ln.length > 0);
|
|
66224
66487
|
return collectFiles(projectRoot, paths, opts);
|
|
66225
66488
|
}
|
|
@@ -66352,7 +66615,7 @@ function estimateBudget(projectRoot, patterns, opts = {}) {
|
|
|
66352
66615
|
const rootResolved = path51.resolve(projectRoot);
|
|
66353
66616
|
let rootReal;
|
|
66354
66617
|
try {
|
|
66355
|
-
rootReal =
|
|
66618
|
+
rootReal = fs43.realpathSync(rootResolved);
|
|
66356
66619
|
} catch {
|
|
66357
66620
|
rootReal = rootResolved;
|
|
66358
66621
|
}
|
|
@@ -66367,7 +66630,7 @@ function estimateBudget(projectRoot, patterns, opts = {}) {
|
|
|
66367
66630
|
let lines2;
|
|
66368
66631
|
let tokens;
|
|
66369
66632
|
try {
|
|
66370
|
-
const data =
|
|
66633
|
+
const data = fs43.readFileSync(fd);
|
|
66371
66634
|
const sampleSize = Math.min(1e3, data.length);
|
|
66372
66635
|
const sampleLines = (data.toString("utf8", 0, sampleSize).match(/\n/g) || []).length;
|
|
66373
66636
|
lines2 = data.length > sampleSize ? Math.ceil(sampleLines * (data.length / sampleSize)) : sampleLines + 1;
|
|
@@ -66385,7 +66648,7 @@ function estimateBudget(projectRoot, patterns, opts = {}) {
|
|
|
66385
66648
|
result.total_lines += lines2;
|
|
66386
66649
|
result.total_tokens += tokens;
|
|
66387
66650
|
} finally {
|
|
66388
|
-
|
|
66651
|
+
fs43.closeSync(fd);
|
|
66389
66652
|
}
|
|
66390
66653
|
}
|
|
66391
66654
|
result.entries.sort((a, b) => b.tokens - a.tokens);
|
|
@@ -66802,7 +67065,7 @@ function formatFailureDeltaJson(delta, runner) {
|
|
|
66802
67065
|
init_define_import_meta_env();
|
|
66803
67066
|
init_constants();
|
|
66804
67067
|
init_util2();
|
|
66805
|
-
import * as
|
|
67068
|
+
import * as fs44 from "node:fs";
|
|
66806
67069
|
import * as path52 from "node:path";
|
|
66807
67070
|
var KEY_RE = /^[A-Za-z0-9_-]{1,80}$/;
|
|
66808
67071
|
var DEFAULT_FAILURES_STATE_KEY = "default";
|
|
@@ -66820,8 +67083,8 @@ function failuresStatePath(projectHash2, key) {
|
|
|
66820
67083
|
function loadFailureSnapshot(projectHash2, key) {
|
|
66821
67084
|
const p = failuresStatePath(projectHash2, key);
|
|
66822
67085
|
try {
|
|
66823
|
-
if (!
|
|
66824
|
-
const parsed = JSON.parse(
|
|
67086
|
+
if (!fs44.existsSync(p)) return null;
|
|
67087
|
+
const parsed = JSON.parse(fs44.readFileSync(p, "utf-8"));
|
|
66825
67088
|
if (typeof parsed !== "object" || parsed === null) return null;
|
|
66826
67089
|
const obj = parsed;
|
|
66827
67090
|
if (!Array.isArray(obj.signatures)) return null;
|
|
@@ -66860,14 +67123,14 @@ init_graph_commands();
|
|
|
66860
67123
|
init_index_reader();
|
|
66861
67124
|
init_paths();
|
|
66862
67125
|
init_project();
|
|
66863
|
-
import * as
|
|
67126
|
+
import * as fs46 from "fs";
|
|
66864
67127
|
import * as path54 from "path";
|
|
66865
67128
|
|
|
66866
67129
|
// src/project_memory.ts
|
|
66867
67130
|
init_define_import_meta_env();
|
|
66868
67131
|
init_constants();
|
|
66869
67132
|
init_util2();
|
|
66870
|
-
import * as
|
|
67133
|
+
import * as fs45 from "node:fs";
|
|
66871
67134
|
import * as path53 from "node:path";
|
|
66872
67135
|
var MAX_ENTRIES = 30;
|
|
66873
67136
|
var KEY_RE2 = /^[A-Za-z0-9_-]{1,80}$/;
|
|
@@ -66917,10 +67180,10 @@ function parseTOML(content) {
|
|
|
66917
67180
|
}
|
|
66918
67181
|
function loadRaw(filePath) {
|
|
66919
67182
|
try {
|
|
66920
|
-
if (!
|
|
67183
|
+
if (!fs45.existsSync(filePath)) {
|
|
66921
67184
|
return {};
|
|
66922
67185
|
}
|
|
66923
|
-
const content =
|
|
67186
|
+
const content = fs45.readFileSync(filePath, "utf-8");
|
|
66924
67187
|
return parseTOML(content);
|
|
66925
67188
|
} catch {
|
|
66926
67189
|
return {};
|
|
@@ -66978,7 +67241,7 @@ function unsetEntry(projectHash2, key) {
|
|
|
66978
67241
|
function clearAll(projectHash2) {
|
|
66979
67242
|
const p = memoryPath(projectHash2);
|
|
66980
67243
|
const doClear = () => {
|
|
66981
|
-
if (
|
|
67244
|
+
if (fs45.existsSync(p)) {
|
|
66982
67245
|
save(p, {});
|
|
66983
67246
|
}
|
|
66984
67247
|
return true;
|
|
@@ -66991,8 +67254,8 @@ init_read_commands();
|
|
|
66991
67254
|
init_session();
|
|
66992
67255
|
init_util2();
|
|
66993
67256
|
function readInput(src) {
|
|
66994
|
-
if (src !== void 0) return
|
|
66995
|
-
return
|
|
67257
|
+
if (src !== void 0) return fs46.readFileSync(src, "utf8");
|
|
67258
|
+
return fs46.readFileSync(0, "utf8");
|
|
66996
67259
|
}
|
|
66997
67260
|
function splitLines2(text) {
|
|
66998
67261
|
return text.split(/\r?\n/);
|
|
@@ -67019,7 +67282,7 @@ function isInsideStringLiteral3(line, markerIndex) {
|
|
|
67019
67282
|
function scanFileForTodos(filePath, kindSet) {
|
|
67020
67283
|
let text;
|
|
67021
67284
|
try {
|
|
67022
|
-
text =
|
|
67285
|
+
text = fs46.readFileSync(filePath, "utf8");
|
|
67023
67286
|
} catch {
|
|
67024
67287
|
return [];
|
|
67025
67288
|
}
|
|
@@ -67043,7 +67306,7 @@ function collectTodoFiles(patterns) {
|
|
|
67043
67306
|
for (const p of patterns) {
|
|
67044
67307
|
const abs = path54.resolve(p);
|
|
67045
67308
|
try {
|
|
67046
|
-
const stat2 =
|
|
67309
|
+
const stat2 = fs46.statSync(abs);
|
|
67047
67310
|
if (stat2.isDirectory()) {
|
|
67048
67311
|
results.push(...walkProject(abs).files);
|
|
67049
67312
|
} else {
|
|
@@ -67475,7 +67738,7 @@ var LOCK_PRIORITY = [
|
|
|
67475
67738
|
"Cargo.lock"
|
|
67476
67739
|
];
|
|
67477
67740
|
function findLockfile(startPath) {
|
|
67478
|
-
const stat2 =
|
|
67741
|
+
const stat2 = fs46.statSync(startPath, { throwIfNoEntry: false });
|
|
67479
67742
|
if (stat2 !== void 0 && stat2.isFile()) {
|
|
67480
67743
|
return { file: startPath, others: [] };
|
|
67481
67744
|
}
|
|
@@ -67483,10 +67746,10 @@ function findLockfile(startPath) {
|
|
|
67483
67746
|
const found = [];
|
|
67484
67747
|
for (const name2 of LOCK_PRIORITY) {
|
|
67485
67748
|
const candidate = path54.join(dir, name2);
|
|
67486
|
-
if (
|
|
67749
|
+
if (fs46.existsSync(candidate)) found.push(candidate);
|
|
67487
67750
|
}
|
|
67488
67751
|
try {
|
|
67489
|
-
const entries =
|
|
67752
|
+
const entries = fs46.readdirSync(dir);
|
|
67490
67753
|
for (const e of entries) {
|
|
67491
67754
|
if (/^requirements.*\.txt$/.test(e)) {
|
|
67492
67755
|
const p = path54.join(dir, e);
|
|
@@ -67687,7 +67950,7 @@ function parsePnpmLock(content) {
|
|
|
67687
67950
|
}
|
|
67688
67951
|
function parseLockFile(filePath) {
|
|
67689
67952
|
const base = path54.basename(filePath);
|
|
67690
|
-
const content =
|
|
67953
|
+
const content = fs46.readFileSync(filePath, "utf8");
|
|
67691
67954
|
if (base === "package-lock.json") return { format: "npm", deps: parsePackageLockJson(content) };
|
|
67692
67955
|
if (base === "yarn.lock") return { format: "yarn", deps: parseYarnLock(content) };
|
|
67693
67956
|
if (base === "pnpm-lock.yaml") return { format: "pnpm", deps: parsePnpmLock(content) };
|
|
@@ -67760,7 +68023,7 @@ function cmdLockdepsPackage(lockfile, format, deps, query, json2) {
|
|
|
67760
68023
|
}
|
|
67761
68024
|
const primary = matches2.find((d) => d.kind === "direct") ?? matches2[0];
|
|
67762
68025
|
const otherVersions = [...new Set(matches2.filter((d) => d.version !== primary.version).map((d) => d.version))];
|
|
67763
|
-
const graph = format === "npm" ? buildNpmEdges(
|
|
68026
|
+
const graph = format === "npm" ? buildNpmEdges(fs46.readFileSync(lockfile, "utf8")) : null;
|
|
67764
68027
|
const graphAvailable = graph !== null;
|
|
67765
68028
|
const dependsOn = graph !== null ? [...graph.edges.get(query) ?? []].sort() : [];
|
|
67766
68029
|
const dependedOnBy = graph !== null ? findReverseDirectDeps(query, graph.edges, graph.directNames) : [];
|
|
@@ -67894,7 +68157,7 @@ function loadAllSessionReadCounts() {
|
|
|
67894
68157
|
const totals = /* @__PURE__ */ new Map();
|
|
67895
68158
|
let entries;
|
|
67896
68159
|
try {
|
|
67897
|
-
entries =
|
|
68160
|
+
entries = fs46.readdirSync(sessionsDir, { withFileTypes: true });
|
|
67898
68161
|
} catch {
|
|
67899
68162
|
return totals;
|
|
67900
68163
|
}
|
|
@@ -67903,7 +68166,7 @@ function loadAllSessionReadCounts() {
|
|
|
67903
68166
|
const filePath = path54.join(sessionsDir, entry.name);
|
|
67904
68167
|
let raw;
|
|
67905
68168
|
try {
|
|
67906
|
-
raw = JSON.parse(
|
|
68169
|
+
raw = JSON.parse(fs46.readFileSync(filePath, "utf8"));
|
|
67907
68170
|
} catch {
|
|
67908
68171
|
continue;
|
|
67909
68172
|
}
|
|
@@ -67979,7 +68242,7 @@ function detectWalkMode(cwd) {
|
|
|
67979
68242
|
if (project?.marker === ".git") return "git";
|
|
67980
68243
|
let cur = cwd;
|
|
67981
68244
|
while (true) {
|
|
67982
|
-
if (
|
|
68245
|
+
if (fs46.existsSync(path54.join(cur, ".git"))) return "git";
|
|
67983
68246
|
const parent = path54.dirname(cur);
|
|
67984
68247
|
if (parent === cur) break;
|
|
67985
68248
|
cur = parent;
|
|
@@ -68035,7 +68298,7 @@ init_overflow_guard();
|
|
|
68035
68298
|
init_stats();
|
|
68036
68299
|
init_util2();
|
|
68037
68300
|
import { createRequire as createRequire7 } from "node:module";
|
|
68038
|
-
import * as
|
|
68301
|
+
import * as fs47 from "node:fs";
|
|
68039
68302
|
import * as path55 from "node:path";
|
|
68040
68303
|
var _require6 = createRequire7(import.meta.url);
|
|
68041
68304
|
var _ts2 = null;
|
|
@@ -68055,21 +68318,21 @@ function loadTs2() {
|
|
|
68055
68318
|
}
|
|
68056
68319
|
function dirExists(p) {
|
|
68057
68320
|
try {
|
|
68058
|
-
return
|
|
68321
|
+
return fs47.statSync(p).isDirectory();
|
|
68059
68322
|
} catch {
|
|
68060
68323
|
return false;
|
|
68061
68324
|
}
|
|
68062
68325
|
}
|
|
68063
68326
|
function fileExists2(p) {
|
|
68064
68327
|
try {
|
|
68065
|
-
return
|
|
68328
|
+
return fs47.statSync(p).isFile();
|
|
68066
68329
|
} catch {
|
|
68067
68330
|
return false;
|
|
68068
68331
|
}
|
|
68069
68332
|
}
|
|
68070
68333
|
function readFileTextOrNull(p) {
|
|
68071
68334
|
try {
|
|
68072
|
-
return
|
|
68335
|
+
return fs47.readFileSync(p, "utf8");
|
|
68073
68336
|
} catch {
|
|
68074
68337
|
return null;
|
|
68075
68338
|
}
|
|
@@ -68077,7 +68340,7 @@ function readFileTextOrNull(p) {
|
|
|
68077
68340
|
function listInstalledPackageNames(nodeModulesDir) {
|
|
68078
68341
|
let entries;
|
|
68079
68342
|
try {
|
|
68080
|
-
entries =
|
|
68343
|
+
entries = fs47.readdirSync(nodeModulesDir, { withFileTypes: true });
|
|
68081
68344
|
} catch {
|
|
68082
68345
|
return [];
|
|
68083
68346
|
}
|
|
@@ -68087,7 +68350,7 @@ function listInstalledPackageNames(nodeModulesDir) {
|
|
|
68087
68350
|
if (entry.name.startsWith("@")) {
|
|
68088
68351
|
let scoped;
|
|
68089
68352
|
try {
|
|
68090
|
-
scoped =
|
|
68353
|
+
scoped = fs47.readdirSync(path55.join(nodeModulesDir, entry.name), { withFileTypes: true });
|
|
68091
68354
|
} catch {
|
|
68092
68355
|
continue;
|
|
68093
68356
|
}
|
|
@@ -68109,7 +68372,7 @@ function findReadmeFile(pkgDir) {
|
|
|
68109
68372
|
function findReadmeIn(dir) {
|
|
68110
68373
|
let entries;
|
|
68111
68374
|
try {
|
|
68112
|
-
entries =
|
|
68375
|
+
entries = fs47.readdirSync(dir, { withFileTypes: true });
|
|
68113
68376
|
} catch {
|
|
68114
68377
|
return null;
|
|
68115
68378
|
}
|
|
@@ -68247,7 +68510,7 @@ function runDepDocs(opts) {
|
|
|
68247
68510
|
const hint = suggestions.length > 0 ? ` (did you mean: ${suggestions.join(", ")}?)` : "";
|
|
68248
68511
|
return { text: `Package '${opts.packageName}' not found under ${nodeModulesDir}${hint}`, code: 1 };
|
|
68249
68512
|
}
|
|
68250
|
-
const pkgJsonRaw =
|
|
68513
|
+
const pkgJsonRaw = fs47.readFileSync(pkgJsonPath, "utf8");
|
|
68251
68514
|
let pkgJson;
|
|
68252
68515
|
try {
|
|
68253
68516
|
pkgJson = JSON.parse(pkgJsonRaw);
|
|
@@ -68331,11 +68594,11 @@ init_install();
|
|
|
68331
68594
|
// src/webfetch.ts
|
|
68332
68595
|
init_define_import_meta_env();
|
|
68333
68596
|
init_constants();
|
|
68334
|
-
import { existsSync as existsSync32, readdirSync as
|
|
68597
|
+
import { existsSync as existsSync32, readdirSync as readdirSync20, statSync as statSync26, unlinkSync as unlinkSync12 } from "fs";
|
|
68335
68598
|
import * as http from "http";
|
|
68336
68599
|
import * as https from "https";
|
|
68337
68600
|
import { isIPv4, isIPv6 } from "net";
|
|
68338
|
-
import { resolve as
|
|
68601
|
+
import { resolve as resolve16, join as join40 } from "path";
|
|
68339
68602
|
import { URL as URL2 } from "url";
|
|
68340
68603
|
import { promisify } from "util";
|
|
68341
68604
|
import { lookup as dnsLookup } from "dns";
|
|
@@ -68504,10 +68767,10 @@ function cleanupStaleDownloads() {
|
|
|
68504
68767
|
if (!existsSync32(cacheDir)) return 0;
|
|
68505
68768
|
let removed = 0;
|
|
68506
68769
|
try {
|
|
68507
|
-
const files =
|
|
68770
|
+
const files = readdirSync20(cacheDir);
|
|
68508
68771
|
for (const file2 of files) {
|
|
68509
68772
|
if (file2.endsWith(".tmp")) {
|
|
68510
|
-
const filePath =
|
|
68773
|
+
const filePath = resolve16(cacheDir, file2);
|
|
68511
68774
|
try {
|
|
68512
68775
|
const stat2 = statSync26(filePath);
|
|
68513
68776
|
if (Date.now() - stat2.mtimeMs < STALE_DOWNLOAD_AGE_MS) continue;
|
|
@@ -69067,6 +69330,121 @@ function cmdBaseline(opts) {
|
|
|
69067
69330
|
process.stdout.write(out2 + String.fromCharCode(10));
|
|
69068
69331
|
}
|
|
69069
69332
|
|
|
69333
|
+
// src/index_reclaim.ts
|
|
69334
|
+
init_define_import_meta_env();
|
|
69335
|
+
init_db();
|
|
69336
|
+
init_constants();
|
|
69337
|
+
init_worker();
|
|
69338
|
+
import * as fs48 from "node:fs";
|
|
69339
|
+
import * as path56 from "node:path";
|
|
69340
|
+
var DERIVED_TABLES = ["chunk_vectors", "chunks", "refs", "symbols", "files"];
|
|
69341
|
+
function indexSizeBytes(dbPath) {
|
|
69342
|
+
let total = 0;
|
|
69343
|
+
for (const p of [dbPath, `${dbPath}-wal`]) {
|
|
69344
|
+
try {
|
|
69345
|
+
total += fs48.statSync(p).size;
|
|
69346
|
+
} catch {
|
|
69347
|
+
}
|
|
69348
|
+
}
|
|
69349
|
+
return total;
|
|
69350
|
+
}
|
|
69351
|
+
function tableExists(db, table) {
|
|
69352
|
+
const row = db.prepare(`SELECT 1 AS present FROM sqlite_master WHERE type IN ('table','view') AND name = ?`).get(table);
|
|
69353
|
+
return row?.present === 1;
|
|
69354
|
+
}
|
|
69355
|
+
function reclaimIndex(dbPath, opts = {}) {
|
|
69356
|
+
const rebuild = opts.rebuild === true;
|
|
69357
|
+
const beforeBytes = indexSizeBytes(dbPath);
|
|
69358
|
+
const db = getDb(dbPath);
|
|
69359
|
+
const dropped = {};
|
|
69360
|
+
if (rebuild) {
|
|
69361
|
+
db.transaction(() => {
|
|
69362
|
+
for (const table of DERIVED_TABLES) {
|
|
69363
|
+
if (!tableExists(db, table)) continue;
|
|
69364
|
+
const before = db.prepare(`SELECT count(*) AS c FROM "${table}"`).get().c;
|
|
69365
|
+
db.prepare(`DELETE FROM "${table}"`).run();
|
|
69366
|
+
dropped[table] = before;
|
|
69367
|
+
}
|
|
69368
|
+
})();
|
|
69369
|
+
if (tableExists(db, "symbols_fts")) {
|
|
69370
|
+
try {
|
|
69371
|
+
db.prepare(`INSERT INTO symbols_fts(symbols_fts) VALUES('rebuild')`).run();
|
|
69372
|
+
} catch {
|
|
69373
|
+
}
|
|
69374
|
+
}
|
|
69375
|
+
}
|
|
69376
|
+
const checkpointBusy = walCheckpointBusy(db);
|
|
69377
|
+
const vacuumDeferred = !vacuumOrDefer(db);
|
|
69378
|
+
const finalCheckpointBusy = walCheckpointBusy(db);
|
|
69379
|
+
return {
|
|
69380
|
+
beforeBytes,
|
|
69381
|
+
afterBytes: indexSizeBytes(dbPath),
|
|
69382
|
+
dropped,
|
|
69383
|
+
rebuilt: rebuild,
|
|
69384
|
+
checkpointBusy: checkpointBusy || finalCheckpointBusy,
|
|
69385
|
+
vacuumDeferred
|
|
69386
|
+
};
|
|
69387
|
+
}
|
|
69388
|
+
function vacuumOrDefer(db) {
|
|
69389
|
+
try {
|
|
69390
|
+
db.exec("VACUUM");
|
|
69391
|
+
return true;
|
|
69392
|
+
} catch (err2) {
|
|
69393
|
+
const code = err2.code ?? "";
|
|
69394
|
+
if (!code.startsWith("SQLITE_BUSY") && !code.startsWith("SQLITE_LOCKED")) throw err2;
|
|
69395
|
+
return false;
|
|
69396
|
+
}
|
|
69397
|
+
}
|
|
69398
|
+
function walCheckpointBusy(db) {
|
|
69399
|
+
const rows = db.pragma("wal_checkpoint(TRUNCATE)");
|
|
69400
|
+
return rows[0]?.busy === 1;
|
|
69401
|
+
}
|
|
69402
|
+
function mb(bytes) {
|
|
69403
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
69404
|
+
}
|
|
69405
|
+
function cmdReclaimIndex(opts) {
|
|
69406
|
+
const dbPath = opts.dbPath ?? globalDbPath();
|
|
69407
|
+
if (opts.force !== true && isWorkerRunning(path56.dirname(dbPath))) {
|
|
69408
|
+
throw new Error(
|
|
69409
|
+
"reclaim-index: the worker daemon is running and writing to this index. Stop it first with 'token-goat worker stop', then re-run. Pass --force to proceed anyway (results may be inaccurate if the worker is really live)."
|
|
69410
|
+
);
|
|
69411
|
+
}
|
|
69412
|
+
const result = reclaimIndex(dbPath, { rebuild: opts.rebuild === true });
|
|
69413
|
+
if (opts.json === true) {
|
|
69414
|
+
process.stdout.write(JSON.stringify({ dbPath, ...result }, null, 2) + "\n");
|
|
69415
|
+
return;
|
|
69416
|
+
}
|
|
69417
|
+
const freed = result.beforeBytes - result.afterBytes;
|
|
69418
|
+
process.stdout.write(`reclaim-index: ${dbPath}
|
|
69419
|
+
`);
|
|
69420
|
+
process.stdout.write(
|
|
69421
|
+
` ${mb(result.beforeBytes)} -> ${mb(result.afterBytes)} (freed ${mb(freed)})
|
|
69422
|
+
`
|
|
69423
|
+
);
|
|
69424
|
+
if (result.rebuilt) {
|
|
69425
|
+
for (const [table, n] of Object.entries(result.dropped)) {
|
|
69426
|
+
process.stdout.write(` dropped ${n} row(s) from ${table}
|
|
69427
|
+
`);
|
|
69428
|
+
}
|
|
69429
|
+
process.stdout.write(
|
|
69430
|
+
` derived rows dropped -- run 'token-goat index' in each project to rebuild them
|
|
69431
|
+
`
|
|
69432
|
+
);
|
|
69433
|
+
}
|
|
69434
|
+
if (result.vacuumDeferred) {
|
|
69435
|
+
process.stdout.write(
|
|
69436
|
+
` note: VACUUM could not get an exclusive lock and was skipped, so on-disk size may be unchanged. The index itself was reclaimed; re-run 'token-goat reclaim-index' once nothing else is using the database to release the freed pages
|
|
69437
|
+
`
|
|
69438
|
+
);
|
|
69439
|
+
}
|
|
69440
|
+
if (result.checkpointBusy) {
|
|
69441
|
+
process.stdout.write(
|
|
69442
|
+
` note: a concurrent reader blocked WAL truncation, so some space may still be held in ${path56.basename(dbPath)}-wal
|
|
69443
|
+
`
|
|
69444
|
+
);
|
|
69445
|
+
}
|
|
69446
|
+
}
|
|
69447
|
+
|
|
69070
69448
|
// src/config_commands.ts
|
|
69071
69449
|
init_define_import_meta_env();
|
|
69072
69450
|
init_dist();
|
|
@@ -69076,13 +69454,14 @@ init_image_shrink();
|
|
|
69076
69454
|
init_project();
|
|
69077
69455
|
init_index_prune();
|
|
69078
69456
|
init_disk_cache();
|
|
69079
|
-
import * as
|
|
69457
|
+
import * as fs49 from "node:fs";
|
|
69080
69458
|
import * as os18 from "node:os";
|
|
69081
|
-
import * as
|
|
69459
|
+
import * as path57 from "node:path";
|
|
69082
69460
|
init_util2();
|
|
69083
69461
|
init_paths();
|
|
69084
69462
|
init_ansi();
|
|
69085
69463
|
init_constants();
|
|
69464
|
+
init_stats();
|
|
69086
69465
|
function emit4(text) {
|
|
69087
69466
|
const payload = colorStdout() ? text : stripAnsi(text);
|
|
69088
69467
|
process.stdout.write(ensureNewline(payload));
|
|
@@ -69091,7 +69470,7 @@ function emitErr4(text) {
|
|
|
69091
69470
|
process.stderr.write(ensureNewline(text));
|
|
69092
69471
|
}
|
|
69093
69472
|
function saveConfigSafe(cfg) {
|
|
69094
|
-
ensureDirSync(
|
|
69473
|
+
ensureDirSync(path57.dirname(configPath()));
|
|
69095
69474
|
saveConfig(cfg);
|
|
69096
69475
|
}
|
|
69097
69476
|
function levenshtein(a, b, cap = 3) {
|
|
@@ -69251,7 +69630,7 @@ function cmdConfig(opts) {
|
|
|
69251
69630
|
const parseErrAtLoad = getLastConfigParseError();
|
|
69252
69631
|
if (parseErrAtLoad !== null) {
|
|
69253
69632
|
try {
|
|
69254
|
-
|
|
69633
|
+
fs49.copyFileSync(configPath(), `${configPath()}.bak`);
|
|
69255
69634
|
emitErr4(`config set: warning: config.toml failed to parse (${parseErrAtLoad}); backed up the original to config.toml.bak and rewriting it from defaults`);
|
|
69256
69635
|
} catch {
|
|
69257
69636
|
}
|
|
@@ -69287,8 +69666,8 @@ function cmdConfig(opts) {
|
|
|
69287
69666
|
saveConfigSafe(cfg);
|
|
69288
69667
|
return coercedValue;
|
|
69289
69668
|
};
|
|
69290
|
-
ensureDirSync(
|
|
69291
|
-
const lockPath =
|
|
69669
|
+
ensureDirSync(path57.dirname(configPath()));
|
|
69670
|
+
const lockPath = path57.join(path57.dirname(configPath()), ".config.lock");
|
|
69292
69671
|
const lockResult = withFileLock(lockPath, applySet, { waitMs: LOCK_WAIT_MS_HARDENED });
|
|
69293
69672
|
const coerced = lockResult === void 0 ? applySet() : lockResult;
|
|
69294
69673
|
invalidateConfigCache();
|
|
@@ -69316,7 +69695,7 @@ function cmdConfig(opts) {
|
|
|
69316
69695
|
let raw = {};
|
|
69317
69696
|
let parseErr = null;
|
|
69318
69697
|
try {
|
|
69319
|
-
const text =
|
|
69698
|
+
const text = fs49.readFileSync(cfgFile, "utf8");
|
|
69320
69699
|
raw = parse(text);
|
|
69321
69700
|
} catch (e) {
|
|
69322
69701
|
const code = e.code;
|
|
@@ -69399,7 +69778,7 @@ function cmdProject(opts) {
|
|
|
69399
69778
|
emitErr4("project exclude requires a path argument");
|
|
69400
69779
|
throw new Error("missing path");
|
|
69401
69780
|
}
|
|
69402
|
-
const target =
|
|
69781
|
+
const target = path57.resolve(opts.pathArg);
|
|
69403
69782
|
const cfg = loadPersistedConfig();
|
|
69404
69783
|
const targetFolded = foldPath(normalizePath(target));
|
|
69405
69784
|
if (cfg.worker.blocked_roots.some((r) => foldPath(normalizePath(r)) === targetFolded)) {
|
|
@@ -69421,7 +69800,7 @@ function cmdProject(opts) {
|
|
|
69421
69800
|
const before = cfg.worker.blocked_roots;
|
|
69422
69801
|
const after = before.filter((r) => {
|
|
69423
69802
|
try {
|
|
69424
|
-
return
|
|
69803
|
+
return fs49.existsSync(r);
|
|
69425
69804
|
} catch {
|
|
69426
69805
|
return false;
|
|
69427
69806
|
}
|
|
@@ -69463,19 +69842,27 @@ function cmdProject(opts) {
|
|
|
69463
69842
|
emitErr4(`project: unknown action '${action}'. Use list, exclude, or prune.`);
|
|
69464
69843
|
throw new Error(`unknown project action: ${action}`);
|
|
69465
69844
|
}
|
|
69845
|
+
function recordCompactDocStat(fullSourceBytes, emittedText, detail) {
|
|
69846
|
+
const bytesSaved = Math.max(1, fullSourceBytes - Buffer.byteLength(emittedText, "utf8"));
|
|
69847
|
+
recordStat("compact_doc", bytesSaved, Math.round(bytesSaved / 4), void 0, detail);
|
|
69848
|
+
}
|
|
69466
69849
|
function cmdCompactDoc(opts) {
|
|
69467
|
-
const resolved =
|
|
69850
|
+
const resolved = path57.resolve(opts.filePath);
|
|
69468
69851
|
if (opts.heading !== void 0) {
|
|
69469
69852
|
const result = compactDoc(resolved, opts.heading);
|
|
69470
69853
|
if (result === null) {
|
|
69471
69854
|
emitErr4(`compact-doc: could not read or compact '${resolved}'`);
|
|
69472
69855
|
throw new Error(`could not compact: ${resolved}`);
|
|
69473
69856
|
}
|
|
69857
|
+
const legacyFullBytes = fs49.statSync(resolved).size;
|
|
69474
69858
|
if (opts.json === true) {
|
|
69475
|
-
|
|
69859
|
+
const jsonText = JSON.stringify({ path: resolved, compact: result }, null, 2);
|
|
69860
|
+
emit4(jsonText);
|
|
69861
|
+
recordCompactDocStat(legacyFullBytes, jsonText, resolved);
|
|
69476
69862
|
return;
|
|
69477
69863
|
}
|
|
69478
69864
|
emit4(result);
|
|
69865
|
+
recordCompactDocStat(legacyFullBytes, result, resolved);
|
|
69479
69866
|
return;
|
|
69480
69867
|
}
|
|
69481
69868
|
let sentences;
|
|
@@ -69494,7 +69881,7 @@ function cmdCompactDoc(opts) {
|
|
|
69494
69881
|
if (opts.force === true || opts.sentences !== void 0 || !fresh) {
|
|
69495
69882
|
let sourceText;
|
|
69496
69883
|
try {
|
|
69497
|
-
sourceText =
|
|
69884
|
+
sourceText = fs49.readFileSync(resolved, "utf-8");
|
|
69498
69885
|
} catch {
|
|
69499
69886
|
emitErr4(`compact-doc: could not read or compact '${resolved}'`);
|
|
69500
69887
|
throw new Error(`could not compact: ${resolved}`);
|
|
@@ -69510,12 +69897,16 @@ function cmdCompactDoc(opts) {
|
|
|
69510
69897
|
}
|
|
69511
69898
|
body = existing;
|
|
69512
69899
|
}
|
|
69900
|
+
const extractiveFullBytes = fs49.statSync(resolved).size;
|
|
69513
69901
|
if (opts.json === true) {
|
|
69514
|
-
|
|
69902
|
+
const jsonText = JSON.stringify({ path: resolved, compactPath, rebuilt, compact: body }, null, 2);
|
|
69903
|
+
emit4(jsonText);
|
|
69904
|
+
recordCompactDocStat(extractiveFullBytes, jsonText, resolved);
|
|
69515
69905
|
return;
|
|
69516
69906
|
}
|
|
69517
69907
|
if (opts.show === true) {
|
|
69518
69908
|
emit4(body);
|
|
69909
|
+
recordCompactDocStat(extractiveFullBytes, body, resolved);
|
|
69519
69910
|
return;
|
|
69520
69911
|
}
|
|
69521
69912
|
emit4(
|
|
@@ -69563,7 +69954,7 @@ async function cmdFetchImage(opts) {
|
|
|
69563
69954
|
throw new Error(`fetch failed: ${opts.url}`, { cause: e });
|
|
69564
69955
|
}
|
|
69565
69956
|
const buf = fetched.body;
|
|
69566
|
-
const outPath = opts.out ??
|
|
69957
|
+
const outPath = opts.out ?? path57.join(os18.tmpdir(), `tg-fetch-${Date.now()}${extensionForContentType(fetched.contentType)}`);
|
|
69567
69958
|
const originalBytes = buf.length;
|
|
69568
69959
|
let shrunkBytes;
|
|
69569
69960
|
let outData;
|
|
@@ -69652,8 +70043,8 @@ init_cli_context_stats();
|
|
|
69652
70043
|
init_memory_prune();
|
|
69653
70044
|
init_project();
|
|
69654
70045
|
init_confirm_apply();
|
|
69655
|
-
import * as
|
|
69656
|
-
import * as
|
|
70046
|
+
import * as fs50 from "node:fs";
|
|
70047
|
+
import * as path58 from "node:path";
|
|
69657
70048
|
function removeExactDupLines(text, report) {
|
|
69658
70049
|
if (report.exactDupLines.length === 0) return text;
|
|
69659
70050
|
const toRemove = new Set(report.exactDupLines.map(([, dupIdx]) => dupIdx));
|
|
@@ -69711,7 +70102,7 @@ function printReport(reports, clusters) {
|
|
|
69711
70102
|
} else {
|
|
69712
70103
|
for (const cluster of clusters) {
|
|
69713
70104
|
w(
|
|
69714
|
-
` [${cluster.method}, similarity ${cluster.similarity}, ~${cluster.tokens} tok] ${cluster.members.map((m) =>
|
|
70105
|
+
` [${cluster.method}, similarity ${cluster.similarity}, ~${cluster.tokens} tok] ${cluster.members.map((m) => path58.basename(m)).join(", ")}
|
|
69715
70106
|
`
|
|
69716
70107
|
);
|
|
69717
70108
|
}
|
|
@@ -69726,7 +70117,7 @@ async function runMemoryCommand(opts = {}) {
|
|
|
69726
70117
|
const claudeMds = findClaudeMdFiles(projectRoot);
|
|
69727
70118
|
const reports = auditClaudeMd(claudeMds);
|
|
69728
70119
|
const memoryMdPath = findMemoryMd(projectRoot);
|
|
69729
|
-
const clusters = memoryMdPath !== null ? await findContentDuplicates(
|
|
70120
|
+
const clusters = memoryMdPath !== null ? await findContentDuplicates(path58.dirname(memoryMdPath)) : [];
|
|
69730
70121
|
printReport(reports, clusters);
|
|
69731
70122
|
if (opts.fix !== true) return;
|
|
69732
70123
|
const changes = [];
|
|
@@ -69734,7 +70125,7 @@ async function runMemoryCommand(opts = {}) {
|
|
|
69734
70125
|
if (report.exactDupLines.length === 0) continue;
|
|
69735
70126
|
let before;
|
|
69736
70127
|
try {
|
|
69737
|
-
before =
|
|
70128
|
+
before = fs50.readFileSync(report.path, "utf-8");
|
|
69738
70129
|
} catch {
|
|
69739
70130
|
continue;
|
|
69740
70131
|
}
|
|
@@ -69773,34 +70164,34 @@ async function runMemoryCommand(opts = {}) {
|
|
|
69773
70164
|
// src/cli_waste.ts
|
|
69774
70165
|
init_define_import_meta_env();
|
|
69775
70166
|
init_project();
|
|
69776
|
-
import * as
|
|
69777
|
-
import * as
|
|
70167
|
+
import * as fs52 from "node:fs";
|
|
70168
|
+
import * as path60 from "node:path";
|
|
69778
70169
|
|
|
69779
70170
|
// src/waste.ts
|
|
69780
70171
|
init_define_import_meta_env();
|
|
69781
70172
|
init_overflow_guard();
|
|
69782
|
-
import * as
|
|
70173
|
+
import * as fs51 from "node:fs";
|
|
69783
70174
|
import * as os19 from "node:os";
|
|
69784
|
-
import * as
|
|
70175
|
+
import * as path59 from "node:path";
|
|
69785
70176
|
function projectTranscriptsDir(projectRoot) {
|
|
69786
|
-
const rootStr =
|
|
70177
|
+
const rootStr = path59.resolve(projectRoot);
|
|
69787
70178
|
const slug = rootStr.replace(/[^A-Za-z0-9]/g, "-");
|
|
69788
|
-
return
|
|
70179
|
+
return path59.join(os19.homedir(), ".claude", "projects", slug);
|
|
69789
70180
|
}
|
|
69790
70181
|
function findLatestTranscript(projectRoot) {
|
|
69791
70182
|
const dir = projectTranscriptsDir(projectRoot);
|
|
69792
70183
|
let entries;
|
|
69793
70184
|
try {
|
|
69794
|
-
entries =
|
|
70185
|
+
entries = fs51.readdirSync(dir).filter((f) => f.endsWith(".jsonl"));
|
|
69795
70186
|
} catch {
|
|
69796
70187
|
return null;
|
|
69797
70188
|
}
|
|
69798
70189
|
let best = null;
|
|
69799
70190
|
for (const name2 of entries) {
|
|
69800
|
-
const full =
|
|
70191
|
+
const full = path59.join(dir, name2);
|
|
69801
70192
|
let stat2;
|
|
69802
70193
|
try {
|
|
69803
|
-
stat2 =
|
|
70194
|
+
stat2 = fs51.statSync(full);
|
|
69804
70195
|
} catch {
|
|
69805
70196
|
continue;
|
|
69806
70197
|
}
|
|
@@ -69857,7 +70248,7 @@ function extractResultText(content) {
|
|
|
69857
70248
|
return "";
|
|
69858
70249
|
}
|
|
69859
70250
|
function parseTranscript2(transcriptPath) {
|
|
69860
|
-
const raw =
|
|
70251
|
+
const raw = fs51.readFileSync(transcriptPath, "utf-8");
|
|
69861
70252
|
const calls = [];
|
|
69862
70253
|
const resultTextById = /* @__PURE__ */ new Map();
|
|
69863
70254
|
let seq = 0;
|
|
@@ -70050,7 +70441,7 @@ function printReport2(report) {
|
|
|
70050
70441
|
}
|
|
70051
70442
|
async function runWasteCommand(opts = {}) {
|
|
70052
70443
|
const projectRoot = resolveProjectRoot(opts.project !== void 0 ? { project: opts.project } : {});
|
|
70053
|
-
const transcriptPath = opts.transcript !== void 0 ?
|
|
70444
|
+
const transcriptPath = opts.transcript !== void 0 ? path60.resolve(opts.transcript) : findLatestTranscript(projectRoot);
|
|
70054
70445
|
if (transcriptPath === null) {
|
|
70055
70446
|
if (opts.json === true) {
|
|
70056
70447
|
process.stdout.write(`${JSON.stringify({ error: "no session transcript found", project: projectRoot })}
|
|
@@ -70064,7 +70455,7 @@ async function runWasteCommand(opts = {}) {
|
|
|
70064
70455
|
process.exitCode = 1;
|
|
70065
70456
|
return;
|
|
70066
70457
|
}
|
|
70067
|
-
if (!
|
|
70458
|
+
if (!fs52.existsSync(transcriptPath)) {
|
|
70068
70459
|
process.stderr.write(`token-goat: transcript not found: ${transcriptPath}
|
|
70069
70460
|
`);
|
|
70070
70461
|
process.exitCode = 1;
|
|
@@ -70082,18 +70473,18 @@ async function runWasteCommand(opts = {}) {
|
|
|
70082
70473
|
// src/session_read.ts
|
|
70083
70474
|
init_define_import_meta_env();
|
|
70084
70475
|
init_compact();
|
|
70085
|
-
import * as
|
|
70086
|
-
import * as
|
|
70476
|
+
import * as fs53 from "node:fs";
|
|
70477
|
+
import * as path61 from "node:path";
|
|
70087
70478
|
import * as readline2 from "node:readline";
|
|
70088
70479
|
init_project();
|
|
70089
70480
|
function resolveSessionTranscript(arg, opts = {}) {
|
|
70090
70481
|
if (arg !== void 0 && arg !== "") {
|
|
70091
|
-
if (
|
|
70482
|
+
if (fs53.existsSync(arg) && fs53.statSync(arg).isFile()) return arg;
|
|
70092
70483
|
const projectRoot2 = resolveProjectRoot(opts.project !== void 0 ? { project: opts.project } : {});
|
|
70093
70484
|
const dir = projectTranscriptsDir(projectRoot2);
|
|
70094
70485
|
const byId = arg.endsWith(".jsonl") ? arg : `${arg}.jsonl`;
|
|
70095
|
-
const candidate =
|
|
70096
|
-
if (
|
|
70486
|
+
const candidate = path61.join(dir, byId);
|
|
70487
|
+
if (fs53.existsSync(candidate) && fs53.statSync(candidate).isFile()) return candidate;
|
|
70097
70488
|
return null;
|
|
70098
70489
|
}
|
|
70099
70490
|
const projectRoot = resolveProjectRoot(opts.project !== void 0 ? { project: opts.project } : {});
|
|
@@ -70151,7 +70542,7 @@ function toolCallsForBlocks(blocks) {
|
|
|
70151
70542
|
return blocks.filter((b) => b.type === "tool_use" && b.name !== void 0).map((b) => b.name);
|
|
70152
70543
|
}
|
|
70153
70544
|
async function* streamTurns(transcriptPath) {
|
|
70154
|
-
const input =
|
|
70545
|
+
const input = fs53.createReadStream(transcriptPath, { encoding: "utf8" });
|
|
70155
70546
|
const rl = readline2.createInterface({ input, crlfDelay: Infinity });
|
|
70156
70547
|
try {
|
|
70157
70548
|
let lineNumber = 0;
|
|
@@ -70252,15 +70643,15 @@ function formatSessionSlice(turns) {
|
|
|
70252
70643
|
init_define_import_meta_env();
|
|
70253
70644
|
init_project();
|
|
70254
70645
|
init_disk_cache();
|
|
70255
|
-
import * as
|
|
70256
|
-
import * as
|
|
70646
|
+
import * as fs54 from "node:fs";
|
|
70647
|
+
import * as path62 from "node:path";
|
|
70257
70648
|
function readMcpConfig(projectRoot) {
|
|
70258
|
-
const configPath2 =
|
|
70649
|
+
const configPath2 = path62.join(projectRoot, ".mcp.json");
|
|
70259
70650
|
try {
|
|
70260
|
-
if (!
|
|
70651
|
+
if (!fs54.existsSync(configPath2)) {
|
|
70261
70652
|
return null;
|
|
70262
70653
|
}
|
|
70263
|
-
const content =
|
|
70654
|
+
const content = fs54.readFileSync(configPath2, "utf-8");
|
|
70264
70655
|
const parsed = JSON.parse(content);
|
|
70265
70656
|
return parsed.mcpServers || parsed;
|
|
70266
70657
|
} catch {
|
|
@@ -70569,8 +70960,8 @@ function requirePositiveInt(flag, raw) {
|
|
|
70569
70960
|
}
|
|
70570
70961
|
async function cmdSemantic(query, opts) {
|
|
70571
70962
|
const limit = opts.limit !== void 0 ? requireNonNegativeInt("--limit", opts.limit) : 20;
|
|
70572
|
-
const { text, code } = await runSemantic(query, { limit });
|
|
70573
|
-
(code === 0 ? out : err)(text);
|
|
70963
|
+
const { text, code } = await runSemantic(query, { limit, ...opts.json === true ? { json: true } : {} });
|
|
70964
|
+
(opts.json === true || code === 0 ? out : err)(text);
|
|
70574
70965
|
process.exitCode = code;
|
|
70575
70966
|
}
|
|
70576
70967
|
async function cmdIndex(pathArg, opts = {}) {
|
|
@@ -70584,7 +70975,13 @@ async function cmdIndex(pathArg, opts = {}) {
|
|
|
70584
70975
|
`no tracked files found under '${root}' (is it a git repo?). Pass --walk to index a non-git folder.`
|
|
70585
70976
|
);
|
|
70586
70977
|
}
|
|
70587
|
-
files = collectWalkIndexFiles(root);
|
|
70978
|
+
files = collectWalkIndexFiles(root, { force: opts.forceWalk === true });
|
|
70979
|
+
if (opts.forceWalk === true) {
|
|
70980
|
+
process.stderr.write(
|
|
70981
|
+
`token-goat: --force-walk raised the walk cap to ${MAX_FILES_SCANNED_FORCED} files; indexing ${files.length} files may take a long time and produce a large index. Run 'token-goat doctor' afterwards to check index size.
|
|
70982
|
+
`
|
|
70983
|
+
);
|
|
70984
|
+
}
|
|
70588
70985
|
}
|
|
70589
70986
|
const blockedRoots = loadConfig().worker.blocked_roots;
|
|
70590
70987
|
const ixCfg = loadConfig().indexing;
|
|
@@ -70671,8 +71068,8 @@ async function cmdMcpServe() {
|
|
|
70671
71068
|
const server = createMcpServer2();
|
|
70672
71069
|
const transport = new StdioServerTransport();
|
|
70673
71070
|
await server.connect(transport);
|
|
70674
|
-
await new Promise((
|
|
70675
|
-
server.server.onclose =
|
|
71071
|
+
await new Promise((resolve21) => {
|
|
71072
|
+
server.server.onclose = resolve21;
|
|
70676
71073
|
});
|
|
70677
71074
|
}
|
|
70678
71075
|
async function cmdHook(event, opts) {
|
|
@@ -70689,6 +71086,9 @@ async function cmdInstall(opts) {
|
|
|
70689
71086
|
out(
|
|
70690
71087
|
claudeMdResult.alreadyInstalled ? `CLAUDE.md block already up to date \u2192 ${claudeMdResult.path}` : `Updated CLAUDE.md \u2192 ${claudeMdResult.path}`
|
|
70691
71088
|
);
|
|
71089
|
+
for (const stray of findStrayClaudeMdBlocks()) {
|
|
71090
|
+
out(`WARNING: stray token-goat block in ${stray} \u2014 not managed by install/uninstall; delete it to avoid duplicate, stale guidance.`);
|
|
71091
|
+
}
|
|
70692
71092
|
const skillResult = installSkill();
|
|
70693
71093
|
out(
|
|
70694
71094
|
skillResult.alreadyInstalled ? `token-goat skill already up to date \u2192 ${skillResult.path}` : `Installed token-goat skill \u2192 ${skillResult.path}`
|
|
@@ -70738,7 +71138,7 @@ async function cmdInstall(opts) {
|
|
|
70738
71138
|
if (copilotResult.alreadyInstalled) {
|
|
70739
71139
|
out(`Copilot CLI integration already installed \u2192 ${copilotResult.configPath}`);
|
|
70740
71140
|
} else {
|
|
70741
|
-
out(`Installed token-goat Copilot CLI integration \u2192 ${copilotResult.configPath}, ${copilotResult.scriptPath}`);
|
|
71141
|
+
out(`Installed token-goat Copilot CLI integration \u2192 ${copilotResult.configPath}, ${copilotResult.scriptPath}, ${copilotResult.instructionsPath}`);
|
|
70742
71142
|
}
|
|
70743
71143
|
}
|
|
70744
71144
|
if (opts.opencode === true) {
|
|
@@ -70763,16 +71163,16 @@ async function cmdInstall(opts) {
|
|
|
70763
71163
|
);
|
|
70764
71164
|
}
|
|
70765
71165
|
try {
|
|
70766
|
-
const skillDir2 =
|
|
70767
|
-
if (
|
|
70768
|
-
const entries =
|
|
71166
|
+
const skillDir2 = path63.join(homedir17(), ".claude", "skills");
|
|
71167
|
+
if (fs55.existsSync(skillDir2)) {
|
|
71168
|
+
const entries = fs55.readdirSync(skillDir2, { withFileTypes: true });
|
|
70769
71169
|
const skillNames = [];
|
|
70770
71170
|
const sessionId = getSessionId();
|
|
70771
71171
|
for (const entry of entries) {
|
|
70772
71172
|
if (!entry.isDirectory()) continue;
|
|
70773
|
-
const skillFile =
|
|
70774
|
-
if (
|
|
70775
|
-
const body =
|
|
71173
|
+
const skillFile = path63.join(skillDir2, entry.name, "SKILL.md");
|
|
71174
|
+
if (fs55.existsSync(skillFile)) {
|
|
71175
|
+
const body = fs55.readFileSync(skillFile, "utf-8");
|
|
70776
71176
|
const compact = extractCompactFromMarker(body);
|
|
70777
71177
|
if (compact === null) continue;
|
|
70778
71178
|
const sourceSha = contentHash(body);
|
|
@@ -70782,10 +71182,10 @@ async function cmdInstall(opts) {
|
|
|
70782
71182
|
}
|
|
70783
71183
|
if (skillNames.length > 0) {
|
|
70784
71184
|
const dir = skillOutputsDir();
|
|
70785
|
-
await
|
|
70786
|
-
const pregenPath =
|
|
71185
|
+
await fs55.promises.mkdir(dir, { recursive: true });
|
|
71186
|
+
const pregenPath = path63.join(dir, "pregen.json");
|
|
70787
71187
|
const pregenData = { ts: Date.now(), names: skillNames };
|
|
70788
|
-
await
|
|
71188
|
+
await fs55.promises.writeFile(pregenPath, JSON.stringify(pregenData, null, 2));
|
|
70789
71189
|
out(`Pre-generated ${skillNames.length} skill compacts.`);
|
|
70790
71190
|
}
|
|
70791
71191
|
}
|
|
@@ -70798,6 +71198,9 @@ function cmdUninstall(opts) {
|
|
|
70798
71198
|
out(removed ? `Removed token-goat hooks (${scope}).` : `No token-goat hooks to remove (${scope}).`);
|
|
70799
71199
|
const claudeMdRemoved = uninstallClaudeMd();
|
|
70800
71200
|
out(claudeMdRemoved ? "Removed token-goat block from CLAUDE.md." : "No token-goat block in CLAUDE.md to remove.");
|
|
71201
|
+
for (const stray of findStrayClaudeMdBlocks()) {
|
|
71202
|
+
out(`NOTE: a token-goat block remains in ${stray} \u2014 outside CLAUDE.md, so it was not removed. Delete it manually if unwanted.`);
|
|
71203
|
+
}
|
|
70801
71204
|
const skillRemoved = uninstallSkill();
|
|
70802
71205
|
out(skillRemoved ? "Removed token-goat skill." : "No token-goat skill to remove.");
|
|
70803
71206
|
const removals = [
|
|
@@ -70900,7 +71303,7 @@ ${formatSessionOutline(turns)}`;
|
|
|
70900
71303
|
}
|
|
70901
71304
|
function sessionTranscriptSize(transcriptPath) {
|
|
70902
71305
|
try {
|
|
70903
|
-
return
|
|
71306
|
+
return fs55.statSync(transcriptPath).size;
|
|
70904
71307
|
} catch {
|
|
70905
71308
|
return 0;
|
|
70906
71309
|
}
|
|
@@ -71004,7 +71407,7 @@ function _applyFiltersAndPrint(content, opts) {
|
|
|
71004
71407
|
}
|
|
71005
71408
|
function fileSizeOrZero(filePath) {
|
|
71006
71409
|
try {
|
|
71007
|
-
return
|
|
71410
|
+
return fs55.statSync(filePath).size;
|
|
71008
71411
|
} catch {
|
|
71009
71412
|
return 0;
|
|
71010
71413
|
}
|
|
@@ -71019,11 +71422,11 @@ function cmdBashOutput(id, opts) {
|
|
|
71019
71422
|
}
|
|
71020
71423
|
let content;
|
|
71021
71424
|
try {
|
|
71022
|
-
const st =
|
|
71425
|
+
const st = fs55.statSync(opts.file);
|
|
71023
71426
|
if (st.isFIFO() || st.isSocket()) {
|
|
71024
71427
|
throw new CliError(`--file '${opts.file}' is a special file (FIFO or socket) \u2014 only regular files are supported`);
|
|
71025
71428
|
}
|
|
71026
|
-
content =
|
|
71429
|
+
content = fs55.readFileSync(opts.file, "utf-8");
|
|
71027
71430
|
} catch (e) {
|
|
71028
71431
|
if (e instanceof CliError) throw e;
|
|
71029
71432
|
throw new CliError(`cannot read file: ${opts.file}`);
|
|
@@ -71359,7 +71762,7 @@ async function cmdSkillBody(name2, opts) {
|
|
|
71359
71762
|
if (filePath === null) {
|
|
71360
71763
|
throw new CliError(`skill '${name2}' not found`);
|
|
71361
71764
|
}
|
|
71362
|
-
const body =
|
|
71765
|
+
const body = fs55.readFileSync(filePath, "utf-8");
|
|
71363
71766
|
if (opts.compact === true) {
|
|
71364
71767
|
out(extractCompactFromMarker(body) ?? body);
|
|
71365
71768
|
} else {
|
|
@@ -71376,7 +71779,7 @@ async function cmdSkillCompact(name2, opts) {
|
|
|
71376
71779
|
for (const skill of skills) {
|
|
71377
71780
|
const filePath = await getSkillFilePath(skill.name);
|
|
71378
71781
|
if (!filePath) continue;
|
|
71379
|
-
const body2 =
|
|
71782
|
+
const body2 = fs55.readFileSync(filePath, "utf-8");
|
|
71380
71783
|
const compact2 = extractCompactFromMarker(body2);
|
|
71381
71784
|
if (compact2 === null) continue;
|
|
71382
71785
|
const sourceSha2 = contentHash(body2);
|
|
@@ -71397,19 +71800,19 @@ async function cmdSkillCompact(name2, opts) {
|
|
|
71397
71800
|
if (!opts.path.trim()) {
|
|
71398
71801
|
throw new CliError("--path cannot be empty");
|
|
71399
71802
|
}
|
|
71400
|
-
if (!
|
|
71803
|
+
if (!fs55.existsSync(opts.path)) {
|
|
71401
71804
|
throw new CliError(`skill file not found: ${opts.path}`);
|
|
71402
71805
|
}
|
|
71403
71806
|
try {
|
|
71404
|
-
body =
|
|
71807
|
+
body = fs55.readFileSync(opts.path, "utf-8");
|
|
71405
71808
|
} catch (e) {
|
|
71406
71809
|
if (e.code === "ENOENT") {
|
|
71407
71810
|
throw new CliError(`skill file not found: ${opts.path}`);
|
|
71408
71811
|
}
|
|
71409
71812
|
throw new CliError(`failed to read skill file '${opts.path}': ${extractErrorMessage(e)}`);
|
|
71410
71813
|
}
|
|
71411
|
-
cacheName = name2 ??
|
|
71412
|
-
sourcePath =
|
|
71814
|
+
cacheName = name2 ?? path63.basename(path63.dirname(path63.resolve(opts.path)));
|
|
71815
|
+
sourcePath = path63.resolve(opts.path);
|
|
71413
71816
|
} else {
|
|
71414
71817
|
if (name2 === void 0 || !name2.trim()) {
|
|
71415
71818
|
throw new CliError("skill-compact requires a <name> or --path <file>");
|
|
@@ -71418,7 +71821,7 @@ async function cmdSkillCompact(name2, opts) {
|
|
|
71418
71821
|
if (filePath === null) {
|
|
71419
71822
|
throw new CliError(`skill '${name2}' not found`);
|
|
71420
71823
|
}
|
|
71421
|
-
body =
|
|
71824
|
+
body = fs55.readFileSync(filePath, "utf-8");
|
|
71422
71825
|
cacheName = name2;
|
|
71423
71826
|
sourcePath = filePath;
|
|
71424
71827
|
}
|
|
@@ -71527,8 +71930,8 @@ async function cmdSkillDiff(name2) {
|
|
|
71527
71930
|
}
|
|
71528
71931
|
const newer = versions[0];
|
|
71529
71932
|
const older = versions[1];
|
|
71530
|
-
const newerBody = await
|
|
71531
|
-
const olderBody = await
|
|
71933
|
+
const newerBody = await fs55.promises.readFile(path63.resolve(dir, `${newer.outputId}.txt`), "utf-8").catch(() => null);
|
|
71934
|
+
const olderBody = await fs55.promises.readFile(path63.resolve(dir, `${older.outputId}.txt`), "utf-8").catch(() => null);
|
|
71532
71935
|
if (newerBody === null || olderBody === null) {
|
|
71533
71936
|
out(`a cached version of '${name2}' was evicted while diffing -- try again`);
|
|
71534
71937
|
return;
|
|
@@ -71557,7 +71960,7 @@ async function cmdSkillSection(nameHeading, headingArg) {
|
|
|
71557
71960
|
if (!filePath) {
|
|
71558
71961
|
throw new CliError(`skill '${skillName}' not found`);
|
|
71559
71962
|
}
|
|
71560
|
-
const body =
|
|
71963
|
+
const body = fs55.readFileSync(filePath, "utf-8");
|
|
71561
71964
|
const extracted = extractNamedSection(body, heading);
|
|
71562
71965
|
if (!extracted) {
|
|
71563
71966
|
process.exitCode = 1;
|
|
@@ -71567,7 +71970,7 @@ async function cmdSkillSection(nameHeading, headingArg) {
|
|
|
71567
71970
|
}
|
|
71568
71971
|
function atomicWriteBuffer(dest, data) {
|
|
71569
71972
|
try {
|
|
71570
|
-
if (
|
|
71973
|
+
if (fs55.statSync(dest).isDirectory()) {
|
|
71571
71974
|
const e = Object.assign(new Error(`EISDIR: illegal operation on a directory, open '${dest}'`), { code: "EISDIR", path: dest });
|
|
71572
71975
|
throw e;
|
|
71573
71976
|
}
|
|
@@ -71575,23 +71978,23 @@ function atomicWriteBuffer(dest, data) {
|
|
|
71575
71978
|
if (e.code !== "ENOENT") throw e;
|
|
71576
71979
|
}
|
|
71577
71980
|
const rnd = Math.random().toString(36).slice(2, 8);
|
|
71578
|
-
const tmp =
|
|
71981
|
+
const tmp = path63.join(path63.dirname(path63.resolve(dest)), `.tmp.${process.pid}.${rnd}`);
|
|
71579
71982
|
try {
|
|
71580
|
-
|
|
71983
|
+
fs55.writeFileSync(tmp, data, { mode: 384 });
|
|
71581
71984
|
try {
|
|
71582
|
-
const destMode =
|
|
71583
|
-
|
|
71985
|
+
const destMode = fs55.statSync(dest).mode;
|
|
71986
|
+
fs55.chmodSync(tmp, destMode);
|
|
71584
71987
|
} catch (e) {
|
|
71585
71988
|
if (e.code !== "ENOENT") throw e;
|
|
71586
71989
|
}
|
|
71587
71990
|
withRetryOnLock(() => {
|
|
71588
71991
|
try {
|
|
71589
|
-
|
|
71992
|
+
fs55.renameSync(tmp, dest);
|
|
71590
71993
|
} catch (e) {
|
|
71591
71994
|
if (e.code === "EXDEV") {
|
|
71592
|
-
|
|
71995
|
+
fs55.copyFileSync(tmp, dest);
|
|
71593
71996
|
try {
|
|
71594
|
-
|
|
71997
|
+
fs55.unlinkSync(tmp);
|
|
71595
71998
|
} catch (ue) {
|
|
71596
71999
|
process.stderr.write(`token-goat write-file: warning: could not remove temp file ${tmp}: ${ue.message}
|
|
71597
72000
|
`);
|
|
@@ -71603,7 +72006,7 @@ function atomicWriteBuffer(dest, data) {
|
|
|
71603
72006
|
});
|
|
71604
72007
|
} catch (e) {
|
|
71605
72008
|
try {
|
|
71606
|
-
|
|
72009
|
+
fs55.unlinkSync(tmp);
|
|
71607
72010
|
} catch {
|
|
71608
72011
|
}
|
|
71609
72012
|
throw e;
|
|
@@ -71613,9 +72016,9 @@ function mapFsError(e, src, dest, srcLabel = "source") {
|
|
|
71613
72016
|
const fe = e;
|
|
71614
72017
|
if (fe.code === "ENOENT") {
|
|
71615
72018
|
const errPath = fe.path ?? "";
|
|
71616
|
-
const isSource = src !== void 0 &&
|
|
72019
|
+
const isSource = src !== void 0 && path63.resolve(errPath) === path63.resolve(src);
|
|
71617
72020
|
if (isSource) throw new CliError(`${srcLabel} file not found: ${src}`);
|
|
71618
|
-
const destDir = dest ?
|
|
72021
|
+
const destDir = dest ? path63.dirname(path63.resolve(dest)) : path63.dirname(path63.resolve(errPath || "."));
|
|
71619
72022
|
throw new CliError(`destination directory does not exist: ${destDir}`);
|
|
71620
72023
|
}
|
|
71621
72024
|
if (fe.code === "ENOTDIR") {
|
|
@@ -71626,7 +72029,7 @@ function mapFsError(e, src, dest, srcLabel = "source") {
|
|
|
71626
72029
|
}
|
|
71627
72030
|
if (fe.code === "EISDIR") {
|
|
71628
72031
|
const errPath = fe.path ?? "";
|
|
71629
|
-
const isSource = src !== void 0 && (errPath === "" ||
|
|
72032
|
+
const isSource = src !== void 0 && (errPath === "" || path63.resolve(errPath) === path63.resolve(src));
|
|
71630
72033
|
if (isSource) throw new CliError(`source is a directory, not a file: ${src}`);
|
|
71631
72034
|
throw new CliError(`destination is a directory, not a file: ${dest ?? (errPath || "(unknown)")}`);
|
|
71632
72035
|
}
|
|
@@ -71695,7 +72098,7 @@ function validateWritablePath(dest, label) {
|
|
|
71695
72098
|
throw new CliError(`${label} path contains a null byte`);
|
|
71696
72099
|
}
|
|
71697
72100
|
if (isWindows()) {
|
|
71698
|
-
const base =
|
|
72101
|
+
const base = path63.basename(dest);
|
|
71699
72102
|
const stem = base.replace(/\.[^.]*$/, "").toUpperCase();
|
|
71700
72103
|
if (WIN_RESERVED.has(stem)) {
|
|
71701
72104
|
throw new CliError(`${label} '${base}' is a reserved Windows device name`);
|
|
@@ -71725,7 +72128,7 @@ function readFileBoundedRaw(filePath, label, allowStdIn = false) {
|
|
|
71725
72128
|
throw new CliError(`${label} ${filePath} requires piped input; use ${altLabel} for interactive use`);
|
|
71726
72129
|
}
|
|
71727
72130
|
try {
|
|
71728
|
-
const st =
|
|
72131
|
+
const st = fs55.statSync(filePath);
|
|
71729
72132
|
if (st.isFIFO() || st.isSocket()) {
|
|
71730
72133
|
throw new CliError(`${label} '${filePath}' is a special file (FIFO or socket) \u2014 only regular files are supported`);
|
|
71731
72134
|
}
|
|
@@ -71733,7 +72136,7 @@ function readFileBoundedRaw(filePath, label, allowStdIn = false) {
|
|
|
71733
72136
|
if (st.size > maxBytes) {
|
|
71734
72137
|
throw new CliError(`${label} '${filePath}' exceeds size limit (${Math.round(st.size / 1024 / 1024)} MB); set TOKEN_GOAT_MAX_STDIN_MB to override`);
|
|
71735
72138
|
}
|
|
71736
|
-
return
|
|
72139
|
+
return fs55.readFileSync(filePath);
|
|
71737
72140
|
} catch (e) {
|
|
71738
72141
|
if (e instanceof CliError) throw e;
|
|
71739
72142
|
mapFsError(e, filePath, void 0, label);
|
|
@@ -71777,7 +72180,7 @@ function cmdNoteAdd(file2, opts) {
|
|
|
71777
72180
|
throw new CliError("note content must be valid UTF-8 text");
|
|
71778
72181
|
}
|
|
71779
72182
|
const resolvedPath = resolveIndexPath(file2);
|
|
71780
|
-
if (!
|
|
72183
|
+
if (!fs55.existsSync(resolvedPath)) {
|
|
71781
72184
|
throw new CliError(`File not found: '${resolvedPath}'`);
|
|
71782
72185
|
}
|
|
71783
72186
|
healStaleIndex(resolvedPath);
|
|
@@ -71834,7 +72237,7 @@ function cmdWriteFile(dest, opts) {
|
|
|
71834
72237
|
throw new CliError(`TOKEN_GOAT_MAX_STDIN_MB must be a positive integer; got '${process.env["TOKEN_GOAT_MAX_STDIN_MB"] ?? ""}'`);
|
|
71835
72238
|
}
|
|
71836
72239
|
const maxBytes = maxMB * 1024 * 1024;
|
|
71837
|
-
return new Promise((
|
|
72240
|
+
return new Promise((resolve21, reject) => {
|
|
71838
72241
|
const chunks = [];
|
|
71839
72242
|
let totalBytes = 0;
|
|
71840
72243
|
let settled = false;
|
|
@@ -71858,7 +72261,7 @@ function cmdWriteFile(dest, opts) {
|
|
|
71858
72261
|
try {
|
|
71859
72262
|
atomicWriteBuffer(dest, Buffer.concat(chunks));
|
|
71860
72263
|
enqueueDirtyPathSafe(dest);
|
|
71861
|
-
|
|
72264
|
+
resolve21();
|
|
71862
72265
|
} catch (e) {
|
|
71863
72266
|
try {
|
|
71864
72267
|
mapFsError(e, void 0, dest);
|
|
@@ -71961,7 +72364,7 @@ function cmdReplace(file2, opts) {
|
|
|
71961
72364
|
const targetBuf = readFileBoundedRaw(file2, "target file", true);
|
|
71962
72365
|
let preWriteStat;
|
|
71963
72366
|
try {
|
|
71964
|
-
preWriteStat =
|
|
72367
|
+
preWriteStat = fs55.statSync(file2);
|
|
71965
72368
|
} catch {
|
|
71966
72369
|
}
|
|
71967
72370
|
const usingFrom = opts.oldFrom !== void 0 || opts.newFrom !== void 0;
|
|
@@ -72030,7 +72433,7 @@ ${diff}`
|
|
|
72030
72433
|
}
|
|
72031
72434
|
let preRenameStat;
|
|
72032
72435
|
try {
|
|
72033
|
-
preRenameStat =
|
|
72436
|
+
preRenameStat = fs55.statSync(file2);
|
|
72034
72437
|
} catch {
|
|
72035
72438
|
}
|
|
72036
72439
|
if (preRenameStat !== void 0 && (preRenameStat.mtimeMs !== preWriteStat.mtimeMs || preRenameStat.size !== preWriteStat.size)) {
|
|
@@ -72061,7 +72464,7 @@ function cmdInsertSection(file2, opts) {
|
|
|
72061
72464
|
}
|
|
72062
72465
|
let preWriteStat;
|
|
72063
72466
|
try {
|
|
72064
|
-
preWriteStat =
|
|
72467
|
+
preWriteStat = fs55.statSync(file2);
|
|
72065
72468
|
} catch {
|
|
72066
72469
|
}
|
|
72067
72470
|
const result = readSection(file2, opts.after);
|
|
@@ -72073,7 +72476,7 @@ function cmdInsertSection(file2, opts) {
|
|
|
72073
72476
|
}
|
|
72074
72477
|
let rawText;
|
|
72075
72478
|
try {
|
|
72076
|
-
rawText =
|
|
72479
|
+
rawText = fs55.readFileSync(file2, "utf-8");
|
|
72077
72480
|
} catch (e) {
|
|
72078
72481
|
mapFsError(e, void 0, file2);
|
|
72079
72482
|
}
|
|
@@ -72088,7 +72491,7 @@ function cmdInsertSection(file2, opts) {
|
|
|
72088
72491
|
if (preWriteStat !== void 0) {
|
|
72089
72492
|
let preRenameStat;
|
|
72090
72493
|
try {
|
|
72091
|
-
preRenameStat =
|
|
72494
|
+
preRenameStat = fs55.statSync(file2);
|
|
72092
72495
|
} catch {
|
|
72093
72496
|
}
|
|
72094
72497
|
if (preRenameStat !== void 0 && (preRenameStat.mtimeMs !== preWriteStat.mtimeMs || preRenameStat.size !== preWriteStat.size)) {
|
|
@@ -72126,25 +72529,25 @@ ${content}`;
|
|
|
72126
72529
|
}
|
|
72127
72530
|
function expandGlobs(root, patterns, globFnOverride) {
|
|
72128
72531
|
const out2 = [];
|
|
72129
|
-
const globFn = globFnOverride ??
|
|
72532
|
+
const globFn = globFnOverride ?? fs55["globSync"];
|
|
72130
72533
|
for (const p of patterns) {
|
|
72131
72534
|
if (globFn !== void 0 && (p.includes("*") || p.includes("?") || p.includes("{"))) {
|
|
72132
72535
|
try {
|
|
72133
72536
|
const hits = globFn(p, { cwd: root });
|
|
72134
|
-
for (const h of hits) out2.push(
|
|
72537
|
+
for (const h of hits) out2.push(path63.isAbsolute(h) ? h : path63.join(root, h));
|
|
72135
72538
|
continue;
|
|
72136
72539
|
} catch {
|
|
72137
72540
|
}
|
|
72138
72541
|
}
|
|
72139
|
-
out2.push(
|
|
72542
|
+
out2.push(path63.isAbsolute(p) ? p : path63.join(root, p));
|
|
72140
72543
|
}
|
|
72141
72544
|
return out2;
|
|
72142
72545
|
}
|
|
72143
72546
|
function readIgnoreFile(root) {
|
|
72144
|
-
const ignorePath =
|
|
72547
|
+
const ignorePath = path63.join(root, ".tokengoatignore");
|
|
72145
72548
|
let raw;
|
|
72146
72549
|
try {
|
|
72147
|
-
raw =
|
|
72550
|
+
raw = fs55.readFileSync(ignorePath, "utf8");
|
|
72148
72551
|
} catch {
|
|
72149
72552
|
return void 0;
|
|
72150
72553
|
}
|
|
@@ -72185,14 +72588,14 @@ function cmdPack(patterns, opts) {
|
|
|
72185
72588
|
}
|
|
72186
72589
|
let instruction;
|
|
72187
72590
|
if (opts.instructionFile !== void 0) {
|
|
72188
|
-
instruction =
|
|
72591
|
+
instruction = fs55.readFileSync(opts.instructionFile, "utf8");
|
|
72189
72592
|
}
|
|
72190
72593
|
const formatted = formatPack(result, style, {
|
|
72191
72594
|
...opts.lineNumbers === true ? { line_numbers: true } : {},
|
|
72192
72595
|
...instruction !== void 0 ? { instruction } : {}
|
|
72193
72596
|
});
|
|
72194
72597
|
if (opts.output !== void 0) {
|
|
72195
|
-
|
|
72598
|
+
fs55.writeFileSync(opts.output, formatted, "utf8");
|
|
72196
72599
|
} else {
|
|
72197
72600
|
out(formatted);
|
|
72198
72601
|
}
|
|
@@ -72210,7 +72613,7 @@ function cmdTokens(patterns, opts) {
|
|
|
72210
72613
|
if (opts.tree === true) {
|
|
72211
72614
|
const dirs = /* @__PURE__ */ new Map();
|
|
72212
72615
|
for (const e of entries) {
|
|
72213
|
-
const dir =
|
|
72616
|
+
const dir = path63.dirname(e.rel_path);
|
|
72214
72617
|
if (!dirs.has(dir)) dirs.set(dir, []);
|
|
72215
72618
|
dirs.get(dir).push(e);
|
|
72216
72619
|
}
|
|
@@ -72220,7 +72623,7 @@ function cmdTokens(patterns, opts) {
|
|
|
72220
72623
|
const pct = result.total_tokens > 0 ? Math.round(dirTokens / result.total_tokens * 100) : 0;
|
|
72221
72624
|
lines3.push(`${dir}/ (${dirTokens} tokens, ${pct}%)`);
|
|
72222
72625
|
for (const e of dirEntries) {
|
|
72223
|
-
lines3.push(` ${
|
|
72626
|
+
lines3.push(` ${path63.basename(e.rel_path).padEnd(30)} ${String(e.tokens).padStart(8)} tokens`);
|
|
72224
72627
|
}
|
|
72225
72628
|
}
|
|
72226
72629
|
out(lines3.join("\n"));
|
|
@@ -72251,7 +72654,7 @@ function cmdBudget(patterns, opts) {
|
|
|
72251
72654
|
}
|
|
72252
72655
|
}
|
|
72253
72656
|
function cmdFailures(src, opts) {
|
|
72254
|
-
const text = src !== void 0 ?
|
|
72657
|
+
const text = src !== void 0 ? fs55.readFileSync(src, "utf8") : fs55.readFileSync(0, "utf8");
|
|
72255
72658
|
const result = extractFailures(text, opts.runner !== void 0 ? { runner: opts.runner } : {});
|
|
72256
72659
|
if (opts.delta !== true) {
|
|
72257
72660
|
out(opts.json === true ? formatFailuresJson(result) : formatFailuresText(result));
|
|
@@ -72323,7 +72726,7 @@ function buildProgram() {
|
|
|
72323
72726
|
).option("-j, --json", "output as JSON").option("--list", "list all section headings in the file instead of reading one").action(
|
|
72324
72727
|
(spec, opts) => opts.list === true ? runExit(() => runListSections({ file: spec, ...opts.json === true ? { json: true } : {} })) : runExitText(() => runSection({ spec, ...opts.json === true ? { json: true } : {} }))
|
|
72325
72728
|
);
|
|
72326
|
-
program2.command("semantic <query>").description("semantic search (falls back to full-text search)").option("-l, --limit <n>", "max results").action(guard(cmdSemantic));
|
|
72729
|
+
program2.command("semantic <query>").description("semantic search (falls back to full-text search)").option("-l, --limit <n>", "max results").option("-j, --json", "output as JSON").action(guard(cmdSemantic));
|
|
72327
72730
|
program2.command("skeleton <file>").description("list all symbols in a file without bodies").option("-j, --json", "output as JSON").option("--min-lines <n>", "only show symbols at least N lines long").option("--force-refresh", "reparse file from disk before querying (ignore stale index)").option("--stats", "add per-symbol reference count and doc-coverage flag").action(
|
|
72328
72731
|
(file2, opts) => runExitText(
|
|
72329
72732
|
() => runSkeleton({
|
|
@@ -72360,14 +72763,14 @@ function buildProgram() {
|
|
|
72360
72763
|
})
|
|
72361
72764
|
)
|
|
72362
72765
|
);
|
|
72363
|
-
program2.command("index [path]").description("parse all git-tracked files and (re)build the symbol index").option("--walk", "if not a git repo, index a bounded directory walk instead (skips .env / generated / oversized trees)").option("--force", "bypass the SHA-freshness cache and reindex every tracked file, even byte-identical ones (e.g. after a parser upgrade changes what gets extracted)").action(guard(cmdIndex));
|
|
72766
|
+
program2.command("index [path]").description("parse all git-tracked files and (re)build the symbol index").option("--walk", "if not a git repo, index a bounded directory walk instead (skips .env / generated / oversized trees)").option("--force", "bypass the SHA-freshness cache and reindex every tracked file, even byte-identical ones (e.g. after a parser upgrade changes what gets extracted)").option("--force-walk", `with --walk, raise the ${MAX_FILES_SCANNED} source-file refusal to ${MAX_FILES_SCANNED_FORCED} for a folder you know is genuinely that large (slow; produces a large index)`).action(guard(cmdIndex));
|
|
72364
72767
|
program2.command("map").description("project overview").option("-c, --compact", "compact, low-token summary").action(guard(cmdMap));
|
|
72365
72768
|
program2.command("bridges-status").description("hook-event parity matrix across every AI-harness bridge (read-only static analysis, never invokes a real harness binary)").option("--json", "emit the matrix as JSON instead of text").action(guard(cmdBridgesStatus));
|
|
72366
72769
|
program2.command("commands").description("machine-readable manifest of every registered command, its options, and its arguments").option("--json", "emit the manifest as JSON instead of text").action(guard(cmdCommands));
|
|
72367
72770
|
program2.command("mcp-serve").description("run token-goat as an MCP stdio server exposing read/symbol/section/outline/skeleton/semantic tools").action(guard(cmdMcpServe));
|
|
72368
72771
|
program2.command("hook <event>").description("hook relay entrypoint (reads JSON on stdin)").option("--harness <name>", "override harness detection for this invocation (sets TOKEN_GOAT_HARNESS_OVERRIDE)").action(guard(cmdHook));
|
|
72369
|
-
program2.command("install").description("install hooks into Claude Code settings").option("-p, --project", "install into project scope instead of user scope").option("--codex", "also patch Codex CLI (~/.codex/config.toml, ~/.codex/AGENTS.md)").option("--gemini", "also patch Gemini CLI (~/.gemini/settings.json)").option("--qwen", "also patch Qwen Code (~/.qwen/settings.json)").option("--pi", "also drop a pi (pi-coding-agent) extension (~/.pi/agent/extensions/token-goat.ts)").option("--opencode", "also drop an opencode plugin (~/.config/opencode/plugins/token-goat.ts, %APPDATA%\\opencode\\plugins\\token-goat.ts on Windows)").option("--hermes", "verify token-goat hooks are present for Hermes Agent (writes nothing new)").option("--openclaw", "also register an OpenClaw plugin (~/.openclaw/openclaw.json, ~/.openclaw/plugins/token-goat.ts)").option("--copilot", "also register a Copilot CLI hook config (~/.copilot/hooks/token-goat.json, ~/.copilot/hooks/token-goat-shim.js)").option("--grok", "also register a Grok CLI (xAI Grok Build) hook config (~/.grok/hooks/token-goat.json, ~/.grok/hooks/token-goat-shim.js)").option("--local", "with --pi, install the project-local extension (<project>/.pi/extensions/token-goat.ts) instead of the global one").action(guard(cmdInstall));
|
|
72370
|
-
program2.command("uninstall").description("remove token-goat hooks from Claude Code settings").option("-p, --project", "uninstall from project scope instead of user scope").option("--codex", "also strip the Codex CLI integration (~/.codex/config.toml, ~/.codex/AGENTS.md)").option("--gemini", "also strip the Gemini CLI integration (~/.gemini/settings.json)").option("--qwen", "also strip the Qwen Code integration (~/.qwen/settings.json)").option("--pi", "also remove the pi (pi-coding-agent) extension").option("--opencode", "also remove the opencode plugin").option("--hermes", "no-op verification flag for symmetry with install (removes no files)").option("--openclaw", "also remove the OpenClaw plugin and config entry").option("--copilot", "also remove the Copilot CLI hook config and shim script").option("--grok", "also remove the Grok CLI hook config and shim script").option("--local", "with --pi, remove the project-local extension instead of the global one").action(guard(cmdUninstall));
|
|
72772
|
+
program2.command("install").description("install hooks into Claude Code settings").option("-p, --project", "install into project scope instead of user scope").option("--codex", "also patch Codex CLI (~/.codex/config.toml, ~/.codex/AGENTS.md)").option("--gemini", "also patch Gemini CLI (~/.gemini/settings.json)").option("--qwen", "also patch Qwen Code (~/.qwen/settings.json)").option("--pi", "also drop a pi (pi-coding-agent) extension (~/.pi/agent/extensions/token-goat.ts)").option("--opencode", "also drop an opencode plugin (~/.config/opencode/plugins/token-goat.ts, %APPDATA%\\opencode\\plugins\\token-goat.ts on Windows)").option("--hermes", "verify token-goat hooks are present for Hermes Agent (writes nothing new)").option("--openclaw", "also register an OpenClaw plugin (~/.openclaw/openclaw.json, ~/.openclaw/plugins/token-goat.ts)").option("--copilot", "also register a Copilot CLI hook config and routing block (~/.copilot/hooks/token-goat.json, ~/.copilot/hooks/token-goat-shim.js, ~/.copilot/copilot-instructions.md; with --local, <project>/.github/hooks/token-goat.json, <project>/.github/hooks/token-goat-shim.js, <project>/.github/copilot-instructions.md)").option("--grok", "also register a Grok CLI (xAI Grok Build) hook config (~/.grok/hooks/token-goat.json, ~/.grok/hooks/token-goat-shim.js)").option("--local", "with --pi, install the project-local extension (<project>/.pi/extensions/token-goat.ts) instead of the global one").action(guard(cmdInstall));
|
|
72773
|
+
program2.command("uninstall").description("remove token-goat hooks from Claude Code settings").option("-p, --project", "uninstall from project scope instead of user scope").option("--codex", "also strip the Codex CLI integration (~/.codex/config.toml, ~/.codex/AGENTS.md)").option("--gemini", "also strip the Gemini CLI integration (~/.gemini/settings.json)").option("--qwen", "also strip the Qwen Code integration (~/.qwen/settings.json)").option("--pi", "also remove the pi (pi-coding-agent) extension").option("--opencode", "also remove the opencode plugin").option("--hermes", "no-op verification flag for symmetry with install (removes no files)").option("--openclaw", "also remove the OpenClaw plugin and config entry").option("--copilot", "also remove the Copilot CLI hook config and shim script, and strip the token-goat block from ~/.copilot/copilot-instructions.md (or <project>/.github/copilot-instructions.md with --local)").option("--grok", "also remove the Grok CLI hook config and shim script").option("--local", "with --pi, remove the project-local extension instead of the global one").action(guard(cmdUninstall));
|
|
72371
72774
|
const worker = program2.command("worker").description("background indexer lifecycle");
|
|
72372
72775
|
worker.command("start").description("start the background indexer").action(guard(cmdWorkerStart));
|
|
72373
72776
|
worker.command("stop").description("stop the background indexer").action(guard(cmdWorkerStop));
|
|
@@ -72565,6 +72968,9 @@ function buildProgram() {
|
|
|
72565
72968
|
program2.command("bash-history").description("list cached bash output entries, newest first").option("-l, --limit <n>", "max results (default: 30)").option("-j, --json", "output as JSON").action((opts) => guard(() => cmdBashHistory(opts))());
|
|
72566
72969
|
program2.command("web-history").description("list cached web-fetch output entries, newest first").option("-l, --limit <n>", "max results (default: 30)").option("-j, --json", "output as JSON").action((opts) => guard(() => cmdWebHistory(opts))());
|
|
72567
72970
|
program2.command("mcp-history").description("list cached MCP tool result entries, newest first").option("-l, --limit <n>", "max results (default: 30)").option("-j, --json", "output as JSON").action((opts) => guard(() => cmdMcpHistory(opts))());
|
|
72971
|
+
program2.command("reclaim-index").description("shrink an oversized symbol index: VACUUM, or --rebuild to drop derived rows so the next index run re-derives them").option("--rebuild", "also drop all derived rows (files/symbols/refs/chunks) so the next `token-goat index` reparses from scratch under current parser rules").option("--db-path <path>", "index database to reclaim (default: the global index)").option("--force", "proceed even if the worker daemon appears to be running").option("-j, --json", "output as JSON").action(
|
|
72972
|
+
(opts) => guard(() => cmdReclaimIndex(opts))()
|
|
72973
|
+
);
|
|
72568
72974
|
program2.command("clean-cache").description("prune all cache subdirs to default retention limits (200 entries, 24 h)").option("-j, --json", "output as JSON").action((opts) => guard(() => cmdCleanCache(opts))());
|
|
72569
72975
|
program2.command("prune-cache").description("evict cache entries older than --max-age-hours or beyond --max-count (caller-specified bounds)").option("--max-count <n>", "max entries to keep per subdir (default: 200)").option("--max-age-hours <h>", "max age in hours to keep (default: 24)").option("-j, --json", "output as JSON").action((opts) => guard(() => cmdPruneCache(opts))());
|
|
72570
72976
|
program2.command("cache-audit").description("check settings.json hook installation and env-var gates that defeat token-goat caching").option("-j, --json", "output as JSON").action((opts) => guard(() => cmdCacheAudit(opts))());
|
|
@@ -72849,6 +73255,43 @@ function subagentStopHandler(event) {
|
|
|
72849
73255
|
registerHook("user_prompt_submit", userPromptSubmitHandler);
|
|
72850
73256
|
registerHook("subagent_stop", subagentStopHandler);
|
|
72851
73257
|
|
|
73258
|
+
// src/hooks_session_start.ts
|
|
73259
|
+
init_define_import_meta_env();
|
|
73260
|
+
init_hook_registry();
|
|
73261
|
+
init_hooks_common();
|
|
73262
|
+
init_config();
|
|
73263
|
+
init_index_reader();
|
|
73264
|
+
init_constants();
|
|
73265
|
+
var GENERIC_REMINDER = 'token-goat: prefer surgical reads over Read/Grep on this codebase -- `token-goat symbol <name>`, `token-goat read "file::symbol"`, `token-goat section "file::Heading"`, `token-goat semantic "description"`, `token-goat outline <file>`. Run `token-goat index .` if this project is not indexed yet.';
|
|
73266
|
+
function buildReminder(cwd) {
|
|
73267
|
+
if (cwd === void 0) return GENERIC_REMINDER;
|
|
73268
|
+
let symbolCount;
|
|
73269
|
+
try {
|
|
73270
|
+
symbolCount = countSymbols({ rootDir: cwd }, globalDbPath());
|
|
73271
|
+
} catch {
|
|
73272
|
+
return GENERIC_REMINDER;
|
|
73273
|
+
}
|
|
73274
|
+
if (symbolCount <= 0) return GENERIC_REMINDER;
|
|
73275
|
+
return `token-goat: this project is indexed (${symbolCount} symbols). Prefer \`symbol <name>\`, \`read "file::symbol"\`, \`section "file::Heading"\`, \`semantic "description"\`, or \`outline <file>\` over a full Read/Grep.`;
|
|
73276
|
+
}
|
|
73277
|
+
function sessionStartHandler(event) {
|
|
73278
|
+
try {
|
|
73279
|
+
if (!loadConfig().hints.session_start_reminder) return passOutput();
|
|
73280
|
+
let context = buildReminder(getCwd(event));
|
|
73281
|
+
try {
|
|
73282
|
+
const dbHealth = checkSymbolBodySize(globalDbPath());
|
|
73283
|
+
if (dbHealth.status === "warn") {
|
|
73284
|
+
context += ` token-goat: ${dbHealth.message}`;
|
|
73285
|
+
}
|
|
73286
|
+
} catch {
|
|
73287
|
+
}
|
|
73288
|
+
return contextOutput(context);
|
|
73289
|
+
} catch {
|
|
73290
|
+
return passOutput();
|
|
73291
|
+
}
|
|
73292
|
+
}
|
|
73293
|
+
registerHook("session_start", sessionStartHandler);
|
|
73294
|
+
|
|
72852
73295
|
// src/hooks_fetch.ts
|
|
72853
73296
|
init_define_import_meta_env();
|
|
72854
73297
|
init_hook_registry();
|
|
@@ -73436,7 +73879,7 @@ function ab(pa, pb, join46) {
|
|
|
73436
73879
|
return (data, i) => mapOuter(pa(data, i), (ma) => mapInner(pb(data, ma.position), (vb, j) => join46(ma.value, vb, data, i, j)));
|
|
73437
73880
|
}
|
|
73438
73881
|
function abc(pa, pb, pc, join46) {
|
|
73439
|
-
return (data, i) => mapOuter(pa(data, i), (ma) => mapOuter(pb(data, ma.position), (
|
|
73882
|
+
return (data, i) => mapOuter(pa(data, i), (ma) => mapOuter(pb(data, ma.position), (mb2) => mapInner(pc(data, mb2.position), (vc, j) => join46(ma.value, mb2.value, vc, data, i, j))));
|
|
73440
73883
|
}
|
|
73441
73884
|
function ahead(p) {
|
|
73442
73885
|
return (data, i) => mapOuter(p(data, i), (m1) => ({
|
|
@@ -77227,8 +77670,8 @@ function trimCharacterEnd(str, char) {
|
|
|
77227
77670
|
function unicodeEscape(str) {
|
|
77228
77671
|
return str.replace(/[\s\S]/g, (c) => "\\u" + c.charCodeAt().toString(16).padStart(4, "0"));
|
|
77229
77672
|
}
|
|
77230
|
-
function get(obj,
|
|
77231
|
-
for (const key of
|
|
77673
|
+
function get(obj, path64) {
|
|
77674
|
+
for (const key of path64) {
|
|
77232
77675
|
if (!obj) {
|
|
77233
77676
|
return void 0;
|
|
77234
77677
|
}
|
|
@@ -78429,8 +78872,8 @@ function withBrackets(str, brackets) {
|
|
|
78429
78872
|
const rbr = typeof brackets[1] === "string" ? brackets[1] : "]";
|
|
78430
78873
|
return lbr + str + rbr;
|
|
78431
78874
|
}
|
|
78432
|
-
function pathRewrite(
|
|
78433
|
-
const modifiedPath = typeof rewriter === "function" ? rewriter(
|
|
78875
|
+
function pathRewrite(path64, rewriter, baseUrl, metadata, elem) {
|
|
78876
|
+
const modifiedPath = typeof rewriter === "function" ? rewriter(path64, metadata, elem) : path64;
|
|
78434
78877
|
return modifiedPath[0] === "/" && baseUrl ? trimCharacterEnd(baseUrl, "/") + modifiedPath : modifiedPath;
|
|
78435
78878
|
}
|
|
78436
78879
|
function formatImage(elem, walk, builder, formatOptions) {
|
|
@@ -78754,9 +79197,9 @@ function handleDeprecatedOptions(options) {
|
|
|
78754
79197
|
options.selectors.push(...tagDefinitions);
|
|
78755
79198
|
options.selectors = mergeDuplicatesPreferLast(options.selectors, (s) => s.selector);
|
|
78756
79199
|
}
|
|
78757
|
-
function set2(obj,
|
|
78758
|
-
const valueKey =
|
|
78759
|
-
for (const key of
|
|
79200
|
+
function set2(obj, path64, value) {
|
|
79201
|
+
const valueKey = path64.pop();
|
|
79202
|
+
for (const key of path64) {
|
|
78760
79203
|
let nested = obj[key];
|
|
78761
79204
|
if (!nested) {
|
|
78762
79205
|
nested = {};
|
|
@@ -79036,9 +79479,10 @@ init_lang_patterns();
|
|
|
79036
79479
|
init_stats();
|
|
79037
79480
|
init_config();
|
|
79038
79481
|
init_parser_types();
|
|
79482
|
+
init_project();
|
|
79039
79483
|
init_util2();
|
|
79040
79484
|
init_hooks_index();
|
|
79041
|
-
import { statSync as
|
|
79485
|
+
import { statSync as statSync32, existsSync as existsSync38 } from "node:fs";
|
|
79042
79486
|
function stripCdPrefix(cmd) {
|
|
79043
79487
|
const stripped = cmd.replace(/^(?:cd\s+(?:"[^"]*"|'[^']*'|\S+)\s*&&\s*)+/, "");
|
|
79044
79488
|
return stripped.trim() || cmd;
|
|
@@ -79128,19 +79572,19 @@ var ORIG_HEAD_ELIGIBLE_GIT_RE = /^\s*git\s+(?:pull|merge|rebase)\b/i;
|
|
|
79128
79572
|
var ORIG_HEAD_REFLOG_MSG_RE = /^(merge\s|rebase\s\(|pull\s)/i;
|
|
79129
79573
|
function isTempPath(fp) {
|
|
79130
79574
|
const norm = fp.replace(/\\/g, "/");
|
|
79131
|
-
return /^\/tmp\//i.test(norm) || /\/var\/folders\//i.test(norm) || /AppData\/Local\/Temp\//i.test(norm) || norm.startsWith("/c/Users/") && norm.includes("/AppData/Local/Temp/");
|
|
79575
|
+
return /^\/tmp\//i.test(norm) || /\/var\/folders\//i.test(norm) || /AppData\/Local\/Temp\//i.test(norm) || norm.startsWith("/c/Users/") && norm.includes("/AppData/Local/Temp/") || isUnderSystemTemp(fp);
|
|
79132
79576
|
}
|
|
79133
79577
|
function isOrchestratorStateFile(filePath) {
|
|
79134
|
-
const
|
|
79135
|
-
return /^\.improve-state-/.test(
|
|
79578
|
+
const basename20 = (filePath.includes("/") ? filePath.split("/").at(-1) : filePath.split("\\").at(-1)) ?? filePath;
|
|
79579
|
+
return /^\.improve-state-/.test(basename20);
|
|
79136
79580
|
}
|
|
79137
79581
|
function extractCatSourceFile(cmd) {
|
|
79138
79582
|
const m = /^cat\s+(\S+\.(?:java|py|ts|tsx|js|jsx|go|rb|rs|cpp|cc|cxx|c|h|hpp|kt|swift|cs|php|scala|clj|css|scss|sass|less))\s*$/.exec(cmd);
|
|
79139
79583
|
return m?.[1] ?? null;
|
|
79140
79584
|
}
|
|
79141
79585
|
function classifyFileExtensions(filePath) {
|
|
79142
|
-
const
|
|
79143
|
-
const isEnvFile = /^\.env(\.\w+)?$/i.test(
|
|
79586
|
+
const basename20 = (filePath.includes("/") ? filePath.split("/").at(-1) : filePath.split("\\").at(-1)) ?? filePath;
|
|
79587
|
+
const isEnvFile = /^\.env(\.\w+)?$/i.test(basename20);
|
|
79144
79588
|
const hasKnownExt = /\.(?:java|py|ts|tsx|js|jsx|go|rb|rs|cpp|cc|cxx|c|h|hpp|kt|swift|cs|php|scala|clj|css|scss|sass|less|md|mdx|rst|txt|json|yaml|yml|toml|xml|conf|cfg|ini|properties|sql|ps1|psm1|env)$/i.test(filePath);
|
|
79145
79589
|
if (!hasKnownExt && !isEnvFile) return null;
|
|
79146
79590
|
const isSql = /\.sql$/i.test(filePath);
|
|
@@ -79185,7 +79629,7 @@ var PS_GETCONTENT_INNER_RE = /^(?:Get-Content|gc|cat|type)(?:\s+(?:-[a-zA-Z]+|--
|
|
|
79185
79629
|
var PS_TEMP_READ_FLOOD_BYTES = 16 * 1024;
|
|
79186
79630
|
function isLargeFileOnDisk(filePath, floor) {
|
|
79187
79631
|
try {
|
|
79188
|
-
return
|
|
79632
|
+
return statSync32(filePath).size >= floor;
|
|
79189
79633
|
} catch {
|
|
79190
79634
|
return false;
|
|
79191
79635
|
}
|
|
@@ -80057,7 +80501,7 @@ function preBashHandlerInner(event) {
|
|
|
80057
80501
|
const prevResolvedPath = prevPath !== null ? resolveIndexPath(prevPath, preHookCwd ?? process.cwd()) : null;
|
|
80058
80502
|
if (prevPath !== null && prevResolvedPath !== null && !existsSync38(prevResolvedPath)) {
|
|
80059
80503
|
clearCurlDownload(curlDl.url);
|
|
80060
|
-
} else if (prevPath !== null && prevResolvedPath !== null &&
|
|
80504
|
+
} else if (prevPath !== null && prevResolvedPath !== null && statSync32(prevResolvedPath).size >= loadConfig().hints.bash_dedup_min_bytes) {
|
|
80061
80505
|
recordStat("session_hint", 0, 0);
|
|
80062
80506
|
return denyOutput(
|
|
80063
80507
|
"Already downloaded to " + prevPath + " earlier this session. Use `rg '<pattern>' " + prevPath + '` to search it, or `token-goat read "' + prevPath + '::SectionName"` to read a part of it.'
|
|
@@ -80994,7 +81438,7 @@ init_session();
|
|
|
80994
81438
|
init_compact();
|
|
80995
81439
|
init_util2();
|
|
80996
81440
|
init_stats();
|
|
80997
|
-
var BRIEFING_TARGET_TOKENS =
|
|
81441
|
+
var BRIEFING_TARGET_TOKENS = 450;
|
|
80998
81442
|
function buildSubagentBriefing() {
|
|
80999
81443
|
try {
|
|
81000
81444
|
const head = [];
|
|
@@ -81022,7 +81466,7 @@ function buildSubagentBriefing() {
|
|
|
81022
81466
|
}
|
|
81023
81467
|
const tail = [];
|
|
81024
81468
|
tail.push("");
|
|
81025
|
-
tail.push('
|
|
81469
|
+
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.');
|
|
81026
81470
|
const withCacheIds = head.join("\n") + cacheIdsBlock + "\n" + tail.join("\n");
|
|
81027
81471
|
if (estimateTokens(withCacheIds) <= BRIEFING_TARGET_TOKENS) {
|
|
81028
81472
|
return withCacheIds;
|
|
@@ -81114,7 +81558,7 @@ init_image_shrink();
|
|
|
81114
81558
|
var DEFAULT_STDIN_TIMEOUT_MS = 5e3;
|
|
81115
81559
|
var MAX_STDIN_BYTES = 64 * 1024 * 1024;
|
|
81116
81560
|
function readStdinJson(timeoutMs = DEFAULT_STDIN_TIMEOUT_MS, maxBytes = MAX_STDIN_BYTES) {
|
|
81117
|
-
return new Promise((
|
|
81561
|
+
return new Promise((resolve21, reject) => {
|
|
81118
81562
|
const chunks = [];
|
|
81119
81563
|
let totalBytes = 0;
|
|
81120
81564
|
let settled = false;
|
|
@@ -81149,7 +81593,7 @@ function readStdinJson(timeoutMs = DEFAULT_STDIN_TIMEOUT_MS, maxBytes = MAX_STDI
|
|
|
81149
81593
|
return;
|
|
81150
81594
|
}
|
|
81151
81595
|
try {
|
|
81152
|
-
|
|
81596
|
+
resolve21(JSON.parse(text));
|
|
81153
81597
|
} catch (err2) {
|
|
81154
81598
|
reject(err2 instanceof Error ? err2 : new Error(String(err2)));
|
|
81155
81599
|
}
|