@askexenow/exe-os 0.8.26 → 0.8.28

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/cli.js CHANGED
@@ -4524,9 +4524,19 @@ You are \${agent_id}. COO \u2014 the founder's most reliable teammate in busines
4524
4524
  - Pattern recognition: surface recurring problems, connect dots across projects
4525
4525
  - Architecture guardian (strategic): verify all work aligns with the PRODUCT VISION and five-mode architecture in .planning/ARCHITECTURE.md. Is this the right feature at the right time? Does it match the build order?
4526
4526
 
4527
+ ## First Boot \u2014 Memory Onboarding
4528
+
4529
+ On your FIRST conversation (when you have few or no prior interactions with the founder):
4530
+ 1. Run recall_my_memory with broad queries to discover what exists: search for "project", "client", "pipeline", "SEO", "campaign", "product", "deal", "meeting"
4531
+ 2. Summarize what you find: "You've been working on X, Y, Z. Here's what I know about each."
4532
+ 3. If memories exist from a backfill, proactively tell the founder what you learned from their history
4533
+ 4. Ask what's most important right now
4534
+
4535
+ Never say "I have no memories" without first searching broadly. Your memory may contain thousands of entries \u2014 surface them by searching for domain-relevant terms, not meta-queries like "what do I know."
4536
+
4527
4537
  ## Tools
4528
4538
 
4529
- - **recall_my_memory / ask_team_memory** \u2014 stay current on all org context
4539
+ - **recall_my_memory / ask_team_memory** \u2014 stay current on all org context. Search with specific topic keywords, not vague queries.
4530
4540
  - **list_tasks** \u2014 monitor queues across all employees and projects
4531
4541
  - **create_task** \u2014 assign work to specialists with clear specs
4532
4542
  - **update_task / close_task** \u2014 finalize reviews, mark work done
@@ -257,8 +257,8 @@ function shardExists(projectName) {
257
257
  }
