@sentry/junior 0.205.0 → 0.207.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 (73) hide show
  1. package/dist/{agent-D4nu8MQV.js → agent-CmQlX68D.js} +603 -394
  2. package/dist/{agent-hooks-DXHpTJ4m.js → agent-hooks-BBX9p6aG.js} +1171 -100
  3. package/dist/{agent-runner-C04colea.js → agent-runner-CQD4HKK2.js} +9 -9
  4. package/dist/api/schema.d.ts +116 -39
  5. package/dist/api/schema.js +3 -3
  6. package/dist/api.d.ts +1 -1
  7. package/dist/api.js +182 -649
  8. package/dist/{app-Cb776lL8.d.ts → app-DfNrn_gS.d.ts} +9 -2
  9. package/dist/app.d.ts +1 -1
  10. package/dist/app.js +205 -233
  11. package/dist/{auth-pause-state-C2P3guS1.js → auth-pause-state-uv8on6cT.js} +7 -7
  12. package/dist/briefs-BXEmjD9D.js +398 -0
  13. package/dist/{catalog-runtime-CXw3asJD.js → catalog-runtime-1BZEOR8J.js} +1 -1
  14. package/dist/{checkpoint-CrViJ8Ps.js → checkpoint-B-JO5F3c.js} +9 -8
  15. package/dist/cli/chat.js +14 -12
  16. package/dist/cli/check.js +3 -3
  17. package/dist/cli/init.js +1 -0
  18. package/dist/cli/main.js +5 -1
  19. package/dist/cli/plugins.js +3 -3
  20. package/dist/cli/run.d.ts +2 -1
  21. package/dist/cli/run.js +2 -1
  22. package/dist/cli/snapshot-create.js +3 -3
  23. package/dist/cli/upgrade.d.ts +1 -1
  24. package/dist/cli/upgrade.js +3 -3
  25. package/dist/{config-BOtJQ7Pc.js → client-Bp297GA0.js} +6 -369
  26. package/dist/config-G2gv97R1.js +386 -0
  27. package/dist/{context-B45_WqVX.js → context-Bplcgypl.js} +13 -13
  28. package/dist/{schema-Rn8-XEaN.js → conversation-AA4R1VUn.js} +580 -558
  29. package/dist/{conversation-privacy-BZRA6Pes.js → conversation-privacy-BUfel19D.js} +1 -1
  30. package/dist/{credential-sync-Bep34IB_.js → credential-sync-D04NWqMR.js} +21 -20
  31. package/dist/{db-BeyXKJOI.d.ts → db-D74z7BZH.d.ts} +1 -1
  32. package/dist/{execution-stats-B6lgWxCK.js → execution-stats-Ds4bSvam.js} +77 -77
  33. package/dist/{executor-BlUhFL7_.js → executor-BZu1Ta06.js} +41 -13
  34. package/dist/instrumentation.js +2 -2
  35. package/dist/{job-queue-DLMqIK74.js → job-queue-rnAPfUhP.js} +1 -1
  36. package/dist/{logging-BMJzdDlP.js → logging-Dx0S5k2z.js} +1 -1
  37. package/dist/nitro.d.ts +1 -1
  38. package/dist/nitro.js +3 -3
  39. package/dist/{oauth-callback-server-WwG5_Zgm.js → oauth-callback-server-xGpwURIj.js} +2 -2
  40. package/dist/{pending-auth-CUbXq06G.js → pending-auth-DIZ4iZjS.js} +2 -2
  41. package/dist/{profile-T0tXE4zu.js → profile-d-fKypxo.js} +4 -3
  42. package/dist/prompt-x-0ZtTyb.js +552 -0
  43. package/dist/{registry-BA0__8ai.js → registry-CWKdLCTG.js} +2 -2
  44. package/dist/{resolve-bvD1ORdv.js → resolve-BhRB1s2A.js} +2 -2
  45. package/dist/{runner-BXYxfIUL.js → runner-DNml3owD.js} +10 -10
  46. package/dist/{sandbox-egress-signals-ngEPjSEW.js → sandbox-egress-signals-DUIl3-gW.js} +1 -1
  47. package/dist/schema-CwTeb-BF.js +559 -0
  48. package/dist/{skills-DJOlYdBs.js → skills-D9WesdJJ.js} +2 -2
  49. package/dist/{spawn-h0R1bTEo.js → spawn-Eh_3-s0M.js} +2 -2
  50. package/dist/{stats-3YZn-Swi.js → stats-CFlUGqVA.js} +292 -268
  51. package/dist/{store-C5qxF2ac.d.ts → store-Det8MQ9g.d.ts} +1 -1
  52. package/dist/{task-queue-CoXwd2eq.js → task-queue-D8I1_5wP.js} +3 -3
  53. package/dist/{task-runner-B2_mJZj0.js → task-runner-DO79gdho.js} +18 -18
  54. package/dist/{thread-state-CqZ1m-es.js → thread-state-DD6BA4xz.js} +5 -5
  55. package/dist/{turn-execution-fI6PZ0iI.js → turn-execution-BSIHxmQJ.js} +3 -3
  56. package/dist/{turn-lifecycle-CcnwrOcp.js → turn-lifecycle-DSBK4Ars.js} +1 -1
  57. package/dist/{usage-B5SfMb3H.js → usage-WRXkNOHp.js} +4 -125
  58. package/dist/{validation-DfWcvhuS.js → validation-BbHZ4r4S.js} +1 -1
  59. package/dist/{version-oD-oPrbO.js → version-C71UcRWw.js} +1 -1
  60. package/dist/version.js +1 -1
  61. package/dist/web-authorization-C73gJV7l.js +38 -0
  62. package/dist/{web-input-BOuq3oKK.js → web-input-Ce1FcNIM.js} +8 -8
  63. package/dist/{work-B91LQKHr.js → work-BEzDU_2x.js} +9 -9
  64. package/dist/{worker-BcRRTe6k.js → worker-MK2ubOv-.js} +5 -4
  65. package/migrations/0040_conversation_briefs.sql +17 -0
  66. package/migrations/0041_automation_outcomes_backfill.sql +27 -0
  67. package/migrations/meta/0040_snapshot.json +3516 -0
  68. package/migrations/meta/0041_snapshot.json +3516 -0
  69. package/migrations/meta/_journal.json +14 -0
  70. package/package.json +4 -4
  71. package/dist/history-CqTuSAdI.js +0 -441
  72. package/dist/usage-schema-CKaDkH_j.js +0 -20
  73. package/dist/web-authorization-Crbzlmzo.js +0 -76
package/dist/api.js CHANGED
@@ -1,24 +1,24 @@
1
- import { f as logWarn, u as logException } from "./logging-BMJzdDlP.js";
2
- import { _ as parseSlackMessageTs, h as parseSlackTeamId, p as parseSlackChannelId } from "./context-B45_WqVX.js";
3
- import { B as getSlackClient, Dt as getSqlExecutor, Et as getDb, Ft as resolveRootConversationId, G as withSlackRetries, J as findUserByEmail, Mt as locationFromRow, O as workspaceRepoCheckoutPath, Pt as parseSessionSource, Tt as getConversationStore, X as resolveViewerUser, Z as updateViewerDisplayName, _ as listWorkspaces, _t as createPluginLogger, bt as listConversationAnnotations, h as getWorkspace, m as deleteWorkspace, p as createWorkspace, u as getPlugins, v as updateWorkspace, w as SANDBOX_RUNTIME, xt as listConversationAnnotationsById, y as WorkspaceValidationError, yt as renderPluginConversationEvent } from "./agent-hooks-DXHpTJ4m.js";
1
+ import { f as logWarn, u as logException } from "./logging-Dx0S5k2z.js";
2
+ import { _ as parseSlackMessageTs, h as parseSlackTeamId, p as parseSlackChannelId } from "./context-Bplcgypl.js";
3
+ import { $ as resolveViewerUser, Ct as readConversationEventPage, D as SANDBOX_RUNTIME, Dt as listConversationAnnotationsById, Et as listConversationAnnotations, Ft as getConversationStore, Gt as resolveRootConversationId, Ht as locationFromRow, It as getDb, J as withSlackRetries, Lt as getSqlExecutor, S as WorkspaceValidationError, St as readLatestConversationBrief, U as getSlackClient, Wt as parseSessionSource, Z as findUserByEmail, _ as deleteWorkspace, b as listWorkspaces, bt as createPluginLogger, et as updateViewerDisplayName, g as createWorkspace, j as workspaceRepoCheckoutPath, u as getPlugins, v as getWorkspace, wt as buildSentryConversationUrl, x as updateWorkspace } from "./agent-hooks-BBX9p6aG.js";
4
4
  import { n as juniorDestinations } from "./destinations-BeBiJeEM.js";
5
- import { C as juniorConversations, S as conversationReadColumns, T as juniorUsers, _ as juniorApiTokens, b as juniorCodeRepositories, g as juniorConversationEvents, m as juniorConversationParticipants, o as juniorSchedulerTasks, w as juniorIdentities, y as juniorCodeChanges } from "./executor-BlUhFL7_.js";
6
- import { o as decodeStoredConversationEvent } from "./history-CqTuSAdI.js";
7
- import { a as hasAgentTurnUsage, i as agentTurnUsageSchema, m as renderJuniorNativeConversationEvent, s as fallbackShortTitle } from "./usage-B5SfMb3H.js";
8
- import { n as hash, t as create } from "./profile-T0tXE4zu.js";
9
- import { A as eventTaskTriggerAvailable, F as effectiveTaskOutcomes, G as listDeletedEventTasksCreatedBy, H as eventTaskBelongsToUser, J as listPublicEventTasksForTeams, K as listEventTasksCreatedBy, Tt as getConversation, V as deleteEventTask, W as getEventTask, X as getResourceEventCatalog, _ as parseScheduledTaskRow, c as parseSlackThreadId, ht as cancelHumanFacingPendingMessages, i as readLiveAttachment, m as listPublicScheduledTasksForTeams, n as readStats, p as isListedScheduledTask, v as readScheduledTask, y as saveScheduledTask } from "./stats-3YZn-Swi.js";
10
- import { t as getCachedSnapshot } from "./resolve-bvD1ORdv.js";
5
+ import { C as conversationReadColumns, E as juniorUsers, T as juniorIdentities, _ as juniorConversationEvents, b as juniorCodeChanges, g as juniorConversationBriefs, m as juniorConversationParticipants, o as juniorSchedulerTasks, v as juniorApiTokens, w as juniorConversations, x as juniorCodeRepositories } from "./executor-BZu1Ta06.js";
6
+ import { D as createConversationBodySchema, O as createConversationMessageBodySchema, T as conversationStatsReportSchema, _ as conversationParamsSchema, a as cancelConversationPendingMessagesBodySchema, c as conversationAttachmentParamsSchema, d as conversationDetailReportSchema, g as conversationFeedSchema, h as conversationFeedQuerySchema, i as archiveConversationResponseSchema, m as conversationEventsQuerySchema, o as cancelConversationPendingMessagesResponseSchema, p as conversationEventPageSchema, r as archiveConversationBodySchema, t as acceptedConversationMessageSchema, u as conversationDetailQuerySchema, x as conversationPendingMessagesReportSchema } from "./conversation-AA4R1VUn.js";
7
+ import { a as hasAgentTurnUsage, i as agentTurnUsageSchema, s as fallbackShortTitle } from "./usage-WRXkNOHp.js";
8
+ import { n as hash, t as create } from "./profile-d-fKypxo.js";
9
+ import { A as eventAutomationTriggerAvailable, F as effectiveTaskOutcomes, G as listDeletedEventAutomationsCreatedBy, H as eventAutomationBelongsToUser, J as listPublicEventAutomationsForTeams, K as listEventAutomationsCreatedBy, Tt as getConversation, V as deleteEventAutomation, W as getEventAutomation, X as getEventCatalog, _ as parseScheduledAutomationRow, c as parseSlackThreadId, ht as cancelHumanFacingPendingMessages, i as readLiveAttachment, m as listPublicScheduledAutomationsForTeams, n as readStats, p as isListedScheduledAutomation, v as readScheduledAutomation, y as saveScheduledAutomation } from "./stats-CFlUGqVA.js";
10
+ import { t as getCachedSnapshot } from "./resolve-BhRB1s2A.js";
11
11
  import { t as getVercelConversationWorkQueue } from "./vercel-queue-DIkVcfK4.js";
