@tjamescouch/niki 0.5.3 → 0.5.4

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 (2) hide show
  1. package/bin/niki +26 -0
  2. package/package.json +1 -1
package/bin/niki CHANGED
@@ -109,6 +109,32 @@ const MAX_RESTARTS = parseInt(opts['max-restarts'], 10);
109
109
  const RESTART_DELAY_S = parseFloat(opts['restart-delay']);
110
110
  const LOG_JSON = opts['log-json'];
111
111
 
112
+ // --- Invocation rate limiting (prevent tight crash loops) ---
113
+
114
+ const INVOCATION_LOCKFILE = `/tmp/niki-invocation-${process.pid}.lock`;
115
+ const GLOBAL_LOCKFILE = '/tmp/niki-last-invocation';
116
+
117
+ try {
118
+ if (existsSync(GLOBAL_LOCKFILE)) {
119
+ const lastInvocation = parseFloat(readFileSync(GLOBAL_LOCKFILE, 'utf8'));
120
+ const now = Date.now() / 1000;
121
+ const delta = now - lastInvocation;
122
+
123
+ if (delta < 1.0) {
124
+ console.error(`[niki] ERROR: Invoked too quickly (${delta.toFixed(3)}s since last invocation)`);
125
+ console.error(`[niki] Refusing to start — something is calling niki in a tight loop`);
126
+ console.error(`[niki] This prevents expensive crash loops. Wait at least 1 second between invocations.`);
127
+ process.exit(42); // Exit code 42 = rate-limited
128
+ }
129
+ }
130
+
131
+ // Update timestamp
132
+ writeFileSync(GLOBAL_LOCKFILE, String(Date.now() / 1000));
133
+ } catch (err) {
134
+ // Non-fatal if we can't write lockfile (e.g., permission issues)
135
+ console.error(`[niki] Warning: Could not check invocation rate (${err.message})`);
136
+ }
137
+
112
138
  // --- Log levels ---
113
139
 
114
140
  const LOG_LEVELS = { debug: 0, info: 1, warn: 2, error: 3 };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tjamescouch/niki",
3
- "version": "0.5.3",
3
+ "version": "0.5.4",
4
4
  "description": "Deterministic process supervisor for AI agents — token budgets, rate limits, and abort control",
5
5
  "bin": {
6
6
  "niki": "./bin/niki"