oh-my-claude-sisyphus 3.6.2 → 3.7.0

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.
Files changed (124) hide show
  1. package/README.md +16 -0
  2. package/commands/doctor.md +1 -1
  3. package/dist/__tests__/delegation-enforcement-levels.test.d.ts +9 -0
  4. package/dist/__tests__/delegation-enforcement-levels.test.d.ts.map +1 -0
  5. package/dist/__tests__/delegation-enforcement-levels.test.js +550 -0
  6. package/dist/__tests__/delegation-enforcement-levels.test.js.map +1 -0
  7. package/dist/__tests__/installer.test.js +1 -1
  8. package/dist/__tests__/rate-limit-wait/daemon.test.d.ts +5 -0
  9. package/dist/__tests__/rate-limit-wait/daemon.test.d.ts.map +1 -0
  10. package/dist/__tests__/rate-limit-wait/daemon.test.js +313 -0
  11. package/dist/__tests__/rate-limit-wait/daemon.test.js.map +1 -0
  12. package/dist/__tests__/rate-limit-wait/integration.test.d.ts +8 -0
  13. package/dist/__tests__/rate-limit-wait/integration.test.d.ts.map +1 -0
  14. package/dist/__tests__/rate-limit-wait/integration.test.js +329 -0
  15. package/dist/__tests__/rate-limit-wait/integration.test.js.map +1 -0
  16. package/dist/__tests__/rate-limit-wait/rate-limit-monitor.test.d.ts +5 -0
  17. package/dist/__tests__/rate-limit-wait/rate-limit-monitor.test.d.ts.map +1 -0
  18. package/dist/__tests__/rate-limit-wait/rate-limit-monitor.test.js +167 -0
  19. package/dist/__tests__/rate-limit-wait/rate-limit-monitor.test.js.map +1 -0
  20. package/dist/__tests__/rate-limit-wait/tmux-detector.test.d.ts +5 -0
  21. package/dist/__tests__/rate-limit-wait/tmux-detector.test.d.ts.map +1 -0
  22. package/dist/__tests__/rate-limit-wait/tmux-detector.test.js +295 -0
  23. package/dist/__tests__/rate-limit-wait/tmux-detector.test.js.map +1 -0
  24. package/dist/__tests__/skills.test.js +6 -5
  25. package/dist/__tests__/skills.test.js.map +1 -1
  26. package/dist/cli/commands/wait.d.ts +52 -0
  27. package/dist/cli/commands/wait.d.ts.map +1 -0
  28. package/dist/cli/commands/wait.js +229 -0
  29. package/dist/cli/commands/wait.js.map +1 -0
  30. package/dist/cli/index.js +54 -0
  31. package/dist/cli/index.js.map +1 -1
  32. package/dist/features/rate-limit-wait/daemon.d.ts +52 -0
  33. package/dist/features/rate-limit-wait/daemon.d.ts.map +1 -0
  34. package/dist/features/rate-limit-wait/daemon.js +545 -0
  35. package/dist/features/rate-limit-wait/daemon.js.map +1 -0
  36. package/dist/features/rate-limit-wait/index.d.ts +16 -0
  37. package/dist/features/rate-limit-wait/index.d.ts.map +1 -0
  38. package/dist/features/rate-limit-wait/index.js +18 -0
  39. package/dist/features/rate-limit-wait/index.js.map +1 -0
  40. package/dist/features/rate-limit-wait/rate-limit-monitor.d.ts +22 -0
  41. package/dist/features/rate-limit-wait/rate-limit-monitor.d.ts.map +1 -0
  42. package/dist/features/rate-limit-wait/rate-limit-monitor.js +99 -0
  43. package/dist/features/rate-limit-wait/rate-limit-monitor.js.map +1 -0
  44. package/dist/features/rate-limit-wait/tmux-detector.d.ts +59 -0
  45. package/dist/features/rate-limit-wait/tmux-detector.d.ts.map +1 -0
  46. package/dist/features/rate-limit-wait/tmux-detector.js +304 -0
  47. package/dist/features/rate-limit-wait/tmux-detector.js.map +1 -0
  48. package/dist/features/rate-limit-wait/types.d.ts +121 -0
  49. package/dist/features/rate-limit-wait/types.d.ts.map +1 -0
  50. package/dist/features/rate-limit-wait/types.js +8 -0
  51. package/dist/features/rate-limit-wait/types.js.map +1 -0
  52. package/dist/hooks/bridge.d.ts +1 -1
  53. package/dist/hooks/bridge.d.ts.map +1 -1
  54. package/dist/hooks/bridge.js +50 -4
  55. package/dist/hooks/bridge.js.map +1 -1
  56. package/dist/hooks/index.d.ts +5 -0
  57. package/dist/hooks/index.d.ts.map +1 -1
  58. package/dist/hooks/index.js +15 -0
  59. package/dist/hooks/index.js.map +1 -1
  60. package/dist/hooks/omc-orchestrator/audit.d.ts +2 -1
  61. package/dist/hooks/omc-orchestrator/audit.d.ts.map +1 -1
  62. package/dist/hooks/omc-orchestrator/audit.js.map +1 -1
  63. package/dist/hooks/omc-orchestrator/index.d.ts +7 -0
  64. package/dist/hooks/omc-orchestrator/index.d.ts.map +1 -1
  65. package/dist/hooks/omc-orchestrator/index.js +95 -8
  66. package/dist/hooks/omc-orchestrator/index.js.map +1 -1
  67. package/dist/hooks/permission-handler/__tests__/index.test.d.ts +2 -0
  68. package/dist/hooks/permission-handler/__tests__/index.test.d.ts.map +1 -0
  69. package/dist/hooks/permission-handler/__tests__/index.test.js +244 -0
  70. package/dist/hooks/permission-handler/__tests__/index.test.js.map +1 -0
  71. package/dist/hooks/permission-handler/index.d.ts +42 -0
  72. package/dist/hooks/permission-handler/index.d.ts.map +1 -0
  73. package/dist/hooks/permission-handler/index.js +111 -0
  74. package/dist/hooks/permission-handler/index.js.map +1 -0
  75. package/dist/hooks/pre-compact/index.d.ts +82 -0
  76. package/dist/hooks/pre-compact/index.d.ts.map +1 -0
  77. package/dist/hooks/pre-compact/index.js +265 -0
  78. package/dist/hooks/pre-compact/index.js.map +1 -0
  79. package/dist/hooks/session-end/index.d.ts +50 -0
  80. package/dist/hooks/session-end/index.d.ts.map +1 -0
  81. package/dist/hooks/session-end/index.js +207 -0
  82. package/dist/hooks/session-end/index.js.map +1 -0
  83. package/dist/hooks/setup/index.d.ts +66 -0
  84. package/dist/hooks/setup/index.d.ts.map +1 -0
  85. package/dist/hooks/setup/index.js +299 -0
  86. package/dist/hooks/setup/index.js.map +1 -0
  87. package/dist/hooks/setup/types.d.ts +25 -0
  88. package/dist/hooks/setup/types.d.ts.map +1 -0
  89. package/dist/hooks/setup/types.js +5 -0
  90. package/dist/hooks/setup/types.js.map +1 -0
  91. package/dist/hooks/subagent-tracker/index.d.ts +68 -29
  92. package/dist/hooks/subagent-tracker/index.d.ts.map +1 -1
  93. package/dist/hooks/subagent-tracker/index.js +301 -131
  94. package/dist/hooks/subagent-tracker/index.js.map +1 -1
  95. package/dist/installer/index.d.ts +1 -1
  96. package/dist/installer/index.js +1 -1
  97. package/docs/MIGRATION.md +2 -2
  98. package/hooks/hooks.json +83 -1
  99. package/package.json +3 -1
  100. package/scripts/permission-handler.mjs +23 -0
  101. package/scripts/pre-compact.mjs +23 -0
  102. package/scripts/session-end.mjs +23 -0
  103. package/scripts/setup-init.mjs +23 -0
  104. package/scripts/setup-maintenance.mjs +23 -0
  105. package/scripts/subagent-tracker.mjs +35 -0
  106. package/skills/doctor/SKILL.md +1 -1
  107. package/templates/hooks/keyword-detector.mjs +198 -0
  108. package/templates/hooks/keyword-detector.sh +102 -0
  109. package/templates/hooks/persistent-mode.mjs +249 -0
  110. package/templates/hooks/persistent-mode.sh +187 -0
  111. package/templates/hooks/post-tool-use.mjs +133 -0
  112. package/templates/hooks/post-tool-use.sh +90 -0
  113. package/templates/hooks/pre-tool-use.mjs +145 -0
  114. package/templates/hooks/pre-tool-use.sh +113 -0
  115. package/templates/hooks/session-start.mjs +100 -0
  116. package/templates/hooks/session-start.sh +62 -0
  117. package/templates/hooks/stop-continuation.mjs +80 -0
  118. package/templates/hooks/stop-continuation.sh +40 -0
  119. package/templates/rules/README.md +40 -0
  120. package/templates/rules/coding-style.md +74 -0
  121. package/templates/rules/git-workflow.md +41 -0
  122. package/templates/rules/performance.md +40 -0
  123. package/templates/rules/security.md +41 -0
  124. package/templates/rules/testing.md +42 -0