12
12
  import { c as runtimeInfoReportSchema, n as pluginOperationalReportFeedSchema, s as pluginsSchema, t as healthReportSchema, u as skillReportsSchema } from "./reporting-schema-DosTN__Q.js";
13
- import { C as createVercelAttachmentStorage, S as legacyWebMailboxMetadataSchema, T as readHealthReport, _ as formatSlackConversationRedactedLabel, a as webActorFromEmail, b as resolveSlackConversationContextFromThreadId, c as conversationArchivedForEmail, d as conversationHasParticipantUser, f as conversationNotArchivedForEmail, l as conversationArchivedForUser, m as viewerConversationMembership, o as readConversationAccessFromSql, p as conversationNotArchivedForUser, r as createAndEnqueueConversation, s as conversationArchiveTimes, t as appendAndEnqueueWebMessage, u as conversationHasParticipantEmail, x as lookupSlackUser } from "./web-input-BOuq3oKK.js";
14
- import { a as readTaskExecutionStatusDays, c as readTaskExecutions, d as conversationActiveDaysColumn, f as conversationAggregateColumns, i as readTaskExecutionHours, l as readTaskRuns, n as readTaskExecutionByConversationId, o as readTaskExecutionStatusHours, p as conversationRangeColumns, r as readTaskExecutionDays, s as readTaskExecutionSummaries, t as emptyTaskRunWindows } from "./execution-stats-B6lgWxCK.js";
15
- import { a as buildSentryEventUrl, i as buildSentryConversationUrl, r as getWebAuthorization } from "./web-authorization-Crbzlmzo.js";
16
- import { $ as sumUtcHoursIntoSixHours, A as actorProfileReportSchema, At as createConversationMessageBodySchema, C as createPersonalTokenBodySchema, D as personalTokenParamsSchema, Dt as conversationStatsReportSchema, Et as conversationReportEventSchema, F as locationDirectoryReportSchema, G as codePersonReportSchema, I as locationParamsSchema, J as HOUR_MS$1, L as activityDays$1, M as personalSpendReportSchema, O as revokePersonalTokenResponseSchema, P as locationDetailReportSchema, Q as startOfUtcHour, R as activityHours$1, T as personalTokenListSchema, W as codeOverviewReportSchema, X as fillUtcHours, Y as fillUtcDays, Z as fillUtcSixHours, _ as taskListSchema, _t as conversationEventsQuerySchema, a as workspaceBodySchema, at as acceptedConversationMessageSchema, bt as conversationParamsSchema, ct as cancelConversationPendingMessagesBodySchema, dt as conversationAttachmentParamsSchema, et as trailingUtcDayWindow, f as taskExecutionListSchema, g as taskListQuerySchema, gt as conversationEventPageSchema, i as deleteWorkspaceResponseSchema, it as utcHourKey, j as personParamsSchema, jt as apiErrorSchema, k as actorDirectoryReportSchema, kt as createConversationBodySchema, l as workspaceSchema, lt as cancelConversationPendingMessagesResponseSchema, mt as conversationDetailReportSchema, n as statsReportSchema, nt as trailingUtcSixHourWindow, o as workspaceListSchema, ot as archiveConversationBodySchema, pt as conversationDetailQuerySchema, q as DAY_MS$1, rt as utcDayKey, s as workspaceParamsSchema, st as archiveConversationResponseSchema, tt as trailingUtcHourWindow, v as taskParamsSchema, vt as conversationFeedQuerySchema, w as createdPersonalTokenSchema, wt as conversationPendingMessagesReportSchema, y as taskRunListSchema, yt as conversationFeedSchema, z as activitySixHours$1 } from "./schema-Rn8-XEaN.js";
13
+ import { C as createVercelAttachmentStorage, S as legacyWebMailboxMetadataSchema, T as readHealthReport, _ as formatSlackConversationRedactedLabel, a as webActorFromEmail, b as resolveSlackConversationContextFromThreadId, c as conversationArchivedForEmail, d as conversationHasParticipantUser, f as conversationNotArchivedForEmail, l as conversationArchivedForUser, m as viewerConversationMembership, o as readConversationAccessFromSql, p as conversationNotArchivedForUser, r as createAndEnqueueConversation, s as conversationArchiveTimes, t as appendAndEnqueueWebMessage, u as conversationHasParticipantEmail, x as lookupSlackUser } from "./web-input-Ce1FcNIM.js";
14
+ import { a as readAutomationExecutionStatusDays, c as readAutomationExecutions, d as conversationActiveDaysColumn, f as conversationAggregateColumns, i as readAutomationExecutionHours, l as readAutomationRuns, n as readAutomationExecutionByConversationId, o as readAutomationExecutionStatusHours, p as conversationRangeColumns, r as readAutomationExecutionDays, s as readAutomationExecutionSummaries, t as emptyAutomationRunWindows } from "./execution-stats-Ds4bSvam.js";
15
+ import { r as getWebAuthorization } from "./web-authorization-C73gJV7l.js";
16
+ import { $ as sumUtcHoursIntoSixHours, A as actorProfileReportSchema, C as createPersonalTokenBodySchema, D as personalTokenParamsSchema, F as locationDirectoryReportSchema, G as codePersonReportSchema, I as locationParamsSchema, J as HOUR_MS$1, L as activityDays$1, M as personalSpendReportSchema, O as revokePersonalTokenResponseSchema, P as locationDetailReportSchema, Q as startOfUtcHour, R as activityHours$1, T as personalTokenListSchema, W as codeOverviewReportSchema, X as fillUtcHours, Y as fillUtcDays, Z as fillUtcSixHours, _ as automationRunListSchema, a as workspaceBodySchema, at as apiErrorSchema, et as trailingUtcDayWindow, g as automationParamsSchema, h as automationListSchema, i as deleteWorkspaceResponseSchema, it as utcHourKey, j as personParamsSchema, k as actorDirectoryReportSchema, l as workspaceSchema, m as automationListQuerySchema, n as statsReportSchema, nt as trailingUtcSixHourWindow, o as workspaceListSchema, q as DAY_MS$1, rt as utcDayKey, s as workspaceParamsSchema, tt as trailingUtcHourWindow, u as automationExecutionListSchema, w as createdPersonalTokenSchema, z as activitySixHours$1 } from "./schema-CwTeb-BF.js";
17
17
  import { Hono } from "hono";
18
18
  import path from "node:path";
19
19
  import { z } from "zod";
20
20
  import { createHash, createHmac, randomBytes, randomUUID, timingSafeEqual } from "node:crypto";
21
- import { and, asc, desc, eq, getTableColumns, gt, gte, inArray, isNotNull, isNull, lt, lte, notExists, notInArray, or, sql } from "drizzle-orm";
21
+ import { and, asc, desc, eq, gt, gte, inArray, isNotNull, isNull, lt, lte, notExists, notInArray, or, sql } from "drizzle-orm";
22
22
  import { conversationSidebarAnnotationSchema, pluginUserPageContentSchema, pluginUserPageCursorSchema, pluginUserPageFilterSchema, pluginUserPageLinksSchema, pluginUserPageQuerySchema } from "@sentry/junior-plugin-api";
23
23
  import { alias } from "drizzle-orm/pg-core";
24
24
  import { readFileSync } from "node:fs";
@@ -460,491 +460,6 @@ function decodeConversationCursor(args) {
460
460
  }
461
461
  }
462
462
  //#endregion
