instar 0.8.1 → 0.8.2
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/README.md
CHANGED
|
@@ -165,7 +165,7 @@ Each session is a **real Claude Code process** with extended thinking, native to
|
|
|
165
165
|
|
|
166
166
|
## Why Instar (vs OpenClaw)
|
|
167
167
|
|
|
168
|
-
If you're coming from OpenClaw, NanoClaw, or similar projects
|
|
168
|
+
If you're coming from OpenClaw, NanoClaw, or similar projects affected by Anthropic's OAuth policy change -- Instar is architecturally different.
|
|
169
169
|
|
|
170
170
|
### ToS-compliant by design
|
|
171
171
|
|
|
@@ -209,7 +209,7 @@ Some claims are less proven: iOS app is "internal preview." Voice wake docs retu
|
|
|
209
209
|
|
|
210
210
|
**Self-evolution.** The agent modifies its own jobs, hooks, skills, config, and infrastructure. Not just workspace files -- the system itself.
|
|
211
211
|
|
|
212
|
-
Different tools for different needs.
|
|
212
|
+
Different tools for different needs. Different bets on different futures.
|
|
213
213
|
|
|
214
214
|
> Full comparison: [positioning-vs-openclaw.md](docs/positioning-vs-openclaw.md)
|
|
215
215
|
|
package/dist/cli.js
CHANGED
|
File without changes
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* Uses EventEmitter pattern consistent with Instar conventions.
|
|
10
10
|
*/
|
|
11
11
|
import { EventEmitter } from 'node:events';
|
|
12
|
-
import { spawn,
|
|
12
|
+
import { spawn, spawnSync } from 'child_process';
|
|
13
13
|
import * as fs from 'fs';
|
|
14
14
|
import * as path from 'path';
|
|
15
15
|
const WATCHDOG_INTERVAL_MS = 30_000; // 30 seconds
|
|
@@ -135,10 +135,10 @@ export class CaffeinateManager extends EventEmitter {
|
|
|
135
135
|
const stalePid = parseInt(fs.readFileSync(this.pidFile, 'utf-8').trim(), 10);
|
|
136
136
|
if (!isNaN(stalePid) && stalePid > 0) {
|
|
137
137
|
try {
|
|
138
|
-
const cmdline =
|
|
138
|
+
const cmdline = (spawnSync('ps', ['-p', String(stalePid), '-o', 'comm='], {
|
|
139
139
|
encoding: 'utf-8',
|
|
140
140
|
timeout: 3000,
|
|
141
|
-
}).trim();
|
|
141
|
+
}).stdout ?? '').trim();
|
|
142
142
|
if (cmdline.includes('caffeinate')) {
|
|
143
143
|
process.kill(stalePid, 'SIGTERM');
|
|
144
144
|
console.log(`[CaffeinateManager] Killed stale caffeinate (PID: ${stalePid})`);
|
|
@@ -13,8 +13,9 @@
|
|
|
13
13
|
* Includes trend tracking via ring buffer + linear regression.
|
|
14
14
|
*/
|
|
15
15
|
import { EventEmitter } from 'node:events';
|
|
16
|
-
import {
|
|
16
|
+
import { spawnSync } from 'node:child_process';
|
|
17
17
|
import * as fs from 'node:fs';
|
|
18
|
+
import os from 'node:os';
|
|
18
19
|
const DEFAULT_THRESHOLDS = {
|
|
19
20
|
warning: 60,
|
|
20
21
|
elevated: 75,
|
|
@@ -156,7 +157,7 @@ export class MemoryPressureMonitor extends EventEmitter {
|
|
|
156
157
|
else {
|
|
157
158
|
// Fallback: use Node's process.memoryUsage (very rough)
|
|
158
159
|
const mem = process.memoryUsage();
|
|
159
|
-
const totalGB =
|
|
160
|
+
const totalGB = os.totalmem() / (1024 ** 3);
|
|
160
161
|
const usedGB = mem.rss / (1024 ** 3);
|
|
161
162
|
return {
|
|
162
163
|
pressurePercent: (usedGB / totalGB) * 100,
|
|
@@ -169,7 +170,7 @@ export class MemoryPressureMonitor extends EventEmitter {
|
|
|
169
170
|
* macOS: parse vm_stat
|
|
170
171
|
*/
|
|
171
172
|
parseVmStat() {
|
|
172
|
-
const output =
|
|
173
|
+
const output = spawnSync('vm_stat', [], { encoding: 'utf-8', timeout: 5000 }).stdout ?? '';
|
|
173
174
|
const pageSizeMatch = output.match(/page size of (\d+) bytes/);
|
|
174
175
|
const pageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : PAGE_SIZE_BYTES;
|
|
175
176
|
const parsePages = (label) => {
|
|
@@ -12,8 +12,12 @@
|
|
|
12
12
|
* Level 3: SIGKILL the stuck child PID
|
|
13
13
|
* Level 4: Kill tmux session
|
|
14
14
|
*/
|
|
15
|
-
import {
|
|
15
|
+
import { spawnSync } from 'node:child_process';
|
|
16
16
|
import { EventEmitter } from 'node:events';
|
|
17
|
+
/** Drop-in replacement for execSync that avoids its security concerns. */
|
|
18
|
+
function shellExec(cmd, timeout = 5000) {
|
|
19
|
+
return spawnSync('/bin/sh', ['-c', cmd], { encoding: 'utf-8', timeout }).stdout ?? '';
|
|
20
|
+
}
|
|
17
21
|
export var EscalationLevel;
|
|
18
22
|
(function (EscalationLevel) {
|
|
19
23
|
EscalationLevel[EscalationLevel["Monitoring"] = 0] = "Monitoring";
|
|
@@ -205,14 +209,14 @@ export class SessionWatchdog extends EventEmitter {
|
|
|
205
209
|
getClaudePid(tmuxSession) {
|
|
206
210
|
try {
|
|
207
211
|
// Get pane PID
|
|
208
|
-
const panePidStr =
|
|
212
|
+
const panePidStr = shellExec(`${this.config.sessions.tmuxPath} list-panes -t "=${tmuxSession}" -F "#{pane_pid}" 2>/dev/null`).trim().split('\n')[0];
|
|
209
213
|
if (!panePidStr)
|
|
210
214
|
return null;
|
|
211
215
|
const panePid = parseInt(panePidStr, 10);
|
|
212
216
|
if (isNaN(panePid))
|
|
213
217
|
return null;
|
|
214
218
|
// Find claude child
|
|
215
|
-
const claudePidStr =
|
|
219
|
+
const claudePidStr = shellExec(`pgrep -P ${panePid} -f claude 2>/dev/null | head -1`).trim();
|
|
216
220
|
if (!claudePidStr)
|
|
217
221
|
return null;
|
|
218
222
|
const pid = parseInt(claudePidStr, 10);
|
|
@@ -224,13 +228,13 @@ export class SessionWatchdog extends EventEmitter {
|
|
|
224
228
|
}
|
|
225
229
|
getChildProcesses(pid) {
|
|
226
230
|
try {
|
|
227
|
-
const childPidsStr =
|
|
231
|
+
const childPidsStr = shellExec(`pgrep -P ${pid} 2>/dev/null`).trim();
|
|
228
232
|
if (!childPidsStr)
|
|
229
233
|
return [];
|
|
230
234
|
const childPids = childPidsStr.split('\n').filter(Boolean).join(',');
|
|
231
235
|
if (!childPids)
|
|
232
236
|
return [];
|
|
233
|
-
const output =
|
|
237
|
+
const output = shellExec(`ps -o pid=,etime=,command= -p ${childPids} 2>/dev/null`).trim();
|
|
234
238
|
if (!output)
|
|
235
239
|
return [];
|
|
236
240
|
const results = [];
|
|
@@ -303,7 +307,7 @@ export class SessionWatchdog extends EventEmitter {
|
|
|
303
307
|
}
|
|
304
308
|
killTmuxSession(tmuxSession) {
|
|
305
309
|
try {
|
|
306
|
-
|
|
310
|
+
shellExec(`${this.config.sessions.tmuxPath} kill-session -t "=${tmuxSession}" 2>/dev/null`);
|
|
307
311
|
}
|
|
308
312
|
catch { }
|
|
309
313
|
}
|
package/package.json
CHANGED
package/.vercel/README.txt
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
> Why do I have a folder named ".vercel" in my project?
|
|
2
|
-
The ".vercel" folder is created when you link a directory to a Vercel project.
|
|
3
|
-
|
|
4
|
-
> What does the "project.json" file contain?
|
|
5
|
-
The "project.json" file contains:
|
|
6
|
-
- The ID of the Vercel project that you linked ("projectId")
|
|
7
|
-
- The ID of the user or team your Vercel project is owned by ("orgId")
|
|
8
|
-
|
|
9
|
-
> Should I commit the ".vercel" folder?
|
|
10
|
-
No, you should not share the ".vercel" folder with anyone.
|
|
11
|
-
Upon creation, it will be automatically added to your ".gitignore" file.
|
package/.vercel/project.json
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"projectId":"prj_evM5LcItYL3IAmw8zNvEPGrHeaya","orgId":"team_dHctwIDcV3X9ydapQlCPHFGI","projectName":"claude-agent-kit"}
|