@askexenow/exe-os 0.9.198 → 0.9.199

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 (151) hide show
  1. package/deploy/compose/cloudflared/config.yml.example +3 -0
  2. package/deploy/compose/init-db.sql +4 -0
  3. package/deploy/stack-manifests/v0.9.json +5 -0
  4. package/dist/{backfill-metadata-KYCN4I7C.js → backfill-metadata-RL7T4XGY.js} +1 -1
  5. package/dist/bin/agentic-ontology-backfill.js +1 -1
  6. package/dist/bin/agentic-reflection-backfill.js +1 -1
  7. package/dist/bin/agentic-semantic-label.js +1 -1
  8. package/dist/bin/backfill-conversations.js +1 -1
  9. package/dist/bin/backfill-responses.js +1 -1
  10. package/dist/bin/backfill-vectors.js +2 -2
  11. package/dist/bin/bulk-sync-postgres.js +1 -1
  12. package/dist/bin/cleanup-stale-review-tasks.js +2 -2
  13. package/dist/bin/cli.js +10 -10
  14. package/dist/bin/exe-agent.js +8 -8
  15. package/dist/bin/exe-assign.js +1 -1
  16. package/dist/bin/exe-boot.js +4 -4
  17. package/dist/bin/exe-call.js +1 -1
  18. package/dist/bin/exe-dispatch.js +2 -2
  19. package/dist/bin/exe-doctor.js +1 -1
  20. package/dist/bin/exe-export-behaviors.js +2 -2
  21. package/dist/bin/exe-forget.js +3 -3
  22. package/dist/bin/exe-gateway.js +4 -4
  23. package/dist/bin/exe-heartbeat.js +2 -2
  24. package/dist/bin/exe-kill.js +3 -3
  25. package/dist/bin/exe-launch-agent.js +3 -9
  26. package/dist/bin/exe-new-employee.js +2 -2
  27. package/dist/bin/exe-pending-messages.js +3 -3
  28. package/dist/bin/exe-pending-notifications.js +2 -2
  29. package/dist/bin/exe-pending-reviews.js +2 -2
  30. package/dist/bin/exe-rename.js +1 -1
  31. package/dist/bin/exe-review.js +3 -3
  32. package/dist/bin/exe-search.js +2 -2
  33. package/dist/bin/exe-session-cleanup.js +5 -5
  34. package/dist/bin/exe-start-codex.js +2 -2
  35. package/dist/bin/exe-start-opencode.js +2 -2
  36. package/dist/bin/exe-status.js +3 -3
  37. package/dist/bin/exe-team.js +1 -1
  38. package/dist/bin/generate-hook-manifest.js +30 -0
  39. package/dist/bin/git-sweep.js +2 -2
  40. package/dist/bin/graph-backfill.js +1 -1
  41. package/dist/bin/graph-export.js +2 -2
  42. package/dist/bin/import-history.js +1 -1
  43. package/dist/bin/install.js +3 -3
  44. package/dist/bin/intercom-check.js +3 -3
  45. package/dist/bin/scan-tasks.js +2 -2
  46. package/dist/bin/setup.js +1 -1
  47. package/dist/bin/shard-migrate.js +1 -1
  48. package/dist/browser-sanitizer-Q3GWRYKI.js +229 -0
  49. package/dist/browser-session-store-TSD4PCY7.js +232 -0
  50. package/dist/{capacity-monitor-H7D43IUQ.js → capacity-monitor-2TRPP3AX.js} +2 -2
  51. package/dist/{catchup-brief-PTVQRBQK.js → catchup-brief-74ORL525.js} +3 -3
  52. package/dist/{chunk-BM4X3WHU.js → chunk-2DWKMJPE.js} +1 -1
  53. package/dist/{chunk-EMUQSTJL.js → chunk-2HEXCZGP.js} +1 -1
  54. package/dist/{chunk-HX4ULQ3E.js → chunk-5YVGHP2B.js} +11 -11
  55. package/dist/{chunk-5RT7IBY4.js → chunk-6BJ5GZD4.js} +3 -3
  56. package/dist/{chunk-BUN6JIDP.js → chunk-ACOQS4ZL.js} +1 -1
  57. package/dist/{chunk-HH4UGDJH.js → chunk-CGAYSKQF.js} +2 -2
  58. package/dist/{chunk-ADI4Z63O.js → chunk-DNEOEKWA.js} +2 -2
  59. package/dist/{chunk-62DAMAFL.js → chunk-FDD7KX7Q.js} +3 -3
  60. package/dist/{chunk-7AJST6LP.js → chunk-FXVTLBBA.js} +1 -1
  61. package/dist/{chunk-CGDA6NJI.js → chunk-IFFVONU6.js} +1 -1
  62. package/dist/{chunk-VGBQKQHJ.js → chunk-JDGCEOT4.js} +1 -1
  63. package/dist/{chunk-2EVDBTCZ.js → chunk-JDHB6I4O.js} +1 -1
  64. package/dist/{chunk-FL4PEEWL.js → chunk-JQLWMZZJ.js} +1 -1
  65. package/dist/{chunk-CHZMPZJ3.js → chunk-JRLSQFIE.js} +44 -44
  66. package/dist/{chunk-34ENR4JM.js → chunk-KRYEHI4V.js} +2 -2
  67. package/dist/{chunk-WP6P3LSI.js → chunk-MABQMUCQ.js} +9 -26
  68. package/dist/chunk-MNNWWEVJ.js +58 -0
  69. package/dist/{chunk-LLEB3QLI.js → chunk-MWGAC2ER.js} +1 -1
  70. package/dist/{chunk-UTDZUTRN.js → chunk-OF6TXNOC.js} +1 -1
  71. package/dist/{chunk-HH2QED73.js → chunk-OYU7TCBG.js} +1 -1
  72. package/dist/{chunk-UTUYZCQA.js → chunk-PHIQW2IU.js} +3 -3
  73. package/dist/{chunk-FXYOH3NG.js → chunk-RUKOGGQG.js} +1 -1
  74. package/dist/{chunk-FC3U23FN.js → chunk-WSYFZZCP.js} +2 -2
  75. package/dist/{chunk-QCNSCSCH.js → chunk-YZIUQ77U.js} +2 -2
  76. package/dist/{chunk-IUC2332K.js → chunk-ZAF4GJTD.js} +4 -4
  77. package/dist/{chunk-Q4WJJBOP.js → chunk-ZLP5TNRU.js} +1 -1
  78. package/dist/{crm-webhook-LRLN55LB.js → crm-webhook-OFWPEK33.js} +2 -2
  79. package/dist/{cto-delegation-gate-2FZN5SUY.js → cto-delegation-gate-7PGS5IN4.js} +1 -1
  80. package/dist/{daemon-orchestration-ZBSS6VZR.js → daemon-orchestration-MP3PPX7Q.js} +3 -3
  81. package/dist/{exe-export-4ZJTQRRE.js → exe-export-QMGWH3PL.js} +1 -1
  82. package/dist/{exe-import-JI3FTSWZ.js → exe-import-7NNKSCKI.js} +1 -1
  83. package/dist/{fast-db-init-URP3KJAE.js → fast-db-init-DAZZ7ZUP.js} +1 -1
  84. package/dist/gateway/index.js +5 -5
  85. package/dist/{git-task-sweep-GPPNL2DK.js → git-task-sweep-SLANXCSW.js} +2 -2
  86. package/dist/hooks/bug-report-worker.js +3 -3
  87. package/dist/hooks/codex-stop-task-finalizer.js +3 -3
  88. package/dist/hooks/commit-complete.js +4 -4
  89. package/dist/hooks/error-recall.js +2 -2
  90. package/dist/hooks/ingest.js +2 -2
  91. package/dist/hooks/instructions-loaded.js +1 -1
  92. package/dist/hooks/manifest.json +25 -0
  93. package/dist/hooks/notification.js +1 -1
  94. package/dist/hooks/post-compact.js +2 -2
  95. package/dist/hooks/post-tool-combined.js +2 -2
  96. package/dist/hooks/pre-compact.js +3 -3
  97. package/dist/hooks/pre-tool-use.js +6 -6
  98. package/dist/hooks/prompt-submit.js +8 -8
  99. package/dist/hooks/session-end.js +18 -4
  100. package/dist/hooks/session-start.js +17 -4
  101. package/dist/hooks/stop.js +5 -5
  102. package/dist/hooks/subagent-stop.js +2 -2
  103. package/dist/hooks/summary-worker.js +5 -5
  104. package/dist/index.js +10 -10
  105. package/dist/{installer-4SH2HTIU.js → installer-CWKEI7SE.js} +2 -2
  106. package/dist/{installer-BTOQSNZI.js → installer-DWVZFKAH.js} +4 -4
  107. package/dist/{installer-MWOEIXKV.js → installer-GSA2KOSE.js} +2 -2
  108. package/dist/lib/consolidation.js +2 -2
  109. package/dist/lib/embed-worker.js +81 -14
  110. package/dist/lib/employee-templates.js +1 -1
  111. package/dist/lib/exe-daemon.js +62 -13
  112. package/dist/lib/hybrid-search.js +2 -2
  113. package/dist/lib/messaging.js +2 -2
  114. package/dist/lib/schedules.js +2 -2
  115. package/dist/lib/store.js +1 -1
  116. package/dist/lib/tasks.js +2 -2
  117. package/dist/lib/tmux-routing.js +1 -1
  118. package/dist/mcp/register-tools.js +26 -26
  119. package/dist/mcp/server.js +29 -29
  120. package/dist/mcp/tools/create-task.js +3 -3
  121. package/dist/mcp/tools/list-tasks.js +3 -3
  122. package/dist/mcp/tools/send-message.js +3 -3
  123. package/dist/mcp/tools/update-task.js +3 -3
  124. package/dist/{notifications-GENT3AWZ.js → notifications-WYNI5OG6.js} +1 -1
  125. package/dist/{orchestrator-A72IFTWK.js → orchestrator-FRFCMLW3.js} +2 -2
  126. package/dist/{reranker-JJRY3V3V.js → reranker-2ZWUZRUF.js} +1 -1
  127. package/dist/{review-polling-UJ4P3BIG.js → review-polling-ADP5YFHW.js} +2 -2
  128. package/dist/runtime/index.js +11 -11
  129. package/dist/{session-events-GWEVYXPJ.js → session-events-JA3MCMZK.js} +2 -2
  130. package/dist/{session-scope-DKE6OPV5.js → session-scope-LXQKQDIS.js} +1 -1
  131. package/dist/{setup-wizard-B4WDA4KT.js → setup-wizard-GRR4F4TX.js} +1 -1
  132. package/dist/{task-enforcement-QYS2QEEO.js → task-enforcement-KSLBFILH.js} +1 -1
  133. package/dist/{task-scope-OS66ZD7O.js → task-scope-AI62AIPT.js} +1 -1
  134. package/dist/{tasks-crud-DJH4NZC2.js → tasks-crud-IEOK55IV.js} +1 -1
  135. package/dist/{tasks-review-Z6PA4AF5.js → tasks-review-ID7V6RSR.js} +1 -1
  136. package/dist/tui/App.js +8 -8
  137. package/dist/{tui-data-JI4URSHX.js → tui-data-HIFVW2PE.js} +1 -1
  138. package/dist/{worker-gate-DIILYSRZ.js → worker-gate-F3L7XDMJ.js} +1 -1
  139. package/dist/{workflow-engine-PJ5YSMRL.js → workflow-engine-H5KTDDJG.js} +2 -2
  140. package/package.json +3 -3
  141. package/release-notes.json +116 -119
  142. package/dist/chunk-WZTQUBIE.js +0 -125
  143. package/dist/{chunk-42QSXHKN.js → chunk-4X7CMJDN.js} +0 -0
  144. package/dist/{chunk-ZGPURQ4J.js → chunk-54MZI4PK.js} +0 -0
  145. package/dist/{chunk-TF2BZTXF.js → chunk-7WUBXLK2.js} +3 -3
  146. /package/dist/{chunk-SSRRHKIO.js → chunk-MQLMIY6U.js} +0 -0
  147. /package/dist/{chunk-M4UP7VWO.js → chunk-NF4AEKQK.js} +0 -0
  148. /package/dist/{chunk-LZU4HY4C.js → chunk-XNXTN5XZ.js} +0 -0
  149. /package/dist/{core-memory-UHWYIN2A.js → core-memory-VQKCHGFX.js} +0 -0
  150. /package/dist/{exe-key-4EUOGKBN.js → exe-key-QZ5GWV6D.js} +0 -0
  151. /package/dist/{skill-refinement-2U2UCV2H.js → skill-refinement-3UVLBCZD.js} +0 -0
