@sentry/junior 0.206.0 → 0.208.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/dist/{agent-C9yuiZUF.js → agent-BfxfHsf1.js} +375 -346
  2. package/dist/{agent-hooks-DNjlz2A-.js → agent-hooks-CuGjLjmR.js} +224 -97
  3. package/dist/{agent-runner-E67lFrDG.js → agent-runner-Dz1PMKP0.js} +9 -9
  4. package/dist/api/schema.d.ts +39 -39
  5. package/dist/api/schema.js +2 -2
  6. package/dist/api.d.ts +1 -1
  7. package/dist/api.js +154 -154
  8. package/dist/{app-AxGmJHwK.d.ts → app-DfNrn_gS.d.ts} +2 -2
  9. package/dist/app.d.ts +1 -1
  10. package/dist/app.js +185 -183
  11. package/dist/{auth-pause-state-MVZ6xvEK.js → auth-pause-state-Bjoh8wCy.js} +7 -7
  12. package/dist/{briefs-CvJFQvhJ.js → briefs-q_onrGmf.js} +3 -3
  13. package/dist/{catalog-runtime-TBR8n4e1.js → catalog-runtime-D8YUMNhb.js} +1 -1
  14. package/dist/{checkpoint-BY47jJCB.js → checkpoint-FKMcINix.js} +8 -8
  15. package/dist/cli/chat.js +13 -13
  16. package/dist/cli/check.js +3 -3
  17. package/dist/cli/main.js +1 -1
  18. package/dist/cli/plugins.js +3 -3
  19. package/dist/cli/snapshot-create.js +3 -3
  20. package/dist/cli/upgrade.d.ts +1 -1
  21. package/dist/cli/upgrade.js +3 -3
  22. package/dist/{client-ceE7NtvC.js → client-bRyPqwAV.js} +4 -4
  23. package/dist/{config-CIE83sR2.js → config-EtF2uEaW.js} +6 -6
  24. package/dist/{context-B45_WqVX.js → context-Bplcgypl.js} +13 -13
  25. package/dist/{conversation-privacy-Auyq26XQ.js → conversation-privacy-whGaV2TG.js} +1 -1
  26. package/dist/{credential-sync-BO33aNQd.js → credential-sync-DM-EE1ey.js} +21 -21
  27. package/dist/{db-BeyXKJOI.d.ts → db-D74z7BZH.d.ts} +1 -1
  28. package/dist/{execution-stats-SiS2FLcv.js → execution-stats-C-f8zwMU.js} +77 -77
  29. package/dist/{executor-BfbYPW63.js → executor-BW5qp0jC.js} +43 -14
  30. package/dist/instrumentation.js +2 -2
  31. package/dist/{job-queue-CyTc24Es.js → job-queue-BIHNIEIX.js} +1 -1
  32. package/dist/{logging-D37bayDc.js → logging-sNS84Yuu.js} +1 -1
  33. package/dist/nitro.d.ts +1 -1
  34. package/dist/nitro.js +3 -3
  35. package/dist/{oauth-callback-server-BtfOeHTZ.js → oauth-callback-server-Co6D_yXP.js} +2 -2
  36. package/dist/{pending-auth-BPUzcs7n.js → pending-auth-CRJCt9Ux.js} +2 -2
  37. package/dist/{profile-CSixooTi.js → profile-BfLMVhWo.js} +4 -4
  38. package/dist/{prompt-3gqNY1Ka.js → prompt-x-0ZtTyb.js} +14 -14
  39. package/dist/{registry-DiR0-xRg.js → registry-Cyww_jnC.js} +2 -2
  40. package/dist/{resolve-Bn5q__9b.js → resolve-BApIFQXX.js} +2 -2
  41. package/dist/{runner-DFx3dIJH.js → runner-C9okx4GL.js} +10 -10
  42. package/dist/{sandbox-egress-signals-bwvjihxA.js → sandbox-egress-signals-BHfx0esj.js} +1 -1
  43. package/dist/{schema-8GXFfclK.js → schema-CwTeb-BF.js} +39 -39
  44. package/dist/{skills-BhM5qyCF.js → skills-DhL_wXEp.js} +2 -2
  45. package/dist/{spawn-Dk0PqdH6.js → spawn-msnzfE8_.js} +2 -2
  46. package/dist/{stats-DKRP4rsY.js → stats-Cq5w_Awk.js} +292 -268
  47. package/dist/{store-C5qxF2ac.d.ts → store-Det8MQ9g.d.ts} +1 -1
  48. package/dist/{task-queue-CdpTvu4R.js → task-queue-JfmWmpjS.js} +3 -3
  49. package/dist/{task-runner-alpjVSxQ.js → task-runner-Cm0gXoLH.js} +15 -15
  50. package/dist/{thread-state-CRK7aA41.js → thread-state-lw2QwQ-y.js} +5 -5
  51. package/dist/{turn-execution-XtyzIHog.js → turn-execution-C7K6lQp1.js} +3 -3
  52. package/dist/{turn-lifecycle-VbwZLfBv.js → turn-lifecycle-DVlJLwB0.js} +1 -1
  53. package/dist/{usage-D4A48Bdl.js → usage-BMuAlKIW.js} +2 -2
  54. package/dist/{validation-jn_46o4U.js → validation-BI-r3iQA.js} +1 -1
  55. package/dist/{version-DcfJxB4z.js → version-s6smK6lP.js} +1 -1
  56. package/dist/version.js +1 -1
  57. package/dist/{web-authorization-CsfLSfEs.js → web-authorization-C9MxPvXX.js} +1 -1
  58. package/dist/{web-input-BPp_sc7t.js → web-input-CwVlaLd0.js} +7 -109
  59. package/dist/{work-Di-ubSGg.js → work-BK0W1QAt.js} +9 -9
  60. package/dist/{worker-Cu_D5Mr8.js → worker-D-WWKHQD.js} +5 -5
  61. package/migrations/0041_automation_outcomes_backfill.sql +27 -0
  62. package/migrations/meta/0041_snapshot.json +3516 -0
  63. package/migrations/meta/_journal.json +7 -0
  64. package/package.json +5 -5
@@ -1,16 +1,16 @@
1
- import { F as isRecord$1, I as toOptionalNumber, L as toOptionalString } from "./logging-D37bayDc.js";
2
- import { a as getChatConfig } from "./config-CIE83sR2.js";
3
- import { _ as parseSlackMessageTs, d as parseStoredSlackActor, h as parseSlackTeamId, p as parseSlackChannelId } from "./context-B45_WqVX.js";
4
- import { Ft as getConversationStore, It as getDb, J as withSlackRetries, Qt as sameDestination, U as getSlackClient, Xt as parseDestination, pt as JUNIOR_THREAD_STATE_TTL_MS, u as getPlugins } from "./agent-hooks-DNjlz2A-.js";
1
+ import { F as isRecord$1, I as toOptionalNumber, L as toOptionalString } from "./logging-sNS84Yuu.js";
2
+ import { a as getChatConfig } from "./config-EtF2uEaW.js";
3
+ import { _ as parseSlackMessageTs, d as parseStoredSlackActor, h as parseSlackTeamId, p as parseSlackChannelId } from "./context-Bplcgypl.js";
4
+ import { Gt as getDb, J as withSlackRetries, U as getSlackClient, Wt as getConversationStore, an as parseDestination, pt as JUNIOR_THREAD_STATE_TTL_MS, sn as sameDestination, u as getPlugins } from "./agent-hooks-CuGjLjmR.js";
5
5
  import { n as juniorDestinations } from "./destinations-BeBiJeEM.js";
6
- import { S as juniorAttachments, a as juniorSchedulerRuns, c as juniorStats, l as juniorEventTasks, o as juniorSchedulerTasks, w as juniorConversations } from "./executor-BfbYPW63.js";
7
- import { o as ToolInputError } from "./usage-D4A48Bdl.js";
8
- import { C as getDefaultRedisStateAdapterFor, w as getStateAdapter } from "./profile-CSixooTi.js";
6
+ import { S as juniorAttachments, a as juniorSchedulerRuns, c as juniorStats, l as juniorEventAutomations, o as juniorSchedulerTasks, w as juniorConversations } from "./executor-BW5qp0jC.js";
7
+ import { o as ToolInputError } from "./usage-BMuAlKIW.js";
8
+ import { C as getDefaultRedisStateAdapterFor, w as getStateAdapter } from "./profile-BfLMVhWo.js";
9
9
  import "./vercel-queue-DIkVcfK4.js";
10
10
  import { z } from "zod";
11
11
  import { createHash, randomUUID } from "node:crypto";
12
12
  import { and, asc, desc, eq, gte, inArray, isNotNull, isNull, lte, ne, notInArray, or, sql } from "drizzle-orm";
13
- import { actorUserIdSchema, destinationSchema, destinationVisibilitySchema, normalizeResourceEventIdentifier, resourceEventMatchSchema, resourceEventMatches, resourceEventTypeSchema, slackDestinationSchema, taskOutcomeSchema } from "@sentry/junior-plugin-api";
13
+ import { actorUserIdSchema, destinationSchema, destinationVisibilitySchema, eventMatchSchema, eventMatches, eventTypeSchema, normalizeEventIdentifier, slackDestinationSchema, taskOutcomeSchema } from "@sentry/junior-plugin-api";
14
14
  //#region src/chat/state/turn-id.ts
15
15
  /** Build a stable turn identifier from a message ID. */