@@ -0,0 +1,99 @@
1
+ /**
2
+ * Rate Limit Monitor
3
+ *
4
+ * Wraps the existing usage-api.ts to provide rate limit status monitoring.
5
+ * Uses the OAuth API to check utilization percentages.
6
+ */
7
+ import { getUsage } from '../../hud/usage-api.js';
8
+ /** Threshold percentage for considering rate limited */
9
+ const RATE_LIMIT_THRESHOLD = 100;
10
+ /**
11
+ * Check current rate limit status using the OAuth API
12
+ *
13
+ * @returns Rate limit status or null if API unavailable
14
+ */
15
+ export async function checkRateLimitStatus() {
16
+ try {
17
+ const usage = await getUsage();
18
+ if (!usage) {
19
+ // No OAuth credentials or API unavailable
20
+ return null;
21
+ }
22
+ const fiveHourLimited = usage.fiveHourPercent >= RATE_LIMIT_THRESHOLD;
23
+ const weeklyLimited = usage.weeklyPercent >= RATE_LIMIT_THRESHOLD;
24
+ const isLimited = fiveHourLimited || weeklyLimited;
25
+ // Determine next reset time
26
+ let nextResetAt = null;
27
+ let timeUntilResetMs = null;
28
+ if (isLimited) {
29
+ const now = Date.now();
30
+ const resets = [];
31
+ if (fiveHourLimited && usage.fiveHourResetsAt) {
32
+ resets.push(usage.fiveHourResetsAt);
33
+ }
34
+ if (weeklyLimited && usage.weeklyResetsAt) {
35
+ resets.push(usage.weeklyResetsAt);
36
+ }
37
+ if (resets.length > 0) {
38
+ // Find earliest reset
39
+ nextResetAt = resets.reduce((earliest, current) => current < earliest ? current : earliest);
40
+ timeUntilResetMs = Math.max(0, nextResetAt.getTime() - now);
41
+ }
42
+ }
43
+ return {
44
+ fiveHourLimited,
45
+ weeklyLimited,
46
+ isLimited,
47
+ fiveHourResetsAt: usage.fiveHourResetsAt ?? null,
48
+ weeklyResetsAt: usage.weeklyResetsAt ?? null,
49
+ nextResetAt,
50
+ timeUntilResetMs,
51
+ lastCheckedAt: new Date(),
52
+ };
53
+ }
54
+ catch (error) {
55
+ // Log error but don't throw - return null to indicate unavailable
56
+ console.error('[RateLimitMonitor] Error checking rate limit:', error);
57
+ return null;
58
+ }
59
+ }
60
+ /**
61
+ * Format time until reset for display
62
+ */
63
+ export function formatTimeUntilReset(ms) {
64
+ if (ms <= 0)
65
+ return 'now';
66
+ const seconds = Math.floor(ms / 1000);
67
+ const minutes = Math.floor(seconds / 60);
68
+ const hours = Math.floor(minutes / 60);
69
+ if (hours > 0) {
70
+ const remainingMinutes = minutes % 60;
71
+ return `${hours}h ${remainingMinutes}m`;
72
+ }
73
+ else if (minutes > 0) {
74
+ const remainingSeconds = seconds % 60;
75
+ return `${minutes}m ${remainingSeconds}s`;
76
+ }
77
+ return `${seconds}s`;
78
+ }
79
+ /**
80
+ * Get a human-readable rate limit status message
81
+ */
82
+ export function formatRateLimitStatus(status) {
83
+ if (!status.isLimited) {
84
+ return 'Not rate limited';
85
+ }
86
+ const parts = [];
87
+ if (status.fiveHourLimited) {
88
+ parts.push('5-hour limit reached');
89
+ }
90
+ if (status.weeklyLimited) {
91
+ parts.push('Weekly limit reached');
92
+ }
93
+ let message = parts.join(' and ');
94
+ if (status.timeUntilResetMs !== null) {
95
+ message += ` (resets in ${formatTimeUntilReset(status.timeUntilResetMs)})`;
96
+ }
97
+ return message;
98
+ }
99
+ //# sourceMappingURL=rate-limit-monitor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limit-monitor.js","sourceRoot":"","sources":["../../../src/features/rate-limit-wait/rate-limit-monitor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * tmux Detector
3
+ *
4
+ * Detects Claude Code sessions running in tmux panes and identifies
5
+ * those that are blocked due to rate limiting.
6
+ *
7
+ * Security considerations:
8
+ * - Pane IDs are validated before use in shell commands
9
+ * - Text inputs are sanitized to prevent command injection
10
+ */
11
+ import type { TmuxPane, PaneAnalysisResult, BlockedPane } from './types.js';
12
+ /**
13
+ * Check if tmux is installed and available
14
+ */
15
+ export declare function isTmuxAvailable(): boolean;
16
+ /**
17
+ * Check if currently running inside a tmux session
18
+ */
19
+ export declare function isInsideTmux(): boolean;
20
+ /**
21
+ * List all tmux panes across all sessions
22
+ */
23
+ export declare function listTmuxPanes(): TmuxPane[];
24
+ /**
25
+ * Capture the content of a specific tmux pane
26
+ *
27
+ * @param paneId - The tmux pane ID (e.g., "%0")
28
+ * @param lines - Number of lines to capture (default: 15)
29
+ */
30
+ export declare function capturePaneContent(paneId: string, lines?: number): string;
31
+ /**
32
+ * Analyze pane content to determine if it shows a rate-limited Claude Code session
33
+ */
34
+ export declare function analyzePaneContent(content: string): PaneAnalysisResult;
35
+ /**
36
+ * Scan all tmux panes for blocked Claude Code sessions
37
+ *
38
+ * @param lines - Number of lines to capture from each pane
39
+ */
40
+ export declare function scanForBlockedPanes(lines?: number): BlockedPane[];
41
+ /**
42
+ * Send resume sequence to a tmux pane
43
+ *
44
+ * This sends "1" followed by Enter to select the first option (usually "Continue"),
45
+ * then waits briefly and sends "continue" if needed.
46
+ *
47
+ * @param paneId - The tmux pane ID
48
+ * @returns Whether the command was sent successfully
49
+ */
50
+ export declare function sendResumeSequence(paneId: string): boolean;
51
+ /**
52
+ * Send custom text to a tmux pane
53
+ */
54
+ export declare function sendToPane(paneId: string, text: string, pressEnter?: boolean): boolean;
55
+ /**
56
+ * Get a summary of blocked panes for display
57
+ */
58
+ export declare function formatBlockedPanesSummary(blockedPanes: BlockedPane[]): string;
59
+ //# sourceMappingURL=tmux-detector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tmux-detector.d.ts","sourceRoot":"","sources":["../../../src/features/rate-limit-wait/tmux-detector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAoD5E;;GAEG;AACH,wBAAgB,eAAe,IAAI,OAAO,CAUzC;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,OAAO,CAEtC;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,QAAQ,EAAE,CAyC1C;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,SAAK,GAAG,MAAM,CAyBrE;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,kBAAkB,CAqDtE;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,SAAK,GAAG,WAAW,EAAE,CAmB7D;AAED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAwB1D;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,UAAO,GAAG,OAAO,CAsBnF;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,YAAY,EAAE,WAAW,EAAE,GAAG,MAAM,CAwB7E"}
@@ -0,0 +1,304 @@
1
+ /**
2
+ * tmux Detector
3
+ *
4
+ * Detects Claude Code sessions running in tmux panes and identifies
5
+ * those that are blocked due to rate limiting.
6
+ *
7
+ * Security considerations:
8
+ * - Pane IDs are validated before use in shell commands
9
+ * - Text inputs are sanitized to prevent command injection
10
+ */
11
+ import { execSync, spawnSync } from 'child_process';
12
+ /**
13
+ * Validate tmux pane ID format to prevent command injection
14
+ * Valid formats: %0, %1, %123, etc.
15
+ */
16
+ function isValidPaneId(paneId) {
17
+ return /^%\d+$/.test(paneId);
18
+ }
19
+ /**
20
+ * Sanitize text for use in tmux send-keys command
21
+ * Escapes single quotes to prevent command injection
22
+ */
23
+ function sanitizeForTmux(text) {
24
+ // Escape single quotes by ending the quote, adding escaped quote, and reopening
25
+ return text.replace(/'/g, "'\\''");
26
+ }
27
+ /** Rate limit message patterns to detect in pane content */
28
+ const RATE_LIMIT_PATTERNS = [
29
+ /rate limit/i,
30
+ /usage limit/i,
31
+ /quota exceeded/i,
32
+ /too many requests/i,
33
+ /please wait/i,
34
+ /try again later/i,
35
+ /limit reached/i,
36
+ /5[- ]?hour/i,
37
+ /weekly/i,
38
+ ];
39
+ /** Patterns that indicate Claude Code is running */
40
+ const CLAUDE_CODE_PATTERNS = [
41
+ /claude/i,
42
+ /anthropic/i,
43
+ /\$ claude/,
44
+ /claude code/i,
45
+ /conversation/i,
46
+ /assistant/i,
47
+ ];
48
+ /** Patterns that indicate the pane is waiting for user input */
49
+ const WAITING_PATTERNS = [
50
+ /\[\d+\]/, // Menu selection prompt like [1], [2], [3]
51
+ /continue\?/i, // Continue prompt
52
+ /press enter/i,
53
+ /waiting for/i,
54
+ /select an option/i,
55
+ /choice:/i,
56
+ ];
57
+ /**
58
+ * Check if tmux is installed and available
59
+ */
60
+ export function isTmuxAvailable() {
61
+ try {
62
+ const result = spawnSync('which', ['tmux'], {
63
+ encoding: 'utf-8',
64
+ timeout: 2000,
65
+ });
66
+ return result.status === 0 && result.stdout.trim().length > 0;
67
+ }
68
+ catch {
69
+ return false;
70
+ }
71
+ }
72
+ /**
73
+ * Check if currently running inside a tmux session
74
+ */
75
+ export function isInsideTmux() {
76
+ return !!process.env.TMUX;
77
+ }
78
+ /**
79
+ * List all tmux panes across all sessions
80
+ */
81
+ export function listTmuxPanes() {
82
+ if (!isTmuxAvailable()) {
83
+ return [];
84
+ }
85
+ try {
86
+ // Format: session_name:window_index.pane_index pane_id pane_active window_name pane_title
87
+ const format = '#{session_name}:#{window_index}.#{pane_index} #{pane_id} #{pane_active} #{window_name} #{pane_title}';
88
+ const result = execSync(`tmux list-panes -a -F '${format}'`, {
89
+ encoding: 'utf-8',
90
+ timeout: 5000,
91
+ });
92
+ const panes = [];
93
+ for (const line of result.trim().split('\n')) {
94
+ if (!line.trim())
95
+ continue;
96
+ const parts = line.split(' ');
97
+ if (parts.length < 4)
98
+ continue;
99
+ const [location, paneId, activeStr, windowName, ...titleParts] = parts;
100
+ const [sessionWindow, paneIndexStr] = location.split('.');
101
+ const [session, windowIndexStr] = sessionWindow.split(':');
102
+ panes.push({
103
+ id: paneId,
104
+ session,
105
+ windowIndex: parseInt(windowIndexStr, 10),
106
+ windowName,
107
+ paneIndex: parseInt(paneIndexStr, 10),
108
+ title: titleParts.join(' ') || undefined,
109
+ isActive: activeStr === '1',
110
+ });
111
+ }
112
+ return panes;
113
+ }
114
+ catch (error) {
115
+ console.error('[TmuxDetector] Error listing panes:', error);
116
+ return [];
117
+ }
118
+ }
119
+ /**
120
+ * Capture the content of a specific tmux pane
121
+ *
122
+ * @param paneId - The tmux pane ID (e.g., "%0")
123
+ * @param lines - Number of lines to capture (default: 15)
124
+ */
125
+ export function capturePaneContent(paneId, lines = 15) {
126
+ if (!isTmuxAvailable()) {
127
+ return '';
128
+ }
129
+ // Validate pane ID to prevent command injection
130
+ if (!isValidPaneId(paneId)) {
131
+ console.error(`[TmuxDetector] Invalid pane ID format: ${paneId}`);
132
+ return '';
133
+ }
134
+ // Validate lines is a reasonable positive integer
135
+ const safeLines = Math.max(1, Math.min(100, Math.floor(lines)));
136
+ try {
137
+ // Capture the last N lines from the pane
138
+ const result = execSync(`tmux capture-pane -t '${paneId}' -p -S -${safeLines}`, {
139
+ encoding: 'utf-8',
140
+ timeout: 5000,
141
+ });
142
+ return result;
143
+ }
144
+ catch (error) {
145
+ console.error(`[TmuxDetector] Error capturing pane ${paneId}:`, error);
146
+ return '';
147
+ }
148
+ }
149
+ /**
150
+ * Analyze pane content to determine if it shows a rate-limited Claude Code session
151
+ */
152
+ export function analyzePaneContent(content) {
153
+ if (!content.trim()) {
154
+ return {
155
+ hasClaudeCode: false,
156
+ hasRateLimitMessage: false,
157
+ isBlocked: false,
158
+ confidence: 0,
159
+ };
160
+ }
161
+ // Check for Claude Code indicators
162
+ const hasClaudeCode = CLAUDE_CODE_PATTERNS.some((pattern) => pattern.test(content));
163
+ // Check for rate limit messages
164
+ const rateLimitMatches = RATE_LIMIT_PATTERNS.filter((pattern) => pattern.test(content));
165
+ const hasRateLimitMessage = rateLimitMatches.length > 0;
166
+ // Check if waiting for user input
167
+ const isWaiting = WAITING_PATTERNS.some((pattern) => pattern.test(content));
168
+ // Determine rate limit type
169
+ let rateLimitType;
170
+ if (hasRateLimitMessage) {
171
+ if (/5[- ]?hour/i.test(content)) {
172
+ rateLimitType = 'five_hour';
173
+ }
174
+ else if (/weekly/i.test(content)) {
175
+ rateLimitType = 'weekly';
176
+ }
177
+ else {
178
+ rateLimitType = 'unknown';
179
+ }
180
+ }
181
+ // Calculate confidence
182
+ let confidence = 0;
183
+ if (hasClaudeCode)
184
+ confidence += 0.4;
185
+ if (hasRateLimitMessage)
186
+ confidence += 0.4;
187
+ if (isWaiting)
188
+ confidence += 0.2;
189
+ if (rateLimitMatches.length > 1)
190
+ confidence += 0.1; // Multiple matches = higher confidence
191
+ // Determine if blocked
192
+ const isBlocked = hasClaudeCode && hasRateLimitMessage && confidence >= 0.6;
193
+ return {
194
+ hasClaudeCode,
195
+ hasRateLimitMessage,
196
+ isBlocked,
197
+ rateLimitType,
198
+ confidence: Math.min(1, confidence),
199
+ };
200
+ }
201
+ /**
202
+ * Scan all tmux panes for blocked Claude Code sessions
203
+ *
204
+ * @param lines - Number of lines to capture from each pane
205
+ */
206
+ export function scanForBlockedPanes(lines = 15) {
207
+ const panes = listTmuxPanes();
208
+ const blocked = [];
209
+ for (const pane of panes) {
210
+ const content = capturePaneContent(pane.id, lines);
211
+ const analysis = analyzePaneContent(content);
212
+ if (analysis.isBlocked) {
213
+ blocked.push({
214
+ ...pane,
215
+ analysis,
216
+ firstDetectedAt: new Date(),
217
+ resumeAttempted: false,
218
+ });
219
+ }
220
+ }
221
+ return blocked;
222
+ }
223
+ /**
224
+ * Send resume sequence to a tmux pane
225
+ *
226
+ * This sends "1" followed by Enter to select the first option (usually "Continue"),
227
+ * then waits briefly and sends "continue" if needed.
228
+ *
229
+ * @param paneId - The tmux pane ID
230
+ * @returns Whether the command was sent successfully
231
+ */
232
+ export function sendResumeSequence(paneId) {
233
+ if (!isTmuxAvailable()) {
234
+ return false;
235
+ }
236
+ // Validate pane ID to prevent command injection
237
+ if (!isValidPaneId(paneId)) {
238
+ console.error(`[TmuxDetector] Invalid pane ID format: ${paneId}`);
239
+ return false;
240
+ }
241
+ try {
242
+ // Send "1" to select the first option (typically "Continue" or similar)
243
+ execSync(`tmux send-keys -t '${paneId}' '1' Enter`, {
244
+ timeout: 2000,
245
+ });
246
+ // Wait a moment for the response
247
+ // Note: In real usage, we should verify the pane state changed
248
+ return true;
249
+ }
250
+ catch (error) {
251
+ console.error(`[TmuxDetector] Error sending resume to pane ${paneId}:`, error);
252
+ return false;
253
+ }
254
+ }
255
+ /**
256
+ * Send custom text to a tmux pane
257
+ */
258
+ export function sendToPane(paneId, text, pressEnter = true) {
259
+ if (!isTmuxAvailable()) {
260
+ return false;
261
+ }
262
+ // Validate pane ID to prevent command injection
263
+ if (!isValidPaneId(paneId)) {
264
+ console.error(`[TmuxDetector] Invalid pane ID format: ${paneId}`);
265
+ return false;
266
+ }
267
+ try {
268
+ const sanitizedText = sanitizeForTmux(text);
269
+ const enterSuffix = pressEnter ? ' Enter' : '';
270
+ execSync(`tmux send-keys -t '${paneId}' '${sanitizedText}'${enterSuffix}`, {
271
+ timeout: 2000,
272
+ });
273
+ return true;
274
+ }
275
+ catch (error) {
276
+ console.error(`[TmuxDetector] Error sending to pane ${paneId}:`, error);
277
+ return false;
278
+ }
279
+ }
280
+ /**
281
+ * Get a summary of blocked panes for display
282
+ */
283
+ export function formatBlockedPanesSummary(blockedPanes) {
284
+ if (blockedPanes.length === 0) {
285
+ return 'No blocked Claude Code sessions detected.';
286
+ }
287
+ const lines = [
288
+ `Found ${blockedPanes.length} blocked Claude Code session(s):`,
289
+ '',
290
+ ];
291
+ for (const pane of blockedPanes) {
292
+ const location = `${pane.session}:${pane.windowIndex}.${pane.paneIndex}`;
293
+ const confidence = Math.round(pane.analysis.confidence * 100);
294
+ const limitType = pane.analysis.rateLimitType || 'unknown';
295
+ const status = pane.resumeAttempted
296
+ ? pane.resumeSuccessful
297
+ ? ' [RESUMED]'
298
+ : ' [RESUME FAILED]'
299
+ : '';
300
+ lines.push(` • ${location} (${pane.id}) - ${limitType} limit, ${confidence}% confidence${status}`);
301
+ }
302
+ return lines.join('\n');
303
+ }
304
+ //# sourceMappingURL=tmux-detector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tmux-detector.js","sourceRoot":"","sources":["../../../src/features/rate-limit-wait/tmux-detector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,121 @@
1
+ /**
2
+ * Rate Limit Wait - Type Definitions
3
+ *
4
+ * Types for the rate limit auto-resume daemon.
5
+ * Reference: https://github.com/EvanOman/cc-wait
6
+ */
7
+ export interface RateLimitStatus {
8
+ /** Whether rate limited on 5-hour window */
9
+ fiveHourLimited: boolean;
10
+ /** Whether rate limited on weekly window */
11
+ weeklyLimited: boolean;
12
+ /** Combined: true if either limit is hit */
13
+ isLimited: boolean;
14
+ /** When 5-hour limit resets */
15
+ fiveHourResetsAt: Date | null;
16
+ /** When weekly limit resets */
17
+ weeklyResetsAt: Date | null;
18
+ /** Earliest reset time */
19
+ nextResetAt: Date | null;
20
+ /** Time until reset in milliseconds */
21
+ timeUntilResetMs: number | null;
22
+ /** Last check timestamp */
23
+ lastCheckedAt: Date;
24
+ }
25
+ export interface TmuxPane {
26
+ /** Pane ID (e.g., "%0") */
27
+ id: string;
28
+ /** Session name */
29
+ session: string;
30
+ /** Window index */
31
+ windowIndex: number;
32
+ /** Window name */
33
+ windowName: string;
34
+ /** Pane index within window */
35
+ paneIndex: number;
36
+ /** Pane title (if set) */
37
+ title?: string;
38
+ /** Whether this pane is currently active */
39
+ isActive: boolean;
40
+ }
41
+ export interface PaneAnalysisResult {
42
+ /** Whether this pane appears to have Claude Code */
43
+ hasClaudeCode: boolean;
44
+ /** Whether rate limit message is visible */
45
+ hasRateLimitMessage: boolean;
46
+ /** Whether the pane appears blocked (waiting for input) */
47
+ isBlocked: boolean;
48
+ /** Detected rate limit type if any */
49
+ rateLimitType?: 'five_hour' | 'weekly' | 'unknown';
50
+ /** Confidence level (0-1) */
51
+ confidence: number;
52
+ }
53
+ export interface BlockedPane extends TmuxPane {
54
+ /** Analysis result for this pane */
55
+ analysis: PaneAnalysisResult;
56
+ /** When this pane was first detected as blocked */
57
+ firstDetectedAt: Date;
58
+ /** Whether resume has been attempted */
59
+ resumeAttempted: boolean;
60
+ /** Whether resume was successful */
61
+ resumeSuccessful?: boolean;
62
+ }
63
+ export interface DaemonState {
64
+ /** Whether daemon is running */
65
+ isRunning: boolean;
66
+ /** Process ID if running */
67
+ pid: number | null;
68
+ /** When daemon started */
69
+ startedAt: Date | null;
70
+ /** Last poll timestamp */
71
+ lastPollAt: Date | null;
72
+ /** Current rate limit status */
73
+ rateLimitStatus: RateLimitStatus | null;
74
+ /** Currently tracked blocked panes */
75
+ blockedPanes: BlockedPane[];
76
+ /** Panes that have been resumed (to avoid re-sending) */
77
+ resumedPaneIds: string[];
78
+ /** Total resume attempts */
79
+ totalResumeAttempts: number;
80
+ /** Successful resume count */
81
+ successfulResumes: number;
82
+ /** Error count */
83
+ errorCount: number;
84
+ /** Last error message */
85
+ lastError?: string;
86
+ }
87
+ export interface DaemonConfig {
88
+ /** Polling interval in milliseconds (default: 60000 = 1 minute) */
89
+ pollIntervalMs?: number;
90
+ /** Number of pane lines to capture for analysis (default: 15) */
91
+ paneLinesToCapture?: number;
92
+ /** Whether to log verbose output (default: false) */
93
+ verbose?: boolean;
94
+ /** State file path (default: ~/.omc/state/rate-limit-daemon.json) */
95
+ stateFilePath?: string;
96
+ /** PID file path (default: ~/.omc/state/rate-limit-daemon.pid) */
97
+ pidFilePath?: string;
98
+ /** Log file path (default: ~/.omc/state/rate-limit-daemon.log) */
99
+ logFilePath?: string;
100
+ }
101
+ export interface ResumeResult {
102
+ /** Pane ID */
103
+ paneId: string;
104
+ /** Whether resume was successful */
105
+ success: boolean;
106
+ /** Error message if failed */
107
+ error?: string;
108
+ /** Timestamp */
109
+ timestamp: Date;
110
+ }
111
+ export interface DaemonCommand {
112
+ action: 'start' | 'stop' | 'status' | 'detect';
113
+ options?: DaemonConfig;
114
+ }
115
+ export interface DaemonResponse {
116
+ success: boolean;
117
+ message: string;
118
+ state?: DaemonState;
119
+ error?: string;
120
+ }
121
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/features/rate-limit-wait/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Rate Limit Wait - Type Definitions
3
+ *
4
+ * Types for the rate limit auto-resume daemon.
5
+ * Reference: https://github.com/EvanOman/cc-wait
6
+ */
7
+ export {};
8
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/features/rate-limit-wait/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
@@ -54,7 +54,7 @@ export interface HookOutput {
54
54
  /**
55
55
  * Hook types that can be processed
56
56
  */
57
- export type HookType = 'keyword-detector' | 'stop-continuation' | 'ralph' | 'persistent-mode' | 'session-start' | 'pre-tool-use' | 'post-tool-use' | 'autopilot';
57
+ export type HookType = 'keyword-detector' | 'stop-continuation' | 'ralph' | 'persistent-mode' | 'session-start' | 'session-end' | 'pre-tool-use' | 'post-tool-use' | 'autopilot' | 'subagent-start' | 'subagent-stop' | 'pre-compact' | 'setup-init' | 'setup-maintenance' | 'permission-request';
58
58
  /**
59
59
  * Main hook processor
60
60
  * Routes to specific hook handler based on type
@@ -1 +1 @@
1
- {"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../../src/hooks/bridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AA8BH;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,yBAAyB;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uBAAuB;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,8CAA8C;IAC9C,OAAO,CAAC,EAAE;QACR,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC;IACF,4CAA4C;IAC5C,KAAK,CAAC,EAAE,KAAK,CAAC;QACZ,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC,CAAC;IACH,iCAAiC;IACjC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4BAA4B;IAC5B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,wCAAwC;IACxC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,wBAAwB;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,6CAA6C;IAC7C,QAAQ,EAAE,OAAO,CAAC;IAClB,8CAA8C;IAC9C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gDAAgD;IAChD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,+CAA+C;IAC/C,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,MAAM,QAAQ,GAChB,kBAAkB,GAClB,mBAAmB,GACnB,OAAO,GACP,iBAAiB,GACjB,eAAe,GACf,cAAc,GACd,eAAe,GACf,WAAW,CAAC;AAoZhB;;;GAGG;AACH,wBAAsB,WAAW,CAC/B,QAAQ,EAAE,QAAQ,EAClB,KAAK,EAAE,SAAS,GACf,OAAO,CAAC,UAAU,CAAC,CAmCrB;AAED;;;GAGG;AACH,wBAAsB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CA+B1C"}
1
+ {"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../../src/hooks/bridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAuDH;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,yBAAyB;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uBAAuB;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,8CAA8C;IAC9C,OAAO,CAAC,EAAE;QACR,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC;IACF,4CAA4C;IAC5C,KAAK,CAAC,EAAE,KAAK,CAAC;QACZ,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC,CAAC;IACH,iCAAiC;IACjC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4BAA4B;IAC5B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,wCAAwC;IACxC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,wBAAwB;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,6CAA6C;IAC7C,QAAQ,EAAE,OAAO,CAAC;IAClB,8CAA8C;IAC9C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gDAAgD;IAChD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,+CAA+C;IAC/C,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,MAAM,QAAQ,GAChB,kBAAkB,GAClB,mBAAmB,GACnB,OAAO,GACP,iBAAiB,GACjB,eAAe,GACf,aAAa,GACb,cAAc,GACd,eAAe,GACf,WAAW,GACX,gBAAgB,GAChB,eAAe,GACf,aAAa,GACb,YAAY,GACZ,mBAAmB,GACnB,oBAAoB,CAAC;AAsazB;;;GAGG;AACH,wBAAsB,WAAW,CAC/B,QAAQ,EAAE,QAAQ,EAClB,KAAK,EAAE,SAAS,GACf,OAAO,CAAC,UAAU,CAAC,CAiErB;AAED;;;GAGG;AACH,wBAAsB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CA+B1C"}