@agenticmail/enterprise 0.5.312 → 0.5.313

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 (208) hide show
  1. package/README.md +682 -544
  2. package/dist/agent-autonomy-PSXQ4MNP.js +766 -0
  3. package/dist/agent-heartbeat-6H3YAQ32.js +510 -0
  4. package/dist/agent-heartbeat-7WS3XILF.js +510 -0
  5. package/dist/agent-heartbeat-BFGKYUUK.js +510 -0
  6. package/dist/agent-heartbeat-SSV65YTX.js +510 -0
  7. package/dist/agent-heartbeat-T5IIHVF4.js +510 -0
  8. package/dist/agent-heartbeat-X3C6FIU2.js +510 -0
  9. package/dist/agent-tools-BW6CLQQ7.js +13897 -0
  10. package/dist/agent-tools-KEA7QEWF.js +13897 -0
  11. package/dist/agent-tools-NU7V3S5N.js +13899 -0
  12. package/dist/agent-tools-WINDYRQ2.js +13897 -0
  13. package/dist/chunk-3ELH5CU6.js +4910 -0
  14. package/dist/chunk-4QYRS3MS.js +1519 -0
  15. package/dist/chunk-52REEVDW.js +1519 -0
  16. package/dist/chunk-5RZJ76YI.js +4977 -0
  17. package/dist/chunk-6L7FQI5Q.js +4909 -0
  18. package/dist/chunk-763OMGFI.js +1519 -0
  19. package/dist/chunk-7ILSXGY6.js +1519 -0
  20. package/dist/chunk-7UCKD25B.js +551 -0
  21. package/dist/chunk-A6MSR7DL.js +4977 -0
  22. package/dist/chunk-ASD2YB6O.js +1519 -0
  23. package/dist/chunk-AZOIHLLX.js +4977 -0
  24. package/dist/chunk-BDCFOP7O.js +537 -0
  25. package/dist/chunk-BSVWPG6I.js +106 -0
  26. package/dist/chunk-C46DNDZB.js +1519 -0
  27. package/dist/chunk-CFVTK4FQ.js +4977 -0
  28. package/dist/chunk-CHJAOKCJ.js +4921 -0
  29. package/dist/chunk-CYEWTXYH.js +4977 -0
  30. package/dist/chunk-D3KFSWLK.js +48 -0
  31. package/dist/chunk-DUVGNAIY.js +4977 -0
  32. package/dist/chunk-DX4XEFVE.js +25229 -0
  33. package/dist/chunk-EX6FQSEV.js +167 -0
  34. package/dist/chunk-F5VZ5EUH.js +1519 -0
  35. package/dist/chunk-FVUDSPOD.js +4977 -0
  36. package/dist/chunk-G6FTZKJX.js +4977 -0
  37. package/dist/chunk-GFEAZN6Y.js +1519 -0
  38. package/dist/chunk-HKV4FQFW.js +1519 -0
  39. package/dist/chunk-ICCPULDT.js +25217 -0
  40. package/dist/chunk-IYEM627Q.js +25216 -0
  41. package/dist/chunk-JHRJ4QJ6.js +1519 -0
  42. package/dist/chunk-K2DAUYHV.js +4977 -0
  43. package/dist/chunk-KDQDSZZQ.js +4973 -0
  44. package/dist/chunk-LDUD6AZY.js +1519 -0
  45. package/dist/chunk-LES5TJ5L.js +4909 -0
  46. package/dist/chunk-MJGGW6MC.js +106 -0
  47. package/dist/chunk-MQKIWAHQ.js +106 -0
  48. package/dist/chunk-NGA7BBPF.js +48 -0
  49. package/dist/chunk-OE3TI4IQ.js +1519 -0
  50. package/dist/chunk-OHSBIYDR.js +4977 -0
  51. package/dist/chunk-OZEYDEPB.js +1519 -0
  52. package/dist/chunk-P4PODSQH.js +1519 -0
  53. package/dist/chunk-P7UOSFIE.js +636 -0
  54. package/dist/chunk-PFN6DODU.js +4921 -0
  55. package/dist/chunk-PKDVM4IY.js +4917 -0
  56. package/dist/chunk-Q5KG3G7U.js +25115 -0
  57. package/dist/chunk-QMVNW4FJ.js +25229 -0
  58. package/dist/chunk-QZ5UPRBE.js +4977 -0
  59. package/dist/chunk-SPP23N42.js +4977 -0
  60. package/dist/chunk-SRGHNFOY.js +4921 -0
  61. package/dist/chunk-TPLVQFXM.js +2594 -0
  62. package/dist/chunk-U3XYF4QP.js +4977 -0
  63. package/dist/chunk-VRRJH2DY.js +4921 -0
  64. package/dist/chunk-WY42BS3F.js +1519 -0
  65. package/dist/chunk-XAA4VHHZ.js +1519 -0
  66. package/dist/chunk-Z5Y5KTPC.js +4977 -0
  67. package/dist/chunk-ZA4QRACH.js +4977 -0
  68. package/dist/chunk-ZHLGSTXF.js +4909 -0
  69. package/dist/cli-agent-26BUULHZ.js +2169 -0
  70. package/dist/cli-agent-2FLJWXOC.js +2169 -0
  71. package/dist/cli-agent-4NNQFLO6.js +2255 -0
  72. package/dist/cli-agent-5WV3EEPW.js +2252 -0
  73. package/dist/cli-agent-65JUT6DU.js +2193 -0
  74. package/dist/cli-agent-6HLL7A5K.js +2255 -0
  75. package/dist/cli-agent-CZ26QWUZ.js +2210 -0
  76. package/dist/cli-agent-HPVSWDNQ.js +2255 -0
  77. package/dist/cli-agent-K4SBVG5X.js +2210 -0
  78. package/dist/cli-agent-K5D424X2.js +2252 -0
  79. package/dist/cli-agent-U4OL5FGK.js +2210 -0
  80. package/dist/cli-agent-WUMPOIKQ.js +2169 -0
  81. package/dist/cli-agent-WWRGGJ2F.js +2255 -0
  82. package/dist/cli-agent-ZDBBTVGU.js +2193 -0
  83. package/dist/cli-agent-ZIZ5JP4O.js +2252 -0
  84. package/dist/cli-recover-I4KNR2OI.js +487 -0
  85. package/dist/cli-recover-IQTUKWR2.js +487 -0
  86. package/dist/cli-recover-OYJHELOR.js +487 -0
  87. package/dist/cli-recover-PVQC7UXB.js +487 -0
  88. package/dist/cli-recover-T32NABFA.js +487 -0
  89. package/dist/cli-serve-FTQJ3RUK.js +143 -0
  90. package/dist/cli-serve-G4PUCASH.js +143 -0
  91. package/dist/cli-serve-HBZYUUQ3.js +143 -0
  92. package/dist/cli-serve-L3NUROMO.js +143 -0
  93. package/dist/cli-serve-LAA5WIZK.js +143 -0
  94. package/dist/cli-serve-LV4TUSJD.js +143 -0
  95. package/dist/cli-serve-MFCTVA2L.js +140 -0
  96. package/dist/cli-serve-QCRUFI5B.js +143 -0
  97. package/dist/cli-serve-S7OGQN4P.js +143 -0
  98. package/dist/cli-serve-SI4BQRXT.js +140 -0
  99. package/dist/cli-serve-UNB7EHN4.js +143 -0
  100. package/dist/cli-serve-UV3GVDRD.js +143 -0
  101. package/dist/cli-serve-V5QICXR5.js +143 -0
  102. package/dist/cli-serve-VG6Z6GIB.js +143 -0
  103. package/dist/cli-serve-XSYHPGZI.js +143 -0
  104. package/dist/cli-serve-Y534FCRV.js +140 -0
  105. package/dist/cli-verify-CZIITRED.js +149 -0
  106. package/dist/cli-verify-N73GOKEF.js +149 -0
  107. package/dist/cli-verify-QEEBZOUZ.js +149 -0
  108. package/dist/cli-verify-RC5HI6DU.js +149 -0
  109. package/dist/cli-verify-VKBNIEAX.js +149 -0
  110. package/dist/cli.js +5 -5
  111. package/dist/dashboard/app.js +8 -2
  112. package/dist/dashboard/components/org-switcher.js +5 -1
  113. package/dist/dashboard/org-switcher.js +156 -0
  114. package/dist/dashboard/pages/login.js +160 -4
  115. package/dist/dashboard/pages/task-pipeline.js +1 -1
  116. package/dist/factory-3IWXVE37.js +9 -0
  117. package/dist/factory-5M6PTMLC.js +11 -0
  118. package/dist/factory-CSSHN7GE.js +11 -0
  119. package/dist/factory-JFWXTAWK.js +11 -0
  120. package/dist/factory-TBGUYM5X.js +9 -0
  121. package/dist/google-W5AYGNUJ.js +33 -0
  122. package/dist/index.js +6 -6
  123. package/dist/meetings-FJ453ENF.js +12 -0
  124. package/dist/postgres-BCHZWRU3.js +832 -0
  125. package/dist/postgres-BI4QVRM6.js +825 -0
  126. package/dist/postgres-BOTHOPDW.js +875 -0
  127. package/dist/postgres-JBUKR3TA.js +873 -0
  128. package/dist/postgres-Z7QYSU6K.js +861 -0
  129. package/dist/routes-7QYAQTWA.js +90 -0
  130. package/dist/routes-JCBVZU54.js +90 -0
  131. package/dist/routes-KEDEJFRE.js +90 -0
  132. package/dist/routes-WI64ADVH.js +90 -0
  133. package/dist/routes-X36OSCID.js +90 -0
  134. package/dist/runtime-75XR6KEW.js +45 -0
  135. package/dist/runtime-BNM7ZNNL.js +45 -0
  136. package/dist/runtime-ES6WCJ7D.js +45 -0
  137. package/dist/runtime-KYJTML2B.js +45 -0
  138. package/dist/runtime-LO67ZHQA.js +45 -0
  139. package/dist/runtime-VIXKKVSZ.js +45 -0
  140. package/dist/runtime-WHWJPCGK.js +45 -0
  141. package/dist/runtime-Z2Q6GUHH.js +45 -0
  142. package/dist/runtime-ZZ6CALSB.js +45 -0
  143. package/dist/server-27A4WEJC.js +28 -0
  144. package/dist/server-2CBXP4WS.js +28 -0
  145. package/dist/server-4JQAB5R4.js +28 -0
  146. package/dist/server-6BOM5U64.js +28 -0
  147. package/dist/server-FLJKNPRD.js +28 -0
  148. package/dist/server-HMIHIQ2N.js +28 -0
  149. package/dist/server-KIXXLR2D.js +28 -0
  150. package/dist/server-KSEIZTXF.js +28 -0
  151. package/dist/server-MPVW7DKZ.js +28 -0
  152. package/dist/server-PRTVRQ2D.js +28 -0
  153. package/dist/server-SYIG6HAX.js +28 -0
  154. package/dist/server-U32KDIXC.js +28 -0
  155. package/dist/server-WFN6CA4T.js +28 -0
  156. package/dist/server-XQUE3FGT.js +28 -0
  157. package/dist/server-XWT2UORK.js +28 -0
  158. package/dist/server-Y3BGNN5Q.js +28 -0
  159. package/dist/setup-352L2TPS.js +20 -0
  160. package/dist/setup-4MM645XK.js +20 -0
  161. package/dist/setup-5JPWW6IP.js +20 -0
  162. package/dist/setup-CUN6LVUV.js +20 -0
  163. package/dist/setup-D3YHPWPY.js +20 -0
  164. package/dist/setup-D4A5I6UM.js +20 -0
  165. package/dist/setup-DOPLXTB3.js +20 -0
  166. package/dist/setup-E3NSIM6B.js +20 -0
  167. package/dist/setup-E3V2D7NL.js +20 -0
  168. package/dist/setup-FSYPGI2C.js +20 -0
  169. package/dist/setup-G3RPKRG3.js +20 -0
  170. package/dist/setup-KJ77HNWK.js +20 -0
  171. package/dist/setup-LPSOY5V5.js +20 -0
  172. package/dist/setup-N3ODDSQE.js +20 -0
  173. package/dist/setup-NLDM3M2P.js +20 -0
  174. package/dist/setup-SWJMNDWF.js +20 -0
  175. package/dist/system-prompts-6OUTAMH6.js +41 -0
  176. package/dist/task-queue-YP2I54IA.js +9 -0
  177. package/dist/telegram-QRNGRT5M.js +17 -0
  178. package/dist/whatsapp-VYVINCGV.js +31 -0
  179. package/god_is_great.html +35 -0
  180. package/package.json +1 -1
  181. package/src/agent-tools/index.ts +4 -1
  182. package/src/agent-tools/tool-resolver.ts +15 -4
  183. package/src/agent-tools/tools/browser.ts +2 -2
  184. package/src/agent-tools/tools/local/dependency-manager.ts +286 -0
  185. package/src/agent-tools/tools/local/index.ts +3 -0
  186. package/src/agent-tools/tools/messaging/telegram.ts +29 -0
  187. package/src/agent-tools/tools/messaging/whatsapp.ts +59 -4
  188. package/src/auth/routes.ts +1 -1
  189. package/src/cli-agent.ts +47 -6
  190. package/src/cli-serve.ts +2 -5
  191. package/src/dashboard/app.js +8 -2
  192. package/src/dashboard/components/org-switcher.js +5 -1
  193. package/src/dashboard/pages/login.js +160 -4
  194. package/src/dashboard/pages/task-pipeline.js +1 -1
  195. package/src/db/adapter.ts +2 -0
  196. package/src/db/factory.ts +78 -0
  197. package/src/db/postgres.ts +57 -12
  198. package/src/engine/agent-autonomy.ts +1 -1
  199. package/src/engine/agent-heartbeat.ts +1 -1
  200. package/src/engine/messaging-poller.ts +146 -11
  201. package/src/engine/oauth-connect-routes.ts +23 -3
  202. package/src/engine/routes.ts +1 -1
  203. package/src/engine/task-poller.ts +54 -3
  204. package/src/engine/task-queue.ts +30 -0
  205. package/src/runtime/index.ts +2 -1
  206. package/src/runtime/types.ts +2 -0
  207. package/src/server.ts +13 -1
  208. package/src/system-prompts/triage.ts +1 -1