16
16
  function buildDeterministicTurnId(messageId) {
@@ -109,7 +109,7 @@ const inboundMessageSourceSchema = z.enum([
109
109
  "internal",
110
110
  "local",
111
111
  "plugin",
112
- "resource_event",
112
+ "event",
113
113
  "scheduler",
114
114
  "slack",
115
115
  "web"
@@ -583,7 +583,7 @@ async function writeConversation(state, lock, conversation) {
583
583
  ...next,
584
584
  execution: {
585
585
  ...next.execution,
586
- pendingMessages: next.execution.pendingMessages.map((message) => storeMessage(message, hasSlackDestination && (message.source === "slack" || message.source === "resource_event" || message.source === "plugin" || message.source === "scheduler")))
586
+ pendingMessages: next.execution.pendingMessages.map((message) => storeMessage(message, hasSlackDestination && (message.source === "slack" || message.source === "event" || message.source === "plugin" || message.source === "scheduler")))
587
587
  }
588
588
  };
589
589
  await state.set(conversationKey(next.conversationId), stored, JUNIOR_THREAD_STATE_TTL_MS);
@@ -1445,43 +1445,43 @@ async function listActiveConversationIds(args = {}) {
1445
1445
  return await listActiveConversationIds$1(args);
1446
1446
  }
1447
1447
  //#endregion
1448
- //#region src/chat/resource-events/catalog.ts
1449
- /** Core-owned resource-event namespace. Not a plugin publisher. */
1450
- const CORE_RESOURCE_EVENT_NAMESPACE = "junior";
1448
+ //#region src/chat/events/catalog.ts
1449
+ /** Core-owned event namespace. Not a plugin publisher. */
1450
+ const CORE_EVENT_NAMESPACE = "junior";
1451
1451
  /** True when the catalog has any enabled registration. */
1452
- function hasResourceEventCatalogEntries(catalog) {
1452
+ function hasEventCatalogEntries(catalog) {
1453
1453
  return Object.keys(catalog).length > 0;
1454
1454
  }
1455
1455
  /**
1456
1456
  * True when at least one plugin namespace is enabled.
1457
1457
  *
1458
1458
  * Core Workspace snapshot events stay in the catalog for search and temporary
1459
- * watches. Durable event tasks still require a plugin publisher.
1459
+ * watches. Durable event automations still require a plugin publisher.
1460
1460
  */
1461
- function hasPluginResourceEventCatalogEntries(catalog) {
1462
- return Object.keys(pluginResourceEventCatalog(catalog)).length > 0;
1461
+ function hasPluginEventCatalogEntries(catalog) {
1462
+ return Object.keys(pluginEventCatalog(catalog)).length > 0;
1463
1463
  }
1464
1464
  /**
1465
- * Catalog entries that durable event tasks may select.
1465
+ * Catalog entries that durable event automations may select.
1466
1466
  *
1467
1467
  * Core Workspace snapshot events only wake temporary watches. Snapshot finish
1468
- * does not run event-task ingest, so those namespaces stay out of create/update
1468
+ * does not run event-automation ingest, so those namespaces stay out of create/update
1469
1469
  * schemas and trigger availability.
1470
1470
  */
1471
- function pluginResourceEventCatalog(catalog) {
1472
- return Object.fromEntries(Object.entries(catalog).filter(([namespace]) => namespace !== CORE_RESOURCE_EVENT_NAMESPACE));
1471
+ function pluginEventCatalog(catalog) {
1472
+ return Object.fromEntries(Object.entries(catalog).filter(([namespace]) => namespace !== CORE_EVENT_NAMESPACE));
1473
1473
  }
1474
1474
  function enumSchema(values, unavailableMessage) {
1475
1475
  if (values.length === 0) return z.string().refine(() => false, unavailableMessage);
1476
1476
  return z.enum(values);
1477
1477
  }
1478
- /** Build the model-facing namespace enum from enabled resource event plugins. */
1478
+ /** Build the model-facing namespace enum from enabled event plugins. */
1479
1479
  function eventNamespaceSchema(catalog) {
1480
- return enumSchema(Object.keys(catalog).sort(), "No resource event namespaces are enabled.");
1480
+ return enumSchema(Object.keys(catalog).sort(), "No event namespaces are enabled.");
1481
1481
  }
1482
1482
  /** Build the model-facing event enum from enabled plugin registrations. */
1483
1483
  function registeredEventTypeSchema(catalog) {
1484
- return enumSchema([...new Set(Object.values(catalog).flatMap((registration) => registration.resourceTypes.flatMap((resourceType) => resourceType.supportedEvents)))].sort(), "No resource event types are enabled.");
1484
+ return enumSchema([...new Set(Object.values(catalog).flatMap((registration) => registration.resourceTypes.flatMap((resourceType) => resourceType.supportedEvents)))].sort(), "No event types are enabled.");
1485
1485
  }
1486
1486
  /** Build the model-facing resource type enum from enabled plugin registrations. */
1487
1487
  function registeredResourceTypeSchema(catalog) {
@@ -1492,22 +1492,22 @@ function pluginSupportsEvent(catalog, namespace, resourceType, eventType) {
1492
1492
  return catalog[namespace]?.resourceTypes.find((candidate) => candidate.type === resourceType)?.supportedEvents.includes(eventType) ?? false;
1493
1493
  }
1494
1494
  /** Return app guidance for one registered resource type and event type. */
1495
- function resourceEventGuidance(catalog, namespace, resourceType, eventType) {
1495
+ function eventGuidance(catalog, namespace, resourceType, eventType) {
1496
1496
  return catalog[namespace]?.resourceTypes.find((candidate) => candidate.type === resourceType)?.guidance?.[eventType];
1497
1497
  }
1498
1498
  /** Return declared match keys for one registered resource type. */
1499
- function resourceEventMatchFields(catalog, namespace, resourceType) {
1499
+ function eventMatchFields(catalog, namespace, resourceType) {
1500
1500
  return catalog[namespace]?.resourceTypes.find((candidate) => candidate.type === resourceType)?.matchFields;
1501
1501
  }
1502
1502
  /** Build the match object the tools accept for one resource type. */
1503
- function registeredResourceEventMatchSchema() {
1504
- return resourceEventMatchSchema.optional().describe("Optional exact values from the resource type matchFields. A single value must equal the event data. A list means the event value may be any one entry. Omit a key to ignore it. Unmatched events are dropped with no agent turn.");
1503
+ function registeredEventMatchSchema() {
1504
+ return eventMatchSchema.optional().describe("Optional exact values from the resource type matchFields. A single value must equal the event data. A list means the event value may be any one entry. Omit a key to ignore it. Unmatched events are dropped with no agent turn.");
1505
1505
  }
1506
1506
  /** Reject match keys the resource type does not list. */
1507
- function requireSupportedResourceEventMatch(catalog, input) {
1507
+ function requireSupportedEventMatch(catalog, input) {
1508
1508
  const match = input.match;
1509
1509
  if (!match || Object.keys(match).length === 0) return void 0;
1510
- const fields = resourceEventMatchFields(catalog, input.namespace, input.resourceType);
1510
+ const fields = eventMatchFields(catalog, input.namespace, input.resourceType);
1511
1511
  if (!fields || Object.keys(fields).length === 0) throw new ToolInputError(`Resource type "${input.namespace}:${input.resourceType}" does not support match.`);
1512
1512
  const normalized = {};
1513
1513
  for (const [key, value] of Object.entries(match)) {
@@ -1529,12 +1529,12 @@ function requireSupportedResourceEventMatch(catalog, input) {
1529
1529
  return Object.keys(normalized).length > 0 ? normalized : void 0;
1530
1530
  }
1531
1531
  /** Normalize one selector with the convention declared by its plugin. */
1532
- function normalizeEventIdentifier(catalog, namespace, identifier) {
1533
- return normalizeResourceEventIdentifier(catalog[namespace], identifier);
1532
+ function normalizeCatalogEventIdentifier(catalog, namespace, identifier) {
1533
+ return normalizeEventIdentifier(catalog[namespace], identifier);
1534
1534
  }
1535
1535
  //#endregion
1536
1536
  //#region src/chat/sandbox/snapshot/events.ts
1537
- const WORKSPACE_SNAPSHOT_NAMESPACE = CORE_RESOURCE_EVENT_NAMESPACE;
1537
+ const WORKSPACE_SNAPSHOT_NAMESPACE = CORE_EVENT_NAMESPACE;
1538
1538
  const WORKSPACE_SNAPSHOT_RESOURCE_TYPE = "workspace_snapshot";
1539
1539
  const WORKSPACE_SNAPSHOT_READY_EVENT = "workspace_snapshot.ready";
1540
1540
  const WORKSPACE_SNAPSHOT_FAILED_EVENT = "workspace_snapshot.failed";
@@ -1544,7 +1544,7 @@ const WORKSPACE_SNAPSHOT_FAILED_EVENT = "workspace_snapshot.failed";
1544
1544
  * Uses the same registration shape as plugins so search, guidance, and tool
1545
1545
  * schemas treat these events like any other resource type.
1546
1546
  */
1547
- function workspaceSnapshotResourceEvents() {
1547
+ function workspaceSnapshotEvents() {
1548
1548
  return { resourceTypes: [{
1549
1549
  type: WORKSPACE_SNAPSHOT_RESOURCE_TYPE,
1550
1550
  supportedEvents: [WORKSPACE_SNAPSHOT_READY_EVENT, WORKSPACE_SNAPSHOT_FAILED_EVENT],
@@ -1588,62 +1588,66 @@ function workspaceSnapshotFinishedEvent(input) {
1588
1588
  return event;
1589
1589
  }
1590
1590
  //#endregion
1591
- //#region src/chat/resource-events/runtime-catalog.ts
1591
+ //#region src/chat/events/runtime-catalog.ts
1592
1592
  /**
1593
- * Enabled resource-event registrations for search, guidance, and tool schemas.
1593
+ * Enabled event registrations for search, guidance, and tool schemas.
1594
1594
  *
1595
1595
  * Includes core Workspace snapshot events under the `junior` namespace, plus
1596
1596
  * every enabled plugin registration. Plugins may not use the `junior` namespace.
1597
1597
  */
1598
- function getResourceEventCatalog() {
1599
- const catalog = { [CORE_RESOURCE_EVENT_NAMESPACE]: workspaceSnapshotResourceEvents() };
1598
+ function getEventCatalog() {
1599
+ const catalog = { [CORE_EVENT_NAMESPACE]: workspaceSnapshotEvents() };
1600
1600
  for (const plugin of getPlugins()) {
1601
- const registration = plugin.resourceEvents;
1601
+ const registration = plugin.events;
1602
1602
  if (!registration || registration.isEnabled?.() === false) continue;
1603
- if (plugin.manifest.name === "junior") throw new Error(`Plugin "${CORE_RESOURCE_EVENT_NAMESPACE}" cannot register resource events; that namespace is reserved for core Workspace snapshots`);
1603
+ if (plugin.manifest.name === "junior") throw new Error(`Plugin "${CORE_EVENT_NAMESPACE}" cannot register events; that namespace is reserved for core Workspace snapshots`);
1604
1604
  catalog[plugin.manifest.name] = registration;
1605
1605
  }
1606
1606
  return catalog;
1607
1607
  }
1608
- /** Validate the persisted Slack creator identity for an event task. */
1609
- const eventTaskPrincipalSchema = z.object({
1608
+ /** Validate the persisted Slack creator identity for an event automation. */
1609
+ const eventAutomationPrincipalSchema = z.object({
1610
1610
  slackUserId: actorUserIdSchema,
1611
1611
  fullName: z.string().optional(),
1612
1612
  userName: z.string().optional()
1613
1613
  }).strict();
1614
- /** Validate one persisted event-task selector and its presentation metadata. */
1615
- const eventTaskTriggerSchema = z.object({
1616
- events: z.array(resourceEventTypeSchema).min(1),
1614
+ /** Validate one persisted event-automation selector and its presentation metadata. */
1615
+ const eventAutomationTriggerSchema = z.object({
1616
+ events: z.array(eventTypeSchema).min(1),
1617
1617
  label: z.string().min(1),
1618
- match: resourceEventMatchSchema.optional(),
1618
+ match: eventMatchSchema.optional(),
1619
1619
  namespace: z.string().min(1),
1620
1620
  identifier: z.string().min(1).max(300),
1621
1621
  resourceType: z.string().min(1)
1622
1622
  }).strict();
1623
- /** Validate one persisted event task. */
1624
- const eventTaskSchema = z.object({
1623
+ /** Validate one persisted event automation. */
1624
+ const eventAutomationSchema = z.object({
1625
1625
  id: z.string().min(1),
1626
1626
  createdAtMs: z.number().finite(),
1627
- createdBy: eventTaskPrincipalSchema,
1627
+ createdBy: eventAutomationPrincipalSchema,
1628
1628
  credentialMode: z.enum(["system", "creator"]),
1629
1629
  destination: slackDestinationSchema,
1630
1630
  destinationVisibility: destinationVisibilitySchema,
1631
- /** Visible effects after successful work. Missing legacy values send a message. */
1632
- outcomes: z.array(taskOutcomeSchema).max(5).optional(),
1631
+ /** Explicit visible effects after successful work. An empty list is silent. */
1632
+ outcomes: z.array(taskOutcomeSchema).max(5),
1633
1633
  task: z.object({ text: z.string().min(1) }).strict(),
1634
- trigger: eventTaskTriggerSchema
1634
+ trigger: eventAutomationTriggerSchema
1635
1635
  }).strict();
1636
1636
  //#endregion
1637
- //#region src/chat/event-tasks/store.ts
1637
+ //#region src/chat/event-automations/store.ts
1638
1638
  /** JSON task payload must not carry SQL-backed columns. */
1639
- function eventTaskJsonPayload(task) {
1639
+ function eventAutomationJsonPayload(task) {
1640
1640
  const { status: _status, title: _title, ...payload } = task;
1641
1641
  return payload;
1642
1642
  }
1643
1643
  function parseTask(row) {
1644
1644
  const raw = row.task && typeof row.task === "object" ? { ...row.task } : row.task;
1645
1645
  if (raw && typeof raw === "object" && "title" in raw) delete raw.title;
1646
- const payload = eventTaskSchema.parse(raw);
1646
+ if (raw && typeof raw === "object" && !("outcomes" in raw) && "destination" in raw) raw.outcomes = [{
1647
+ action: "send_message",
1648
+ destination: raw.destination
1649
+ }];
1650
+ const payload = eventAutomationSchema.parse(raw);
1647
1651
  const title = row.title?.trim();
1648
1652
  return {
1649
1653
  ...payload,
@@ -1651,23 +1655,23 @@ function parseTask(row) {
1651
1655
  ...title ? { title } : void 0
1652
1656
  };
1653
1657
  }
1654
- function activeEventTaskWhere() {
1655
- return ne(juniorEventTasks.status, "deleted");
1658
+ function activeEventAutomationWhere() {
1659
+ return ne(juniorEventAutomations.status, "deleted");
1656
1660
  }
1657
- /** Read one event task by id, including deleted rows when present. */
1658
- async function getEventTask(db, id) {
1661
+ /** Read one event automation by id, including deleted rows when present. */
1662
+ async function getEventAutomation(db, id) {
1659
1663
  const rows = await db.select({
1660
- status: juniorEventTasks.status,
1661
- task: juniorEventTasks.task,
1662
- title: juniorEventTasks.title
1663
- }).from(juniorEventTasks).where(eq(juniorEventTasks.id, id)).limit(1);
1664
+ status: juniorEventAutomations.status,
1665
+ task: juniorEventAutomations.task,
1666
+ title: juniorEventAutomations.title
1667
+ }).from(juniorEventAutomations).where(eq(juniorEventAutomations.id, id)).limit(1);
1664
1668
  return rows[0] ? parseTask(rows[0]) : void 0;
1665
1669
  }
1666
- /** Create one retry-stable event task, or revive a deleted row with the new payload. */
1667
- async function createEventTask(db, task) {
1668
- const parsed = eventTaskSchema.parse(eventTaskJsonPayload(task));
1670
+ /** Create one retry-stable event automation, or revive a deleted row with the new payload. */
1671
+ async function createEventAutomation(db, task) {
1672
+ const parsed = eventAutomationSchema.parse(eventAutomationJsonPayload(task));
1669
1673
  const title = task.title?.trim() || null;
1670
- await db.insert(juniorEventTasks).values({
1674
+ await db.insert(juniorEventAutomations).values({
1671
1675
  id: parsed.id,
1672
1676
  teamId: parsed.destination.teamId,
1673
1677
  namespace: parsed.trigger.namespace,
@@ -1677,118 +1681,118 @@ async function createEventTask(db, task) {
1677
1681
  title,
1678
1682
  task: parsed
1679
1683
  }).onConflictDoNothing();
1680
- const existing = await getEventTask(db, parsed.id);
1684
+ const existing = await getEventAutomation(db, parsed.id);
1681
1685
  if (!existing) return {
1682
1686
  ...parsed,
1683
1687
  status: "active",
1684
1688
  ...title ? { title } : void 0
1685
1689
  };
1686
1690
  if (existing.status !== "deleted") return existing;
1687
- const rows = await db.update(juniorEventTasks).set({
1691
+ const rows = await db.update(juniorEventAutomations).set({
1688
1692
  teamId: parsed.destination.teamId,
1689
1693
  namespace: parsed.trigger.namespace,
1690
1694
  identifier: parsed.trigger.identifier,
1691
1695
  status: "active",
1692
1696
  title,
1693
1697
  task: parsed
1694
- }).where(and(eq(juniorEventTasks.id, parsed.id), eq(juniorEventTasks.status, "deleted"))).returning({
1695
- status: juniorEventTasks.status,
1696
- task: juniorEventTasks.task,
1697
- title: juniorEventTasks.title
1698
+ }).where(and(eq(juniorEventAutomations.id, parsed.id), eq(juniorEventAutomations.status, "deleted"))).returning({
1699
+ status: juniorEventAutomations.status,
1700
+ task: juniorEventAutomations.task,
1701
+ title: juniorEventAutomations.title
1698
1702
  });
1699
- return rows[0] ? parseTask(rows[0]) : await getEventTask(db, parsed.id) ?? {
1703
+ return rows[0] ? parseTask(rows[0]) : await getEventAutomation(db, parsed.id) ?? {
1700
1704
  ...parsed,
1701
1705
  status: "active",
1702
1706
  ...title ? { title } : void 0
1703
1707
  };
1704
1708
  }
1705
- /** Replace an existing non-deleted event task. */
1706
- async function saveEventTask(db, task) {
1707
- const parsed = eventTaskSchema.parse(eventTaskJsonPayload(task));
1709
+ /** Replace an existing non-deleted event automation. */
1710
+ async function saveEventAutomation(db, task) {
1711
+ const parsed = eventAutomationSchema.parse(eventAutomationJsonPayload(task));
1708
1712
  const title = task.title?.trim() || null;
1709
- const rows = await db.update(juniorEventTasks).set({
1713
+ const rows = await db.update(juniorEventAutomations).set({
1710
1714
  namespace: parsed.trigger.namespace,
1711
1715
  identifier: parsed.trigger.identifier,
1712
1716
  title,
1713
1717
  task: parsed
1714
- }).where(and(eq(juniorEventTasks.id, parsed.id), activeEventTaskWhere())).returning({
1715
- status: juniorEventTasks.status,
1716
- task: juniorEventTasks.task,
1717
- title: juniorEventTasks.title
1718
+ }).where(and(eq(juniorEventAutomations.id, parsed.id), activeEventAutomationWhere())).returning({
1719
+ status: juniorEventAutomations.status,
1720
+ task: juniorEventAutomations.task,
1721
+ title: juniorEventAutomations.title
1718
1722
  });
1719
1723
  return rows[0] ? parseTask(rows[0]) : void 0;
1720
1724
  }
1721
- /** Mark one existing event task deleted while retaining the row for history. */
1722
- async function deleteEventTask(db, id) {
1723
- const rows = await db.update(juniorEventTasks).set({ status: "deleted" }).where(and(eq(juniorEventTasks.id, id), activeEventTaskWhere())).returning({
1724
- status: juniorEventTasks.status,
1725
- task: juniorEventTasks.task,
1726
- title: juniorEventTasks.title
1725
+ /** Mark one existing event automation deleted while retaining the row for history. */
1726
+ async function deleteEventAutomation(db, id) {
1727
+ const rows = await db.update(juniorEventAutomations).set({ status: "deleted" }).where(and(eq(juniorEventAutomations.id, id), activeEventAutomationWhere())).returning({
1728
+ status: juniorEventAutomations.status,
1729
+ task: juniorEventAutomations.task,
1730
+ title: juniorEventAutomations.title
1727
1731
  });
1728
1732
  return rows[0] ? parseTask(rows[0]) : void 0;
1729
1733
  }
1730
- /** List live event tasks in one Slack workspace. */
1731
- async function listEventTasksForTeam(db, teamId) {
1734
+ /** List live event automations in one Slack workspace. */
1735
+ async function listEventAutomationsForTeam(db, teamId) {
1732
1736
  return (await db.select({
1733
- status: juniorEventTasks.status,
1734
- task: juniorEventTasks.task,
1735
- title: juniorEventTasks.title
1736
- }).from(juniorEventTasks).where(and(eq(juniorEventTasks.teamId, teamId), activeEventTaskWhere())).orderBy(asc(juniorEventTasks.createdAtMs), asc(juniorEventTasks.id))).map(parseTask);
1737
+ status: juniorEventAutomations.status,
1738
+ task: juniorEventAutomations.task,
1739
+ title: juniorEventAutomations.title
1740
+ }).from(juniorEventAutomations).where(and(eq(juniorEventAutomations.teamId, teamId), activeEventAutomationWhere())).orderBy(asc(juniorEventAutomations.createdAtMs), asc(juniorEventAutomations.id))).map(parseTask);
1737
1741
  }
1738
1742
  function viewerSlackIdentities(user) {
1739
1743
  return user.identities.filter((identity) => identity.provider === "slack" && Boolean(identity.providerTenantId) && Boolean(identity.providerSubjectId));
1740
1744
  }
1741
- /** Return whether one event task was created by a viewer-linked Slack identity. */
1742
- function eventTaskBelongsToUser(task, user) {
1745
+ /** Return whether one event automation was created by a viewer-linked Slack identity. */
1746
+ function eventAutomationBelongsToUser(task, user) {
1743
1747
  return viewerSlackIdentities(user).some((identity) => identity.providerTenantId === task.destination.teamId && identity.providerSubjectId === task.createdBy.slackUserId);
1744
1748
  }
1745
- /** List a bounded newest-first page of live event tasks created by one user. */
1746
- async function listEventTasksCreatedBy(db, user, limit, query) {
1749
+ /** List a bounded newest-first page of live event automations created by one user. */
1750
+ async function listEventAutomationsCreatedBy(db, user, limit, query) {
1747
1751
  const identities = viewerSlackIdentities(user);
1748
- const ownership = or(...identities.map((identity) => and(eq(juniorEventTasks.teamId, identity.providerTenantId), sql`${juniorEventTasks.task}->'createdBy'->>'slackUserId' = ${identity.providerSubjectId}`)));
1752
+ const ownership = or(...identities.map((identity) => and(eq(juniorEventAutomations.teamId, identity.providerTenantId), sql`${juniorEventAutomations.task}->'createdBy'->>'slackUserId' = ${identity.providerSubjectId}`)));
1749
1753
  if (!ownership) return [];
1750
1754
  return (await db.select({
1751
- status: juniorEventTasks.status,
1752
- task: juniorEventTasks.task,
1753
- title: juniorEventTasks.title
1754
- }).from(juniorEventTasks).where(and(ownership, activeEventTaskWhere(), query ? sql`strpos(lower(coalesce(${juniorEventTasks.title}, ${juniorEventTasks.task}->'task'->>'text')), ${query}) > 0` : void 0)).orderBy(desc(juniorEventTasks.createdAtMs), desc(juniorEventTasks.id)).limit(limit)).map(parseTask);
1755
+ status: juniorEventAutomations.status,
1756
+ task: juniorEventAutomations.task,
1757
+ title: juniorEventAutomations.title
1758
+ }).from(juniorEventAutomations).where(and(ownership, activeEventAutomationWhere(), query ? sql`strpos(lower(coalesce(${juniorEventAutomations.title}, ${juniorEventAutomations.task}->'task'->>'text')), ${query}) > 0` : void 0)).orderBy(desc(juniorEventAutomations.createdAtMs), desc(juniorEventAutomations.id)).limit(limit)).map(parseTask);
1755
1759
  }
1756
1760
  /**
1757
- * List deleted event tasks created by one user, newest first.
1758
- * Used only to keep historical runs after the live task list drops the row.
1761
+ * List deleted event automations created by one user, newest first.
1762
+ * Used only to keep historical runs after the live automation list drops the row.
1759
1763
  */
1760
- async function listDeletedEventTasksCreatedBy(db, user, limit) {
1764
+ async function listDeletedEventAutomationsCreatedBy(db, user, limit) {
1761
1765
  const identities = viewerSlackIdentities(user);
1762
- const ownership = or(...identities.map((identity) => and(eq(juniorEventTasks.teamId, identity.providerTenantId), sql`${juniorEventTasks.task}->'createdBy'->>'slackUserId' = ${identity.providerSubjectId}`)));
1766
+ const ownership = or(...identities.map((identity) => and(eq(juniorEventAutomations.teamId, identity.providerTenantId), sql`${juniorEventAutomations.task}->'createdBy'->>'slackUserId' = ${identity.providerSubjectId}`)));
1763
1767
  if (!ownership) return [];
1764
1768
  return (await db.select({
1765
- status: juniorEventTasks.status,
1766
- task: juniorEventTasks.task,
1767
- title: juniorEventTasks.title
1768
- }).from(juniorEventTasks).where(and(ownership, eq(juniorEventTasks.status, "deleted"))).orderBy(desc(juniorEventTasks.createdAtMs), desc(juniorEventTasks.id)).limit(limit)).map(parseTask);
1769
+ status: juniorEventAutomations.status,
1770
+ task: juniorEventAutomations.task,
1771
+ title: juniorEventAutomations.title
1772
+ }).from(juniorEventAutomations).where(and(ownership, eq(juniorEventAutomations.status, "deleted"))).orderBy(desc(juniorEventAutomations.createdAtMs), desc(juniorEventAutomations.id)).limit(limit)).map(parseTask);
1769
1773
  }
1770
- /** List live event tasks whose current Slack destination is public. */
1771
- async function listPublicEventTasksForTeams(db, teamIds, limit, query) {
1774
+ /** List live event automations whose current Slack destination is public. */
1775
+ async function listPublicEventAutomationsForTeams(db, teamIds, limit, query) {
1772
1776
  if (teamIds.length === 0) return [];
1773
1777
  return (await db.select({
1774
- status: juniorEventTasks.status,
1775
- task: juniorEventTasks.task,
1776
- title: juniorEventTasks.title
1777
- }).from(juniorEventTasks).innerJoin(juniorDestinations, and(eq(juniorDestinations.provider, "slack"), eq(juniorDestinations.providerTenantId, juniorEventTasks.teamId), sql`${juniorDestinations.providerDestinationId} = ${juniorEventTasks.task}->'destination'->>'channelId'`)).where(and(inArray(juniorEventTasks.teamId, teamIds), activeEventTaskWhere(), query ? sql`strpos(lower(coalesce(${juniorEventTasks.title}, ${juniorEventTasks.task}->'task'->>'text')), ${query}) > 0` : void 0, eq(juniorDestinations.visibility, "public"))).orderBy(desc(juniorEventTasks.createdAtMs), desc(juniorEventTasks.id)).limit(limit)).map(parseTask);
1778
+ status: juniorEventAutomations.status,
1779
+ task: juniorEventAutomations.task,
1780
+ title: juniorEventAutomations.title
1781
+ }).from(juniorEventAutomations).innerJoin(juniorDestinations, and(eq(juniorDestinations.provider, "slack"), eq(juniorDestinations.providerTenantId, juniorEventAutomations.teamId), sql`${juniorDestinations.providerDestinationId} = ${juniorEventAutomations.task}->'destination'->>'channelId'`)).where(and(inArray(juniorEventAutomations.teamId, teamIds), activeEventAutomationWhere(), query ? sql`strpos(lower(coalesce(${juniorEventAutomations.title}, ${juniorEventAutomations.task}->'task'->>'text')), ${query}) > 0` : void 0, eq(juniorDestinations.visibility, "public"))).orderBy(desc(juniorEventAutomations.createdAtMs), desc(juniorEventAutomations.id)).limit(limit)).map(parseTask);
1778
1782
  }
1779
1783
  /**
1780
- * Collect match keys from live event tasks for these identifiers and event types.
1784
+ * Collect match keys from live event automations for these identifiers and event types.
1781
1785
  * Does not evaluate match values — only reports keys that filters use.
1782
1786
  */
1783
- async function collectEventTaskMatchKeys(db, input) {
1787
+ async function collectEventAutomationMatchKeys(db, input) {
1784
1788
  const eventTypes = new Set(input.eventTypes.map((eventType) => eventType.trim()).filter(Boolean));
1785
1789
  const identifiers = [...new Set(input.identifiers.map((value) => value.trim()).filter(Boolean))];
1786
1790
  if (eventTypes.size === 0 || identifiers.length === 0) return [];
1787
1791
  const rows = await db.select({
1788
- status: juniorEventTasks.status,
1789
- task: juniorEventTasks.task,
1790
- title: juniorEventTasks.title
1791
- }).from(juniorEventTasks).where(and(eq(juniorEventTasks.teamId, input.teamId), eq(juniorEventTasks.namespace, input.namespace), inArray(juniorEventTasks.identifier, identifiers), activeEventTaskWhere())).orderBy(asc(juniorEventTasks.createdAtMs), asc(juniorEventTasks.id));
1792
+ status: juniorEventAutomations.status,
1793
+ task: juniorEventAutomations.task,
1794
+ title: juniorEventAutomations.title
1795
+ }).from(juniorEventAutomations).where(and(eq(juniorEventAutomations.teamId, input.teamId), eq(juniorEventAutomations.namespace, input.namespace), inArray(juniorEventAutomations.identifier, identifiers), activeEventAutomationWhere())).orderBy(asc(juniorEventAutomations.createdAtMs), asc(juniorEventAutomations.id));
1792
1796
  const keys = /* @__PURE__ */ new Set();
1793
1797
  for (const row of rows) {
1794
1798
  const task = parseTask(row);
@@ -1797,45 +1801,35 @@ async function collectEventTaskMatchKeys(db, input) {
1797
1801
  }
1798
1802
  return [...keys].sort();
1799
1803
  }
1800
- /** Find every live task matching one normalized resource event. */
1801
- async function findMatchingEventTasks(db, event, teamId) {
1804
+ /** Find every live task matching one normalized event. */
1805
+ async function findMatchingEventAutomations(db, event, teamId) {
1802
1806
  return (await db.select({
1803
- status: juniorEventTasks.status,
1804
- task: juniorEventTasks.task,
1805
- title: juniorEventTasks.title
1806
- }).from(juniorEventTasks).where(and(eq(juniorEventTasks.teamId, teamId), eq(juniorEventTasks.namespace, event.namespace), eq(juniorEventTasks.identifier, event.identifier), activeEventTaskWhere())).orderBy(asc(juniorEventTasks.createdAtMs), asc(juniorEventTasks.id))).map(parseTask).filter((task) => task.trigger.events.includes(event.eventType) && resourceEventMatches(task.trigger.match, event.data));
1807
+ status: juniorEventAutomations.status,
1808
+ task: juniorEventAutomations.task,
1809
+ title: juniorEventAutomations.title
1810
+ }).from(juniorEventAutomations).where(and(eq(juniorEventAutomations.teamId, teamId), eq(juniorEventAutomations.namespace, event.namespace), eq(juniorEventAutomations.identifier, event.identifier), activeEventAutomationWhere())).orderBy(asc(juniorEventAutomations.createdAtMs), asc(juniorEventAutomations.id))).map(parseTask).filter((task) => task.trigger.events.includes(event.eventType) && eventMatches(task.trigger.match, event.data));
1807
1811
  }
1808
1812
  //#endregion
1809
1813
  //#region src/chat/task-outcomes.ts
1810
- const taskMessageDestinationInputSchema = z.union([slackDestinationSchema, z.object({
1811
- platform: z.literal("slack"),
1812
- teamId: z.string().min(1),
1813
- userId: actorUserIdSchema
1814
- }).strict()]);
1814
+ const taskMessageDestinationInputSchema = z.enum(["current_conversation", "task_creator"]).describe("Where to send the message. Use current_conversation for posts, digests, summaries, and channel reminders. Use task_creator only when the user asks for a direct reminder or notification.");
1815
1815
  /** Input accepted by task authoring tools before a user becomes a DM Destination. */
1816
1816
  const taskOutcomeInputSchema = z.object({
1817
1817
  action: z.literal("send_message"),
1818
1818
  destination: taskMessageDestinationInputSchema
1819
1819
  }).strict();
1820
- /** Resolve tool input to the Slack Destinations stored on a task. */
1820
+ /** Resolve explicit message outcomes to the Slack Destinations stored on an Automation. */
1821
1821
  async function resolveTaskOutcomes(outcomes, currentDestination, creatorSlackUserId) {
1822
- if (outcomes === void 0) return [{
1823
- action: "send_message",
1824
- destination: currentDestination
1825
- }];
1822
+ if (outcomes === void 0) return [];
1826
1823
  const resolved = [];
1827
1824
  for (const outcome of outcomes) {
1828
- if (outcome.destination.teamId !== currentDestination.teamId) throw new Error("Message destinations must be in the current Slack workspace.");
1829
- if ("channelId" in outcome.destination) {
1830
- if (outcome.destination.channelId !== currentDestination.channelId) throw new Error("Messages can only be sent to the current Slack conversation or the task creator.");
1825
+ if (outcome.destination === "current_conversation") {
1831
1826
  resolved.push({
1832
1827
  action: "send_message",
1833
1828
  destination: currentDestination
1834
1829
  });
1835
1830
  continue;
1836
1831
  }
1837
- const userId = outcome.destination.userId;
1838
- if (userId !== creatorSlackUserId) throw new Error("Direct messages can only be sent to the task creator.");
1832
+ const userId = creatorSlackUserId;
1839
1833
  const channelId = (await withSlackRetries(() => getSlackClient().conversations.open({ users: userId }), 3, { action: "conversations.open" })).channel?.id;
1840
1834
  if (!channelId) throw new Error("Slack did not return a direct message destination.");
1841
1835
  resolved.push({
@@ -1852,12 +1846,9 @@ async function resolveTaskOutcomes(outcomes, currentDestination, creatorSlackUse
1852
1846
  function outcomeTargetsDestination(outcome, destination) {
1853
1847
  return outcome.destination.teamId === destination.teamId && outcome.destination.channelId === destination.channelId && (!outcome.destination.threadTs || outcome.destination.threadTs === destination.threadTs);
1854
1848
  }
1855
- /** Return outcomes with legacy same-channel messages bound to the task Destination. */
1849
+ /** Bind same-channel message outcomes to the Automation Destination. */
1856
1850
  function effectiveTaskOutcomes(outcomes, destination) {
1857
- return (outcomes ?? [{
1858
- action: "send_message",
1859
- destination
1860
- }]).map((outcome) => destination.threadTs && outcomeTargetsDestination(outcome, destination) ? {
1851
+ return outcomes.map((outcome) => destination.threadTs && outcomeTargetsDestination(outcome, destination) ? {
1861
1852
  ...outcome,
1862
1853
  destination
1863
1854
  } : outcome);
@@ -1870,53 +1861,66 @@ function moveTaskOutcomes(outcomes, currentDestination, nextDestination) {
1870
1861
  } : outcome);
1871
1862
  }
1872
1863
  //#endregion
1873
- //#region src/chat/event-tasks/tool-support.ts
1874
- const compactEventTaskResultSchema = z.object({
1864
+ //#region src/chat/event-automations/tool-support.ts
1865
+ const compactEventAutomationResultSchema = z.object({
1875
1866
  id: z.string().min(1),
1876
- task: z.string().min(1),
1877
- namespace: z.string().min(1),
1878
- identifier: z.string().min(1),
1879
- resourceType: z.string().min(1),
1880
- label: z.string().min(1),
1881
- events: z.array(z.string().min(1)).min(1),
1882
- match: z.record(z.string(), z.unknown()).optional(),
1867
+ title: z.string().min(1).nullable(),
1868
+ instruction: z.string().min(1),
1869
+ trigger: z.object({
1870
+ namespace: z.string().min(1),
1871
+ identifier: z.string().min(1),
1872
+ resourceType: z.string().min(1),
1873
+ label: z.string().min(1),
1874
+ events: z.array(z.string().min(1)).min(1),
1875
+ match: z.record(z.string(), z.unknown()).optional(),
1876
+ available: z.boolean()
1877
+ }).strict(),
1883
1878
  credentialMode: z.enum(["system", "creator"]),
1884
- outcomes: z.array(taskOutcomeSchema).max(5),
1885
- createdBy: eventTaskPrincipalSchema,
1886
- triggerAvailable: z.boolean()
1879
+ isCreator: z.boolean(),
1880
+ outcomes: z.array(z.object({
1881
+ action: z.literal("send_message"),
1882
+ destination: z.object({
1883
+ channel: z.string().min(1),
1884
+ thread: z.string().min(1).nullable()
1885
+ }).strict()
1886
+ }).strict()).max(5),
1887
+ createdBy: z.object({
1888
+ name: z.string().min(1).nullable(),
1889
+ username: z.string().min(1).nullable()
1890
+ }).strict()
1887
1891
  }).strict();
1888
- /** Validate one successful event-task mutation result. */
1889
- const eventTaskToolResultSchema = juniorToolOutputSchema.extend({ task: compactEventTaskResultSchema }).strict();
1890
- /** Validate one successful event-task list result. */
1891
- const eventTaskListToolResultSchema = juniorToolOutputSchema.extend({
1892
- tasks: z.array(compactEventTaskResultSchema),
1892
+ /** Validate one successful event-automation mutation result. */
1893
+ const eventAutomationToolResultSchema = juniorToolOutputSchema.extend({ automation: compactEventAutomationResultSchema }).strict();
1894
+ /** Validate one successful event-automation list result. */
1895
+ const eventAutomationListToolResultSchema = juniorToolOutputSchema.extend({
1896
+ automations: z.array(compactEventAutomationResultSchema),
1893
1897
  truncated: z.boolean()
1894
1898
  }).strict();
1895
- /** Build the validated resource-event trigger accepted by event-task tools. */
1896
- function registeredEventTaskTriggerSchema(catalog) {
1897
- const plugins = pluginResourceEventCatalog(catalog);
1899
+ /** Build the validated event trigger accepted by event-automation tools. */
1900
+ function registeredEventAutomationTriggerSchema(catalog) {
1901
+ const plugins = pluginEventCatalog(catalog);
1898
1902
  return z.object({
1899
1903
  namespace: eventNamespaceSchema(plugins),
1900
1904
  identifier: z.string().trim().min(1).max(300),
1901
1905
  resourceType: registeredResourceTypeSchema(plugins),
1902
1906
  label: z.string().trim().min(1).max(500),
1903
1907
  events: z.array(registeredEventTypeSchema(plugins)).min(1),
1904
- match: registeredResourceEventMatchSchema()
1908
+ match: registeredEventMatchSchema()
1905
1909
  }).strict();
1906
1910
  }
1907
- /** Reject an event-task trigger that is no longer supported by the catalog. */
1908
- function requireSupportedEventTaskTrigger(catalog, trigger) {
1909
- const plugins = pluginResourceEventCatalog(catalog);
1911
+ /** Reject an event-automation trigger that is no longer supported by the catalog. */
1912
+ function requireSupportedEventAutomationTrigger(catalog, trigger) {
1913
+ const plugins = pluginEventCatalog(catalog);
1910
1914
  for (const eventType of trigger.events) if (!pluginSupportsEvent(plugins, trigger.namespace, trigger.resourceType, eventType)) throw new ToolInputError(`Resource type "${trigger.namespace}:${trigger.resourceType}" does not support event "${eventType}".`);
1911
- return requireSupportedResourceEventMatch(plugins, {
1915
+ return requireSupportedEventMatch(plugins, {
1912
1916
  match: trigger.match,
1913
1917
  namespace: trigger.namespace,
1914
1918
  resourceType: trigger.resourceType
1915
1919
  });
1916
1920
  }
1917
- /** Require the active Slack authority used for event-task management. */
1918
- function requireEventTaskSlackContext(context) {
1919
- if (context.source.kind !== "slack" || context.destination.platform !== "slack" || context.actor?.platform !== "slack" || context.actor.teamId !== context.source.teamId) throw new ToolInputError("Event tasks require an active Slack channel or DM and actor.");
1921
+ /** Require the active Slack authority used for event-automation management. */
1922
+ function requireEventAutomationSlackContext(context) {
1923
+ if (context.source.kind !== "slack" || context.destination.platform !== "slack" || context.actor?.platform !== "slack" || context.actor.teamId !== context.source.teamId) throw new ToolInputError("Event automations require an active Slack channel or DM and actor.");
1920
1924
  return {
1921
1925
  actor: context.actor,
1922
1926
  destination: {
@@ -1928,61 +1932,74 @@ function requireEventTaskSlackContext(context) {
1928
1932
  source: context.source
1929
1933
  };
1930
1934
  }
1931
- /** Return whether an event task belongs to the active Slack destination. */
1932
- function eventTaskMatchesDestination(task, destination) {
1935
+ /** Return whether an event automation belongs to the active Slack destination. */
1936
+ function eventAutomationMatchesDestination(task, destination) {
1933
1937
  return task.destination.teamId === destination.teamId && task.destination.channelId === destination.channelId;
1934
1938
  }
1935
1939
  /**
1936
- * Return whether the active destination may update or delete this task.
1937
- * Same-destination tasks stay local. Public tasks may be managed by id from
1940
+ * Return whether the active destination may update or delete this automation.
1941
+ * Same-destination automations stay local. Public automations may be managed by id from
1938
1942
  * another destination in the same workspace.
1939
1943
  */
1940
- function eventTaskIsWritableFrom(task, destination) {
1944
+ function eventAutomationIsWritableFrom(task, destination) {
1941
1945
  if (task.destination.teamId !== destination.teamId) return false;
1942
1946
  return task.destination.channelId === destination.channelId || task.destinationVisibility === "public";
1943
1947
  }
1944
- /** Load one task the active destination may update or delete. */
1945
- async function writableEventTask(context, id) {
1946
- const { destination } = requireEventTaskSlackContext(context);
1947
- const task = await getEventTask(getDb(), id);
1948
- if (!task || task.status === "deleted" || !eventTaskIsWritableFrom(task, destination)) throw new ToolInputError("Event task was not found.");
1948
+ /** Load one automation the active destination may update or delete. */
1949
+ async function writableEventAutomation(context, id) {
1950
+ const { destination } = requireEventAutomationSlackContext(context);
1951
+ const task = await getEventAutomation(getDb(), id);
1952
+ if (!task || task.status === "deleted" || !eventAutomationIsWritableFrom(task, destination)) throw new ToolInputError("Event automation was not found.");
1949
1953
  return task;
1950
1954
  }
1951
- function eventTaskTriggerAvailable(task, catalog) {
1952
- const registration = pluginResourceEventCatalog(catalog)[task.trigger.namespace];
1955
+ function eventAutomationTriggerAvailable(task, catalog) {
1956
+ const registration = pluginEventCatalog(catalog)[task.trigger.namespace];
1953
1957
  return Boolean(registration && task.trigger.events.every((eventType) => registration.resourceTypes.some((resourceType) => resourceType.supportedEvents.includes(eventType))));
1954
1958
  }
1955
- /** Project an event task into the bounded tool-result shape. */
1956
- function compactEventTask(task, catalog) {
1957
- return compactEventTaskResultSchema.parse({
1959
+ /** Project an event automation into the bounded tool-result shape. */
1960
+ function compactEventAutomation(task, catalog, requesterSlackUserId) {
1961
+ return compactEventAutomationResultSchema.parse({
1958
1962
  id: task.id,
1959
- task: task.task.text,
1960
- namespace: task.trigger.namespace,
1961
- identifier: task.trigger.identifier,
1962
- resourceType: task.trigger.resourceType,
1963
- label: task.trigger.label,
1964
- events: task.trigger.events,
1965
- ...task.trigger.match ? { match: task.trigger.match } : void 0,
1963
+ title: task.title?.trim() || null,
1964
+ instruction: task.task.text,
1965
+ trigger: {
1966
+ namespace: task.trigger.namespace,
1967
+ identifier: task.trigger.identifier,
1968
+ resourceType: task.trigger.resourceType,
1969
+ label: task.trigger.label,
1970
+ events: task.trigger.events,
1971
+ ...task.trigger.match ? { match: task.trigger.match } : void 0,
1972
+ available: eventAutomationTriggerAvailable(task, catalog)
1973
+ },
1966
1974
  credentialMode: task.credentialMode,
1967
- outcomes: effectiveTaskOutcomes(task.outcomes, task.destination),
1968
- createdBy: task.createdBy,
1969
- triggerAvailable: eventTaskTriggerAvailable(task, catalog)
1975
+ isCreator: task.createdBy.slackUserId === requesterSlackUserId,
1976
+ outcomes: effectiveTaskOutcomes(task.outcomes, task.destination).map((outcome) => ({
1977
+ action: outcome.action,
1978
+ destination: {
1979
+ channel: outcome.destination.channelId,
1980
+ thread: outcome.destination.threadTs ?? null
1981
+ }
1982
+ })),
1983
+ createdBy: {
1984
+ name: task.createdBy.fullName ?? null,
1985
+ username: task.createdBy.userName ?? null
1986
+ }
1970
1987
  });
1971
1988
  }
1972
- /** Return the standard successful event-task tool result. */
1973
- function eventTaskSuccess(task, catalog) {
1974
- return { task: compactEventTask(task, catalog) };
1989
+ /** Return the standard successful event-automation tool result. */
1990
+ function eventAutomationToolResult(task, catalog, requesterSlackUserId) {
1991
+ return { automation: compactEventAutomation(task, catalog, requesterSlackUserId) };
1975
1992
  }
1976
1993
  //#endregion
1977
- //#region src/chat/scheduled-tasks/types.ts
1978
- /** Durable scheduled-task domain types owned by Junior core. */
1979
- const scheduledTaskStatusSchema = z.enum([
1994
+ //#region src/chat/scheduled-automations/types.ts
1995
+ /** Durable scheduled-automation domain types owned by Junior core. */
1996
+ const scheduledAutomationStatusSchema = z.enum([
1980
1997
  "active",
1981
1998
  "blocked",
1982
1999
  "completed",
1983
2000
  "deleted"
1984
2001
  ]);
1985
- const scheduledTaskCredentialModeSchema = z.enum(["system", "creator"]);
2002
+ const scheduledAutomationCredentialModeSchema = z.enum(["system", "creator"]);
1986
2003
  const scheduledRunStatusSchema = z.enum([
1987
2004
  "pending",
1988
2005
  "running",
@@ -1991,12 +2008,12 @@ const scheduledRunStatusSchema = z.enum([
1991
2008
  "blocked",
1992
2009
  "skipped"
1993
2010
  ]);
1994
- const scheduledTaskPrincipalSchema = z.object({
2011
+ const scheduledAutomationPrincipalSchema = z.object({
1995
2012
  slackUserId: actorUserIdSchema,
1996
2013
  fullName: z.string().optional(),
1997
2014
  userName: z.string().optional()
1998
2015
  }).strict();
1999
- const scheduledTaskRecurrenceSchema = z.object({
2016
+ const scheduledAutomationRecurrenceSchema = z.object({
2000
2017
  dayOfMonth: z.number().optional(),
2001
2018
  frequency: z.enum([
2002
2019
  "daily",
@@ -2013,18 +2030,18 @@ const scheduledTaskRecurrenceSchema = z.object({
2013
2030
  }).strict(),
2014
2031
  weekdays: z.array(z.number()).optional()
2015
2032
  }).strict();
2016
- const scheduledTaskScheduleSchema = z.object({
2033
+ const scheduledAutomationScheduleSchema = z.object({
2017
2034
  description: z.string(),
2018
2035
  kind: z.enum(["one_off", "recurring"]),
2019
- recurrence: scheduledTaskRecurrenceSchema.optional(),
2036
+ recurrence: scheduledAutomationRecurrenceSchema.optional(),
2020
2037
  timezone: z.string()
2021
2038
  }).strict();
2022
- const scheduledTaskExecutionActorSchema = z.object({
2039
+ const scheduledAutomationExecutionActorSchema = z.object({
2023
2040
  platform: z.literal("system"),
2024
2041
  name: z.string()
2025
2042
  }).strict();
2026
- /** Validate the current scheduled-task domain shape. */
2027
- const scheduledTaskSchema = z.object({
2043
+ /** Validate the current scheduled-automation domain shape. */
2044
+ const scheduledAutomationSchema = z.object({
2028
2045
  id: z.string(),
2029
2046
  conversationAccess: z.object({
2030
2047
  audience: z.enum([
@@ -2035,22 +2052,22 @@ const scheduledTaskSchema = z.object({
2035
2052
  visibility: z.enum(["private", "public"])
2036
2053
  }).strict(),
2037
2054
  createdAtMs: z.number(),
2038
- createdBy: scheduledTaskPrincipalSchema,
2055
+ createdBy: scheduledAutomationPrincipalSchema,
2039
2056
  /** Authoritative provider identity that created the task. */
2040
2057
  creatorIdentityId: z.string(),
2041
2058
  /** Selects system credentials or task-bound creator credential delegation. */
2042
- credentialMode: scheduledTaskCredentialModeSchema,
2059
+ credentialMode: scheduledAutomationCredentialModeSchema,
2043
2060
  destination: slackDestinationSchema,
2044
- executionActor: scheduledTaskExecutionActorSchema.optional(),
2061
+ executionActor: scheduledAutomationExecutionActorSchema.optional(),
2045
2062
  lastRunAtMs: z.number().optional(),
2046
2063
  nextRunAtMs: z.number().optional(),
2047
2064
  originalRequest: z.string().optional(),
2048
2065
  runNowAtMs: z.number().optional(),
2049
- schedule: scheduledTaskScheduleSchema,
2050
- status: scheduledTaskStatusSchema,
2066
+ schedule: scheduledAutomationScheduleSchema,
2067
+ status: scheduledAutomationStatusSchema,
2051
2068
  statusReason: z.string().optional(),
2052
- /** Visible effects after successful work. Missing legacy values send a message. */
2053
- outcomes: z.array(taskOutcomeSchema).max(5).optional(),
2069
+ /** Explicit visible effects after successful work. An empty list is silent. */
2070
+ outcomes: z.array(taskOutcomeSchema).max(5),
2054
2071
  task: z.object({ text: z.string() }).strict(),
2055
2072
  /** SQL-backed short display title generated from the task instruction. */
2056
2073
  title: z.string().optional(),
@@ -2070,14 +2087,14 @@ const scheduledRunSchema = z.object({
2070
2087
  status: scheduledRunStatusSchema,
2071
2088
  taskId: z.string()
2072
2089
  }).strict();
2073
- const SCHEDULED_TASK_SYSTEM_ACTOR = Object.freeze({
2090
+ const SCHEDULED_AUTOMATION_SYSTEM_ACTOR = Object.freeze({
2074
2091
  platform: "system",
2075
- name: "scheduled-task"
2092
+ name: "scheduled-automation"
2076
2093
  });
2077
2094
  //#endregion
2078
- //#region src/chat/scheduled-tasks/tasks.ts
2095
+ //#region src/chat/scheduled-automations/tasks.ts
2079
2096
  const SCHEDULER_KEY_PREFIX = "junior:scheduler";
2080
- const retainedScheduledTaskSchema = scheduledTaskSchema.omit({
2097
+ const retainedScheduledAutomationSchema = scheduledAutomationSchema.omit({
2081
2098
  creatorIdentityId: true,
2082
2099
  title: true
2083
2100
  }).extend({
@@ -2091,11 +2108,18 @@ const retainedScheduledTaskSchema = scheduledTaskSchema.omit({
2091
2108
  version: z.number().optional()
2092
2109
  }).strict();
2093
2110
  /** Decode a retained scheduler task row and reject invalid routing context. */
2094
- function parseScheduledTaskRow(row) {
2111
+ function parseScheduledAutomationRow(row) {
2095
2112
  const record = z.record(z.string(), z.unknown()).safeParse(row.record);
2096
2113
  if (!record.success) return void 0;
2097
2114
  const { creatorIdentityId: legacyCreatorIdentityId, title: legacyTitle, ...retained } = record.data;
2098
- const parsed = retainedScheduledTaskSchema.safeParse(retained);
2115
+ const current = retained.outcomes === void 0 && retained.destination !== void 0 ? {
2116
+ ...retained,
2117
+ outcomes: [{
2118
+ action: "send_message",
2119
+ destination: retained.destination
2120
+ }]
2121
+ } : retained;
2122
+ const parsed = retainedScheduledAutomationSchema.safeParse(current);
2099
2123
  if (!parsed.success) return void 0;
2100
2124
  const { status, version: _version, ...task } = parsed.data;
2101
2125
  const fallbackIdentity = row.creatorIdentityId === null ? z.string().safeParse(legacyCreatorIdentityId) : void 0;
@@ -2120,23 +2144,23 @@ function parseScheduledTaskRow(row) {
2120
2144
  };
2121
2145
  }
2122
2146
  /** Keep scan paths from returning current or legacy tombstones. */
2123
- function isListedScheduledTask(task) {
2147
+ function isListedScheduledAutomation(task) {
2124
2148
  return task !== void 0 && task.status !== "deleted";
2125
2149
  }
2126
2150
  /** Build the stable run id for one task occurrence. */
2127
2151
  function scheduledRunId(taskId, scheduledForMs) {
2128
2152
  return `${taskId}:${scheduledForMs}`;
2129
2153
  }
2130
- /** Acquire the deployed advisory lock for one scheduled task. */
2131
- function withScheduledTaskLock(db, taskId, callback) {
2154
+ /** Acquire the deployed advisory lock for one scheduled automation. */
2155
+ function withScheduledAutomationLock(db, taskId, callback) {
2132
2156
  return db.transaction(async (tx) => {
2133
2157
  await tx.execute(sql`SELECT pg_advisory_xact_lock(hashtext(${`${SCHEDULER_KEY_PREFIX}:task:${taskId}:lock`}))`);
2134
2158
  return await callback(tx);
2135
2159
  });
2136
2160
  }
2137
2161
  function requireStoredTask(task) {
2138
- const parsed = scheduledTaskSchema.safeParse(task);
2139
- if (!parsed.success) throw new Error("Scheduled task routing context is invalid.");
2162
+ const parsed = scheduledAutomationSchema.safeParse(task);
2163
+ if (!parsed.success) throw new Error("Scheduled automation routing context is invalid.");
2140
2164
  const { title, ...current } = parsed.data;
2141
2165
  const normalizedTitle = title?.trim() || void 0;
2142
2166
  return {
@@ -2144,11 +2168,11 @@ function requireStoredTask(task) {
2144
2168
  ...normalizedTitle ? { title: normalizedTitle } : void 0
2145
2169
  };
2146
2170
  }
2147
- function scheduledTaskJsonRecord(task) {
2171
+ function scheduledAutomationJsonRecord(task) {
2148
2172
  const { title: _title, ...record } = task;
2149
2173
  return record;
2150
2174
  }
2151
- async function upsertScheduledTask(db, task) {
2175
+ async function upsertScheduledAutomation(db, task) {
2152
2176
  const title = task.title?.trim() || null;
2153
2177
  await db.insert(juniorSchedulerTasks).values({
2154
2178
  createdAtMs: task.createdAtMs,
@@ -2156,7 +2180,7 @@ async function upsertScheduledTask(db, task) {
2156
2180
  creatorSlackUserId: task.createdBy.slackUserId,
2157
2181
  id: task.id,
2158
2182
  nextRunAtMs: task.nextRunAtMs,
2159
- record: scheduledTaskJsonRecord(task),
2183
+ record: scheduledAutomationJsonRecord(task),
2160
2184
  runNowAtMs: task.runNowAtMs,
2161
2185
  status: task.status,
2162
2186
  teamId: task.destination.teamId,
@@ -2176,37 +2200,37 @@ async function upsertScheduledTask(db, task) {
2176
2200
  }
2177
2201
  });
2178
2202
  }
2179
- /** Read and decode one scheduled task. */
2180
- async function readScheduledTask(db, taskId) {
2203
+ /** Read and decode one scheduled automation. */
2204
+ async function readScheduledAutomation(db, taskId) {
2181
2205
  const rows = await db.select({
2182
2206
  creatorIdentityId: juniorSchedulerTasks.creatorIdentityId,
2183
2207
  record: juniorSchedulerTasks.record,
2184
2208
  title: juniorSchedulerTasks.title
2185
2209
  }).from(juniorSchedulerTasks).where(eq(juniorSchedulerTasks.id, taskId)).limit(1);
2186
- return rows[0] ? parseScheduledTaskRow(rows[0]) : void 0;
2210
+ return rows[0] ? parseScheduledAutomationRow(rows[0]) : void 0;
2187
2211
  }
2188
- async function readListedScheduledTasks(db, teamId) {
2212
+ async function readListedScheduledAutomations(db, teamId) {
2189
2213
  return (await db.select({
2190
2214
  creatorIdentityId: juniorSchedulerTasks.creatorIdentityId,
2191
2215
  record: juniorSchedulerTasks.record,
2192
2216
  title: juniorSchedulerTasks.title
2193
- }).from(juniorSchedulerTasks).where(and(notInArray(juniorSchedulerTasks.status, ["deleted", "paused"]), teamId === void 0 ? void 0 : eq(juniorSchedulerTasks.teamId, teamId))).orderBy(asc(juniorSchedulerTasks.createdAtMs), asc(juniorSchedulerTasks.id))).map(parseScheduledTaskRow).filter(isListedScheduledTask);
2217
+ }).from(juniorSchedulerTasks).where(and(notInArray(juniorSchedulerTasks.status, ["deleted", "paused"]), teamId === void 0 ? void 0 : eq(juniorSchedulerTasks.teamId, teamId))).orderBy(asc(juniorSchedulerTasks.createdAtMs), asc(juniorSchedulerTasks.id))).map(parseScheduledAutomationRow).filter(isListedScheduledAutomation);
2194
2218
  }
2195
- /** List decoded scheduled tasks in stable creation order. */
2196
- async function listScheduledTasks(db) {
2197
- return await readListedScheduledTasks(db);
2219
+ /** List decoded scheduled automations in stable creation order. */
2220
+ async function listScheduledAutomations(db) {
2221
+ return await readListedScheduledAutomations(db);
2198
2222
  }
2199
- /** List decoded scheduled tasks for one team in stable creation order. */
2200
- async function listScheduledTasksForTeam(db, teamId) {
2201
- return await readListedScheduledTasks(db, teamId);
2223
+ /** List decoded scheduled automations for one team in stable creation order. */
2224
+ async function listScheduledAutomationsForTeam(db, teamId) {
2225
+ return await readListedScheduledAutomations(db, teamId);
2202
2226
  }
2203
- async function writeScheduledTask(db, task, current) {
2227
+ async function writeScheduledAutomation(db, task, current) {
2204
2228
  if (current?.status === "blocked" && task.status === "active" && typeof task.nextRunAtMs === "number" && Number.isFinite(task.nextRunAtMs)) await db.delete(juniorSchedulerRuns).where(and(eq(juniorSchedulerRuns.id, scheduledRunId(task.id, task.nextRunAtMs)), eq(juniorSchedulerRuns.status, "blocked")));
2205
2229
  if (task.status === "deleted" && current?.status !== "deleted") await skipPendingRunsForDeletedTask(db, task);
2206
- await upsertScheduledTask(db, task);
2230
+ await upsertScheduledAutomation(db, task);
2207
2231
  }
2208
2232
  async function skipPendingRunsForDeletedTask(db, task) {
2209
- const errorMessage = `Scheduled task ${task.id} was deleted before the run started.`;
2233
+ const errorMessage = `Scheduled automation ${task.id} was deleted before the run started.`;
2210
2234
  const rows = await db.select({ record: juniorSchedulerRuns.record }).from(juniorSchedulerRuns).where(and(eq(juniorSchedulerRuns.taskId, task.id), eq(juniorSchedulerRuns.status, "pending")));
2211
2235
  for (const row of rows) {
2212
2236
  const parsed = scheduledRunSchema.safeParse(row.record);
@@ -2223,31 +2247,31 @@ async function skipPendingRunsForDeletedTask(db, task) {
2223
2247
  }).where(and(eq(juniorSchedulerRuns.id, next.id), eq(juniorSchedulerRuns.status, "pending")));
2224
2248
  }
2225
2249
  }
2226
- /** Create a scheduled task once under its retry-stable task lock. */
2227
- async function createScheduledTask(db, task) {
2250
+ /** Create a scheduled automation once under its retry-stable task lock. */
2251
+ async function createScheduledAutomation(db, task) {
2228
2252
  const next = requireStoredTask(task);
2229
- return await withScheduledTaskLock(db, task.id, async (tx) => {
2230
- const current = await readScheduledTask(tx, task.id);
2253
+ return await withScheduledAutomationLock(db, task.id, async (tx) => {
2254
+ const current = await readScheduledAutomation(tx, task.id);
2231
2255
  if (current) return current;
2232
- await writeScheduledTask(tx, next, void 0);
2256
+ await writeScheduledAutomation(tx, next, void 0);
2233
2257
  return next;
2234
2258
  });
2235
2259
  }
2236
- /** Save a scheduled task and clear its blocked occurrence on reactivation. */
2237
- async function saveScheduledTask(db, task) {
2260
+ /** Save a scheduled automation and clear its blocked occurrence on reactivation. */
2261
+ async function saveScheduledAutomation(db, task) {
2238
2262
  const next = requireStoredTask(task);
2239
- await withScheduledTaskLock(db, task.id, async (tx) => {
2240
- const current = await readScheduledTask(tx, task.id);
2241
- await writeScheduledTask(tx, next, current);
2263
+ await withScheduledAutomationLock(db, task.id, async (tx) => {
2264
+ const current = await readScheduledAutomation(tx, task.id);
2265
+ await writeScheduledAutomation(tx, next, current);
2242
2266
  });
2243
2267
  return next;
2244
2268
  }
2245
- /** Save a scheduled task inside a task lock already held by the caller. */
2246
- async function saveScheduledTaskInLock(db, task, current) {
2247
- await writeScheduledTask(db, requireStoredTask(task), current);
2269
+ /** Save a scheduled automation inside a task lock already held by the caller. */
2270
+ async function saveScheduledAutomationInLock(db, task, current) {
2271
+ await writeScheduledAutomation(db, requireStoredTask(task), current);
2248
2272
  }
2249
- /** List scheduled tasks whose current Slack destination is public. */
2250
- async function listPublicScheduledTasksForTeams(db, teamIds, input) {
2273
+ /** List scheduled automations whose current Slack destination is public. */
2274
+ async function listPublicScheduledAutomationsForTeams(db, teamIds, input) {
2251
2275
  if (teamIds.length === 0) return [];
2252
2276
  return (await db.select({
2253
2277
  creatorIdentityId: juniorSchedulerTasks.creatorIdentityId,
@@ -2257,7 +2281,7 @@ async function listPublicScheduledTasksForTeams(db, teamIds, input) {
2257
2281
  "completed",
2258
2282
  "deleted",
2259
2283
  "paused"
2260
- ]), input.query ? sql`strpos(lower(coalesce(${juniorSchedulerTasks.title}, ${juniorSchedulerTasks.record}->'task'->>'text')), ${input.query}) > 0` : void 0, eq(juniorDestinations.visibility, "public"))).orderBy(desc(juniorSchedulerTasks.createdAtMs), desc(juniorSchedulerTasks.id)).limit(input.limit)).map(parseScheduledTaskRow).filter(isListedScheduledTask);
2284
+ ]), input.query ? sql`strpos(lower(coalesce(${juniorSchedulerTasks.title}, ${juniorSchedulerTasks.record}->'task'->>'text')), ${input.query}) > 0` : void 0, eq(juniorDestinations.visibility, "public"))).orderBy(desc(juniorSchedulerTasks.createdAtMs), desc(juniorSchedulerTasks.id)).limit(input.limit)).map(parseScheduledAutomationRow).filter(isListedScheduledAutomation);
2261
2285
  }
2262
2286
  //#endregion
2263
2287
  //#region src/chat/slack/context.ts
@@ -2645,4 +2669,4 @@ async function readStats(start, end) {
2645
2669
  return await getDb().select().from(juniorStats).where(and(gte(juniorStats.date, start), lte(juniorStats.date, end))).orderBy(asc(juniorStats.date), asc(juniorStats.namespace), asc(juniorStats.metric), asc(juniorStats.name));
2646
2670
  }
2647
2671
  //#endregion
2648
- export { workspaceSnapshotFinishedEvent as $, eventTaskTriggerAvailable as A, recordConversationRetry as At, createEventTask as B, isFinalAttempt as Bt, SCHEDULED_TASK_SYSTEM_ACTOR as C, drainConversationMailbox as Ct, eventTaskMatchesDestination as D, hasRunnableConversationWork as Dt, eventTaskListToolResultSchema as E, getConversationWorkState as Et, effectiveTaskOutcomes as F, startConversationWork as Ft, listDeletedEventTasksCreatedBy as G, buildDeterministicAssistantMessageId as Gt, eventTaskBelongsToUser as H, injectContinuationToolName as Ht, moveTaskOutcomes as I, stopConversationWork as It, listPublicEventTasksForTeams as J, listEventTasksCreatedBy as K, buildDeterministicTurnId as Kt, resolveTaskOutcomes as L, CONVERSATION_WORK_CHECK_IN_INTERVAL_MS as Lt, requireEventTaskSlackContext as M, removeActiveConversation as Mt, requireSupportedEventTaskTrigger as N, requestAnotherSlice as Nt, eventTaskSuccess as O, listActiveConversationIds as Ot, writableEventTask as P, requestConversationWork as Pt, WORKSPACE_SNAPSHOT_READY_EVENT as Q, taskOutcomeInputSchema as R, CONVERSATION_WORK_STALE_ENQUEUE_MS as Rt, withScheduledTaskLock as S, deadLetterAttempt as St, compactEventTask as T, getConversation as Tt, findMatchingEventTasks as U, juniorToolOutputSchema as Ut, deleteEventTask as V, isInvalidConversationRecordError as Vt, getEventTask as W, makeStructuredToolOutput as Wt, getResourceEventCatalog as X, saveEventTask as Y, WORKSPACE_SNAPSHOT_FAILED_EVENT as Z, parseScheduledTaskRow as _, clearConsumedConversationWake as _t, requestAttachmentDeletion as a, pluginSupportsEvent as at, saveScheduledTaskInLock as b, completeConversationWork as bt, parseSlackThreadId as c, registeredResourceTypeSchema as ct, resolveSlackChannelIdFromThreadId as d, ackMessages as dt, workspaceSnapshotWatch as et, createScheduledTask as f, appendAndEnqueueExclusiveInboundMessage as ft, listScheduledTasksForTeam as g, checkInConversationWork as gt, listScheduledTasks as h, cancelHumanFacingPendingMessages as ht, readLiveAttachment as i, normalizeEventIdentifier as it, registeredEventTaskTriggerSchema as j, releaseConversationWork as jt, eventTaskToolResultSchema as k, recordAttemptFailure as kt, readSlackRawMessageContext as l, requireSupportedResourceEventMatch as lt, listPublicScheduledTasksForTeams as m, beginConversationResume as mt, readStats as n, hasPluginResourceEventCatalogEntries as nt, storeAttachment as o, registeredEventTypeSchema as ot, isListedScheduledTask as p, appendAndEnqueueInboundMessage as pt, listEventTasksForTeam as q, collectAttachmentGarbage as r, hasResourceEventCatalogEntries as rt, storeAttachments as s, registeredResourceEventMatchSchema as st, incrementStat as t, eventNamespaceSchema as tt, resolveSlackChannelIdFromMessage as u, resourceEventGuidance as ut, readScheduledTask as v, clearExpiredConversationLease as vt, scheduledRunSchema as w, ensureConversationWake as wt, scheduledRunId as x, countPendingConversationMessages as xt, saveScheduledTask as y, completeConversationStop as yt, collectEventTaskMatchKeys as z, hasRunnableConversationWork$1 as zt };
2672
+ export { workspaceSnapshotFinishedEvent as $, eventAutomationTriggerAvailable as A, recordConversationRetry as At, createEventAutomation as B, isFinalAttempt as Bt, SCHEDULED_AUTOMATION_SYSTEM_ACTOR as C, drainConversationMailbox as Ct, eventAutomationMatchesDestination as D, hasRunnableConversationWork as Dt, eventAutomationListToolResultSchema as E, getConversationWorkState as Et, effectiveTaskOutcomes as F, startConversationWork as Ft, listDeletedEventAutomationsCreatedBy as G, buildDeterministicAssistantMessageId as Gt, eventAutomationBelongsToUser as H, injectContinuationToolName as Ht, moveTaskOutcomes as I, stopConversationWork as It, listPublicEventAutomationsForTeams as J, listEventAutomationsCreatedBy as K, buildDeterministicTurnId as Kt, resolveTaskOutcomes as L, CONVERSATION_WORK_CHECK_IN_INTERVAL_MS as Lt, requireEventAutomationSlackContext as M, removeActiveConversation as Mt, requireSupportedEventAutomationTrigger as N, requestAnotherSlice as Nt, eventAutomationToolResult as O, listActiveConversationIds as Ot, writableEventAutomation as P, requestConversationWork as Pt, WORKSPACE_SNAPSHOT_READY_EVENT as Q, taskOutcomeInputSchema as R, CONVERSATION_WORK_STALE_ENQUEUE_MS as Rt, withScheduledAutomationLock as S, deadLetterAttempt as St, compactEventAutomation as T, getConversation as Tt, findMatchingEventAutomations as U, juniorToolOutputSchema as Ut, deleteEventAutomation as V, isInvalidConversationRecordError as Vt, getEventAutomation as W, makeStructuredToolOutput as Wt, getEventCatalog as X, saveEventAutomation as Y, WORKSPACE_SNAPSHOT_FAILED_EVENT as Z, parseScheduledAutomationRow as _, clearConsumedConversationWake as _t, requestAttachmentDeletion as a, normalizeCatalogEventIdentifier as at, saveScheduledAutomationInLock as b, completeConversationWork as bt, parseSlackThreadId as c, registeredEventTypeSchema as ct, resolveSlackChannelIdFromThreadId as d, ackMessages as dt, workspaceSnapshotWatch as et, createScheduledAutomation as f, appendAndEnqueueExclusiveInboundMessage as ft, listScheduledAutomationsForTeam as g, checkInConversationWork as gt, listScheduledAutomations as h, cancelHumanFacingPendingMessages as ht, readLiveAttachment as i, hasPluginEventCatalogEntries as it, registeredEventAutomationTriggerSchema as j, releaseConversationWork as jt, eventAutomationToolResultSchema as k, recordAttemptFailure as kt, readSlackRawMessageContext as l, registeredResourceTypeSchema as lt, listPublicScheduledAutomationsForTeams as m, beginConversationResume as mt, readStats as n, eventNamespaceSchema as nt, storeAttachment as o, pluginSupportsEvent as ot, isListedScheduledAutomation as p, appendAndEnqueueInboundMessage as pt, listEventAutomationsForTeam as q, collectAttachmentGarbage as r, hasEventCatalogEntries as rt, storeAttachments as s, registeredEventMatchSchema as st, incrementStat as t, eventGuidance as tt, resolveSlackChannelIdFromMessage as u, requireSupportedEventMatch as ut, readScheduledAutomation as v, clearExpiredConversationLease as vt, scheduledRunSchema as w, ensureConversationWake as wt, scheduledRunId as x, countPendingConversationMessages as xt, saveScheduledAutomation as y, completeConversationStop as yt, collectEventAutomationMatchKeys as z, hasRunnableConversationWork$1 as zt };