@@ -6,7 +6,7 @@ import "../chunk-OGQX7HLN.js";
6
6
  import {
7
7
  disposeStore,
8
8
  initStore
9
- } from "../chunk-42QSXHKN.js";
9
+ } from "../chunk-4X7CMJDN.js";
10
10
  import "../chunk-CHCA3ZM2.js";
11
11
  import "../chunk-OO5CPMT3.js";
12
12
  import {
@@ -180,7 +180,7 @@ async function main() {
180
180
  } catch {
181
181
  }
182
182
  try {
183
- const { verifyOpenCodeHooks, runOpenCodeInstaller } = await import("../installer-MWOEIXKV.js");
183
+ const { verifyOpenCodeHooks, runOpenCodeInstaller } = await import("../installer-GSA2KOSE.js");
184
184
  if (!verifyOpenCodeHooks()) {
185
185
  process.stderr.write("[exe-start-opencode] hooks missing \u2014 registering now\n");
186
186
  await runOpenCodeInstaller();
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  status
4
- } from "../chunk-34ENR4JM.js";
5
- import "../chunk-M4UP7VWO.js";
6
- import "../chunk-WP6P3LSI.js";
4
+ } from "../chunk-KRYEHI4V.js";
5
+ import "../chunk-NF4AEKQK.js";
6
+ import "../chunk-MABQMUCQ.js";
7
7
  import "../chunk-RN6XYY7U.js";
8
8
  import "../chunk-QI4IXJN7.js";
9
9
  import "../chunk-64WZEXXA.js";
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  fastDbInit
4
- } from "../chunk-M4UP7VWO.js";
4
+ } from "../chunk-NF4AEKQK.js";
5
5
  import {
6
6
  getClient,
7
7
  loadEmployees
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/bin/generate-hook-manifest.ts
4
+ import { createHash } from "crypto";
5
+ import { readFileSync, writeFileSync, readdirSync, existsSync } from "fs";
6
+ import path from "path";
7
+ import { fileURLToPath } from "url";
8
+ var __dirname = path.dirname(fileURLToPath(import.meta.url));
9
+ var HOOKS_DIR = path.resolve(__dirname, "..", "hooks");
10
+ var MANIFEST_PATH = path.join(HOOKS_DIR, "manifest.json");
11
+ function main() {
12
+ if (!existsSync(HOOKS_DIR)) {
13
+ console.error(`[generate-hook-manifest] Hooks directory not found: ${HOOKS_DIR}`);
14
+ process.exit(1);
15
+ }
16
+ const files = readdirSync(HOOKS_DIR).filter((f) => f.endsWith(".js"));
17
+ const hashes = {};
18
+ for (const file of files) {
19
+ const content = readFileSync(path.join(HOOKS_DIR, file));
20
+ hashes[file] = createHash("sha256").update(content).digest("hex");
21
+ }
22
+ const manifest = {
23
+ version: 1,
24
+ generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
25
+ hashes
26
+ };
27
+ writeFileSync(MANIFEST_PATH, JSON.stringify(manifest, null, 2) + "\n");
28
+ console.log(`[generate-hook-manifest] Written ${files.length} hashes to ${MANIFEST_PATH}`);
29
+ }
30
+ main();
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  sweepTasks
4
- } from "../chunk-ADI4Z63O.js";
5
- import "../chunk-WP6P3LSI.js";
4
+ } from "../chunk-DNEOEKWA.js";
5
+ import "../chunk-MABQMUCQ.js";
6
6
  import "../chunk-RN6XYY7U.js";
