@sentry/junior 0.251.0 → 0.252.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.
- package/dist/{admin-Dth5-1lw.js → admin-C_-XEdym.js} +1 -1
- package/dist/{agent-hooks-Ctw_jKaS.js → agent-hooks-DcoKnnxn.js} +8 -8
- package/dist/{agent-runner-dgQdPoGH.js → agent-runner-B-7S_DCS.js} +19 -19
- package/dist/api/schema.d.ts +32 -32
- package/dist/api.js +22 -22
- package/dist/app.js +38 -29
- package/dist/{assistant-reply-DBFRnZRx.js → assistant-reply-DbPLvsnL.js} +1 -1
- package/dist/{briefs-SDwPKduW.js → briefs-D4SMqc-r.js} +2 -2
- package/dist/{catalog-runtime-ulFceOA-.js → catalog-runtime-BQQiwwA7.js} +1 -1
- package/dist/cli/chat.js +15 -15
- package/dist/cli/check.js +3 -3
- package/dist/cli/main.js +2 -2
- package/dist/cli/plugins.js +4 -4
- package/dist/cli/snapshot-create.js +3 -3
- package/dist/cli/upgrade.js +3 -3
- package/dist/{client-DMt9kArs.js → client-ROZeVjq0.js} +2 -2
- package/dist/{config-iEOq080E.js → config-DNNkxfGS.js} +2 -2
- package/dist/{connections-BFU6GarA.js → connections-DJV6mLrH.js} +9 -9
- package/dist/{conversation-privacy-yZhQHnBe.js → conversation-privacy-B19umzIL.js} +1 -1
- package/dist/{credential-sync-GW0Rj57H.js → credential-sync-CEd2F5PS.js} +14 -14
- package/dist/{executor-BeH9LDKI.js → executor-_4bdoCxe.js} +59 -19
- package/dist/{images-hIXWwpRg.js → images-BAN7DHuO.js} +2 -2
- package/dist/instrumentation.js +2 -2
- package/dist/{job-queue-Bxlao6zL.js → job-queue-DSQx1qFY.js} +1 -1
- package/dist/{logging-BkI10z0D.js → logging-COUsTFIL.js} +1 -1
- package/dist/{message-BUcVfXmK.js → message-CtDDEwwV.js} +3 -3
- package/dist/nitro.js +3 -3
- package/dist/{oauth-callback-server-CYSEV35l.js → oauth-callback-server-CCiKrS0s.js} +2 -2
- package/dist/{pending-auth-h0B3FQEo.js → pending-auth-DDx3EU4M.js} +2 -2
- package/dist/{profile-AsD2uz0m.js → profile-DP4LKL6V.js} +4 -4
- package/dist/{registry-CN2Nie72.js → registry-CeEpPna6.js} +1 -1
- package/dist/{resolve-CrgwPWTS.js → resolve-B5ma3igH.js} +2 -2
- package/dist/{result-Cokw_MYC.js → result-Da0RVuWG.js} +6 -6
- package/dist/{runner-D-VZlBb_.js → runner-se1W_jGZ.js} +9 -9
- package/dist/{sandbox-egress-signals-Sie51RW0.js → sandbox-egress-signals-CS959-wm.js} +1 -1
- package/dist/{session-stop-DD0k0BXI.js → session-stop-DlRDisF5.js} +10 -10
- package/dist/{skills-CpyJJyqH.js → skills-CSzgs0EC.js} +2 -2
- package/dist/{spawn-DX3YjDtm.js → spawn-DT9fMjtd.js} +2 -2
- package/dist/{store-D-n2b2cI.js → store-Dx1U69mm.js} +6 -6
- package/dist/{task-queue-Bj2hFpjr.js → task-queue-BX9YrIsw.js} +3 -3
- package/dist/{task-runner-B3g16wjr.js → task-runner-CO55Olal.js} +14 -16
- package/dist/{tasks-DDzBxMio.js → tasks-DwGlFX9i.js} +129 -200
- package/dist/{thread-state-BlD6loX7.js → thread-state-Ces6tXmB.js} +6 -6
- package/dist/{turn-failure-response-BRlfATgu.js → turn-failure-response-B4VCvEQf.js} +7 -7
- package/dist/{turn-lifecycle-hMCbr_Ah.js → turn-lifecycle-B1VV58Yo.js} +1 -1
- package/dist/{turn-session-routing-DLb6eQMT.js → turn-session-routing-Dw2Kamg9.js} +1 -1
- package/dist/{validation-C2lG6yVH.js → validation-yJF9LKOv.js} +1 -1
- package/dist/{version-CyJ_kMe8.js → version-CZYqvIFh.js} +1 -1
- package/dist/version.js +1 -1
- package/dist/{viewer-C8u1HAdN.js → viewer-D96vo_42.js} +3 -3
- package/dist/{web-input-DHgIfSwj.js → web-input-5mls-41-.js} +65 -98
- package/dist/{work-hoPN8qjl.js → work-D2M2-zCO.js} +9 -9
- package/dist/{worker-CavJZxi8.js → worker-BwCpf8tB.js} +5 -5
- package/migrations/0055_automations.sql +125 -0
- package/migrations/meta/0055_snapshot.json +3948 -0
- package/migrations/meta/_journal.json +8 -1
- package/package.json +4 -4
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
import { d as unwrapCurrentInstruction, f as escapeXml, i as completeText, o as resolveGatewayModel } from "./client-
|
|
2
|
-
import { d as logException, o as getActiveTraceId, p as logWarn, s as getLogContextAttributes, t as buildTurnFailureResponse, v as setSpanAttributes } from "./logging-
|
|
1
|
+
import { d as unwrapCurrentInstruction, f as escapeXml, i as completeText, o as resolveGatewayModel } from "./client-ROZeVjq0.js";
|
|
2
|
+
import { d as logException, o as getActiveTraceId, p as logWarn, s as getLogContextAttributes, t as buildTurnFailureResponse, v as setSpanAttributes } from "./logging-COUsTFIL.js";
|
|
3
3
|
import { n as captureMessage } from "./sentry-CgWZM_kV.js";
|
|
4
|
-
import { n as botConfig, v as normalizeSlackEmojiName } from "./config-
|
|
4
|
+
import { n as botConfig, v as normalizeSlackEmojiName } from "./config-DNNkxfGS.js";
|
|
5
5
|
import { c as toStoredSlackActor, f as parseSlackUserId, g as parseSlackMessageTs } from "./actor-BTtLaeWy.js";
|
|
6
|
-
import { c as getConversationEventStore, f as getSqlExecutor, m as withConversationEventLock, p as createSqlConversationEventStore, u as getConversationStore, v as startLocationThread, x as addAgentTurnUsage, y as bindProviderConversation } from "./viewer-
|
|
7
|
-
import { a as juniorSchedulerRuns, o as
|
|
6
|
+
import { c as getConversationEventStore, f as getSqlExecutor, m as withConversationEventLock, p as createSqlConversationEventStore, u as getConversationStore, v as startLocationThread, x as addAgentTurnUsage, y as bindProviderConversation } from "./viewer-D96vo_42.js";
|
|
7
|
+
import { a as juniorSchedulerRuns, o as juniorAutomationVersions, s as juniorAutomations } from "./executor-_4bdoCxe.js";
|
|
8
8
|
import { d as contextProvenance, f as instructionActors, n as agentHistoryItemSchema, p as instructionProvenanceFor } from "./history-9pO1Zd4Y.js";
|
|
9
|
-
import { p as credentialSubjectSchema } from "./registry-
|
|
10
|
-
import { $t as authenticationUnlinkedEvent, Gt as normalizeSlackConversationId, Ht as getSlackClient, Qt as authenticationLinkedEvent, Rt as SlackActionError, Xt as JUNIOR_NATIVE_EVENT_NAMESPACE, Zt as agentsInstructionsUpdatedEvent, n as applyPluginFormatMarkdown, qt as withSlackRetries } from "./agent-hooks-
|
|
9
|
+
import { p as credentialSubjectSchema } from "./registry-CeEpPna6.js";
|
|
10
|
+
import { $t as authenticationUnlinkedEvent, Gt as normalizeSlackConversationId, Ht as getSlackClient, Qt as authenticationLinkedEvent, Rt as SlackActionError, Xt as JUNIOR_NATIVE_EVENT_NAMESPACE, Zt as agentsInstructionsUpdatedEvent, n as applyPluginFormatMarkdown, qt as withSlackRetries } from "./agent-hooks-DcoKnnxn.js";
|
|
11
11
|
import { G as messageCardRef } from "./conversation-T18Xlkx9.js";
|
|
12
|
-
import { D as fenceLock, O as withLock, T as MUTATION_LOCK_TTL_MS, k as sleep, w as getStateAdapter } from "./profile-
|
|
12
|
+
import { D as fenceLock, O as withLock, T as MUTATION_LOCK_TTL_MS, k as sleep, w as getStateAdapter } from "./profile-DP4LKL6V.js";
|
|
13
13
|
import { A as eventAutomationSchema, D as scheduledRunSchema, E as scheduledAutomationSchema, S as automationVersionSchema } from "./automation-gznOMaQ2.js";
|
|
14
14
|
import { isDeepStrictEqual } from "node:util";
|
|
15
15
|
import { z } from "zod";
|
|
16
16
|
import { createHash } from "node:crypto";
|
|
17
|
-
import { and, asc, desc, eq, inArray, ne,
|
|
18
|
-
import { actorSchema, eventMatches,
|
|
17
|
+
import { and, asc, desc, eq, inArray, ne, or, sql } from "drizzle-orm";
|
|
18
|
+
import { actorSchema, eventMatches, sourceSchema } from "@sentry/junior-plugin-api";
|
|
19
19
|
//#region src/chat/pi/messages.ts
|
|
20
20
|
/** Permissive schema for durable Pi SDK messages whose content shape may evolve. */
|
|
21
21
|
const piMessageSchema = z.object({ role: z.string() }).passthrough().transform((value) => value);
|
|
@@ -2854,26 +2854,31 @@ function sameDefinitionValue(left, right) {
|
|
|
2854
2854
|
* transaction and lock as the Automation write. Without `current`, the
|
|
2855
2855
|
* Automation is new, so the creator saves version 1.
|
|
2856
2856
|
*/
|
|
2857
|
-
async function recordAutomationVersion(db,
|
|
2857
|
+
async function recordAutomationVersion(db, task, current, editedBy) {
|
|
2858
2858
|
const definition = automationDefinition(task);
|
|
2859
2859
|
if (current && sameDefinitionValue(automationDefinition(current), definition)) return;
|
|
2860
2860
|
await db.insert(juniorAutomationVersions).values({
|
|
2861
|
-
kind,
|
|
2862
2861
|
automationId: task.id,
|
|
2863
2862
|
version: sql`(
|
|
2864
2863
|
SELECT coalesce(max(${juniorAutomationVersions.version}), 0) + 1
|
|
2865
2864
|
FROM ${juniorAutomationVersions}
|
|
2866
|
-
WHERE ${juniorAutomationVersions.
|
|
2867
|
-
AND ${juniorAutomationVersions.automationId} = ${task.id}
|
|
2865
|
+
WHERE ${juniorAutomationVersions.automationId} = ${task.id}
|
|
2868
2866
|
)`,
|
|
2869
2867
|
createdAtMs: Date.now(),
|
|
2870
2868
|
editedBy: editedBy ?? (current ? null : task.createdBy),
|
|
2871
2869
|
definition
|
|
2872
2870
|
});
|
|
2873
2871
|
}
|
|
2874
|
-
|
|
2872
|
+
const versionColumns = {
|
|
2873
|
+
createdAtMs: juniorAutomationVersions.createdAtMs,
|
|
2874
|
+
definition: juniorAutomationVersions.definition,
|
|
2875
|
+
editedBy: juniorAutomationVersions.editedBy,
|
|
2876
|
+
kind: juniorAutomations.kind,
|
|
2877
|
+
version: juniorAutomationVersions.version
|
|
2878
|
+
};
|
|
2879
|
+
function parseVersionRow(row) {
|
|
2875
2880
|
return automationVersionSchema.parse({
|
|
2876
|
-
kind,
|
|
2881
|
+
kind: row.kind,
|
|
2877
2882
|
version: row.version,
|
|
2878
2883
|
createdAt: new Date(row.createdAtMs).toISOString(),
|
|
2879
2884
|
editedBy: row.editedBy,
|
|
@@ -2881,13 +2886,13 @@ function parseVersionRow(kind, row) {
|
|
|
2881
2886
|
});
|
|
2882
2887
|
}
|
|
2883
2888
|
/** Read one saved definition. */
|
|
2884
|
-
async function readAutomationVersion(db,
|
|
2885
|
-
const [row] = await db.select().from(juniorAutomationVersions).
|
|
2886
|
-
return row ? parseVersionRow(
|
|
2889
|
+
async function readAutomationVersion(db, automationId, version) {
|
|
2890
|
+
const [row] = await db.select(versionColumns).from(juniorAutomationVersions).innerJoin(juniorAutomations, eq(juniorAutomations.id, juniorAutomationVersions.automationId)).where(and(eq(juniorAutomationVersions.automationId, automationId), eq(juniorAutomationVersions.version, version))).limit(1);
|
|
2891
|
+
return row ? parseVersionRow(row) : void 0;
|
|
2887
2892
|
}
|
|
2888
2893
|
/** Read saved definitions, newest first. */
|
|
2889
|
-
async function listAutomationVersions(db,
|
|
2890
|
-
return (await db.select().from(juniorAutomationVersions).
|
|
2894
|
+
async function listAutomationVersions(db, automationId, limit) {
|
|
2895
|
+
return (await db.select(versionColumns).from(juniorAutomationVersions).innerJoin(juniorAutomations, eq(juniorAutomations.id, juniorAutomationVersions.automationId)).where(eq(juniorAutomationVersions.automationId, automationId)).orderBy(desc(juniorAutomationVersions.version)).limit(limit)).map(parseVersionRow);
|
|
2891
2896
|
}
|
|
2892
2897
|
//#endregion
|
|
2893
2898
|
//#region src/chat/event-automations/run-limit.ts
|
|
@@ -2960,99 +2965,78 @@ async function clearEventAutomationRuns(automationId, state = getStateAdapter())
|
|
|
2960
2965
|
}
|
|
2961
2966
|
//#endregion
|
|
2962
2967
|
//#region src/chat/event-automations/store.ts
|
|
2963
|
-
|
|
2964
|
-
|
|
2965
|
-
|
|
2966
|
-
|
|
2967
|
-
|
|
2968
|
-
status:
|
|
2969
|
-
|
|
2970
|
-
|
|
2971
|
-
|
|
2972
|
-
|
|
2973
|
-
|
|
2974
|
-
|
|
2975
|
-
|
|
2976
|
-
|
|
2968
|
+
/**
|
|
2969
|
+
* Validate an event automation and split it into its SQL columns. Lifecycle
|
|
2970
|
+
* columns are written separately.
|
|
2971
|
+
*/
|
|
2972
|
+
function eventAutomationColumns(task) {
|
|
2973
|
+
const { status: _status, statusReason: _statusReason, title, ...definition } = task;
|
|
2974
|
+
const { createdAtMs: _createdAtMs, id: _id, ...record } = eventAutomationSchema.parse(definition);
|
|
2975
|
+
return {
|
|
2976
|
+
channelId: record.destination.channelId,
|
|
2977
|
+
creatorSlackUserId: record.createdBy.slackUserId,
|
|
2978
|
+
identifier: record.trigger.identifier,
|
|
2979
|
+
instruction: record.task.text,
|
|
2980
|
+
namespace: record.trigger.namespace,
|
|
2981
|
+
record,
|
|
2982
|
+
teamId: record.destination.teamId,
|
|
2983
|
+
title: title?.trim() || null
|
|
2984
|
+
};
|
|
2977
2985
|
}
|
|
2978
|
-
/** Decode
|
|
2986
|
+
/** Decode an event Automation row with its SQL-backed fields. */
|
|
2979
2987
|
function parseEventAutomationRow(row) {
|
|
2980
|
-
const
|
|
2981
|
-
|
|
2982
|
-
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
}];
|
|
2986
|
-
const retained = retainedEventAutomationSchema.parse(raw);
|
|
2987
|
-
const { threadTs: _threadTs, ...destination } = retained.destination;
|
|
2988
|
+
const task = eventAutomationSchema.parse({
|
|
2989
|
+
...row.record,
|
|
2990
|
+
createdAtMs: row.createdAtMs,
|
|
2991
|
+
id: row.id
|
|
2992
|
+
});
|
|
2988
2993
|
const title = row.title?.trim();
|
|
2989
2994
|
return {
|
|
2990
|
-
...
|
|
2991
|
-
|
|
2992
|
-
outcomes: retained.outcomes.map((outcome) => {
|
|
2993
|
-
const { threadTs: _threadTs, ...destination } = outcome.destination;
|
|
2994
|
-
return {
|
|
2995
|
-
...outcome,
|
|
2996
|
-
destination
|
|
2997
|
-
};
|
|
2998
|
-
}),
|
|
2999
|
-
status: row.status ?? "active",
|
|
2995
|
+
...task,
|
|
2996
|
+
status: row.status,
|
|
3000
2997
|
...row.statusReason ? { statusReason: row.statusReason } : void 0,
|
|
3001
2998
|
...title ? { title } : void 0
|
|
3002
2999
|
};
|
|
3003
3000
|
}
|
|
3001
|
+
function eventAutomationWhere(id) {
|
|
3002
|
+
return and(eq(juniorAutomations.id, id), eq(juniorAutomations.kind, "event"));
|
|
3003
|
+
}
|
|
3004
3004
|
function activeEventAutomationWhere() {
|
|
3005
|
-
return ne(
|
|
3005
|
+
return and(eq(juniorAutomations.kind, "event"), ne(juniorAutomations.status, "deleted"));
|
|
3006
3006
|
}
|
|
3007
3007
|
/** Read one event automation by id, including deleted rows when present. */
|
|
3008
3008
|
async function getEventAutomation(db, id) {
|
|
3009
|
-
const rows = await db.select(
|
|
3009
|
+
const rows = await db.select().from(juniorAutomations).where(eventAutomationWhere(id)).limit(1);
|
|
3010
3010
|
return rows[0] ? parseEventAutomationRow(rows[0]) : void 0;
|
|
3011
3011
|
}
|
|
3012
3012
|
/** Create one retry-stable event automation, or revive a deleted row with the new payload. */
|
|
3013
3013
|
async function createEventAutomation(db, task) {
|
|
3014
|
-
const
|
|
3015
|
-
|
|
3016
|
-
if ((await getEventAutomation(db, parsed.id))?.status === "deleted") await clearEventAutomationRuns(parsed.id);
|
|
3014
|
+
const columns = eventAutomationColumns(task);
|
|
3015
|
+
if ((await getEventAutomation(db, task.id))?.status === "deleted") await clearEventAutomationRuns(task.id);
|
|
3017
3016
|
return db.transaction(async (tx) => {
|
|
3018
|
-
const inserted = await tx.insert(
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
|
|
3023
|
-
|
|
3024
|
-
|
|
3025
|
-
title,
|
|
3026
|
-
task: parsed
|
|
3027
|
-
}).onConflictDoNothing().returning({ ...eventAutomationRowColumns });
|
|
3017
|
+
const inserted = await tx.insert(juniorAutomations).values({
|
|
3018
|
+
...columns,
|
|
3019
|
+
createdAtMs: task.createdAtMs,
|
|
3020
|
+
id: task.id,
|
|
3021
|
+
kind: "event",
|
|
3022
|
+
status: "active"
|
|
3023
|
+
}).onConflictDoNothing().returning();
|
|
3028
3024
|
if (inserted[0]) {
|
|
3029
3025
|
const created = parseEventAutomationRow(inserted[0]);
|
|
3030
|
-
await recordAutomationVersion(tx,
|
|
3026
|
+
await recordAutomationVersion(tx, created, void 0);
|
|
3031
3027
|
return created;
|
|
3032
3028
|
}
|
|
3033
|
-
const existing = await getEventAutomation(tx,
|
|
3034
|
-
if (!existing)
|
|
3035
|
-
...parsed,
|
|
3036
|
-
status: "active",
|
|
3037
|
-
...title ? { title } : void 0
|
|
3038
|
-
};
|
|
3029
|
+
const existing = await getEventAutomation(tx, task.id);
|
|
3030
|
+
if (!existing) throw new Error(`Automation ${task.id} already exists with another kind.`);
|
|
3039
3031
|
if (existing.status !== "deleted") return existing;
|
|
3040
|
-
const rows = await tx.update(
|
|
3041
|
-
|
|
3042
|
-
namespace: parsed.trigger.namespace,
|
|
3043
|
-
identifier: parsed.trigger.identifier,
|
|
3044
|
-
status: "active",
|
|
3045
|
-
statusReason: null,
|
|
3046
|
-
title,
|
|
3047
|
-
task: parsed
|
|
3048
|
-
}).where(and(eq(juniorEventAutomations.id, parsed.id), eq(juniorEventAutomations.status, "deleted"))).returning({ ...eventAutomationRowColumns });
|
|
3049
|
-
if (!rows[0]) return await getEventAutomation(tx, parsed.id) ?? {
|
|
3050
|
-
...parsed,
|
|
3032
|
+
const rows = await tx.update(juniorAutomations).set({
|
|
3033
|
+
...columns,
|
|
3051
3034
|
status: "active",
|
|
3052
|
-
|
|
3053
|
-
};
|
|
3035
|
+
statusReason: null
|
|
3036
|
+
}).where(and(eventAutomationWhere(task.id), eq(juniorAutomations.status, "deleted"))).returning();
|
|
3037
|
+
if (!rows[0]) return await getEventAutomation(tx, task.id);
|
|
3054
3038
|
const revived = parseEventAutomationRow(rows[0]);
|
|
3055
|
-
await recordAutomationVersion(tx,
|
|
3039
|
+
await recordAutomationVersion(tx, revived, void 0);
|
|
3056
3040
|
return revived;
|
|
3057
3041
|
});
|
|
3058
3042
|
}
|
|
@@ -3061,31 +3045,25 @@ async function createEventAutomation(db, task) {
|
|
|
3061
3045
|
* Pass `editedBy` when a person changes the definition so its version names them.
|
|
3062
3046
|
*/
|
|
3063
3047
|
async function saveEventAutomation(db, task, expectedRevision, editedBy) {
|
|
3064
|
-
const
|
|
3065
|
-
const title = task.title?.trim() || null;
|
|
3048
|
+
const columns = eventAutomationColumns(task);
|
|
3066
3049
|
return db.transaction(async (tx) => {
|
|
3067
|
-
const rows = await tx.select(
|
|
3050
|
+
const rows = await tx.select().from(juniorAutomations).where(eventAutomationWhere(task.id)).for("update");
|
|
3068
3051
|
const current = rows[0] ? parseEventAutomationRow(rows[0]) : void 0;
|
|
3069
3052
|
if (expectedRevision !== void 0) requireAutomationRevision(current, expectedRevision);
|
|
3070
3053
|
if (!current || current.status === "deleted") return void 0;
|
|
3071
|
-
const saved = parseEventAutomationRow((await tx.update(
|
|
3072
|
-
|
|
3073
|
-
identifier: parsed.trigger.identifier,
|
|
3074
|
-
title,
|
|
3075
|
-
task: parsed
|
|
3076
|
-
}).where(eq(juniorEventAutomations.id, parsed.id)).returning({ ...eventAutomationRowColumns }))[0]);
|
|
3077
|
-
await recordAutomationVersion(tx, "event", saved, current, editedBy);
|
|
3054
|
+
const saved = parseEventAutomationRow((await tx.update(juniorAutomations).set(columns).where(eventAutomationWhere(task.id)).returning())[0]);
|
|
3055
|
+
await recordAutomationVersion(tx, saved, current, editedBy);
|
|
3078
3056
|
return saved;
|
|
3079
3057
|
});
|
|
3080
3058
|
}
|
|
3081
3059
|
/** Mark one existing event automation deleted while retaining the row for history. */
|
|
3082
3060
|
async function deleteEventAutomation(db, id) {
|
|
3083
|
-
const rows = await db.update(
|
|
3061
|
+
const rows = await db.update(juniorAutomations).set({ status: "deleted" }).where(and(eq(juniorAutomations.id, id), activeEventAutomationWhere())).returning();
|
|
3084
3062
|
return rows[0] ? parseEventAutomationRow(rows[0]) : void 0;
|
|
3085
3063
|
}
|
|
3086
3064
|
/** List live event automations in one Slack workspace. */
|
|
3087
3065
|
async function listEventAutomationsForTeam(db, teamId) {
|
|
3088
|
-
return (await db.select(
|
|
3066
|
+
return (await db.select().from(juniorAutomations).where(and(eq(juniorAutomations.teamId, teamId), activeEventAutomationWhere())).orderBy(asc(juniorAutomations.createdAtMs), asc(juniorAutomations.id))).map(parseEventAutomationRow);
|
|
3089
3067
|
}
|
|
3090
3068
|
function viewerSlackIdentities(user) {
|
|
3091
3069
|
return user.identities.filter((identity) => identity.provider === "slack" && Boolean(identity.providerTenantId) && Boolean(identity.providerSubjectId));
|
|
@@ -3100,9 +3078,9 @@ function eventAutomationBelongsToUser(task, user) {
|
|
|
3100
3078
|
*/
|
|
3101
3079
|
async function listDeletedEventAutomationsCreatedBy(db, user, limit) {
|
|
3102
3080
|
const identities = viewerSlackIdentities(user);
|
|
3103
|
-
const ownership = or(...identities.map((identity) => and(eq(
|
|
3081
|
+
const ownership = or(...identities.map((identity) => and(eq(juniorAutomations.teamId, identity.providerTenantId), eq(juniorAutomations.creatorSlackUserId, identity.providerSubjectId))));
|
|
3104
3082
|
if (!ownership) return [];
|
|
3105
|
-
return (await db.select(
|
|
3083
|
+
return (await db.select().from(juniorAutomations).where(and(ownership, eq(juniorAutomations.kind, "event"), eq(juniorAutomations.status, "deleted"))).orderBy(desc(juniorAutomations.createdAtMs), desc(juniorAutomations.id)).limit(limit)).map(parseEventAutomationRow);
|
|
3106
3084
|
}
|
|
3107
3085
|
/**
|
|
3108
3086
|
* Collect match keys from live event automations for these identifiers and event types.
|
|
@@ -3112,7 +3090,7 @@ async function collectEventAutomationMatchKeys(db, input) {
|
|
|
3112
3090
|
const eventTypes = new Set(input.eventTypes.map((eventType) => eventType.trim()).filter(Boolean));
|
|
3113
3091
|
const identifiers = [...new Set(input.identifiers.map((value) => value.trim()).filter(Boolean))];
|
|
3114
3092
|
if (eventTypes.size === 0 || identifiers.length === 0) return [];
|
|
3115
|
-
const rows = await db.select(
|
|
3093
|
+
const rows = await db.select().from(juniorAutomations).where(and(eq(juniorAutomations.kind, "event"), eq(juniorAutomations.teamId, input.teamId), eq(juniorAutomations.namespace, input.namespace), inArray(juniorAutomations.identifier, identifiers), eq(juniorAutomations.status, "active"))).orderBy(asc(juniorAutomations.createdAtMs), asc(juniorAutomations.id));
|
|
3116
3094
|
const keys = /* @__PURE__ */ new Set();
|
|
3117
3095
|
for (const row of rows) {
|
|
3118
3096
|
const task = parseEventAutomationRow(row);
|
|
@@ -3123,7 +3101,7 @@ async function collectEventAutomationMatchKeys(db, input) {
|
|
|
3123
3101
|
}
|
|
3124
3102
|
/** Find every live task matching one normalized event. */
|
|
3125
3103
|
async function findMatchingEventAutomations(db, event, teamId) {
|
|
3126
|
-
return (await db.select(
|
|
3104
|
+
return (await db.select().from(juniorAutomations).where(and(eq(juniorAutomations.kind, "event"), eq(juniorAutomations.teamId, teamId), eq(juniorAutomations.namespace, event.namespace), eq(juniorAutomations.identifier, event.identifier), eq(juniorAutomations.status, "active"))).orderBy(asc(juniorAutomations.createdAtMs), asc(juniorAutomations.id))).map(parseEventAutomationRow).filter((task) => task.trigger.events.includes(event.eventType) && eventMatches(task.trigger.match, event.data));
|
|
3127
3105
|
}
|
|
3128
3106
|
/**
|
|
3129
3107
|
* Change lifecycle under the same row lock as edits, without changing
|
|
@@ -3134,7 +3112,7 @@ async function findMatchingEventAutomations(db, event, teamId) {
|
|
|
3134
3112
|
async function setEventAutomationStatus(db, id, status, revision) {
|
|
3135
3113
|
if (status === "active" && (await getEventAutomation(db, id))?.status !== "active") await clearEventAutomationRuns(id);
|
|
3136
3114
|
return db.transaction(async (tx) => {
|
|
3137
|
-
const rows = await tx.select().from(
|
|
3115
|
+
const rows = await tx.select().from(juniorAutomations).where(eventAutomationWhere(id)).for("update");
|
|
3138
3116
|
const current = rows[0] ? parseEventAutomationRow(rows[0]) : void 0;
|
|
3139
3117
|
requireAutomationRevision(current, revision);
|
|
3140
3118
|
if (!current || current.status === "deleted") throw new Error("Automation no longer exists.");
|
|
@@ -3148,10 +3126,10 @@ async function setEventAutomationStatus(db, id, status, revision) {
|
|
|
3148
3126
|
status,
|
|
3149
3127
|
statusReason: void 0
|
|
3150
3128
|
};
|
|
3151
|
-
await tx.update(
|
|
3129
|
+
await tx.update(juniorAutomations).set({
|
|
3152
3130
|
status: next.status,
|
|
3153
3131
|
statusReason: next.statusReason ?? null
|
|
3154
|
-
}).where(
|
|
3132
|
+
}).where(eventAutomationWhere(id));
|
|
3155
3133
|
const { statusReason: _statusReason, ...rest } = current;
|
|
3156
3134
|
return {
|
|
3157
3135
|
...rest,
|
|
@@ -3169,65 +3147,31 @@ async function setEventAutomationStatus(db, id, status, revision) {
|
|
|
3169
3147
|
* an automation that the dashboard shows as paused.
|
|
3170
3148
|
*/
|
|
3171
3149
|
async function blockEventAutomation(db, id, reason) {
|
|
3172
|
-
return (await db.update(
|
|
3173
|
-
status: sql`case when ${
|
|
3150
|
+
return (await db.update(juniorAutomations).set({
|
|
3151
|
+
status: sql`case when ${juniorAutomations.status} = 'active' then 'blocked' else ${juniorAutomations.status} end`,
|
|
3174
3152
|
statusReason: reason
|
|
3175
|
-
}).where(and(
|
|
3153
|
+
}).where(and(eventAutomationWhere(id), or(eq(juniorAutomations.status, "active"), and(eq(juniorAutomations.status, "paused"), sql`${juniorAutomations.statusReason} is distinct from ${reason}`)))).returning({ status: juniorAutomations.status }))[0]?.status === "blocked";
|
|
3176
3154
|
}
|
|
3177
3155
|
//#endregion
|
|
3178
3156
|
//#region src/chat/scheduled-automations/tasks.ts
|
|
3179
3157
|
const SCHEDULER_KEY_PREFIX = "junior:scheduler";
|
|
3180
|
-
|
|
3181
|
-
creatorIdentityId: true,
|
|
3182
|
-
title: true
|
|
3183
|
-
}).extend({
|
|
3184
|
-
destination: slackDestinationSchema,
|
|
3185
|
-
outcomes: z.array(taskOutcomeSchema).max(5),
|
|
3186
|
-
version: z.number().optional()
|
|
3187
|
-
}).strict();
|
|
3188
|
-
/** Decode a retained scheduler task row and reject invalid routing context. */
|
|
3158
|
+
/** Decode a Scheduled automation row. Returns undefined for an invalid row. */
|
|
3189
3159
|
function parseScheduledAutomationRow(row) {
|
|
3190
|
-
const
|
|
3191
|
-
|
|
3192
|
-
|
|
3193
|
-
|
|
3194
|
-
|
|
3195
|
-
|
|
3196
|
-
|
|
3197
|
-
|
|
3198
|
-
|
|
3199
|
-
} : retained;
|
|
3200
|
-
const parsed = retainedScheduledAutomationSchema.safeParse(current);
|
|
3201
|
-
if (!parsed.success) return void 0;
|
|
3202
|
-
const { status, version: _version, ...retainedTask } = parsed.data;
|
|
3203
|
-
const destination = {
|
|
3204
|
-
platform: "slack",
|
|
3205
|
-
teamId: retainedTask.destination.teamId,
|
|
3206
|
-
channelId: retainedTask.destination.channelId
|
|
3207
|
-
};
|
|
3208
|
-
const task = {
|
|
3209
|
-
...retainedTask,
|
|
3210
|
-
destination,
|
|
3211
|
-
outcomes: retainedTask.outcomes.map((outcome) => ({
|
|
3212
|
-
...outcome,
|
|
3213
|
-
destination: {
|
|
3214
|
-
platform: "slack",
|
|
3215
|
-
teamId: outcome.destination.teamId,
|
|
3216
|
-
channelId: outcome.destination.channelId
|
|
3217
|
-
}
|
|
3218
|
-
}))
|
|
3219
|
-
};
|
|
3220
|
-
const fallbackIdentity = row.creatorIdentityId === null ? z.string().safeParse(legacyCreatorIdentityId) : void 0;
|
|
3221
|
-
const creatorIdentityId = row.creatorIdentityId ?? (fallbackIdentity?.success ? fallbackIdentity.data : void 0);
|
|
3222
|
-
if (creatorIdentityId === void 0) return void 0;
|
|
3223
|
-
const fallbackTitle = row.title === null ? z.string().safeParse(legacyTitle) : void 0;
|
|
3224
|
-
const title = (row.title !== null ? row.title : fallbackTitle?.success ? fallbackTitle.data : void 0)?.trim() || void 0;
|
|
3225
|
-
return {
|
|
3226
|
-
...task,
|
|
3227
|
-
creatorIdentityId,
|
|
3228
|
-
status,
|
|
3229
|
-
...title ? { title } : void 0
|
|
3160
|
+
const columns = {
|
|
3161
|
+
createdAtMs: row.createdAtMs,
|
|
3162
|
+
creatorIdentityId: row.creatorIdentityId,
|
|
3163
|
+
id: row.id,
|
|
3164
|
+
nextRunAtMs: row.nextRunAtMs,
|
|
3165
|
+
runNowAtMs: row.runNowAtMs,
|
|
3166
|
+
status: row.status,
|
|
3167
|
+
statusReason: row.statusReason,
|
|
3168
|
+
title: row.title
|
|
3230
3169
|
};
|
|
3170
|
+
const parsed = scheduledAutomationSchema.safeParse({
|
|
3171
|
+
...row.record,
|
|
3172
|
+
...Object.fromEntries(Object.entries(columns).filter(([, value]) => value !== null))
|
|
3173
|
+
});
|
|
3174
|
+
return parsed.success ? parsed.data : void 0;
|
|
3231
3175
|
}
|
|
3232
3176
|
/** Keep scan paths from returning current or legacy tombstones. */
|
|
3233
3177
|
function isListedScheduledAutomation(task) {
|
|
@@ -3254,53 +3198,38 @@ function requireStoredTask(task) {
|
|
|
3254
3198
|
...normalizedTitle ? { title: normalizedTitle } : void 0
|
|
3255
3199
|
};
|
|
3256
3200
|
}
|
|
3257
|
-
function scheduledAutomationJsonRecord(task) {
|
|
3258
|
-
const { title: _title, ...record } = task;
|
|
3259
|
-
return record;
|
|
3260
|
-
}
|
|
3261
3201
|
async function upsertScheduledAutomation(db, task) {
|
|
3262
|
-
const title = task
|
|
3263
|
-
|
|
3264
|
-
|
|
3265
|
-
|
|
3266
|
-
|
|
3267
|
-
|
|
3268
|
-
|
|
3269
|
-
|
|
3270
|
-
|
|
3271
|
-
|
|
3272
|
-
|
|
3273
|
-
|
|
3202
|
+
const { createdAtMs, creatorIdentityId, id, nextRunAtMs, runNowAtMs, status, statusReason, title, ...record } = task;
|
|
3203
|
+
const columns = {
|
|
3204
|
+
channelId: record.destination.channelId,
|
|
3205
|
+
createdAtMs,
|
|
3206
|
+
creatorIdentityId,
|
|
3207
|
+
creatorSlackUserId: record.createdBy.slackUserId,
|
|
3208
|
+
instruction: record.task.text,
|
|
3209
|
+
nextRunAtMs: nextRunAtMs ?? null,
|
|
3210
|
+
record,
|
|
3211
|
+
runNowAtMs: runNowAtMs ?? null,
|
|
3212
|
+
status,
|
|
3213
|
+
statusReason: statusReason ?? null,
|
|
3214
|
+
teamId: record.destination.teamId,
|
|
3215
|
+
title: title?.trim() || null
|
|
3216
|
+
};
|
|
3217
|
+
await db.insert(juniorAutomations).values({
|
|
3218
|
+
...columns,
|
|
3219
|
+
id,
|
|
3220
|
+
kind: "scheduled"
|
|
3274
3221
|
}).onConflictDoUpdate({
|
|
3275
|
-
target:
|
|
3276
|
-
set:
|
|
3277
|
-
createdAtMs: sql`excluded.created_at_ms`,
|
|
3278
|
-
creatorIdentityId: sql`excluded.creator_identity_id`,
|
|
3279
|
-
creatorSlackUserId: sql`excluded.creator_slack_user_id`,
|
|
3280
|
-
nextRunAtMs: sql`excluded.next_run_at_ms`,
|
|
3281
|
-
record: sql`excluded.record`,
|
|
3282
|
-
runNowAtMs: sql`excluded.run_now_at_ms`,
|
|
3283
|
-
status: sql`excluded.status`,
|
|
3284
|
-
teamId: sql`excluded.team_id`,
|
|
3285
|
-
title: sql`excluded.title`
|
|
3286
|
-
}
|
|
3222
|
+
target: juniorAutomations.id,
|
|
3223
|
+
set: columns
|
|
3287
3224
|
});
|
|
3288
3225
|
}
|
|
3289
3226
|
/** Read and decode one scheduled automation. */
|
|
3290
3227
|
async function readScheduledAutomation(db, taskId) {
|
|
3291
|
-
const rows = await db.select(
|
|
3292
|
-
creatorIdentityId: juniorSchedulerTasks.creatorIdentityId,
|
|
3293
|
-
record: juniorSchedulerTasks.record,
|
|
3294
|
-
title: juniorSchedulerTasks.title
|
|
3295
|
-
}).from(juniorSchedulerTasks).where(eq(juniorSchedulerTasks.id, taskId)).limit(1);
|
|
3228
|
+
const rows = await db.select().from(juniorAutomations).where(and(eq(juniorAutomations.id, taskId), eq(juniorAutomations.kind, "scheduled"))).limit(1);
|
|
3296
3229
|
return rows[0] ? parseScheduledAutomationRow(rows[0]) : void 0;
|
|
3297
3230
|
}
|
|
3298
3231
|
async function readListedScheduledAutomations(db, teamId) {
|
|
3299
|
-
return (await db.select(
|
|
3300
|
-
creatorIdentityId: juniorSchedulerTasks.creatorIdentityId,
|
|
3301
|
-
record: juniorSchedulerTasks.record,
|
|
3302
|
-
title: juniorSchedulerTasks.title
|
|
3303
|
-
}).from(juniorSchedulerTasks).where(and(notInArray(juniorSchedulerTasks.status, ["deleted"]), teamId === void 0 ? void 0 : eq(juniorSchedulerTasks.teamId, teamId))).orderBy(asc(juniorSchedulerTasks.createdAtMs), asc(juniorSchedulerTasks.id))).map(parseScheduledAutomationRow).filter(isListedScheduledAutomation);
|
|
3232
|
+
return (await db.select().from(juniorAutomations).where(and(eq(juniorAutomations.kind, "scheduled"), ne(juniorAutomations.status, "deleted"), teamId === void 0 ? void 0 : eq(juniorAutomations.teamId, teamId))).orderBy(asc(juniorAutomations.createdAtMs), asc(juniorAutomations.id))).map(parseScheduledAutomationRow).filter(isListedScheduledAutomation);
|
|
3304
3233
|
}
|
|
3305
3234
|
/** List decoded scheduled automations in stable creation order. */
|
|
3306
3235
|
async function listScheduledAutomations(db) {
|
|
@@ -3314,7 +3243,7 @@ async function writeScheduledAutomation(db, task, current, editedBy) {
|
|
|
3314
3243
|
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")));
|
|
3315
3244
|
if (task.status === "deleted" && current?.status !== "deleted") await skipPendingRunsForDeletedTask(db, task);
|
|
3316
3245
|
await upsertScheduledAutomation(db, task);
|
|
3317
|
-
await recordAutomationVersion(db,
|
|
3246
|
+
await recordAutomationVersion(db, task, current, editedBy);
|
|
3318
3247
|
}
|
|
3319
3248
|
async function skipPendingRunsForDeletedTask(db, task) {
|
|
3320
3249
|
const errorMessage = `Scheduled automation ${task.id} was deleted before the run started.`;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { I as isRecord, L as toOptionalNumber, R as toOptionalString } from "./logging-
|
|
2
|
-
import { d as getDb } from "./viewer-
|
|
1
|
+
import { I as isRecord, L as toOptionalNumber, R as toOptionalString } from "./logging-COUsTFIL.js";
|
|
2
|
+
import { d as getDb } from "./viewer-D96vo_42.js";
|
|
3
3
|
import { d as juniorDestinations } from "./agent-invocations-D_YoNnAn.js";
|
|
4
|
-
import {
|
|
5
|
-
import { Kt as persistConversationMessages } from "./tasks-
|
|
6
|
-
import { it as JUNIOR_THREAD_STATE_TTL_MS } from "./agent-hooks-
|
|
7
|
-
import { w as getStateAdapter } from "./profile-
|
|
4
|
+
import { u as juniorLocationConfigurations } from "./executor-_4bdoCxe.js";
|
|
5
|
+
import { Kt as persistConversationMessages } from "./tasks-DwGlFX9i.js";
|
|
6
|
+
import { it as JUNIOR_THREAD_STATE_TTL_MS } from "./agent-hooks-DcoKnnxn.js";
|
|
7
|
+
import { w as getStateAdapter } from "./profile-DP4LKL6V.js";
|
|
8
8
|
import { z } from "zod";
|
|
9
9
|
import { randomUUID } from "node:crypto";
|
|
10
10
|
import { and, eq, sql } from "drizzle-orm";
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { _ as getProviderErrorUserMessage, g as getProviderErrorAttributes, h as findProviderError, p as ProviderError } from "./client-
|
|
2
|
-
import { I as isRecord, t as buildTurnFailureResponse } from "./logging-
|
|
1
|
+
import { _ as getProviderErrorUserMessage, g as getProviderErrorAttributes, h as findProviderError, p as ProviderError } from "./client-ROZeVjq0.js";
|
|
2
|
+
import { I as isRecord, t as buildTurnFailureResponse } from "./logging-COUsTFIL.js";
|
|
3
3
|
import { g as parseSlackMessageTs } from "./actor-BTtLaeWy.js";
|
|
4
|
-
import { c as getConversationEventStore, d as getDb } from "./viewer-
|
|
5
|
-
import { Gt as hydrateConversationMessages, an as markConversationMessage } from "./tasks-
|
|
6
|
-
import { Nt as listConversationAnnotations } from "./agent-hooks-
|
|
4
|
+
import { c as getConversationEventStore, d as getDb } from "./viewer-D96vo_42.js";
|
|
5
|
+
import { Gt as hydrateConversationMessages, an as markConversationMessage } from "./tasks-DwGlFX9i.js";
|
|
6
|
+
import { Nt as listConversationAnnotations } from "./agent-hooks-DcoKnnxn.js";
|
|
7
7
|
import { J as removedCardSchema, Y as resolveMessageCards, q as readMessageCardRefs } from "./conversation-T18Xlkx9.js";
|
|
8
|
-
import { r as clearPendingAuth, u as buildDeterministicTurnId } from "./pending-auth-
|
|
8
|
+
import { r as clearPendingAuth, u as buildDeterministicTurnId } from "./pending-auth-DDx3EU4M.js";
|
|
9
9
|
import { d as markTurnCompleted, u as markTurnClosed } from "./oauth-authorization-BA4Dt6a7.js";
|
|
10
|
-
import { o as persistThreadStateById, r as getPersistedThreadState, s as coerceThreadConversationState } from "./thread-state-
|
|
10
|
+
import { o as persistThreadStateById, r as getPersistedThreadState, s as coerceThreadConversationState } from "./thread-state-Ces6tXmB.js";
|
|
11
11
|
//#region src/chat/conversations/pending-cards.ts
|
|
12
12
|
/** Select undelivered cards and load their latest saved facts. */
|
|
13
13
|
async function loadPendingMessageCards(conversationId) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { c as getConversationEventStore } from "./viewer-
|
|
1
|
+
import { c as getConversationEventStore } from "./viewer-D96vo_42.js";
|
|
2
2
|
//#region src/chat/conversations/turn-lifecycle.ts
|
|
3
3
|
/** Persist correlated turn lifecycle facts with retry-safe terminal exclusion. */
|
|
4
4
|
var ConversationTurnLifecycleService = class {
|
|
@@ -34,7 +34,7 @@ function slackSourceForDestination(args) {
|
|
|
34
34
|
* Reads parent Conversations when this Conversation has no Destination.
|
|
35
35
|
*/
|
|
36
36
|
async function resolveConversationRouting(args) {
|
|
37
|
-
const conversationStore = args.conversationStore ?? (await import("./viewer-
|
|
37
|
+
const conversationStore = args.conversationStore ?? (await import("./viewer-D96vo_42.js").then((n) => n.s)).getConversationStore();
|
|
38
38
|
const chain = await loadConversationChain(args.conversationId, conversationStore);
|
|
39
39
|
let destination;
|
|
40
40
|
let source;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-B4FMCO8f.js";
|
|
2
|
-
import { n as pluginCatalogRuntime } from "./catalog-runtime-
|
|
2
|
+
import { n as pluginCatalogRuntime } from "./catalog-runtime-BQQiwwA7.js";
|
|
3
3
|
import { isDeepStrictEqual } from "node:util";
|
|
4
4
|
//#region src/chat/plugins/validation.ts
|
|
5
5
|
var validation_exports = /* @__PURE__ */ __exportAll({
|
package/dist/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as JUNIOR_VERSION } from "./version-
|
|
1
|
+
import { t as JUNIOR_VERSION } from "./version-CZYqvIFh.js";
|
|
2
2
|
export { JUNIOR_VERSION };
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-B4FMCO8f.js";
|
|
2
|
-
import { F as normalizeIdentityEmail } from "./logging-
|
|
3
|
-
import { i as getChatConfig } from "./config-
|
|
2
|
+
import { F as normalizeIdentityEmail } from "./logging-COUsTFIL.js";
|
|
3
|
+
import { i as getChatConfig } from "./config-DNNkxfGS.js";
|
|
4
4
|
import { d as parseSlackTeamId, o as parseActorUserId, u as parseSlackChannelReferenceId } from "./actor-BTtLaeWy.js";
|
|
5
5
|
import { c as juniorIdentities, d as juniorDestinations, l as juniorUsers, o as conversationReadColumns, s as juniorConversations } from "./agent-invocations-D_YoNnAn.js";
|
|
6
|
-
import {
|
|
6
|
+
import { d as juniorConversationParticipants, f as juniorConversationBindings, g as juniorConversationEvents, h as juniorConversationMetrics, m as CONVERSATION_METRICS, t as createJuniorSqlExecutor, v as juniorConversationAnnotations } from "./executor-_4bdoCxe.js";
|
|
7
7
|
import { c as newConversationEventSchema, h as usageSchema, l as encodeHistoryPayload, o as decodeStoredConversationEvent, r as conversationEventDataSchema, s as historyReplacementSchema } from "./history-9pO1Zd4Y.js";
|
|
8
8
|
import { randomUUID } from "node:crypto";
|
|
9
9
|
import { and, asc, desc, eq, gt, gte, inArray, isNull, lt, lte, ne, or, sql } from "drizzle-orm";
|