463
- //#region src/api/conversations/events.ts
464
- /** Canonical event types that can contribute to the reporting projection. */
465
- const conversationReportSourceEventTypes = [
466
- "message",
467
- "message_handled",
468
- "assistant_message",
469
- "tool_result",
470
- "tool_execution_started",
471
- "guardian_action_reviewed",
472
- "turn_started",
473
- "turn_context",
474
- "structured_event",
475
- "attachments_delivered",
476
- "turn_routed",
477
- "turn_completed",
478
- "turn_failed",
479
- "compaction",
480
- "handoff",
481
- "subagent_started",
482
- "subagent_ended"
483
- ];
484
- const reportingAssistantMessageSchema = z.object({
485
- type: z.literal("assistant_message"),
486
- content: z.array(z.unknown())
487
- }).passthrough();
488
- const reportingToolCallPartSchema = z.object({
489
- type: z.literal("toolCall"),
490
- id: z.string().min(1),
491
- name: z.string().min(1),
492
- arguments: z.unknown()
493
- }).passthrough();
494
- const reportingToolResultMessageSchema = z.object({
495
- type: z.literal("tool_result"),
496
- toolCallId: z.string().min(1),
497
- toolName: z.string().min(1).optional(),
498
- name: z.string().min(1).optional(),
499
- content: z.array(z.unknown()),
500
- details: z.unknown().optional(),
501
- isError: z.boolean().optional()
502
- }).passthrough();
503
- const reportingToolResultDetailsSchema = z.object({
504
- ok: z.boolean().optional(),
505
- status: z.string().optional()
506
- }).passthrough();
507
- const reportingTextPartSchema = z.object({
508
- type: z.literal("text"),
509
- text: z.string()
510
- }).passthrough();
511
- const reportingReasoningPartSchema = z.object({
512
- type: z.literal("thinking"),
513
- thinking: z.string(),
514
- redacted: z.literal(true).optional()
515
- }).passthrough();
516
- const reportingMediaPartSchema = z.object({
517
- type: z.enum(["image", "audio"]),
518
- mimeType: z.string().min(1).optional()
519
- }).passthrough();
520
- const reportingMessageAuthorSchema = z.object({
521
- fullName: z.string().min(1).optional(),
522
- userId: z.string().min(1).optional(),
523
- userName: z.string().min(1).optional()
524
- }).passthrough();
525
- /** Retain model-visible text and media descriptors, dropping all opaque fields. */
526
- function sanitizeModelContentPart(value) {
527
- const text = reportingTextPartSchema.safeParse(value);
528
- if (text.success) return {
529
- type: "text",
530
- text: text.data.text
531
- };
532
- const media = reportingMediaPartSchema.safeParse(value);
533
- if (!media.success) return void 0;
534
- return {
535
- type: media.data.type,
536
- ...media.data.mimeType ? { mimeType: media.data.mimeType } : void 0
537
- };
538
- }
539
- /** Convert allowlisted Pi content parts into the reporting result value. */
540
- function modelVisibleToolOutput(content) {
541
- const sanitized = content.map(sanitizeModelContentPart).filter((part) => part !== void 0);
542
- if (sanitized.length === 0) return void 0;
543
- if (sanitized.length !== 1) return sanitized;
544
- const only = sanitized[0];
545
- return only.type === "text" ? only.text : only;
546
- }
547
- function reportMessageActorIdentity(data) {
548
- if (data.role !== "user") return void 0;
549
- const author = reportingMessageAuthorSchema.safeParse(data.meta?.author);
550
- if (!author.success) return void 0;
551
- const actorIdentity = {
552
- ...author.data.fullName ? { fullName: author.data.fullName } : void 0,
553
- ...author.data.userId ? { slackUserId: author.data.userId } : void 0,
554
- ...author.data.userName ? { slackUserName: author.data.userName } : void 0
555
- };
556
- return Object.keys(actorIdentity).length > 0 ? actorIdentity : void 0;
557
- }
558
- /** Project native assistant tool calls through the existing reporting shape. */
559
- function reportToolCalls(args) {
560
- const message = reportingAssistantMessageSchema.safeParse(args.message);
561
- if (!message.success) return void 0;
562
- const calls = message.data.content.flatMap((part) => {
563
- const call = reportingToolCallPartSchema.safeParse(part);
564
- if (!call.success) return [];
565
- return [{
566
- toolCallId: call.data.id,
567
- name: call.data.name,
568
- status: "running",
569
- startedAt: new Date(args.createdAtMs).toISOString(),
570
- startedSeq: args.seq,
571
- ...args.canExposePayload && call.data.arguments !== void 0 ? { input: call.data.arguments } : void 0
572
- }];
573
- });
574
- return calls.length > 0 ? {
575
- type: "tool_calls",
576
- calls
577
- } : void 0;
578
- }
579
- /** Project assistant reasoning with tool ids retained only for display order. */
580
- function reportAssistantMessage(args) {
581
- const message = reportingAssistantMessageSchema.safeParse(args.message);
582
- if (!message.success) return void 0;
583
- if (!message.data.content.some((part) => {
584
- const reasoning = reportingReasoningPartSchema.safeParse(part);
585
- return reasoning.success && reasoning.data.redacted !== true && reasoning.data.thinking.trim().length > 0;
586
- })) return reportToolCalls(args);
587
- const reasoningParts = [];
588
- const assistantParts = [];
589
- for (const part of message.data.content) {
590
- const reasoning = reportingReasoningPartSchema.safeParse(part);
591
- if (reasoning.success) {
592
- if (reasoning.data.redacted !== true && reasoning.data.thinking.trim().length > 0) {
593
- const projected = {
594
- type: "reasoning",
595
- ...args.canExposePayload ? { text: reasoning.data.thinking } : { redacted: true }
596
- };
597
- reasoningParts.push(projected);
598
- assistantParts.push(projected);
599
- }
600
- continue;
601
- }
602
- const call = reportingToolCallPartSchema.safeParse(part);
603
- if (call.success) assistantParts.push({
604
- type: "tool_call",
605
- toolCallId: call.data.id
606
- });
607
- }
608
- const toolCalls = reportToolCalls(args);
609
- if (toolCalls?.type === "tool_calls") return {
610
- ...toolCalls,
611
- assistant: { parts: assistantParts }
612
- };
613
- return reasoningParts.length > 0 ? {
614
- type: "assistant_message",
615
- parts: reasoningParts
616
- } : void 0;
617
- }
618
- /** Project a native tool result without exposing host-only result details. */
619
- function reportToolResult(args) {
620
- const message = reportingToolResultMessageSchema.safeParse(args.message);
621
- if (!message.success) return void 0;
622
- const details = reportingToolResultDetailsSchema.safeParse(message.data.details);
623
- const outcome = message.data.isError === true || details.success && (details.data.ok === false || details.data.status === "error") ? "error" : "completed";
624
- const output = modelVisibleToolOutput(message.data.content);
625
- const name = message.data.toolName ?? message.data.name ?? args.start?.name;
626
- if (!name) return void 0;
627
- return {
628
- type: "tool_calls",
629
- calls: [{
630
- toolCallId: message.data.toolCallId,
631
- name,
632
- status: outcome,
633
- ...args.start ? {
634
- startedAt: new Date(args.start.createdAtMs).toISOString(),
635
- startedSeq: args.start.seq
636
- } : void 0,
637
- ...args.canExposePayload && output !== void 0 ? { output } : void 0
638
- }]
639
- };
640
- }
641
- /** Return tool result ids that may need start metadata from outside a page. */
642
- function conversationReportToolResultIds(events) {
643
- return [...new Set(events.flatMap((event) => {
644
- const result = reportingToolResultMessageSchema.safeParse(event.data);
645
- return result.success ? [result.data.toolCallId] : [];
646
- }))];
647
- }
648
- function reportEventData(args) {
649
- const { data } = args;
650
- if (data.type === "structured_event") {
651
- if (!args.canExposePayload) return void 0;
652
- const presentation = data.namespace === "junior" ? renderJuniorNativeConversationEvent(data) : renderPluginConversationEvent(data);
653
- if (!presentation) return void 0;
654
- return {
655
- type: "structured_event",
656
- namespace: data.namespace,
657
- name: data.name,
658
- version: data.version,
659
- ...data.turnId ? { turnId: data.turnId } : void 0,
660
- presentation
661
- };
662
- }
663
- switch (data.type) {
664
- case "message": {
665
- const actorIdentity = args.canExposePayload ? reportMessageActorIdentity(data) : void 0;
666
- return {
667
- type: "message",
668
- messageId: data.messageId,
669
- role: data.role,
670
- ...data.meta?.source === "web" || data.meta?.source === "slack" ? { source: data.meta.source } : void 0,
671
- ...actorIdentity ? { actorIdentity } : void 0,
672
- ...typeof data.meta?.eventType === "string" ? { eventType: data.meta.eventType } : void 0,
673
- ...typeof data.meta?.explicitMention === "boolean" ? { explicitMention: data.meta.explicitMention } : void 0,
674
- ...args.canExposePayload && typeof data.meta?.trustedSummary === "string" ? { trustedSummary: data.meta.trustedSummary } : void 0,
675
- ...args.canExposePayload ? { text: data.text } : { redacted: true }
676
- };
677
- }
678
- case "message_handled": return {
679
- type: "message_handled",
680
- messageId: data.messageId
681
- };
682
- case "turn_started": return {
683
- type: "turn_lifecycle",
684
- turnId: data.turnId,
685
- state: "started",
686
- ...data.inputMessageIds.length > 0 ? { inputMessageIds: data.inputMessageIds } : void 0
687
- };
688
- case "turn_context":
689
- if (!args.canExposePayload) return;
690
- return {
691
- type: "turn_context",
692
- turnId: data.turnId,
693
- pluginName: data.pluginName,
694
- kind: data.kind,
695
- version: data.version,
696
- content: data.content
697
- };
698
- case "attachments_delivered":
699
- if (!args.canExposePayload) return;
700
- return {
701
- type: "attachments_delivered",
702
- attachments: data.attachments
703
- };
704
- case "turn_routed": return {
705
- type: "turn_routed",
706
- turnId: data.turnId,
707
- modelProfile: data.modelProfile,
708
- modelId: data.modelId,
709
- ...data.costUsd !== void 0 ? { costUsd: data.costUsd } : void 0,
710
- reasoningLevel: data.reasoningLevel,
711
- ...data.confidence !== void 0 ? { confidence: data.confidence } : void 0,
712
- source: data.source
713
- };
714
- case "guardian_action_reviewed": return {
715
- type: "guardian_action_reviewed",
716
- turnId: data.turnId,
717
- toolCallId: data.toolCallId,
718
- toolName: data.toolName,
719
- decision: data.decision,
720
- riskLevel: data.riskLevel,
721
- userAuthorization: data.userAuthorization
722
- };
723
- case "turn_completed": return {
724
- type: "turn_lifecycle",
725
- turnId: data.turnId,
726
- state: data.outcome === "success" ? "succeeded" : "no_reply"
727
- };
728
- case "turn_failed": {
729
- const eventId = data.eventId;
730
- const sentryEventUrl = eventId ? buildSentryEventUrl(eventId) : void 0;
731
- return {
732
- type: "turn_lifecycle",
733
- turnId: data.turnId,
734
- state: "failed",
735
- failureCode: data.failureCode,
736
- ...data.failureReason ? { failureReason: data.failureReason } : void 0,
737
- ...eventId ? { eventId } : void 0,
738
- ...sentryEventUrl ? { sentryEventUrl } : void 0
739
- };
740
- }
741
- case "compaction": return {
742
- type: "compaction",
743
- modelProfile: data.modelProfile,
744
- modelId: data.modelId,
745
- ...args.canExposePayload && data.summary ? { summary: data.summary } : void 0,
746
- ...data.details ? { details: data.details } : void 0
747
- };
748
- default: return;
749
- }
750
- }
751
- /**
752
- * Project canonical events into the ordered reporting boundary.
753
- *
754
- * `canExposePayload` must come from the authorized conversation-detail policy;
755
- * this projection never derives visibility or authorization from event data.
756
- */
757
- function projectConversationReportEventPage(args) {
758
- const subagentStarts = /* @__PURE__ */ new Map();
759
- for (const event of args.subagentStartEvents ?? []) if (event.data.type === "subagent_started") subagentStarts.set(event.data.subagentInvocationId, {
760
- createdAtMs: event.createdAtMs,
761
- data: event.data,
762
- seq: event.seq
763
- });
764
- const toolStarts = /* @__PURE__ */ new Map();
765
- for (const event of args.toolStartEvents ?? []) if (event.data.type === "tool_execution_started") {
766
- const current = toolStarts.get(event.data.toolCallId);
767
- if (!current || event.seq < current.seq) toolStarts.set(event.data.toolCallId, {
768
- createdAtMs: event.createdAtMs,
769
- name: event.data.toolName,
770
- seq: event.seq
771
- });
772
- }
773
- const projected = [];
774
- for (const event of args.events) {
775
- let data;
776
- if (event.data.type === "assistant_message" || event.data.type === "tool_result") {
777
- const reportArgs = {
778
- canExposePayload: args.canExposePayload,
779
- createdAtMs: event.createdAtMs,
780
- message: event.data,
781
- seq: event.seq
782
- };
783
- const result = reportingToolResultMessageSchema.safeParse(event.data);
784
- const start = result.success ? toolStarts.get(result.data.toolCallId) : void 0;
785
- data = reportAssistantMessage(reportArgs) ?? reportToolResult({
786
- canExposePayload: args.canExposePayload,
787
- message: event.data,
788
- ...start && start.seq < event.seq ? { start } : void 0
789
- });
790
- } else if (event.data.type === "tool_execution_started") {
791
- toolStarts.set(event.data.toolCallId, {
792
- createdAtMs: event.createdAtMs,
793
- name: event.data.toolName,
794
- seq: event.seq
795
- });
796
- data = {
797
- type: "tool_calls",
798
- calls: [{
799
- toolCallId: event.data.toolCallId,
800
- name: event.data.toolName,
801
- status: "running",
802
- startedAt: new Date(event.createdAtMs).toISOString(),
803
- startedSeq: event.seq
804
- }]
805
- };
806
- } else if (event.data.type === "subagent_started") {
807
- subagentStarts.set(event.data.subagentInvocationId, {
808
- createdAtMs: event.createdAtMs,
809
- data: event.data,
810
- seq: event.seq
811
- });
812
- data = {
813
- type: "subagent",
814
- startedSeq: event.seq,
815
- startedAt: new Date(event.createdAtMs).toISOString(),
816
- childConversationId: event.data.childConversationId,
817
- subagentKind: event.data.subagentKind,
818
- status: "running",
819
- ...event.data.parentToolCallId ? { parentToolCallId: event.data.parentToolCallId } : void 0
820
- };
821
- } else if (event.data.type === "subagent_ended") {
822
- const started = subagentStarts.get(event.data.subagentInvocationId);
823
- if (started && started.seq < event.seq) {
824
- data = {
825
- type: "subagent",
826
- startedSeq: started.seq,
827
- startedAt: new Date(started.createdAtMs).toISOString(),
828
- childConversationId: started.data.childConversationId,
829
- subagentKind: started.data.subagentKind,
830
- ...started.data.parentToolCallId ? { parentToolCallId: started.data.parentToolCallId } : void 0,
831
- status: event.data.outcome === "success" ? "completed" : event.data.outcome
832
- };
833
- subagentStarts.delete(event.data.subagentInvocationId);
834
- }
835
- } else if (event.data.type === "handoff") data = {
836
- type: "handoff",
837
- modelProfile: event.data.modelProfile,
838
- modelId: event.data.modelId,
839
- ...event.data.reasoningLevel ? { reasoningLevel: event.data.reasoningLevel } : void 0,
840
- ...event.data.triggeringToolCallId ? { triggeringToolCallId: event.data.triggeringToolCallId } : void 0,
841
- ...args.canExposePayload && event.data.summary ? { summary: event.data.summary } : void 0
842
- };
843
- else data = reportEventData({
844
- canExposePayload: args.canExposePayload,
845
- data: event.data
846
- });
847
- if (!data) continue;
848
- projected.push(conversationReportEventSchema.parse({
849
- seq: event.seq,
850
- createdAt: new Date(event.createdAtMs).toISOString(),
851
- data
852
- }));
853
- }
854
- return projected;
855
- }
856
- //#endregion
857
- //#region src/api/conversations/event-page.ts
858
- const conversationEventColumns = getTableColumns(juniorConversationEvents);
859
- const MIN_SCAN_SIZE = 64;
860
- /** Read bounded canonical rows while excluding model-only replacement history. */
861
- async function readConversationEventRows(executor, args) {
862
- return executor.db().select({
863
- ...conversationEventColumns,
864
- payload: sql`case
865
- when ${juniorConversationEvents.type} in ('compaction', 'handoff')
866
- then jsonb_set(
867
- ${juniorConversationEvents.payload},
868
- '{replacementHistory}',
869
- '[]'::jsonb
870
- )
871
- else ${juniorConversationEvents.payload}
872
- end`
873
- }).from(juniorConversationEvents).where(and(eq(juniorConversationEvents.conversationId, args.conversationId), args.beforeSeq === void 0 ? void 0 : lt(juniorConversationEvents.seq, args.beforeSeq), inArray(juniorConversationEvents.type, args.types ?? [...conversationReportSourceEventTypes]), args.subagentInvocationIds === void 0 ? void 0 : inArray(sql`${juniorConversationEvents.payload}->>'subagentInvocationId'`, args.subagentInvocationIds), args.toolCallIds === void 0 ? void 0 : inArray(sql`${juniorConversationEvents.payload}->>'toolCallId'`, args.toolCallIds))).orderBy(args.direction === "forward" ? asc(juniorConversationEvents.seq) : desc(juniorConversationEvents.seq)).limit(args.limit);
874
- }
875
- function decodeConversationEventRow(row) {
876
- return decodeStoredConversationEvent({
877
- schemaVersion: row.schemaVersion,
878
- seq: row.seq,
879
- historyVersion: row.historyVersion,
880
- ...row.idempotencyKey ? { idempotencyKey: row.idempotencyKey } : void 0,
881
- createdAtMs: row.createdAt.getTime(),
882
- type: row.type,
883
- payload: row.payload
884
- });
885
- }
886
- /** Project stored rows and resolve entity starts that precede the page. */
887
- async function projectConversationEventRows(executor, args) {
888
- const events = args.rows.map(decodeConversationEventRow).sort((left, right) => left.seq - right.seq);
889
- const endedInvocationIds = [...new Set(events.flatMap((event) => event.data.type === "subagent_ended" ? [event.data.subagentInvocationId] : []))];
890
- const subagentStartRows = endedInvocationIds.length === 0 ? [] : await readConversationEventRows(executor, {
891
- conversationId: args.conversationId,
892
- direction: "forward",
893
- limit: endedInvocationIds.length,
894
- subagentInvocationIds: endedInvocationIds,
895
- types: ["subagent_started"]
896
- });
897
- const toolResultIds = conversationReportToolResultIds(events);
898
- const toolStartRows = toolResultIds.length === 0 ? [] : await readConversationEventRows(executor, {
899
- conversationId: args.conversationId,
900
- direction: "forward",
901
- limit: toolResultIds.length,
902
- toolCallIds: toolResultIds,
903
- types: ["tool_execution_started"]
904
- });
905
- return projectConversationReportEventPage({
906
- canExposePayload: args.canExposePayload,
907
- events,
908
- subagentStartEvents: subagentStartRows.map(decodeConversationEventRow),
909
- toolStartEvents: toolStartRows.map(decodeConversationEventRow)
910
- });
911
- }
912
- /**
913
- * Read the latest reporting events before an exclusive boundary.
914
- *
915
- * Source rows are scanned in bounded chunks until the requested projected page
916
- * and one older event are known. This keeps ordinary pages bounded without
917
- * assuming every agent history event produces a reporting event.
918
- */
919
- async function readConversationEventPage(executor, args) {
920
- const scanSize = Math.max(args.limit + 1, MIN_SCAN_SIZE);
921
- const rows = [];
922
- let beforeSeq = args.beforeSeq;
923
- let projected = [];
924
- while (projected.length <= args.limit) {
925
- const batch = await readConversationEventRows(executor, {
926
- beforeSeq,
927
- conversationId: args.conversationId,
928
- direction: "backward",
929
- limit: scanSize
930
- });
931
- if (batch.length === 0) break;
932
- rows.push(...batch);
933
- projected = await projectConversationEventRows(executor, {
934
- canExposePayload: args.canExposePayload,
935
- conversationId: args.conversationId,
936
- rows
937
- });
938
- if (projected.length > args.limit || batch.length < scanSize) break;
939
- beforeSeq = batch.at(-1).seq;
940
- }
941
- const events = projected.slice(-args.limit);
942
- return {
943
- events,
944
- ...projected.length > events.length && events[0] ? { previousSeq: events[0].seq } : void 0
945
- };
946
- }
947
- //#endregion
948
463
  //#region src/api/conversations/shared.ts