7
7
  import "../chunk-QI4IXJN7.js";
8
8
  import "../chunk-64WZEXXA.js";
@@ -11,7 +11,7 @@ import "../chunk-I7AW4237.js";
11
11
  import {
12
12
  disposeStore,
13
13
  initStore
14
- } from "../chunk-42QSXHKN.js";
14
+ } from "../chunk-4X7CMJDN.js";
15
15
  import "../chunk-CHCA3ZM2.js";
16
16
  import "../chunk-OO5CPMT3.js";
17
17
  import "../chunk-MP2AFCGL.js";
@@ -5,10 +5,10 @@ import {
5
5
  } from "../chunk-46SQTBQW.js";
6
6
  import {
7
7
  fastDbInit
8
- } from "../chunk-M4UP7VWO.js";
8
+ } from "../chunk-NF4AEKQK.js";
9
9
  import {
10
10
  disposeStore
11
- } from "../chunk-42QSXHKN.js";
11
+ } from "../chunk-4X7CMJDN.js";
12
12
  import "../chunk-CHCA3ZM2.js";
13
13
  import "../chunk-OO5CPMT3.js";
14
14
  import "../chunk-MP2AFCGL.js";
@@ -12,7 +12,7 @@ import {
12
12
  flushBatch,
13
13
  initStore,
14
14
  writeMemory
15
- } from "../chunk-42QSXHKN.js";
15
+ } from "../chunk-4X7CMJDN.js";
16
16
  import {
17
17
  extractKeywords,
18
18
  keywordsToString
@@ -6,9 +6,9 @@ import {
6
6
  setupGhostty,
7
7
  setupTmux,
8
8
  setupWezterm
9
- } from "../chunk-TF2BZTXF.js";
10
- import "../chunk-QPSUK5HA.js";
9
+ } from "../chunk-7WUBXLK2.js";
11
10
  import "../chunk-GNHN5HRQ.js";