@@ -51,7 +51,7 @@ async function findVaultEntryByName(
51
51
 
52
52
  // ─── Route Factory ──────────────────────────────────────
53
53
 
54
- export function createOAuthConnectRoutes(vault: SecureVault, lifecycle?: any) {
54
+ export function createOAuthConnectRoutes(vault: SecureVault, lifecycle?: any, getAdminDb?: () => any) {
55
55
  const router = new Hono();
56
56
 
57
57
  // ─── GET /authorize/:skillId — Start OAuth flow ─────
@@ -211,7 +211,7 @@ export function createOAuthConnectRoutes(vault: SecureVault, lifecycle?: any) {
211
211
  const managed = lifecycle.getAgent(state);
212
212
  console.log(`[OAuth callback] state=${state}, lifecycle exists=${!!lifecycle}, agent found=${!!managed}, emailStatus=${managed?.config?.emailConfig?.status}`);
213
213
  if (managed?.config?.emailConfig?.status === 'awaiting_oauth' || managed?.config?.emailConfig?.status === 'connected') {
214
- return await handleAgentEmailOAuthCallback(c, state, code, managed, lifecycle);
214
+ return await handleAgentEmailOAuthCallback(c, state, code, managed, lifecycle, getAdminDb);
215
215
  }
216
216
  } else {
217
217
  console.log(`[OAuth callback] state=${state}, lifecycle is null/undefined`);
@@ -436,8 +436,28 @@ export function createOAuthConnectRoutes(vault: SecureVault, lifecycle?: any) {
436
436
 
437
437
  // ─── Agent Email OAuth Callback Handler ─────────────────
438
438
 
439
- async function handleAgentEmailOAuthCallback(c: any, agentId: string, code: string, managed: any, lifecycle: any) {
439
+ async function handleAgentEmailOAuthCallback(c: any, agentId: string, code: string, managed: any, lifecycle: any, _getAdminDb?: () => any) {
440
440
  const emailConfig = managed.config.emailConfig;
441
+
442
+ // If client secret is missing, try to inherit from org-level email config
443
+ if (!emailConfig.oauthClientSecret && _getAdminDb) {
444
+ try {
445
+ const adminDb = _getAdminDb();
446
+ if (adminDb?.getSettings) {
447
+ const settings = await adminDb.getSettings();
448
+ if (settings?.orgEmailConfig?.oauthClientSecret && settings.orgEmailConfig.provider === emailConfig.oauthProvider) {
449
+ emailConfig.oauthClientSecret = settings.orgEmailConfig.oauthClientSecret;
450
+ if (!emailConfig.oauthClientId && settings.orgEmailConfig.oauthClientId) {
451
+ emailConfig.oauthClientId = settings.orgEmailConfig.oauthClientId;
452
+ }
453
+ console.log('[OAuth callback] Inherited org-level client credentials for agent', agentId);
454
+ }
455
+ }
456
+ } catch (e) {
457
+ console.error('[OAuth callback] Failed to inherit org email config:', e);
458
+ }
459
+ }
460
+
441
461
  try {
442
462
  if (emailConfig.oauthProvider === 'microsoft') {
443
463
  const tokenRes = await fetch(`https://login.microsoftonline.com/${emailConfig.oauthTenantId || 'common'}/oauth2/v2.0/token`, {
@@ -323,7 +323,7 @@ engine.route('/policies', createPolicyImportRoutes(policyImporter));
323
323
  engine.route('/knowledge-contribution', createKnowledgeContributionRoutes(knowledgeContribution, { lifecycle }));
324
324
  engine.route('/knowledge-import', createKnowledgeImportRoutes(knowledgeImport));
325
325
  engine.route('/skill-updates', createSkillUpdaterRoutes(skillUpdater));
326
- engine.route('/oauth', createOAuthConnectRoutes(vault, lifecycle));
326
+ engine.route('/oauth', createOAuthConnectRoutes(vault, lifecycle, () => _adminDb));
327
327
  engine.route('/org-integrations', createOrgIntegrationRoutes(orgIntegrations));
328
328
 
329
329
  // Database Access system
@@ -107,6 +107,15 @@ export class TaskPoller {
107
107
 
108
108
  try {
109
109
  const now = Date.now();
110
+
111
+ // Sync from database first — ensures we catch tasks that were reset, added externally,
112
+ // or survived a process restart. This is the enterprise-grade approach.
113
+ try {
114
+ await this.deps.taskQueue.syncFromDb?.();
115
+ } catch (syncErr: any) {
116
+ this.log('DB sync warning (non-fatal):', syncErr.message);
117
+ }
118
+
110
119
  const activeTasks = this.deps.taskQueue.getActiveTasks();
111
120
  checked = activeTasks.length;
112
121
 
@@ -256,6 +265,27 @@ export class TaskPoller {
256
265
  }
257
266
  }
258
267
 
268
+ // Session not found or gone — this means a crash/restart happened
269
+ if (task.sessionId) {
270
+ this.log(`Task ${task.id.slice(0, 8)}: session ${task.sessionId} is DEAD (agent crash/restart)`);
271
+ await taskQueue.updateTask(task.id, {
272
+ status: 'assigned',
273
+ sessionId: null as any,
274
+ activityLog: [
275
+ ...task.activityLog,
276
+ {
277
+ ts: new Date().toISOString(),
278
+ type: 'crash',
279
+ agent: 'task-poller',
280
+ detail: `Session ${task.sessionId} died (agent crash/restart). Reason: ${reason}. Recovering...`,
281
+ previousStatus: task.status,
282
+ retryCount: (this.retries.get(task.id)?.count ?? 0) + 1,
283
+ nextRetryAt: new Date(Date.now() + 5000).toISOString(),
284
+ },
285
+ ],
286
+ });
287
+ }
288
+
259
289
  // Strategy 2: Check if agent has ANY active session to route to
260
290
  const activeSessions = sessionRouter.getActiveSessions(agentId);
261
291
  const chatSession = activeSessions.find(s => s.type === 'chat' || s.type === 'task');
@@ -278,22 +308,43 @@ export class TaskPoller {
278
308
  }
279
309
 
280
310
  // Strategy 3: Spawn a new session
281
- this.log(`Task ${task.id}: spawning new session`);
311
+ this.log(`Task ${task.id.slice(0, 8)}: spawning new session`);
282
312
  try {
283
313
  const sessionId = await spawnForTask(task);
284
314
  if (sessionId) {
315
+ const retryCount = (this.retries.get(task.id)?.count ?? 0) + 1;
285
316
  await taskQueue.updateTask(task.id, {
286
317
  status: 'in_progress',
287
318
  sessionId,
319
+ startedAt: new Date().toISOString(),
288
320
  activityLog: [
289
321
  ...task.activityLog,
290
- { ts: new Date().toISOString(), type: 'note', agent: 'task-poller', detail: `Spawned recovery session ${sessionId}: ${reason}` },
322
+ {
323
+ ts: new Date().toISOString(),
324
+ type: 'recovery',
325
+ agent: 'task-poller',
326
+ detail: `Recovery session spawned (attempt ${retryCount}/${this.maxRetries}): ${reason}`,
327
+ sessionId,
328
+ retryCount,
329
+ },
291
330
  ],
292
331
  });
293
332
  return true;
294
333
  }
295
334
  } catch (e: any) {
296
- this.log(`Failed to spawn session for task ${task.id}:`, e.message);
335
+ this.log(`Failed to spawn session for task ${task.id.slice(0, 8)}:`, e.message);
336
+ // Log the failure
337
+ await taskQueue.updateTask(task.id, {
338
+ activityLog: [
339
+ ...task.activityLog,
340
+ {
341
+ ts: new Date().toISOString(),
342
+ type: 'error',
343
+ agent: 'task-poller',
344
+ detail: `Recovery spawn failed: ${e.message}. Will retry in ~${Math.round(this.intervalMs / 1000)}s.`,
345
+ },
346
+ ],
347
+ }).catch(() => {});
297
348
  }
298
349
 
299
350
  return false;
@@ -194,6 +194,36 @@ export class TaskQueueManager {
194
194
  this.initialized = true;
195
195
  }
196
196
 
197
+ /**
198
+ * Sync active tasks from database into memory.
199
+ * Called by the task poller before each cycle to catch externally-added or reset tasks.
200
+ */
201
+ async syncFromDb(): Promise<void> {
202
+ if (!this.db) return;
203
+ try {
204
+ const rows = await this.db.all(
205
+ `SELECT * FROM task_pipeline WHERE status IN ('created','assigned','in_progress') ORDER BY created_at DESC LIMIT 200`
206
+ );
207
+ if (!rows) return;
208
+ let added = 0;
209
+ for (const row of rows) {
210
+ const existing = this.tasks.get(row.id);
211
+ const dbTask = this.rowToTask(row);
212
+ if (!existing) {
213
+ // New task not in memory — add it
214
+ this.tasks.set(row.id, dbTask);
215
+ added++;
216
+ } else if (existing.status !== dbTask.status || existing.sessionId !== dbTask.sessionId) {
217
+ // Status changed externally (e.g., reset after crash) — update in memory
218
+ this.tasks.set(row.id, dbTask);
219
+ }
220
+ }
221
+ if (added > 0) console.log(`[TaskQueue] syncFromDb: added ${added} tasks from DB`);
222
+ } catch (e: any) {
223
+ console.error('[TaskQueue] syncFromDb error:', e.message);
224
+ }
225
+ }
226
+
197
227
  // ─── CRUD ─────────────────────────────────────────────
198
228
 
199
229
  async createTask(opts: {
@@ -413,7 +413,8 @@ export class AgentRuntime {
413
413
  }
414
414
  }
415
415
 
416
- this.runSessionLoop(session.id, agentConfig, [{ role: 'user', content: opts.message }], apiKey);
416
+ const initialContent = opts.messageContent || opts.message;
417
+ this.runSessionLoop(session.id, agentConfig, [{ role: 'user', content: initialContent }], apiKey);
417
418
 
418
419
  return session;
419
420
  }
@@ -230,6 +230,8 @@ export interface SpawnOptions {
230
230
  agentId: string;
231
231
  orgId?: string;
232
232
  message: string;
233
+ /** Multimodal content blocks (images + text). When provided, overrides `message` for the initial user turn. */
234
+ messageContent?: any[];
233
235
  model?: ModelConfig;
234
236
  systemPrompt?: string;
235
237
  tools?: AnyAgentTool[];
package/src/server.ts CHANGED
@@ -299,6 +299,13 @@ export function createServer(config: ServerConfig): ServerInstance {
299
299
  return c.json({ error: 'Access denied: you can only access your assigned organization' }, 403);
300
300
  }
301
301
 
302
+ // INJECT clientOrgId when no orgId is specified — ensures downstream queries are always scoped
303
+ // Store for downstream handlers; also override userOrgId so audit/filtering uses client org
304
+ if (!requestedOrg) {
305
+ c.set('enforcedOrgId', clientOrgId);
306
+ c.set('userOrgId', clientOrgId);
307
+ }
308
+
302
309
  // Block org listing — only return their own org
303
310
  const path = c.req.path;
304
311
  if (path === '/api/organizations' && c.req.method === 'GET') {
@@ -469,7 +476,12 @@ export function createServer(config: ServerConfig): ServerInstance {
469
476
  if ((c as any)._decryptedBody !== undefined) {
470
477
  subBody = JSON.stringify((c as any)._decryptedBody);
471
478
  } else {
472
- subBody = c.req.raw.body;
479
+ try {
480
+ // Clone the body to avoid "disturbed or locked" errors
481
+ subBody = c.req.raw.bodyUsed ? null : c.req.raw.body;
482
+ } catch {
483
+ subBody = null;
484
+ }
473
485
  }
474
486
  }
475
487
  const subReq = new Request(new URL(subPath, 'http://localhost'), {
@@ -22,7 +22,7 @@ Good morning! Here's what accumulated while you were off:
22
22
  - ${ctx.failedChats} chat message(s) may be unanswered
23
23
 
24
24
  Your morning routine:
25
- 1. Check your inbox with gmail_list (unread only) — scan subjects and senders
25
+ 1. Check your inbox with gmail_search (unread only) — scan subjects and senders
26
26
  2. For each important email, create a Google Task: google_tasks_create with title, notes, and priority
27
27
  3. Check Google Chat for any unanswered messages: google_chat_list_messages
28
28
  4. For any failed sessions that look important, add them as tasks too