@askexenow/exe-os 0.8.80 → 0.8.82
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/bin/backfill-conversations.js +359 -267
- package/dist/bin/backfill-responses.js +357 -265
- package/dist/bin/backfill-vectors.js +339 -264
- package/dist/bin/cleanup-stale-review-tasks.js +315 -256
- package/dist/bin/cli.js +494 -240
- package/dist/bin/exe-agent.js +141 -46
- package/dist/bin/exe-assign.js +151 -63
- package/dist/bin/exe-boot.js +294 -115
- package/dist/bin/exe-call.js +76 -51
- package/dist/bin/exe-cloud.js +58 -45
- package/dist/bin/exe-dispatch.js +434 -277
- package/dist/bin/exe-doctor.js +317 -246
- package/dist/bin/exe-export-behaviors.js +328 -248
- package/dist/bin/exe-forget.js +314 -231
- package/dist/bin/exe-gateway.js +2676 -1402
- package/dist/bin/exe-heartbeat.js +329 -264
- package/dist/bin/exe-kill.js +324 -244
- package/dist/bin/exe-launch-agent.js +574 -463
- package/dist/bin/exe-link.js +1055 -95
- package/dist/bin/exe-new-employee.js +49 -54
- package/dist/bin/exe-pending-messages.js +310 -253
- package/dist/bin/exe-pending-notifications.js +299 -228
- package/dist/bin/exe-pending-reviews.js +314 -245
- package/dist/bin/exe-rename.js +259 -195
- package/dist/bin/exe-review.js +140 -64
- package/dist/bin/exe-search.js +543 -356
- package/dist/bin/exe-session-cleanup.js +463 -382
- package/dist/bin/exe-settings.js +129 -99
- package/dist/bin/exe-start.sh +6 -6
- package/dist/bin/exe-status.js +95 -36
- package/dist/bin/exe-team.js +116 -51
- package/dist/bin/git-sweep.js +482 -307
- package/dist/bin/graph-backfill.js +357 -245
- package/dist/bin/graph-export.js +324 -244
- package/dist/bin/install.js +33 -10
- package/dist/bin/scan-tasks.js +481 -307
- package/dist/bin/setup.js +1147 -140
- package/dist/bin/shard-migrate.js +321 -241
- package/dist/bin/update.js +1 -7
- package/dist/bin/wiki-sync.js +318 -238
- package/dist/gateway/index.js +2656 -1383
- package/dist/hooks/bug-report-worker.js +641 -472
- package/dist/hooks/commit-complete.js +482 -307
- package/dist/hooks/error-recall.js +363 -135
- package/dist/hooks/exe-heartbeat-hook.js +97 -27
- package/dist/hooks/ingest-worker.js +584 -397
- package/dist/hooks/ingest.js +123 -58
- package/dist/hooks/instructions-loaded.js +212 -82
- package/dist/hooks/notification.js +200 -70
- package/dist/hooks/post-compact.js +199 -81
- package/dist/hooks/pre-compact.js +352 -140
- package/dist/hooks/pre-tool-use.js +416 -278
- package/dist/hooks/prompt-ingest-worker.js +376 -299
- package/dist/hooks/prompt-submit.js +414 -188
- package/dist/hooks/response-ingest-worker.js +408 -338
- package/dist/hooks/session-end.js +209 -83
- package/dist/hooks/session-start.js +382 -158
- package/dist/hooks/stop.js +209 -83
- package/dist/hooks/subagent-stop.js +209 -85
- package/dist/hooks/summary-worker.js +606 -510
- package/dist/index.js +2133 -855
- package/dist/lib/cloud-sync.js +1175 -184
- package/dist/lib/config.js +1 -9
- package/dist/lib/consolidation.js +71 -34
- package/dist/lib/database.js +166 -14
- package/dist/lib/device-registry.js +189 -117
- package/dist/lib/embedder.js +6 -10
- package/dist/lib/employee-templates.js +134 -39
- package/dist/lib/employees.js +30 -7
- package/dist/lib/exe-daemon-client.js +5 -7
- package/dist/lib/exe-daemon.js +514 -152
- package/dist/lib/hybrid-search.js +543 -356
- package/dist/lib/identity-templates.js +15 -15
- package/dist/lib/identity.js +19 -15
- package/dist/lib/license.js +1 -7
- package/dist/lib/messaging.js +157 -135
- package/dist/lib/reminders.js +97 -0
- package/dist/lib/schedules.js +302 -231
- package/dist/lib/skill-learning.js +33 -27
- package/dist/lib/status-brief.js +11 -14
- package/dist/lib/store.js +326 -237
- package/dist/lib/task-router.js +105 -1
- package/dist/lib/tasks.js +233 -116
- package/dist/lib/tmux-routing.js +173 -56
- package/dist/lib/ws-client.js +13 -3
- package/dist/mcp/server.js +2009 -1015
- package/dist/mcp/tools/complete-reminder.js +97 -0
- package/dist/mcp/tools/create-reminder.js +97 -0
- package/dist/mcp/tools/create-task.js +426 -262
- package/dist/mcp/tools/deactivate-behavior.js +119 -44
- package/dist/mcp/tools/list-reminders.js +97 -0
- package/dist/mcp/tools/list-tasks.js +56 -57
- package/dist/mcp/tools/send-message.js +206 -143
- package/dist/mcp/tools/update-task.js +259 -85
- package/dist/runtime/index.js +495 -316
- package/dist/tui/App.js +1128 -919
- package/package.json +2 -10
- package/src/commands/exe/afk.md +8 -8
- package/src/commands/exe/assign.md +1 -1
- package/src/commands/exe/build-adv.md +1 -1
- package/src/commands/exe/call.md +10 -10
- package/src/commands/exe/employee-heartbeat.md +9 -6
- package/src/commands/exe/heartbeat.md +5 -5
- package/src/commands/exe/intercom.md +26 -15
- package/src/commands/exe/launch.md +2 -2
- package/src/commands/exe/new-employee.md +1 -1
- package/src/commands/exe/review.md +2 -2
- package/src/commands/exe/schedule.md +1 -1
- package/src/commands/exe/sessions.md +2 -2
- package/src/commands/exe.md +22 -20
package/dist/bin/exe-agent.js
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
// src/bin/exe-agent.ts
|
|
4
4
|
import { createInterface } from "readline";
|
|
5
|
-
import { readFileSync } from "fs";
|
|
6
|
-
import
|
|
7
|
-
import
|
|
5
|
+
import { readFileSync as readFileSync3 } from "fs";
|
|
6
|
+
import path9 from "path";
|
|
7
|
+
import os4 from "os";
|
|
8
8
|
|
|
9
9
|
// src/runtime/external-agent-mode.ts
|
|
10
10
|
var HARD_BLOCKED_TOOLS = /* @__PURE__ */ new Set([
|
|
@@ -1150,6 +1150,101 @@ import { randomUUID as randomUUID3 } from "crypto";
|
|
|
1150
1150
|
// src/lib/database.ts
|
|
1151
1151
|
import { createClient } from "@libsql/client";
|
|
1152
1152
|
|
|
1153
|
+
// src/lib/employees.ts
|
|
1154
|
+
import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
|
|
1155
|
+
import { existsSync as existsSync2, symlinkSync, readlinkSync, readFileSync as readFileSync2, renameSync as renameSync2, unlinkSync, writeFileSync } from "fs";
|
|
1156
|
+
import { execSync } from "child_process";
|
|
1157
|
+
import path2 from "path";
|
|
1158
|
+
import os2 from "os";
|
|
1159
|
+
|
|
1160
|
+
// src/lib/config.ts
|
|
1161
|
+
import { readFile, writeFile, mkdir, chmod } from "fs/promises";
|
|
1162
|
+
import { readFileSync, existsSync, renameSync } from "fs";
|
|
1163
|
+
import path from "path";
|
|
1164
|
+
import os from "os";
|
|
1165
|
+
function resolveDataDir() {
|
|
1166
|
+
if (process.env.EXE_OS_DIR) return process.env.EXE_OS_DIR;
|
|
1167
|
+
if (process.env.EXE_MEM_DIR) return process.env.EXE_MEM_DIR;
|
|
1168
|
+
const newDir = path.join(os.homedir(), ".exe-os");
|
|
1169
|
+
const legacyDir = path.join(os.homedir(), ".exe-mem");
|
|
1170
|
+
if (!existsSync(newDir) && existsSync(legacyDir)) {
|
|
1171
|
+
try {
|
|
1172
|
+
renameSync(legacyDir, newDir);
|
|
1173
|
+
process.stderr.write(`[exe-os] Migrated data directory: ~/.exe-mem \u2192 ~/.exe-os
|
|
1174
|
+
`);
|
|
1175
|
+
} catch {
|
|
1176
|
+
return legacyDir;
|
|
1177
|
+
}
|
|
1178
|
+
}
|
|
1179
|
+
return newDir;
|
|
1180
|
+
}
|
|
1181
|
+
var EXE_AI_DIR = resolveDataDir();
|
|
1182
|
+
var DB_PATH = path.join(EXE_AI_DIR, "memories.db");
|
|
1183
|
+
var MODELS_DIR = path.join(EXE_AI_DIR, "models");
|
|
1184
|
+
var CONFIG_PATH = path.join(EXE_AI_DIR, "config.json");
|
|
1185
|
+
var LEGACY_LANCE_PATH = path.join(EXE_AI_DIR, "local.lance");
|
|
1186
|
+
var CURRENT_CONFIG_VERSION = 1;
|
|
1187
|
+
var DEFAULT_CONFIG = {
|
|
1188
|
+
config_version: CURRENT_CONFIG_VERSION,
|
|
1189
|
+
dbPath: DB_PATH,
|
|
1190
|
+
modelFile: "jina-embeddings-v5-small-q4_k_m.gguf",
|
|
1191
|
+
embeddingDim: 1024,
|
|
1192
|
+
batchSize: 20,
|
|
1193
|
+
flushIntervalMs: 1e4,
|
|
1194
|
+
autoIngestion: true,
|
|
1195
|
+
autoRetrieval: true,
|
|
1196
|
+
searchMode: "hybrid",
|
|
1197
|
+
hookSearchMode: "hybrid",
|
|
1198
|
+
fileGrepEnabled: true,
|
|
1199
|
+
splashEffect: true,
|
|
1200
|
+
consolidationEnabled: true,
|
|
1201
|
+
consolidationIntervalMs: 6 * 60 * 60 * 1e3,
|
|
1202
|
+
consolidationModel: "claude-haiku-4-5-20251001",
|
|
1203
|
+
consolidationMaxCallsPerRun: 20,
|
|
1204
|
+
selfQueryRouter: true,
|
|
1205
|
+
selfQueryModel: "claude-haiku-4-5-20251001",
|
|
1206
|
+
rerankerEnabled: true,
|
|
1207
|
+
scalingRoadmap: {
|
|
1208
|
+
rerankerAutoTrigger: {
|
|
1209
|
+
enabled: true,
|
|
1210
|
+
broadQueryMinCardinality: 5e4,
|
|
1211
|
+
fetchTopK: 150,
|
|
1212
|
+
returnTopK: 5
|
|
1213
|
+
}
|
|
1214
|
+
},
|
|
1215
|
+
graphRagEnabled: true,
|
|
1216
|
+
wikiEnabled: false,
|
|
1217
|
+
wikiUrl: "",
|
|
1218
|
+
wikiApiKey: "",
|
|
1219
|
+
wikiSyncIntervalMs: 30 * 60 * 1e3,
|
|
1220
|
+
wikiWorkspaceMapping: {},
|
|
1221
|
+
wikiAutoUpdate: true,
|
|
1222
|
+
wikiAutoUpdateThreshold: 0.5,
|
|
1223
|
+
wikiAutoUpdateCreateNew: true,
|
|
1224
|
+
skillLearning: true,
|
|
1225
|
+
skillThreshold: 3,
|
|
1226
|
+
skillModel: "claude-haiku-4-5-20251001",
|
|
1227
|
+
exeHeartbeat: {
|
|
1228
|
+
enabled: true,
|
|
1229
|
+
intervalSeconds: 60,
|
|
1230
|
+
staleInProgressThresholdHours: 2
|
|
1231
|
+
},
|
|
1232
|
+
sessionLifecycle: {
|
|
1233
|
+
idleKillEnabled: true,
|
|
1234
|
+
idleKillTicksRequired: 3,
|
|
1235
|
+
idleKillIntercomAckWindowMs: 1e4,
|
|
1236
|
+
maxAutoInstances: 10
|
|
1237
|
+
},
|
|
1238
|
+
autoUpdate: {
|
|
1239
|
+
checkOnBoot: true,
|
|
1240
|
+
autoInstall: false,
|
|
1241
|
+
checkIntervalMs: 24 * 60 * 60 * 1e3
|
|
1242
|
+
}
|
|
1243
|
+
};
|
|
1244
|
+
|
|
1245
|
+
// src/lib/employees.ts
|
|
1246
|
+
var EMPLOYEES_PATH = path2.join(EXE_AI_DIR, "exe-employees.json");
|
|
1247
|
+
|
|
1153
1248
|
// src/lib/platform-procedures.ts
|
|
1154
1249
|
var PLATFORM_PROCEDURES = [
|
|
1155
1250
|
// --- Foundation: what is exe-os ---
|
|
@@ -1157,26 +1252,26 @@ var PLATFORM_PROCEDURES = [
|
|
|
1157
1252
|
title: "What is exe-os \u2014 the operating model every agent must understand",
|
|
1158
1253
|
domain: "architecture",
|
|
1159
1254
|
priority: "p0",
|
|
1160
|
-
content: "Exe OS is an AI employee operating system. A founder runs 5-10 AI agents as a real org: COO
|
|
1255
|
+
content: "Exe OS is an AI employee operating system. A founder runs 5-10 AI agents as a real org: COO, CTO, CMO, engineers, and content production specialists. Each agent has identity, expertise, and experience layers \u2014 persistent memory that makes them better over time. All data is local-first, E2EE, owned by the user. The MCP server is the ONLY data interface \u2014 never access the DB directly."
|
|
1161
1256
|
},
|
|
1162
1257
|
{
|
|
1163
1258
|
title: "Mode 1 \u2014 how exe-os runs inside Claude Code",
|
|
1164
1259
|
domain: "architecture",
|
|
1165
1260
|
priority: "p0",
|
|
1166
|
-
content: "Mode 1: exe-os runs AS hooks + MCP + skills inside Claude Code. The founder opens CC
|
|
1261
|
+
content: "Mode 1: exe-os runs AS hooks + MCP + skills inside Claude Code. The founder opens CC and boots the COO. The COO manages employees in tmux sessions. Each coordinator session is a separate CC window/project. Employees run in their own tmux panes via create_task auto-spawn. The founder talks to the COO; the COO orchestrates the team. CC is the shell, exe-os is the brain."
|
|
1167
1262
|
},
|
|
1168
1263
|
{
|
|
1169
|
-
title: "Sessions explained \u2014
|
|
1264
|
+
title: "Sessions explained \u2014 coordinator session names and projects",
|
|
1170
1265
|
domain: "architecture",
|
|
1171
1266
|
priority: "p0",
|
|
1172
|
-
content: "Each
|
|
1267
|
+
content: "Each coordinator session is an isolated project session. One might be exe-os development, another might be exe-wiki. Each session spawns its own employees using {employee}-{coordinatorSession}. Sessions share the same memory DB but tasks are scoped to the session that created them. A founder can run multiple projects simultaneously. Sessions never interfere with each other."
|
|
1173
1268
|
},
|
|
1174
1269
|
// --- Hierarchy and dispatch ---
|
|
1175
1270
|
{
|
|
1176
1271
|
title: "Chain of command \u2014 who talks to whom",
|
|
1177
1272
|
domain: "workflow",
|
|
1178
1273
|
priority: "p0",
|
|
1179
|
-
content: "Founder
|
|
1274
|
+
content: "Founder -> COO -> CTO/CMO. CTO -> engineers. CMO -> content production. Never skip levels: the COO does not bypass managers for specialist work. Specialists report to their manager. If you need cross-team info, use ask_team_memory \u2014 don't read other agents' task folders. Each level owns dispatch downward and review upward."
|
|
1180
1275
|
},
|
|
1181
1276
|
{
|
|
1182
1277
|
title: "Single dispatch path \u2014 create_task only",
|
|
@@ -1186,30 +1281,30 @@ var PLATFORM_PROCEDURES = [
|
|
|
1186
1281
|
},
|
|
1187
1282
|
// --- Session isolation ---
|
|
1188
1283
|
{
|
|
1189
|
-
title: "Session scoping \u2014 stay in your
|
|
1284
|
+
title: "Session scoping \u2014 stay in your coordinator boundary",
|
|
1190
1285
|
domain: "security",
|
|
1191
1286
|
priority: "p0",
|
|
1192
|
-
content: "Session scoping is mandatory. Managers dispatch to workers within their own
|
|
1287
|
+
content: "Session scoping is mandatory. Managers dispatch to workers within their own coordinator session ONLY. Employee sessions use {employee}-{coordinatorSession}. Cross-session dispatch is blocked by the system. Verify session names before dispatch. Tasks are scoped to the creating coordinator session."
|
|
1193
1288
|
},
|
|
1194
1289
|
{
|
|
1195
1290
|
title: "Session isolation \u2014 never touch another session's work",
|
|
1196
1291
|
domain: "workflow",
|
|
1197
1292
|
priority: "p0",
|
|
1198
|
-
content:
|
|
1293
|
+
content: "Sessions are isolated. A coordinator session owns ONLY tasks it dispatched. (1) Never close/update/cancel tasks from another coordinator session. (2) Never review work from a different session \u2014 report that it belongs to another session and skip. (3) Ignore other sessions' items in list_tasks results. (4) Employees inherit session: employee sessions work ONLY on their parent coordinator session's tasks. Cross-session work is a system violation."
|
|
1199
1294
|
},
|
|
1200
1295
|
// --- Engineering: session scoping in code ---
|
|
1201
1296
|
{
|
|
1202
1297
|
title: "Three-dimensional scoping \u2014 session, project, role \u2014 enforced in every query",
|
|
1203
1298
|
domain: "architecture",
|
|
1204
1299
|
priority: "p0",
|
|
1205
|
-
content: "Every DB query, notification, review count, and task operation MUST be scoped on 3 dimensions: (1) Session \u2014 filter by session_scope matching current
|
|
1300
|
+
content: "Every DB query, notification, review count, and task operation MUST be scoped on 3 dimensions: (1) Session \u2014 filter by session_scope matching the current coordinator session. (2) Project \u2014 filter by project_name. (3) Role \u2014 agents only see data at their hierarchy level. When writing ANY function that touches tasks, reviews, messages, or notifications: always accept a sessionScope parameter and pass it to the SQL WHERE clause. Unscoped queries are bugs. Test by running 2+ coordinator sessions simultaneously."
|
|
1206
1301
|
},
|
|
1207
1302
|
// --- Hard constraints ---
|
|
1208
1303
|
{
|
|
1209
1304
|
title: "What you CANNOT do in exe-os \u2014 hard constraints",
|
|
1210
1305
|
domain: "security",
|
|
1211
1306
|
priority: "p0",
|
|
1212
|
-
content: "NEVER: (1) Access the database directly \u2014 it's SQLCipher encrypted, always fails. Use MCP tools only. (2) Manually spawn tmux sessions \u2014 create_task handles it. (3) Run git checkout main \u2014 agents work in worktrees. (4) Modify another agent's in-progress task. (5) Push to remote \u2014
|
|
1307
|
+
content: "NEVER: (1) Access the database directly \u2014 it's SQLCipher encrypted, always fails. Use MCP tools only. (2) Manually spawn tmux sessions \u2014 create_task handles it. (3) Run git checkout main \u2014 agents work in worktrees. (4) Modify another agent's in-progress task. (5) Push to remote \u2014 the COO reviews and pushes. (6) Skip update_task(done) \u2014 it's the ONLY way your work gets reviewed. (7) Run git init."
|
|
1213
1308
|
},
|
|
1214
1309
|
// --- Operations ---
|
|
1215
1310
|
{
|
|
@@ -1297,13 +1392,13 @@ Ethos:
|
|
|
1297
1392
|
- Founder zero-ego. Distributors and customers are the loudest voice.
|
|
1298
1393
|
- Crypto values: big companies should not own consumer/SMB AI.
|
|
1299
1394
|
|
|
1300
|
-
STOP AND REDIRECT: Any decision that compromises memory sovereignty, 3-layer cognition, MCP boundary, or AGPL boundary kills all three business paths. Surface the conflict to
|
|
1395
|
+
STOP AND REDIRECT: Any decision that compromises memory sovereignty, 3-layer cognition, MCP boundary, or AGPL boundary kills all three business paths. Surface the conflict to the COO before proceeding.
|
|
1301
1396
|
|
|
1302
1397
|
Always reference .planning/ARCHITECTURE.md and .planning/PROJECT.md as source of truth for all architectural and product decisions.
|
|
1303
1398
|
|
|
1304
1399
|
OPERATING PROCEDURES (mandatory for all employees):
|
|
1305
1400
|
|
|
1306
|
-
You report to the COO. All work flows through
|
|
1401
|
+
You report to the COO. All work flows through the COO. These procedures are non-negotiable.
|
|
1307
1402
|
|
|
1308
1403
|
1. BEFORE starting work:
|
|
1309
1404
|
- Read exe/ARCHITECTURE.md (if it exists). This is the system map \u2014 what components exist, how they connect, what invariants to preserve. Understand the architecture before changing anything.
|
|
@@ -1328,15 +1423,15 @@ You report to the COO. All work flows through exe. These procedures are non-nego
|
|
|
1328
1423
|
- Include what was done, decisions made, and any issues
|
|
1329
1424
|
- If you're stuck, looping, confused, or running low on context \u2014 update_task(done) with whatever partial result you have. A partial result is infinitely better than no result.
|
|
1330
1425
|
- NEVER let a failed commit, a loop, or an error prevent you from calling update_task(done).
|
|
1331
|
-
- Do NOT use close_task \u2014 that is reserved for reviewers
|
|
1426
|
+
- Do NOT use close_task \u2014 that is reserved for reviewers to finalize after review.
|
|
1332
1427
|
|
|
1333
1428
|
4. AFTER update_task(done) \u2014 COMMIT (best-effort, do NOT let this block):
|
|
1334
1429
|
- If your task changed system structure, update exe/ARCHITECTURE.md first.
|
|
1335
1430
|
- Commit IF you are in a git repo (check: \`git rev-parse --git-dir 2>/dev/null\`). Stage only the files you changed, write a clear commit message.
|
|
1336
1431
|
- If you are NOT in a git repo, skip entirely. NEVER run \`git init\`.
|
|
1337
1432
|
- If the commit fails, note it but move on \u2014 the work is already marked done via update_task.
|
|
1338
|
-
- Do NOT push \u2014
|
|
1339
|
-
- NEVER run \`git checkout main\`. You work in your own git worktree on a feature branch.
|
|
1433
|
+
- Do NOT push \u2014 the COO reviews commits and decides what to push.
|
|
1434
|
+
- NEVER run \`git checkout main\`. You work in your own git worktree on a feature branch. The COO stays on main and merges PRs. Switching branches in a shared repo stomps other agents' work.
|
|
1340
1435
|
|
|
1341
1436
|
5. AFTER commit \u2014 REPORT (best-effort):
|
|
1342
1437
|
Use store_memory to write a structured summary. Include: project name, what was done,
|
|
@@ -1350,7 +1445,7 @@ You report to the COO. All work flows through exe. These procedures are non-nego
|
|
|
1350
1445
|
|
|
1351
1446
|
7. AFTER reporting \u2014 CHECK FOR NEXT WORK (mandatory):
|
|
1352
1447
|
- First: run list_tasks(status='needs_review') \u2014 check if YOU are the reviewer on any pending reviews. Reviews are work. Process them before anything else.
|
|
1353
|
-
- Second: run list_tasks(status='blocked') \u2014 check if any tasks are blocked. For each blocked task: can YOU unblock it? If yes, unblock it now. If not, escalate to
|
|
1448
|
+
- Second: run list_tasks(status='blocked') \u2014 check if any tasks are blocked. For each blocked task: can YOU unblock it? If yes, unblock it now. If not, escalate to the COO immediately. Blocked tasks sitting >24h without action is a pipeline failure.
|
|
1354
1449
|
- Then: re-read your task folder: exe/<your-name>/
|
|
1355
1450
|
- If there are more open tasks, start the next highest-priority one (go to step 1)
|
|
1356
1451
|
- If no more open tasks AND no pending reviews AND no blocked tasks you can fix, tell the user: "All tasks complete. Anything else?"
|
|
@@ -1367,7 +1462,7 @@ DO NOT keep working degraded. Instead:
|
|
|
1367
1462
|
Format the text as: "CONTEXT CHECKPOINT [<task-id>]: <summary>"
|
|
1368
1463
|
Include: task ID + title, what you completed, what's left, open decisions or blockers, key file paths.
|
|
1369
1464
|
|
|
1370
|
-
2. Send intercom to
|
|
1465
|
+
2. Send intercom to the COO session to trigger kill + relaunch:
|
|
1371
1466
|
MY_SESSION=$(tmux display-message -p '#{session_name}' 2>/dev/null)
|
|
1372
1467
|
EXE_SESSION="\${MY_SESSION#\${AGENT_ID}-}"
|
|
1373
1468
|
tmux send-keys -t "$EXE_SESSION" "/exe-intercom context-full: \${AGENT_ID} hit capacity. Checkpoint saved. Resume task <task-id>." Enter
|
|
@@ -1375,8 +1470,8 @@ DO NOT keep working degraded. Instead:
|
|
|
1375
1470
|
3. Stop working immediately. Do not attempt to continue with degraded context.
|
|
1376
1471
|
|
|
1377
1472
|
COMMUNICATION CHAIN \u2014 who you talk to:
|
|
1378
|
-
- You report to the COO. Your completion reports, status updates, and questions go to
|
|
1379
|
-
- Do NOT address the human user directly for decisions, permissions, or status updates. That's
|
|
1473
|
+
- You report to the COO. Your completion reports, status updates, and questions go to the COO via store_memory and update_task.
|
|
1474
|
+
- Do NOT address the human user directly for decisions, permissions, or status updates. That's the COO's job. The user talks to the COO; the COO talks to you.
|
|
1380
1475
|
- Exception: if the user sends you a direct message in your tmux window, respond to them. But default to reporting through exe.
|
|
1381
1476
|
|
|
1382
1477
|
SKILL CAPTURE (encouraged, not mandatory):
|
|
@@ -1598,13 +1693,13 @@ var BashTool = {
|
|
|
1598
1693
|
|
|
1599
1694
|
// src/runtime/tools/file-read.ts
|
|
1600
1695
|
import fs from "fs/promises";
|
|
1601
|
-
import
|
|
1696
|
+
import path4 from "path";
|
|
1602
1697
|
import { z as z2 } from "zod";
|
|
1603
1698
|
|
|
1604
1699
|
// src/runtime/safety-checks.ts
|
|
1605
|
-
import
|
|
1606
|
-
import
|
|
1607
|
-
var HOME =
|
|
1700
|
+
import path3 from "path";
|
|
1701
|
+
import os3 from "os";
|
|
1702
|
+
var HOME = os3.homedir();
|
|
1608
1703
|
var BYPASS_IMMUNE_PATTERNS = [
|
|
1609
1704
|
{
|
|
1610
1705
|
pattern: /\/\.git\/hooks\//,
|
|
@@ -1615,11 +1710,11 @@ var BYPASS_IMMUNE_PATTERNS = [
|
|
|
1615
1710
|
reason: "Git config can set hooks and command execution"
|
|
1616
1711
|
},
|
|
1617
1712
|
{
|
|
1618
|
-
pattern: (p) => p.startsWith(
|
|
1713
|
+
pattern: (p) => p.startsWith(path3.join(HOME, ".claude")),
|
|
1619
1714
|
reason: "Claude configuration files are protected"
|
|
1620
1715
|
},
|
|
1621
1716
|
{
|
|
1622
|
-
pattern: (p) => p.startsWith(
|
|
1717
|
+
pattern: (p) => p.startsWith(path3.join(HOME, ".exe-os")),
|
|
1623
1718
|
reason: "exe-os configuration files are protected"
|
|
1624
1719
|
},
|
|
1625
1720
|
{
|
|
@@ -1636,7 +1731,7 @@ var BYPASS_IMMUNE_PATTERNS = [
|
|
|
1636
1731
|
},
|
|
1637
1732
|
{
|
|
1638
1733
|
pattern: (p) => {
|
|
1639
|
-
const name =
|
|
1734
|
+
const name = path3.basename(p);
|
|
1640
1735
|
return [".bashrc", ".zshrc", ".profile", ".bash_profile", ".zprofile", ".zshenv"].includes(name);
|
|
1641
1736
|
},
|
|
1642
1737
|
reason: "Shell configuration files can execute arbitrary code on login"
|
|
@@ -1655,7 +1750,7 @@ var BYPASS_IMMUNE_PATTERNS = [
|
|
|
1655
1750
|
}
|
|
1656
1751
|
];
|
|
1657
1752
|
function checkPathSafety(filePath) {
|
|
1658
|
-
const resolved =
|
|
1753
|
+
const resolved = path3.resolve(filePath);
|
|
1659
1754
|
for (const { pattern, reason } of BYPASS_IMMUNE_PATTERNS) {
|
|
1660
1755
|
const matches = typeof pattern === "function" ? pattern(resolved) : pattern.test(resolved);
|
|
1661
1756
|
if (matches) {
|
|
@@ -1665,7 +1760,7 @@ function checkPathSafety(filePath) {
|
|
|
1665
1760
|
return { safe: true, bypassImmune: true };
|
|
1666
1761
|
}
|
|
1667
1762
|
function checkReadPathSafety(filePath) {
|
|
1668
|
-
const resolved =
|
|
1763
|
+
const resolved = path3.resolve(filePath);
|
|
1669
1764
|
const credPatterns = BYPASS_IMMUNE_PATTERNS.filter(
|
|
1670
1765
|
(p) => typeof p.pattern !== "function" && (p.reason.includes("secrets") || p.reason.includes("Private key") || p.reason.includes("Credential"))
|
|
1671
1766
|
);
|
|
@@ -1701,7 +1796,7 @@ var FileReadTool = {
|
|
|
1701
1796
|
return { behavior: "allow" };
|
|
1702
1797
|
},
|
|
1703
1798
|
async call(input, context) {
|
|
1704
|
-
const filePath =
|
|
1799
|
+
const filePath = path4.isAbsolute(input.file_path) ? input.file_path : path4.resolve(context.cwd, input.file_path);
|
|
1705
1800
|
let stat;
|
|
1706
1801
|
try {
|
|
1707
1802
|
stat = await fs.stat(filePath);
|
|
@@ -1741,7 +1836,7 @@ function isBinary(buf) {
|
|
|
1741
1836
|
|
|
1742
1837
|
// src/runtime/tools/file-edit.ts
|
|
1743
1838
|
import fs2 from "fs/promises";
|
|
1744
|
-
import
|
|
1839
|
+
import path5 from "path";
|
|
1745
1840
|
import { z as z3 } from "zod";
|
|
1746
1841
|
var inputSchema3 = z3.object({
|
|
1747
1842
|
file_path: z3.string(),
|
|
@@ -1766,7 +1861,7 @@ var FileEditTool = {
|
|
|
1766
1861
|
return { behavior: "allow" };
|
|
1767
1862
|
},
|
|
1768
1863
|
async call(input, context) {
|
|
1769
|
-
const filePath =
|
|
1864
|
+
const filePath = path5.isAbsolute(input.file_path) ? input.file_path : path5.resolve(context.cwd, input.file_path);
|
|
1770
1865
|
let content;
|
|
1771
1866
|
try {
|
|
1772
1867
|
content = await fs2.readFile(filePath, "utf-8");
|
|
@@ -1815,7 +1910,7 @@ function countOccurrences(haystack, needle) {
|
|
|
1815
1910
|
|
|
1816
1911
|
// src/runtime/tools/file-write.ts
|
|
1817
1912
|
import fs3 from "fs/promises";
|
|
1818
|
-
import
|
|
1913
|
+
import path6 from "path";
|
|
1819
1914
|
import { z as z4 } from "zod";
|
|
1820
1915
|
var inputSchema4 = z4.object({
|
|
1821
1916
|
file_path: z4.string(),
|
|
@@ -1838,8 +1933,8 @@ var FileWriteTool = {
|
|
|
1838
1933
|
return { behavior: "allow" };
|
|
1839
1934
|
},
|
|
1840
1935
|
async call(input, context) {
|
|
1841
|
-
const filePath =
|
|
1842
|
-
const dir =
|
|
1936
|
+
const filePath = path6.isAbsolute(input.file_path) ? input.file_path : path6.resolve(context.cwd, input.file_path);
|
|
1937
|
+
const dir = path6.dirname(filePath);
|
|
1843
1938
|
await fs3.mkdir(dir, { recursive: true });
|
|
1844
1939
|
await fs3.writeFile(filePath, input.content, "utf-8");
|
|
1845
1940
|
return {
|
|
@@ -1851,7 +1946,7 @@ var FileWriteTool = {
|
|
|
1851
1946
|
|
|
1852
1947
|
// src/runtime/tools/glob.ts
|
|
1853
1948
|
import fs4 from "fs/promises";
|
|
1854
|
-
import
|
|
1949
|
+
import path7 from "path";
|
|
1855
1950
|
import { z as z5 } from "zod";
|
|
1856
1951
|
var inputSchema5 = z5.object({
|
|
1857
1952
|
pattern: z5.string(),
|
|
@@ -1863,11 +1958,11 @@ var GlobTool = {
|
|
|
1863
1958
|
inputSchema: inputSchema5,
|
|
1864
1959
|
isReadOnly: true,
|
|
1865
1960
|
async call(input, context) {
|
|
1866
|
-
const baseDir = input.path ?
|
|
1961
|
+
const baseDir = input.path ? path7.isAbsolute(input.path) ? input.path : path7.resolve(context.cwd, input.path) : context.cwd;
|
|
1867
1962
|
try {
|
|
1868
1963
|
const entries = await walkDir(baseDir);
|
|
1869
1964
|
const matched = entries.filter(
|
|
1870
|
-
(e) => simpleGlobMatch(
|
|
1965
|
+
(e) => simpleGlobMatch(path7.relative(baseDir, e.path), input.pattern)
|
|
1871
1966
|
);
|
|
1872
1967
|
matched.sort((a, b) => b.mtime - a.mtime);
|
|
1873
1968
|
if (matched.length === 0) {
|
|
@@ -1897,7 +1992,7 @@ async function walkDir(dir, maxDepth = 10) {
|
|
|
1897
1992
|
if (entry.isDirectory() && (entry.name === "node_modules" || entry.name === ".git")) {
|
|
1898
1993
|
continue;
|
|
1899
1994
|
}
|
|
1900
|
-
const fullPath =
|
|
1995
|
+
const fullPath = path7.join(current, entry.name);
|
|
1901
1996
|
if (entry.isDirectory()) {
|
|
1902
1997
|
await walk(fullPath, depth + 1);
|
|
1903
1998
|
} else {
|
|
@@ -1921,7 +2016,7 @@ function simpleGlobMatch(filePath, pattern) {
|
|
|
1921
2016
|
// src/runtime/tools/grep.ts
|
|
1922
2017
|
import { spawn as spawn2 } from "child_process";
|
|
1923
2018
|
import fs5 from "fs/promises";
|
|
1924
|
-
import
|
|
2019
|
+
import path8 from "path";
|
|
1925
2020
|
import { z as z6 } from "zod";
|
|
1926
2021
|
var inputSchema6 = z6.object({
|
|
1927
2022
|
pattern: z6.string(),
|
|
@@ -1935,7 +2030,7 @@ var GrepTool = {
|
|
|
1935
2030
|
inputSchema: inputSchema6,
|
|
1936
2031
|
isReadOnly: true,
|
|
1937
2032
|
async call(input, context) {
|
|
1938
|
-
const searchPath = input.path ?
|
|
2033
|
+
const searchPath = input.path ? path8.isAbsolute(input.path) ? input.path : path8.resolve(context.cwd, input.path) : context.cwd;
|
|
1939
2034
|
try {
|
|
1940
2035
|
const result = await runRipgrep(input, searchPath, context);
|
|
1941
2036
|
return result;
|
|
@@ -2003,7 +2098,7 @@ async function nodeGrep(input, searchPath) {
|
|
|
2003
2098
|
}
|
|
2004
2099
|
for (const entry of entries) {
|
|
2005
2100
|
if (entry.name === "node_modules" || entry.name === ".git") continue;
|
|
2006
|
-
const fullPath =
|
|
2101
|
+
const fullPath = path8.join(dir, entry.name);
|
|
2007
2102
|
if (entry.isDirectory()) {
|
|
2008
2103
|
await walk(fullPath);
|
|
2009
2104
|
} else {
|
|
@@ -2050,8 +2145,8 @@ function parseArgs(argv) {
|
|
|
2050
2145
|
}
|
|
2051
2146
|
function loadEmployee(name) {
|
|
2052
2147
|
try {
|
|
2053
|
-
const rosterPath =
|
|
2054
|
-
const roster = JSON.parse(
|
|
2148
|
+
const rosterPath = path9.join(os4.homedir(), ".exe-os", "exe-employees.json");
|
|
2149
|
+
const roster = JSON.parse(readFileSync3(rosterPath, "utf8"));
|
|
2055
2150
|
return roster.find((e) => e.name.toLowerCase() === name.toLowerCase()) ?? null;
|
|
2056
2151
|
} catch {
|
|
2057
2152
|
return null;
|