11
+ import "../chunk-QPSUK5HA.js";
12
12
  import {
13
13
  generateSessionWrappers
14
14
  } from "../chunk-ZHMQDTGE.js";
@@ -329,7 +329,7 @@ if (args.includes("--commands-only")) {
329
329
  }
330
330
  try {
331
331
  execSync("which codex", { encoding: "utf8", timeout: 5e3 });
332
- const { runCodexInstaller } = await import("../installer-BTOQSNZI.js");
332
+ const { runCodexInstaller } = await import("../installer-DWVZFKAH.js");
333
333
  await runCodexInstaller();
334
334
  } catch {
335
335
  }
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  fastDbInit
4
- } from "../chunk-M4UP7VWO.js";
4
+ } from "../chunk-NF4AEKQK.js";
5
5
  import "../chunk-MLKGABMK.js";
6
6
 
7
7
  // src/bin/intercom-check.ts
@@ -17,7 +17,7 @@ async function main() {
17
17
  }
18
18
  if (isCoordinator) {
19
19
  try {
20
- const { listPendingReviews, cleanupOrphanedReviews, formatAge, isStale } = await import("../tasks-review-Z6PA4AF5.js");
20
+ const { listPendingReviews, cleanupOrphanedReviews, formatAge, isStale } = await import("../tasks-review-ID7V6RSR.js");
21
21
  const { extractRootExe } = await import("../lib/tmux-routing.js");
22
22
  let sessionScope = process.env.EXE_SESSION ? extractRootExe(process.env.EXE_SESSION) ?? void 0 : void 0;
23
23
  if (!sessionScope) {
@@ -115,7 +115,7 @@ async function main() {
115
115
  }
116
116
  }
117
117
  try {
118
- const { readUnreadNotifications, markAsRead } = await import("../notifications-GENT3AWZ.js");
118
+ const { readUnreadNotifications, markAsRead } = await import("../notifications-WYNI5OG6.js");
119
119
  const { resolveExeSession } = await import("../lib/tmux-routing.js");
120
120
  const sessionScope = resolveExeSession();
121
121
  const notifications = await readUnreadNotifications(agent, sessionScope);
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  queryTaskRows
4
- } from "../chunk-WP6P3LSI.js";
4
+ } from "../chunk-MABQMUCQ.js";
5
5
  import "../chunk-RN6XYY7U.js";
6
6
  import "../chunk-QI4IXJN7.js";
7
7
  import "../chunk-64WZEXXA.js";
@@ -72,7 +72,7 @@ function checkMcpHealth() {
72
72
  }
73
73
  }
74
74
  async function scanFromDb(agentId, tmuxSession, projectName) {
75
- const { fastDbInit } = await import("../fast-db-init-URP3KJAE.js");
75
+ const { fastDbInit } = await import("../fast-db-init-DAZZ7ZUP.js");
76
76
  try {
77
77
  await fastDbInit();
78
78
  } catch (err) {
package/dist/bin/setup.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  runSetupWizard
4
- } from "../chunk-SSRRHKIO.js";
4
+ } from "../chunk-MQLMIY6U.js";
5
5
  import "../chunk-6D23UNXU.js";
6
6
  import "../chunk-4GXRETYL.js";
