@sentry/junior 0.128.0 → 0.129.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/{agent-hooks-F75ANGBV.js → agent-hooks-ZM4WMZCN.js} +9 -9
- package/dist/api/schema/task.d.ts +152 -0
- package/dist/api/schema.d.ts +2 -0
- package/dist/api/schema.js +13 -3
- package/dist/api/tasks/routes.d.ts +4 -0
- package/dist/api.js +425 -23
- package/dist/app.d.ts +2 -1
- package/dist/app.js +315 -27
- package/dist/{catalog-runtime-ZPSA5QM2.js → catalog-runtime-TN2GPVEI.js} +5 -5
- package/dist/chat/agent-dispatch/context.d.ts +18 -0
- package/dist/chat/event-tasks/store.d.ts +7 -1
- package/dist/chat/event-tasks/tool-support.d.ts +1 -0
- package/dist/chat/resource-events/runtime-catalog.d.ts +3 -0
- package/dist/chat/sandbox/resources.d.ts +12 -1
- package/dist/chat/scheduled-tasks/cadence.d.ts +27 -0
- package/dist/chat/scheduled-tasks/heartbeat.d.ts +6 -0
- package/dist/chat/scheduled-tasks/identity.d.ts +6 -0
- package/dist/chat/scheduled-tasks/personal.d.ts +26 -0
- package/dist/chat/scheduled-tasks/schedule-intent.d.ts +61 -0
- package/dist/chat/scheduled-tasks/store.d.ts +77 -0
- package/dist/chat/scheduled-tasks/tool-support.d.ts +203 -0
- package/dist/chat/scheduled-tasks/tools/create.d.ts +80 -0
- package/dist/chat/scheduled-tasks/tools/delete.d.ts +56 -0
- package/dist/chat/scheduled-tasks/tools/list.d.ts +54 -0
- package/dist/chat/scheduled-tasks/tools/run-now.d.ts +56 -0
- package/dist/chat/scheduled-tasks/tools/update.d.ts +82 -0
- package/dist/chat/scheduled-tasks/tools.d.ts +6 -0
- package/dist/chat/scheduled-tasks/types.d.ts +81 -0
- package/dist/chat/tasks/read.d.ts +9 -0
- package/dist/chat/tools/scheduled-tasks.d.ts +4 -0
- package/dist/{chunk-K5ZB3WWH.js → chunk-2BCQKJTX.js} +2 -2
- package/dist/{chunk-G6XQODHM.js → chunk-3N4MWF3R.js} +1 -1
- package/dist/{chunk-NHWE6Y7G.js → chunk-6CMYU62S.js} +7 -7
- package/dist/{chunk-YY6CVET7.js → chunk-6QQOLIJJ.js} +1308 -804
- package/dist/{chunk-WZ365SQC.js → chunk-A6QQPVSH.js} +1 -1
- package/dist/chunk-BDIEEZK7.js +1470 -0
- package/dist/{chunk-AFJF3RGU.js → chunk-BVKP37NE.js} +61 -13
- package/dist/{chunk-5KKIBIIP.js → chunk-CZJUBH6O.js} +12 -12
- package/dist/{chunk-OLGB5Y7R.js → chunk-CZQ2DSQZ.js} +1 -1
- package/dist/{chunk-3PKF6YNU.js → chunk-E4UCPRYL.js} +1 -1
- package/dist/{chunk-KNRODVH2.js → chunk-ESYXDXNX.js} +6 -6
- package/dist/{chunk-Z4KTQMWW.js → chunk-GPWHBHAG.js} +1 -1
- package/dist/{chunk-JDCPDJ54.js → chunk-GURSWCI4.js} +2 -2
- package/dist/{chunk-RYWMDDWK.js → chunk-K3U5447S.js} +1 -1
- package/dist/{chunk-SHMHHXD5.js → chunk-KB2M27DL.js} +58 -0
- package/dist/{chunk-PBWUUVVG.js → chunk-LV2BQ26V.js} +1 -1
- package/dist/{chunk-KTGJAWRO.js → chunk-NNRV4T2C.js} +1 -2
- package/dist/{chunk-B6E3YA2H.js → chunk-P6I7LFKC.js} +1 -1
- package/dist/{chunk-B7FPRGUJ.js → chunk-PQFNTLZI.js} +3 -3
- package/dist/{chunk-A76LKS5W.js → chunk-QAOA4GUG.js} +5 -5
- package/dist/{chunk-BY43CEXN.js → chunk-R62DRNKB.js} +2 -2
- package/dist/{chunk-HBFQLSGV.js → chunk-U23X4ASF.js} +4 -4
- package/dist/{chunk-2HTHX6XV.js → chunk-XENYUOZG.js} +38 -17
- package/dist/cli/chat.js +24 -24
- package/dist/cli/check.js +6 -6
- package/dist/cli/plugins.js +12 -12
- package/dist/cli/snapshot-create.js +9 -9
- package/dist/cli/upgrade.js +9 -17
- package/dist/db/schema/scheduled-tasks.d.ts +257 -0
- package/dist/db/schema.d.ts +258 -1
- package/dist/{db-FYJYPAKG.js → db-ZI6TBXIS.js} +7 -7
- package/dist/instrumentation.js +4 -4
- package/dist/nitro.js +2 -2
- package/dist/{oauth-callback-server-W3PPIHCS.js → oauth-callback-server-TLA4GARF.js} +17 -17
- package/dist/{runner-5NOFUYKR.js → runner-23YFRWQJ.js} +11 -11
- package/dist/{skills-ENIBKF5V.js → skills-QIUG4D6M.js} +6 -6
- package/dist/{validation-BHLBOO6K.js → validation-3KGEBATS.js} +6 -6
- package/dist/version.js +1 -1
- package/migrations/0016_neat_the_anarchist.sql +171 -0
- package/migrations/meta/0016_snapshot.json +1617 -0
- package/migrations/meta/_journal.json +7 -0
- package/package.json +5 -6
- package/dist/chunk-FJEIX3AH.js +0 -37
package/dist/api.js
CHANGED
|
@@ -24,13 +24,15 @@ import {
|
|
|
24
24
|
personalTokenListSchema,
|
|
25
25
|
personalTokenParamsSchema,
|
|
26
26
|
revokePersonalTokenResponseSchema,
|
|
27
|
-
statsReportSchema
|
|
28
|
-
|
|
27
|
+
statsReportSchema,
|
|
28
|
+
taskListSchema,
|
|
29
|
+
taskParamsSchema
|
|
30
|
+
} from "./chunk-BVKP37NE.js";
|
|
29
31
|
import {
|
|
30
32
|
formatSlackConversationRedactedLabel,
|
|
31
33
|
readHealthReport,
|
|
32
34
|
resolveSlackConversationContextFromThreadId
|
|
33
|
-
} from "./chunk-
|
|
35
|
+
} from "./chunk-GURSWCI4.js";
|
|
34
36
|
import {
|
|
35
37
|
buildSentryConversationUrl
|
|
36
38
|
} from "./chunk-4CODA7P5.js";
|
|
@@ -42,11 +44,20 @@ import {
|
|
|
42
44
|
skillReportsSchema
|
|
43
45
|
} from "./chunk-UTL3MHPC.js";
|
|
44
46
|
import {
|
|
47
|
+
createSchedulerSqlStore,
|
|
48
|
+
deleteEventTask,
|
|
49
|
+
eventTaskBelongsToUser,
|
|
50
|
+
eventTaskTriggerAvailable,
|
|
51
|
+
getEventTask,
|
|
52
|
+
getResourceEventCatalog,
|
|
53
|
+
listEventTasksCreatedBy,
|
|
54
|
+
listPublicEventTasksForTeams,
|
|
55
|
+
listPublicScheduledTasksForTeams,
|
|
45
56
|
readStats
|
|
46
|
-
} from "./chunk-
|
|
57
|
+
} from "./chunk-BDIEEZK7.js";
|
|
47
58
|
import {
|
|
48
59
|
parseSlackThreadId
|
|
49
|
-
} from "./chunk-
|
|
60
|
+
} from "./chunk-LV2BQ26V.js";
|
|
50
61
|
import {
|
|
51
62
|
agentTurnUsageSchema,
|
|
52
63
|
hasAgentTurnUsage,
|
|
@@ -59,41 +70,41 @@ import {
|
|
|
59
70
|
listConversationAnnotations,
|
|
60
71
|
renderPluginConversationEvent,
|
|
61
72
|
resolveViewerUser
|
|
62
|
-
} from "./chunk-
|
|
73
|
+
} from "./chunk-QAOA4GUG.js";
|
|
63
74
|
import {
|
|
64
75
|
decodeStoredConversationEvent,
|
|
65
76
|
getDb,
|
|
66
77
|
getSqlExecutor,
|
|
67
78
|
parseSessionSource
|
|
68
|
-
} from "./chunk-
|
|
79
|
+
} from "./chunk-PQFNTLZI.js";
|
|
69
80
|
import {
|
|
70
81
|
juniorApiTokens,
|
|
71
82
|
juniorConversationEvents,
|
|
72
83
|
juniorConversations,
|
|
73
84
|
juniorIdentities,
|
|
74
85
|
juniorUsers
|
|
75
|
-
} from "./chunk-
|
|
76
|
-
import "./chunk-
|
|
77
|
-
import "./chunk-
|
|
86
|
+
} from "./chunk-KB2M27DL.js";
|
|
87
|
+
import "./chunk-3N4MWF3R.js";
|
|
88
|
+
import "./chunk-2BCQKJTX.js";
|
|
78
89
|
import {
|
|
79
90
|
juniorDestinations
|
|
80
91
|
} from "./chunk-VFUK3X5B.js";
|
|
81
92
|
import {
|
|
82
93
|
canExposeConversationPayload
|
|
83
|
-
} from "./chunk-
|
|
94
|
+
} from "./chunk-GPWHBHAG.js";
|
|
84
95
|
import "./chunk-HZF5P5UN.js";
|
|
85
96
|
import {
|
|
86
97
|
parseSlackChannelId,
|
|
87
98
|
parseSlackTeamId
|
|
88
99
|
} from "./chunk-F3B2YJ76.js";
|
|
89
|
-
import "./chunk-
|
|
100
|
+
import "./chunk-P6I7LFKC.js";
|
|
90
101
|
import "./chunk-6GWA276C.js";
|
|
91
|
-
import "./chunk-
|
|
92
|
-
import "./chunk-
|
|
102
|
+
import "./chunk-K3U5447S.js";
|
|
103
|
+
import "./chunk-NNRV4T2C.js";
|
|
93
104
|
import "./chunk-MLKGABMK.js";
|
|
94
105
|
|
|
95
106
|
// src/api.ts
|
|
96
|
-
import { Hono as
|
|
107
|
+
import { Hono as Hono7 } from "hono";
|
|
97
108
|
|
|
98
109
|
// src/api/conversations/routes.ts
|
|
99
110
|
import { Hono } from "hono";
|
|
@@ -2015,7 +2026,7 @@ function readDescriptionText(home) {
|
|
|
2015
2026
|
}
|
|
2016
2027
|
}
|
|
2017
2028
|
async function readSkillReports() {
|
|
2018
|
-
const { discoverSkills } = await import("./skills-
|
|
2029
|
+
const { discoverSkills } = await import("./skills-QIUG4D6M.js");
|
|
2019
2030
|
const skills = await discoverSkills();
|
|
2020
2031
|
return skillReportsSchema.parse(
|
|
2021
2032
|
skills.map((skill) => ({
|
|
@@ -2025,7 +2036,7 @@ async function readSkillReports() {
|
|
|
2025
2036
|
);
|
|
2026
2037
|
}
|
|
2027
2038
|
async function readPlugins() {
|
|
2028
|
-
const { pluginCatalogRuntime } = await import("./catalog-runtime-
|
|
2039
|
+
const { pluginCatalogRuntime } = await import("./catalog-runtime-TN2GPVEI.js");
|
|
2029
2040
|
return pluginsSchema.parse(
|
|
2030
2041
|
pluginCatalogRuntime.getProviders().map((plugin) => ({
|
|
2031
2042
|
configKeys: plugin.manifest.configKeys ?? [],
|
|
@@ -2038,7 +2049,7 @@ async function readPlugins() {
|
|
|
2038
2049
|
async function readRuntimeInfoReport() {
|
|
2039
2050
|
const [{ homeDir }, { pluginCatalogRuntime }, plugins, skills] = await Promise.all([
|
|
2040
2051
|
import("./discovery-GUFTFBTL.js"),
|
|
2041
|
-
import("./catalog-runtime-
|
|
2052
|
+
import("./catalog-runtime-TN2GPVEI.js"),
|
|
2042
2053
|
readPlugins(),
|
|
2043
2054
|
readSkillReports()
|
|
2044
2055
|
]);
|
|
@@ -2054,7 +2065,7 @@ async function readRuntimeInfoReport() {
|
|
|
2054
2065
|
}
|
|
2055
2066
|
async function readPluginOperationalReportFeed() {
|
|
2056
2067
|
const nowMs = Date.now();
|
|
2057
|
-
const { getPluginOperationalReports } = await import("./agent-hooks-
|
|
2068
|
+
const { getPluginOperationalReports } = await import("./agent-hooks-ZM4WMZCN.js");
|
|
2058
2069
|
return pluginOperationalReportFeedSchema.parse({
|
|
2059
2070
|
source: "plugins",
|
|
2060
2071
|
generatedAt: new Date(nowMs).toISOString(),
|
|
@@ -3262,8 +3273,8 @@ async function readPluginUserPage(input) {
|
|
|
3262
3273
|
(candidate) => candidate.id === input.pageId
|
|
3263
3274
|
);
|
|
3264
3275
|
if (!plugin || !page) return void 0;
|
|
3265
|
-
const
|
|
3266
|
-
if (!
|
|
3276
|
+
const viewer2 = await resolveViewerUser(input.email);
|
|
3277
|
+
if (!viewer2) {
|
|
3267
3278
|
throw new Error("Authenticated viewer user could not be resolved");
|
|
3268
3279
|
}
|
|
3269
3280
|
const content = pluginUserPageContentSchema.parse(
|
|
@@ -3272,7 +3283,7 @@ async function readPluginUserPage(input) {
|
|
|
3272
3283
|
db: getDb(),
|
|
3273
3284
|
log: createPluginLogger(plugin.manifest.name),
|
|
3274
3285
|
plugin: { name: plugin.manifest.name },
|
|
3275
|
-
viewer
|
|
3286
|
+
viewer: viewer2
|
|
3276
3287
|
},
|
|
3277
3288
|
input.query
|
|
3278
3289
|
)
|
|
@@ -3333,6 +3344,396 @@ function createUserPageRoutes() {
|
|
|
3333
3344
|
return app;
|
|
3334
3345
|
}
|
|
3335
3346
|
|
|
3347
|
+
// src/api/tasks/routes.ts
|
|
3348
|
+
import { Hono as Hono6 } from "hono";
|
|
3349
|
+
|
|
3350
|
+
// src/chat/tasks/read.ts
|
|
3351
|
+
import { and as and14, eq as eq15, or as or3 } from "drizzle-orm";
|
|
3352
|
+
|
|
3353
|
+
// src/chat/scheduled-tasks/personal.ts
|
|
3354
|
+
import { z as z3 } from "zod";
|
|
3355
|
+
var cursorSchema = z3.object({
|
|
3356
|
+
createdAtMs: z3.number().finite(),
|
|
3357
|
+
id: z3.string().min(1),
|
|
3358
|
+
query: z3.string().max(200).optional(),
|
|
3359
|
+
version: z3.literal(1)
|
|
3360
|
+
}).strict();
|
|
3361
|
+
var InvalidScheduledTaskCursorError = class extends Error {
|
|
3362
|
+
constructor() {
|
|
3363
|
+
super("Scheduled task cursor is invalid.");
|
|
3364
|
+
this.name = "InvalidScheduledTaskCursorError";
|
|
3365
|
+
}
|
|
3366
|
+
};
|
|
3367
|
+
var PersonalScheduledTaskNotFoundError = class extends Error {
|
|
3368
|
+
constructor() {
|
|
3369
|
+
super("Scheduled task was not found.");
|
|
3370
|
+
this.name = "PersonalScheduledTaskNotFoundError";
|
|
3371
|
+
}
|
|
3372
|
+
};
|
|
3373
|
+
function normalizeQuery(query) {
|
|
3374
|
+
return query?.trim().toLowerCase() || void 0;
|
|
3375
|
+
}
|
|
3376
|
+
function decodeCursor(value, query) {
|
|
3377
|
+
if (!value) return void 0;
|
|
3378
|
+
try {
|
|
3379
|
+
const parsed = cursorSchema.parse(
|
|
3380
|
+
JSON.parse(Buffer.from(value, "base64url").toString("utf8"))
|
|
3381
|
+
);
|
|
3382
|
+
if (parsed.query !== query) {
|
|
3383
|
+
throw new InvalidScheduledTaskCursorError();
|
|
3384
|
+
}
|
|
3385
|
+
return { createdAtMs: parsed.createdAtMs, id: parsed.id };
|
|
3386
|
+
} catch {
|
|
3387
|
+
throw new InvalidScheduledTaskCursorError();
|
|
3388
|
+
}
|
|
3389
|
+
}
|
|
3390
|
+
function encodeCursor(task, query) {
|
|
3391
|
+
return Buffer.from(
|
|
3392
|
+
JSON.stringify({
|
|
3393
|
+
createdAtMs: task.createdAtMs,
|
|
3394
|
+
id: task.id,
|
|
3395
|
+
...query ? { query } : {},
|
|
3396
|
+
version: 1
|
|
3397
|
+
}),
|
|
3398
|
+
"utf8"
|
|
3399
|
+
).toString("base64url");
|
|
3400
|
+
}
|
|
3401
|
+
function createViewerScheduledTasks(store, user) {
|
|
3402
|
+
const identityIds = new Set(user.identities.map((identity) => identity.id));
|
|
3403
|
+
return {
|
|
3404
|
+
async delete(id, nowMs = Date.now()) {
|
|
3405
|
+
const task = await store.getTask(id);
|
|
3406
|
+
if (!task || task.status === "deleted" || !identityIds.has(task.creatorIdentityId)) {
|
|
3407
|
+
throw new PersonalScheduledTaskNotFoundError();
|
|
3408
|
+
}
|
|
3409
|
+
await store.saveTask({
|
|
3410
|
+
...task,
|
|
3411
|
+
nextRunAtMs: void 0,
|
|
3412
|
+
runNowAtMs: void 0,
|
|
3413
|
+
status: "deleted",
|
|
3414
|
+
updatedAtMs: nowMs
|
|
3415
|
+
});
|
|
3416
|
+
},
|
|
3417
|
+
async list(input) {
|
|
3418
|
+
const query = normalizeQuery(input.query);
|
|
3419
|
+
const cursor = decodeCursor(input.cursor, query);
|
|
3420
|
+
const matching = await store.listTasksCreatedBy({
|
|
3421
|
+
...cursor ? { before: cursor } : {},
|
|
3422
|
+
identityIds: [...identityIds],
|
|
3423
|
+
limit: input.limit + 1,
|
|
3424
|
+
...query ? { query } : {}
|
|
3425
|
+
});
|
|
3426
|
+
const tasks = matching.slice(0, input.limit);
|
|
3427
|
+
return {
|
|
3428
|
+
tasks,
|
|
3429
|
+
...matching.length > input.limit && tasks.length > 0 ? { nextCursor: encodeCursor(tasks.at(-1), query) } : {}
|
|
3430
|
+
};
|
|
3431
|
+
}
|
|
3432
|
+
};
|
|
3433
|
+
}
|
|
3434
|
+
|
|
3435
|
+
// src/chat/tasks/read.ts
|
|
3436
|
+
var TASK_LIST_LIMIT = 100;
|
|
3437
|
+
var TASK_FETCH_LIMIT = TASK_LIST_LIMIT + 1;
|
|
3438
|
+
function creatorLabel(creator) {
|
|
3439
|
+
return creator.fullName?.trim() || (creator.userName?.trim() ? `@${creator.userName.trim()}` : "") || creator.slackUserId;
|
|
3440
|
+
}
|
|
3441
|
+
function creatorKey(teamId, slackUserId) {
|
|
3442
|
+
return `${teamId}:${slackUserId}`;
|
|
3443
|
+
}
|
|
3444
|
+
async function creatorProfileEmails(candidates) {
|
|
3445
|
+
const selectors = new Map(
|
|
3446
|
+
candidates.map(({ task }) => {
|
|
3447
|
+
const teamId = task.destination.teamId;
|
|
3448
|
+
const slackUserId = task.createdBy.slackUserId;
|
|
3449
|
+
return [
|
|
3450
|
+
creatorKey(teamId, slackUserId),
|
|
3451
|
+
{ slackUserId, teamId }
|
|
3452
|
+
];
|
|
3453
|
+
})
|
|
3454
|
+
);
|
|
3455
|
+
if (selectors.size === 0) return /* @__PURE__ */ new Map();
|
|
3456
|
+
const rows = await getDb().select({
|
|
3457
|
+
email: juniorUsers.primaryEmailNormalized,
|
|
3458
|
+
slackUserId: juniorIdentities.providerSubjectId,
|
|
3459
|
+
teamId: juniorIdentities.providerTenantId
|
|
3460
|
+
}).from(juniorIdentities).innerJoin(juniorUsers, eq15(juniorUsers.id, juniorIdentities.userId)).where(
|
|
3461
|
+
and14(
|
|
3462
|
+
eq15(juniorIdentities.kind, "user"),
|
|
3463
|
+
eq15(juniorIdentities.provider, "slack"),
|
|
3464
|
+
eq15(juniorIdentities.emailVerified, true),
|
|
3465
|
+
or3(
|
|
3466
|
+
...[...selectors.values()].map(
|
|
3467
|
+
(selector) => and14(
|
|
3468
|
+
eq15(juniorIdentities.providerTenantId, selector.teamId),
|
|
3469
|
+
eq15(juniorIdentities.providerSubjectId, selector.slackUserId)
|
|
3470
|
+
)
|
|
3471
|
+
)
|
|
3472
|
+
)
|
|
3473
|
+
)
|
|
3474
|
+
);
|
|
3475
|
+
return new Map(
|
|
3476
|
+
rows.map((row) => [creatorKey(row.teamId, row.slackUserId), row.email])
|
|
3477
|
+
);
|
|
3478
|
+
}
|
|
3479
|
+
function destinationKey(destination) {
|
|
3480
|
+
return `${destination.teamId}:${destination.channelId}`;
|
|
3481
|
+
}
|
|
3482
|
+
function displayText(value, fallback) {
|
|
3483
|
+
return value.trim() || fallback;
|
|
3484
|
+
}
|
|
3485
|
+
async function destinationDetails(destinations) {
|
|
3486
|
+
const selectors = new Map(
|
|
3487
|
+
destinations.map((destination) => [
|
|
3488
|
+
destinationKey(destination),
|
|
3489
|
+
destination
|
|
3490
|
+
])
|
|
3491
|
+
);
|
|
3492
|
+
if (selectors.size === 0) return /* @__PURE__ */ new Map();
|
|
3493
|
+
const rows = await getDb().select({
|
|
3494
|
+
displayName: juniorDestinations.displayName,
|
|
3495
|
+
kind: juniorDestinations.kind,
|
|
3496
|
+
providerDestinationId: juniorDestinations.providerDestinationId,
|
|
3497
|
+
providerTenantId: juniorDestinations.providerTenantId,
|
|
3498
|
+
visibility: juniorDestinations.visibility
|
|
3499
|
+
}).from(juniorDestinations).where(
|
|
3500
|
+
or3(
|
|
3501
|
+
...[...selectors.values()].map(
|
|
3502
|
+
(destination) => and14(
|
|
3503
|
+
eq15(juniorDestinations.provider, "slack"),
|
|
3504
|
+
eq15(juniorDestinations.providerTenantId, destination.teamId),
|
|
3505
|
+
eq15(juniorDestinations.providerDestinationId, destination.channelId)
|
|
3506
|
+
)
|
|
3507
|
+
)
|
|
3508
|
+
)
|
|
3509
|
+
);
|
|
3510
|
+
return new Map(
|
|
3511
|
+
rows.map((row) => {
|
|
3512
|
+
const name = row.displayName?.trim();
|
|
3513
|
+
const label = name ? row.kind === "channel" ? `#${name.replace(/^#/, "")}` : name : row.kind === "dm" ? "Direct message" : row.kind === "group" ? "Group message" : `Channel ${row.providerDestinationId}`;
|
|
3514
|
+
return [
|
|
3515
|
+
`${row.providerTenantId}:${row.providerDestinationId}`,
|
|
3516
|
+
{
|
|
3517
|
+
label,
|
|
3518
|
+
visibility: row.visibility === "public" ? "public" : "private"
|
|
3519
|
+
}
|
|
3520
|
+
];
|
|
3521
|
+
})
|
|
3522
|
+
);
|
|
3523
|
+
}
|
|
3524
|
+
function scheduledTaskSummary(task, ownedByViewer, destination) {
|
|
3525
|
+
if (task.status === "deleted") {
|
|
3526
|
+
throw new Error("Deleted scheduled tasks cannot enter the Tasks view");
|
|
3527
|
+
}
|
|
3528
|
+
const nextRunAtMs = task.runNowAtMs ?? task.nextRunAtMs;
|
|
3529
|
+
return {
|
|
3530
|
+
createdAt: new Date(task.createdAtMs).toISOString(),
|
|
3531
|
+
createdBy: creatorLabel(task.createdBy),
|
|
3532
|
+
destination: {
|
|
3533
|
+
channelId: task.destination.channelId,
|
|
3534
|
+
label: destination.label,
|
|
3535
|
+
teamId: task.destination.teamId,
|
|
3536
|
+
visibility: destination.visibility
|
|
3537
|
+
},
|
|
3538
|
+
id: task.id,
|
|
3539
|
+
instruction: displayText(task.task.text, "Untitled scheduled task"),
|
|
3540
|
+
kind: "scheduled",
|
|
3541
|
+
...nextRunAtMs !== void 0 ? { nextRunAt: new Date(nextRunAtMs).toISOString() } : {},
|
|
3542
|
+
ownedByViewer,
|
|
3543
|
+
schedule: displayText(task.schedule.description, "Schedule unavailable"),
|
|
3544
|
+
status: task.status
|
|
3545
|
+
};
|
|
3546
|
+
}
|
|
3547
|
+
async function readViewerTasks(user) {
|
|
3548
|
+
const db = getDb();
|
|
3549
|
+
const schedulerStore = createSchedulerSqlStore(db);
|
|
3550
|
+
const identityIds = new Set(user.identities.map((identity) => identity.id));
|
|
3551
|
+
const teamIds = [
|
|
3552
|
+
...new Set(
|
|
3553
|
+
user.identities.filter((identity) => identity.provider === "slack").map((identity) => identity.providerTenantId).filter((teamId) => Boolean(teamId))
|
|
3554
|
+
)
|
|
3555
|
+
];
|
|
3556
|
+
const [scheduledPage, publicScheduled, eventTasks, publicEventTasks] = await Promise.all([
|
|
3557
|
+
createViewerScheduledTasks(schedulerStore, user).list({
|
|
3558
|
+
limit: TASK_FETCH_LIMIT
|
|
3559
|
+
}),
|
|
3560
|
+
listPublicScheduledTasksForTeams(db, teamIds, TASK_FETCH_LIMIT),
|
|
3561
|
+
listEventTasksCreatedBy(db, user, TASK_FETCH_LIMIT),
|
|
3562
|
+
listPublicEventTasksForTeams(db, teamIds, TASK_FETCH_LIMIT)
|
|
3563
|
+
]);
|
|
3564
|
+
const candidatesById = /* @__PURE__ */ new Map();
|
|
3565
|
+
const publicScheduledIds = new Set(publicScheduled.map((task) => task.id));
|
|
3566
|
+
const publicEventTaskIds = new Set(publicEventTasks.map((task) => task.id));
|
|
3567
|
+
for (const task of [...scheduledPage.tasks, ...publicScheduled]) {
|
|
3568
|
+
candidatesById.set(`scheduled:${task.id}`, {
|
|
3569
|
+
kind: "scheduled",
|
|
3570
|
+
ownedByViewer: identityIds.has(task.creatorIdentityId),
|
|
3571
|
+
publicToViewer: publicScheduledIds.has(task.id),
|
|
3572
|
+
task
|
|
3573
|
+
});
|
|
3574
|
+
}
|
|
3575
|
+
for (const task of [...eventTasks, ...publicEventTasks]) {
|
|
3576
|
+
candidatesById.set(`event:${task.id}`, {
|
|
3577
|
+
kind: "event",
|
|
3578
|
+
ownedByViewer: eventTaskBelongsToUser(task, user),
|
|
3579
|
+
publicToViewer: publicEventTaskIds.has(task.id),
|
|
3580
|
+
task
|
|
3581
|
+
});
|
|
3582
|
+
}
|
|
3583
|
+
const candidates = [...candidatesById.values()].sort(
|
|
3584
|
+
(left, right) => right.task.createdAtMs - left.task.createdAtMs || right.task.id.localeCompare(left.task.id)
|
|
3585
|
+
);
|
|
3586
|
+
const ownedCandidates = candidates.filter(
|
|
3587
|
+
(candidate) => candidate.ownedByViewer
|
|
3588
|
+
);
|
|
3589
|
+
const publicCandidates = candidates.filter(
|
|
3590
|
+
(candidate) => candidate.publicToViewer
|
|
3591
|
+
);
|
|
3592
|
+
const selectedCandidates = /* @__PURE__ */ new Set([
|
|
3593
|
+
...ownedCandidates.slice(0, TASK_LIST_LIMIT),
|
|
3594
|
+
...publicCandidates.slice(0, TASK_LIST_LIMIT)
|
|
3595
|
+
]);
|
|
3596
|
+
const selected = candidates.filter(
|
|
3597
|
+
(candidate) => selectedCandidates.has(candidate)
|
|
3598
|
+
);
|
|
3599
|
+
const [destinations, creatorEmails] = await Promise.all([
|
|
3600
|
+
destinationDetails(selected.map(({ task }) => task.destination)),
|
|
3601
|
+
creatorProfileEmails(selected)
|
|
3602
|
+
]);
|
|
3603
|
+
const eventCatalog = getResourceEventCatalog();
|
|
3604
|
+
const visible = selected.filter(
|
|
3605
|
+
(candidate) => candidate.ownedByViewer || destinations.get(destinationKey(candidate.task.destination))?.visibility === "public"
|
|
3606
|
+
);
|
|
3607
|
+
const tasks = visible.map((candidate) => {
|
|
3608
|
+
const destination = destinations.get(
|
|
3609
|
+
destinationKey(candidate.task.destination)
|
|
3610
|
+
) ?? {
|
|
3611
|
+
label: `Channel ${candidate.task.destination.channelId}`,
|
|
3612
|
+
visibility: "private"
|
|
3613
|
+
};
|
|
3614
|
+
const createdByEmail = creatorEmails.get(
|
|
3615
|
+
creatorKey(
|
|
3616
|
+
candidate.task.destination.teamId,
|
|
3617
|
+
candidate.task.createdBy.slackUserId
|
|
3618
|
+
)
|
|
3619
|
+
);
|
|
3620
|
+
if (candidate.kind === "scheduled") {
|
|
3621
|
+
const summary = scheduledTaskSummary(
|
|
3622
|
+
candidate.task,
|
|
3623
|
+
candidate.ownedByViewer,
|
|
3624
|
+
destination
|
|
3625
|
+
);
|
|
3626
|
+
return {
|
|
3627
|
+
...summary,
|
|
3628
|
+
...createdByEmail ? { createdByEmail } : {}
|
|
3629
|
+
};
|
|
3630
|
+
}
|
|
3631
|
+
const task = candidate.task;
|
|
3632
|
+
return {
|
|
3633
|
+
createdAt: new Date(task.createdAtMs).toISOString(),
|
|
3634
|
+
createdBy: creatorLabel(task.createdBy),
|
|
3635
|
+
...createdByEmail ? { createdByEmail } : {},
|
|
3636
|
+
destination: {
|
|
3637
|
+
channelId: task.destination.channelId,
|
|
3638
|
+
label: destination.label,
|
|
3639
|
+
teamId: task.destination.teamId,
|
|
3640
|
+
visibility: destination.visibility
|
|
3641
|
+
},
|
|
3642
|
+
events: task.trigger.events,
|
|
3643
|
+
id: task.id,
|
|
3644
|
+
instruction: task.task.text,
|
|
3645
|
+
kind: "event",
|
|
3646
|
+
ownedByViewer: candidate.ownedByViewer,
|
|
3647
|
+
resource: `${task.trigger.label} \xB7 ${task.trigger.identifier}`,
|
|
3648
|
+
source: task.trigger.namespace,
|
|
3649
|
+
triggerAvailable: eventTaskTriggerAvailable(task, eventCatalog)
|
|
3650
|
+
};
|
|
3651
|
+
});
|
|
3652
|
+
return {
|
|
3653
|
+
tasks,
|
|
3654
|
+
truncated: ownedCandidates.length > TASK_LIST_LIMIT || publicCandidates.length > TASK_LIST_LIMIT
|
|
3655
|
+
};
|
|
3656
|
+
}
|
|
3657
|
+
var ViewerTaskNotFoundError = class extends Error {
|
|
3658
|
+
constructor() {
|
|
3659
|
+
super("Task was not found.");
|
|
3660
|
+
this.name = "ViewerTaskNotFoundError";
|
|
3661
|
+
}
|
|
3662
|
+
};
|
|
3663
|
+
async function deleteViewerTask(user, kind, id) {
|
|
3664
|
+
if (kind === "scheduled") {
|
|
3665
|
+
try {
|
|
3666
|
+
await createViewerScheduledTasks(
|
|
3667
|
+
createSchedulerSqlStore(getDb()),
|
|
3668
|
+
user
|
|
3669
|
+
).delete(id);
|
|
3670
|
+
return;
|
|
3671
|
+
} catch (error) {
|
|
3672
|
+
if (error instanceof PersonalScheduledTaskNotFoundError) {
|
|
3673
|
+
throw new ViewerTaskNotFoundError();
|
|
3674
|
+
}
|
|
3675
|
+
throw error;
|
|
3676
|
+
}
|
|
3677
|
+
}
|
|
3678
|
+
const task = await getEventTask(getDb(), id);
|
|
3679
|
+
if (!task || !eventTaskBelongsToUser(task, user)) {
|
|
3680
|
+
throw new ViewerTaskNotFoundError();
|
|
3681
|
+
}
|
|
3682
|
+
await deleteEventTask(getDb(), id);
|
|
3683
|
+
}
|
|
3684
|
+
|
|
3685
|
+
// src/api/tasks/routes.ts
|
|
3686
|
+
async function viewer(context) {
|
|
3687
|
+
const email = context.get("verifiedViewerEmail")?.trim();
|
|
3688
|
+
return email ? await resolveViewerUser(email) : void 0;
|
|
3689
|
+
}
|
|
3690
|
+
function createTaskRoutes() {
|
|
3691
|
+
const app = new Hono6();
|
|
3692
|
+
app.get("/", async (context) => {
|
|
3693
|
+
const user = await viewer(context);
|
|
3694
|
+
return user ? jsonResponse(taskListSchema, await readViewerTasks(user)) : jsonResponse(
|
|
3695
|
+
apiErrorSchema,
|
|
3696
|
+
{ error: "Authentication required." },
|
|
3697
|
+
{ status: 401 }
|
|
3698
|
+
);
|
|
3699
|
+
});
|
|
3700
|
+
app.delete("/:kind/:id", async (context) => {
|
|
3701
|
+
const user = await viewer(context);
|
|
3702
|
+
if (!user) {
|
|
3703
|
+
return jsonResponse(
|
|
3704
|
+
apiErrorSchema,
|
|
3705
|
+
{ error: "Authentication required." },
|
|
3706
|
+
{ status: 401 }
|
|
3707
|
+
);
|
|
3708
|
+
}
|
|
3709
|
+
const params = taskParamsSchema.safeParse(context.req.param());
|
|
3710
|
+
if (!params.success) {
|
|
3711
|
+
return jsonResponse(
|
|
3712
|
+
apiErrorSchema,
|
|
3713
|
+
{ error: "Invalid task." },
|
|
3714
|
+
{ status: 400 }
|
|
3715
|
+
);
|
|
3716
|
+
}
|
|
3717
|
+
try {
|
|
3718
|
+
await deleteViewerTask(user, params.data.kind, params.data.id);
|
|
3719
|
+
return new Response(null, {
|
|
3720
|
+
headers: { "cache-control": "no-store" },
|
|
3721
|
+
status: 204
|
|
3722
|
+
});
|
|
3723
|
+
} catch (error) {
|
|
3724
|
+
if (error instanceof ViewerTaskNotFoundError) {
|
|
3725
|
+
return jsonResponse(
|
|
3726
|
+
apiErrorSchema,
|
|
3727
|
+
{ error: error.message },
|
|
3728
|
+
{ status: 404 }
|
|
3729
|
+
);
|
|
3730
|
+
}
|
|
3731
|
+
throw error;
|
|
3732
|
+
}
|
|
3733
|
+
});
|
|
3734
|
+
return app;
|
|
3735
|
+
}
|
|
3736
|
+
|
|
3336
3737
|
// src/api/plugins.ts
|
|
3337
3738
|
var plugins_default = defineApiRoute({
|
|
3338
3739
|
method: "get",
|
|
@@ -3390,13 +3791,14 @@ var routes4 = [
|
|
|
3390
3791
|
stats_default2
|
|
3391
3792
|
];
|
|
3392
3793
|
function createJuniorApi() {
|
|
3393
|
-
const app = new
|
|
3794
|
+
const app = new Hono7();
|
|
3394
3795
|
registerApiRoutes(app, routes4);
|
|
3395
3796
|
app.route("/api/conversations", createConversationRoutes());
|
|
3396
3797
|
app.route("/api/personal-tokens", createPersonalTokenRoutes());
|
|
3397
3798
|
app.route("/api/people", createPeopleRoutes());
|
|
3398
3799
|
app.route("/api/locations", createLocationRoutes());
|
|
3399
3800
|
app.route("/api/user-pages", createUserPageRoutes());
|
|
3801
|
+
app.route("/api/tasks", createTaskRoutes());
|
|
3400
3802
|
app.notFound(
|
|
3401
3803
|
() => jsonResponse(
|
|
3402
3804
|
apiErrorSchema,
|
package/dist/app.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Hono } from "hono";
|
|
2
|
+
import { type SandboxResourceConfig } from "@/chat/sandbox/resources";
|
|
2
3
|
import { type JuniorPluginSet } from "./plugins";
|
|
3
4
|
import { type VercelConversationWorkCallbackOptions } from "@/chat/task-execution/vercel-callback";
|
|
4
5
|
import type { WaitUntilFn } from "@/handlers/types";
|
|
@@ -22,7 +23,7 @@ export interface JuniorAppOptions {
|
|
|
22
23
|
/** Direct plugin set override. Usually omitted when `juniorNitro()` uses a plugin module. */
|
|
23
24
|
plugins?: JuniorPluginSet;
|
|
24
25
|
/** Sandbox execution options. */
|
|
25
|
-
sandbox?: {
|
|
26
|
+
sandbox?: SandboxResourceConfig & {
|
|
26
27
|
/**
|
|
27
28
|
* Egress domains allowed to carry Sentry trace propagation headers.
|
|
28
29
|
* Entries may be exact domains or leading wildcard domains such as
|