258
258
  function listShards() {
259
259
  if (!existsSync3(SHARDS_DIR)) return [];
260
- const { readdirSync: readdirSync3 } = __require("fs");
261
- return readdirSync3(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
260
+ const { readdirSync: readdirSync4 } = __require("fs");
261
+ return readdirSync4(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
262
262
  }
263
263
  async function ensureShardSchema(client) {
264
264
  await client.execute("PRAGMA journal_mode = WAL");
@@ -1129,10 +1129,189 @@ All memory, tasks, behaviors, documents, and wiki content belonging to {{company
1129
1129
  }
1130
1130
  });
1131
1131
 
1132
+ // src/lib/session-key.ts
1133
+ import { execSync as execSync3 } from "child_process";
1134
+ function getSessionKey() {
1135
+ if (_cached) return _cached;
1136
+ let pid = process.ppid;
1137
+ for (let i = 0; i < 10; i++) {
1138
+ try {
1139
+ const info = execSync3(`ps -p ${pid} -o ppid=,comm=`, {
1140
+ encoding: "utf8",
1141
+ timeout: 2e3
1142
+ }).trim();
1143
+ const match = info.match(/^\s*(\d+)\s+(.+)$/);
1144
+ if (!match) break;
1145
+ const [, ppid, cmd] = match;
1146
+ if (cmd === "claude" || cmd.endsWith("/claude")) {
1147
+ _cached = String(pid);
1148
+ return _cached;
1149
+ }
1150
+ pid = parseInt(ppid, 10);
1151
+ if (pid <= 1) break;
1152
+ } catch {
1153
+ break;
1154
+ }
1155
+ }
1156
+ _cached = process.env.CLAUDE_CODE_SSE_PORT ?? String(process.ppid);
1157
+ return _cached;
1158
+ }
1159
+ var _cached;
1160
+ var init_session_key = __esm({
1161
+ "src/lib/session-key.ts"() {
1162
+ "use strict";
1163
+ _cached = null;
1164
+ }
1165
+ });
1166
+
1167
+ // src/adapters/claude/session-key.ts
1168
+ var init_session_key2 = __esm({
1169
+ "src/adapters/claude/session-key.ts"() {
1170
+ "use strict";
1171
+ init_session_key();
1172
+ }
1173
+ });
1174
+
1175
+ // src/adapters/claude/active-agent.ts
1176
+ var active_agent_exports = {};
1177
+ __export(active_agent_exports, {
1178
+ cleanupSessionMarkers: () => cleanupSessionMarkers,
1179
+ clearActiveAgent: () => clearActiveAgent,
1180
+ getActiveAgent: () => getActiveAgent,
1181
+ getAllActiveAgents: () => getAllActiveAgents,
1182
+ writeActiveAgent: () => writeActiveAgent
1183
+ });
1184
+ import { readFileSync as readFileSync2, writeFileSync as writeFileSync2, mkdirSync as mkdirSync3, unlinkSync as unlinkSync2, readdirSync as readdirSync2 } from "fs";
1185
+ import { execSync as execSync4 } from "child_process";
1186
+ import path6 from "path";
1187
+ function getMarkerPath() {
1188
+ return path6.join(CACHE_DIR, `active-agent-${getSessionKey()}.json`);
1189
+ }
1190
+ function writeActiveAgent(agentId, agentRole) {
1191
+ try {
1192
+ mkdirSync3(CACHE_DIR, { recursive: true });
1193
+ writeFileSync2(
1194
+ getMarkerPath(),
1195
+ JSON.stringify({ agentId, agentRole, startedAt: (/* @__PURE__ */ new Date()).toISOString() })
1196
+ );
1197
+ } catch {
1198
+ }
1199
+ }
1200
+ function clearActiveAgent() {
1201
+ try {
1202
+ unlinkSync2(getMarkerPath());
1203
+ } catch {
1204
+ }
1205
+ }
1206
+ function getActiveAgent() {
1207
+ try {
1208
+ const markerPath = getMarkerPath();
1209
+ const raw = readFileSync2(markerPath, "utf8");
1210
+ const data = JSON.parse(raw);
1211
+ if (data.agentId) {
1212
+ if (data.startedAt) {
1213
+ const age = Date.now() - new Date(data.startedAt).getTime();
1214
+ if (age > STALE_MS) {
1215
+ try {
1216
+ unlinkSync2(markerPath);
1217
+ } catch {
1218
+ }
1219
+ } else {
1220
+ return {
1221
+ agentId: data.agentId,
1222
+ agentRole: data.agentRole || "employee"
1223
+ };
1224
+ }
1225
+ } else {
1226
+ return {
1227
+ agentId: data.agentId,
1228
+ agentRole: data.agentRole || "employee"
1229
+ };
1230
+ }
1231
+ }
1232
+ } catch {
1233
+ }
1234
+ try {
1235
+ const sessionName = execSync4(
1236
+ "tmux display-message -p '#{session_name}' 2>/dev/null",
1237
+ { encoding: "utf8", timeout: 2e3 }
1238
+ ).trim();
1239
+ const empMatch = sessionName.match(/^(\w+)-exe\d+$/);
1240
+ if (empMatch && empMatch[1] !== "exe") {
1241
+ return { agentId: empMatch[1], agentRole: "employee" };
1242
+ }
1243
+ if (/^exe\d+$/.test(sessionName)) {
1244
+ return { agentId: "exe", agentRole: "COO" };
1245
+ }
1246
+ } catch {
1247
+ }
1248
+ return {
1249
+ agentId: process.env.AGENT_ID || "default",
1250
+ agentRole: process.env.AGENT_ROLE || "employee"
1251
+ };
1252
+ }
1253
+ function getAllActiveAgents() {
1254
+ try {
1255
+ const files = readdirSync2(CACHE_DIR);
1256
+ const sessions = [];
1257
+ for (const file of files) {
1258
+ if (!file.startsWith("active-agent-") || !file.endsWith(".json")) continue;
1259
+ const key = file.slice("active-agent-".length, -".json".length);
1260
+ if (key === "undefined") continue;
1261
+ try {
1262
+ const raw = readFileSync2(path6.join(CACHE_DIR, file), "utf8");
1263
+ const data = JSON.parse(raw);
1264
+ if (!data.agentId) continue;
1265
+ if (data.startedAt) {
1266
+ const age = Date.now() - new Date(data.startedAt).getTime();
1267
+ if (age > STALE_MS) {
1268
+ try {
1269
+ unlinkSync2(path6.join(CACHE_DIR, file));
1270
+ } catch {
1271
+ }
1272
+ continue;
1273
+ }
1274
+ }
1275
+ sessions.push({
1276
+ agentId: data.agentId,
1277
+ agentRole: data.agentRole || "employee",
1278
+ startedAt: data.startedAt || (/* @__PURE__ */ new Date()).toISOString(),
1279
+ sessionKey: key
1280
+ });
1281
+ } catch {
1282
+ }
1283
+ }
1284
+ return sessions;
1285
+ } catch {
1286
+ return [];
1287
+ }
1288
+ }
1289
+ function cleanupSessionMarkers() {
1290
+ const key = getSessionKey();
1291
+ try {
1292
+ unlinkSync2(path6.join(CACHE_DIR, `active-agent-${key}.json`));
1293
+ } catch {
1294
+ }
1295
+ try {
1296
+ unlinkSync2(path6.join(CACHE_DIR, "active-agent-undefined.json"));
1297
+ } catch {
1298
+ }
1299
+ }
1300
+ var CACHE_DIR, STALE_MS;
1301
+ var init_active_agent = __esm({
1302
+ "src/adapters/claude/active-agent.ts"() {
1303
+ "use strict";
1304
+ init_config();
1305
+ init_session_key2();
1306
+ CACHE_DIR = path6.join(EXE_AI_DIR, "session-cache");
1307
+ STALE_MS = 24 * 60 * 60 * 1e3;
1308
+ }
1309
+ });
1310
+
1132
1311
  // src/bin/exe-launch-agent.ts
1133
1312
  import os3 from "os";
1134
- import path6 from "path";
1135
- import { existsSync as existsSync6, readFileSync as readFileSync2, writeFileSync as writeFileSync2, mkdirSync as mkdirSync3, readdirSync as readdirSync2 } from "fs";
1313
+ import path7 from "path";
1314
+ import { existsSync as existsSync6, readFileSync as readFileSync3, writeFileSync as writeFileSync3, mkdirSync as mkdirSync4, readdirSync as readdirSync3 } from "fs";
1136
1315
  import { spawnSync } from "child_process";
1137
1316
 
1138
1317
  // src/lib/database.ts
@@ -2342,7 +2521,7 @@ function parseBasename(basename) {
2342
2521
  return { agent, provider };
2343
2522
  }
2344
2523
  function resolveAgent(argv) {
2345
- const invokedAs = path6.basename(argv[1] ?? "");
2524
+ const invokedAs = path7.basename(argv[1] ?? "");
2346
2525
  if (invokedAs && invokedAs !== "exe-launch-agent" && !invokedAs.endsWith(".js")) {
2347
2526
  const { agent: agent2, provider } = parseBasename(invokedAs);
2348
2527
  return { agent: agent2, provider, passthrough: argv.slice(2) };
@@ -2368,20 +2547,20 @@ async function isKnownAgent(agent) {
2368
2547
  }
2369
2548
  }
2370
2549
  function identityPathFor(agent) {
2371
- return path6.join(os3.homedir(), ".exe-os", "identity", `${agent}.md`);
2550
+ return path7.join(os3.homedir(), ".exe-os", "identity", `${agent}.md`);
2372
2551
  }
2373
2552
  function leanMcpConfigFor(agent) {
2374
- const p = path6.join(os3.homedir(), ".exe-os", "mcp-configs", `${agent}-lean.json`);
2553
+ const p = path7.join(os3.homedir(), ".exe-os", "mcp-configs", `${agent}-lean.json`);
2375
2554
  return existsSync6(p) ? p : null;
2376
2555
  }
2377
2556
  function buildLaunchPlan(agent, behaviorsPath, passthrough, _hasAgentFlag, _provider) {
2378
2557
  const args = ["--dangerously-skip-permissions"];
2379
2558
  const idPath = identityPathFor(agent);
2380
- const ccAgentPath = path6.join(os3.homedir(), ".claude", "agents", `${agent}.md`);
2559
+ const ccAgentPath = path7.join(os3.homedir(), ".claude", "agents", `${agent}.md`);
2381
2560
  const effectiveIdPath = existsSync6(idPath) ? idPath : existsSync6(ccAgentPath) ? ccAgentPath : null;
2382
2561
  if (effectiveIdPath) {
2383
2562
  try {
2384
- const identity = readFileSync2(effectiveIdPath, "utf-8");
2563
+ const identity = readFileSync3(effectiveIdPath, "utf-8");
2385
2564
  args.push("--system-prompt", identity);
2386
2565
  } catch {
2387
2566
  args.push("--append-system-prompt-file", effectiveIdPath);
@@ -2497,8 +2676,8 @@ async function main() {
2497
2676
  _resetCcAgentSupportCache();
2498
2677
  const hasAgentFlag = claudeSupportsAgentFlag();
2499
2678
  if (hasAgentFlag) {
2500
- const ccAgentDir = path6.join(os3.homedir(), ".claude", "agents");
2501
- const ccAgentFile = path6.join(ccAgentDir, `${agent}.md`);
2679
+ const ccAgentDir = path7.join(os3.homedir(), ".claude", "agents");
2680
+ const ccAgentFile = path7.join(ccAgentDir, `${agent}.md`);
2502
2681
  if (!existsSync6(ccAgentFile)) {
2503
2682
  const exeIdentity = identityPathFor(agent);
2504
2683
  let sourceFile = null;
@@ -2506,19 +2685,19 @@ async function main() {
2506
2685
  sourceFile = exeIdentity;
2507
2686
  } else {
2508
2687
  try {
2509
- const identityDir = path6.dirname(exeIdentity);
2510
- const files = readdirSync2(identityDir);
2688
+ const identityDir = path7.dirname(exeIdentity);
2689
+ const files = readdirSync3(identityDir);
2511
2690
  const match = files.find((f) => f.toLowerCase() === `${agent.toLowerCase()}.md`);
2512
- if (match) sourceFile = path6.join(identityDir, match);
2691
+ if (match) sourceFile = path7.join(identityDir, match);
2513
2692
  } catch {
2514
2693
  }
2515
2694
  }
2516
2695
  if (sourceFile) {
2517
2696
  try {
2518
- mkdirSync3(ccAgentDir, { recursive: true });
2519
- let content = readFileSync2(sourceFile, "utf-8");
2697
+ mkdirSync4(ccAgentDir, { recursive: true });
2698
+ let content = readFileSync3(sourceFile, "utf-8");
2520
2699
  content = content.replace(/\$\{agent_id\}/g, agent);
2521
- writeFileSync2(ccAgentFile, content, "utf-8");
2700
+ writeFileSync3(ccAgentFile, content, "utf-8");
2522
2701
  process.stderr.write(
2523
2702
  `[exe-launch-agent] auto-provisioned ${ccAgentFile} from ${sourceFile}
2524
2703
  `
@@ -2529,6 +2708,27 @@ async function main() {
2529
2708
  }
2530
2709
  }
2531
2710
  const plan = buildLaunchPlan(agent, behaviorsPath, passthrough, hasAgentFlag, provider);
2711
+ process.env.AGENT_ID = agent;
2712
+ const empRole = (() => {
2713
+ try {
2714
+ const emps = __require("fs").readFileSync(
2715
+ path7.join(os3.homedir(), ".exe-os", "exe-employees.json"),
2716
+ "utf-8"
2717
+ );
2718
+ const found = JSON.parse(emps).find(
2719
+ (e) => e.name.toLowerCase() === agent.toLowerCase()
2720
+ );
2721
+ return found?.role ?? "employee";
2722
+ } catch {
2723
+ return "employee";
2724
+ }
2725
+ })();
2726
+ process.env.AGENT_ROLE = empRole;
2727
+ try {
2728
+ const { writeActiveAgent: writeActiveAgent2 } = await Promise.resolve().then(() => (init_active_agent(), active_agent_exports));
2729
+ writeActiveAgent2(agent, empRole);
2730
+ } catch {
2731
+ }
2532
2732
  if (!process.env.CLAUDE_CODE_DISABLE_ADAPTIVE_THINKING) {
2533
2733
  process.env.CLAUDE_CODE_DISABLE_ADAPTIVE_THINKING = "1";
2534
2734
  }
@@ -196,9 +196,19 @@ You are \${agent_id}. COO \u2014 the founder's most reliable teammate in busines
196
196
  - Pattern recognition: surface recurring problems, connect dots across projects
197
197
  - Architecture guardian (strategic): verify all work aligns with the PRODUCT VISION and five-mode architecture in .planning/ARCHITECTURE.md. Is this the right feature at the right time? Does it match the build order?
198
198
 
199
+ ## First Boot \u2014 Memory Onboarding
200
+
201
+ On your FIRST conversation (when you have few or no prior interactions with the founder):
202
+ 1. Run recall_my_memory with broad queries to discover what exists: search for "project", "client", "pipeline", "SEO", "campaign", "product", "deal", "meeting"
203
+ 2. Summarize what you find: "You've been working on X, Y, Z. Here's what I know about each."
204
+ 3. If memories exist from a backfill, proactively tell the founder what you learned from their history
205
+ 4. Ask what's most important right now
206
+
207
+ Never say "I have no memories" without first searching broadly. Your memory may contain thousands of entries \u2014 surface them by searching for domain-relevant terms, not meta-queries like "what do I know."
208
+
199
209
  ## Tools
200
210
 
201
- - **recall_my_memory / ask_team_memory** \u2014 stay current on all org context
211
+ - **recall_my_memory / ask_team_memory** \u2014 stay current on all org context. Search with specific topic keywords, not vague queries.
202
212
  - **list_tasks** \u2014 monitor queues across all employees and projects
203
213
  - **create_task** \u2014 assign work to specialists with clear specs
204
214
  - **update_task / close_task** \u2014 finalize reviews, mark work done
package/dist/bin/setup.js CHANGED
@@ -1871,9 +1871,19 @@ You are \${agent_id}. COO \u2014 the founder's most reliable teammate in busines
1871
1871
  - Pattern recognition: surface recurring problems, connect dots across projects
1872
1872
  - Architecture guardian (strategic): verify all work aligns with the PRODUCT VISION and five-mode architecture in .planning/ARCHITECTURE.md. Is this the right feature at the right time? Does it match the build order?
1873
1873
 
1874
+ ## First Boot \u2014 Memory Onboarding
1875
+
1876
+ On your FIRST conversation (when you have few or no prior interactions with the founder):
1877
+ 1. Run recall_my_memory with broad queries to discover what exists: search for "project", "client", "pipeline", "SEO", "campaign", "product", "deal", "meeting"
1878
+ 2. Summarize what you find: "You've been working on X, Y, Z. Here's what I know about each."
1879
+ 3. If memories exist from a backfill, proactively tell the founder what you learned from their history
1880
+ 4. Ask what's most important right now
1881
+
1882
+ Never say "I have no memories" without first searching broadly. Your memory may contain thousands of entries \u2014 surface them by searching for domain-relevant terms, not meta-queries like "what do I know."
1883
+
1874
1884
  ## Tools
1875
1885
 
1876
- - **recall_my_memory / ask_team_memory** \u2014 stay current on all org context
1886
+ - **recall_my_memory / ask_team_memory** \u2014 stay current on all org context. Search with specific topic keywords, not vague queries.
1877
1887
  - **list_tasks** \u2014 monitor queues across all employees and projects
1878
1888
  - **create_task** \u2014 assign work to specialists with clear specs
1879
1889
  - **update_task / close_task** \u2014 finalize reviews, mark work done
@@ -47,9 +47,19 @@ You are \${agent_id}. COO \u2014 the founder's most reliable teammate in busines
47
47
  - Pattern recognition: surface recurring problems, connect dots across projects
48
48
  - Architecture guardian (strategic): verify all work aligns with the PRODUCT VISION and five-mode architecture in .planning/ARCHITECTURE.md. Is this the right feature at the right time? Does it match the build order?
49
49
 
50
+ ## First Boot \u2014 Memory Onboarding
51
+
52
+ On your FIRST conversation (when you have few or no prior interactions with the founder):
53
+ 1. Run recall_my_memory with broad queries to discover what exists: search for "project", "client", "pipeline", "SEO", "campaign", "product", "deal", "meeting"
54
+ 2. Summarize what you find: "You've been working on X, Y, Z. Here's what I know about each."
55
+ 3. If memories exist from a backfill, proactively tell the founder what you learned from their history
56
+ 4. Ask what's most important right now
57
+
58
+ Never say "I have no memories" without first searching broadly. Your memory may contain thousands of entries \u2014 surface them by searching for domain-relevant terms, not meta-queries like "what do I know."
59
+
50
60
  ## Tools
51
61
 
52
- - **recall_my_memory / ask_team_memory** \u2014 stay current on all org context
62
+ - **recall_my_memory / ask_team_memory** \u2014 stay current on all org context. Search with specific topic keywords, not vague queries.
53
63
  - **list_tasks** \u2014 monitor queues across all employees and projects
54
64
  - **create_task** \u2014 assign work to specialists with clear specs
55
65
  - **update_task / close_task** \u2014 finalize reviews, mark work done
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@askexenow/exe-os",
3
- "version": "0.8.26",
3
+ "version": "0.8.28",
4
4
  "description": "AI employee operating system — persistent memory, task management, and multi-agent coordination for Claude Code.",
5
5
  "license": "CC-BY-NC-4.0",
6
6
  "type": "module",