oh-my-claude-sisyphus 3.6.0 → 3.6.1
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/commands/omc-setup.md +3 -3
- package/commands/release.md +1 -1
- package/dist/__tests__/analytics/transcript-scanner.test.js +69 -27
- package/dist/__tests__/analytics/transcript-scanner.test.js.map +1 -1
- package/dist/__tests__/installer.test.js +2 -1
- package/dist/__tests__/installer.test.js.map +1 -1
- package/dist/analytics/session-manager.d.ts +24 -0
- package/dist/analytics/session-manager.d.ts.map +1 -1
- package/dist/analytics/session-manager.js +98 -9
- package/dist/analytics/session-manager.js.map +1 -1
- package/dist/analytics/transcript-scanner.d.ts +9 -8
- package/dist/analytics/transcript-scanner.d.ts.map +1 -1
- package/dist/analytics/transcript-scanner.js +146 -16
- package/dist/analytics/transcript-scanner.js.map +1 -1
- package/dist/cli/analytics.js +0 -0
- package/dist/cli/index.js +0 -0
- package/dist/hooks/empty-message-sanitizer/__tests__/index.test.d.ts +2 -0
- package/dist/hooks/empty-message-sanitizer/__tests__/index.test.d.ts.map +1 -0
- package/dist/hooks/empty-message-sanitizer/__tests__/index.test.js +416 -0
- package/dist/hooks/empty-message-sanitizer/__tests__/index.test.js.map +1 -0
- package/dist/hooks/keyword-detector/__tests__/index.test.d.ts +2 -0
- package/dist/hooks/keyword-detector/__tests__/index.test.d.ts.map +1 -0
- package/dist/hooks/keyword-detector/__tests__/index.test.js +427 -0
- package/dist/hooks/keyword-detector/__tests__/index.test.js.map +1 -0
- package/dist/hooks/think-mode/__tests__/index.test.d.ts +2 -0
- package/dist/hooks/think-mode/__tests__/index.test.d.ts.map +1 -0
- package/dist/hooks/think-mode/__tests__/index.test.js +556 -0
- package/dist/hooks/think-mode/__tests__/index.test.js.map +1 -0
- package/dist/installer/index.d.ts.map +1 -1
- package/dist/installer/index.js +8 -0
- package/dist/installer/index.js.map +1 -1
- package/package.json +1 -1
- package/skills/omc-setup/SKILL.md +27 -3
- package/skills/release/SKILL.md +1 -1
- package/dist/__tests__/analytics/analytics-summary.test.d.ts +0 -2
- package/dist/__tests__/analytics/analytics-summary.test.d.ts.map +0 -1
- package/dist/__tests__/analytics/analytics-summary.test.js +0 -267
- package/dist/__tests__/analytics/analytics-summary.test.js.map +0 -1
- package/dist/__tests__/analytics/cost-estimator.test.d.ts +0 -2
- package/dist/__tests__/analytics/cost-estimator.test.d.ts.map +0 -1
- package/dist/__tests__/analytics/cost-estimator.test.js +0 -212
- package/dist/__tests__/analytics/cost-estimator.test.js.map +0 -1
- package/dist/__tests__/hooks/auto-slash-command/executor.test.d.ts +0 -7
- package/dist/__tests__/hooks/auto-slash-command/executor.test.d.ts.map +0 -1
- package/dist/__tests__/hooks/auto-slash-command/executor.test.js +0 -374
- package/dist/__tests__/hooks/auto-slash-command/executor.test.js.map +0 -1
- package/dist/__tests__/hud/auto-tracking.integration.test.d.ts +0 -2
- package/dist/__tests__/hud/auto-tracking.integration.test.d.ts.map +0 -1
- package/dist/__tests__/hud/auto-tracking.integration.test.js +0 -12
- package/dist/__tests__/hud/auto-tracking.integration.test.js.map +0 -1
- package/dist/__tests__/learned-skills/config.test.d.ts +0 -2
- package/dist/__tests__/learned-skills/config.test.d.ts.map +0 -1
- package/dist/__tests__/learned-skills/config.test.js +0 -37
- package/dist/__tests__/learned-skills/config.test.js.map +0 -1
- package/dist/__tests__/learned-skills/detector.test.d.ts +0 -2
- package/dist/__tests__/learned-skills/detector.test.d.ts.map +0 -1
- package/dist/__tests__/learned-skills/detector.test.js +0 -99
- package/dist/__tests__/learned-skills/detector.test.js.map +0 -1
- package/dist/__tests__/learned-skills/finder.test.d.ts +0 -2
- package/dist/__tests__/learned-skills/finder.test.d.ts.map +0 -1
- package/dist/__tests__/learned-skills/finder.test.js +0 -59
- package/dist/__tests__/learned-skills/finder.test.js.map +0 -1
- package/dist/__tests__/learned-skills/loader.test.d.ts +0 -2
- package/dist/__tests__/learned-skills/loader.test.d.ts.map +0 -1
- package/dist/__tests__/learned-skills/loader.test.js +0 -69
- package/dist/__tests__/learned-skills/loader.test.js.map +0 -1
- package/dist/__tests__/learned-skills/parser.test.d.ts +0 -2
- package/dist/__tests__/learned-skills/parser.test.d.ts.map +0 -1
- package/dist/__tests__/learned-skills/parser.test.js +0 -81
- package/dist/__tests__/learned-skills/parser.test.js.map +0 -1
- package/dist/__tests__/learned-skills/validator.test.d.ts +0 -2
- package/dist/__tests__/learned-skills/validator.test.d.ts.map +0 -1
- package/dist/__tests__/learned-skills/validator.test.js +0 -85
- package/dist/__tests__/learned-skills/validator.test.js.map +0 -1
- package/dist/agents/codex-agents.d.ts +0 -20
- package/dist/agents/codex-agents.d.ts.map +0 -1
- package/dist/agents/codex-agents.js +0 -36
- package/dist/agents/codex-agents.js.map +0 -1
- package/dist/agents/document-writer.d.ts +0 -11
- package/dist/agents/document-writer.d.ts.map +0 -1
- package/dist/agents/document-writer.js +0 -209
- package/dist/agents/document-writer.js.map +0 -1
- package/dist/agents/frontend-engineer.d.ts +0 -11
- package/dist/agents/frontend-engineer.d.ts.map +0 -1
- package/dist/agents/frontend-engineer.js +0 -115
- package/dist/agents/frontend-engineer.js.map +0 -1
- package/dist/agents/librarian.d.ts +0 -12
- package/dist/agents/librarian.d.ts.map +0 -1
- package/dist/agents/librarian.js +0 -103
- package/dist/agents/librarian.js.map +0 -1
- package/dist/agents/metis.d.ts +0 -12
- package/dist/agents/metis.d.ts.map +0 -1
- package/dist/agents/metis.js +0 -117
- package/dist/agents/metis.js.map +0 -1
- package/dist/agents/momus.d.ts +0 -12
- package/dist/agents/momus.d.ts.map +0 -1
- package/dist/agents/momus.js +0 -128
- package/dist/agents/momus.js.map +0 -1
- package/dist/agents/multimodal-looker.d.ts +0 -11
- package/dist/agents/multimodal-looker.d.ts.map +0 -1
- package/dist/agents/multimodal-looker.js +0 -70
- package/dist/agents/multimodal-looker.js.map +0 -1
- package/dist/agents/oracle.d.ts +0 -13
- package/dist/agents/oracle.d.ts.map +0 -1
- package/dist/agents/oracle.js +0 -191
- package/dist/agents/oracle.js.map +0 -1
- package/dist/agents/orchestrator-sisyphus.d.ts +0 -11
- package/dist/agents/orchestrator-sisyphus.d.ts.map +0 -1
- package/dist/agents/orchestrator-sisyphus.js +0 -115
- package/dist/agents/orchestrator-sisyphus.js.map +0 -1
- package/dist/agents/prometheus.d.ts +0 -12
- package/dist/agents/prometheus.d.ts.map +0 -1
- package/dist/agents/prometheus.js +0 -195
- package/dist/agents/prometheus.js.map +0 -1
- package/dist/agents/sisyphus-junior.d.ts +0 -12
- package/dist/agents/sisyphus-junior.d.ts.map +0 -1
- package/dist/agents/sisyphus-junior.js +0 -93
- package/dist/agents/sisyphus-junior.js.map +0 -1
- package/dist/cli/components/CostDashboard.d.ts +0 -15
- package/dist/cli/components/CostDashboard.d.ts.map +0 -1
- package/dist/cli/components/CostDashboard.js +0 -15
- package/dist/cli/components/CostDashboard.js.map +0 -1
- package/dist/cli/components/LiveStats.d.ts +0 -16
- package/dist/cli/components/LiveStats.d.ts.map +0 -1
- package/dist/cli/components/LiveStats.js +0 -16
- package/dist/cli/components/LiveStats.js.map +0 -1
- package/dist/cli/components/SessionBrowser.d.ts +0 -14
- package/dist/cli/components/SessionBrowser.d.ts.map +0 -1
- package/dist/cli/components/SessionBrowser.js +0 -14
- package/dist/cli/components/SessionBrowser.js.map +0 -1
- package/dist/cli/tui.d.ts +0 -21
- package/dist/cli/tui.d.ts.map +0 -1
- package/dist/cli/tui.js +0 -21
- package/dist/cli/tui.js.map +0 -1
- package/dist/hooks/autopilot/signals.d.ts +0 -20
- package/dist/hooks/autopilot/signals.d.ts.map +0 -1
- package/dist/hooks/autopilot/signals.js +0 -75
- package/dist/hooks/autopilot/signals.js.map +0 -1
- package/dist/hooks/autopilot/summary.d.ts +0 -27
- package/dist/hooks/autopilot/summary.d.ts.map +0 -1
- package/dist/hooks/autopilot/summary.js +0 -160
- package/dist/hooks/autopilot/summary.js.map +0 -1
- package/dist/hooks/autopilot/transition.d.ts +0 -39
- package/dist/hooks/autopilot/transition.d.ts.map +0 -1
- package/dist/hooks/autopilot/transition.js +0 -216
- package/dist/hooks/autopilot/transition.js.map +0 -1
- package/dist/hooks/context-window-limit-recovery/constants.d.ts +0 -28
- package/dist/hooks/context-window-limit-recovery/constants.d.ts.map +0 -1
- package/dist/hooks/context-window-limit-recovery/constants.js +0 -85
- package/dist/hooks/context-window-limit-recovery/constants.js.map +0 -1
- package/dist/hooks/context-window-limit-recovery/index.d.ts +0 -62
- package/dist/hooks/context-window-limit-recovery/index.d.ts.map +0 -1
- package/dist/hooks/context-window-limit-recovery/index.js +0 -201
- package/dist/hooks/context-window-limit-recovery/index.js.map +0 -1
- package/dist/hooks/context-window-limit-recovery/parser.d.ts +0 -31
- package/dist/hooks/context-window-limit-recovery/parser.d.ts.map +0 -1
- package/dist/hooks/context-window-limit-recovery/parser.js +0 -241
- package/dist/hooks/context-window-limit-recovery/parser.js.map +0 -1
- package/dist/hooks/context-window-limit-recovery/types.d.ts +0 -84
- package/dist/hooks/context-window-limit-recovery/types.d.ts.map +0 -1
- package/dist/hooks/context-window-limit-recovery/types.js +0 -34
- package/dist/hooks/context-window-limit-recovery/types.js.map +0 -1
- package/dist/hooks/edit-error-recovery/index.d.ts +0 -62
- package/dist/hooks/edit-error-recovery/index.d.ts.map +0 -1
- package/dist/hooks/edit-error-recovery/index.js +0 -89
- package/dist/hooks/edit-error-recovery/index.js.map +0 -1
- package/dist/hooks/learned-skills/config.d.ts +0 -53
- package/dist/hooks/learned-skills/config.d.ts.map +0 -1
- package/dist/hooks/learned-skills/config.js +0 -103
- package/dist/hooks/learned-skills/config.js.map +0 -1
- package/dist/hooks/learned-skills/constants.d.ts +0 -24
- package/dist/hooks/learned-skills/constants.d.ts.map +0 -1
- package/dist/hooks/learned-skills/constants.js +0 -26
- package/dist/hooks/learned-skills/constants.js.map +0 -1
- package/dist/hooks/learned-skills/detection-hook.d.ts +0 -39
- package/dist/hooks/learned-skills/detection-hook.d.ts.map +0 -1
- package/dist/hooks/learned-skills/detection-hook.js +0 -83
- package/dist/hooks/learned-skills/detection-hook.js.map +0 -1
- package/dist/hooks/learned-skills/detector.d.ts +0 -30
- package/dist/hooks/learned-skills/detector.d.ts.map +0 -1
- package/dist/hooks/learned-skills/detector.js +0 -150
- package/dist/hooks/learned-skills/detector.js.map +0 -1
- package/dist/hooks/learned-skills/finder.d.ts +0 -21
- package/dist/hooks/learned-skills/finder.d.ts.map +0 -1
- package/dist/hooks/learned-skills/finder.js +0 -117
- package/dist/hooks/learned-skills/finder.js.map +0 -1
- package/dist/hooks/learned-skills/index.d.ts +0 -62
- package/dist/hooks/learned-skills/index.d.ts.map +0 -1
- package/dist/hooks/learned-skills/index.js +0 -137
- package/dist/hooks/learned-skills/index.js.map +0 -1
- package/dist/hooks/learned-skills/loader.d.ts +0 -20
- package/dist/hooks/learned-skills/loader.d.ts.map +0 -1
- package/dist/hooks/learned-skills/loader.js +0 -107
- package/dist/hooks/learned-skills/loader.js.map +0 -1
- package/dist/hooks/learned-skills/parser.d.ts +0 -21
- package/dist/hooks/learned-skills/parser.d.ts.map +0 -1
- package/dist/hooks/learned-skills/parser.js +0 -190
- package/dist/hooks/learned-skills/parser.js.map +0 -1
- package/dist/hooks/learned-skills/promotion.d.ts +0 -29
- package/dist/hooks/learned-skills/promotion.d.ts.map +0 -1
- package/dist/hooks/learned-skills/promotion.js +0 -87
- package/dist/hooks/learned-skills/promotion.js.map +0 -1
- package/dist/hooks/learned-skills/types.d.ts +0 -109
- package/dist/hooks/learned-skills/types.d.ts.map +0 -1
- package/dist/hooks/learned-skills/types.js +0 -8
- package/dist/hooks/learned-skills/types.js.map +0 -1
- package/dist/hooks/learned-skills/validator.d.ts +0 -15
- package/dist/hooks/learned-skills/validator.d.ts.map +0 -1
- package/dist/hooks/learned-skills/validator.js +0 -87
- package/dist/hooks/learned-skills/validator.js.map +0 -1
- package/dist/hooks/learned-skills/writer.d.ts +0 -27
- package/dist/hooks/learned-skills/writer.d.ts.map +0 -1
- package/dist/hooks/learned-skills/writer.js +0 -126
- package/dist/hooks/learned-skills/writer.js.map +0 -1
- package/dist/hooks/mnemosyne/config.d.ts +0 -53
- package/dist/hooks/mnemosyne/config.d.ts.map +0 -1
- package/dist/hooks/mnemosyne/config.js +0 -103
- package/dist/hooks/mnemosyne/config.js.map +0 -1
- package/dist/hooks/mnemosyne/constants.d.ts +0 -24
- package/dist/hooks/mnemosyne/constants.d.ts.map +0 -1
- package/dist/hooks/mnemosyne/constants.js +0 -26
- package/dist/hooks/mnemosyne/constants.js.map +0 -1
- package/dist/hooks/mnemosyne/detection-hook.d.ts +0 -39
- package/dist/hooks/mnemosyne/detection-hook.d.ts.map +0 -1
- package/dist/hooks/mnemosyne/detection-hook.js +0 -83
- package/dist/hooks/mnemosyne/detection-hook.js.map +0 -1
- package/dist/hooks/mnemosyne/detector.d.ts +0 -30
- package/dist/hooks/mnemosyne/detector.d.ts.map +0 -1
- package/dist/hooks/mnemosyne/detector.js +0 -150
- package/dist/hooks/mnemosyne/detector.js.map +0 -1
- package/dist/hooks/mnemosyne/finder.d.ts +0 -21
- package/dist/hooks/mnemosyne/finder.d.ts.map +0 -1
- package/dist/hooks/mnemosyne/finder.js +0 -117
- package/dist/hooks/mnemosyne/finder.js.map +0 -1
- package/dist/hooks/mnemosyne/index.d.ts +0 -62
- package/dist/hooks/mnemosyne/index.d.ts.map +0 -1
- package/dist/hooks/mnemosyne/index.js +0 -137
- package/dist/hooks/mnemosyne/index.js.map +0 -1
- package/dist/hooks/mnemosyne/loader.d.ts +0 -20
- package/dist/hooks/mnemosyne/loader.d.ts.map +0 -1
- package/dist/hooks/mnemosyne/loader.js +0 -113
- package/dist/hooks/mnemosyne/loader.js.map +0 -1
- package/dist/hooks/mnemosyne/parser.d.ts +0 -21
- package/dist/hooks/mnemosyne/parser.d.ts.map +0 -1
- package/dist/hooks/mnemosyne/parser.js +0 -190
- package/dist/hooks/mnemosyne/parser.js.map +0 -1
- package/dist/hooks/mnemosyne/promotion.d.ts +0 -29
- package/dist/hooks/mnemosyne/promotion.d.ts.map +0 -1
- package/dist/hooks/mnemosyne/promotion.js +0 -87
- package/dist/hooks/mnemosyne/promotion.js.map +0 -1
- package/dist/hooks/mnemosyne/types.d.ts +0 -109
- package/dist/hooks/mnemosyne/types.d.ts.map +0 -1
- package/dist/hooks/mnemosyne/types.js +0 -8
- package/dist/hooks/mnemosyne/types.js.map +0 -1
- package/dist/hooks/mnemosyne/validator.d.ts +0 -15
- package/dist/hooks/mnemosyne/validator.d.ts.map +0 -1
- package/dist/hooks/mnemosyne/validator.js +0 -87
- package/dist/hooks/mnemosyne/validator.js.map +0 -1
- package/dist/hooks/mnemosyne/writer.d.ts +0 -27
- package/dist/hooks/mnemosyne/writer.d.ts.map +0 -1
- package/dist/hooks/mnemosyne/writer.js +0 -126
- package/dist/hooks/mnemosyne/writer.js.map +0 -1
- package/dist/hooks/ralph-loop/index.d.ts +0 -116
- package/dist/hooks/ralph-loop/index.d.ts.map +0 -1
- package/dist/hooks/ralph-loop/index.js +0 -322
- package/dist/hooks/ralph-loop/index.js.map +0 -1
- package/dist/hooks/ralph-prd/index.d.ts +0 -130
- package/dist/hooks/ralph-prd/index.d.ts.map +0 -1
- package/dist/hooks/ralph-prd/index.js +0 -310
- package/dist/hooks/ralph-prd/index.js.map +0 -1
- package/dist/hooks/ralph-progress/index.d.ts +0 -102
- package/dist/hooks/ralph-progress/index.d.ts.map +0 -1
- package/dist/hooks/ralph-progress/index.js +0 -408
- package/dist/hooks/ralph-progress/index.js.map +0 -1
- package/dist/hooks/ralph-verifier/index.d.ts +0 -72
- package/dist/hooks/ralph-verifier/index.d.ts.map +0 -1
- package/dist/hooks/ralph-verifier/index.js +0 -223
- package/dist/hooks/ralph-verifier/index.js.map +0 -1
- package/dist/hooks/session-recovery/constants.d.ts +0 -56
- package/dist/hooks/session-recovery/constants.d.ts.map +0 -1
- package/dist/hooks/session-recovery/constants.js +0 -78
- package/dist/hooks/session-recovery/constants.js.map +0 -1
- package/dist/hooks/session-recovery/index.d.ts +0 -53
- package/dist/hooks/session-recovery/index.d.ts.map +0 -1
- package/dist/hooks/session-recovery/index.js +0 -321
- package/dist/hooks/session-recovery/index.js.map +0 -1
- package/dist/hooks/session-recovery/storage.d.ts +0 -76
- package/dist/hooks/session-recovery/storage.d.ts.map +0 -1
- package/dist/hooks/session-recovery/storage.js +0 -383
- package/dist/hooks/session-recovery/storage.js.map +0 -1
- package/dist/hooks/session-recovery/types.d.ts +0 -145
- package/dist/hooks/session-recovery/types.d.ts.map +0 -1
- package/dist/hooks/session-recovery/types.js +0 -8
- package/dist/hooks/session-recovery/types.js.map +0 -1
- package/dist/hooks/sisyphus-orchestrator/constants.d.ts +0 -23
- package/dist/hooks/sisyphus-orchestrator/constants.d.ts.map +0 -1
- package/dist/hooks/sisyphus-orchestrator/constants.js +0 -142
- package/dist/hooks/sisyphus-orchestrator/constants.js.map +0 -1
- package/dist/hooks/sisyphus-orchestrator/index.d.ts +0 -113
- package/dist/hooks/sisyphus-orchestrator/index.d.ts.map +0 -1
- package/dist/hooks/sisyphus-orchestrator/index.js +0 -309
- package/dist/hooks/sisyphus-orchestrator/index.js.map +0 -1
- package/dist/hooks/ultraqa-loop/index.d.ts +0 -94
- package/dist/hooks/ultraqa-loop/index.d.ts.map +0 -1
- package/dist/hooks/ultraqa-loop/index.js +0 -216
- package/dist/hooks/ultraqa-loop/index.js.map +0 -1
- package/dist/hooks/ultrawork-state/index.d.ts +0 -62
- package/dist/hooks/ultrawork-state/index.d.ts.map +0 -1
- package/dist/hooks/ultrawork-state/index.js +0 -208
- package/dist/hooks/ultrawork-state/index.js.map +0 -1
- package/dist/hud/sisyphus-state.d.ts +0 -31
- package/dist/hud/sisyphus-state.d.ts.map +0 -1
- package/dist/hud/sisyphus-state.js +0 -163
- package/dist/hud/sisyphus-state.js.map +0 -1
|
@@ -2,6 +2,21 @@ import { readdir, stat } from 'fs/promises';
|
|
|
2
2
|
import { existsSync } from 'fs';
|
|
3
3
|
import { join } from 'path';
|
|
4
4
|
import { homedir } from 'os';
|
|
5
|
+
/**
|
|
6
|
+
* Check if the encoded path looks like a Windows path (starts with drive letter)
|
|
7
|
+
* Examples: "C--Users-user-project" or "D--work-project"
|
|
8
|
+
*/
|
|
9
|
+
function isWindowsEncodedPath(dirName) {
|
|
10
|
+
return /^[A-Za-z]-/.test(dirName);
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Normalize decoded path to use OS-native separators consistently
|
|
14
|
+
*/
|
|
15
|
+
function normalizePathForOS(decodedPath) {
|
|
16
|
+
// On Windows, convert forward slashes to backslashes for consistency
|
|
17
|
+
// But existsSync works with both, so we normalize to forward slashes for cross-platform
|
|
18
|
+
return decodedPath.replace(/\\/g, '/');
|
|
19
|
+
}
|
|
5
20
|
/**
|
|
6
21
|
* UUID regex pattern for session IDs
|
|
7
22
|
*/
|
|
@@ -10,32 +25,138 @@ const UUID_REGEX = /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12
|
|
|
10
25
|
* Decode project directory name back to original path.
|
|
11
26
|
*
|
|
12
27
|
* The encoding scheme used by Claude Code is lossy - it converts all path
|
|
13
|
-
* separators (/) to dashes (-), but legitimate dashes in directory names
|
|
28
|
+
* separators (/ or \) to dashes (-), but legitimate dashes in directory names
|
|
14
29
|
* also become dashes, making them indistinguishable.
|
|
15
30
|
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
* 3. Fall back to simple decode if nothing else works
|
|
31
|
+
* Encoding patterns:
|
|
32
|
+
* - Unix: "/home/user/project" → "-home-user-project"
|
|
33
|
+
* - Windows: "C:\Users\user\project" → "C--Users-user-project"
|
|
20
34
|
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
35
|
+
* Strategy:
|
|
36
|
+
* 1. Detect if it's a Windows or Unix encoded path
|
|
37
|
+
* 2. Try simple decode (all dashes -> slashes) and check if path exists
|
|
38
|
+
* 3. If not, try to reconstruct by checking filesystem for partial matches
|
|
39
|
+
* 4. Fall back to simple decode if nothing else works
|
|
24
40
|
*
|
|
25
41
|
* @internal Exported for testing
|
|
26
42
|
*/
|
|
27
43
|
export function decodeProjectPath(dirName) {
|
|
28
|
-
|
|
29
|
-
|
|
44
|
+
// Handle Windows encoded paths (e.g., "C--Users-user-project")
|
|
45
|
+
if (isWindowsEncodedPath(dirName)) {
|
|
46
|
+
return decodeWindowsPath(dirName);
|
|
47
|
+
}
|
|
48
|
+
// Handle Unix encoded paths (e.g., "-home-user-project")
|
|
49
|
+
if (dirName.startsWith('-')) {
|
|
50
|
+
return decodeUnixPath(dirName);
|
|
51
|
+
}
|
|
52
|
+
// Not an encoded path, return as-is
|
|
53
|
+
return dirName;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Split path string preserving consecutive hyphens as single segments.
|
|
57
|
+
* e.g., "a--b-c" → ["a", "-", "b", "c"] (the "-" represents a hyphen in original name)
|
|
58
|
+
*/
|
|
59
|
+
function splitPreservingConsecutiveHyphens(str) {
|
|
60
|
+
const result = [];
|
|
61
|
+
let current = '';
|
|
62
|
+
let i = 0;
|
|
63
|
+
while (i < str.length) {
|
|
64
|
+
if (str[i] === '-') {
|
|
65
|
+
if (current) {
|
|
66
|
+
result.push(current);
|
|
67
|
+
current = '';
|
|
68
|
+
}
|
|
69
|
+
// Check for consecutive hyphens
|
|
70
|
+
if (i + 1 < str.length && str[i + 1] === '-') {
|
|
71
|
+
// Consecutive hyphens - this means the original had a hyphen
|
|
72
|
+
// Push empty string as marker, will be joined with hyphen later
|
|
73
|
+
result.push('');
|
|
74
|
+
i++; // Skip the second hyphen
|
|
75
|
+
}
|
|
76
|
+
i++;
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
current += str[i];
|
|
80
|
+
i++;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
if (current) {
|
|
84
|
+
result.push(current);
|
|
85
|
+
}
|
|
86
|
+
return result;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Decode Windows encoded path (e.g., "C--Users-user-project" → "C:/Users/user/project")
|
|
90
|
+
*/
|
|
91
|
+
function decodeWindowsPath(dirName) {
|
|
92
|
+
const driveLetter = dirName[0];
|
|
93
|
+
const rest = dirName.slice(2); // Skip "X-"
|
|
94
|
+
// Simple decode: drive letter + colon + rest with dashes as slashes
|
|
95
|
+
const simplePath = `${driveLetter}:/${rest.replace(/-/g, '/')}`;
|
|
96
|
+
// Normalize double slashes that might occur from empty segments
|
|
97
|
+
const normalizedSimple = simplePath.replace(/\/+/g, '/');
|
|
98
|
+
// If simple decode exists, we're done
|
|
99
|
+
if (existsSync(normalizedSimple)) {
|
|
100
|
+
return normalizedSimple;
|
|
101
|
+
}
|
|
102
|
+
// Try to reconstruct by checking filesystem for partial matches
|
|
103
|
+
// Use special splitting to handle consecutive hyphens
|
|
104
|
+
const segments = splitPreservingConsecutiveHyphens(rest);
|
|
105
|
+
if (segments.length === 0) {
|
|
106
|
+
return `${driveLetter}:/`;
|
|
107
|
+
}
|
|
108
|
+
const possiblePaths = [];
|
|
109
|
+
// Generate all possible interpretations by trying different hyphen positions
|
|
110
|
+
function generatePaths(parts, index, currentPath) {
|
|
111
|
+
if (index >= parts.length) {
|
|
112
|
+
possiblePaths.push(currentPath);
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
const part = parts[index];
|
|
116
|
+
// Empty string means this was a consecutive hyphen - must join with previous
|
|
117
|
+
if (part === '' && currentPath) {
|
|
118
|
+
const pathParts = currentPath.split('/');
|
|
119
|
+
const lastPart = pathParts.pop() || '';
|
|
120
|
+
const newPath = pathParts.join('/') + '/' + lastPart + '-';
|
|
121
|
+
generatePaths(parts, index + 1, newPath);
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
// Try adding next segment as a new directory
|
|
125
|
+
const newDir = currentPath + '/' + part;
|
|
126
|
+
generatePaths(parts, index + 1, newDir);
|
|
127
|
+
// Try combining with previous segment using hyphen (if not first segment)
|
|
128
|
+
if (index > 0 && currentPath) {
|
|
129
|
+
const pathParts = currentPath.split('/');
|
|
130
|
+
const lastPart = pathParts.pop() || '';
|
|
131
|
+
const newPath = pathParts.join('/') + '/' + lastPart + '-' + part;
|
|
132
|
+
generatePaths(parts, index + 1, newPath);
|
|
133
|
+
}
|
|
30
134
|
}
|
|
135
|
+
generatePaths(segments, 0, `${driveLetter}:`);
|
|
136
|
+
// Find the first path that exists on filesystem
|
|
137
|
+
for (const path of possiblePaths) {
|
|
138
|
+
if (existsSync(path)) {
|
|
139
|
+
return path;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
// Fall back to simple decode
|
|
143
|
+
return normalizedSimple;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Decode Unix encoded path (e.g., "-home-user-project" → "/home/user/project")
|
|
147
|
+
*/
|
|
148
|
+
function decodeUnixPath(dirName) {
|
|
31
149
|
// Simple decode: replace all dashes with slashes
|
|
32
150
|
const simplePath = '/' + dirName.slice(1).replace(/-/g, '/');
|
|
151
|
+
// Normalize double slashes
|
|
152
|
+
const normalizedSimple = simplePath.replace(/\/+/g, '/');
|
|
33
153
|
// If simple decode exists, we're done
|
|
34
|
-
if (existsSync(
|
|
35
|
-
return
|
|
154
|
+
if (existsSync(normalizedSimple)) {
|
|
155
|
+
return normalizedSimple;
|
|
36
156
|
}
|
|
37
157
|
// Try to reconstruct by checking filesystem for partial matches
|
|
38
|
-
|
|
158
|
+
// Use special splitting to handle consecutive hyphens
|
|
159
|
+
const segments = splitPreservingConsecutiveHyphens(dirName.slice(1));
|
|
39
160
|
const possiblePaths = [];
|
|
40
161
|
// Generate all possible interpretations by trying different hyphen positions
|
|
41
162
|
function generatePaths(parts, index, currentPath) {
|
|
@@ -43,13 +164,22 @@ export function decodeProjectPath(dirName) {
|
|
|
43
164
|
possiblePaths.push(currentPath);
|
|
44
165
|
return;
|
|
45
166
|
}
|
|
167
|
+
const part = parts[index];
|
|
168
|
+
// Empty string means this was a consecutive hyphen - must join with previous
|
|
169
|
+
if (part === '' && currentPath) {
|
|
170
|
+
const pathParts = currentPath.split('/');
|
|
171
|
+
const lastPart = pathParts.pop() || '';
|
|
172
|
+
const newPath = pathParts.join('/') + '/' + lastPart + '-';
|
|
173
|
+
generatePaths(parts, index + 1, newPath);
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
46
176
|
// Try adding next segment as a new directory
|
|
47
|
-
generatePaths(parts, index + 1, currentPath + '/' +
|
|
177
|
+
generatePaths(parts, index + 1, currentPath + '/' + part);
|
|
48
178
|
// Try combining with previous segment using hyphen (if not first segment)
|
|
49
179
|
if (index > 0 && currentPath) {
|
|
50
180
|
const pathParts = currentPath.split('/');
|
|
51
181
|
const lastPart = pathParts.pop() || '';
|
|
52
|
-
const newPath = pathParts.join('/') + '/' + lastPart + '-' +
|
|
182
|
+
const newPath = pathParts.join('/') + '/' + lastPart + '-' + part;
|
|
53
183
|
generatePaths(parts, index + 1, newPath);
|
|
54
184
|
}
|
|
55
185
|
}
|
|
@@ -61,7 +191,7 @@ export function decodeProjectPath(dirName) {
|
|
|
61
191
|
}
|
|
62
192
|
}
|
|
63
193
|
// Fall back to simple decode
|
|
64
|
-
return
|
|
194
|
+
return normalizedSimple;
|
|
65
195
|
}
|
|
66
196
|
/**
|
|
67
197
|
* Check if a path matches a glob pattern (simple implementation)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transcript-scanner.js","sourceRoot":"","sources":["../../src/analytics/transcript-scanner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAChC,OAAO,EAAE,IAAI,
|
|
1
|
+
{"version":3,"file":"transcript-scanner.js","sourceRoot":"","sources":["../../src/analytics/transcript-scanner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAChC,OAAO,EAAE,IAAI,EAAO,MAAM,MAAM,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAE7B;;;GAGG;AACH,SAAS,oBAAoB,CAAC,OAAe;IAC3C,OAAO,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AACpC,CAAC;AAED;;GAEG;AACH,SAAS,kBAAkB,CAAC,WAAmB;IAC7C,qEAAqE;IACrE,wFAAwF;IACxF,OAAO,WAAW,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;AACzC,CAAC;AA+BD;;GAEG;AACH,MAAM,UAAU,GAAG,gEAAgE,CAAC;AAEpF;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAAe;IAC/C,+DAA+D;IAC/D,IAAI,oBAAoB,CAAC,OAAO,CAAC,EAAE,CAAC;QAClC,OAAO,iBAAiB,CAAC,OAAO,CAAC,CAAC;IACpC,CAAC;IAED,yDAAyD;IACzD,IAAI,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QAC5B,OAAO,cAAc,CAAC,OAAO,CAAC,CAAC;IACjC,CAAC;IAED,oCAAoC;IACpC,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;GAGG;AACH,SAAS,iCAAiC,CAAC,GAAW;IACpD,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,OAAO,GAAG,EAAE,CAAC;IACjB,IAAI,CAAC,GAAG,CAAC,CAAC;IAEV,OAAO,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC;QACtB,IAAI,GAAG,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;YACnB,IAAI,OAAO,EAAE,CAAC;gBACZ,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBACrB,OAAO,GAAG,EAAE,CAAC;YACf,CAAC;YACD,gCAAgC;YAChC,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;gBAC7C,6DAA6D;gBAC7D,gEAAgE;gBAChE,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;gBAChB,CAAC,EAAE,CAAC,CAAC,yBAAyB;YAChC,CAAC;YACD,CAAC,EAAE,CAAC;QACN,CAAC;aAAM,CAAC;YACN,OAAO,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC,EAAE,CAAC;QACN,CAAC;IACH,CAAC;IAED,IAAI,OAAO,EAAE,CAAC;QACZ,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACvB,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;GAEG;AACH,SAAS,iBAAiB,CAAC,OAAe;IACxC,MAAM,WAAW,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IAC/B,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY;IAE3C,oEAAoE;IACpE,MAAM,UAAU,GAAG,GAAG,WAAW,KAAK,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC;IAEhE,gEAAgE;IAChE,MAAM,gBAAgB,GAAG,UAAU,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAEzD,sCAAsC;IACtC,IAAI,UAAU,CAAC,gBAAgB,CAAC,EAAE,CAAC;QACjC,OAAO,gBAAgB,CAAC;IAC1B,CAAC;IAED,gEAAgE;IAChE,sDAAsD;IACtD,MAAM,QAAQ,GAAG,iCAAiC,CAAC,IAAI,CAAC,CAAC;IACzD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,GAAG,WAAW,IAAI,CAAC;IAC5B,CAAC;IAED,MAAM,aAAa,GAAa,EAAE,CAAC;IAEnC,6EAA6E;IAC7E,SAAS,aAAa,CAAC,KAAe,EAAE,KAAa,EAAE,WAAmB;QACxE,IAAI,KAAK,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;YAC1B,aAAa,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YAChC,OAAO;QACT,CAAC;QAED,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC;QAE1B,6EAA6E;QAC7E,IAAI,IAAI,KAAK,EAAE,IAAI,WAAW,EAAE,CAAC;YAC/B,MAAM,SAAS,GAAG,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACzC,MAAM,QAAQ,GAAG,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC;YACvC,MAAM,OAAO,GAAG,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,QAAQ,GAAG,GAAG,CAAC;YAC3D,aAAa,CAAC,KAAK,EAAE,KAAK,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC;YACzC,OAAO;QACT,CAAC;QAED,6CAA6C;QAC7C,MAAM,MAAM,GAAG,WAAW,GAAG,GAAG,GAAG,IAAI,CAAC;QACxC,aAAa,CAAC,KAAK,EAAE,KAAK,GAAG,CAAC,EAAE,MAAM,CAAC,CAAC;QAExC,0EAA0E;QAC1E,IAAI,KAAK,GAAG,CAAC,IAAI,WAAW,EAAE,CAAC;YAC7B,MAAM,SAAS,GAAG,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACzC,MAAM,QAAQ,GAAG,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC;YACvC,MAAM,OAAO,GAAG,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,QAAQ,GAAG,GAAG,GAAG,IAAI,CAAC;YAClE,aAAa,CAAC,KAAK,EAAE,KAAK,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC;QAC3C,CAAC;IACH,CAAC;IAED,aAAa,CAAC,QAAQ,EAAE,CAAC,EAAE,GAAG,WAAW,GAAG,CAAC,CAAC;IAE9C,gDAAgD;IAChD,KAAK,MAAM,IAAI,IAAI,aAAa,EAAE,CAAC;QACjC,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACrB,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,6BAA6B;IAC7B,OAAO,gBAAgB,CAAC;AAC1B,CAAC;AAED;;GAEG;AACH,SAAS,cAAc,CAAC,OAAe;IACrC,iDAAiD;IACjD,MAAM,UAAU,GAAG,GAAG,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAE7D,2BAA2B;IAC3B,MAAM,gBAAgB,GAAG,UAAU,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAEzD,sCAAsC;IACtC,IAAI,UAAU,CAAC,gBAAgB,CAAC,EAAE,CAAC;QACjC,OAAO,gBAAgB,CAAC;IAC1B,CAAC;IAED,gEAAgE;IAChE,sDAAsD;IACtD,MAAM,QAAQ,GAAG,iCAAiC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACrE,MAAM,aAAa,GAAa,EAAE,CAAC;IAEnC,6EAA6E;IAC7E,SAAS,aAAa,CAAC,KAAe,EAAE,KAAa,EAAE,WAAmB;QACxE,IAAI,KAAK,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;YAC1B,aAAa,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YAChC,OAAO;QACT,CAAC;QAED,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC;QAE1B,6EAA6E;QAC7E,IAAI,IAAI,KAAK,EAAE,IAAI,WAAW,EAAE,CAAC;YAC/B,MAAM,SAAS,GAAG,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACzC,MAAM,QAAQ,GAAG,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC;YACvC,MAAM,OAAO,GAAG,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,QAAQ,GAAG,GAAG,CAAC;YAC3D,aAAa,CAAC,KAAK,EAAE,KAAK,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC;YACzC,OAAO;QACT,CAAC;QAED,6CAA6C;QAC7C,aAAa,CAAC,KAAK,EAAE,KAAK,GAAG,CAAC,EAAE,WAAW,GAAG,GAAG,GAAG,IAAI,CAAC,CAAC;QAE1D,0EAA0E;QAC1E,IAAI,KAAK,GAAG,CAAC,IAAI,WAAW,EAAE,CAAC;YAC7B,MAAM,SAAS,GAAG,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACzC,MAAM,QAAQ,GAAG,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC;YACvC,MAAM,OAAO,GAAG,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,QAAQ,GAAG,GAAG,GAAG,IAAI,CAAC;YAClE,aAAa,CAAC,KAAK,EAAE,KAAK,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC;QAC3C,CAAC;IACH,CAAC;IAED,aAAa,CAAC,QAAQ,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;IAE/B,gDAAgD;IAChD,KAAK,MAAM,IAAI,IAAI,aAAa,EAAE,CAAC;QACjC,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACrB,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,6BAA6B;IAC7B,OAAO,gBAAgB,CAAC;AAC1B,CAAC;AAED;;GAEG;AACH,SAAS,cAAc,CAAC,IAAY,EAAE,OAAgB;IACpD,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAE1B,gCAAgC;IAChC,MAAM,YAAY,GAAG,OAAO;SACzB,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC;SACrB,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC;SACpB,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAEvB,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,IAAI,YAAY,GAAG,CAAC,CAAC;IAC9C,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,UAAuB,EAAE;IAC7D,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;IAC3D,MAAM,WAAW,GAAqB,EAAE,CAAC;IACzC,MAAM,WAAW,GAAG,IAAI,GAAG,EAAU,CAAC;IAEtC,IAAI,CAAC;QACH,+BAA+B;QAC/B,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,WAAW,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QAEpE,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE;gBAAE,SAAS;YAEnC,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC;YAC9B,MAAM,WAAW,GAAG,iBAAiB,CAAC,UAAU,CAAC,CAAC;YAElD,oCAAoC;YACpC,IAAI,CAAC,cAAc,CAAC,WAAW,EAAE,OAAO,CAAC,aAAa,CAAC,EAAE,CAAC;gBACxD,SAAS;YACX,CAAC;YAED,MAAM,eAAe,GAAG,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;YAEtD,2CAA2C;YAC3C,MAAM,YAAY,GAAG,MAAM,OAAO,CAAC,eAAe,CAAC,CAAC;YAEpD,KAAK,MAAM,QAAQ,IAAI,YAAY,EAAE,CAAC;gBACpC,oDAAoD;gBACpD,IAAI,QAAQ,KAAK,qBAAqB,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;oBACvE,SAAS;gBACX,CAAC;gBAED,mCAAmC;gBACnC,MAAM,SAAS,GAAG,QAAQ,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;gBAEjD,4CAA4C;gBAC5C,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;oBAChC,SAAS;gBACX,CAAC;gBAED,MAAM,QAAQ,GAAG,IAAI,CAAC,eAAe,EAAE,QAAQ,CAAC,CAAC;gBACjD,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC;gBAEvC,iCAAiC;gBACjC,IAAI,OAAO,CAAC,OAAO,IAAI,SAAS,CAAC,KAAK,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;oBACzD,SAAS;gBACX,CAAC;gBAED,WAAW,CAAC,IAAI,CAAC;oBACf,WAAW;oBACX,UAAU;oBACV,SAAS;oBACT,QAAQ;oBACR,QAAQ,EAAE,SAAS,CAAC,IAAI;oBACxB,YAAY,EAAE,SAAS,CAAC,KAAK;iBAC9B,CAAC,CAAC;gBAEH,WAAW,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;YAC9B,CAAC;QACH,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,2DAA2D;QAC3D,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACvD,OAAO;gBACL,WAAW,EAAE,EAAE;gBACf,SAAS,EAAE,CAAC;gBACZ,YAAY,EAAE,CAAC;aAChB,CAAC;QACJ,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;IAED,MAAM,SAAS,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;IAEtE,OAAO;QACL,WAAW;QACX,SAAS;QACT,YAAY,EAAE,WAAW,CAAC,IAAI;KAC/B,CAAC;AACJ,CAAC"}
|
package/dist/cli/analytics.js
CHANGED
|
File without changes
|
package/dist/cli/index.js
CHANGED
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.test.d.ts","sourceRoot":"","sources":["../../../../src/hooks/empty-message-sanitizer/__tests__/index.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,416 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { hasTextContent, isToolPart, hasValidContent, sanitizeMessage, sanitizeMessages, createEmptyMessageSanitizerHook, PLACEHOLDER_TEXT, TOOL_PART_TYPES, HOOK_NAME, } from '../index.js';
|
|
3
|
+
// Helper to create message parts
|
|
4
|
+
function createTextPart(text, id) {
|
|
5
|
+
return {
|
|
6
|
+
id: id || `part-${Date.now()}`,
|
|
7
|
+
type: 'text',
|
|
8
|
+
text,
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
function createToolPart(type, id) {
|
|
12
|
+
return {
|
|
13
|
+
id: id || `part-${Date.now()}`,
|
|
14
|
+
type,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
// Helper to create messages
|
|
18
|
+
function createMessage(role, parts, id) {
|
|
19
|
+
return {
|
|
20
|
+
info: {
|
|
21
|
+
id: id || `msg-${Date.now()}`,
|
|
22
|
+
role,
|
|
23
|
+
sessionID: 'test-session',
|
|
24
|
+
},
|
|
25
|
+
parts,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
describe('empty-message-sanitizer', () => {
|
|
29
|
+
describe('hasTextContent', () => {
|
|
30
|
+
it('should return true for part with non-empty text', () => {
|
|
31
|
+
const part = createTextPart('Hello');
|
|
32
|
+
expect(hasTextContent(part)).toBe(true);
|
|
33
|
+
});
|
|
34
|
+
it('should return false for part with empty text', () => {
|
|
35
|
+
const part = createTextPart('');
|
|
36
|
+
expect(hasTextContent(part)).toBe(false);
|
|
37
|
+
});
|
|
38
|
+
it('should return false for part with whitespace only', () => {
|
|
39
|
+
const part = createTextPart(' \n\t ');
|
|
40
|
+
expect(hasTextContent(part)).toBe(false);
|
|
41
|
+
});
|
|
42
|
+
it('should return false for part with undefined text', () => {
|
|
43
|
+
const part = createTextPart(undefined);
|
|
44
|
+
expect(hasTextContent(part)).toBe(false);
|
|
45
|
+
});
|
|
46
|
+
it('should return false for non-text part types', () => {
|
|
47
|
+
const part = createToolPart('tool_use');
|
|
48
|
+
expect(hasTextContent(part)).toBe(false);
|
|
49
|
+
});
|
|
50
|
+
it('should return true for text with only newlines but also content', () => {
|
|
51
|
+
const part = createTextPart('\nHello\n');
|
|
52
|
+
expect(hasTextContent(part)).toBe(true);
|
|
53
|
+
});
|
|
54
|
+
it('should return false for null-like text value', () => {
|
|
55
|
+
const part = { type: 'text', text: null };
|
|
56
|
+
expect(hasTextContent(part)).toBe(false);
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
describe('isToolPart', () => {
|
|
60
|
+
it('should return true for tool part type', () => {
|
|
61
|
+
const part = createToolPart('tool');
|
|
62
|
+
expect(isToolPart(part)).toBe(true);
|
|
63
|
+
});
|
|
64
|
+
it('should return true for tool_use part type', () => {
|
|
65
|
+
const part = createToolPart('tool_use');
|
|
66
|
+
expect(isToolPart(part)).toBe(true);
|
|
67
|
+
});
|
|
68
|
+
it('should return true for tool_result part type', () => {
|
|
69
|
+
const part = createToolPart('tool_result');
|
|
70
|
+
expect(isToolPart(part)).toBe(true);
|
|
71
|
+
});
|
|
72
|
+
it('should return false for text part type', () => {
|
|
73
|
+
const part = createTextPart('text content');
|
|
74
|
+
expect(isToolPart(part)).toBe(false);
|
|
75
|
+
});
|
|
76
|
+
it('should return false for image part type', () => {
|
|
77
|
+
const part = { type: 'image' };
|
|
78
|
+
expect(isToolPart(part)).toBe(false);
|
|
79
|
+
});
|
|
80
|
+
it('should return false for unknown part type', () => {
|
|
81
|
+
const part = { type: 'unknown_type' };
|
|
82
|
+
expect(isToolPart(part)).toBe(false);
|
|
83
|
+
});
|
|
84
|
+
it('should use TOOL_PART_TYPES constant', () => {
|
|
85
|
+
expect(TOOL_PART_TYPES.has('tool')).toBe(true);
|
|
86
|
+
expect(TOOL_PART_TYPES.has('tool_use')).toBe(true);
|
|
87
|
+
expect(TOOL_PART_TYPES.has('tool_result')).toBe(true);
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
describe('hasValidContent', () => {
|
|
91
|
+
it('should return true for parts with non-empty text', () => {
|
|
92
|
+
const parts = [createTextPart('Hello')];
|
|
93
|
+
expect(hasValidContent(parts)).toBe(true);
|
|
94
|
+
});
|
|
95
|
+
it('should return true for parts with tool part', () => {
|
|
96
|
+
const parts = [createToolPart('tool_use')];
|
|
97
|
+
expect(hasValidContent(parts)).toBe(true);
|
|
98
|
+
});
|
|
99
|
+
it('should return true for parts with both text and tool', () => {
|
|
100
|
+
const parts = [
|
|
101
|
+
createTextPart('Hello'),
|
|
102
|
+
createToolPart('tool_use'),
|
|
103
|
+
];
|
|
104
|
+
expect(hasValidContent(parts)).toBe(true);
|
|
105
|
+
});
|
|
106
|
+
it('should return false for empty parts array', () => {
|
|
107
|
+
expect(hasValidContent([])).toBe(false);
|
|
108
|
+
});
|
|
109
|
+
it('should return false for parts with only empty text', () => {
|
|
110
|
+
const parts = [createTextPart(''), createTextPart(' ')];
|
|
111
|
+
expect(hasValidContent(parts)).toBe(false);
|
|
112
|
+
});
|
|
113
|
+
it('should return false for parts with undefined text', () => {
|
|
114
|
+
const parts = [createTextPart(undefined)];
|
|
115
|
+
expect(hasValidContent(parts)).toBe(false);
|
|
116
|
+
});
|
|
117
|
+
it('should return true when one part has valid text among empties', () => {
|
|
118
|
+
const parts = [
|
|
119
|
+
createTextPart(''),
|
|
120
|
+
createTextPart('Valid'),
|
|
121
|
+
createTextPart(' '),
|
|
122
|
+
];
|
|
123
|
+
expect(hasValidContent(parts)).toBe(true);
|
|
124
|
+
});
|
|
125
|
+
it('should return true when tool part exists among empty text parts', () => {
|
|
126
|
+
const parts = [
|
|
127
|
+
createTextPart(''),
|
|
128
|
+
createToolPart('tool_result'),
|
|
129
|
+
];
|
|
130
|
+
expect(hasValidContent(parts)).toBe(true);
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
describe('sanitizeMessage', () => {
|
|
134
|
+
it('should not modify message with valid text content', () => {
|
|
135
|
+
const message = createMessage('user', [createTextPart('Hello')]);
|
|
136
|
+
const result = sanitizeMessage(message, false);
|
|
137
|
+
expect(result).toBe(false);
|
|
138
|
+
expect(message.parts[0].text).toBe('Hello');
|
|
139
|
+
});
|
|
140
|
+
it('should not modify message with tool part', () => {
|
|
141
|
+
const message = createMessage('assistant', [createToolPart('tool_use')]);
|
|
142
|
+
const result = sanitizeMessage(message, false);
|
|
143
|
+
expect(result).toBe(false);
|
|
144
|
+
});
|
|
145
|
+
it('should skip final assistant message', () => {
|
|
146
|
+
const message = createMessage('assistant', []);
|
|
147
|
+
const result = sanitizeMessage(message, true);
|
|
148
|
+
expect(result).toBe(false);
|
|
149
|
+
expect(message.parts.length).toBe(0);
|
|
150
|
+
});
|
|
151
|
+
it('should sanitize non-final assistant message with empty content', () => {
|
|
152
|
+
const message = createMessage('assistant', []);
|
|
153
|
+
const result = sanitizeMessage(message, false);
|
|
154
|
+
expect(result).toBe(true);
|
|
155
|
+
expect(message.parts.length).toBe(1);
|
|
156
|
+
expect(message.parts[0].text).toBe(PLACEHOLDER_TEXT);
|
|
157
|
+
expect(message.parts[0].synthetic).toBe(true);
|
|
158
|
+
});
|
|
159
|
+
it('should sanitize user message with empty parts array', () => {
|
|
160
|
+
const message = createMessage('user', []);
|
|
161
|
+
const result = sanitizeMessage(message, false);
|
|
162
|
+
expect(result).toBe(true);
|
|
163
|
+
expect(message.parts.length).toBe(1);
|
|
164
|
+
expect(message.parts[0].text).toBe(PLACEHOLDER_TEXT);
|
|
165
|
+
});
|
|
166
|
+
it('should replace existing empty text part', () => {
|
|
167
|
+
const message = createMessage('user', [createTextPart('')]);
|
|
168
|
+
const result = sanitizeMessage(message, false);
|
|
169
|
+
expect(result).toBe(true);
|
|
170
|
+
expect(message.parts.length).toBe(1);
|
|
171
|
+
expect(message.parts[0].text).toBe(PLACEHOLDER_TEXT);
|
|
172
|
+
expect(message.parts[0].synthetic).toBe(true);
|
|
173
|
+
});
|
|
174
|
+
it('should replace whitespace-only text part', () => {
|
|
175
|
+
const message = createMessage('user', [createTextPart(' \n ')]);
|
|
176
|
+
const result = sanitizeMessage(message, false);
|
|
177
|
+
expect(result).toBe(true);
|
|
178
|
+
expect(message.parts[0].text).toBe(PLACEHOLDER_TEXT);
|
|
179
|
+
});
|
|
180
|
+
it('should insert text part before tool part when no text exists', () => {
|
|
181
|
+
const message = createMessage('user', [createToolPart('tool_use')]);
|
|
182
|
+
const originalLength = message.parts.length;
|
|
183
|
+
const result = sanitizeMessage(message, false);
|
|
184
|
+
expect(result).toBe(false); // Tool part counts as valid content
|
|
185
|
+
});
|
|
186
|
+
it('should append text part when no tool parts exist', () => {
|
|
187
|
+
const message = createMessage('user', []);
|
|
188
|
+
sanitizeMessage(message, false);
|
|
189
|
+
expect(message.parts.length).toBe(1);
|
|
190
|
+
expect(message.parts[0].type).toBe('text');
|
|
191
|
+
});
|
|
192
|
+
it('should use custom placeholder text', () => {
|
|
193
|
+
const message = createMessage('user', []);
|
|
194
|
+
const customPlaceholder = '[custom placeholder]';
|
|
195
|
+
sanitizeMessage(message, false, customPlaceholder);
|
|
196
|
+
expect(message.parts[0].text).toBe(customPlaceholder);
|
|
197
|
+
});
|
|
198
|
+
it('should set synthetic flag on injected parts', () => {
|
|
199
|
+
const message = createMessage('user', []);
|
|
200
|
+
sanitizeMessage(message, false);
|
|
201
|
+
expect(message.parts[0].synthetic).toBe(true);
|
|
202
|
+
});
|
|
203
|
+
it('should sanitize empty text parts alongside valid content', () => {
|
|
204
|
+
const message = createMessage('user', [
|
|
205
|
+
createTextPart('Valid'),
|
|
206
|
+
createTextPart(''),
|
|
207
|
+
]);
|
|
208
|
+
const result = sanitizeMessage(message, false);
|
|
209
|
+
expect(result).toBe(true);
|
|
210
|
+
expect(message.parts[1].text).toBe(PLACEHOLDER_TEXT);
|
|
211
|
+
expect(message.parts[1].synthetic).toBe(true);
|
|
212
|
+
});
|
|
213
|
+
it('should not modify non-empty text alongside empty text', () => {
|
|
214
|
+
const message = createMessage('user', [
|
|
215
|
+
createTextPart('Valid'),
|
|
216
|
+
createTextPart(''),
|
|
217
|
+
]);
|
|
218
|
+
sanitizeMessage(message, false);
|
|
219
|
+
expect(message.parts[0].text).toBe('Valid');
|
|
220
|
+
expect(message.parts[0].synthetic).toBeUndefined();
|
|
221
|
+
});
|
|
222
|
+
it('should handle message with multiple empty text parts', () => {
|
|
223
|
+
const message = createMessage('user', [
|
|
224
|
+
createTextPart(''),
|
|
225
|
+
createTextPart(' '),
|
|
226
|
+
]);
|
|
227
|
+
sanitizeMessage(message, false);
|
|
228
|
+
// First empty text part should be replaced
|
|
229
|
+
expect(message.parts[0].text).toBe(PLACEHOLDER_TEXT);
|
|
230
|
+
});
|
|
231
|
+
});
|
|
232
|
+
describe('sanitizeMessages', () => {
|
|
233
|
+
it('should sanitize all messages in input', () => {
|
|
234
|
+
const input = {
|
|
235
|
+
messages: [
|
|
236
|
+
createMessage('user', []),
|
|
237
|
+
createMessage('assistant', [createTextPart('')]),
|
|
238
|
+
createMessage('user', [createTextPart('Valid')]),
|
|
239
|
+
],
|
|
240
|
+
};
|
|
241
|
+
const result = sanitizeMessages(input);
|
|
242
|
+
expect(result.sanitizedCount).toBe(2);
|
|
243
|
+
expect(result.modified).toBe(true);
|
|
244
|
+
});
|
|
245
|
+
it('should return modified false when no sanitization needed', () => {
|
|
246
|
+
const input = {
|
|
247
|
+
messages: [
|
|
248
|
+
createMessage('user', [createTextPart('Hello')]),
|
|
249
|
+
createMessage('assistant', [createTextPart('World')]),
|
|
250
|
+
],
|
|
251
|
+
};
|
|
252
|
+
const result = sanitizeMessages(input);
|
|
253
|
+
expect(result.sanitizedCount).toBe(0);
|
|
254
|
+
expect(result.modified).toBe(false);
|
|
255
|
+
});
|
|
256
|
+
it('should skip final assistant message', () => {
|
|
257
|
+
const input = {
|
|
258
|
+
messages: [
|
|
259
|
+
createMessage('user', [createTextPart('Hello')]),
|
|
260
|
+
createMessage('assistant', []), // Last message, assistant with empty content
|
|
261
|
+
],
|
|
262
|
+
};
|
|
263
|
+
const result = sanitizeMessages(input);
|
|
264
|
+
expect(result.sanitizedCount).toBe(0);
|
|
265
|
+
expect(input.messages[1].parts.length).toBe(0);
|
|
266
|
+
});
|
|
267
|
+
it('should use custom placeholder text from config', () => {
|
|
268
|
+
const input = {
|
|
269
|
+
messages: [createMessage('user', [])],
|
|
270
|
+
};
|
|
271
|
+
const result = sanitizeMessages(input, { placeholderText: '[custom]' });
|
|
272
|
+
expect(input.messages[0].parts[0].text).toBe('[custom]');
|
|
273
|
+
});
|
|
274
|
+
it('should return messages array in output', () => {
|
|
275
|
+
const input = {
|
|
276
|
+
messages: [createMessage('user', [createTextPart('Test')])],
|
|
277
|
+
};
|
|
278
|
+
const result = sanitizeMessages(input);
|
|
279
|
+
expect(result.messages).toBe(input.messages);
|
|
280
|
+
});
|
|
281
|
+
it('should handle empty messages array', () => {
|
|
282
|
+
const input = {
|
|
283
|
+
messages: [],
|
|
284
|
+
};
|
|
285
|
+
const result = sanitizeMessages(input);
|
|
286
|
+
expect(result.sanitizedCount).toBe(0);
|
|
287
|
+
expect(result.modified).toBe(false);
|
|
288
|
+
});
|
|
289
|
+
it('should sanitize non-final assistant message in the middle', () => {
|
|
290
|
+
const input = {
|
|
291
|
+
messages: [
|
|
292
|
+
createMessage('user', [createTextPart('Hello')]),
|
|
293
|
+
createMessage('assistant', []), // Not last, should be sanitized
|
|
294
|
+
createMessage('user', [createTextPart('Follow up')]),
|
|
295
|
+
],
|
|
296
|
+
};
|
|
297
|
+
const result = sanitizeMessages(input);
|
|
298
|
+
expect(result.sanitizedCount).toBe(1);
|
|
299
|
+
expect(input.messages[1].parts[0].text).toBe(PLACEHOLDER_TEXT);
|
|
300
|
+
});
|
|
301
|
+
it('should handle single message array', () => {
|
|
302
|
+
const input = {
|
|
303
|
+
messages: [createMessage('user', [])],
|
|
304
|
+
};
|
|
305
|
+
const result = sanitizeMessages(input);
|
|
306
|
+
// Single user message is not the "last assistant", so should be sanitized
|
|
307
|
+
expect(result.sanitizedCount).toBe(1);
|
|
308
|
+
});
|
|
309
|
+
it('should preserve sessionId in input', () => {
|
|
310
|
+
const input = {
|
|
311
|
+
messages: [createMessage('user', [createTextPart('Test')])],
|
|
312
|
+
sessionId: 'test-session-123',
|
|
313
|
+
};
|
|
314
|
+
const result = sanitizeMessages(input);
|
|
315
|
+
expect(result.messages).toBe(input.messages);
|
|
316
|
+
});
|
|
317
|
+
});
|
|
318
|
+
describe('createEmptyMessageSanitizerHook', () => {
|
|
319
|
+
it('should create hook with sanitize method', () => {
|
|
320
|
+
const hook = createEmptyMessageSanitizerHook();
|
|
321
|
+
expect(typeof hook.sanitize).toBe('function');
|
|
322
|
+
});
|
|
323
|
+
it('should create hook with getName method', () => {
|
|
324
|
+
const hook = createEmptyMessageSanitizerHook();
|
|
325
|
+
expect(typeof hook.getName).toBe('function');
|
|
326
|
+
expect(hook.getName()).toBe(HOOK_NAME);
|
|
327
|
+
});
|
|
328
|
+
it('should sanitize messages via hook sanitize method', () => {
|
|
329
|
+
const hook = createEmptyMessageSanitizerHook();
|
|
330
|
+
const input = {
|
|
331
|
+
messages: [createMessage('user', [])],
|
|
332
|
+
};
|
|
333
|
+
const result = hook.sanitize(input);
|
|
334
|
+
expect(result.sanitizedCount).toBe(1);
|
|
335
|
+
expect(result.modified).toBe(true);
|
|
336
|
+
});
|
|
337
|
+
it('should use custom placeholder from config', () => {
|
|
338
|
+
const hook = createEmptyMessageSanitizerHook({ placeholderText: '[hook custom]' });
|
|
339
|
+
const input = {
|
|
340
|
+
messages: [createMessage('user', [])],
|
|
341
|
+
};
|
|
342
|
+
hook.sanitize(input);
|
|
343
|
+
expect(input.messages[0].parts[0].text).toBe('[hook custom]');
|
|
344
|
+
});
|
|
345
|
+
it('should use default placeholder when no config', () => {
|
|
346
|
+
const hook = createEmptyMessageSanitizerHook();
|
|
347
|
+
const input = {
|
|
348
|
+
messages: [createMessage('user', [])],
|
|
349
|
+
};
|
|
350
|
+
hook.sanitize(input);
|
|
351
|
+
expect(input.messages[0].parts[0].text).toBe(PLACEHOLDER_TEXT);
|
|
352
|
+
});
|
|
353
|
+
});
|
|
354
|
+
describe('constants', () => {
|
|
355
|
+
it('should export PLACEHOLDER_TEXT', () => {
|
|
356
|
+
expect(PLACEHOLDER_TEXT).toBe('[user interrupted]');
|
|
357
|
+
});
|
|
358
|
+
it('should export HOOK_NAME', () => {
|
|
359
|
+
expect(HOOK_NAME).toBe('empty-message-sanitizer');
|
|
360
|
+
});
|
|
361
|
+
it('should export TOOL_PART_TYPES with correct values', () => {
|
|
362
|
+
expect(TOOL_PART_TYPES.size).toBe(3);
|
|
363
|
+
expect(TOOL_PART_TYPES.has('tool')).toBe(true);
|
|
364
|
+
expect(TOOL_PART_TYPES.has('tool_use')).toBe(true);
|
|
365
|
+
expect(TOOL_PART_TYPES.has('tool_result')).toBe(true);
|
|
366
|
+
});
|
|
367
|
+
});
|
|
368
|
+
describe('edge cases', () => {
|
|
369
|
+
it('should handle message with mixed valid and invalid parts', () => {
|
|
370
|
+
const message = createMessage('user', [
|
|
371
|
+
createTextPart(''),
|
|
372
|
+
createToolPart('tool_use'),
|
|
373
|
+
createTextPart(' '),
|
|
374
|
+
createTextPart('Valid'),
|
|
375
|
+
]);
|
|
376
|
+
const result = sanitizeMessage(message, false);
|
|
377
|
+
// Empty text parts should be sanitized
|
|
378
|
+
expect(result).toBe(true);
|
|
379
|
+
});
|
|
380
|
+
it('should handle very long placeholder text', () => {
|
|
381
|
+
const longPlaceholder = 'x'.repeat(1000);
|
|
382
|
+
const message = createMessage('user', []);
|
|
383
|
+
sanitizeMessage(message, false, longPlaceholder);
|
|
384
|
+
expect(message.parts[0].text).toBe(longPlaceholder);
|
|
385
|
+
});
|
|
386
|
+
it('should handle special characters in text', () => {
|
|
387
|
+
const message = createMessage('user', [createTextPart('!@#$%^&*()')]);
|
|
388
|
+
const result = sanitizeMessage(message, false);
|
|
389
|
+
expect(result).toBe(false);
|
|
390
|
+
expect(message.parts[0].text).toBe('!@#$%^&*()');
|
|
391
|
+
});
|
|
392
|
+
it('should handle unicode text', () => {
|
|
393
|
+
const message = createMessage('user', [createTextPart('한글 テスト 中文')]);
|
|
394
|
+
const result = sanitizeMessage(message, false);
|
|
395
|
+
expect(result).toBe(false);
|
|
396
|
+
expect(message.parts[0].text).toBe('한글 テスト 中文');
|
|
397
|
+
});
|
|
398
|
+
it('should handle emoji text', () => {
|
|
399
|
+
const message = createMessage('user', [createTextPart('Hello 👋 World 🌍')]);
|
|
400
|
+
const result = sanitizeMessage(message, false);
|
|
401
|
+
expect(result).toBe(false);
|
|
402
|
+
});
|
|
403
|
+
it('should preserve message info when sanitizing', () => {
|
|
404
|
+
const message = createMessage('user', [], 'my-custom-id');
|
|
405
|
+
sanitizeMessage(message, false);
|
|
406
|
+
expect(message.info.id).toBe('my-custom-id');
|
|
407
|
+
expect(message.info.role).toBe('user');
|
|
408
|
+
});
|
|
409
|
+
it('should set correct messageID on synthetic part', () => {
|
|
410
|
+
const message = createMessage('user', [], 'test-msg-id');
|
|
411
|
+
sanitizeMessage(message, false);
|
|
412
|
+
expect(message.parts[0].messageID).toBe('test-msg-id');
|
|
413
|
+
});
|
|
414
|
+
});
|
|
415
|
+
});
|
|
416
|
+
//# sourceMappingURL=index.test.js.map
|