@pi-unipi/unipi 2.6.0 → 2.6.2
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/CHANGELOG.md +19 -0
- package/package.json +21 -22
- package/packages/ask-user/package.json +2 -2
- package/packages/ask-user/settings-tui.ts +18 -34
- package/packages/autocomplete/package.json +1 -1
- package/packages/autocomplete/src/constants.ts +2 -15
- package/packages/autocomplete/src/provider.ts +3 -17
- package/packages/btw/extensions/btw.ts +18 -45
- package/packages/btw/package.json +2 -2
- package/packages/compactor/README.md +2 -2
- package/packages/compactor/package.json +3 -3
- package/packages/compactor/skills/compactor/SKILL.md +1 -1
- package/packages/compactor/skills/compactor-detail/SKILL.md +3 -5
- package/packages/compactor/skills/compactor-doctor/SKILL.md +1 -1
- package/packages/compactor/skills/compactor-stats/SKILL.md +1 -1
- package/packages/compactor/src/commands/index.ts +47 -78
- package/packages/compactor/src/compaction/brief.ts +161 -90
- package/packages/compactor/src/compaction/build-sections.ts +3 -4
- package/packages/compactor/src/compaction/compact-args.ts +86 -0
- package/packages/compactor/src/compaction/cut.ts +270 -28
- package/packages/compactor/src/compaction/drill-down.ts +261 -0
- package/packages/compactor/src/compaction/format-recall.ts +96 -0
- package/packages/compactor/src/compaction/format.ts +8 -3
- package/packages/compactor/src/compaction/hooks.ts +248 -72
- package/packages/compactor/src/compaction/merge.ts +34 -4
- package/packages/compactor/src/compaction/rank.ts +270 -0
- package/packages/compactor/src/compaction/recall-scope.ts +28 -0
- package/packages/compactor/src/compaction/search-entries.ts +333 -96
- package/packages/compactor/src/compaction/skill-collapse.ts +35 -0
- package/packages/compactor/src/compaction/summarize.ts +37 -6
- package/packages/compactor/src/compaction/token-estimate.ts +104 -0
- package/packages/compactor/src/compaction/touched-files.ts +35 -0
- package/packages/compactor/src/config/manager.ts +2 -27
- package/packages/compactor/src/config/presets.ts +0 -2
- package/packages/compactor/src/config/schema.ts +2 -16
- package/packages/compactor/src/executor/executor.ts +6 -15
- package/packages/compactor/src/executor/runtime.ts +2 -12
- package/packages/compactor/src/index.ts +4 -121
- package/packages/compactor/src/info-screen.ts +3 -10
- package/packages/compactor/src/security/evaluator.ts +0 -53
- package/packages/compactor/src/security/policy.ts +7 -8
- package/packages/compactor/src/session/db.ts +0 -6
- package/packages/compactor/src/tools/ctx-execute-file.ts +0 -5
- package/packages/compactor/src/tools/register.ts +27 -50
- package/packages/compactor/src/tools/vcc-recall.ts +86 -48
- package/packages/compactor/src/tui/settings-overlay.ts +20 -40
- package/packages/compactor/src/types.ts +43 -100
- package/packages/core/constants.ts +1 -28
- package/packages/core/events.ts +1 -83
- package/packages/core/index.ts +1 -0
- package/packages/core/model-cache.ts +18 -12
- package/packages/core/package.json +3 -1
- package/packages/core/tui-overlay.ts +89 -0
- package/packages/core/tui-width.ts +18 -0
- package/packages/core/utils.ts +43 -0
- package/packages/footer/package.json +2 -2
- package/packages/footer/src/help.ts +2 -2
- package/packages/footer/src/index.ts +9 -10
- package/packages/footer/src/presets.ts +1 -27
- package/packages/footer/src/registry/index.ts +0 -23
- package/packages/footer/src/rendering/icons.ts +0 -13
- package/packages/footer/src/rendering/renderer.ts +5 -40
- package/packages/footer/src/rendering/separators.ts +0 -10
- package/packages/footer/src/rendering/theme.ts +1 -15
- package/packages/footer/src/segments/compactor.ts +7 -14
- package/packages/footer/src/segments/core.ts +15 -54
- package/packages/footer/src/segments/kanboard.ts +5 -5
- package/packages/footer/src/segments/mcp.ts +5 -5
- package/packages/footer/src/segments/memory.ts +4 -4
- package/packages/footer/src/segments/notify.ts +2 -2
- package/packages/footer/src/segments/ralph.ts +3 -3
- package/packages/footer/src/segments/status-ext.ts +1 -1
- package/packages/footer/src/segments/workflow.ts +3 -3
- package/packages/footer/src/tps-tracker.ts +0 -8
- package/packages/footer/src/tui/settings-tui.ts +14 -31
- package/packages/footer/src/types.ts +0 -15
- package/packages/image/package.json +2 -2
- package/packages/image/src/register-providers.ts +0 -11
- package/packages/image/src/tools.ts +0 -3
- package/packages/image/src/tui/model-selector.ts +36 -71
- package/packages/info-screen/config.ts +0 -16
- package/packages/info-screen/core-groups.ts +0 -10
- package/packages/info-screen/index.ts +22 -13
- package/packages/info-screen/package.json +2 -2
- package/packages/info-screen/registry.ts +1 -72
- package/packages/info-screen/tui/info-overlay.ts +85 -100
- package/packages/info-screen/usage-parser.ts +12 -47
- package/packages/input-shortcuts/package.json +2 -2
- package/packages/input-shortcuts/src/index.ts +3 -3
- package/packages/input-shortcuts/src/registers.ts +0 -8
- package/packages/input-shortcuts/src/settings-overlay.ts +4 -13
- package/packages/input-shortcuts/src/undo-redo.ts +0 -12
- package/packages/kanboard/package.json +2 -2
- package/packages/mcp/package.json +2 -2
- package/packages/mcp/src/bridge/client.ts +0 -15
- package/packages/mcp/src/config/manager.ts +0 -38
- package/packages/mcp/src/config/schema.ts +0 -27
- package/packages/mcp/src/config/sync.ts +0 -29
- package/packages/mcp/src/index.ts +1 -1
- package/packages/mcp/src/tui/add-overlay.ts +6 -6
- package/packages/mcp/src/types.ts +0 -6
- package/packages/memory/embedding.ts +0 -31
- package/packages/memory/mempalace.ts +0 -16
- package/packages/memory/package.json +4 -8
- package/packages/memory/storage.ts +56 -753
- package/packages/milestone/hooks.ts +1 -6
- package/packages/milestone/milestone.ts +2 -41
- package/packages/milestone/package.json +2 -2
- package/packages/notify/README.md +1 -0
- package/packages/notify/commands.ts +61 -3
- package/packages/notify/events.ts +0 -10
- package/packages/notify/package.json +2 -2
- package/packages/notify/settings.ts +0 -19
- package/packages/notify/tui/gotify-setup.ts +108 -143
- package/packages/notify/tui/ntfy-setup.ts +137 -172
- package/packages/notify/tui/recap-model-selector.ts +107 -101
- package/packages/notify/tui/settings-overlay.ts +94 -117
- package/packages/notify/tui/telegram-setup.ts +48 -79
- package/packages/notify/types.ts +0 -2
- package/packages/ralph/index.ts +11 -35
- package/packages/ralph/package.json +3 -3
- package/packages/ralph/ralph-loop.ts +3 -44
- package/packages/subagents/package.json +2 -1
- package/packages/subagents/src/agent-manager.ts +0 -51
- package/packages/subagents/src/agent-runner.ts +6 -80
- package/packages/subagents/src/conversation-viewer.ts +1 -19
- package/packages/subagents/src/core-compat.ts +8 -25
- package/packages/subagents/src/custom-agents.ts +0 -1
- package/packages/subagents/src/index.ts +3 -48
- package/packages/subagents/src/types.ts +0 -11
- package/packages/subagents/src/widget.ts +5 -5
- package/packages/unipi/bundled.js +4468 -7769
- package/packages/unipi/index.ts +6 -3
- package/packages/updater/package.json +2 -2
- package/packages/updater/src/changelog.ts +1 -16
- package/packages/updater/src/index.ts +0 -5
- package/packages/updater/src/installer.ts +4 -26
- package/packages/updater/src/markdown.ts +6 -152
- package/packages/updater/src/settings.ts +0 -15
- package/packages/updater/src/tui/changelog-overlay.ts +42 -234
- package/packages/updater/src/tui/list-detail-overlay.ts +260 -0
- package/packages/updater/src/tui/readme-overlay.ts +53 -210
- package/packages/updater/src/tui/settings-overlay.ts +13 -26
- package/packages/updater/src/version.ts +2 -31
- package/packages/utility/package.json +2 -4
- package/packages/utility/src/commands.ts +4 -5
- package/packages/utility/src/herdr-sync.ts +136 -0
- package/packages/utility/src/index.ts +11 -68
- package/packages/utility/src/lifecycle/cleanup.ts +2 -16
- package/packages/utility/src/{diff/settings.ts → settings.ts} +42 -80
- package/packages/utility/src/tools/env.ts +0 -0
- package/packages/utility/src/tui/name-badge-state.ts +18 -2
- package/packages/utility/src/tui/name-badge.ts +5 -4
- package/packages/utility/src/tui/util-settings-tui.ts +41 -224
- package/packages/web-api/package.json +2 -6
- package/packages/web-api/src/engine/dependencies.ts +13 -134
- package/packages/web-api/src/engine/extract.ts +9 -99
- package/packages/web-api/src/engine/format.ts +0 -75
- package/packages/web-api/src/engine/types.ts +0 -39
- package/packages/web-api/src/index.ts +1 -2
- package/packages/web-api/src/providers/base.ts +0 -10
- package/packages/web-api/src/providers/duckduckgo.ts +0 -1
- package/packages/web-api/src/providers/firecrawl.ts +0 -9
- package/packages/web-api/src/providers/jina-reader.ts +0 -9
- package/packages/web-api/src/providers/jina-search.ts +0 -9
- package/packages/web-api/src/providers/perplexity.ts +0 -9
- package/packages/web-api/src/providers/registry.ts +0 -80
- package/packages/web-api/src/providers/serpapi.ts +0 -9
- package/packages/web-api/src/providers/tavily.ts +0 -9
- package/packages/web-api/src/providers/wigolo-client.ts +0 -30
- package/packages/web-api/src/providers/wigolo.ts +0 -1
- package/packages/web-api/src/settings.ts +17 -77
- package/packages/web-api/src/tools.ts +21 -24
- package/packages/web-api/src/tui/settings-dialog.ts +0 -1
- package/packages/workflow/commands.ts +38 -122
- package/packages/workflow/index.ts +1 -5
- package/packages/workflow/package.json +2 -2
- package/packages/cocoindex/README.md +0 -94
- package/packages/cocoindex/bridge.ts +0 -842
- package/packages/cocoindex/commands.ts +0 -175
- package/packages/cocoindex/index.ts +0 -48
- package/packages/cocoindex/installer.ts +0 -397
- package/packages/cocoindex/package.json +0 -49
- package/packages/cocoindex/skills/cocoindex/SKILL.md +0 -88
- package/packages/cocoindex/tools.ts +0 -157
- package/packages/compactor/src/display/diff-renderer.ts +0 -281
- package/packages/compactor/src/display/line-width-safety.ts +0 -28
- package/packages/compactor/src/display/render-utils.ts +0 -52
- package/packages/compactor/src/display/thinking-label.ts +0 -18
- package/packages/compactor/src/display/tool-overrides.ts +0 -136
- package/packages/compactor/src/tools/compact.ts +0 -20
- package/packages/subagents/src/file-lock.ts +0 -102
- package/packages/utility/src/cache/ttl-cache.ts +0 -311
- package/packages/utility/src/diff/highlighter.ts +0 -352
- package/packages/utility/src/diff/parser.ts +0 -191
- package/packages/utility/src/diff/renderer.ts +0 -395
- package/packages/utility/src/diff/theme.ts +0 -316
- package/packages/utility/src/diff/wrapper.ts +0 -339
- package/packages/utility/src/display/capabilities.ts +0 -214
- package/packages/utility/src/display/width.ts +0 -226
- package/packages/utility/src/tools/batch.ts +0 -229
- package/packages/utility/src/tui/badge-settings-tui.ts +0 -388
- package/packages/utility/src/tui/badge-settings.ts +0 -67
- package/packages/utility/src/tui/settings-inspector.ts +0 -303
- package/packages/web-api/src/providers/llm-summarize.ts +0 -71
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Touched-file aggregation (pi-vcc parity, mode:"touched") — files worked on
|
|
3
|
+
* with their entry indices, aggregated across the searched window.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { NormalizedBlock } from "../types.js";
|
|
7
|
+
import { extractPath } from "./extract/files.js";
|
|
8
|
+
|
|
9
|
+
/** A file touched in one block — used by mode:touched aggregation. */
|
|
10
|
+
export interface FileTouch {
|
|
11
|
+
index: number;
|
|
12
|
+
toolName: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/** Aggregated view of a file touched across multiple blocks. */
|
|
16
|
+
export interface TouchedFile {
|
|
17
|
+
path: string;
|
|
18
|
+
entries: FileTouch[];
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** Aggregate file operations across tool_call blocks. */
|
|
22
|
+
export function getTouchedFiles(blocks: NormalizedBlock[]): TouchedFile[] {
|
|
23
|
+
const map = new Map<string, TouchedFile>();
|
|
24
|
+
for (const b of blocks) {
|
|
25
|
+
if (b.kind !== "tool_call") continue;
|
|
26
|
+
const path = extractPath(b.args);
|
|
27
|
+
if (!path) continue;
|
|
28
|
+
const index = b.sourceIndex ?? 0;
|
|
29
|
+
if (!map.has(path)) {
|
|
30
|
+
map.set(path, { path, entries: [] });
|
|
31
|
+
}
|
|
32
|
+
map.get(path)!.entries.push({ index, toolName: b.name });
|
|
33
|
+
}
|
|
34
|
+
return Array.from(map.values());
|
|
35
|
+
}
|
|
@@ -91,36 +91,11 @@ export function saveConfig(config: CompactorConfig, opts?: { perProject?: boolea
|
|
|
91
91
|
|
|
92
92
|
/**
|
|
93
93
|
* Migrate partial config to full schema, filling missing keys from defaults.
|
|
94
|
+
* Uses deepMerge so nested strategy objects merge recursively.
|
|
94
95
|
*/
|
|
95
96
|
export function migrateConfig(partial: Partial<CompactorConfig>): CompactorConfig {
|
|
96
97
|
const defaults = structuredClone(DEFAULT_COMPACTOR_CONFIG);
|
|
97
|
-
|
|
98
|
-
function mergeStrategy<K extends keyof CompactorConfig>(
|
|
99
|
-
key: K,
|
|
100
|
-
defaultVal: CompactorConfig[K],
|
|
101
|
-
partialVal: CompactorConfig[K] | undefined,
|
|
102
|
-
): CompactorConfig[K] {
|
|
103
|
-
if (!partialVal || typeof partialVal !== "object") return defaultVal;
|
|
104
|
-
return { ...(defaultVal as any), ...(partialVal as any) };
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
return {
|
|
108
|
-
sessionGoals: mergeStrategy("sessionGoals", defaults.sessionGoals, partial.sessionGoals),
|
|
109
|
-
filesAndChanges: mergeStrategy("filesAndChanges", defaults.filesAndChanges, partial.filesAndChanges),
|
|
110
|
-
commits: mergeStrategy("commits", defaults.commits, partial.commits),
|
|
111
|
-
outstandingContext: mergeStrategy("outstandingContext", defaults.outstandingContext, partial.outstandingContext),
|
|
112
|
-
userPreferences: mergeStrategy("userPreferences", defaults.userPreferences, partial.userPreferences),
|
|
113
|
-
briefTranscript: mergeStrategy("briefTranscript", defaults.briefTranscript, partial.briefTranscript),
|
|
114
|
-
sessionContinuity: mergeStrategy("sessionContinuity", defaults.sessionContinuity, partial.sessionContinuity),
|
|
115
|
-
fts5Index: mergeStrategy("fts5Index", defaults.fts5Index, partial.fts5Index),
|
|
116
|
-
sandboxExecution: mergeStrategy("sandboxExecution", defaults.sandboxExecution, partial.sandboxExecution),
|
|
117
|
-
toolDisplay: mergeStrategy("toolDisplay", defaults.toolDisplay, partial.toolDisplay),
|
|
118
|
-
pipeline: mergeStrategy("pipeline", defaults.pipeline, (partial as any).pipeline) as any,
|
|
119
|
-
autoCompaction: mergeStrategy("autoCompaction", defaults.autoCompaction, partial.autoCompaction),
|
|
120
|
-
overrideDefaultCompaction: partial.overrideDefaultCompaction ?? defaults.overrideDefaultCompaction,
|
|
121
|
-
debug: partial.debug ?? defaults.debug,
|
|
122
|
-
showTruncationHints: partial.showTruncationHints ?? defaults.showTruncationHints,
|
|
123
|
-
};
|
|
98
|
+
return deepMerge(defaults, partial);
|
|
124
99
|
}
|
|
125
100
|
|
|
126
101
|
/**
|
|
@@ -34,8 +34,6 @@ const preset = (
|
|
|
34
34
|
// Legacy compatibility data only; presets never advertise or alter it.
|
|
35
35
|
fts5Index: { ...DEFAULT_COMPACTOR_CONFIG.fts5Index },
|
|
36
36
|
sandboxExecution: { ...DEFAULT_COMPACTOR_CONFIG.sandboxExecution, ...(overrides.sandboxExecution ?? {}) },
|
|
37
|
-
// Legacy compatibility data only; presets never advertise or alter it.
|
|
38
|
-
toolDisplay: { ...DEFAULT_COMPACTOR_CONFIG.toolDisplay },
|
|
39
37
|
pipeline: pipeline(overrides.pipeline),
|
|
40
38
|
autoCompaction: { ...DEFAULT_COMPACTOR_CONFIG.autoCompaction, ...(overrides.autoCompaction ?? {}) },
|
|
41
39
|
});
|
|
@@ -39,23 +39,8 @@ export const DEFAULT_COMPACTOR_CONFIG: CompactorConfig = {
|
|
|
39
39
|
allowedLanguages: ["javascript", "typescript", "python", "shell"],
|
|
40
40
|
outputLimit: 100 * 1024 * 1024,
|
|
41
41
|
},
|
|
42
|
-
toolDisplay: {
|
|
43
|
-
...strategy(true, "opencode"),
|
|
44
|
-
mode: "opencode",
|
|
45
|
-
diffLayout: "auto",
|
|
46
|
-
diffIndicator: "bars",
|
|
47
|
-
showThinkingLabels: true,
|
|
48
|
-
showUserMessageBox: true,
|
|
49
|
-
showBashSpinner: true,
|
|
50
|
-
showPendingPreviews: true,
|
|
51
|
-
},
|
|
52
42
|
pipeline: {
|
|
53
|
-
ttlCache: false,
|
|
54
43
|
autoInjection: false,
|
|
55
|
-
proximityReranking: false,
|
|
56
|
-
timelineSort: false,
|
|
57
|
-
progressiveThrottling: false,
|
|
58
|
-
mmapPragma: false,
|
|
59
44
|
customNoisePatterns: [],
|
|
60
45
|
},
|
|
61
46
|
autoCompaction: {
|
|
@@ -66,6 +51,7 @@ export const DEFAULT_COMPACTOR_CONFIG: CompactorConfig = {
|
|
|
66
51
|
notify: true,
|
|
67
52
|
},
|
|
68
53
|
overrideDefaultCompaction: true,
|
|
54
|
+
smartKeepTail: true,
|
|
55
|
+
continueAfterThresholdCompact: true,
|
|
69
56
|
debug: false,
|
|
70
|
-
showTruncationHints: true,
|
|
71
57
|
};
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* PolyglotExecutor — sandboxed code execution for 11 languages
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import { spawn, execSync
|
|
5
|
+
import { spawn, execSync } from "node:child_process";
|
|
6
6
|
import { mkdtempSync, writeFileSync, rmSync, existsSync } from "node:fs";
|
|
7
7
|
import { join, resolve } from "node:path";
|
|
8
8
|
import { tmpdir } from "node:os";
|
|
@@ -11,19 +11,7 @@ import type { ExecResult } from "../types.js";
|
|
|
11
11
|
|
|
12
12
|
const isWin = process.platform === "win32";
|
|
13
13
|
|
|
14
|
-
const OS_TMPDIR = (()
|
|
15
|
-
if (isWin) return process.env.TEMP ?? process.env.TMP ?? tmpdir();
|
|
16
|
-
try {
|
|
17
|
-
const result = execFileSync(
|
|
18
|
-
process.platform === "darwin" ? "getconf" : "mktemp",
|
|
19
|
-
process.platform === "darwin" ? ["DARWIN_USER_TEMP_DIR"] : ["-u", "-d"],
|
|
20
|
-
{ env: { ...process.env, TMPDIR: undefined as unknown as string }, encoding: "utf-8" },
|
|
21
|
-
).trim();
|
|
22
|
-
const dir = process.platform === "darwin" ? result : resolve(result, "..");
|
|
23
|
-
if (dir && dir !== process.cwd()) return dir;
|
|
24
|
-
} catch { /* fall through */ }
|
|
25
|
-
return "/tmp";
|
|
26
|
-
})();
|
|
14
|
+
const OS_TMPDIR = isWin ? (process.env.TEMP ?? process.env.TMP ?? tmpdir()) : tmpdir();
|
|
27
15
|
|
|
28
16
|
function killTree(proc: ReturnType<typeof spawn>): void {
|
|
29
17
|
if (isWin && proc.pid) {
|
|
@@ -73,8 +61,11 @@ interface ExecuteOptions {
|
|
|
73
61
|
background?: boolean;
|
|
74
62
|
}
|
|
75
63
|
|
|
76
|
-
interface ExecuteFileOptions
|
|
64
|
+
interface ExecuteFileOptions {
|
|
65
|
+
language: Language;
|
|
77
66
|
path: string;
|
|
67
|
+
timeout?: number;
|
|
68
|
+
background?: boolean;
|
|
78
69
|
}
|
|
79
70
|
|
|
80
71
|
export class PolyglotExecutor {
|
|
@@ -2,18 +2,8 @@
|
|
|
2
2
|
* Runtime detection for sandbox executor
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
| "typescript"
|
|
8
|
-
| "python"
|
|
9
|
-
| "shell"
|
|
10
|
-
| "ruby"
|
|
11
|
-
| "go"
|
|
12
|
-
| "rust"
|
|
13
|
-
| "php"
|
|
14
|
-
| "perl"
|
|
15
|
-
| "r"
|
|
16
|
-
| "elixir";
|
|
5
|
+
import type { Language } from "../types.js";
|
|
6
|
+
export type { Language };
|
|
17
7
|
|
|
18
8
|
export interface RuntimeMap {
|
|
19
9
|
javascript: string;
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
6
|
-
import { MODULES, UNIPI_EVENTS, COMPACTOR_COMMANDS, COMPACTOR_TOOLS, COMPACTOR_INSTRUCTION, emitEvent } from "@pi-unipi/core";
|
|
6
|
+
import { MODULES, UNIPI_EVENTS, COMPACTOR_COMMANDS, COMPACTOR_TOOLS, COMPACTOR_INSTRUCTION, emitEvent, formatTokens } from "@pi-unipi/core";
|
|
7
7
|
import { scaffoldConfig, loadConfig } from "./config/manager.js";
|
|
8
8
|
import { registerCompactionHooks } from "./compaction/hooks.js";
|
|
9
9
|
import {
|
|
@@ -22,45 +22,13 @@ import { registerCompactorTools } from "./tools/register.js";
|
|
|
22
22
|
import { normalizeMessages } from "./compaction/normalize.js";
|
|
23
23
|
import { filterNoise } from "./compaction/filter-noise.js";
|
|
24
24
|
import { recallBlocksFromContext } from "./session/recall-blocks.js";
|
|
25
|
-
import type { NormalizedBlock, CompactorStrategyConfig, RuntimeCounters
|
|
25
|
+
import type { NormalizedBlock, CompactorStrategyConfig, RuntimeCounters } from "./types.js";
|
|
26
26
|
|
|
27
|
-
/** Debug logger — only logs when config.debug === true */
|
|
28
|
-
function createDebugLogger(getConfig: () => { debug: boolean }) {
|
|
29
|
-
return (_event: string, _data?: Record<string, unknown>) => {
|
|
30
|
-
// Debug logging disabled — was writing to stdout causing TUI rendering issues.
|
|
31
|
-
return;
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
27
|
|
|
35
|
-
const formatTokenCount = (n: number): string => {
|
|
36
|
-
if (n >= 1_000_000) return `${(n / 1_000_000).toFixed(1)}M`;
|
|
37
|
-
if (n >= 1_000) return `${(n / 1_000).toFixed(1)}k`;
|
|
38
|
-
return String(n);
|
|
39
|
-
};
|
|
40
28
|
|
|
41
29
|
/** Measure byte size of a tool_result event's response content. */
|
|
42
|
-
function measureResponseBytes(event: any): number {
|
|
43
|
-
try {
|
|
44
|
-
const content = event.content;
|
|
45
|
-
if (typeof content === "string") return Buffer.byteLength(content, "utf-8");
|
|
46
|
-
if (Array.isArray(content)) {
|
|
47
|
-
return content.reduce((sum: number, block: any) => {
|
|
48
|
-
if (typeof block?.text === "string") return sum + Buffer.byteLength(block.text, "utf-8");
|
|
49
|
-
if (typeof block === "string") return sum + Buffer.byteLength(block, "utf-8");
|
|
50
|
-
return sum;
|
|
51
|
-
}, 0);
|
|
52
|
-
}
|
|
53
|
-
if (event.output && typeof event.output === "string") return Buffer.byteLength(event.output, "utf-8");
|
|
54
|
-
} catch {
|
|
55
|
-
// Non-blocking: byte measurement errors silently skipped
|
|
56
|
-
}
|
|
57
|
-
return 0;
|
|
58
|
-
}
|
|
59
30
|
|
|
60
31
|
/** Check if a tool is a sandbox tool (output stays in sandbox, not context). */
|
|
61
|
-
function isSandboxTool(name: string): boolean {
|
|
62
|
-
return name === "bash" || name === "Bash";
|
|
63
|
-
}
|
|
64
32
|
|
|
65
33
|
export default function compactorExtension(pi: ExtensionAPI): void {
|
|
66
34
|
let sessionDB: SessionDB | null = null;
|
|
@@ -78,17 +46,6 @@ export default function compactorExtension(pi: ExtensionAPI): void {
|
|
|
78
46
|
};
|
|
79
47
|
const getCounters = () => counters;
|
|
80
48
|
|
|
81
|
-
const runtimeStats: RuntimeStats = {
|
|
82
|
-
bytesReturned: {},
|
|
83
|
-
bytesSandboxed: 0,
|
|
84
|
-
calls: {},
|
|
85
|
-
sessionStart: Date.now(),
|
|
86
|
-
cacheHits: 0,
|
|
87
|
-
cacheBytesSaved: 0,
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
const debug = createDebugLogger(() => config);
|
|
91
|
-
|
|
92
49
|
const init = async () => {
|
|
93
50
|
scaffoldConfig();
|
|
94
51
|
config = loadConfig();
|
|
@@ -134,8 +91,6 @@ export default function compactorExtension(pi: ExtensionAPI): void {
|
|
|
134
91
|
const fullSessionId = `${sessionId}${suffix}`;
|
|
135
92
|
currentSessionId = fullSessionId;
|
|
136
93
|
|
|
137
|
-
debug("session_start", { sessionId: fullSessionId, projectDir });
|
|
138
|
-
|
|
139
94
|
// Seed runtime counters from DB so they reflect prior usage
|
|
140
95
|
if (sessionDB) {
|
|
141
96
|
try {
|
|
@@ -148,12 +103,6 @@ export default function compactorExtension(pi: ExtensionAPI): void {
|
|
|
148
103
|
}
|
|
149
104
|
|
|
150
105
|
// Reset runtime stats for new session
|
|
151
|
-
runtimeStats.bytesReturned = {};
|
|
152
|
-
runtimeStats.bytesSandboxed = 0;
|
|
153
|
-
runtimeStats.calls = {};
|
|
154
|
-
runtimeStats.sessionStart = Date.now();
|
|
155
|
-
runtimeStats.cacheHits = 0;
|
|
156
|
-
runtimeStats.cacheBytesSaved = 0;
|
|
157
106
|
autoCompactionState = createAutoCompactionState();
|
|
158
107
|
|
|
159
108
|
sessionDB?.ensureSession(fullSessionId, projectDir);
|
|
@@ -226,8 +175,6 @@ export default function compactorExtension(pi: ExtensionAPI): void {
|
|
|
226
175
|
tools: Object.values(COMPACTOR_TOOLS),
|
|
227
176
|
});
|
|
228
177
|
|
|
229
|
-
debug("MODULE_READY", { commands: Object.values(COMPACTOR_COMMANDS), tools: Object.values(COMPACTOR_TOOLS) });
|
|
230
|
-
|
|
231
178
|
ctx.ui.notify("🗜️ Compactor ready", "info");
|
|
232
179
|
});
|
|
233
180
|
|
|
@@ -235,7 +182,6 @@ export default function compactorExtension(pi: ExtensionAPI): void {
|
|
|
235
182
|
const cwd = (ctx as any).cwd ?? process.cwd();
|
|
236
183
|
config = loadConfig(cwd);
|
|
237
184
|
currentSessionId = `${(ctx as any).sessionId ?? "default"}${getWorktreeSuffix()}`;
|
|
238
|
-
debug("before_agent_start", { sessionId: currentSessionId, configDebug: config.debug });
|
|
239
185
|
|
|
240
186
|
// Evaluate autoDetect conditions for strategies
|
|
241
187
|
try {
|
|
@@ -248,7 +194,6 @@ export default function compactorExtension(pi: ExtensionAPI): void {
|
|
|
248
194
|
if ((strat as any).autoDetect === "git") {
|
|
249
195
|
const gitDir = join(cwd, ".git");
|
|
250
196
|
if (!existsSync(gitDir)) {
|
|
251
|
-
debug("autoDetect_disable", { strategy: key, reason: "no .git dir" });
|
|
252
197
|
// Non-destructive: temporarily disable at runtime, don't modify config file
|
|
253
198
|
strat.enabled = false;
|
|
254
199
|
}
|
|
@@ -280,7 +225,6 @@ export default function compactorExtension(pi: ExtensionAPI): void {
|
|
|
280
225
|
const continuityEnabled = isSessionContinuityEnabled(config);
|
|
281
226
|
if (sessionDB && continuityEnabled) {
|
|
282
227
|
const resumeContext = await buildResumeContextMessage(sessionDB, currentSessionId);
|
|
283
|
-
debug("resume_snapshot", { injected: !!resumeContext });
|
|
284
228
|
return resumeContext;
|
|
285
229
|
}
|
|
286
230
|
});
|
|
@@ -297,23 +241,12 @@ export default function compactorExtension(pi: ExtensionAPI): void {
|
|
|
297
241
|
});
|
|
298
242
|
autoCompactionState = decision.state;
|
|
299
243
|
|
|
300
|
-
debug("auto_compaction_decision", {
|
|
301
|
-
enabled: config.autoCompaction.enabled,
|
|
302
|
-
reason: decision.reason,
|
|
303
|
-
shouldTrigger: decision.shouldTrigger,
|
|
304
|
-
percent: decision.usage?.percent,
|
|
305
|
-
tokens: decision.usage?.tokens,
|
|
306
|
-
thresholdPercent: decision.thresholdPercent,
|
|
307
|
-
cooldownRemainingMs: decision.cooldownRemainingMs,
|
|
308
|
-
tokenGrowth: decision.tokenGrowth,
|
|
309
|
-
});
|
|
310
|
-
|
|
311
244
|
if (!decision.shouldTrigger) return;
|
|
312
245
|
|
|
313
246
|
const notify = config.autoCompaction.notify;
|
|
314
247
|
if (notify && decision.usage) {
|
|
315
248
|
ctx.ui.notify(
|
|
316
|
-
`Auto-compacting at ${decision.usage.percent.toFixed(1)}% context (~${
|
|
249
|
+
`Auto-compacting at ${decision.usage.percent.toFixed(1)}% context (~${formatTokens(decision.usage.tokens)} tokens; threshold ${decision.thresholdPercent}%).`,
|
|
317
250
|
"info",
|
|
318
251
|
);
|
|
319
252
|
}
|
|
@@ -351,7 +284,6 @@ export default function compactorExtension(pi: ExtensionAPI): void {
|
|
|
351
284
|
const sessionId = currentSessionId;
|
|
352
285
|
const events = sessionDB.getEvents(sessionId, { limit: 1000 });
|
|
353
286
|
const stats = sessionDB.getSessionStats(sessionId);
|
|
354
|
-
debug("session_before_compact", { sessionId, eventCount: events.length, compactCount: stats?.compact_count ?? 0 });
|
|
355
287
|
const { buildResumeSnapshot } = await import("./session/snapshot.js");
|
|
356
288
|
const snapshot = buildResumeSnapshot(events, {
|
|
357
289
|
compactCount: stats?.compact_count ?? 1,
|
|
@@ -419,12 +351,10 @@ export default function compactorExtension(pi: ExtensionAPI): void {
|
|
|
419
351
|
tokensSaved,
|
|
420
352
|
compressionRatio: kept > 0 ? `${Math.round(totalEstimated / kept)}:1` : "0:1",
|
|
421
353
|
});
|
|
422
|
-
debug("session_compact", { sessionId, tokensBefore, hasCompactionEntry: !!compactionEntry });
|
|
423
354
|
}
|
|
424
355
|
});
|
|
425
356
|
|
|
426
357
|
pi.on("session_shutdown", async (_event, _ctx) => {
|
|
427
|
-
debug("session_shutdown");
|
|
428
358
|
if (sessionDB) {
|
|
429
359
|
sessionDB.cleanupOldSessions(7);
|
|
430
360
|
}
|
|
@@ -435,7 +365,6 @@ export default function compactorExtension(pi: ExtensionAPI): void {
|
|
|
435
365
|
pi.on("input", async (event, _ctx) => {
|
|
436
366
|
const toolName = (event as any).toolName ?? "";
|
|
437
367
|
const args = (event as any).args ?? {};
|
|
438
|
-
debug("input", { toolName, args: JSON.stringify(args).slice(0, 200) });
|
|
439
368
|
|
|
440
369
|
// Existing network tool guard
|
|
441
370
|
if (toolName === "bash" || toolName === "Bash") {
|
|
@@ -447,7 +376,7 @@ export default function compactorExtension(pi: ExtensionAPI): void {
|
|
|
447
376
|
|
|
448
377
|
// Security scanner/evaluator wiring (fail-open pattern)
|
|
449
378
|
try {
|
|
450
|
-
const { evaluateCommand, evaluateFilePath
|
|
379
|
+
const { evaluateCommand, evaluateFilePath } = await import("./security/evaluator.js");
|
|
451
380
|
const { hasShellEscapes, scanForShellEscapes } = await import("./security/scanner.js");
|
|
452
381
|
const { readsOrCreatesPolicy } = await import("./security/policy.js");
|
|
453
382
|
|
|
@@ -461,7 +390,6 @@ export default function compactorExtension(pi: ExtensionAPI): void {
|
|
|
461
390
|
if (cmd) {
|
|
462
391
|
const decision = evaluateCommand(cmd, denyPolicy);
|
|
463
392
|
if (decision === "deny") {
|
|
464
|
-
debug("security_deny", { toolName, cmd: cmd.slice(0, 100) });
|
|
465
393
|
return {
|
|
466
394
|
content: [{ type: "text", text: `Command blocked by security policy: ${cmd.slice(0, 80)}` }],
|
|
467
395
|
isError: true,
|
|
@@ -478,7 +406,6 @@ export default function compactorExtension(pi: ExtensionAPI): void {
|
|
|
478
406
|
if (language && language !== "shell" && code) {
|
|
479
407
|
if (hasShellEscapes(code, language)) {
|
|
480
408
|
const findings = scanForShellEscapes(code, language);
|
|
481
|
-
debug("security_shell_escapes", { toolName, language, findings });
|
|
482
409
|
// Fail-open: log but don't block (the hooks system is enforcement)
|
|
483
410
|
}
|
|
484
411
|
}
|
|
@@ -491,14 +418,12 @@ export default function compactorExtension(pi: ExtensionAPI): void {
|
|
|
491
418
|
if (filePath) {
|
|
492
419
|
const decision = evaluateFilePath(filePath, denyPolicy, cwd);
|
|
493
420
|
if (decision === "deny") {
|
|
494
|
-
debug("security_deny_file", { toolName, filePath });
|
|
495
421
|
// Non-fatal: log warning but allow through (fail-open)
|
|
496
422
|
}
|
|
497
423
|
}
|
|
498
424
|
}
|
|
499
425
|
} catch (err) {
|
|
500
426
|
// Fail-open: security checks are advisory, never block on errors
|
|
501
|
-
debug("security_check_error", { error: String(err) });
|
|
502
427
|
}
|
|
503
428
|
|
|
504
429
|
return undefined;
|
|
@@ -511,8 +436,6 @@ export default function compactorExtension(pi: ExtensionAPI): void {
|
|
|
511
436
|
const toolNameRaw = (event as any).toolName ?? "";
|
|
512
437
|
const isError = (event as any).isError ?? false;
|
|
513
438
|
|
|
514
|
-
debug("tool_result", { toolName: toolNameRaw, isError, sessionId });
|
|
515
|
-
|
|
516
439
|
// Extract and store session events
|
|
517
440
|
const toolEvents = extractEventsFromToolResult({
|
|
518
441
|
toolName: (event as any).toolName ?? "",
|
|
@@ -523,22 +446,6 @@ export default function compactorExtension(pi: ExtensionAPI): void {
|
|
|
523
446
|
|
|
524
447
|
for (const ev of toolEvents) {
|
|
525
448
|
sessionDB.insertEvent(sessionId, ev, "PostToolUse");
|
|
526
|
-
debug("event_stored", { category: ev.category, type: ev.type });
|
|
527
|
-
}
|
|
528
|
-
|
|
529
|
-
// Track byte consumption per tool for analytics
|
|
530
|
-
try {
|
|
531
|
-
const responseBytes = measureResponseBytes(event);
|
|
532
|
-
if (responseBytes > 0) {
|
|
533
|
-
const tName = (event as any).toolName ?? "unknown";
|
|
534
|
-
runtimeStats.calls[tName] = (runtimeStats.calls[tName] || 0) + 1;
|
|
535
|
-
runtimeStats.bytesReturned[tName] = (runtimeStats.bytesReturned[tName] || 0) + responseBytes;
|
|
536
|
-
if (isSandboxTool(tName)) {
|
|
537
|
-
runtimeStats.bytesSandboxed += responseBytes;
|
|
538
|
-
}
|
|
539
|
-
}
|
|
540
|
-
} catch {
|
|
541
|
-
// Non-blocking: byte tracking errors silently skipped
|
|
542
449
|
}
|
|
543
450
|
|
|
544
451
|
const toolName = (event as any).toolName ?? "";
|
|
@@ -558,36 +465,12 @@ export default function compactorExtension(pi: ExtensionAPI): void {
|
|
|
558
465
|
);
|
|
559
466
|
const clamped = clampDiffToWidth(details.diff);
|
|
560
467
|
if (clamped !== details.diff) {
|
|
561
|
-
debug("diff_width_clamped", { toolName });
|
|
562
468
|
return { details: { ...details, diff: clamped } } as any;
|
|
563
469
|
}
|
|
564
470
|
}
|
|
565
471
|
} catch (err) {
|
|
566
|
-
debug("diff_width_clamp_error", { error: String(err) });
|
|
567
472
|
}
|
|
568
473
|
}
|
|
569
474
|
});
|
|
570
475
|
|
|
571
|
-
pi.on("message_update", async (event, _ctx) => {
|
|
572
|
-
const msg = (event as any).message;
|
|
573
|
-
if (msg?.thinking) {
|
|
574
|
-
debug("message_update", { thinking: true, length: String(msg.thinking).length });
|
|
575
|
-
}
|
|
576
|
-
});
|
|
577
|
-
|
|
578
|
-
pi.on("message_end", async (_event, _ctx) => {
|
|
579
|
-
debug("message_end");
|
|
580
|
-
});
|
|
581
|
-
|
|
582
|
-
pi.on("context", async (event, _ctx) => {
|
|
583
|
-
const { sanitizeThinkingArtifacts } = await import("./display/thinking-label.js");
|
|
584
|
-
const ctxStr = (event as any).context;
|
|
585
|
-
if (typeof ctxStr === "string") {
|
|
586
|
-
const sanitized = sanitizeThinkingArtifacts(ctxStr);
|
|
587
|
-
if (sanitized !== ctxStr) {
|
|
588
|
-
debug("context", { sanitized: true, beforeLen: ctxStr.length, afterLen: sanitized.length });
|
|
589
|
-
}
|
|
590
|
-
(event as any).context = sanitized;
|
|
591
|
-
}
|
|
592
|
-
});
|
|
593
476
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { formatTokens } from "@pi-unipi/core";
|
|
1
2
|
/**
|
|
2
3
|
* Info-screen integration for @pi-unipi/compactor
|
|
3
4
|
*
|
|
@@ -11,7 +12,7 @@
|
|
|
11
12
|
*/
|
|
12
13
|
|
|
13
14
|
import type { SessionDB } from "./session/db.js";
|
|
14
|
-
import { getLastCompactionStats } from "./compaction/hooks.js";
|
|
15
|
+
import { getLastCompactionStats, formatCompactionStats } from "./compaction/hooks.js";
|
|
15
16
|
import { parseUsageStatsAsync } from "@pi-unipi/info-screen/usage-parser.js";
|
|
16
17
|
import type { RuntimeCounters } from "./types.js";
|
|
17
18
|
|
|
@@ -25,14 +26,6 @@ export interface CompactorInfoData {
|
|
|
25
26
|
}
|
|
26
27
|
|
|
27
28
|
/** Format token count for display (e.g., "12.4k", "1.2M"). */
|
|
28
|
-
function formatTokens(n: number): string {
|
|
29
|
-
if (n < 1000) return String(n);
|
|
30
|
-
if (n < 10_000) return `${(n / 1000).toFixed(1)}k`;
|
|
31
|
-
if (n < 1_000_000) return `${Math.round(n / 1000)}k`;
|
|
32
|
-
if (n < 10_000_000) return `${(n / 1_000_000).toFixed(1)}M`;
|
|
33
|
-
return `${Math.round(n / 1_000_000)}M`;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
29
|
/** Format cost for display (e.g., "$0.34", "<$0.01"). */
|
|
37
30
|
function formatCost(n: number): string {
|
|
38
31
|
if (n === 0) return "$0.00";
|
|
@@ -184,7 +177,7 @@ export async function getInfoScreenData(
|
|
|
184
177
|
compactions: {
|
|
185
178
|
value: String(compactionCount),
|
|
186
179
|
detail: compactStats
|
|
187
|
-
? `Last: ${
|
|
180
|
+
? `Last: ${formatCompactionStats(compactStats)}`
|
|
188
181
|
: compactionCount > 0
|
|
189
182
|
? `${compactionCount} compaction(s) across all sessions`
|
|
190
183
|
: "No compactions yet",
|
|
@@ -14,28 +14,6 @@ import { parseBashPattern, parseToolPattern, globToRegex, fileGlobToRegex } from
|
|
|
14
14
|
* Load permission patterns from .pi/settings.json in the given directory.
|
|
15
15
|
* Returns a SecurityPolicy merged with the provided policy.
|
|
16
16
|
*/
|
|
17
|
-
export function loadProjectPermissions(
|
|
18
|
-
cwd: string,
|
|
19
|
-
basePolicy: SecurityPolicy,
|
|
20
|
-
): SecurityPolicy {
|
|
21
|
-
const settingsPath = join(cwd, ".pi", "settings.json");
|
|
22
|
-
if (!existsSync(settingsPath)) return basePolicy;
|
|
23
|
-
|
|
24
|
-
try {
|
|
25
|
-
const raw = readFileSync(settingsPath, "utf-8");
|
|
26
|
-
const settings = JSON.parse(raw);
|
|
27
|
-
const permissions = settings.permissions ?? settings.security ?? {};
|
|
28
|
-
|
|
29
|
-
return {
|
|
30
|
-
deny: [...basePolicy.deny, ...(permissions.deny ?? [])],
|
|
31
|
-
ask: [...basePolicy.ask, ...(permissions.ask ?? [])],
|
|
32
|
-
allow: [...basePolicy.allow, ...(permissions.allow ?? [])],
|
|
33
|
-
};
|
|
34
|
-
} catch {
|
|
35
|
-
return basePolicy;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
17
|
export function evaluateCommand(
|
|
40
18
|
command: string,
|
|
41
19
|
policy: SecurityPolicy,
|
|
@@ -73,37 +51,6 @@ export function evaluateCommand(
|
|
|
73
51
|
return "allow";
|
|
74
52
|
}
|
|
75
53
|
|
|
76
|
-
export function splitChainedCommands(command: string): string[] {
|
|
77
|
-
const commands: string[] = [];
|
|
78
|
-
let current = "";
|
|
79
|
-
let inQuotes = false;
|
|
80
|
-
let quoteChar = "";
|
|
81
|
-
|
|
82
|
-
for (let i = 0; i < command.length; i++) {
|
|
83
|
-
const char = command[i];
|
|
84
|
-
|
|
85
|
-
if (!inQuotes && (char === '"' || char === "'" || char === "`")) {
|
|
86
|
-
inQuotes = true;
|
|
87
|
-
quoteChar = char;
|
|
88
|
-
current += char;
|
|
89
|
-
} else if (inQuotes && char === quoteChar) {
|
|
90
|
-
inQuotes = false;
|
|
91
|
-
quoteChar = "";
|
|
92
|
-
current += char;
|
|
93
|
-
} else if (!inQuotes && (char === "&" || char === "|" || char === ";")) {
|
|
94
|
-
if (current.trim()) commands.push(current.trim());
|
|
95
|
-
current = "";
|
|
96
|
-
// Skip the next char if it's part of && or ||
|
|
97
|
-
if ((char === "&" || char === "|") && command[i + 1] === char) i++;
|
|
98
|
-
} else {
|
|
99
|
-
current += char;
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
if (current.trim()) commands.push(current.trim());
|
|
104
|
-
return commands;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
54
|
export function evaluateFilePath(
|
|
108
55
|
filePath: string,
|
|
109
56
|
policy: SecurityPolicy,
|
|
@@ -23,14 +23,13 @@ export function parseToolPattern(pattern: string): { tool: string; glob: string
|
|
|
23
23
|
return match ? { tool: match[1], glob: match[2] } : null;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
function escapeRegex(str: string): string {
|
|
27
|
-
return str.replace(/[.*+?^${}()|[\]\\/\-]/g, "\\$&");
|
|
28
|
-
}
|
|
29
|
-
|
|
30
26
|
function convertGlobPart(glob: string): string {
|
|
27
|
+
// Replace wildcards FIRST, then escape the literal remainder — escaping first
|
|
28
|
+
// would turn `*` into `\*` and the wildcard replace would never fire.
|
|
31
29
|
return glob
|
|
32
|
-
.
|
|
33
|
-
.
|
|
30
|
+
.split("*")
|
|
31
|
+
.map((part) => RegExp.escape(part))
|
|
32
|
+
.join(".*");
|
|
34
33
|
}
|
|
35
34
|
|
|
36
35
|
export function globToRegex(glob: string, caseInsensitive: boolean = false): RegExp {
|
|
@@ -39,7 +38,7 @@ export function globToRegex(glob: string, caseInsensitive: boolean = false): Reg
|
|
|
39
38
|
if (colonIdx !== -1) {
|
|
40
39
|
const command = glob.slice(0, colonIdx);
|
|
41
40
|
const argsGlob = glob.slice(colonIdx + 1);
|
|
42
|
-
const escapedCmd =
|
|
41
|
+
const escapedCmd = RegExp.escape(command);
|
|
43
42
|
const argsRegex = convertGlobPart(argsGlob);
|
|
44
43
|
regexStr = `^${escapedCmd}(\\s${argsRegex})?$`;
|
|
45
44
|
} else {
|
|
@@ -68,7 +67,7 @@ export function fileGlobToRegex(glob: string, caseInsensitive: boolean = false):
|
|
|
68
67
|
regexStr += "[^/]";
|
|
69
68
|
i++;
|
|
70
69
|
} else {
|
|
71
|
-
regexStr +=
|
|
70
|
+
regexStr += RegExp.escape(glob[i]);
|
|
72
71
|
i++;
|
|
73
72
|
}
|
|
74
73
|
}
|
|
@@ -191,7 +191,6 @@ export class SessionDB {
|
|
|
191
191
|
p("addCompactionStats", `UPDATE session_meta SET total_chars_before = total_chars_before + ?, total_chars_kept = total_chars_kept + ?, total_messages_summarized = total_messages_summarized + ? WHERE session_id = ?`);
|
|
192
192
|
p("getAllTimeStats", `SELECT COALESCE(SUM(total_chars_before), 0) AS all_chars_before, COALESCE(SUM(total_chars_kept), 0) AS all_chars_kept, COALESCE(SUM(total_messages_summarized), 0) AS all_messages_summarized, COALESCE(SUM(compact_count), 0) AS all_compactions, COALESCE(SUM(sandbox_runs), 0) AS all_sandbox_runs, COALESCE(SUM(search_queries), 0) AS all_search_queries FROM session_meta`);
|
|
193
193
|
p("incrementSandboxRuns", `UPDATE session_meta SET sandbox_runs = sandbox_runs + 1 WHERE session_id = ?`);
|
|
194
|
-
p("incrementSearchQueries", `UPDATE session_meta SET search_queries = search_queries + 1 WHERE session_id = ?`);
|
|
195
194
|
p("upsertResume", `INSERT INTO session_resume (session_id, snapshot, event_count) VALUES (?, ?, ?) ON CONFLICT(session_id) DO UPDATE SET snapshot = excluded.snapshot, event_count = excluded.event_count, created_at = datetime('now'), consumed = 0`);
|
|
196
195
|
p("getResume", `SELECT snapshot, event_count, consumed FROM session_resume WHERE session_id = ?`);
|
|
197
196
|
p("markResumeConsumed", `UPDATE session_resume SET consumed = 1 WHERE session_id = ?`);
|
|
@@ -283,11 +282,6 @@ export class SessionDB {
|
|
|
283
282
|
this.stmt("incrementSandboxRuns").run(sessionId);
|
|
284
283
|
}
|
|
285
284
|
|
|
286
|
-
incrementSearchQueries(sessionId: string): void {
|
|
287
|
-
if (!this.stmts) return;
|
|
288
|
-
this.stmt("incrementSearchQueries").run(sessionId);
|
|
289
|
-
}
|
|
290
|
-
|
|
291
285
|
upsertResume(sessionId: string, snapshot: string, eventCount?: number): void {
|
|
292
286
|
if (!this.stmts) return;
|
|
293
287
|
this.stmt("upsertResume").run(sessionId, snapshot, eventCount ?? 0);
|
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
|
|
5
5
|
import { PolyglotExecutor } from "../executor/executor.js";
|
|
6
6
|
import type { Language, ExecResult } from "../types.js";
|
|
7
|
-
import { readFileSync } from "node:fs";
|
|
8
7
|
|
|
9
8
|
export interface CtxExecuteFileInput {
|
|
10
9
|
language: Language;
|
|
@@ -16,13 +15,9 @@ export async function ctxExecuteFile(
|
|
|
16
15
|
input: CtxExecuteFileInput,
|
|
17
16
|
executor = new PolyglotExecutor(),
|
|
18
17
|
): Promise<ExecResult> {
|
|
19
|
-
const content = readFileSync(input.path, "utf-8");
|
|
20
|
-
const code = `const FILE_CONTENT = ${JSON.stringify(content)};\n// User script follows:\n`;
|
|
21
|
-
|
|
22
18
|
return executor.executeFile({
|
|
23
19
|
language: input.language,
|
|
24
20
|
path: input.path,
|
|
25
|
-
code,
|
|
26
21
|
timeout: input.timeout ?? 30000,
|
|
27
22
|
});
|
|
28
23
|
}
|