949
464
  /** Format a Slack destination without exposing private channel names. */
950
465
  function slackStatsLocationLabel(input) {
@@ -1389,19 +904,18 @@ async function readConversationActivityPreviews(db, conversationIds) {
1389
904
  //#endregion
1390
905
  //#region src/api/conversations/list.ts
1391
906
  const CONVERSATION_FEED_LIMIT = 50;
1392
- const RECENT_ARCHIVE_WINDOW_MS = 1728e5;
1393
- function conversationFeedMembershipFilter(status, filter, archivedAfter) {
907
+ function conversationFeedMembershipFilter(status, filter) {
1394
908
  if (!filter) return status === "archived" ? sql`false` : void 0;
1395
909
  if (filter.kind === "viewer") return and(viewerConversationMembership({
1396
910
  actorMatch: eq(juniorIdentities.userId, filter.userId),
1397
911
  participantMatch: conversationHasParticipantUser(filter.userId)
1398
- }), status === "archived" ? conversationArchivedForUser(filter.userId) : status === "all" ? void 0 : or(conversationNotArchivedForUser(filter.userId), conversationArchivedForUser(filter.userId, archivedAfter)));
912
+ }), status === "archived" ? conversationArchivedForUser(filter.userId) : status === "all" ? void 0 : conversationNotArchivedForUser(filter.userId));
1399
913
  return and(viewerConversationMembership({
1400
914
  actorMatch: eq(juniorUsers.primaryEmailNormalized, filter.email),
1401
915
  participantMatch: conversationHasParticipantEmail(filter.email)
1402
- }), status === "archived" ? conversationArchivedForEmail(filter.email) : status === "all" ? void 0 : or(conversationNotArchivedForEmail(filter.email), conversationArchivedForEmail(filter.email, archivedAfter)));
916
+ }), status === "archived" ? conversationArchivedForEmail(filter.email) : status === "all" ? void 0 : conversationNotArchivedForEmail(filter.email));
1403
917
  }
1404
- async function conversationRows(db, limit, status, filter, archivedAfter, query) {
918
+ async function conversationRows(db, limit, status, filter, query, includePrivateBriefs = false) {
1405
919
  return db.select({
1406
920
  conversation: conversationReadColumns(),
1407
921
  location: juniorDestinations,
@@ -1412,7 +926,19 @@ async function conversationRows(db, limit, status, filter, archivedAfter, query)
1412
926
  identitySubjectId: juniorIdentities.providerSubjectId,
1413
927
  identityTenantId: juniorIdentities.providerTenantId,
1414
928
  userDisplayName: juniorUsers.displayName
1415
- }).from(juniorConversations).leftJoin(juniorDestinations, eq(juniorDestinations.id, juniorConversations.destinationId)).leftJoin(juniorIdentities, eq(juniorIdentities.id, juniorConversations.actorIdentityId)).leftJoin(juniorUsers, eq(juniorUsers.id, juniorIdentities.userId)).where(and(isNull(juniorConversations.parentConversationId), conversationFeedMembershipFilter(status, filter, archivedAfter), query ? sql`strpos(lower(coalesce(${juniorConversations.title}, '')), ${query}) > 0` : void 0)).orderBy(desc(juniorConversations.lastActivityAt), asc(juniorConversations.conversationId)).limit(limit);
929
+ }).from(juniorConversations).leftJoin(juniorDestinations, eq(juniorDestinations.id, juniorConversations.destinationId)).leftJoin(juniorIdentities, eq(juniorIdentities.id, juniorConversations.actorIdentityId)).leftJoin(juniorUsers, eq(juniorUsers.id, juniorIdentities.userId)).where(and(isNull(juniorConversations.parentConversationId), conversationFeedMembershipFilter(status, filter), query ? or(sql`strpos(lower(coalesce(${juniorConversations.title}, '')), ${query}) > 0`, sql`exists (
930
+ select 1
931
+ from ${juniorConversationBriefs}
932
+ where ${juniorConversationBriefs.conversationId} = ${juniorConversations.conversationId}
933
+ and ${includePrivateBriefs ? sql`true` : eq(juniorDestinations.visibility, "public")}
934
+ and ${juniorConversationBriefs.version} = (
935
+ select max(${juniorConversationBriefs.version})
936
+ from ${juniorConversationBriefs}
937
+ where ${juniorConversationBriefs.conversationId} = ${juniorConversations.conversationId}
938
+ )
939
+ and to_tsvector('english', ${juniorConversationBriefs.searchText})
940
+ @@ websearch_to_tsquery('english', ${query})
941
+ )`) : void 0)).orderBy(desc(juniorConversations.lastActivityAt), asc(juniorConversations.conversationId)).limit(limit);
1416
942
  }
