rex-claude 4.0.0 → 6.0.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.
- package/dist/agents-JIZXXASP.js +853 -0
- package/dist/app-3VWDSH5F.js +248 -0
- package/dist/audio-US2J627E.js +196 -0
- package/dist/audit-ZVTGE4L4.js +8 -0
- package/dist/call-AQZ3Z5SE.js +143 -0
- package/dist/chunk-5ND7JYY3.js +62 -0
- package/dist/chunk-6SRV2I2H.js +56 -0
- package/dist/{setup-AO3MW46W.js → chunk-A7ZLQUOX.js} +93 -16
- package/dist/chunk-E5UYN3W7.js +105 -0
- package/dist/chunk-HAHJD3QH.js +147 -0
- package/dist/{init-DLFEGD6O.js → chunk-KR7ISYZH.js} +328 -29
- package/dist/chunk-LTOM55UV.js +154 -0
- package/dist/chunk-PDX44BCA.js +11 -0
- package/dist/chunk-PPGYFMU5.js +67 -0
- package/dist/{chunk-7AGI43F5.js → chunk-WBMVBMWB.js} +4 -2
- package/dist/{context-FN5O5YBI.js → context-XNCG2M5Q.js} +2 -1
- package/dist/daemon-5KNSNFTD.js +208 -0
- package/dist/gateway-YLP66MCQ.js +2273 -0
- package/dist/hammerspoon/rex-call-watcher.lua +186 -0
- package/dist/index.js +309 -15
- package/dist/init-RDZFIBLA.js +30 -0
- package/dist/install-63JBDPRU.js +41 -0
- package/dist/{llm-YRORUH7E.js → llm-RALIPIMI.js} +2 -1
- package/dist/mcp_registry-DX4GGSP6.js +514 -0
- package/dist/migrate-GDO37TI5.js +87 -0
- package/dist/{optimize-UKMAGQQE.js → optimize-5TE5RKZV.js} +2 -1
- package/dist/paths-4SECM6E6.js +38 -0
- package/dist/preload-I3MYBVNU.js +78 -0
- package/dist/projects-V6TSLO7E.js +17 -0
- package/dist/{prune-2PPIVDXK.js → prune-B7F5B5OF.js} +2 -1
- package/dist/recategorize-YXYIMQLZ.js +155 -0
- package/dist/router-2JD34COX.js +12 -0
- package/dist/self-improve-YK7RCYF4.js +197 -0
- package/dist/setup-KNDTVFO6.js +8 -0
- package/dist/skills-AIWFY5NH.js +374 -0
- package/dist/voice-RITC3EVC.js +248 -0
- package/package.json +12 -3
- package/dist/gateway-EKMU5D7J.js +0 -784
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
// src/llm.ts
|
|
4
4
|
var OLLAMA_URL = process.env.OLLAMA_URL || "http://localhost:11434";
|
|
5
|
-
var PREFERRED_MODELS = ["
|
|
5
|
+
var PREFERRED_MODELS = ["qwen2.5:1.5b", "qwen3.5:4b", "llama3.2", "mistral"];
|
|
6
6
|
async function detectModel() {
|
|
7
7
|
if (process.env.REX_LLM_MODEL) return process.env.REX_LLM_MODEL;
|
|
8
8
|
try {
|
|
@@ -28,7 +28,9 @@ async function llm(prompt, system, model) {
|
|
|
28
28
|
model: useModel,
|
|
29
29
|
prompt,
|
|
30
30
|
system,
|
|
31
|
-
stream: false
|
|
31
|
+
stream: false,
|
|
32
|
+
think: false,
|
|
33
|
+
keep_alive: "30s"
|
|
32
34
|
})
|
|
33
35
|
});
|
|
34
36
|
if (!res.ok) throw new Error(`Ollama generate failed: ${res.status}`);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import "./chunk-PDX44BCA.js";
|
|
2
3
|
|
|
3
4
|
// src/context.ts
|
|
4
5
|
import { existsSync, readFileSync } from "fs";
|
|
@@ -68,7 +69,7 @@ ${line}`);
|
|
|
68
69
|
console.log(`${COLORS.bold} REX CONTEXT${COLORS.reset}`);
|
|
69
70
|
console.log(`${line}
|
|
70
71
|
`);
|
|
71
|
-
const absPath = join(process.cwd(), targetPath === "." ? "" : targetPath);
|
|
72
|
+
const absPath = targetPath.startsWith("/") ? targetPath : join(process.cwd(), targetPath === "." ? "" : targetPath);
|
|
72
73
|
const projectName = basename(absPath);
|
|
73
74
|
console.log(` ${COLORS.cyan}Project:${COLORS.reset} ${projectName}`);
|
|
74
75
|
console.log(` ${COLORS.cyan}Path:${COLORS.reset} ${absPath}
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
loadConfig
|
|
4
|
+
} from "./chunk-PPGYFMU5.js";
|
|
5
|
+
import {
|
|
6
|
+
createLogger,
|
|
7
|
+
rotateLog
|
|
8
|
+
} from "./chunk-5ND7JYY3.js";
|
|
9
|
+
import {
|
|
10
|
+
BACKUPS_DIR,
|
|
11
|
+
MEMORY_DB_PATH,
|
|
12
|
+
PENDING_DIR,
|
|
13
|
+
ensureRexDirs
|
|
14
|
+
} from "./chunk-6SRV2I2H.js";
|
|
15
|
+
import "./chunk-PDX44BCA.js";
|
|
16
|
+
|
|
17
|
+
// src/daemon.ts
|
|
18
|
+
import { existsSync, readdirSync, unlinkSync, copyFileSync, statSync } from "fs";
|
|
19
|
+
import { join } from "path";
|
|
20
|
+
import { execSync } from "child_process";
|
|
21
|
+
var OLLAMA_URL = process.env.OLLAMA_URL || "http://localhost:11434";
|
|
22
|
+
var log = createLogger("daemon");
|
|
23
|
+
async function checkOllama() {
|
|
24
|
+
try {
|
|
25
|
+
const res = await fetch(`${OLLAMA_URL}/api/tags`, { signal: AbortSignal.timeout(3e3) });
|
|
26
|
+
return res.ok;
|
|
27
|
+
} catch {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
async function restartOllama() {
|
|
32
|
+
try {
|
|
33
|
+
execSync("ollama serve &", { timeout: 5e3, stdio: "ignore" });
|
|
34
|
+
await new Promise((r) => setTimeout(r, 3e3));
|
|
35
|
+
return checkOllama();
|
|
36
|
+
} catch {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function checkDiskSpace() {
|
|
41
|
+
try {
|
|
42
|
+
const output = execSync("df -g ~ | tail -1 | awk '{print $4}'", { encoding: "utf-8" }).trim();
|
|
43
|
+
return parseInt(output) || 999;
|
|
44
|
+
} catch {
|
|
45
|
+
return 999;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
function checkDbIntegrity() {
|
|
49
|
+
if (!existsSync(MEMORY_DB_PATH)) return true;
|
|
50
|
+
try {
|
|
51
|
+
const result = execSync(`sqlite3 "${MEMORY_DB_PATH}" "PRAGMA integrity_check"`, { encoding: "utf-8" }).trim();
|
|
52
|
+
return result === "ok";
|
|
53
|
+
} catch {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
function backupDb() {
|
|
58
|
+
if (!existsSync(MEMORY_DB_PATH)) return;
|
|
59
|
+
const date = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
60
|
+
const backupPath = join(BACKUPS_DIR, `rex-${date}.sqlite`);
|
|
61
|
+
if (existsSync(backupPath)) return;
|
|
62
|
+
copyFileSync(MEMORY_DB_PATH, backupPath);
|
|
63
|
+
log.info(`Backup: ${backupPath}`);
|
|
64
|
+
}
|
|
65
|
+
function pruneBackups(retainDays = 7) {
|
|
66
|
+
if (!existsSync(BACKUPS_DIR)) return;
|
|
67
|
+
const cutoff = Date.now() - retainDays * 864e5;
|
|
68
|
+
for (const f of readdirSync(BACKUPS_DIR)) {
|
|
69
|
+
const fPath = join(BACKUPS_DIR, f);
|
|
70
|
+
try {
|
|
71
|
+
if (statSync(fPath).mtimeMs < cutoff) {
|
|
72
|
+
unlinkSync(fPath);
|
|
73
|
+
log.debug(`Pruned backup: ${f}`);
|
|
74
|
+
}
|
|
75
|
+
} catch {
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
function countPending() {
|
|
80
|
+
if (!existsSync(PENDING_DIR)) return 0;
|
|
81
|
+
return readdirSync(PENDING_DIR).filter((f) => f.endsWith(".json")).length;
|
|
82
|
+
}
|
|
83
|
+
function runCmd(cmd, timeout = 12e4) {
|
|
84
|
+
try {
|
|
85
|
+
execSync(cmd, { timeout, encoding: "utf-8", stdio: "pipe" });
|
|
86
|
+
} catch (e) {
|
|
87
|
+
log.error(`Command error (${cmd.slice(0, 30)}): ${e.message?.slice(0, 200)}`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
async function sendTelegramNotify(message) {
|
|
91
|
+
try {
|
|
92
|
+
const token = process.env.REX_TELEGRAM_BOT_TOKEN;
|
|
93
|
+
const chatId = process.env.REX_TELEGRAM_CHAT_ID;
|
|
94
|
+
if (!token || !chatId) return;
|
|
95
|
+
await fetch(`https://api.telegram.org/bot${token}/sendMessage`, {
|
|
96
|
+
method: "POST",
|
|
97
|
+
headers: { "Content-Type": "application/json" },
|
|
98
|
+
body: JSON.stringify({ chat_id: chatId, text: message, parse_mode: "Markdown" }),
|
|
99
|
+
signal: AbortSignal.timeout(1e4)
|
|
100
|
+
});
|
|
101
|
+
} catch {
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
async function healthCheck() {
|
|
105
|
+
const ollamaUp = await checkOllama();
|
|
106
|
+
if (!ollamaUp) {
|
|
107
|
+
log.warn("Ollama down \u2014 attempting restart");
|
|
108
|
+
const restarted = await restartOllama();
|
|
109
|
+
if (restarted) log.info("Ollama restarted successfully");
|
|
110
|
+
else log.error("Ollama restart failed");
|
|
111
|
+
}
|
|
112
|
+
if (await checkOllama()) {
|
|
113
|
+
const pending = countPending();
|
|
114
|
+
if (pending > 0) {
|
|
115
|
+
log.info(`Processing ${pending} pending files`);
|
|
116
|
+
runCmd("rex ingest");
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
if (!checkDbIntegrity()) {
|
|
120
|
+
log.error("DB integrity check FAILED");
|
|
121
|
+
const backups = existsSync(BACKUPS_DIR) ? readdirSync(BACKUPS_DIR).filter((f) => f.endsWith(".sqlite")).sort().reverse() : [];
|
|
122
|
+
if (backups.length) {
|
|
123
|
+
copyFileSync(join(BACKUPS_DIR, backups[0]), MEMORY_DB_PATH);
|
|
124
|
+
log.warn(`Restored DB from ${backups[0]}`);
|
|
125
|
+
await sendTelegramNotify("\u26A0\uFE0F REX: DB integrity fail \u2014 restored from backup");
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
const freeGb = checkDiskSpace();
|
|
129
|
+
if (freeGb < 1) {
|
|
130
|
+
log.warn(`Disk low: ${freeGb}GB free`);
|
|
131
|
+
pruneBackups(3);
|
|
132
|
+
await sendTelegramNotify(`\u26A0\uFE0F REX: Disk low (${freeGb}GB free)`);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
async function ingestCycle() {
|
|
136
|
+
log.info("Ingest cycle start");
|
|
137
|
+
runCmd("rex ingest");
|
|
138
|
+
runCmd("rex categorize --batch=100", 18e4);
|
|
139
|
+
runCmd("rex recategorize --batch=20", 18e4);
|
|
140
|
+
log.info("Ingest cycle done");
|
|
141
|
+
}
|
|
142
|
+
async function maintenanceCycle() {
|
|
143
|
+
log.info("Maintenance cycle start");
|
|
144
|
+
backupDb();
|
|
145
|
+
pruneBackups(7);
|
|
146
|
+
runCmd("rex projects", 3e4);
|
|
147
|
+
rotateLog();
|
|
148
|
+
log.info("Maintenance cycle done");
|
|
149
|
+
}
|
|
150
|
+
async function selfReviewCycle() {
|
|
151
|
+
log.info("Self-review cycle start");
|
|
152
|
+
runCmd("rex self-review");
|
|
153
|
+
const config = loadConfig();
|
|
154
|
+
if (config.notifications.daily) {
|
|
155
|
+
try {
|
|
156
|
+
const Database = (await import("better-sqlite3")).default;
|
|
157
|
+
const db = new Database(MEMORY_DB_PATH, { readonly: true });
|
|
158
|
+
const total = db.prepare("SELECT COUNT(*) as c FROM memories").get().c;
|
|
159
|
+
const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
160
|
+
const todayCount = db.prepare("SELECT COUNT(*) as c FROM memories WHERE created_at >= ?").get(today).c;
|
|
161
|
+
const uncategorized = db.prepare("SELECT COUNT(*) as c FROM memories WHERE category IN ('session', 'general')").get().c;
|
|
162
|
+
db.close();
|
|
163
|
+
const msg = `\u{1F996} *REX Daily*
|
|
164
|
+
|
|
165
|
+
Memories: ${total} total, +${todayCount} today
|
|
166
|
+
Uncategorized: ${uncategorized}
|
|
167
|
+
Disk: ${checkDiskSpace()}GB free`;
|
|
168
|
+
await sendTelegramNotify(msg);
|
|
169
|
+
} catch {
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
log.info("Self-review cycle done");
|
|
173
|
+
}
|
|
174
|
+
async function daemon() {
|
|
175
|
+
ensureRexDirs();
|
|
176
|
+
const config = loadConfig();
|
|
177
|
+
log.info("REX Daemon started");
|
|
178
|
+
log.info(`Health: ${config.daemon.healthCheckInterval}s | Ingest: ${config.daemon.ingestInterval}s | Maintenance: ${config.daemon.maintenanceInterval}s | Self-review: ${config.daemon.selfReviewInterval}s`);
|
|
179
|
+
await healthCheck();
|
|
180
|
+
let lastHealth = Date.now();
|
|
181
|
+
let lastIngest = Date.now();
|
|
182
|
+
let lastMaintenance = Date.now();
|
|
183
|
+
let lastSelfReview = Date.now();
|
|
184
|
+
await maintenanceCycle();
|
|
185
|
+
while (true) {
|
|
186
|
+
const now = Date.now();
|
|
187
|
+
if (now - lastHealth >= config.daemon.healthCheckInterval * 1e3) {
|
|
188
|
+
await healthCheck();
|
|
189
|
+
lastHealth = now;
|
|
190
|
+
}
|
|
191
|
+
if (now - lastIngest >= config.daemon.ingestInterval * 1e3) {
|
|
192
|
+
await ingestCycle();
|
|
193
|
+
lastIngest = now;
|
|
194
|
+
}
|
|
195
|
+
if (now - lastMaintenance >= config.daemon.maintenanceInterval * 1e3) {
|
|
196
|
+
await maintenanceCycle();
|
|
197
|
+
lastMaintenance = now;
|
|
198
|
+
}
|
|
199
|
+
if (now - lastSelfReview >= config.daemon.selfReviewInterval * 1e3) {
|
|
200
|
+
await selfReviewCycle();
|
|
201
|
+
lastSelfReview = now;
|
|
202
|
+
}
|
|
203
|
+
await new Promise((r) => setTimeout(r, 3e4));
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
export {
|
|
207
|
+
daemon
|
|
208
|
+
};
|