@kolisachint/hoocode-agent 0.4.105 → 0.4.107
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 +16 -0
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +4 -4
- package/dist/cli/args.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +0 -1
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +2 -2
- package/dist/config.js.map +1 -1
- package/dist/core/agent-session.d.ts +1 -3
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +2 -2
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/bash-executor.d.ts.map +1 -1
- package/dist/core/bash-executor.js +1 -1
- package/dist/core/bash-executor.js.map +1 -1
- package/dist/core/extension-mcp-servers.d.ts +1 -1
- package/dist/core/extension-mcp-servers.d.ts.map +1 -1
- package/dist/core/extension-mcp-servers.js +1 -1
- package/dist/core/extension-mcp-servers.js.map +1 -1
- package/dist/core/extensions/plugins/index.d.ts.map +1 -1
- package/dist/core/extensions/plugins/index.js +1 -1
- package/dist/core/extensions/plugins/index.js.map +1 -1
- package/dist/core/extensions/types.d.ts +1 -3
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/index.d.ts +1 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/mode-prompts.d.ts +1 -1
- package/dist/core/mode-prompts.d.ts.map +1 -1
- package/dist/core/mode-prompts.js +1 -1
- package/dist/core/mode-prompts.js.map +1 -1
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js +1 -1
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +1 -2
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-manager.d.ts +2 -97
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +4 -65
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +2 -3
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/telemetry.d.ts.map +1 -1
- package/dist/core/telemetry.js +1 -1
- package/dist/core/telemetry.js.map +1 -1
- package/dist/core/timings.d.ts +1 -1
- package/dist/core/timings.d.ts.map +1 -1
- package/dist/core/timings.js +2 -2
- package/dist/core/timings.js.map +1 -1
- package/dist/core/tools/{browser-continue.d.ts → browser/browser-continue.d.ts} +1 -1
- package/dist/core/tools/browser/browser-continue.d.ts.map +1 -0
- package/dist/core/tools/{browser-continue.js → browser/browser-continue.js} +2 -2
- package/dist/core/tools/browser/browser-continue.js.map +1 -0
- package/dist/core/tools/{browser-run.d.ts → browser/browser-run.d.ts} +2 -2
- package/dist/core/tools/browser/browser-run.d.ts.map +1 -0
- package/dist/core/tools/{browser-run.js → browser/browser-run.js} +2 -2
- package/dist/core/tools/browser/browser-run.js.map +1 -0
- package/dist/core/tools/browser/browsertools-shared.d.ts.map +1 -0
- package/dist/core/tools/{browsertools-shared.js → browser/browsertools-shared.js} +1 -1
- package/dist/core/tools/browser/browsertools-shared.js.map +1 -0
- package/dist/core/tools/browser/index.d.ts +8 -0
- package/dist/core/tools/browser/index.d.ts.map +1 -0
- package/dist/core/tools/browser/index.js +8 -0
- package/dist/core/tools/browser/index.js.map +1 -0
- package/dist/core/tools/{docedit.d.ts → doc/docedit.d.ts} +2 -2
- package/dist/core/tools/doc/docedit.d.ts.map +1 -0
- package/dist/core/tools/{docedit.js → doc/docedit.js} +7 -7
- package/dist/core/tools/doc/docedit.js.map +1 -0
- package/dist/core/tools/{docgrep.d.ts → doc/docgrep.d.ts} +2 -2
- package/dist/core/tools/doc/docgrep.d.ts.map +1 -0
- package/dist/core/tools/{docgrep.js → doc/docgrep.js} +6 -6
- package/dist/core/tools/doc/docgrep.js.map +1 -0
- package/dist/core/tools/{docpeek.d.ts → doc/docpeek.d.ts} +2 -2
- package/dist/core/tools/{docpeek.js.map → doc/docpeek.d.ts.map} +1 -1
- package/dist/core/tools/{docpeek.js → doc/docpeek.js} +6 -6
- package/dist/core/tools/doc/docpeek.js.map +1 -0
- package/dist/core/tools/{docread.d.ts → doc/docread.d.ts} +2 -2
- package/dist/core/tools/doc/docread.d.ts.map +1 -0
- package/dist/core/tools/{docread.js → doc/docread.js} +6 -6
- package/dist/core/tools/doc/docread.js.map +1 -0
- package/dist/core/tools/{docscan.d.ts → doc/docscan.d.ts} +2 -2
- package/dist/core/tools/doc/docscan.d.ts.map +1 -0
- package/dist/core/tools/{docscan.js → doc/docscan.js} +6 -6
- package/dist/core/tools/doc/docscan.js.map +1 -0
- package/dist/core/tools/{docwrite.d.ts → doc/docwrite.d.ts} +1 -1
- package/dist/core/tools/doc/docwrite.d.ts.map +1 -0
- package/dist/core/tools/{docwrite.js → doc/docwrite.js} +6 -6
- package/dist/core/tools/doc/docwrite.js.map +1 -0
- package/dist/core/tools/doc/index.d.ts +11 -0
- package/dist/core/tools/doc/index.d.ts.map +1 -0
- package/dist/core/tools/doc/index.js +11 -0
- package/dist/core/tools/doc/index.js.map +1 -0
- package/dist/core/tools/grep.d.ts.map +1 -1
- package/dist/core/tools/grep.js +1 -1
- package/dist/core/tools/grep.js.map +1 -1
- package/dist/core/tools/index.d.ts +42 -28
- package/dist/core/tools/index.d.ts.map +1 -1
- package/dist/core/tools/index.js +61 -199
- package/dist/core/tools/index.js.map +1 -1
- package/dist/core/tools/output-accumulator.d.ts.map +1 -1
- package/dist/core/tools/output-accumulator.js +1 -1
- package/dist/core/tools/output-accumulator.js.map +1 -1
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +1 -1
- package/dist/core/tools/read.js.map +1 -1
- package/dist/extensions/core/ask-options.d.ts +10 -0
- package/dist/extensions/core/ask-options.d.ts.map +1 -0
- package/dist/extensions/core/ask-options.js +83 -0
- package/dist/extensions/core/ask-options.js.map +1 -0
- package/dist/extensions/core/config.d.ts +80 -0
- package/dist/extensions/core/config.d.ts.map +1 -0
- package/dist/extensions/core/config.js +110 -0
- package/dist/extensions/core/config.js.map +1 -0
- package/dist/extensions/core/cost.d.ts +11 -0
- package/dist/extensions/core/cost.d.ts.map +1 -0
- package/dist/extensions/core/cost.js +64 -0
- package/dist/extensions/core/cost.js.map +1 -0
- package/dist/extensions/core/hoo-core.d.ts +16 -179
- package/dist/extensions/core/hoo-core.d.ts.map +1 -1
- package/dist/extensions/core/hoo-core.js +27 -1663
- package/dist/extensions/core/hoo-core.js.map +1 -1
- package/dist/extensions/core/loop.d.ts +15 -0
- package/dist/extensions/core/loop.d.ts.map +1 -0
- package/dist/extensions/core/loop.js +235 -0
- package/dist/extensions/core/loop.js.map +1 -0
- package/dist/extensions/core/marketplace.d.ts +17 -0
- package/dist/extensions/core/marketplace.d.ts.map +1 -0
- package/dist/extensions/core/marketplace.js +167 -0
- package/dist/extensions/core/marketplace.js.map +1 -0
- package/dist/extensions/core/mcp-loader.d.ts +26 -0
- package/dist/extensions/core/mcp-loader.d.ts.map +1 -0
- package/dist/extensions/core/mcp-loader.js +391 -0
- package/dist/extensions/core/mcp-loader.js.map +1 -0
- package/dist/extensions/core/modes.d.ts +56 -0
- package/dist/extensions/core/modes.d.ts.map +1 -0
- package/dist/extensions/core/modes.js +268 -0
- package/dist/extensions/core/modes.js.map +1 -0
- package/dist/extensions/core/permission-gate.d.ts +10 -0
- package/dist/extensions/core/permission-gate.d.ts.map +1 -0
- package/dist/extensions/core/permission-gate.js +167 -0
- package/dist/extensions/core/permission-gate.js.map +1 -0
- package/dist/extensions/core/scaffold.d.ts +9 -0
- package/dist/extensions/core/scaffold.d.ts.map +1 -0
- package/dist/extensions/core/scaffold.js +146 -0
- package/dist/extensions/core/scaffold.js.map +1 -0
- package/dist/extensions/core/thinking-escalation.d.ts +18 -0
- package/dist/extensions/core/thinking-escalation.d.ts.map +1 -0
- package/dist/extensions/core/thinking-escalation.js +70 -0
- package/dist/extensions/core/thinking-escalation.js.map +1 -0
- package/dist/index.d.ts +2 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -4
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +2 -2
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/command-executor.d.ts +0 -5
- package/dist/modes/interactive/command-executor.d.ts.map +1 -1
- package/dist/modes/interactive/command-executor.js +0 -7
- package/dist/modes/interactive/command-executor.js.map +1 -1
- package/dist/modes/interactive/components/branch-summary-message.d.ts +1 -1
- package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.d.ts +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
- package/dist/modes/interactive/components/custom-message.d.ts +1 -1
- package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-message.js.map +1 -1
- package/dist/modes/interactive/components/index.d.ts +0 -2
- package/dist/modes/interactive/components/index.d.ts.map +1 -1
- package/dist/modes/interactive/components/index.js +0 -2
- package/dist/modes/interactive/components/index.js.map +1 -1
- package/dist/modes/interactive/extension-chrome.d.ts +56 -0
- package/dist/modes/interactive/extension-chrome.d.ts.map +1 -0
- package/dist/modes/interactive/extension-chrome.js +172 -0
- package/dist/modes/interactive/extension-chrome.js.map +1 -0
- package/dist/modes/interactive/extension-dialogs.d.ts +82 -0
- package/dist/modes/interactive/extension-dialogs.d.ts.map +1 -0
- package/dist/modes/interactive/extension-dialogs.js +259 -0
- package/dist/modes/interactive/extension-dialogs.js.map +1 -0
- package/dist/modes/interactive/interactive-mode.d.ts +11 -161
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +263 -1571
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/resource-display.d.ts +59 -0
- package/dist/modes/interactive/resource-display.d.ts.map +1 -0
- package/dist/modes/interactive/resource-display.js +499 -0
- package/dist/modes/interactive/resource-display.js.map +1 -0
- package/dist/modes/interactive/startup-checks.d.ts +17 -0
- package/dist/modes/interactive/startup-checks.d.ts.map +1 -0
- package/dist/modes/interactive/startup-checks.js +102 -0
- package/dist/modes/interactive/startup-checks.js.map +1 -0
- package/dist/modes/interactive/team-focus.d.ts +56 -0
- package/dist/modes/interactive/team-focus.d.ts.map +1 -0
- package/dist/modes/interactive/team-focus.js +167 -0
- package/dist/modes/interactive/team-focus.js.map +1 -0
- package/dist/modes/interactive/voice/voice-controller.d.ts +66 -0
- package/dist/modes/interactive/voice/voice-controller.d.ts.map +1 -0
- package/dist/modes/interactive/voice/voice-controller.js +312 -0
- package/dist/modes/interactive/voice/voice-controller.js.map +1 -0
- package/dist/modes/interactive/voice/voice-panel.d.ts.map +1 -0
- package/dist/modes/interactive/voice/voice-panel.js.map +1 -0
- package/dist/modes/interactive/{voice-transcribe.d.ts → voice/voice-transcribe.d.ts} +16 -1
- package/dist/modes/interactive/voice/voice-transcribe.d.ts.map +1 -0
- package/dist/modes/interactive/{voice-transcribe.js → voice/voice-transcribe.js} +31 -4
- package/dist/modes/interactive/voice/voice-transcribe.js.map +1 -0
- package/dist/modes/rpc/rpc-client.d.ts +1 -2
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts +1 -2
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-types.js.map +1 -1
- package/dist/resources-cli.d.ts.map +1 -1
- package/dist/resources-cli.js +1 -1
- package/dist/resources-cli.js.map +1 -1
- package/dist/utils/tools-manager.d.ts.map +1 -1
- package/dist/utils/tools-manager.js +1 -1
- package/dist/utils/tools-manager.js.map +1 -1
- package/dist/utils/version-check.d.ts.map +1 -1
- package/dist/utils/version-check.js +2 -2
- package/dist/utils/version-check.js.map +1 -1
- package/docs/project-local-resources.md +1 -1
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/with-deps/package.json +1 -1
- package/package.json +4 -4
- package/dist/core/compaction/branch-summarization.d.ts +0 -88
- package/dist/core/compaction/branch-summarization.d.ts.map +0 -1
- package/dist/core/compaction/branch-summarization.js +0 -243
- package/dist/core/compaction/branch-summarization.js.map +0 -1
- package/dist/core/compaction/compaction.d.ts +0 -123
- package/dist/core/compaction/compaction.d.ts.map +0 -1
- package/dist/core/compaction/compaction.js +0 -635
- package/dist/core/compaction/compaction.js.map +0 -1
- package/dist/core/compaction/index.d.ts +0 -7
- package/dist/core/compaction/index.d.ts.map +0 -1
- package/dist/core/compaction/index.js +0 -7
- package/dist/core/compaction/index.js.map +0 -1
- package/dist/core/compaction/utils.d.ts +0 -38
- package/dist/core/compaction/utils.d.ts.map +0 -1
- package/dist/core/compaction/utils.js +0 -156
- package/dist/core/compaction/utils.js.map +0 -1
- package/dist/core/messages.d.ts +0 -124
- package/dist/core/messages.d.ts.map +0 -1
- package/dist/core/messages.js +0 -221
- package/dist/core/messages.js.map +0 -1
- package/dist/core/tools/browser-continue.d.ts.map +0 -1
- package/dist/core/tools/browser-continue.js.map +0 -1
- package/dist/core/tools/browser-run.d.ts.map +0 -1
- package/dist/core/tools/browser-run.js.map +0 -1
- package/dist/core/tools/browsertools-shared.d.ts.map +0 -1
- package/dist/core/tools/browsertools-shared.js.map +0 -1
- package/dist/core/tools/docedit.d.ts.map +0 -1
- package/dist/core/tools/docedit.js.map +0 -1
- package/dist/core/tools/docgrep.d.ts.map +0 -1
- package/dist/core/tools/docgrep.js.map +0 -1
- package/dist/core/tools/docpeek.d.ts.map +0 -1
- package/dist/core/tools/docread.d.ts.map +0 -1
- package/dist/core/tools/docread.js.map +0 -1
- package/dist/core/tools/docscan.d.ts.map +0 -1
- package/dist/core/tools/docscan.js.map +0 -1
- package/dist/core/tools/docwrite.d.ts.map +0 -1
- package/dist/core/tools/docwrite.js.map +0 -1
- package/dist/core/tools/output-compression.d.ts +0 -53
- package/dist/core/tools/output-compression.d.ts.map +0 -1
- package/dist/core/tools/output-compression.js +0 -392
- package/dist/core/tools/output-compression.js.map +0 -1
- package/dist/modes/interactive/components/armin.d.ts +0 -34
- package/dist/modes/interactive/components/armin.d.ts.map +0 -1
- package/dist/modes/interactive/components/armin.js +0 -333
- package/dist/modes/interactive/components/armin.js.map +0 -1
- package/dist/modes/interactive/components/daxnuts.d.ts +0 -23
- package/dist/modes/interactive/components/daxnuts.d.ts.map +0 -1
- package/dist/modes/interactive/components/daxnuts.js +0 -140
- package/dist/modes/interactive/components/daxnuts.js.map +0 -1
- package/dist/modes/interactive/components/voice-panel.d.ts.map +0 -1
- package/dist/modes/interactive/components/voice-panel.js.map +0 -1
- package/dist/modes/interactive/voice-transcribe.d.ts.map +0 -1
- package/dist/modes/interactive/voice-transcribe.js.map +0 -1
- /package/dist/core/tools/{browsertools-shared.d.ts → browser/browsertools-shared.d.ts} +0 -0
- /package/dist/modes/interactive/{components → voice}/voice-panel.d.ts +0 -0
- /package/dist/modes/interactive/{components → voice}/voice-panel.js +0 -0
|
@@ -1,392 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Lossless output compression utilities for tool outputs.
|
|
3
|
-
*
|
|
4
|
-
* All compression is strictly lossless - no useful information is removed.
|
|
5
|
-
* Compression is command-aware where possible, and general-purpose otherwise.
|
|
6
|
-
*/
|
|
7
|
-
/** Minimum output size (in bytes) to apply compression. Below this, overhead exceeds savings. */
|
|
8
|
-
const MIN_COMPRESSION_SIZE = 1024; // 1KB
|
|
9
|
-
// ============================================================================
|
|
10
|
-
// General Compression (applied to all outputs)
|
|
11
|
-
// ============================================================================
|
|
12
|
-
/**
|
|
13
|
-
* Collapse 3+ consecutive blank lines to 2 (preserves paragraph separation).
|
|
14
|
-
*/
|
|
15
|
-
export function collapseBlankLines(text) {
|
|
16
|
-
return text.replace(/\n{3,}/g, "\n\n");
|
|
17
|
-
}
|
|
18
|
-
/**
|
|
19
|
-
* Strip trailing whitespace from each line.
|
|
20
|
-
*/
|
|
21
|
-
export function stripTrailingWhitespace(text) {
|
|
22
|
-
return text
|
|
23
|
-
.split("\n")
|
|
24
|
-
.map((line) => line.trimEnd())
|
|
25
|
-
.join("\n");
|
|
26
|
-
}
|
|
27
|
-
/**
|
|
28
|
-
* Remove duplicate consecutive lines (keeps first occurrence).
|
|
29
|
-
*/
|
|
30
|
-
export function removeDuplicateLines(text) {
|
|
31
|
-
const lines = text.split("\n");
|
|
32
|
-
const result = [];
|
|
33
|
-
let prevLine;
|
|
34
|
-
for (const line of lines) {
|
|
35
|
-
if (line !== prevLine) {
|
|
36
|
-
result.push(line);
|
|
37
|
-
prevLine = line;
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
return result.join("\n");
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* Apply general lossless compression to any output.
|
|
44
|
-
* Single-pass implementation for efficiency.
|
|
45
|
-
*/
|
|
46
|
-
export function compressGeneral(text) {
|
|
47
|
-
const lines = text.split("\n");
|
|
48
|
-
const result = [];
|
|
49
|
-
let blankCount = 0;
|
|
50
|
-
for (const line of lines) {
|
|
51
|
-
const trimmed = line.trimEnd();
|
|
52
|
-
if (trimmed === "") {
|
|
53
|
-
blankCount++;
|
|
54
|
-
// Allow at most 2 consecutive blank lines
|
|
55
|
-
if (blankCount <= 2) {
|
|
56
|
-
result.push(trimmed);
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
else {
|
|
60
|
-
blankCount = 0;
|
|
61
|
-
result.push(trimmed);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
return result.join("\n");
|
|
65
|
-
}
|
|
66
|
-
// ============================================================================
|
|
67
|
-
// Command-Specific Compression (bash only)
|
|
68
|
-
// ============================================================================
|
|
69
|
-
/**
|
|
70
|
-
* Detect the primary command from a bash command string.
|
|
71
|
-
*/
|
|
72
|
-
function detectCommand(command) {
|
|
73
|
-
const trimmed = command.trim();
|
|
74
|
-
// Strip leading env vars (FOO=bar command)
|
|
75
|
-
const withoutEnv = trimmed.replace(/^[A-Z_]+=\S+\s+/, "");
|
|
76
|
-
// Strip leading sudo
|
|
77
|
-
const withoutSudo = withoutEnv.replace(/^sudo\s+/, "");
|
|
78
|
-
// Get first word (the actual command)
|
|
79
|
-
const firstWord = withoutSudo.split(/\s+/)[0] ?? "";
|
|
80
|
-
// Strip path prefix if any
|
|
81
|
-
return firstWord.split("/").pop() ?? "";
|
|
82
|
-
}
|
|
83
|
-
/**
|
|
84
|
-
* Compress npm/yarn/pnpm install output.
|
|
85
|
-
* - Remove download progress lines
|
|
86
|
-
* - Collapse "added N packages" summaries
|
|
87
|
-
*/
|
|
88
|
-
function compressNpmInstall(output) {
|
|
89
|
-
const lines = output.split("\n");
|
|
90
|
-
const result = [];
|
|
91
|
-
for (const line of lines) {
|
|
92
|
-
// Skip download progress (e.g., "fetchMetadata: ...", "reify: ...")
|
|
93
|
-
if (/^(fetchMetadata|reify|audit|idealTree|sill|warn)\b/.test(line)) {
|
|
94
|
-
continue;
|
|
95
|
-
}
|
|
96
|
-
// Skip verbose fetch/cache lines
|
|
97
|
-
if (/^\s*(http|https|fetch|cache|tarball|extract)\b/.test(line)) {
|
|
98
|
-
continue;
|
|
99
|
-
}
|
|
100
|
-
// Keep everything else (errors, warnings, summaries)
|
|
101
|
-
result.push(line);
|
|
102
|
-
}
|
|
103
|
-
return result.join("\n");
|
|
104
|
-
}
|
|
105
|
-
/**
|
|
106
|
-
* Compress git diff output.
|
|
107
|
-
* - Strip file headers (diff --git, index, ---, +++)
|
|
108
|
-
* - Collapse unchanged context lines
|
|
109
|
-
*/
|
|
110
|
-
function compressGitDiff(output) {
|
|
111
|
-
const lines = output.split("\n");
|
|
112
|
-
const result = [];
|
|
113
|
-
let contextCount = 0;
|
|
114
|
-
for (const line of lines) {
|
|
115
|
-
// Skip git diff metadata
|
|
116
|
-
if (/^(diff --git|index [0-9a-f]+|--- a\/|\+\+\+ b\/)/.test(line)) {
|
|
117
|
-
continue;
|
|
118
|
-
}
|
|
119
|
-
// Count context lines (lines starting with space)
|
|
120
|
-
if (line.startsWith(" ") && !line.startsWith(" ")) {
|
|
121
|
-
contextCount++;
|
|
122
|
-
// Only show first 2 context lines per hunk, then skip
|
|
123
|
-
if (contextCount > 2) {
|
|
124
|
-
continue;
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
else {
|
|
128
|
-
contextCount = 0;
|
|
129
|
-
}
|
|
130
|
-
result.push(line);
|
|
131
|
-
}
|
|
132
|
-
return result.join("\n");
|
|
133
|
-
}
|
|
134
|
-
/**
|
|
135
|
-
* Compress cargo/rustc test output.
|
|
136
|
-
* - Collapse passing tests, keep failures
|
|
137
|
-
*/
|
|
138
|
-
function compressCargoTest(output) {
|
|
139
|
-
const lines = output.split("\n");
|
|
140
|
-
const result = [];
|
|
141
|
-
let passingCount = 0;
|
|
142
|
-
for (const line of lines) {
|
|
143
|
-
// Count passing test lines (e.g., "test foo ... ok")
|
|
144
|
-
if (/^test\s+.+\s+\.\.\.\s+ok\s*$/.test(line)) {
|
|
145
|
-
passingCount++;
|
|
146
|
-
continue;
|
|
147
|
-
}
|
|
148
|
-
// Count ignored tests
|
|
149
|
-
if (/^test\s+.+\s+\.\.\.\s+ignored\s*$/.test(line)) {
|
|
150
|
-
continue;
|
|
151
|
-
}
|
|
152
|
-
// Show test summary line
|
|
153
|
-
if (/^test result:/.test(line)) {
|
|
154
|
-
result.push(line);
|
|
155
|
-
continue;
|
|
156
|
-
}
|
|
157
|
-
// Keep failures, errors, and everything else
|
|
158
|
-
if (passingCount > 0 && line === "") {
|
|
159
|
-
// Add summary before blank line
|
|
160
|
-
result.push(` (${passingCount} passing tests omitted)`);
|
|
161
|
-
passingCount = 0;
|
|
162
|
-
}
|
|
163
|
-
result.push(line);
|
|
164
|
-
}
|
|
165
|
-
// Handle case where output ends with passing tests
|
|
166
|
-
if (passingCount > 0) {
|
|
167
|
-
result.push(` (${passingCount} passing tests omitted)`);
|
|
168
|
-
}
|
|
169
|
-
return result.join("\n");
|
|
170
|
-
}
|
|
171
|
-
/**
|
|
172
|
-
* Compress docker build output.
|
|
173
|
-
* - Strip layer download progress
|
|
174
|
-
* - Keep build steps and errors
|
|
175
|
-
*/
|
|
176
|
-
function compressDockerBuild(output) {
|
|
177
|
-
const lines = output.split("\n");
|
|
178
|
-
const result = [];
|
|
179
|
-
for (const line of lines) {
|
|
180
|
-
// Skip download progress (e.g., "Downloading layer...")
|
|
181
|
-
if (/^(Downloading|Pulling|Extracting|Waiting|Verifying)/.test(line)) {
|
|
182
|
-
continue;
|
|
183
|
-
}
|
|
184
|
-
// Skip progress bars
|
|
185
|
-
if (/[\u2588\u2591\u2592]{10,}/.test(line)) {
|
|
186
|
-
continue;
|
|
187
|
-
}
|
|
188
|
-
// Keep build steps (FROM, RUN, COPY, etc.) and errors
|
|
189
|
-
result.push(line);
|
|
190
|
-
}
|
|
191
|
-
return result.join("\n");
|
|
192
|
-
}
|
|
193
|
-
/**
|
|
194
|
-
* Compress jest/mocha test output.
|
|
195
|
-
* - Collapse passing tests
|
|
196
|
-
* - Keep failures
|
|
197
|
-
*/
|
|
198
|
-
function compressJsTest(output) {
|
|
199
|
-
const lines = output.split("\n");
|
|
200
|
-
const result = [];
|
|
201
|
-
let passingCount = 0;
|
|
202
|
-
for (const line of lines) {
|
|
203
|
-
// Skip passing test indicators (✓, ✔, ○)
|
|
204
|
-
if (/^\s*[✓✔○●]\s+/.test(line)) {
|
|
205
|
-
passingCount++;
|
|
206
|
-
continue;
|
|
207
|
-
}
|
|
208
|
-
// Skip passing test lines (e.g., " PASS src/foo.test.ts")
|
|
209
|
-
if (/^\s*PASS\s+/.test(line)) {
|
|
210
|
-
passingCount++;
|
|
211
|
-
continue;
|
|
212
|
-
}
|
|
213
|
-
// Show test summary
|
|
214
|
-
if (/^(Tests|Test Suites):/.test(line)) {
|
|
215
|
-
result.push(line);
|
|
216
|
-
continue;
|
|
217
|
-
}
|
|
218
|
-
// Keep failures (×, ✗, FAIL) and everything else
|
|
219
|
-
if (passingCount > 0 && (line.includes("FAIL") || line.includes("×") || line.includes("✗"))) {
|
|
220
|
-
result.push(` (${passingCount} passing tests omitted)`);
|
|
221
|
-
passingCount = 0;
|
|
222
|
-
}
|
|
223
|
-
result.push(line);
|
|
224
|
-
}
|
|
225
|
-
if (passingCount > 0) {
|
|
226
|
-
result.push(` (${passingCount} passing tests omitted)`);
|
|
227
|
-
}
|
|
228
|
-
return result.join("\n");
|
|
229
|
-
}
|
|
230
|
-
/**
|
|
231
|
-
* Compress go test output.
|
|
232
|
-
* - Collapse passing tests
|
|
233
|
-
* - Keep failures
|
|
234
|
-
*/
|
|
235
|
-
function compressGoTest(output) {
|
|
236
|
-
const lines = output.split("\n");
|
|
237
|
-
const result = [];
|
|
238
|
-
let passingCount = 0;
|
|
239
|
-
for (const line of lines) {
|
|
240
|
-
// Skip passing test lines (e.g., "--- PASS: TestFoo (0.00s)")
|
|
241
|
-
if (/^---\s+PASS:/.test(line)) {
|
|
242
|
-
passingCount++;
|
|
243
|
-
continue;
|
|
244
|
-
}
|
|
245
|
-
// Skip PASS lines
|
|
246
|
-
if (/^PASS$/.test(line)) {
|
|
247
|
-
continue;
|
|
248
|
-
}
|
|
249
|
-
// Show test summary
|
|
250
|
-
if (/^(ok|FAIL)\s+/.test(line)) {
|
|
251
|
-
result.push(line);
|
|
252
|
-
continue;
|
|
253
|
-
}
|
|
254
|
-
// Keep failures and everything else
|
|
255
|
-
if (passingCount > 0 && line.includes("FAIL")) {
|
|
256
|
-
result.push(` (${passingCount} passing tests omitted)`);
|
|
257
|
-
passingCount = 0;
|
|
258
|
-
}
|
|
259
|
-
result.push(line);
|
|
260
|
-
}
|
|
261
|
-
if (passingCount > 0) {
|
|
262
|
-
result.push(` (${passingCount} passing tests omitted)`);
|
|
263
|
-
}
|
|
264
|
-
return result.join("\n");
|
|
265
|
-
}
|
|
266
|
-
/**
|
|
267
|
-
* Apply command-specific compression based on the detected command.
|
|
268
|
-
*/
|
|
269
|
-
function compressCommandSpecific(command, output) {
|
|
270
|
-
const cmd = detectCommand(command);
|
|
271
|
-
switch (cmd) {
|
|
272
|
-
case "npm":
|
|
273
|
-
case "yarn":
|
|
274
|
-
case "pnpm":
|
|
275
|
-
// Check if it's an install/add command
|
|
276
|
-
if (/\b(install|add|i)\b/.test(command)) {
|
|
277
|
-
return compressNpmInstall(output);
|
|
278
|
-
}
|
|
279
|
-
break;
|
|
280
|
-
case "git":
|
|
281
|
-
// Check if it's a diff command
|
|
282
|
-
if (/\bdiff\b/.test(command)) {
|
|
283
|
-
return compressGitDiff(output);
|
|
284
|
-
}
|
|
285
|
-
break;
|
|
286
|
-
case "cargo":
|
|
287
|
-
// Check if it's a test command
|
|
288
|
-
if (/\btest\b/.test(command)) {
|
|
289
|
-
return compressCargoTest(output);
|
|
290
|
-
}
|
|
291
|
-
break;
|
|
292
|
-
case "docker":
|
|
293
|
-
// Check if it's a build command
|
|
294
|
-
if (/\bbuild\b/.test(command)) {
|
|
295
|
-
return compressDockerBuild(output);
|
|
296
|
-
}
|
|
297
|
-
break;
|
|
298
|
-
case "jest":
|
|
299
|
-
case "mocha":
|
|
300
|
-
case "vitest":
|
|
301
|
-
case "pytest":
|
|
302
|
-
return compressJsTest(output);
|
|
303
|
-
case "go":
|
|
304
|
-
// Check if it's a test command
|
|
305
|
-
if (/\btest\b/.test(command)) {
|
|
306
|
-
return compressGoTest(output);
|
|
307
|
-
}
|
|
308
|
-
break;
|
|
309
|
-
}
|
|
310
|
-
return output;
|
|
311
|
-
}
|
|
312
|
-
/**
|
|
313
|
-
* Strip common noise patterns from any bash output.
|
|
314
|
-
* This is applied to all commands regardless of detection.
|
|
315
|
-
*/
|
|
316
|
-
function stripNoisePatterns(text) {
|
|
317
|
-
return (text
|
|
318
|
-
// Strip npm warnings (keep errors)
|
|
319
|
-
.replace(/^npm (warn|notice) .+$/gm, "")
|
|
320
|
-
// Strip yarn warnings
|
|
321
|
-
.replace(/^warning .+$/gm, "")
|
|
322
|
-
// Strip pnpm warnings
|
|
323
|
-
.replace(/^pnpm (warn|notice) .+$/gm, "")
|
|
324
|
-
// Strip common shell warnings
|
|
325
|
-
.replace(/^bash: .+ warning: .+$/gm, "")
|
|
326
|
-
// Strip "The command completed with non-zero exit status" noise
|
|
327
|
-
.replace(/^The command exited with exit code .+$/gm, ""));
|
|
328
|
-
}
|
|
329
|
-
/**
|
|
330
|
-
* Apply all compression to a bash command output.
|
|
331
|
-
* This is the main entry point for bash output compression.
|
|
332
|
-
*
|
|
333
|
-
* @param command - The bash command that was executed
|
|
334
|
-
* @param output - The raw output from the command
|
|
335
|
-
* @returns Compressed output (lossless)
|
|
336
|
-
*/
|
|
337
|
-
export function compressBashOutput(command, output) {
|
|
338
|
-
// Skip compression for small outputs (overhead > savings)
|
|
339
|
-
if (Buffer.byteLength(output, "utf-8") < MIN_COMPRESSION_SIZE) {
|
|
340
|
-
return output;
|
|
341
|
-
}
|
|
342
|
-
let result = output;
|
|
343
|
-
// Phase 1: Strip noise patterns
|
|
344
|
-
result = stripNoisePatterns(result);
|
|
345
|
-
// Phase 2: Command-specific compression
|
|
346
|
-
result = compressCommandSpecific(command, result);
|
|
347
|
-
// Phase 3: General compression
|
|
348
|
-
result = compressGeneral(result);
|
|
349
|
-
return result;
|
|
350
|
-
}
|
|
351
|
-
/**
|
|
352
|
-
* Apply compression to grep output.
|
|
353
|
-
* This strips redundant context and normalizes output.
|
|
354
|
-
*/
|
|
355
|
-
export function compressGrepOutput(output) {
|
|
356
|
-
if (Buffer.byteLength(output, "utf-8") < MIN_COMPRESSION_SIZE) {
|
|
357
|
-
return output;
|
|
358
|
-
}
|
|
359
|
-
return compressGeneral(output);
|
|
360
|
-
}
|
|
361
|
-
/**
|
|
362
|
-
* Apply compression to read output.
|
|
363
|
-
* This normalizes whitespace but preserves content.
|
|
364
|
-
*/
|
|
365
|
-
export function compressReadOutput(output) {
|
|
366
|
-
// For read, we only do light compression - no line collapsing
|
|
367
|
-
if (Buffer.byteLength(output, "utf-8") < MIN_COMPRESSION_SIZE) {
|
|
368
|
-
return output;
|
|
369
|
-
}
|
|
370
|
-
return stripTrailingWhitespace(output);
|
|
371
|
-
}
|
|
372
|
-
/**
|
|
373
|
-
* Apply compression to find output.
|
|
374
|
-
* This normalizes paths and removes duplicates.
|
|
375
|
-
*/
|
|
376
|
-
export function compressFindOutput(output) {
|
|
377
|
-
if (Buffer.byteLength(output, "utf-8") < MIN_COMPRESSION_SIZE) {
|
|
378
|
-
return output;
|
|
379
|
-
}
|
|
380
|
-
return compressGeneral(output);
|
|
381
|
-
}
|
|
382
|
-
/**
|
|
383
|
-
* Apply compression to ls output.
|
|
384
|
-
* This normalizes formatting.
|
|
385
|
-
*/
|
|
386
|
-
export function compressLsOutput(output) {
|
|
387
|
-
if (Buffer.byteLength(output, "utf-8") < MIN_COMPRESSION_SIZE) {
|
|
388
|
-
return output;
|
|
389
|
-
}
|
|
390
|
-
return compressGeneral(output);
|
|
391
|
-
}
|
|
392
|
-
//# sourceMappingURL=output-compression.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"output-compression.js","sourceRoot":"","sources":["../../../src/core/tools/output-compression.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Lossless output compression utilities for tool outputs.\n *\n * All compression is strictly lossless - no useful information is removed.\n * Compression is command-aware where possible, and general-purpose otherwise.\n */\n\n/** Minimum output size (in bytes) to apply compression. Below this, overhead exceeds savings. */\nconst MIN_COMPRESSION_SIZE = 1024; // 1KB\n\n// ============================================================================\n// General Compression (applied to all outputs)\n// ============================================================================\n\n/**\n * Collapse 3+ consecutive blank lines to 2 (preserves paragraph separation).\n */\nexport function collapseBlankLines(text: string): string {\n\treturn text.replace(/\\n{3,}/g, \"\\n\\n\");\n}\n\n/**\n * Strip trailing whitespace from each line.\n */\nexport function stripTrailingWhitespace(text: string): string {\n\treturn text\n\t\t.split(\"\\n\")\n\t\t.map((line) => line.trimEnd())\n\t\t.join(\"\\n\");\n}\n\n/**\n * Remove duplicate consecutive lines (keeps first occurrence).\n */\nexport function removeDuplicateLines(text: string): string {\n\tconst lines = text.split(\"\\n\");\n\tconst result: string[] = [];\n\tlet prevLine: string | undefined;\n\n\tfor (const line of lines) {\n\t\tif (line !== prevLine) {\n\t\t\tresult.push(line);\n\t\t\tprevLine = line;\n\t\t}\n\t}\n\n\treturn result.join(\"\\n\");\n}\n\n/**\n * Apply general lossless compression to any output.\n * Single-pass implementation for efficiency.\n */\nexport function compressGeneral(text: string): string {\n\tconst lines = text.split(\"\\n\");\n\tconst result: string[] = [];\n\tlet blankCount = 0;\n\n\tfor (const line of lines) {\n\t\tconst trimmed = line.trimEnd();\n\n\t\tif (trimmed === \"\") {\n\t\t\tblankCount++;\n\t\t\t// Allow at most 2 consecutive blank lines\n\t\t\tif (blankCount <= 2) {\n\t\t\t\tresult.push(trimmed);\n\t\t\t}\n\t\t} else {\n\t\t\tblankCount = 0;\n\t\t\tresult.push(trimmed);\n\t\t}\n\t}\n\n\treturn result.join(\"\\n\");\n}\n\n// ============================================================================\n// Command-Specific Compression (bash only)\n// ============================================================================\n\n/**\n * Detect the primary command from a bash command string.\n */\nfunction detectCommand(command: string): string {\n\tconst trimmed = command.trim();\n\t// Strip leading env vars (FOO=bar command)\n\tconst withoutEnv = trimmed.replace(/^[A-Z_]+=\\S+\\s+/, \"\");\n\t// Strip leading sudo\n\tconst withoutSudo = withoutEnv.replace(/^sudo\\s+/, \"\");\n\t// Get first word (the actual command)\n\tconst firstWord = withoutSudo.split(/\\s+/)[0] ?? \"\";\n\t// Strip path prefix if any\n\treturn firstWord.split(\"/\").pop() ?? \"\";\n}\n\n/**\n * Compress npm/yarn/pnpm install output.\n * - Remove download progress lines\n * - Collapse \"added N packages\" summaries\n */\nfunction compressNpmInstall(output: string): string {\n\tconst lines = output.split(\"\\n\");\n\tconst result: string[] = [];\n\n\tfor (const line of lines) {\n\t\t// Skip download progress (e.g., \"fetchMetadata: ...\", \"reify: ...\")\n\t\tif (/^(fetchMetadata|reify|audit|idealTree|sill|warn)\\b/.test(line)) {\n\t\t\tcontinue;\n\t\t}\n\t\t// Skip verbose fetch/cache lines\n\t\tif (/^\\s*(http|https|fetch|cache|tarball|extract)\\b/.test(line)) {\n\t\t\tcontinue;\n\t\t}\n\t\t// Keep everything else (errors, warnings, summaries)\n\t\tresult.push(line);\n\t}\n\n\treturn result.join(\"\\n\");\n}\n\n/**\n * Compress git diff output.\n * - Strip file headers (diff --git, index, ---, +++)\n * - Collapse unchanged context lines\n */\nfunction compressGitDiff(output: string): string {\n\tconst lines = output.split(\"\\n\");\n\tconst result: string[] = [];\n\tlet contextCount = 0;\n\n\tfor (const line of lines) {\n\t\t// Skip git diff metadata\n\t\tif (/^(diff --git|index [0-9a-f]+|--- a\\/|\\+\\+\\+ b\\/)/.test(line)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Count context lines (lines starting with space)\n\t\tif (line.startsWith(\" \") && !line.startsWith(\" \")) {\n\t\t\tcontextCount++;\n\t\t\t// Only show first 2 context lines per hunk, then skip\n\t\t\tif (contextCount > 2) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t} else {\n\t\t\tcontextCount = 0;\n\t\t}\n\n\t\tresult.push(line);\n\t}\n\n\treturn result.join(\"\\n\");\n}\n\n/**\n * Compress cargo/rustc test output.\n * - Collapse passing tests, keep failures\n */\nfunction compressCargoTest(output: string): string {\n\tconst lines = output.split(\"\\n\");\n\tconst result: string[] = [];\n\tlet passingCount = 0;\n\n\tfor (const line of lines) {\n\t\t// Count passing test lines (e.g., \"test foo ... ok\")\n\t\tif (/^test\\s+.+\\s+\\.\\.\\.\\s+ok\\s*$/.test(line)) {\n\t\t\tpassingCount++;\n\t\t\tcontinue;\n\t\t}\n\t\t// Count ignored tests\n\t\tif (/^test\\s+.+\\s+\\.\\.\\.\\s+ignored\\s*$/.test(line)) {\n\t\t\tcontinue;\n\t\t}\n\t\t// Show test summary line\n\t\tif (/^test result:/.test(line)) {\n\t\t\tresult.push(line);\n\t\t\tcontinue;\n\t\t}\n\t\t// Keep failures, errors, and everything else\n\t\tif (passingCount > 0 && line === \"\") {\n\t\t\t// Add summary before blank line\n\t\t\tresult.push(` (${passingCount} passing tests omitted)`);\n\t\t\tpassingCount = 0;\n\t\t}\n\t\tresult.push(line);\n\t}\n\n\t// Handle case where output ends with passing tests\n\tif (passingCount > 0) {\n\t\tresult.push(` (${passingCount} passing tests omitted)`);\n\t}\n\n\treturn result.join(\"\\n\");\n}\n\n/**\n * Compress docker build output.\n * - Strip layer download progress\n * - Keep build steps and errors\n */\nfunction compressDockerBuild(output: string): string {\n\tconst lines = output.split(\"\\n\");\n\tconst result: string[] = [];\n\n\tfor (const line of lines) {\n\t\t// Skip download progress (e.g., \"Downloading layer...\")\n\t\tif (/^(Downloading|Pulling|Extracting|Waiting|Verifying)/.test(line)) {\n\t\t\tcontinue;\n\t\t}\n\t\t// Skip progress bars\n\t\tif (/[\\u2588\\u2591\\u2592]{10,}/.test(line)) {\n\t\t\tcontinue;\n\t\t}\n\t\t// Keep build steps (FROM, RUN, COPY, etc.) and errors\n\t\tresult.push(line);\n\t}\n\n\treturn result.join(\"\\n\");\n}\n\n/**\n * Compress jest/mocha test output.\n * - Collapse passing tests\n * - Keep failures\n */\nfunction compressJsTest(output: string): string {\n\tconst lines = output.split(\"\\n\");\n\tconst result: string[] = [];\n\tlet passingCount = 0;\n\n\tfor (const line of lines) {\n\t\t// Skip passing test indicators (✓, ✔, ○)\n\t\tif (/^\\s*[✓✔○●]\\s+/.test(line)) {\n\t\t\tpassingCount++;\n\t\t\tcontinue;\n\t\t}\n\t\t// Skip passing test lines (e.g., \" PASS src/foo.test.ts\")\n\t\tif (/^\\s*PASS\\s+/.test(line)) {\n\t\t\tpassingCount++;\n\t\t\tcontinue;\n\t\t}\n\t\t// Show test summary\n\t\tif (/^(Tests|Test Suites):/.test(line)) {\n\t\t\tresult.push(line);\n\t\t\tcontinue;\n\t\t}\n\t\t// Keep failures (×, ✗, FAIL) and everything else\n\t\tif (passingCount > 0 && (line.includes(\"FAIL\") || line.includes(\"×\") || line.includes(\"✗\"))) {\n\t\t\tresult.push(` (${passingCount} passing tests omitted)`);\n\t\t\tpassingCount = 0;\n\t\t}\n\t\tresult.push(line);\n\t}\n\n\tif (passingCount > 0) {\n\t\tresult.push(` (${passingCount} passing tests omitted)`);\n\t}\n\n\treturn result.join(\"\\n\");\n}\n\n/**\n * Compress go test output.\n * - Collapse passing tests\n * - Keep failures\n */\nfunction compressGoTest(output: string): string {\n\tconst lines = output.split(\"\\n\");\n\tconst result: string[] = [];\n\tlet passingCount = 0;\n\n\tfor (const line of lines) {\n\t\t// Skip passing test lines (e.g., \"--- PASS: TestFoo (0.00s)\")\n\t\tif (/^---\\s+PASS:/.test(line)) {\n\t\t\tpassingCount++;\n\t\t\tcontinue;\n\t\t}\n\t\t// Skip PASS lines\n\t\tif (/^PASS$/.test(line)) {\n\t\t\tcontinue;\n\t\t}\n\t\t// Show test summary\n\t\tif (/^(ok|FAIL)\\s+/.test(line)) {\n\t\t\tresult.push(line);\n\t\t\tcontinue;\n\t\t}\n\t\t// Keep failures and everything else\n\t\tif (passingCount > 0 && line.includes(\"FAIL\")) {\n\t\t\tresult.push(` (${passingCount} passing tests omitted)`);\n\t\t\tpassingCount = 0;\n\t\t}\n\t\tresult.push(line);\n\t}\n\n\tif (passingCount > 0) {\n\t\tresult.push(` (${passingCount} passing tests omitted)`);\n\t}\n\n\treturn result.join(\"\\n\");\n}\n\n/**\n * Apply command-specific compression based on the detected command.\n */\nfunction compressCommandSpecific(command: string, output: string): string {\n\tconst cmd = detectCommand(command);\n\n\tswitch (cmd) {\n\t\tcase \"npm\":\n\t\tcase \"yarn\":\n\t\tcase \"pnpm\":\n\t\t\t// Check if it's an install/add command\n\t\t\tif (/\\b(install|add|i)\\b/.test(command)) {\n\t\t\t\treturn compressNpmInstall(output);\n\t\t\t}\n\t\t\tbreak;\n\t\tcase \"git\":\n\t\t\t// Check if it's a diff command\n\t\t\tif (/\\bdiff\\b/.test(command)) {\n\t\t\t\treturn compressGitDiff(output);\n\t\t\t}\n\t\t\tbreak;\n\t\tcase \"cargo\":\n\t\t\t// Check if it's a test command\n\t\t\tif (/\\btest\\b/.test(command)) {\n\t\t\t\treturn compressCargoTest(output);\n\t\t\t}\n\t\t\tbreak;\n\t\tcase \"docker\":\n\t\t\t// Check if it's a build command\n\t\t\tif (/\\bbuild\\b/.test(command)) {\n\t\t\t\treturn compressDockerBuild(output);\n\t\t\t}\n\t\t\tbreak;\n\t\tcase \"jest\":\n\t\tcase \"mocha\":\n\t\tcase \"vitest\":\n\t\tcase \"pytest\":\n\t\t\treturn compressJsTest(output);\n\t\tcase \"go\":\n\t\t\t// Check if it's a test command\n\t\t\tif (/\\btest\\b/.test(command)) {\n\t\t\t\treturn compressGoTest(output);\n\t\t\t}\n\t\t\tbreak;\n\t}\n\n\treturn output;\n}\n\n/**\n * Strip common noise patterns from any bash output.\n * This is applied to all commands regardless of detection.\n */\nfunction stripNoisePatterns(text: string): string {\n\treturn (\n\t\ttext\n\t\t\t// Strip npm warnings (keep errors)\n\t\t\t.replace(/^npm (warn|notice) .+$/gm, \"\")\n\t\t\t// Strip yarn warnings\n\t\t\t.replace(/^warning .+$/gm, \"\")\n\t\t\t// Strip pnpm warnings\n\t\t\t.replace(/^pnpm (warn|notice) .+$/gm, \"\")\n\t\t\t// Strip common shell warnings\n\t\t\t.replace(/^bash: .+ warning: .+$/gm, \"\")\n\t\t\t// Strip \"The command completed with non-zero exit status\" noise\n\t\t\t.replace(/^The command exited with exit code .+$/gm, \"\")\n\t);\n}\n\n/**\n * Apply all compression to a bash command output.\n * This is the main entry point for bash output compression.\n *\n * @param command - The bash command that was executed\n * @param output - The raw output from the command\n * @returns Compressed output (lossless)\n */\nexport function compressBashOutput(command: string, output: string): string {\n\t// Skip compression for small outputs (overhead > savings)\n\tif (Buffer.byteLength(output, \"utf-8\") < MIN_COMPRESSION_SIZE) {\n\t\treturn output;\n\t}\n\n\tlet result = output;\n\n\t// Phase 1: Strip noise patterns\n\tresult = stripNoisePatterns(result);\n\n\t// Phase 2: Command-specific compression\n\tresult = compressCommandSpecific(command, result);\n\n\t// Phase 3: General compression\n\tresult = compressGeneral(result);\n\n\treturn result;\n}\n\n/**\n * Apply compression to grep output.\n * This strips redundant context and normalizes output.\n */\nexport function compressGrepOutput(output: string): string {\n\tif (Buffer.byteLength(output, \"utf-8\") < MIN_COMPRESSION_SIZE) {\n\t\treturn output;\n\t}\n\treturn compressGeneral(output);\n}\n\n/**\n * Apply compression to read output.\n * This normalizes whitespace but preserves content.\n */\nexport function compressReadOutput(output: string): string {\n\t// For read, we only do light compression - no line collapsing\n\tif (Buffer.byteLength(output, \"utf-8\") < MIN_COMPRESSION_SIZE) {\n\t\treturn output;\n\t}\n\treturn stripTrailingWhitespace(output);\n}\n\n/**\n * Apply compression to find output.\n * This normalizes paths and removes duplicates.\n */\nexport function compressFindOutput(output: string): string {\n\tif (Buffer.byteLength(output, \"utf-8\") < MIN_COMPRESSION_SIZE) {\n\t\treturn output;\n\t}\n\treturn compressGeneral(output);\n}\n\n/**\n * Apply compression to ls output.\n * This normalizes formatting.\n */\nexport function compressLsOutput(output: string): string {\n\tif (Buffer.byteLength(output, \"utf-8\") < MIN_COMPRESSION_SIZE) {\n\t\treturn output;\n\t}\n\treturn compressGeneral(output);\n}\n"]}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Armin says hi! A fun easter egg with animated XBM art.
|
|
3
|
-
*/
|
|
4
|
-
import type { Component, TUI } from "@kolisachint/hoocode-tui";
|
|
5
|
-
export declare class ArminComponent implements Component {
|
|
6
|
-
private ui;
|
|
7
|
-
private interval;
|
|
8
|
-
private effect;
|
|
9
|
-
private finalGrid;
|
|
10
|
-
private currentGrid;
|
|
11
|
-
private effectState;
|
|
12
|
-
private cachedLines;
|
|
13
|
-
private cachedWidth;
|
|
14
|
-
private gridVersion;
|
|
15
|
-
private cachedVersion;
|
|
16
|
-
constructor(ui: TUI);
|
|
17
|
-
invalidate(): void;
|
|
18
|
-
render(width: number): string[];
|
|
19
|
-
private createEmptyGrid;
|
|
20
|
-
private initEffect;
|
|
21
|
-
private startAnimation;
|
|
22
|
-
private stopAnimation;
|
|
23
|
-
private tickEffect;
|
|
24
|
-
private tickTypewriter;
|
|
25
|
-
private tickScanline;
|
|
26
|
-
private tickRain;
|
|
27
|
-
private tickFade;
|
|
28
|
-
private tickCrt;
|
|
29
|
-
private tickGlitch;
|
|
30
|
-
private tickDissolve;
|
|
31
|
-
private updateDisplay;
|
|
32
|
-
dispose(): void;
|
|
33
|
-
}
|
|
34
|
-
//# sourceMappingURL=armin.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"armin.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/armin.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,0BAA0B,CAAC;AAuD/D,qBAAa,cAAe,YAAW,SAAS;IAC/C,OAAO,CAAC,EAAE,CAAM;IAChB,OAAO,CAAC,QAAQ,CAA+C;IAC/D,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,SAAS,CAAa;IAC9B,OAAO,CAAC,WAAW,CAAa;IAChC,OAAO,CAAC,WAAW,CAA+B;IAClD,OAAO,CAAC,WAAW,CAAgB;IACnC,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,aAAa,CAAM;IAE3B,YAAY,EAAE,EAAE,GAAG,EAQlB;IAED,UAAU,IAAI,IAAI,CAEjB;IAED,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAwB9B;IAED,OAAO,CAAC,eAAe;IAIvB,OAAO,CAAC,UAAU;IAgElB,OAAO,CAAC,cAAc;IAYtB,OAAO,CAAC,aAAa;IAOrB,OAAO,CAAC,UAAU;IAqBlB,OAAO,CAAC,cAAc;IActB,OAAO,CAAC,YAAY;IAYpB,OAAO,CAAC,QAAQ;IAmDhB,OAAO,CAAC,QAAQ;IAahB,OAAO,CAAC,OAAO;IAoBf,OAAO,CAAC,UAAU;IAgClB,OAAO,CAAC,YAAY;IAapB,OAAO,CAAC,aAAa;IAIrB,OAAO,IAAI,IAAI,CAEd;CACD","sourcesContent":["/**\n * Armin says hi! A fun easter egg with animated XBM art.\n */\n\nimport type { Component, TUI } from \"@kolisachint/hoocode-tui\";\nimport { theme } from \"../theme/theme.js\";\n\n// XBM image: 31x36 pixels, LSB first, 1=background, 0=foreground\nconst WIDTH = 31;\nconst HEIGHT = 36;\nconst BITS = [\n\t0xff, 0xff, 0xff, 0x7f, 0xff, 0xf0, 0xff, 0x7f, 0xff, 0xed, 0xff, 0x7f, 0xff, 0xdb, 0xff, 0x7f, 0xff, 0xb7, 0xff,\n\t0x7f, 0xff, 0x77, 0xfe, 0x7f, 0x3f, 0xf8, 0xfe, 0x7f, 0xdf, 0xff, 0xfe, 0x7f, 0xdf, 0x3f, 0xfc, 0x7f, 0x9f, 0xc3,\n\t0xfb, 0x7f, 0x6f, 0xfc, 0xf4, 0x7f, 0xf7, 0x0f, 0xf7, 0x7f, 0xf7, 0xff, 0xf7, 0x7f, 0xf7, 0xff, 0xe3, 0x7f, 0xf7,\n\t0x07, 0xe8, 0x7f, 0xef, 0xf8, 0x67, 0x70, 0x0f, 0xff, 0xbb, 0x6f, 0xf1, 0x00, 0xd0, 0x5b, 0xfd, 0x3f, 0xec, 0x53,\n\t0xc1, 0xff, 0xef, 0x57, 0x9f, 0xfd, 0xee, 0x5f, 0x9f, 0xfc, 0xae, 0x5f, 0x1f, 0x78, 0xac, 0x5f, 0x3f, 0x00, 0x50,\n\t0x6c, 0x7f, 0x00, 0xdc, 0x77, 0xff, 0xc0, 0x3f, 0x78, 0xff, 0x01, 0xf8, 0x7f, 0xff, 0x03, 0x9c, 0x78, 0xff, 0x07,\n\t0x8c, 0x7c, 0xff, 0x0f, 0xce, 0x78, 0xff, 0xff, 0xcf, 0x7f, 0xff, 0xff, 0xcf, 0x78, 0xff, 0xff, 0xdf, 0x78, 0xff,\n\t0xff, 0xdf, 0x7d, 0xff, 0xff, 0x3f, 0x7e, 0xff, 0xff, 0xff, 0x7f,\n];\n\nconst BYTES_PER_ROW = Math.ceil(WIDTH / 8);\nconst DISPLAY_HEIGHT = Math.ceil(HEIGHT / 2); // Half-block rendering\n\ntype Effect = \"typewriter\" | \"scanline\" | \"rain\" | \"fade\" | \"crt\" | \"glitch\" | \"dissolve\";\n\nconst EFFECTS: Effect[] = [\"typewriter\", \"scanline\", \"rain\", \"fade\", \"crt\", \"glitch\", \"dissolve\"];\n\n// Get pixel at (x, y): true = foreground, false = background\nfunction getPixel(x: number, y: number): boolean {\n\tif (y >= HEIGHT) return false;\n\tconst byteIndex = y * BYTES_PER_ROW + Math.floor(x / 8);\n\tconst bitIndex = x % 8;\n\treturn ((BITS[byteIndex] >> bitIndex) & 1) === 0;\n}\n\n// Get the character for a cell (2 vertical pixels packed)\nfunction getChar(x: number, row: number): string {\n\tconst upper = getPixel(x, row * 2);\n\tconst lower = getPixel(x, row * 2 + 1);\n\tif (upper && lower) return \"█\";\n\tif (upper) return \"▀\";\n\tif (lower) return \"▄\";\n\treturn \" \";\n}\n\n// Build the final image grid\nfunction buildFinalGrid(): string[][] {\n\tconst grid: string[][] = [];\n\tfor (let row = 0; row < DISPLAY_HEIGHT; row++) {\n\t\tconst line: string[] = [];\n\t\tfor (let x = 0; x < WIDTH; x++) {\n\t\t\tline.push(getChar(x, row));\n\t\t}\n\t\tgrid.push(line);\n\t}\n\treturn grid;\n}\n\nexport class ArminComponent implements Component {\n\tprivate ui: TUI;\n\tprivate interval: ReturnType<typeof setInterval> | null = null;\n\tprivate effect: Effect;\n\tprivate finalGrid: string[][];\n\tprivate currentGrid: string[][];\n\tprivate effectState: Record<string, unknown> = {};\n\tprivate cachedLines: string[] = [];\n\tprivate cachedWidth = 0;\n\tprivate gridVersion = 0;\n\tprivate cachedVersion = -1;\n\n\tconstructor(ui: TUI) {\n\t\tthis.ui = ui;\n\t\tthis.effect = EFFECTS[Math.floor(Math.random() * EFFECTS.length)];\n\t\tthis.finalGrid = buildFinalGrid();\n\t\tthis.currentGrid = this.createEmptyGrid();\n\n\t\tthis.initEffect();\n\t\tthis.startAnimation();\n\t}\n\n\tinvalidate(): void {\n\t\tthis.cachedWidth = 0;\n\t}\n\n\trender(width: number): string[] {\n\t\tif (width === this.cachedWidth && this.cachedVersion === this.gridVersion) {\n\t\t\treturn this.cachedLines;\n\t\t}\n\n\t\tconst padding = 1;\n\t\tconst availableWidth = width - padding;\n\n\t\tthis.cachedLines = this.currentGrid.map((row) => {\n\t\t\t// Clip row to available width before applying color\n\t\t\tconst clipped = row.slice(0, availableWidth).join(\"\");\n\t\t\tconst padRight = Math.max(0, width - padding - clipped.length);\n\t\t\treturn ` ${theme.fg(\"accent\", clipped)}${\" \".repeat(padRight)}`;\n\t\t});\n\n\t\t// Add \"ARMIN SAYS HI\" at the end\n\t\tconst message = \"ARMIN SAYS HI\";\n\t\tconst msgPadRight = Math.max(0, width - padding - message.length);\n\t\tthis.cachedLines.push(` ${theme.fg(\"accent\", message)}${\" \".repeat(msgPadRight)}`);\n\n\t\tthis.cachedWidth = width;\n\t\tthis.cachedVersion = this.gridVersion;\n\n\t\treturn this.cachedLines;\n\t}\n\n\tprivate createEmptyGrid(): string[][] {\n\t\treturn Array.from({ length: DISPLAY_HEIGHT }, () => Array(WIDTH).fill(\" \"));\n\t}\n\n\tprivate initEffect(): void {\n\t\tswitch (this.effect) {\n\t\t\tcase \"typewriter\":\n\t\t\t\tthis.effectState = { pos: 0 };\n\t\t\t\tbreak;\n\t\t\tcase \"scanline\":\n\t\t\t\tthis.effectState = { row: 0 };\n\t\t\t\tbreak;\n\t\t\tcase \"rain\":\n\t\t\t\t// Track falling position for each column\n\t\t\t\tthis.effectState = {\n\t\t\t\t\tdrops: Array.from({ length: WIDTH }, () => ({\n\t\t\t\t\t\ty: -Math.floor(Math.random() * DISPLAY_HEIGHT * 2),\n\t\t\t\t\t\tsettled: 0,\n\t\t\t\t\t})),\n\t\t\t\t};\n\t\t\t\tbreak;\n\t\t\tcase \"fade\": {\n\t\t\t\t// Shuffle all pixel positions\n\t\t\t\tconst positions: [number, number][] = [];\n\t\t\t\tfor (let row = 0; row < DISPLAY_HEIGHT; row++) {\n\t\t\t\t\tfor (let x = 0; x < WIDTH; x++) {\n\t\t\t\t\t\tpositions.push([row, x]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// Fisher-Yates shuffle\n\t\t\t\tfor (let i = positions.length - 1; i > 0; i--) {\n\t\t\t\t\tconst j = Math.floor(Math.random() * (i + 1));\n\t\t\t\t\t[positions[i], positions[j]] = [positions[j], positions[i]];\n\t\t\t\t}\n\t\t\t\tthis.effectState = { positions, idx: 0 };\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"crt\":\n\t\t\t\tthis.effectState = { expansion: 0 };\n\t\t\t\tbreak;\n\t\t\tcase \"glitch\":\n\t\t\t\tthis.effectState = { phase: 0, glitchFrames: 8 };\n\t\t\t\tbreak;\n\t\t\tcase \"dissolve\": {\n\t\t\t\t// Start with random noise\n\t\t\t\tthis.currentGrid = Array.from({ length: DISPLAY_HEIGHT }, () =>\n\t\t\t\t\tArray.from({ length: WIDTH }, () => {\n\t\t\t\t\t\tconst chars = [\" \", \"░\", \"▒\", \"▓\", \"█\", \"▀\", \"▄\"];\n\t\t\t\t\t\treturn chars[Math.floor(Math.random() * chars.length)];\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\t// Shuffle positions for gradual resolve\n\t\t\t\tconst dissolvePositions: [number, number][] = [];\n\t\t\t\tfor (let row = 0; row < DISPLAY_HEIGHT; row++) {\n\t\t\t\t\tfor (let x = 0; x < WIDTH; x++) {\n\t\t\t\t\t\tdissolvePositions.push([row, x]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tfor (let i = dissolvePositions.length - 1; i > 0; i--) {\n\t\t\t\t\tconst j = Math.floor(Math.random() * (i + 1));\n\t\t\t\t\t[dissolvePositions[i], dissolvePositions[j]] = [dissolvePositions[j], dissolvePositions[i]];\n\t\t\t\t}\n\t\t\t\tthis.effectState = { positions: dissolvePositions, idx: 0 };\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate startAnimation(): void {\n\t\tconst fps = this.effect === \"glitch\" ? 60 : 30;\n\t\tthis.interval = setInterval(() => {\n\t\t\tconst done = this.tickEffect();\n\t\t\tthis.updateDisplay();\n\t\t\tthis.ui.requestRender();\n\t\t\tif (done) {\n\t\t\t\tthis.stopAnimation();\n\t\t\t}\n\t\t}, 1000 / fps);\n\t}\n\n\tprivate stopAnimation(): void {\n\t\tif (this.interval) {\n\t\t\tclearInterval(this.interval);\n\t\t\tthis.interval = null;\n\t\t}\n\t}\n\n\tprivate tickEffect(): boolean {\n\t\tswitch (this.effect) {\n\t\t\tcase \"typewriter\":\n\t\t\t\treturn this.tickTypewriter();\n\t\t\tcase \"scanline\":\n\t\t\t\treturn this.tickScanline();\n\t\t\tcase \"rain\":\n\t\t\t\treturn this.tickRain();\n\t\t\tcase \"fade\":\n\t\t\t\treturn this.tickFade();\n\t\t\tcase \"crt\":\n\t\t\t\treturn this.tickCrt();\n\t\t\tcase \"glitch\":\n\t\t\t\treturn this.tickGlitch();\n\t\t\tcase \"dissolve\":\n\t\t\t\treturn this.tickDissolve();\n\t\t\tdefault:\n\t\t\t\treturn true;\n\t\t}\n\t}\n\n\tprivate tickTypewriter(): boolean {\n\t\tconst state = this.effectState as { pos: number };\n\t\tconst pixelsPerFrame = 3;\n\n\t\tfor (let i = 0; i < pixelsPerFrame; i++) {\n\t\t\tconst row = Math.floor(state.pos / WIDTH);\n\t\t\tconst x = state.pos % WIDTH;\n\t\t\tif (row >= DISPLAY_HEIGHT) return true;\n\t\t\tthis.currentGrid[row][x] = this.finalGrid[row][x];\n\t\t\tstate.pos++;\n\t\t}\n\t\treturn false;\n\t}\n\n\tprivate tickScanline(): boolean {\n\t\tconst state = this.effectState as { row: number };\n\t\tif (state.row >= DISPLAY_HEIGHT) return true;\n\n\t\t// Copy row\n\t\tfor (let x = 0; x < WIDTH; x++) {\n\t\t\tthis.currentGrid[state.row][x] = this.finalGrid[state.row][x];\n\t\t}\n\t\tstate.row++;\n\t\treturn false;\n\t}\n\n\tprivate tickRain(): boolean {\n\t\tconst state = this.effectState as {\n\t\t\tdrops: { y: number; settled: number }[];\n\t\t};\n\n\t\tlet allSettled = true;\n\t\tthis.currentGrid = this.createEmptyGrid();\n\n\t\tfor (let x = 0; x < WIDTH; x++) {\n\t\t\tconst drop = state.drops[x];\n\n\t\t\t// Draw settled pixels\n\t\t\tfor (let row = DISPLAY_HEIGHT - 1; row >= DISPLAY_HEIGHT - drop.settled; row--) {\n\t\t\t\tif (row >= 0) {\n\t\t\t\t\tthis.currentGrid[row][x] = this.finalGrid[row][x];\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Check if this column is done\n\t\t\tif (drop.settled >= DISPLAY_HEIGHT) continue;\n\n\t\t\tallSettled = false;\n\n\t\t\t// Find the target row for this column (lowest non-space pixel)\n\t\t\tlet targetRow = -1;\n\t\t\tfor (let row = DISPLAY_HEIGHT - 1 - drop.settled; row >= 0; row--) {\n\t\t\t\tif (this.finalGrid[row][x] !== \" \") {\n\t\t\t\t\ttargetRow = row;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Move drop down\n\t\t\tdrop.y++;\n\n\t\t\t// Draw falling drop\n\t\t\tif (drop.y >= 0 && drop.y < DISPLAY_HEIGHT) {\n\t\t\t\tif (targetRow >= 0 && drop.y >= targetRow) {\n\t\t\t\t\t// Settle\n\t\t\t\t\tdrop.settled = DISPLAY_HEIGHT - targetRow;\n\t\t\t\t\tdrop.y = -Math.floor(Math.random() * 5) - 1;\n\t\t\t\t} else {\n\t\t\t\t\t// Still falling\n\t\t\t\t\tthis.currentGrid[drop.y][x] = \"▓\";\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn allSettled;\n\t}\n\n\tprivate tickFade(): boolean {\n\t\tconst state = this.effectState as { positions: [number, number][]; idx: number };\n\t\tconst pixelsPerFrame = 15;\n\n\t\tfor (let i = 0; i < pixelsPerFrame; i++) {\n\t\t\tif (state.idx >= state.positions.length) return true;\n\t\t\tconst [row, x] = state.positions[state.idx];\n\t\t\tthis.currentGrid[row][x] = this.finalGrid[row][x];\n\t\t\tstate.idx++;\n\t\t}\n\t\treturn false;\n\t}\n\n\tprivate tickCrt(): boolean {\n\t\tconst state = this.effectState as { expansion: number };\n\t\tconst midRow = Math.floor(DISPLAY_HEIGHT / 2);\n\n\t\tthis.currentGrid = this.createEmptyGrid();\n\n\t\t// Draw from middle expanding outward\n\t\tconst top = midRow - state.expansion;\n\t\tconst bottom = midRow + state.expansion;\n\n\t\tfor (let row = Math.max(0, top); row <= Math.min(DISPLAY_HEIGHT - 1, bottom); row++) {\n\t\t\tfor (let x = 0; x < WIDTH; x++) {\n\t\t\t\tthis.currentGrid[row][x] = this.finalGrid[row][x];\n\t\t\t}\n\t\t}\n\n\t\tstate.expansion++;\n\t\treturn state.expansion > DISPLAY_HEIGHT;\n\t}\n\n\tprivate tickGlitch(): boolean {\n\t\tconst state = this.effectState as { phase: number; glitchFrames: number };\n\n\t\tif (state.phase < state.glitchFrames) {\n\t\t\t// Glitch phase: show corrupted version\n\t\t\tthis.currentGrid = this.finalGrid.map((row) => {\n\t\t\t\tconst offset = Math.floor(Math.random() * 7) - 3;\n\t\t\t\tconst glitchRow = [...row];\n\n\t\t\t\t// Random horizontal offset\n\t\t\t\tif (Math.random() < 0.3) {\n\t\t\t\t\tconst shifted = glitchRow.slice(offset).concat(glitchRow.slice(0, offset));\n\t\t\t\t\treturn shifted.slice(0, WIDTH);\n\t\t\t\t}\n\n\t\t\t\t// Random vertical swap\n\t\t\t\tif (Math.random() < 0.2) {\n\t\t\t\t\tconst swapRow = Math.floor(Math.random() * DISPLAY_HEIGHT);\n\t\t\t\t\treturn [...this.finalGrid[swapRow]];\n\t\t\t\t}\n\n\t\t\t\treturn glitchRow;\n\t\t\t});\n\t\t\tstate.phase++;\n\t\t\treturn false;\n\t\t}\n\n\t\t// Final frame: show clean image\n\t\tthis.currentGrid = this.finalGrid.map((row) => [...row]);\n\t\treturn true;\n\t}\n\n\tprivate tickDissolve(): boolean {\n\t\tconst state = this.effectState as { positions: [number, number][]; idx: number };\n\t\tconst pixelsPerFrame = 20;\n\n\t\tfor (let i = 0; i < pixelsPerFrame; i++) {\n\t\t\tif (state.idx >= state.positions.length) return true;\n\t\t\tconst [row, x] = state.positions[state.idx];\n\t\t\tthis.currentGrid[row][x] = this.finalGrid[row][x];\n\t\t\tstate.idx++;\n\t\t}\n\t\treturn false;\n\t}\n\n\tprivate updateDisplay(): void {\n\t\tthis.gridVersion++;\n\t}\n\n\tdispose(): void {\n\t\tthis.stopAnimation();\n\t}\n}\n"]}
|