1417
943
  /** Decode a conversation row with the linked user name and identity-scoped provider fields. */
1418
944
  function conversationFromRow(row) {
@@ -1490,7 +1016,7 @@ async function readConversationFeedFromSql(options = {}) {
1490
1016
  const db = getDb();
1491
1017
  const filter = conversationFeedFilter(options);
1492
1018
  const query = options.q?.trim().toLowerCase() || void 0;
1493
- const rows = await conversationRows(db, options.limit ?? CONVERSATION_FEED_LIMIT, query ? "all" : options.status ?? "active", filter, /* @__PURE__ */ new Date(nowMs - RECENT_ARCHIVE_WINDOW_MS), query);
1019
+ const rows = await conversationRows(db, options.limit ?? CONVERSATION_FEED_LIMIT, query ? "all" : options.status ?? "active", filter, query, filter?.kind === "viewer");
1494
1020
  const conversations = rows.map((row) => conversationFromRow(row));
1495
1021
  const conversationIds = conversations.map((conversation) => conversation.conversationId);
1496
1022
  const [accessByConversation, archiveTimesByConversation, annotationsByConversation, auxiliaryCostsByRoot, metricsByRoot, teamDomainByTeamId, conversationWork, lastUserMessageAtByConversation, activityPreviewByConversation] = await Promise.all([
@@ -1555,23 +1081,23 @@ async function readConversationFeed(options = {}) {
1555
1081
  return conversationFeedSchema.parse(await readConversationFeedFromSql(options));
1556
1082
  }
1557
1083
  //#endregion
1558
- //#region src/chat/scheduled-tasks/personal.ts
1084
+ //#region src/chat/scheduled-automations/personal.ts
1559
1085
  const cursorSchema = z.object({
1560
1086
  createdAtMs: z.number().finite(),
1561
1087
  id: z.string().min(1),
1562
1088
  query: z.string().max(200).optional(),
1563
1089
  version: z.literal(1)
1564
1090
  }).strict();
1565
- var InvalidScheduledTaskCursorError = class extends Error {
1091
+ var InvalidScheduledAutomationCursorError = class extends Error {
1566
1092
  constructor() {
1567
- super("Scheduled task cursor is invalid.");
1568
- this.name = "InvalidScheduledTaskCursorError";
1093
+ super("Scheduled automation cursor is invalid.");
1094
+ this.name = "InvalidScheduledAutomationCursorError";
1569
1095
  }
1570
1096
  };
1571
- var PersonalScheduledTaskNotFoundError = class extends Error {
1097
+ var PersonalScheduledAutomationNotFoundError = class extends Error {
1572
1098
  constructor() {
1573
- super("Scheduled task was not found.");
1574
- this.name = "PersonalScheduledTaskNotFoundError";
1099
+ super("Scheduled automation was not found.");
1100
+ this.name = "PersonalScheduledAutomationNotFoundError";
1575
1101
  }
1576
1102
  };
1577
1103
  function normalizeQuery(query) {
@@ -1581,13 +1107,13 @@ function decodeCursor(value, query) {
1581
1107
  if (!value) return void 0;
1582
1108
  try {
1583
1109
  const parsed = cursorSchema.parse(JSON.parse(Buffer.from(value, "base64url").toString("utf8")));
1584
- if (parsed.query !== query) throw new InvalidScheduledTaskCursorError();
1110
+ if (parsed.query !== query) throw new InvalidScheduledAutomationCursorError();
1585
1111
  return {
1586
1112
  createdAtMs: parsed.createdAtMs,
1587
1113
  id: parsed.id
1588
1114
  };
1589
1115
  } catch {
1590
- throw new InvalidScheduledTaskCursorError();
1116
+ throw new InvalidScheduledAutomationCursorError();
1591
1117
  }
1592
1118
  }
1593
1119
  function encodeCursor(task, query) {
@@ -1598,12 +1124,12 @@ function encodeCursor(task, query) {
1598
1124
  version: 1
1599
1125
  }), "utf8").toString("base64url");
1600
1126
  }
1601
- /** Delete one scheduled task created by the viewer. */
1602
- async function deleteViewerScheduledTask(db, user, id, nowMs = Date.now()) {
1127
+ /** Delete one scheduled automation created by the viewer. */
1128
+ async function deleteViewerScheduledAutomation(db, user, id, nowMs = Date.now()) {
1603
1129
  const identityIds = new Set(user.identities.map((identity) => identity.id));
1604
- const task = await readScheduledTask(db, id);
1605
- if (!task || task.status === "deleted" || !identityIds.has(task.creatorIdentityId)) throw new PersonalScheduledTaskNotFoundError();
1606
- await saveScheduledTask(db, {
1130
+ const task = await readScheduledAutomation(db, id);
1131
+ if (!task || task.status === "deleted" || !identityIds.has(task.creatorIdentityId)) throw new PersonalScheduledAutomationNotFoundError();
1132
+ await saveScheduledAutomation(db, {
1607
1133
  ...task,
1608
1134
  nextRunAtMs: void 0,
1609
1135
  runNowAtMs: void 0,
@@ -1611,16 +1137,16 @@ async function deleteViewerScheduledTask(db, user, id, nowMs = Date.now()) {
1611
1137
  updatedAtMs: nowMs
1612
1138
  });
1613
1139
  }
1614
- /** List scheduled tasks created by the viewer with a stable SQL cursor. */
1615
- async function listViewerScheduledTasks(db, user, input) {
1140
+ /** List scheduled automations created by the viewer with a stable SQL cursor. */
1141
+ async function listViewerScheduledAutomations(db, user, input) {
1616
1142
  const identityIds = user.identities.map((identity) => identity.id);
1617
- if (identityIds.length === 0) return { tasks: [] };
1143
+ if (identityIds.length === 0) return { automations: [] };
1618
1144
  const query = normalizeQuery(input.query);
1619
1145
  const cursor = decodeCursor(input.cursor, query);
1620
- const tasks = [];
1146
+ const automations = [];
1621
1147
  let before = cursor;
1622
1148
  const fetchLimit = input.limit + 1;
1623
- while (tasks.length < fetchLimit) {
1149
+ while (automations.length < fetchLimit) {
1624
1150
  const cursorFilter = before ? or(lt(juniorSchedulerTasks.createdAtMs, before.createdAtMs), and(eq(juniorSchedulerTasks.createdAtMs, before.createdAtMs), lt(juniorSchedulerTasks.id, before.id))) : void 0;
1625
1151
  const search = query ? sql`strpos(lower(coalesce(${juniorSchedulerTasks.title}, ${juniorSchedulerTasks.record}->'task'->>'text')), ${query}) > 0` : void 0;
1626
1152
  const rows = await db.select({
@@ -1630,7 +1156,7 @@ async function listViewerScheduledTasks(db, user, input) {
1630
1156
  record: juniorSchedulerTasks.record,
1631
1157
  title: juniorSchedulerTasks.title
1632
1158
  }).from(juniorSchedulerTasks).where(and(notInArray(juniorSchedulerTasks.status, ["deleted", "paused"]), inArray(juniorSchedulerTasks.creatorIdentityId, identityIds), cursorFilter, search)).orderBy(desc(juniorSchedulerTasks.createdAtMs), desc(juniorSchedulerTasks.id)).limit(fetchLimit);
1633
- tasks.push(...rows.map(parseScheduledTaskRow).filter(isListedScheduledTask));
1159
+ automations.push(...rows.map(parseScheduledAutomationRow).filter(isListedScheduledAutomation));
1634
1160
  if (rows.length < fetchLimit) break;
1635
1161
  const last = rows.at(-1);
1636
1162
  before = {
@@ -1638,14 +1164,14 @@ async function listViewerScheduledTasks(db, user, input) {
1638
1164
  id: last.id
1639
1165
  };
1640
1166
  }
1641
- const page = tasks.slice(0, input.limit);
1167
+ const page = automations.slice(0, input.limit);
1642
1168
  return {
1643
- tasks: page,
1644
- ...tasks.length > input.limit && page.length > 0 ? { nextCursor: encodeCursor(page.at(-1), query) } : void 0
1169
+ automations: page,
1170
+ ...automations.length > input.limit && page.length > 0 ? { nextCursor: encodeCursor(page.at(-1), query) } : void 0
1645
1171
  };
1646
1172
  }
1647
1173
  //#endregion
1648
- //#region src/chat/tasks/read.ts
1174
+ //#region src/chat/automations/read.ts
1649
1175
  const TASK_LIST_LIMIT = 100;
1650
1176
  const TASK_FETCH_LIMIT = 101;
1651
1177
  const TASK_EXECUTION_LIST_LIMIT = 100;
@@ -1706,14 +1232,14 @@ function executionSummaryFields(stats) {
1706
1232
  return {
1707
1233
  ...stats?.lastConversationId ? { lastConversationId: stats.lastConversationId } : void 0,
1708
1234
  ...stats?.lastExecutedAtMs ? { lastRunAt: new Date(stats.lastExecutedAtMs).toISOString() } : void 0,
1709
- runs: stats?.runs ?? emptyTaskRunWindows(),
1235
+ runs: stats?.runs ?? emptyAutomationRunWindows(),
1710
1236
  totalRuns: stats?.totalRuns ?? 0
1711
1237
  };
1712
1238
  }
1713
- function scheduledTaskSummary(task, ownedByViewer, destination, stats, createdByEmail) {
1714
- if (task.status === "deleted") throw new Error("Deleted scheduled tasks cannot enter the Tasks view");
1239
+ function scheduledAutomationSummary(task, ownedByViewer, destination, stats, createdByEmail) {
1240
+ if (task.status === "deleted") throw new Error("Deleted scheduled automations cannot enter the Automations view");
1715
1241
  const nextRunAtMs = task.runNowAtMs ?? task.nextRunAtMs;
1716
- const instruction = displayText(task.task.text, "Untitled scheduled task");
1242
+ const instruction = displayText(task.task.text, "Untitled scheduled automation");
1717
1243
  return {
1718
1244
  createdAt: new Date(task.createdAtMs).toISOString(),
1719
1245
  createdBy: creatorLabel(task.createdBy),
@@ -1733,10 +1259,10 @@ function scheduledTaskSummary(task, ownedByViewer, destination, stats, createdBy
1733
1259
  schedule: displayText(task.schedule.description, "Schedule unavailable"),
1734
1260
  status: task.status,
1735
1261
  outcomes: effectiveTaskOutcomes(task.outcomes, task.destination),
1736
- title: taskDisplayTitle(task.title, instruction, "Untitled scheduled task")
1262
+ title: taskDisplayTitle(task.title, instruction, "Untitled scheduled automation")
1737
1263
  };
1738
1264
  }
1739
- function eventTaskSummary(task, ownedByViewer, destination, stats, createdByEmail) {
1265
+ function eventAutomationSummary(task, ownedByViewer, destination, stats, createdByEmail) {
1740
1266
  const instruction = task.task.text;
1741
1267
  return {
1742
1268
  createdAt: new Date(task.createdAtMs).toISOString(),
@@ -1757,8 +1283,8 @@ function eventTaskSummary(task, ownedByViewer, destination, stats, createdByEmai
1757
1283
  resource: `${task.trigger.label} · ${task.trigger.identifier}`,
1758
1284
  source: task.trigger.namespace,
1759
1285
  outcomes: effectiveTaskOutcomes(task.outcomes, task.destination),
1760
- title: taskDisplayTitle(task.title, instruction, "Untitled event task"),
1761
- triggerAvailable: eventTaskTriggerAvailable(task, getResourceEventCatalog())
1286
+ title: taskDisplayTitle(task.title, instruction, "Untitled event automation"),
1287
+ triggerAvailable: eventAutomationTriggerAvailable(task, getEventCatalog())
1762
1288
  };
1763
1289
  }
1764
1290
  function viewerTeamIds(user) {
@@ -1769,7 +1295,7 @@ async function resolveViewerTaskCandidate(user, kind, id) {
1769
1295
  const identityIds = new Set(user.identities.map((identity) => identity.id));
1770
1296
  const teamIds = viewerTeamIds(user);
1771
1297
  if (kind === "scheduled") {
1772
- const task = await readScheduledTask(db, id);
1298
+ const task = await readScheduledAutomation(db, id);
1773
1299
  if (!task || task.status === "deleted") return void 0;
1774
1300
  const ownedByViewer = identityIds.has(task.creatorIdentityId);
1775
1301
  const destination = (await destinationDetails([task.destination])).get(destinationKey(task.destination));
@@ -1782,9 +1308,9 @@ async function resolveViewerTaskCandidate(user, kind, id) {
1782
1308
  task
1783
1309
  };
1784
1310
  }
1785
- const task = await getEventTask(db, id);
1311
+ const task = await getEventAutomation(db, id);
1786
1312
  if (!task || task.status === "deleted") return void 0;
1787
- const ownedByViewer = eventTaskBelongsToUser(task, user);
1313
+ const ownedByViewer = eventAutomationBelongsToUser(task, user);
1788
1314
  const destination = (await destinationDetails([task.destination])).get(destinationKey(task.destination));
1789
1315
  const publicToViewer = teamIds.includes(task.destination.teamId) && destination?.visibility === "public";
1790
1316
  if (!ownedByViewer && !publicToViewer) return void 0;
@@ -1795,22 +1321,22 @@ async function resolveViewerTaskCandidate(user, kind, id) {
1795
1321
  task
1796
1322
  };
1797
1323
  }
1798
- async function taskSummaryForCandidate(candidate) {
1324
+ async function automationSummaryForCandidate(candidate) {
1799
1325
  const [destinations, creatorEmails, stats] = await Promise.all([
1800
1326
  destinationDetails([candidate.task.destination]),
1801
1327
  creatorProfileEmails([candidate]),
1802
- readTaskExecutionSummaries(candidate.kind, "junior")
1328
+ readAutomationExecutionSummaries(candidate.kind, "junior")
1803
1329
  ]);
1804
1330
  const destination = destinations.get(destinationKey(candidate.task.destination)) ?? {
1805
1331
  label: `Channel ${candidate.task.destination.channelId}`,
1806
1332
  visibility: "private"
1807
1333
  };
1808
1334
  const createdByEmail = creatorEmails.get(creatorKey(candidate.task.destination.teamId, candidate.task.createdBy.slackUserId));
1809
- if (candidate.kind === "scheduled") return scheduledTaskSummary(candidate.task, candidate.ownedByViewer, destination, stats.get(candidate.task.id), createdByEmail);
1810
- return eventTaskSummary(candidate.task, candidate.ownedByViewer, destination, stats.get(candidate.task.id), createdByEmail);
1335
+ if (candidate.kind === "scheduled") return scheduledAutomationSummary(candidate.task, candidate.ownedByViewer, destination, stats.get(candidate.task.id), createdByEmail);
1336
+ return eventAutomationSummary(candidate.task, candidate.ownedByViewer, destination, stats.get(candidate.task.id), createdByEmail);
1811
1337
  }
1812
- /** Read viewer-owned and public-workspace tasks as one bounded newest-first projection. */
1813
- function emptyTaskExecutionDay(date) {
1338
+ /** Read viewer-owned and public-workspace automations as one bounded newest-first projection. */
1339
+ function emptyAutomationExecutionDay(date) {
1814
1340
  return {
1815
1341
  costUsd: 0,
1816
1342
  date,
@@ -1818,7 +1344,7 @@ function emptyTaskExecutionDay(date) {
1818
1344
  scheduled: 0
1819
1345
  };
1820
1346
  }
1821
- function emptyTaskExecutionStatusDay(date) {
1347
+ function emptyAutomationExecutionStatusDay(date) {
1822
1348
  return {
1823
1349
  blocked: 0,
1824
1350
  completed: 0,
@@ -1826,51 +1352,51 @@ function emptyTaskExecutionStatusDay(date) {
1826
1352
  failed: 0
1827
1353
  };
1828
1354
  }
1829
- function taskExecutionSixHours(hours, nowMs = Date.now()) {
1355
+ function automationExecutionSixHours(hours, nowMs = Date.now()) {
1830
1356
  return sumUtcHoursIntoSixHours({
1831
- empty: emptyTaskExecutionDay,
1357
+ empty: emptyAutomationExecutionDay,
1832
1358
  hours,
1833
1359
  nowMs
1834
1360
  });
1835
1361
  }
1836
- function taskExecutionStatusSixHours(hours, nowMs = Date.now()) {
1362
+ function automationExecutionStatusSixHours(hours, nowMs = Date.now()) {
1837
1363
  return sumUtcHoursIntoSixHours({
1838
- empty: emptyTaskExecutionStatusDay,
1364
+ empty: emptyAutomationExecutionStatusDay,
1839
1365
  hours,
1840
1366
  nowMs
1841
1367
  });
1842
1368
  }
1843
- /** List one viewer's scheduled and event tasks, optionally filtered by title or instruction search. */
1844
- async function readViewerTasks(user, input = {}) {
1369
+ /** List one viewer's scheduled and event automations, optionally filtered by title or instruction search. */
1370
+ async function readViewerAutomations(user, input = {}) {
1845
1371
  const db = getDb();
1846
1372
  const query = input.q?.trim().toLowerCase() || void 0;
1847
1373
  const identityIds = new Set(user.identities.map((identity) => identity.id));
1848
1374
  const teamIds = viewerTeamIds(user);
1849
- const [scheduledPage, publicScheduled, eventTasks, publicEventTasks] = await Promise.all([
1850
- listViewerScheduledTasks(db, user, {
1375
+ const [scheduledPage, publicScheduled, eventAutomations, publicEventAutomations] = await Promise.all([
1376
+ listViewerScheduledAutomations(db, user, {
1851
1377
  limit: TASK_FETCH_LIMIT,
1852
1378
  query
1853
1379
  }),
1854
- listPublicScheduledTasksForTeams(db, teamIds, {
1380
+ listPublicScheduledAutomationsForTeams(db, teamIds, {
1855
1381
  limit: TASK_FETCH_LIMIT,
1856
1382
  query
1857
1383
  }),
1858
- listEventTasksCreatedBy(db, user, TASK_FETCH_LIMIT, query),
1859
- listPublicEventTasksForTeams(db, teamIds, TASK_FETCH_LIMIT, query)
1384
+ listEventAutomationsCreatedBy(db, user, TASK_FETCH_LIMIT, query),
1385
+ listPublicEventAutomationsForTeams(db, teamIds, TASK_FETCH_LIMIT, query)
1860
1386
  ]);
1861
1387
  const candidatesById = /* @__PURE__ */ new Map();
1862
1388
  const publicScheduledIds = new Set(publicScheduled.map((task) => task.id));
1863
- const publicEventTaskIds = new Set(publicEventTasks.map((task) => task.id));
1864
- for (const task of [...scheduledPage.tasks, ...publicScheduled]) candidatesById.set(`scheduled:${task.id}`, {
1389
+ const publicEventAutomationIds = new Set(publicEventAutomations.map((task) => task.id));
1390
+ for (const task of [...scheduledPage.automations, ...publicScheduled]) candidatesById.set(`scheduled:${task.id}`, {
1865
1391
  kind: "scheduled",
1866
1392
  ownedByViewer: identityIds.has(task.creatorIdentityId),
1867
1393
  publicToViewer: publicScheduledIds.has(task.id),
1868
1394
  task
1869
1395
  });
1870
- for (const task of [...eventTasks, ...publicEventTasks]) candidatesById.set(`event:${task.id}`, {
1396
+ for (const task of [...eventAutomations, ...publicEventAutomations]) candidatesById.set(`event:${task.id}`, {
1871
1397
  kind: "event",
1872
- ownedByViewer: eventTaskBelongsToUser(task, user),
1873
- publicToViewer: publicEventTaskIds.has(task.id),
1398
+ ownedByViewer: eventAutomationBelongsToUser(task, user),
1399
+ publicToViewer: publicEventAutomationIds.has(task.id),
1874
1400
  task
1875
1401
  });
1876
1402
  const candidates = [...candidatesById.values()].sort((left, right) => right.task.createdAtMs - left.task.createdAtMs || right.task.id.localeCompare(left.task.id));
@@ -1881,30 +1407,30 @@ async function readViewerTasks(user, input = {}) {
1881
1407
  const [destinations, creatorEmails] = await Promise.all([destinationDetails(selected.map(({ task }) => task.destination)), creatorProfileEmails(selected)]);
1882
1408
  const visible = selected.filter((candidate) => candidate.ownedByViewer || destinations.get(destinationKey(candidate.task.destination))?.visibility === "public");
1883
1409
  const [executionDays, executionHours, scheduledStats, eventStats] = await Promise.all([
1884
- readTaskExecutionDays(),
1885
- readTaskExecutionHours(),
1886
- readTaskExecutionSummaries("scheduled", "junior"),
1887
- readTaskExecutionSummaries("event", "junior")
1410
+ readAutomationExecutionDays(),
1411
+ readAutomationExecutionHours(),
1412
+ readAutomationExecutionSummaries("scheduled", "junior"),
1413
+ readAutomationExecutionSummaries("event", "junior")
1888
1414
  ]);
1889
- const tasks = visible.map((candidate) => {
1415
+ const automations = visible.map((candidate) => {
1890
1416
  const destination = destinations.get(destinationKey(candidate.task.destination)) ?? {
1891
1417
  label: `Channel ${candidate.task.destination.channelId}`,
1892
1418
  visibility: "private"
1893
1419
  };
1894
1420
  const createdByEmail = creatorEmails.get(creatorKey(candidate.task.destination.teamId, candidate.task.createdBy.slackUserId));
1895
- if (candidate.kind === "scheduled") return scheduledTaskSummary(candidate.task, candidate.ownedByViewer, destination, scheduledStats.get(candidate.task.id), createdByEmail);
1896
- return eventTaskSummary(candidate.task, candidate.ownedByViewer, destination, eventStats.get(candidate.task.id), createdByEmail);
1421
+ if (candidate.kind === "scheduled") return scheduledAutomationSummary(candidate.task, candidate.ownedByViewer, destination, scheduledStats.get(candidate.task.id), createdByEmail);
1422
+ return eventAutomationSummary(candidate.task, candidate.ownedByViewer, destination, eventStats.get(candidate.task.id), createdByEmail);
1897
1423
  });
1898
1424
  return {
1899
1425
  executionDays,
1900
1426
  executionHours,
1901
- executionSixHours: taskExecutionSixHours(executionHours),
1902
- tasks,
1427
+ executionSixHours: automationExecutionSixHours(executionHours),
1428
+ automations,
1903
1429
  truncated: ownedCandidates.length > TASK_LIST_LIMIT || publicCandidates.length > TASK_LIST_LIMIT
1904
1430
  };
1905
1431
  }
1906
- /** Load deleted scheduled tasks the viewer still owns, newest first. */
1907
- async function readDeletedOwnedScheduledTasks(user) {
1432
+ /** Load deleted scheduled automations the viewer still owns, newest first. */
1433
+ async function readDeletedOwnedScheduledAutomations(user) {
1908
1434
  const identityIds = user.identities.map((identity) => identity.id);
1909
1435
  if (identityIds.length === 0) return [];
1910
1436
  return (await getDb().select({
@@ -1912,68 +1438,68 @@ async function readDeletedOwnedScheduledTasks(user) {
1912
1438
  id: juniorSchedulerTasks.id,
1913
1439
  record: juniorSchedulerTasks.record,
1914
1440
  title: juniorSchedulerTasks.title
1915
- }).from(juniorSchedulerTasks).where(and(eq(juniorSchedulerTasks.status, "deleted"), inArray(juniorSchedulerTasks.creatorIdentityId, identityIds))).orderBy(desc(juniorSchedulerTasks.createdAtMs), desc(juniorSchedulerTasks.id)).limit(TASK_EXECUTION_LIST_LIMIT)).map(parseScheduledTaskRow).filter((task) => task?.status === "deleted");
1441
+ }).from(juniorSchedulerTasks).where(and(eq(juniorSchedulerTasks.status, "deleted"), inArray(juniorSchedulerTasks.creatorIdentityId, identityIds))).orderBy(desc(juniorSchedulerTasks.createdAtMs), desc(juniorSchedulerTasks.id)).limit(TASK_EXECUTION_LIST_LIMIT)).map(parseScheduledAutomationRow).filter((task) => task?.status === "deleted");
1916
1442
  }
1917
- /** Load deleted event tasks the viewer still owns, newest first. */
1918
- async function readDeletedOwnedEventTasks(user) {
1919
- return await listDeletedEventTasksCreatedBy(getDb(), user, TASK_EXECUTION_LIST_LIMIT);
1443
+ /** Load deleted event automations the viewer still owns, newest first. */
1444
+ async function readDeletedOwnedEventAutomations(user) {
1445
+ return await listDeletedEventAutomationsCreatedBy(getDb(), user, TASK_EXECUTION_LIST_LIMIT);
1920
1446
  }
1921
- function taskTitleForRun(run, taskTitles) {
1922
- return taskTitles.get(`${run.kind}:${run.taskId}`) ?? run.title?.trim() ?? "Untitled task";
1447
+ function automationTitleForRun(run, automationTitles) {
1448
+ return automationTitles.get(`${run.kind}:${run.automationId}`) ?? run.title?.trim() ?? "Untitled task";
1923
1449
  }
1924
- function addDeletedTaskRun(args, taskTitles, tasks) {
1925
- const key = `${args.kind}:${args.taskId}`;
1926
- if (taskTitles.has(key)) return;
1927
- taskTitles.set(key, args.title);
1928
- tasks.push({
1450
+ function addDeletedAutomationRun(args, automationTitles, automations) {
1451
+ const key = `${args.kind}:${args.automationId}`;
1452
+ if (automationTitles.has(key)) return;
1453
+ automationTitles.set(key, args.title);
1454
+ automations.push({
1929
1455
  kind: args.kind,
1930
- taskId: args.taskId
1456
+ automationId: args.automationId
1931
1457
  });
1932
1458
  }
1933
1459
  /**
1934
- * Read newest runs across live viewer-visible tasks and deleted tasks the
1460
+ * Read newest runs across live viewer-visible automations and deleted automations the
1935
1461
  * viewer owns. Deleted task rows stay available so history does not depend on
1936
1462
  * conversation actor membership.
1937
1463
  */
1938
- async function readViewerTaskRuns(user) {
1464
+ async function readViewerAutomationRuns(user) {
1939
1465
  const [taskList, deletedScheduled, deletedEvent] = await Promise.all([
1940
- readViewerTasks(user),
1941
- readDeletedOwnedScheduledTasks(user),
1942
- readDeletedOwnedEventTasks(user)
1466
+ readViewerAutomations(user),
1467
+ readDeletedOwnedScheduledAutomations(user),
1468
+ readDeletedOwnedEventAutomations(user)
1943
1469
  ]);
1944
- const taskTitles = /* @__PURE__ */ new Map();
1945
- const tasks = [];
1946
- for (const task of taskList.tasks) {
1947
- taskTitles.set(`${task.kind}:${task.id}`, task.title);
1948
- tasks.push({
1470
+ const automationTitles = /* @__PURE__ */ new Map();
1471
+ const automations = [];
1472
+ for (const task of taskList.automations) {
1473
+ automationTitles.set(`${task.kind}:${task.id}`, task.title);
1474
+ automations.push({
1949
1475
  kind: task.kind,
1950
- taskId: task.id
1476
+ automationId: task.id
1951
1477
  });
1952
1478
  }
1953
1479
  for (const task of deletedScheduled) {
1954
- const instruction = displayText(task.task.text, "Untitled scheduled task");
1955
- addDeletedTaskRun({
1480
+ const instruction = displayText(task.task.text, "Untitled scheduled automation");
1481
+ addDeletedAutomationRun({
1956
1482
  kind: "scheduled",
1957
- taskId: task.id,
1958
- title: taskDisplayTitle(task.title, instruction, "Untitled scheduled task")
1959
- }, taskTitles, tasks);
1483
+ automationId: task.id,
1484
+ title: taskDisplayTitle(task.title, instruction, "Untitled scheduled automation")
1485
+ }, automationTitles, automations);
1960
1486
  }
1961
1487
  for (const task of deletedEvent) {
1962
- const instruction = displayText(task.task.text, "Untitled event task");
1963
- addDeletedTaskRun({
1488
+ const instruction = displayText(task.task.text, "Untitled event automation");
1489
+ addDeletedAutomationRun({
1964
1490
  kind: "event",
1965
- taskId: task.id,
1966
- title: taskDisplayTitle(task.title, instruction, "Untitled event task")
1967
- }, taskTitles, tasks);
1491
+ automationId: task.id,
1492
+ title: taskDisplayTitle(task.title, instruction, "Untitled event automation")
1493
+ }, automationTitles, automations);
1968
1494
  }
1969
- const runs = await readTaskRuns({
1495
+ const runs = await readAutomationRuns({
1970
1496
  limit: 101,
1971
- tasks
1497
+ automations
1972
1498
  });
1973
1499
  return {
1974
1500
  runs: runs.slice(0, TASK_EXECUTION_LIST_LIMIT).map((run) => ({
1975
1501
  ...run,
1976
- taskTitle: taskTitleForRun(run, taskTitles)
1502
+ automationTitle: automationTitleForRun(run, automationTitles)
1977
1503
  })),
1978
1504
  truncated: runs.length > TASK_EXECUTION_LIST_LIMIT
1979
1505
  };
@@ -1985,70 +1511,70 @@ var ViewerTaskNotFoundError = class extends Error {
1985
1511
  }
1986
1512
  };
1987
1513
  /** Read one viewer-visible task and its newest terminal executions. */
1988
- async function readViewerTaskExecutions(user, kind, id) {
1514
+ async function readViewerAutomationExecutions(user, kind, id) {
1989
1515
  const candidate = await resolveViewerTaskCandidate(user, kind, id);
1990
1516
  if (!candidate) throw new ViewerTaskNotFoundError();
1991
- const [task, executions, executionDays, executionHours] = await Promise.all([
1992
- taskSummaryForCandidate(candidate),
1993
- readTaskExecutions({
1517
+ const [automation, executions, executionDays, executionHours] = await Promise.all([
1518
+ automationSummaryForCandidate(candidate),
1519
+ readAutomationExecutions({
1994
1520
  kind,
1995
1521
  limit: 101,
1996
- taskId: id
1522
+ automationId: id
1997
1523
  }),
1998
- readTaskExecutionStatusDays({
1524
+ readAutomationExecutionStatusDays({
1999
1525
  kind,
2000
- taskId: id
1526
+ automationId: id
2001
1527
  }),
2002
- readTaskExecutionStatusHours({
1528
+ readAutomationExecutionStatusHours({
2003
1529
  kind,
2004
- taskId: id
1530
+ automationId: id
2005
1531
  })
2006
1532
  ]);
2007
1533
  return {
2008
1534
  executionDays,
2009
1535
  executionHours,
2010
- executionSixHours: taskExecutionStatusSixHours(executionHours),
1536
+ executionSixHours: automationExecutionStatusSixHours(executionHours),
2011
1537
  executions: executions.slice(0, TASK_EXECUTION_LIST_LIMIT),
2012
- task,
1538
+ automation,
2013
1539
  truncated: executions.length > TASK_EXECUTION_LIST_LIMIT
2014
1540
  };
2015
1541
  }
2016
1542
  /** Resolve the source task for one conversation when a terminal execution links it. */
2017
1543
  async function readConversationSourceTask(args) {
2018
- const execution = await readTaskExecutionByConversationId({ conversationId: args.conversationId });
1544
+ const execution = await readAutomationExecutionByConversationId({ conversationId: args.conversationId });
2019
1545
  if (!execution) return void 0;
2020
1546
  if (!args.viewer) return { kind: execution.kind };
2021
- const candidate = await resolveViewerTaskCandidate(args.viewer, execution.kind, execution.taskId);
1547
+ const candidate = await resolveViewerTaskCandidate(args.viewer, execution.kind, execution.automationId);
2022
1548
  if (!candidate) return { kind: execution.kind };
2023
1549
  if (candidate.kind === "scheduled") {
2024
- const instruction = displayText(candidate.task.task.text, "Untitled scheduled task");
1550
+ const instruction = displayText(candidate.task.task.text, "Untitled scheduled automation");
2025
1551
  return {
2026
1552
  id: candidate.task.id,
2027
1553
  kind: "scheduled",
2028
1554
  label: instruction,
2029
- title: taskDisplayTitle(candidate.task.title, instruction, "Untitled scheduled task")
1555
+ title: taskDisplayTitle(candidate.task.title, instruction, "Untitled scheduled automation")
2030
1556
  };
2031
1557
  }
2032
- const instruction = displayText(candidate.task.task.text, "Untitled event task");
1558
+ const instruction = displayText(candidate.task.task.text, "Untitled event automation");
2033
1559
  return {
2034
1560
  id: candidate.task.id,
2035
1561
  kind: "event",
2036
1562
  label: instruction,
2037
- title: taskDisplayTitle(candidate.task.title, instruction, "Untitled event task")
1563
+ title: taskDisplayTitle(candidate.task.title, instruction, "Untitled event automation")
2038
1564
  };
2039
1565
  }
2040
- /** Delete one viewer-owned scheduled or event task. */
1566
+ /** Delete one viewer-owned scheduled or event automation. */
2041
1567
  async function deleteViewerTask(user, kind, id) {
2042
1568
  if (kind === "scheduled") try {
2043
- await deleteViewerScheduledTask(getDb(), user, id);
1569
+ await deleteViewerScheduledAutomation(getDb(), user, id);
2044
1570
  return;
2045
1571
  } catch (error) {
2046
- if (error instanceof PersonalScheduledTaskNotFoundError) throw new ViewerTaskNotFoundError();
1572
+ if (error instanceof PersonalScheduledAutomationNotFoundError) throw new ViewerTaskNotFoundError();
2047
1573
  throw error;
2048
1574
  }
2049
- const task = await getEventTask(getDb(), id);
2050
- if (!task || task.status === "deleted" || !eventTaskBelongsToUser(task, user)) throw new ViewerTaskNotFoundError();
2051
- await deleteEventTask(getDb(), id);
1575
+ const task = await getEventAutomation(getDb(), id);
1576
+ if (!task || task.status === "deleted" || !eventAutomationBelongsToUser(task, user)) throw new ViewerTaskNotFoundError();
1577
+ await deleteEventAutomation(getDb(), id);
2052
1578
  }
2053
1579
  //#endregion
2054
1580
  //#region src/api/conversations/detail.ts
@@ -2072,6 +1598,7 @@ function projectConversationDetail(args) {
2072
1598
  usage: args.usage
2073
1599
  }),
2074
1600
  annotations: canExposePayload ? args.annotations : [],
1601
+ ...canExposePayload && args.brief ? { brief: args.brief } : void 0,
2075
1602
  events: args.events,
2076
1603
  ...args.previousSeq !== void 0 ? { previousCursor: encodeConversationCursor({
2077
1604
  conversationId,
@@ -2093,10 +1620,11 @@ async function readConversationDetailFromSql(conversationId, options) {
2093
1620
  const archivedAtMs = options.viewer ? await readConversationArchivedAt(options.viewer, conversationId) : void 0;
2094
1621
  const executor = getSqlExecutor();
2095
1622
  const includeDescendantMetrics = record.rootConversationId === conversationId;
2096
- const [accessByConversation, annotations, auxiliaryCostsByConversation, modelUsage, metricsByRoot, sourceTask, teamDomainByTeamId] = await Promise.all([
1623
+ const [accessByConversation, annotations, auxiliaryCostsByConversation, briefVersion, modelUsage, metricsByRoot, sourceTask, teamDomainByTeamId] = await Promise.all([
2097
1624
  readConversationAccessFromSql(getDb(), [conversationId], options.viewer),
2098
1625
  listConversationAnnotations(getDb(), conversationId),
2099
1626
  readConversationAuxiliaryCostsFromSql(getDb(), [conversationId], { includeDescendants: includeDescendantMetrics }),
1627
+ readLatestConversationBrief(getDb(), conversationId),
2100
1628
  record.conversation.transcriptPurgedAtMs === void 0 ? readConversationModelUsageFromSql(executor, {
2101
1629
  conversationId,
2102
1630
  includeDescendants: includeDescendantMetrics
@@ -2121,6 +1649,11 @@ async function readConversationDetailFromSql(conversationId, options) {
2121
1649
  ...archivedAtMs === void 0 ? void 0 : { archivedAtMs },
2122
1650
  annotations,
2123
1651
  auxiliaryCosts: auxiliaryCostsByConversation.get(conversationId),
1652
+ ...briefVersion ? { brief: {
1653
+ content: briefVersion.content,
1654
+ updatedAt: briefVersion.createdAt.toISOString(),
1655
+ version: briefVersion.version
1656
+ } } : void 0,
2124
1657
  durationMs: metrics?.durationMs ?? record.durationMs,
2125
1658
  events: page.events,
2126
1659
  modelUsage,
@@ -3876,7 +3409,7 @@ async function readPeoplePluginReports(args) {
3876
3409
  reports: [],
3877
3410
  source: "plugins"
3878
3411
  });
3879
- const { getPluginProfileReports } = await import("./agent-hooks-DXHpTJ4m.js").then((n) => n.t);
3412
+ const { getPluginProfileReports } = await import("./agent-hooks-BBX9p6aG.js").then((n) => n.t);
3880
3413
  return pluginOperationalReportFeedSchema.parse({
3881
3414
  generatedAt: new Date(nowMs).toISOString(),
3882
3415
  reports: await getPluginProfileReports({
@@ -4324,30 +3857,30 @@ function createUserPageRoutes() {
4324
3857
  return app;
4325
3858
  }
4326
3859
  //#endregion
4327
- //#region src/api/tasks/routes.ts
3860
+ //#region src/api/automations/routes.ts
4328
3861
  /** Create authenticated native task list and action routes. */
4329
- function createTaskRoutes() {
3862
+ function createAutomationRoutes() {
4330
3863
  const app = new Hono();
4331
- app.get("/", requireViewer, validateRequest("query", taskListQuerySchema, "Invalid task list query."), async (context) => {
3864
+ app.get("/", requireViewer, validateRequest("query", automationListQuerySchema, "Invalid task list query."), async (context) => {
4332
3865
  const user = context.get("viewer");
4333
3866
  const query = context.req.valid("query");
4334
- return jsonResponse(taskListSchema, await readViewerTasks(user, query));
3867
+ return jsonResponse(automationListSchema, await readViewerAutomations(user, query));
4335
3868
  });
4336
3869
  app.get("/runs", requireViewer, async (context) => {
4337
3870
  const user = context.get("viewer");
4338
- return jsonResponse(taskRunListSchema, await readViewerTaskRuns(user));
3871
+ return jsonResponse(automationRunListSchema, await readViewerAutomationRuns(user));
4339
3872
  });
4340
- app.get("/:kind/:id/executions", requireViewer, validateRequest("param", taskParamsSchema, "Invalid task."), async (context) => {
3873
+ app.get("/:kind/:id/executions", requireViewer, validateRequest("param", automationParamsSchema, "Invalid task."), async (context) => {
4341
3874
  const user = context.get("viewer");
4342
3875
  const params = context.req.valid("param");
4343
3876
  try {
4344
- return jsonResponse(taskExecutionListSchema, await readViewerTaskExecutions(user, params.kind, params.id));
3877
+ return jsonResponse(automationExecutionListSchema, await readViewerAutomationExecutions(user, params.kind, params.id));
4345
3878
  } catch (error) {
4346
3879
  if (error instanceof ViewerTaskNotFoundError) return jsonResponse(apiErrorSchema, { error: error.message }, { status: 404 });
4347
3880
  throw error;
4348
3881
  }
4349
3882
  });
4350
- app.delete("/:kind/:id", requireViewer, validateRequest("param", taskParamsSchema, "Invalid task."), async (context) => {
3883
+ app.delete("/:kind/:id", requireViewer, validateRequest("param", automationParamsSchema, "Invalid task."), async (context) => {
4351
3884
  const user = context.get("viewer");
4352
3885
  const params = context.req.valid("param");
4353
3886
  try {
@@ -4485,7 +4018,7 @@ function readDescriptionText(home) {
4485
4018
  }
4486
4019
  /** Read discovered skill names for authenticated runtime diagnostics. */
4487
4020
  async function readSkillReports() {
4488
- const { discoverSkills } = await import("./skills-DJOlYdBs.js").then((n) => n.o);
4021
+ const { discoverSkills } = await import("./skills-D9WesdJJ.js").then((n) => n.o);
4489
4022
  const skills = await discoverSkills();
4490
4023
  return skillReportsSchema.parse(skills.map((skill) => ({
4491
4024
  name: skill.name,
@@ -4494,7 +4027,7 @@ async function readSkillReports() {
4494
4027
  }
4495
4028
  /** Read safe configured plugin metadata for authenticated runtime diagnostics. */
4496
4029
  async function readPlugins() {
4497
- const { pluginCatalogRuntime } = await import("./catalog-runtime-CXw3asJD.js").then((n) => n.t);
4030
+ const { pluginCatalogRuntime } = await import("./catalog-runtime-1BZEOR8J.js").then((n) => n.t);
4498
4031
  return pluginsSchema.parse(pluginCatalogRuntime.getProviders().map((plugin) => ({
4499
4032
  configKeys: plugin.manifest.configKeys ?? [],
4500
4033
  description: plugin.manifest.description,
@@ -4506,7 +4039,7 @@ async function readPlugins() {
4506
4039
  async function readRuntimeInfoReport() {
4507
4040
  const [{ homeDir }, { pluginCatalogRuntime }, plugins, skills] = await Promise.all([
4508
4041
  import("./package-discovery-7a9YqLhE.js").then((n) => n.r),
4509
- import("./catalog-runtime-CXw3asJD.js").then((n) => n.t),
4042
+ import("./catalog-runtime-1BZEOR8J.js").then((n) => n.t),
4510
4043
  readPlugins(),
4511
4044
  readSkillReports()
4512
4045
  ]);
@@ -4523,7 +4056,7 @@ async function readRuntimeInfoReport() {
4523
4056
  /** Read sanitized operational summaries contributed by plugins. */
4524
4057
  async function readPluginOperationalReportFeed() {
4525
4058
  const nowMs = Date.now();
4526
- const { getPluginOperationalReports } = await import("./agent-hooks-DXHpTJ4m.js").then((n) => n.t);
4059
+ const { getPluginOperationalReports } = await import("./agent-hooks-BBX9p6aG.js").then((n) => n.t);
4527
4060
  return pluginOperationalReportFeedSchema.parse({
4528
4061
  source: "plugins",
4529
4062
  generatedAt: new Date(nowMs).toISOString(),
@@ -4547,7 +4080,7 @@ function createJuniorApi() {
4547
4080
  app.route("/api/people", createPeopleRoutes());
4548
4081
  app.route("/api/locations", createLocationRoutes());
4549
4082
  app.route("/api/user-pages", createUserPageRoutes());
4550
- app.route("/api/tasks", createTaskRoutes());
4083
+ app.route("/api/automations", createAutomationRoutes());
4551
4084
  app.route("/api/workspaces", createWorkspaceRoutes());
4552
4085
  app.notFound(() => jsonResponse(apiErrorSchema, { error: "Resource not found." }, { status: 404 }));
4553
4086
  app.onError((error, _context) => {