7
7
  import "../chunk-LYH5HE24.js";
@@ -8,7 +8,7 @@ import {
8
8
  import {
9
9
  disposeStore,
10
10
  initStore
11
- } from "../chunk-42QSXHKN.js";
11
+ } from "../chunk-4X7CMJDN.js";
12
12
  import "../chunk-CHCA3ZM2.js";
13
13
  import "../chunk-OO5CPMT3.js";
14
14
  import "../chunk-MP2AFCGL.js";
@@ -0,0 +1,229 @@
1
+ import "./chunk-MLKGABMK.js";
2
+
3
+ // src/lib/browser-sanitizer.ts
4
+ import crypto from "crypto";
5
+ var _canaries = /* @__PURE__ */ new Map();
6
+ function getCanaryToken(agentId) {
7
+ let canary = _canaries.get(agentId);
8
+ if (!canary) {
9
+ canary = crypto.randomBytes(16).toString("hex");
10
+ _canaries.set(agentId, canary);
11
+ }
12
+ return canary;
13
+ }
14
+ function clearCanaryToken(agentId) {
15
+ _canaries.delete(agentId);
16
+ }
17
+ function checkCanary(content, agentId) {
18
+ const canary = _canaries.get(agentId);
19
+ if (!canary) return { injectionDetected: false };
20
+ const idx = content.indexOf(canary);
21
+ if (idx === -1) return { injectionDetected: false };
22
+ const start = Math.max(0, idx - 50);
23
+ const end = Math.min(content.length, idx + canary.length + 50);
24
+ return {
25
+ injectionDetected: true,
26
+ foundAt: idx,
27
+ context: content.slice(start, end)
28
+ };
29
+ }
30
+ var INVISIBLE_CHARS_PATTERN = new RegExp(
31
+ [
32
+ "\\u200B",
33
+ // Zero-width space
34
+ "\\u200C",
35
+ // Zero-width non-joiner
36
+ "\\u200D",
37
+ // Zero-width joiner
38
+ "\\u200E",
39
+ // Left-to-right mark
40
+ "\\u200F",
41
+ // Right-to-left mark
42
+ "\\u2060",
43
+ // Word joiner
44
+ "\\u2061",
45
+ // Function application
46
+ "\\u2062",
47
+ // Invisible times
48
+ "\\u2063",
49
+ // Invisible separator
50
+ "\\u2064",
51
+ // Invisible plus
52
+ "\\uFEFF",
53
+ // BOM / zero-width no-break space
54
+ "\\u00AD",
55
+ // Soft hyphen
56
+ "\\u034F",
57
+ // Combining grapheme joiner
58
+ "\\u061C",
59
+ // Arabic letter mark
60
+ "\\u115F",
61
+ // Hangul choseong filler
62
+ "\\u1160",
63
+ // Hangul jungseong filler
64
+ "\\u17B4",
65
+ // Khmer vowel inherent aq
66
+ "\\u17B5",
67
+ // Khmer vowel inherent aa
68
+ "\\u180E",
69
+ // Mongolian vowel separator
70
+ "\\u2000",
71
+ // En quad (sometimes abused)
72
+ "\\u2001",
73
+ // Em quad
74
+ "\\u2002",
75
+ // En space
76
+ "\\u2003",
77
+ // Em space
78
+ "\\u2004",
79
+ // Three-per-em space
80
+ "\\u2005",
81
+ // Four-per-em space
82
+ "\\u2006",
83
+ // Six-per-em space
84
+ "\\u2007",
85
+ // Figure space
86
+ "\\u2008",
87
+ // Punctuation space
88
+ "\\u2009",
89
+ // Thin space
90
+ "\\u200A",
91
+ // Hair space
92
+ "\\u202A",
93
+ // Left-to-right embedding
94
+ "\\u202B",
95
+ // Right-to-left embedding
96
+ "\\u202C",
97
+ // Pop directional formatting
98
+ "\\u202D",
99
+ // Left-to-right override
100
+ "\\u202E",
101
+ // Right-to-left override
102
+ "\\u2066",
103
+ // Left-to-right isolate
104
+ "\\u2067",
105
+ // Right-to-left isolate
106
+ "\\u2068",
107
+ // First strong isolate
108
+ "\\u2069",
109
+ // Pop directional isolate
110
+ "\\uFFA0",
111
+ // Halfwidth Hangul filler
112
+ "\\uFFF9",
113
+ // Interlinear annotation anchor
114
+ "\\uFFFA",
115
+ // Interlinear annotation separator
116
+ "\\uFFFB"
117
+ // Interlinear annotation terminator
118
+ ].join("|"),
119
+ "g"
120
+ );
121
+ var HTML_COMMENT_PATTERN = /<!--[\s\S]*?-->/g;
122
+ var HIDDEN_ELEMENT_PATTERNS = [
123
+ // display:none elements
124
+ /<[^>]+style\s*=\s*"[^"]*display\s*:\s*none[^"]*"[^>]*>[\s\S]*?<\/[^>]+>/gi,
125
+ /<[^>]+style\s*=\s*'[^']*display\s*:\s*none[^']*'[^>]*>[\s\S]*?<\/[^>]+>/gi,
126
+ // visibility:hidden elements
127
+ /<[^>]+style\s*=\s*"[^"]*visibility\s*:\s*hidden[^"]*"[^>]*>[\s\S]*?<\/[^>]+>/gi,
128
+ /<[^>]+style\s*=\s*'[^']*visibility\s*:\s*hidden[^']*'[^>]*>[\s\S]*?<\/[^>]+>/gi,
129
+ // opacity:0 elements
130
+ /<[^>]+style\s*=\s*"[^"]*opacity\s*:\s*0[^"]*"[^>]*>[\s\S]*?<\/[^>]+>/gi,
131
+ /<[^>]+style\s*=\s*'[^']*opacity\s*:\s*0[^']*'[^>]*>[\s\S]*?<\/[^>]+>/gi,
132
+ // Hidden attribute
133
+ /<[^>]+\bhidden\b[^>]*>[\s\S]*?<\/[^>]+>/gi,
134
+ // aria-hidden="true" (sometimes used to hide injection text)
135
+ /<[^>]+aria-hidden\s*=\s*"true"[^>]*>[\s\S]*?<\/[^>]+>/gi,
136
+ // Absolute positioning off-screen (common injection technique)
137
+ /<[^>]+style\s*=\s*"[^"]*position\s*:\s*absolute[^"]*left\s*:\s*-\d{4,}[^"]*"[^>]*>[\s\S]*?<\/[^>]+>/gi,
138
+ /<[^>]+style\s*=\s*"[^"]*position\s*:\s*absolute[^"]*top\s*:\s*-\d{4,}[^"]*"[^>]*>[\s\S]*?<\/[^>]+>/gi
139
+ ];
140
+ var SUSPICIOUS_DATA_ATTRS = /\s+data-(?:prompt|instruction|system|ai-instruction|llm-prompt|agent-instruction|hidden-prompt|inject|command|role|context|persona)\s*=\s*"[^"]*"/gi;
141
+ var SCRIPT_STYLE_PATTERN = /<(?:script|style)\b[^>]*>[\s\S]*?<\/(?:script|style)>/gi;
142
+ var NOSCRIPT_PATTERN = /<noscript\b[^>]*>[\s\S]*?<\/noscript>/gi;
143
+ function sanitizeBrowserContent(rawContent, options = {}) {
144
+ const {
145
+ stripHidden = true,
146
+ stripComments = true,
147
+ stripInvisible = true,
148
+ stripScripts = true,
149
+ stripSuspiciousAttrs = true,
150
+ stripNoscript = true,
151
+ agentId
152
+ } = options;
153
+ let content = rawContent;
154
+ let strippedCount = 0;
155
+ const strippedCategories = [];
156
+ let injectionDetected = false;
157
+ let warning;
158
+ if (agentId) {
159
+ const canaryResult = checkCanary(content, agentId);
160
+ if (canaryResult.injectionDetected) {
161
+ injectionDetected = true;
162
+ warning = `\u26A0\uFE0F PROMPT INJECTION DETECTED: Page content contains your session canary token at offset ${canaryResult.foundAt}. This page may be attempting to extract or manipulate your system prompt. Context: "${canaryResult.context}"`;
163
+ }
164
+ }
165
+ if (stripScripts) {
166
+ const before = content.length;
167
+ content = content.replace(SCRIPT_STYLE_PATTERN, "");
168
+ if (content.length < before) {
169
+ strippedCount++;
170
+ strippedCategories.push("scripts/styles");
171
+ }
172
+ }
173
+ if (stripHidden) {
174
+ const before = content.length;
175
+ for (const pattern of HIDDEN_ELEMENT_PATTERNS) {
176
+ content = content.replace(pattern, "");
177
+ }
178
+ if (content.length < before) {
179
+ strippedCount++;
180
+ strippedCategories.push("hidden-elements");
181
+ }
182
+ }
183
+ if (stripComments) {
184
+ const before = content.length;
185
+ content = content.replace(HTML_COMMENT_PATTERN, "");
186
+ if (content.length < before) {
187
+ strippedCount++;
188
+ strippedCategories.push("html-comments");
189
+ }
190
+ }
191
+ if (stripInvisible) {
192
+ const before = content.length;
193
+ content = content.replace(INVISIBLE_CHARS_PATTERN, "");
194
+ if (content.length < before) {
195
+ strippedCount++;
196
+ strippedCategories.push("invisible-chars");
197
+ }
198
+ }
199
+ if (stripSuspiciousAttrs) {
200
+ const before = content.length;
201
+ content = content.replace(SUSPICIOUS_DATA_ATTRS, "");
202
+ if (content.length < before) {
203
+ strippedCount++;
204
+ strippedCategories.push("suspicious-data-attrs");
205
+ }
206
+ }
207
+ if (stripNoscript) {
208
+ const before = content.length;
209
+ content = content.replace(NOSCRIPT_PATTERN, "");
210
+ if (content.length < before) {
211
+ strippedCount++;
212
+ strippedCategories.push("noscript");
213
+ }
214
+ }
215
+ content = content.replace(/\n{3,}/g, "\n\n").trim();
216
+ return {
217
+ content,
218
+ injectionDetected,
219
+ strippedCount,
220
+ strippedCategories,
221
+ warning
222
+ };
223
+ }
224
+ export {
225
+ checkCanary,
226
+ clearCanaryToken,
227
+ getCanaryToken,
228
+ sanitizeBrowserContent
229
+ };
@@ -0,0 +1,232 @@
1
+ import {
2
+ enforcePrivateFileSync,
3
+ ensurePrivateDirSync
4
+ } from "./chunk-LYH5HE24.js";
5
+ import "./chunk-MLKGABMK.js";
6
+
7
+ // src/lib/browser-session-store.ts
8
+ import crypto from "crypto";
9
+ import path from "path";
10
+ import os from "os";
11
+ import {
12
+ existsSync,
13
+ readFileSync,
14
+ writeFileSync,
15
+ unlinkSync,
16
+ readdirSync,
17
+ statSync
18
+ } from "fs";
19
+ var ALGORITHM = "aes-256-gcm";
20
+ var IV_LENGTH = 12;
21
+ var TAG_LENGTH = 16;
22
+ var HKDF_INFO = "exe-browser-cookies-v1";
23
+ var DEFAULT_TTL_MS = 30 * 60 * 1e3;
24
+ var _jarCache = /* @__PURE__ */ new Map();
25
+ var _cookieKey = null;
26
+ function initCookieCrypto(masterKey) {
27
+ if (masterKey.length !== 32) {
28
+ throw new Error(`Master key must be 32 bytes, got ${masterKey.length}`);
29
+ }
30
+ _cookieKey = Buffer.from(
31
+ crypto.hkdfSync("sha256", masterKey, "", HKDF_INFO, 32)
32
+ );
33
+ }
34
+ function isCookieCryptoInitialized() {
35
+ return _cookieKey !== null;
36
+ }
37
+ function encrypt(data) {
38
+ if (!_cookieKey) {
39
+ return "plain:" + Buffer.from(data, "utf-8").toString("base64");
40
+ }
41
+ const iv = crypto.randomBytes(IV_LENGTH);
42
+ const cipher = crypto.createCipheriv(ALGORITHM, _cookieKey, iv);
43
+ const encrypted = Buffer.concat([
44
+ cipher.update(Buffer.from(data, "utf-8")),
45
+ cipher.final()
46
+ ]);
47
+ const tag = cipher.getAuthTag();
48
+ return "enc:" + Buffer.concat([iv, encrypted, tag]).toString("base64");
49
+ }
50
+ function decrypt(ciphertext) {
51
+ if (ciphertext.startsWith("plain:")) {
52
+ return Buffer.from(ciphertext.slice(6), "base64").toString("utf-8");
53
+ }
54
+ if (!ciphertext.startsWith("enc:")) {
55
+ throw new Error("Unknown cookie store format");
56
+ }
57
+ if (!_cookieKey) {
58
+ throw new Error("Cookie crypto not initialized but encrypted data found");
59
+ }
60
+ const combined = Buffer.from(ciphertext.slice(4), "base64");
61
+ if (combined.length < IV_LENGTH + TAG_LENGTH) {
62
+ throw new Error("Cookie data too short");
63
+ }
64
+ const iv = combined.subarray(0, IV_LENGTH);
65
+ const tag = combined.subarray(combined.length - TAG_LENGTH);
66
+ const encrypted = combined.subarray(IV_LENGTH, combined.length - TAG_LENGTH);
67
+ const decipher = crypto.createDecipheriv(ALGORITHM, _cookieKey, iv);
68
+ decipher.setAuthTag(tag);
69
+ return Buffer.concat([
70
+ decipher.update(encrypted),
71
+ decipher.final()
72
+ ]).toString("utf-8");
73
+ }
74
+ function getStoreDir() {
75
+ const base = process.env.EXE_OS_DIR ?? path.join(os.homedir(), ".exe-os");
76
+ return path.join(base, "browser-sessions");
77
+ }
78
+ function getJarPath(agentId, sessionKey) {
79
+ const safe = (s) => s.replace(/[^a-zA-Z0-9_-]/g, "_");
80
+ return path.join(getStoreDir(), `${safe(agentId)}-${safe(sessionKey)}.cookies.enc`);
81
+ }
82
+ function jarCacheKey(agentId, sessionKey) {
83
+ return `${agentId}:${sessionKey}`;
84
+ }
85
+ function getTtlMs() {
86
+ const envTtl = process.env.EXE_BROWSER_SESSION_TTL;
87
+ if (envTtl) {
88
+ const parsed = parseInt(envTtl, 10);
89
+ if (!isNaN(parsed) && parsed > 0) return parsed * 1e3;
90
+ }
91
+ return DEFAULT_TTL_MS;
92
+ }
93
+ function loadCookieJar(agentId, sessionKey) {
94
+ const cacheKey = jarCacheKey(agentId, sessionKey);
95
+ const cached = _jarCache.get(cacheKey);
96
+ if (cached) {
97
+ const ttl = getTtlMs();
98
+ if (Date.now() - cached.lastAccessed > ttl) {
99
+ clearCookieJar(agentId, sessionKey);
100
+ return null;
101
+ }
102
+ return cached;
103
+ }
104
+ const jarPath = getJarPath(agentId, sessionKey);
105
+ if (!existsSync(jarPath)) return null;
106
+ try {
107
+ const raw = readFileSync(jarPath, "utf-8");
108
+ const jar = JSON.parse(decrypt(raw));
109
+ const ttl = getTtlMs();
110
+ if (Date.now() - jar.lastAccessed > ttl) {
111
+ clearCookieJar(agentId, sessionKey);
112
+ return null;
113
+ }
114
+ const now = Math.floor(Date.now() / 1e3);
115
+ jar.cookies = jar.cookies.filter((c) => !c.expires || c.expires > now);
116
+ _jarCache.set(cacheKey, jar);
117
+ return jar;
118
+ } catch {
119
+ try {
120
+ unlinkSync(jarPath);
121
+ } catch {
122
+ }
123
+ return null;
124
+ }
125
+ }
126
+ function saveCookieJar(agentId, sessionKey, cookies) {
127
+ const cacheKey = jarCacheKey(agentId, sessionKey);
128
+ const existing = loadCookieJar(agentId, sessionKey);
129
+ const now = Date.now();
130
+ const cookieMap = /* @__PURE__ */ new Map();
131
+ if (existing) {
132
+ for (const c of existing.cookies) {
133
+ cookieMap.set(`${c.domain}:${c.path}:${c.name}`, c);
134
+ }
135
+ }
136
+ for (const c of cookies) {
137
+ cookieMap.set(`${c.domain}:${c.path}:${c.name}`, c);
138
+ }
139
+ const nowSec = Math.floor(now / 1e3);
140
+ const merged = [...cookieMap.values()].filter(
141
+ (c) => !c.expires || c.expires > nowSec
142
+ );
143
+ const jar = {
144
+ agentId,
145
+ sessionKey,
146
+ cookies: merged,
147
+ lastAccessed: now,
148
+ createdAt: existing?.createdAt ?? now
149
+ };
150
+ const storeDir = getStoreDir();
151
+ ensurePrivateDirSync(storeDir);
152
+ const jarPath = getJarPath(agentId, sessionKey);
153
+ const encrypted = encrypt(JSON.stringify(jar));
154
+ writeFileSync(jarPath, encrypted, "utf-8");
155
+ enforcePrivateFileSync(jarPath);
156
+ _jarCache.set(cacheKey, jar);
157
+ }
158
+ function getCookiesForUrl(agentId, sessionKey, url) {
159
+ const jar = loadCookieJar(agentId, sessionKey);
160
+ if (!jar || jar.cookies.length === 0) return [];
161
+ let hostname;
162
+ try {
163
+ hostname = new URL(url).hostname;
164
+ } catch {
165
+ return [];
166
+ }
167
+ const now = Math.floor(Date.now() / 1e3);
168
+ return jar.cookies.filter((c) => {
169
+ if (c.expires && c.expires <= now) return false;
170
+ const cookieDomain = c.domain.startsWith(".") ? c.domain.slice(1) : c.domain;
171
+ return hostname === cookieDomain || hostname.endsWith("." + cookieDomain);
172
+ });
173
+ }
174
+ function clearCookieJar(agentId, sessionKey) {
175
+ const cacheKey = jarCacheKey(agentId, sessionKey);
176
+ _jarCache.delete(cacheKey);
177
+ const jarPath = getJarPath(agentId, sessionKey);
178
+ try {
179
+ if (existsSync(jarPath)) unlinkSync(jarPath);
180
+ } catch {
181
+ }
182
+ }
183
+ function cleanupExpiredJars() {
184
+ const storeDir = getStoreDir();
185
+ if (!existsSync(storeDir)) return 0;
186
+ const ttl = getTtlMs();
187
+ const now = Date.now();
188
+ let cleaned = 0;
189
+ try {
190
+ const files = readdirSync(storeDir).filter((f) => f.endsWith(".cookies.enc"));
191
+ for (const file of files) {
192
+ const filePath = path.join(storeDir, file);
193
+ try {
194
+ const stat = statSync(filePath);
195
+ if (now - stat.mtimeMs > ttl) {
196
+ unlinkSync(filePath);
197
+ cleaned++;
198
+ }
199
+ } catch {
200
+ }
201
+ }
202
+ } catch {
203
+ }
204
+ return cleaned;
205
+ }
206
+ function touchCookieJar(agentId, sessionKey) {
207
+ const cacheKey = jarCacheKey(agentId, sessionKey);
208
+ const cached = _jarCache.get(cacheKey);
209
+ if (cached) {
210
+ cached.lastAccessed = Date.now();
211
+ const jarPath = getJarPath(agentId, sessionKey);
212
+ try {
213
+ if (existsSync(jarPath)) {
214
+ const raw = readFileSync(jarPath, "utf-8");
215
+ const jar = JSON.parse(decrypt(raw));
216
+ jar.lastAccessed = Date.now();
217
+ writeFileSync(jarPath, encrypt(JSON.stringify(jar)), "utf-8");
218
+ }
219
+ } catch {
220
+ }
221
+ }
222
+ }
223
+ export {
224
+ cleanupExpiredJars,
225
+ clearCookieJar,
226
+ getCookiesForUrl,
227
+ initCookieCrypto,
228
+ isCookieCryptoInitialized,
229
+ loadCookieJar,
230
+ saveCookieJar,
231
+ touchCookieJar
232
+ };
@@ -8,9 +8,9 @@ import {
8
8
  isAtCapacity,
9
9
  isWithinRelaunchCooldown,
10
10
  pollCapacityDead
11
- } from "./chunk-Q4WJJBOP.js";
11
+ } from "./chunk-ZLP5TNRU.js";
12
12
  import "./chunk-WRCETUYE.js";
13
- import "./chunk-WP6P3LSI.js";
13
+ import "./chunk-MABQMUCQ.js";
14
14
  import "./chunk-RN6XYY7U.js";
15
15
  import "./chunk-QI4IXJN7.js";
16
16
  import "./chunk-64WZEXXA.js";