safeword 0.15.11 → 0.15.12

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "safeword",
3
- "version": "0.15.11",
3
+ "version": "0.15.12",
4
4
  "description": "CLI for setting up and managing safeword development environments",
5
5
  "type": "module",
6
6
  "bin": {
@@ -49,15 +49,17 @@
49
49
  },
50
50
  "devDependencies": {
51
51
  "@types/node": "^20.10.0",
52
- "@vitest/coverage-v8": "^4.0.16",
52
+ "@vitest/coverage-v8": "^4.0.17",
53
+ "dependency-cruiser": "^17.3.6",
53
54
  "eslint": "^9.39.2",
54
55
  "knip": "^5.79.0",
55
56
  "prettier": "^3.7.4",
56
57
  "prettier-plugin-sh": "^0.18.0",
57
58
  "publint": "^0.3.16",
59
+ "safeword": "^0.15.11",
58
60
  "tsup": "^8.0.0",
59
61
  "typescript": "^5.3.0",
60
- "vitest": "^4.0.15"
62
+ "vitest": "^4.0.17"
61
63
  },
62
64
  "keywords": [
63
65
  "cli",
@@ -152,6 +152,31 @@ if (!(await transcriptFile.exists())) {
152
152
  const transcriptText = await transcriptFile.text();
153
153
  const lines = transcriptText.trim().split('\n');
154
154
 
155
+ // Check last message for usage limit (avoids false positives from conversation content)
156
+ // Claude shows blocking messages when quota exceeded - these are short, standalone messages
157
+ // Patterns: "5-hour limit reached", "Usage limit reached", {"type":"exceeded_limit"}
158
+ const USAGE_LIMIT_PATTERN =
159
+ /\b(usage limit reached|5-hour limit reached|"type"\s*:\s*"exceeded_limit")\b/i;
160
+ try {
161
+ const lastLine = lines[lines.length - 1] ?? '';
162
+ const lastMessage: TranscriptMessage = JSON.parse(lastLine);
163
+ // Extract text content from message
164
+ const textContent =
165
+ lastMessage.message?.content
166
+ ?.filter(
167
+ (item): item is ContentItem & { text: string } => item.type === 'text' && !!item.text,
168
+ )
169
+ .map(item => item.text)
170
+ .join('') ?? '';
171
+ // Only trigger if text content is short (< 200 chars) - limit messages are brief
172
+ if (textContent.length > 0 && textContent.length < 200 && USAGE_LIMIT_PATTERN.test(textContent)) {
173
+ console.error('SAFEWORD: Claude usage limit reached. Try again after reset.');
174
+ process.exit(1);
175
+ }
176
+ } catch {
177
+ // Not valid JSON or missing structure - continue with normal processing
178
+ }
179
+
155
180
  // Only look at the LAST assistant message for JSON summary
156
181
  // Scan up to 5 recent assistant messages for edit tool detection
157
182
  const recentTexts: string[] = [];