@sentry/junior 0.257.0 → 0.259.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/{actor-BTtLaeWy.js → actor-tlxzqaRe.js} +3 -6
- package/dist/adapter-Bn0gFVSF.js +270 -0
- package/dist/{admin-DgIkm6Vy.js → admin-C8xz2f10.js} +2 -3
- package/dist/{agent-hooks-BjtTzvru.js → agent-hooks-B00FaKdP.js} +70 -109
- package/dist/{agent-invocations-Bdu3ROfo.js → agent-invocations-Qfz7dWgU.js} +6 -12
- package/dist/{agent-runner-D7OboVb3.js → agent-runner-CPSd7rKm.js} +324 -742
- package/dist/api/schema.d.ts +442 -447
- package/dist/api/schema.js +6 -6
- package/dist/api.d.ts +2 -12
- package/dist/api.js +165 -158
- package/dist/{app-BsU5QNBd.d.ts → app-Bbxrehjf.d.ts} +25 -45
- package/dist/app.d.ts +3 -3
- package/dist/app.js +206 -321
- package/dist/{assistant-reply-CbTPebzL.js → assistant-reply-CqthTerd.js} +3 -5
- package/dist/{automation-CHdlHVZP.js → automation-DWBFBenG.js} +6 -11
- package/dist/{briefs-oLOldnDM.js → briefs-DNYbQ9cD.js} +8 -11
- package/dist/{cadence-D00SCzT1.js → cadence-R7Em4RjE.js} +1 -2
- package/dist/{catalog-runtime-CZzhGQ7F.js → catalog-runtime-B8SuFPGb.js} +3 -4
- package/dist/cli/chat.d.ts +2 -4
- package/dist/cli/chat.js +22 -24
- package/dist/cli/check.d.ts +1 -3
- package/dist/cli/check.js +4 -5
- package/dist/cli/env.d.ts +1 -3
- package/dist/cli/env.js +1 -2
- package/dist/cli/init.d.ts +1 -3
- package/dist/cli/init.js +3 -3
- package/dist/cli/main.d.ts +1 -3
- package/dist/cli/main.js +8 -5
- package/dist/cli/plugins.d.ts +2 -4
- package/dist/cli/plugins.js +7 -8
- package/dist/cli/run.d.ts +3 -3
- package/dist/cli/run.js +3 -3
- package/dist/cli/snapshot-create.d.ts +1 -3
- package/dist/cli/snapshot-create.js +5 -5
- package/dist/cli/upgrade.d.ts +3 -6
- package/dist/cli/upgrade.js +11 -17
- package/dist/{client-D8HnkOQX.js → client-BZdxgKyL.js} +64 -18
- package/dist/{config-CJRnWK9H.js → config-Deqpfpg9.js} +21 -15
- package/dist/{connections-ClYrKzpX.js → connections-9gJkfS85.js} +179 -20
- package/dist/{conversation-CKNLYBJt.js → conversation-DjN3mlog.js} +8 -15
- package/dist/{conversation-privacy-C8b1nphZ.js → conversation-privacy-CFhNKxp-.js} +2 -3
- package/dist/{conversation-work-C6y3T5Hx.js → conversation-work-BaT_T6EB.js} +1 -2
- package/dist/{credential-sync-BXfohNmJ.js → credential-sync-BABGymK3.js} +23 -190
- package/dist/{db-Ca9Nt5ci.d.ts → db-BnRqQ7G5.d.ts} +1 -1
- package/dist/{executor-Do0THDRR.js → executor-Bb3eQb8q.js} +30 -52
- package/dist/{experimental-CQIvMUO7.js → experimental-BNK1l1jv.js} +2 -4
- package/dist/{history-9pO1Zd4Y.js → history-AY8rs-FR.js} +5 -9
- package/dist/{history-DvqWZlYX.d.ts → history-BgI33Kie.d.ts} +12 -20
- package/dist/{images-BN_BiBXF.js → images-BbSdVHC6.js} +5 -6
- package/dist/instrumentation.d.ts +1 -3
- package/dist/instrumentation.js +6 -8
- package/dist/{job-queue-B6SV9uVa.js → job-queue-vdGU-5ge.js} +6 -12
- package/dist/{logging-CWxiIuCF.js → logging-BStXN56b.js} +7 -12
- package/dist/{message-TUOdbSBW.js → message-DRf6m4uO.js} +5 -6
- package/dist/{model-profile-BwU8mqwD.js → model-profile-Bg8EoCKD.js} +2 -4
- package/dist/nitro.d.ts +3 -5
- package/dist/nitro.js +12 -17
- package/dist/{oauth-authorization-BA4Dt6a7.js → oauth-authorization-djQn5Nhy.js} +2 -4
- package/dist/{oauth-callback-server-Dj5UJODo.js → oauth-callback-server-JmOgLcGl.js} +3 -4
- package/dist/{oauth-relay-CdCnu80W.js → oauth-relay-CTygMkNx.js} +2 -3
- package/dist/{package-discovery-BVvSnQBB.js → package-discovery-DJBompdd.js} +17 -21
- package/dist/{pending-auth-s_QFribU.js → pending-auth-rG5U_QS1.js} +92 -83
- package/dist/{plugin-module-CVvEUSMH.js → plugin-module-Cf5gVPWP.js} +1 -2
- package/dist/{plugins-CjfUP5gJ.d.ts → plugins-B_0Cr0MO.d.ts} +5 -5
- package/dist/{plugins-egKWjgue.js → plugins-DOm9Y6qI.js} +2 -3
- package/dist/{private-trace-result-BLvBjy_e.js → private-trace-result-CE7_lEdq.js} +1 -2
- package/dist/{profile-h-72wM78.js → profile-qBM6B_-V.js} +14 -295
- package/dist/{prompt-DyoEj9c2.js → prompt-xgpyMtg7.js} +5 -9
- package/dist/{queue-B5SnqRln.d.ts → queue-C37RbDVc.d.ts} +0 -2
- package/dist/{registry-sLTr-sV9.js → registry-B_M_x_iS.js} +56 -30
- package/dist/{resolve-ncQPZROQ.js → resolve-BzpuLh8c.js} +8 -12
- package/dist/{result-C883vngT.js → result-DEZH_AnZ.js} +13 -17
- package/dist/{rolldown-runtime-B4FMCO8f.js → rolldown-runtime-nwUcYXjP.js} +1 -2
- package/dist/{runner-CzYImdOF.js → runner-BqQlG10t.js} +12 -13
- package/dist/{sandbox-egress-signals-CZbMINHI.js → sandbox-egress-signals-DCq3WLs5.js} +2 -3
- package/dist/{schema-Dy69D4Ge.js → schema-CF9HqNRY.js} +30 -27
- package/dist/{sentry-CgWZM_kV.js → sentry-BBUlHih9.js} +2 -3
- package/dist/service-account-BqTBkyD7.js +120 -0
- package/dist/service-account-BzhW7kXu.js +661 -0
- package/dist/{session-stop-CQjKd4a2.js → session-stop-CV65ZlU3.js} +23 -33
- package/dist/{skills-C22SLruK.js → skills-CiWS5_Ub.js} +9 -9
- package/dist/{spawn-DY9CLXDL.js → spawn-BSAQ7UQZ.js} +4 -5
- package/dist/{store-DXFIQy-G.js → store-B1GES4gC.js} +13 -15
- package/dist/{store-DoewL5mG.d.ts → store-CG0VJyye.d.ts} +0 -14
- package/dist/{task-queue-B17vV0La.js → task-queue-BAeGEMjJ.js} +5 -7
- package/dist/{task-runner-DUjvzYXj.js → task-runner-BlGhcQPi.js} +22 -26
- package/dist/{tasks-D_WIJtvO.js → tasks-DieKX3d4.js} +63 -78
- package/dist/{thread-state-Ch4yuCqG.js → thread-state-DpSWS4Rr.js} +13 -19
- package/dist/{turn-failure-response-C5nBKC4S.js → turn-failure-response-DQljogGJ.js} +16 -22
- package/dist/{turn-lifecycle-CO-ylUmV.js → turn-lifecycle-BLgrkV_L.js} +2 -3
- package/dist/{turn-session-routing-B3LWooK5.js → turn-session-routing-BlajheOU.js} +2 -3
- package/dist/{validation-CXYxaNYx.js → validation-23d7K9tX.js} +3 -4
- package/dist/vercel.d.ts +1 -3
- package/dist/vercel.js +1 -2
- package/dist/{version-BcdZy2zg.js → version-B_XumRx-.js} +3 -5
- package/dist/{version-CnXZ614E.d.ts → version-Cc2OFd9G.d.ts} +0 -2
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -2
- package/dist/{viewer-DSZXygMU.js → viewer-B2_ABsYi.js} +26 -57
- package/dist/{web-input-B9Bv0_lR.js → web-input-BZDyxpzR.js} +101 -158
- package/dist/{web-message-id-xPI_EFSC.js → web-message-id-CJSUiksE.js} +3 -6
- package/dist/{work-nAfDSUFP.js → work-D3QKiV0O.js} +14 -16
- package/dist/{worker-vGXZ6XFT.js → worker-C8mUjYf9.js} +7 -8
- package/package.json +10 -9
package/dist/api.js
CHANGED
|
@@ -1,27 +1,30 @@
|
|
|
1
|
-
import { K as listChildAgents, L as editEventAutomation, O as parseSlackThreadId, P as editScheduledAutomation, R as AutomationEditError,
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { c as
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import { t as
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import { d as
|
|
22
|
-
import { a as
|
|
23
|
-
import {
|
|
24
|
-
import {
|
|
1
|
+
import { It as createUserTokenStore, K as listChildAgents, L as editEventAutomation, O as parseSlackThreadId, P as editScheduledAutomation, R as AutomationEditError, T as readLiveAttachment, V as resolveTaskOutcomes, bt as conversationSubtreeColumns, g as readStats, ot as getChildAgentLabel, yt as conversationSubtree, z as eventAutomationTriggerAvailable } from "./agent-runner-CPSd7rKm.js";
|
|
2
|
+
import { p as escapeXml } from "./client-BZdxgKyL.js";
|
|
3
|
+
import { f as logException, m as logWarn, p as logInfo } from "./logging-BStXN56b.js";
|
|
4
|
+
import { d as parseSlackTeamId, g as parseSlackMessageTs, l as parseSlackChannelId } from "./actor-tlxzqaRe.js";
|
|
5
|
+
import { C as addAgentTurnUsage, D as hasAgentTurnUsage, E as agentTurnUsageSchema, O as resolveRootConversationId, S as parseSessionSource, c as getConversationEventStore, d as getDb, f as getSqlExecutor, h as loadConversationSlackTenantId, i as resolveViewerUser, m as withConversationEventLock, o as updateViewerDisplayName, t as findUserByEmail, u as getConversationStore, v as locationFromRow } from "./viewer-B2_ABsYi.js";
|
|
6
|
+
import { c as juniorIdentities, d as juniorDestinations, l as juniorUsers, o as conversationReadColumns, s as juniorConversations } from "./agent-invocations-Qfz7dWgU.js";
|
|
7
|
+
import { f as juniorConversationBriefs, g as juniorApiTokens, h as juniorConversationEvents, m as juniorConversationMetrics, u as juniorConversationParticipants, v as juniorCodeChanges, y as juniorCodeRepositories } from "./executor-Bb3eQb8q.js";
|
|
8
|
+
import { d as contextProvenance } from "./history-AY8rs-FR.js";
|
|
9
|
+
import { n as pluginCatalogRuntime } from "./catalog-runtime-B8SuFPGb.js";
|
|
10
|
+
import { At as loadTurnProjection, D as AutomationConflictError, E as sameDefinitionValue, O as automationRevision, S as automationDefinition, T as readAutomationVersion, a as saveScheduledAutomation, k as requireAutomationRevision, pn as piMessageFromHistoryItem, v as saveEventAutomation, y as setEventAutomationStatus } from "./tasks-DieKX3d4.js";
|
|
11
|
+
import { C as WorkspaceValidationError, Ct as readLatestConversationBrief, Ht as getSlackClient, Lt as lookupSlackUser, M as workspaceRepoCheckoutPath, Nt as listConversationAnnotations, O as SANDBOX_RUNTIME, Pt as listConversationAnnotationsById, S as updateWorkspace, Tt as buildSentryConversationUrl, _ as deleteWorkspace, _t as conversationHasParticipantEmail, b as listWorkspaces, bt as conversationNotArchivedForUser, ft as createPluginLogger, g as createWorkspace, gt as conversationArchivedForUser, ht as conversationArchivedForEmail, mt as conversationArchiveTimes, pt as readConversationAccessFromSql, qt as withSlackRetries, u as getPlugins, v as getWorkspace, vt as conversationHasParticipantUser, wt as readConversationEventPage, x as listWorkspacesByRepository, xt as viewerConversationMembership, yt as conversationNotArchivedForEmail } from "./agent-hooks-B00FaKdP.js";
|
|
12
|
+
import { A as forkConversationBodySchema, F as readMessageAttachments, I as INPUT_IMAGE_TYPES, O as createConversationBodySchema, T as conversationStatsReportSchema, _ as conversationParamsSchema, a as cancelConversationPendingMessagesBodySchema, c as conversationAttachmentParamsSchema, d as conversationDetailReportSchema, g as conversationFeedSchema, h as conversationFeedQuerySchema, i as archiveConversationResponseSchema, j as forkConversationResponseSchema, k as createConversationMessageBodySchema, m as conversationEventsQuerySchema, o as cancelConversationPendingMessagesResponseSchema, p as conversationEventPageSchema, r as archiveConversationBodySchema, t as acceptedConversationMessageSchema, u as conversationDetailQuerySchema, x as conversationPendingMessagesReportSchema } from "./conversation-DjN3mlog.js";
|
|
13
|
+
import { n as hash, t as create } from "./profile-qBM6B_-V.js";
|
|
14
|
+
import { l as getEventCatalog, y as automationEventCatalog } from "./session-stop-CV65ZlU3.js";
|
|
15
|
+
import { t as getFirstRunAtMs } from "./cadence-R7Em4RjE.js";
|
|
16
|
+
import { t as getCachedSnapshot } from "./resolve-BzpuLh8c.js";
|
|
17
|
+
import { a as getVercelConversationWorkQueue } from "./job-queue-vdGU-5ge.js";
|
|
18
|
+
import { a as cancelHumanFacingPendingMessages, h as getConversation } from "./store-B1GES4gC.js";
|
|
19
|
+
import { n as finishServiceAccountSignIn, o as serviceAccountPlugins, r as getServiceAccountStatus, s as startServiceAccountSignIn, t as disconnectServiceAccount } from "./service-account-BzhW7kXu.js";
|
|
20
|
+
import { M as compileScheduleIntent, P as weekdaySchema, _ as automationSummarySchema, b as automationVersionListSchema, c as automationLifecycleSchema, d as automationParamsSchema, f as automationRunListSchema, g as automationSchedulePreviewSchema, h as automationScheduleIntentSchema, i as automationExecutionListSchema, j as ScheduleIntentError, l as automationListQuerySchema, n as automationEditSchema, r as automationEventCatalogSchema, t as automationEditErrorSchema, u as automationListSchema, v as automationUpdateSchema, x as automationVersionParamsSchema, y as automationVersionActivateSchema } from "./automation-DWBFBenG.js";
|
|
21
|
+
import { C as skillReportsSchema, a as fillUtcHours, b as pluginsSchema, c as sumUtcHoursIntoSixHours, d as trailingUtcSixHourWindow, f as utcDayKey, h as pluginOperationalReportFeedSchema, i as fillUtcDays, l as trailingUtcDayWindow, m as healthReportSchema, n as DAY_MS$1, o as fillUtcSixHours, p as utcHourKey, r as HOUR_MS$1, s as startOfUtcHour, u as trailingUtcHourWindow, x as runtimeInfoReportSchema } from "./web-message-id-CJSUiksE.js";
|
|
22
|
+
import { B as readHealthReport, I as createVercelAttachmentStorage, _ as readViewerAutomationRuns, a as recordWebConversationActivity, b as readViewerAutomations, d as resolveSlackConversationContextFromThreadId, g as readViewerAutomationExecutions, h as readConversationSourceTask, i as createConversationId, k as stopConversationTurn, l as getProductionSlackAdapter, m as deleteViewerTask, o as webActorFromEmail, p as ViewerTaskNotFoundError, r as createAndEnqueueConversation, t as appendAndEnqueueWebMessage, u as formatSlackConversationRedactedLabel, v as readViewerAutomationSummary, w as clearSlackPendingReactions, x as resolveViewerTaskCandidate, y as readViewerAutomationVersions } from "./web-input-BZDyxpzR.js";
|
|
23
|
+
import { F as conversationAggregateColumns, I as conversationRangeColumns, M as readAutomationTitlesByConversationId, P as conversationActiveDaysColumn } from "./task-runner-BlGhcQPi.js";
|
|
24
|
+
import { d as legacyWebMailboxMetadataSchema } from "./result-DEZH_AnZ.js";
|
|
25
|
+
import { a as startConnection, l as getWebAuthorization, n as isConnectableProvider, r as listConnections, t as disconnectConnection, u as htmlCallbackResponse } from "./connections-9gJkfS85.js";
|
|
26
|
+
import { t as decodeInputImages } from "./images-BbSdVHC6.js";
|
|
27
|
+
import { A as activityHours$1, C as personParamsSchema, D as locationDirectoryReportSchema, E as locationDetailReportSchema, H as codePersonReportSchema, I as disconnectConnectionResponseSchema, J as stopConversationTurnResponseSchema, L as startConnectionResponseSchema, N as connectionListSchema, O as locationParamsSchema, P as connectionParamsSchema, S as actorProfileReportSchema, U as codeRepositoryParamsSchema, V as codeOverviewReportSchema, W as codeRepositoryReportSchema, Y as apiErrorSchema, _ as personalTokenListSchema, a as workspaceBodySchema, b as revokePersonalTokenResponseSchema, d as serviceAccountListSchema, f as serviceAccountParamsSchema, g as createdPersonalTokenSchema, h as createPersonalTokenBodySchema, i as deleteWorkspaceResponseSchema, j as activitySixHours$1, k as activityDays$1, l as workspaceSchema, m as startServiceAccountSignInResponseSchema, n as statsReportSchema, o as workspaceListSchema, q as conversationChildAgentsReportSchema, s as workspaceParamsSchema, u as disconnectServiceAccountResponseSchema, w as personalSpendReportSchema, x as actorDirectoryReportSchema, y as personalTokenParamsSchema } from "./schema-CF9HqNRY.js";
|
|
25
28
|
import { Hono } from "hono";
|
|
26
29
|
import path from "node:path";
|
|
27
30
|
import { z } from "zod";
|
|
@@ -34,7 +37,7 @@ import { HTTPException } from "hono/http-exception";
|
|
|
34
37
|
import { bodyLimit } from "hono/body-limit";
|
|
35
38
|
import { zValidator } from "@hono/zod-validator";
|
|
36
39
|
import { createMiddleware } from "hono/factory";
|
|
37
|
-
|
|
40
|
+
// src/api/http.ts
|
|
38
41
|
const NO_STORE_HEADERS = { "cache-control": "no-store" };
|
|
39
42
|
/** Build response init that keeps personalized API payloads out of shared caches. */
|
|
40
43
|
function noStoreInit(init) {
|
|
@@ -62,23 +65,27 @@ function throwApiError(status, message, cause) {
|
|
|
62
65
|
res: jsonResponse(apiErrorSchema, { error: message }, { status })
|
|
63
66
|
});
|
|
64
67
|
}
|
|
65
|
-
|
|
66
|
-
//#region src/api/validation.ts
|
|
68
|
+
// src/api/validation.ts
|
|
67
69
|
/** Validate one request input and use Junior's stable JSON error contract. */
|
|
68
70
|
function validateRequest(target, schema, message) {
|
|
69
71
|
return zValidator(target, schema, (result) => {
|
|
70
72
|
if (!result.success) throwApiError(400, message, result.error);
|
|
71
73
|
});
|
|
72
74
|
}
|
|
73
|
-
|
|
74
|
-
//#region src/api/viewer.ts
|
|
75
|
+
// src/api/viewer.ts
|
|
75
76
|
/** Require a viewer and refine later Hono handlers to authenticated context. */
|
|
76
77
|
const requireViewer = createMiddleware(async (context, next) => {
|
|
77
78
|
if (!context.get("viewer")) throwApiError(401, "Authentication required.");
|
|
78
79
|
await next();
|
|
79
80
|
});
|
|
80
|
-
|
|
81
|
-
|
|
81
|
+
/** Require a Junior admin viewer. */
|
|
82
|
+
const requireAdmin = createMiddleware(async (context, next) => {
|
|
83
|
+
const viewer = context.get("viewer");
|
|
84
|
+
if (!viewer) throwApiError(401, "Authentication required.");
|
|
85
|
+
if (viewer.isAdmin !== true) throwApiError(403, "Only Junior admins can do this.");
|
|
86
|
+
await next();
|
|
87
|
+
});
|
|
88
|
+
// src/api/conversations/archive.ts
|
|
82
89
|
async function setViewerArchive(args) {
|
|
83
90
|
const executor = getSqlExecutor();
|
|
84
91
|
return await executor.transaction(async () => {
|
|
@@ -133,8 +140,7 @@ async function archiveConversation(viewer, conversationId, body) {
|
|
|
133
140
|
if (result.status === "missing") throwApiError(404, "Conversation not found.");
|
|
134
141
|
throwApiError(409, "Conversation received new activity.");
|
|
135
142
|
}
|
|
136
|
-
|
|
137
|
-
//#region src/chat/conversations/fork.ts
|
|
143
|
+
// src/chat/conversations/fork.ts
|
|
138
144
|
/** Event key of the agent note that follows the copied events in a fork. */
|
|
139
145
|
const FORK_NOTE_KEY = "fork:note";
|
|
140
146
|
const forkNote = alias(juniorConversationEvents, "fork_note");
|
|
@@ -283,8 +289,7 @@ function hasUnfinishedToolCalls(messages) {
|
|
|
283
289
|
} else if (message.role === "toolResult") pending.delete(message.toolCallId);
|
|
284
290
|
return pending.size > 0;
|
|
285
291
|
}
|
|
286
|
-
|
|
287
|
-
//#region src/api/conversations/auxiliary-costs.ts
|
|
292
|
+
// src/api/conversations/auxiliary-costs.ts
|
|
288
293
|
function eventCost() {
|
|
289
294
|
return sql`CASE
|
|
290
295
|
WHEN ${juniorConversationEvents.type} = 'structured_event'
|
|
@@ -344,8 +349,7 @@ async function readConversationAuxiliaryCostsFromSql(db, conversationIds) {
|
|
|
344
349
|
}
|
|
345
350
|
return result;
|
|
346
351
|
}
|
|
347
|
-
|
|
348
|
-
//#region src/api/conversations/usage.ts
|
|
352
|
+
// src/api/conversations/usage.ts
|
|
349
353
|
const usage$1 = juniorConversations.usage;
|
|
350
354
|
const componentFields = [
|
|
351
355
|
"inputTokens",
|
|
@@ -455,8 +459,7 @@ function childAgentTotalsReport(metrics, auxiliaryCosts) {
|
|
|
455
459
|
...childAgents.usage ? { cumulativeUsage: childAgents.usage } : void 0
|
|
456
460
|
};
|
|
457
461
|
}
|
|
458
|
-
|
|
459
|
-
//#region src/api/conversations/child-agents.ts
|
|
462
|
+
// src/api/conversations/child-agents.ts
|
|
460
463
|
/**
|
|
461
464
|
* Load the direct child agents of one Conversation, or throw a standard API
|
|
462
465
|
* not-found error. Viewers who cannot see private content get only the status,
|
|
@@ -494,8 +497,7 @@ async function requireConversationChildAgents(conversationId, options = {}) {
|
|
|
494
497
|
conversationId
|
|
495
498
|
});
|
|
496
499
|
}
|
|
497
|
-
|
|
498
|
-
//#region src/api/conversations/attachments.ts
|
|
500
|
+
// src/api/conversations/attachments.ts
|
|
499
501
|
function contentDisposition(filename, contentType) {
|
|
500
502
|
return `${INPUT_IMAGE_TYPES.some((type) => type === contentType) ? "inline" : "attachment"}; filename="${filename.replace(/[^\x20-\x7e]|["\\]/g, "_")}"; filename*=UTF-8''${encodeURIComponent(filename)}`;
|
|
501
503
|
}
|
|
@@ -536,8 +538,7 @@ async function requireConversationAttachment(args) {
|
|
|
536
538
|
if (!opened) throwApiError(404, "Attachment not found.");
|
|
537
539
|
return opened;
|
|
538
540
|
}
|
|
539
|
-
|
|
540
|
-
//#region src/api/conversations/create.ts
|
|
541
|
+
// src/api/conversations/create.ts
|
|
541
542
|
/** Turn image validation failures into request errors before accepting work. */
|
|
542
543
|
function parseImages(images) {
|
|
543
544
|
try {
|
|
@@ -596,8 +597,7 @@ async function appendConversationMessageForViewer(viewer, conversationId, body,
|
|
|
596
597
|
throwApiError(500, "Unable to append message.", error);
|
|
597
598
|
}
|
|
598
599
|
}
|
|
599
|
-
|
|
600
|
-
//#region src/chat/plugins/conversation-sidebar.ts
|
|
600
|
+
// src/chat/plugins/conversation-sidebar.ts
|
|
601
601
|
/** Show native objects by default and let plugins select compact sidebar labels. */
|
|
602
602
|
async function listConversationSidebarAnnotations(conversationIds, annotationsByConversation) {
|
|
603
603
|
const candidates = new Set(conversationIds);
|
|
@@ -646,8 +646,7 @@ async function listConversationSidebarAnnotations(conversationIds, annotationsBy
|
|
|
646
646
|
}
|
|
647
647
|
return selected;
|
|
648
648
|
}
|
|
649
|
-
|
|
650
|
-
//#region src/chat/slack/location-url.ts
|
|
649
|
+
// src/chat/slack/location-url.ts
|
|
651
650
|
/** Parse a Slack workspace subdomain used in `https://{domain}.slack.com` URLs. */
|
|
652
651
|
function parseSlackTeamDomain(value) {
|
|
653
652
|
if (typeof value !== "string") return void 0;
|
|
@@ -674,8 +673,7 @@ function buildSlackLocationUrl(args) {
|
|
|
674
673
|
url.searchParams.set("cid", channelId);
|
|
675
674
|
return url.toString();
|
|
676
675
|
}
|
|
677
|
-
|
|
678
|
-
//#region src/chat/slack/team-domain.ts
|
|
676
|
+
// src/chat/slack/team-domain.ts
|
|
679
677
|
const TEAM_DOMAIN_CACHE_TTL_MS = 864e5;
|
|
680
678
|
const TEAM_DOMAIN_NEGATIVE_CACHE_TTL_MS = 6e4;
|
|
681
679
|
const teamDomainCache = /* @__PURE__ */ new Map();
|
|
@@ -746,8 +744,7 @@ async function resolveSlackTeamDomains(teamIds) {
|
|
|
746
744
|
}));
|
|
747
745
|
return new Map(resolved.filter((entry) => entry !== void 0));
|
|
748
746
|
}
|
|
749
|
-
|
|
750
|
-
//#region src/chat/pi/sql-model-usage.ts
|
|
747
|
+
// src/chat/pi/sql-model-usage.ts
|
|
751
748
|
/** SQL reporting adapter for usage stored on assistant history events. */
|
|
752
749
|
const message = sql`${juniorConversationEvents.payload}`;
|
|
753
750
|
const usage = sql`${message}->'usage'`;
|
|
@@ -851,8 +848,7 @@ async function readConversationModelUsageFromSql(executor, options) {
|
|
|
851
848
|
}] : [];
|
|
852
849
|
});
|
|
853
850
|
}
|
|
854
|
-
|
|
855
|
-
//#region src/api/conversations/cursor.ts
|
|
851
|
+
// src/api/conversations/cursor.ts
|
|
856
852
|
const CURSOR_CONTEXT = "junior-conversation-report-cursor";
|
|
857
853
|
const conversationCursorPayloadSchema = z.object({
|
|
858
854
|
conversationId: z.string().min(1),
|
|
@@ -891,8 +887,7 @@ function decodeConversationCursor(args) {
|
|
|
891
887
|
return;
|
|
892
888
|
}
|
|
893
889
|
}
|
|
894
|
-
|
|
895
|
-
//#region src/api/conversations/message-mentions.ts
|
|
890
|
+
// src/api/conversations/message-mentions.ts
|
|
896
891
|
const SLACK_USER_MENTION_RE = /<@([UW][A-Z0-9]+)(?:\|[^<>]*)?>/g;
|
|
897
892
|
function mentionedSlackUserIds(text) {
|
|
898
893
|
if (!text) return [];
|
|
@@ -968,8 +963,7 @@ async function attachMessageMentions(executor, conversationId, events) {
|
|
|
968
963
|
} : event;
|
|
969
964
|
});
|
|
970
965
|
}
|
|
971
|
-
|
|
972
|
-
//#region src/api/conversations/shared.ts
|
|
966
|
+
// src/api/conversations/shared.ts
|
|
973
967
|
/** Format a Slack destination without exposing private channel names. */
|
|
974
968
|
function slackStatsLocationLabel(input) {
|
|
975
969
|
const channelId = input.channel;
|
|
@@ -991,8 +985,7 @@ function surfaceFallbackLabel(surface) {
|
|
|
991
985
|
if (surface === "internal") return "Internal";
|
|
992
986
|
return "Conversation";
|
|
993
987
|
}
|
|
994
|
-
|
|
995
|
-
//#region src/api/conversations/projection.ts
|
|
988
|
+
// src/api/conversations/projection.ts
|
|
996
989
|
const PRIVATE_CONVERSATION_LABEL = "Private Conversation";
|
|
997
990
|
function privateConversationLabel(slackConversation) {
|
|
998
991
|
if (!slackConversation) return PRIVATE_CONVERSATION_LABEL;
|
|
@@ -1122,8 +1115,7 @@ function conversationSummaryFromStoredConversation(args) {
|
|
|
1122
1115
|
...args.locationId && !channelNameRedacted ? { locationId: args.locationId } : void 0
|
|
1123
1116
|
};
|
|
1124
1117
|
}
|
|
1125
|
-
|
|
1126
|
-
//#region src/chat/plugins/unfinished-work.ts
|
|
1118
|
+
// src/chat/plugins/unfinished-work.ts
|
|
1127
1119
|
/**
|
|
1128
1120
|
* Return assigned and unfinished plugin work for the candidate conversations.
|
|
1129
1121
|
* Feed Priority combines these signals with conversation activity on the host.
|
|
@@ -1177,8 +1169,7 @@ async function listConversationWork(conversationIds) {
|
|
|
1177
1169
|
unfinishedIds: conversationIds.filter((conversationId) => unfinished.has(conversationId))
|
|
1178
1170
|
};
|
|
1179
1171
|
}
|
|
1180
|
-
|
|
1181
|
-
//#region src/api/conversations/priority.ts
|
|
1172
|
+
// src/api/conversations/priority.ts
|
|
1182
1173
|
/** Conversations with no known work leave Priority after this idle window. */
|
|
1183
1174
|
const UNASSIGNED_PRIORITY_WINDOW_MS = 108e5;
|
|
1184
1175
|
/** Unfinished work leaves Priority after this idle window. */
|
|
@@ -1204,8 +1195,7 @@ function isConversationPriority(conversation, nowMs) {
|
|
|
1204
1195
|
}
|
|
1205
1196
|
return nowMs - lastSeenAt <= UNASSIGNED_PRIORITY_WINDOW_MS;
|
|
1206
1197
|
}
|
|
1207
|
-
|
|
1208
|
-
//#region src/api/conversations/user-message-activity.ts
|
|
1198
|
+
// src/api/conversations/user-message-activity.ts
|
|
1209
1199
|
/** Read the latest true user message time for each selected conversation. */
|
|
1210
1200
|
async function readLastUserMessageAtByConversation(db, conversationIds) {
|
|
1211
1201
|
if (conversationIds.length === 0) return /* @__PURE__ */ new Map();
|
|
@@ -1218,8 +1208,7 @@ async function readLastUserMessageAtByConversation(db, conversationIds) {
|
|
|
1218
1208
|
}).from(juniorConversationEvents).where(and(inArray(juniorConversationEvents.conversationId, conversationIds), or(and(eq(juniorConversationEvents.type, "user_message"), eq(authority, "instruction"), sql`${actorPlatform} in ('slack', 'local', 'web')`), and(eq(juniorConversationEvents.type, "message"), eq(role, "user"), isNotNull(juniorConversationEvents.actorIdentityId))))).groupBy(juniorConversationEvents.conversationId);
|
|
1219
1209
|
return new Map(rows.map((row) => [row.conversationId, new Date(row.lastUserMessageAt).toISOString()]));
|
|
1220
1210
|
}
|
|
1221
|
-
|
|
1222
|
-
//#region src/api/conversations/activity-preview.ts
|
|
1211
|
+
// src/api/conversations/activity-preview.ts
|
|
1223
1212
|
/** Read one recent assistant message, or the latest user message, for each conversation. */
|
|
1224
1213
|
async function readConversationActivityPreviews(db, conversationIds) {
|
|
1225
1214
|
if (conversationIds.length === 0) return /* @__PURE__ */ new Map();
|
|
@@ -1238,8 +1227,7 @@ async function readConversationActivityPreviews(db, conversationIds) {
|
|
|
1238
1227
|
text: row.text
|
|
1239
1228
|
}]));
|
|
1240
1229
|
}
|
|
1241
|
-
|
|
1242
|
-
//#region src/api/conversations/participants.ts
|
|
1230
|
+
// src/api/conversations/participants.ts
|
|
1243
1231
|
const identityColumns = {
|
|
1244
1232
|
displayName: juniorIdentities.displayName,
|
|
1245
1233
|
email: juniorIdentities.email,
|
|
@@ -1293,8 +1281,7 @@ async function readConversationParticipants(db, conversationIds) {
|
|
|
1293
1281
|
for (const row of eventRows.sort((left, right) => left.seq - right.seq)) add(row.conversationId, row);
|
|
1294
1282
|
return new Map([...ordered].map(([conversationId, group]) => [conversationId, group.identities]));
|
|
1295
1283
|
}
|
|
1296
|
-
|
|
1297
|
-
//#region src/api/conversations/list.ts
|
|
1284
|
+
// src/api/conversations/list.ts
|
|
1298
1285
|
const CONVERSATION_FEED_LIMIT = 50;
|
|
1299
1286
|
function conversationFeedMembershipFilter(status, filter) {
|
|
1300
1287
|
if (!filter) return status === "archived" ? sql`false` : void 0;
|
|
@@ -1506,8 +1493,7 @@ async function readConversationFeedFromSql(options = {}) {
|
|
|
1506
1493
|
async function readConversationFeed(options = {}) {
|
|
1507
1494
|
return conversationFeedSchema.parse(await readConversationFeedFromSql(options));
|
|
1508
1495
|
}
|
|
1509
|
-
|
|
1510
|
-
//#region src/api/conversations/fork.ts
|
|
1496
|
+
// src/api/conversations/fork.ts
|
|
1511
1497
|
/** Fork a Conversation that the viewer can read into a new root they own. */
|
|
1512
1498
|
async function forkConversationForViewer(viewer, sourceConversationId, body) {
|
|
1513
1499
|
if (!(await readConversationAccessFromSql(getDb(), [sourceConversationId], viewer)).get(sourceConversationId)?.canViewPrivateContent) throwApiError(403, "You do not have access to this conversation.");
|
|
@@ -1559,8 +1545,7 @@ async function readConversationForks(conversationId, viewer) {
|
|
|
1559
1545
|
}
|
|
1560
1546
|
return result;
|
|
1561
1547
|
}
|
|
1562
|
-
|
|
1563
|
-
//#region src/api/conversations/agent-tree.ts
|
|
1548
|
+
// src/api/conversations/agent-tree.ts
|
|
1564
1549
|
/** Bound the parent chain that one agent tree reads. */
|
|
1565
1550
|
const MAX_AGENT_TREE_DEPTH = 16;
|
|
1566
1551
|
const CHILD_LABEL = "Subagent";
|
|
@@ -1606,8 +1591,7 @@ async function readConversationAgentTree(conversationId, viewer) {
|
|
|
1606
1591
|
};
|
|
1607
1592
|
}));
|
|
1608
1593
|
}
|
|
1609
|
-
|
|
1610
|
-
//#region src/api/conversations/detail.ts
|
|
1594
|
+
// src/api/conversations/detail.ts
|
|
1611
1595
|
/** Project stored metadata and a bounded event page into a signed history cursor. */
|
|
1612
1596
|
function projectConversationDetail(args) {
|
|
1613
1597
|
const { conversation } = args;
|
|
@@ -1717,8 +1701,7 @@ async function readConversationDetail(conversationId, options = {}) {
|
|
|
1717
1701
|
...agentTree ? { agentTree } : void 0
|
|
1718
1702
|
});
|
|
1719
1703
|
}
|
|
1720
|
-
|
|
1721
|
-
//#region src/api/conversations/event-list.ts
|
|
1704
|
+
// src/api/conversations/event-list.ts
|
|
1722
1705
|
/** Read one bounded page of reporting events before a signed cursor. */
|
|
1723
1706
|
async function readConversationEvents(conversationId, beforeValue, options = {}) {
|
|
1724
1707
|
const record = await readConversationRecordFromSql(conversationId);
|
|
@@ -1749,8 +1732,7 @@ async function readConversationEvents(conversationId, beforeValue, options = {})
|
|
|
1749
1732
|
generatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1750
1733
|
});
|
|
1751
1734
|
}
|
|
1752
|
-
|
|
1753
|
-
//#region src/api/conversations/cancel-pending-messages.ts
|
|
1735
|
+
// src/api/conversations/cancel-pending-messages.ts
|
|
1754
1736
|
/** Cancel accepted human-facing mailbox rows for one conversation participant. */
|
|
1755
1737
|
async function cancelConversationPendingMessagesForViewer(viewer, conversationId, body = {}) {
|
|
1756
1738
|
if (!await getConversationStore().get({ conversationId })) throwApiError(404, "Conversation not found.");
|
|
@@ -1775,8 +1757,7 @@ async function cancelConversationPendingMessagesForViewer(viewer, conversationId
|
|
|
1775
1757
|
throwApiError(500, "Unable to cancel queued messages.", error);
|
|
1776
1758
|
}
|
|
1777
1759
|
}
|
|
1778
|
-
|
|
1779
|
-
//#region src/api/conversations/pending-messages.ts
|
|
1760
|
+
// src/api/conversations/pending-messages.ts
|
|
1780
1761
|
const slackMailboxAuthorSchema = z.object({
|
|
1781
1762
|
userId: z.string(),
|
|
1782
1763
|
userName: z.string().optional(),
|
|
@@ -1902,8 +1883,7 @@ async function requireConversationPendingMessages(conversationId, options = {})
|
|
|
1902
1883
|
if (!report) throwApiError(404, "Conversation not found.");
|
|
1903
1884
|
return report;
|
|
1904
1885
|
}
|
|
1905
|
-
|
|
1906
|
-
//#region src/api/conversations/metric-buckets.ts
|
|
1886
|
+
// src/api/conversations/metric-buckets.ts
|
|
1907
1887
|
/** Sum all Conversation metrics into UTC day or hour buckets. */
|
|
1908
1888
|
async function readConversationMetricBuckets(db, options) {
|
|
1909
1889
|
const date = options.bucket === "day" ? sql`to_char(${juniorConversationMetrics.occurredAt} at time zone 'UTC', 'YYYY-MM-DD')` : sql`to_char(${juniorConversationMetrics.occurredAt} at time zone 'UTC', 'YYYY-MM-DD"T"HH24')`;
|
|
@@ -1913,8 +1893,7 @@ async function readConversationMetricBuckets(db, options) {
|
|
|
1913
1893
|
value: sql`sum(${juniorConversationMetrics.value})::double precision`
|
|
1914
1894
|
}).from(juniorConversationMetrics).where(and(gte(juniorConversationMetrics.occurredAt, options.start), lte(juniorConversationMetrics.occurredAt, options.end))).groupBy(date, juniorConversationMetrics.metric).orderBy(asc(date), asc(juniorConversationMetrics.metric));
|
|
1915
1895
|
}
|
|
1916
|
-
|
|
1917
|
-
//#region src/api/conversations/stats.query.ts
|
|
1896
|
+
// src/api/conversations/stats.query.ts
|
|
1918
1897
|
const treeConversation$1 = alias(juniorConversations, "stats_tree_conversation");
|
|
1919
1898
|
const treeAggregateColumns$1 = conversationAggregateColumns({
|
|
1920
1899
|
metrics: treeConversation$1,
|
|
@@ -2253,14 +2232,12 @@ async function readConversationStatsFromSql() {
|
|
|
2253
2232
|
windowStart: start.toISOString()
|
|
2254
2233
|
};
|
|
2255
2234
|
}
|
|
2256
|
-
|
|
2257
|
-
//#region src/api/conversations/stats.ts
|
|
2235
|
+
// src/api/conversations/stats.ts
|
|
2258
2236
|
/** Load aggregate conversation stats directly from durable SQL records. */
|
|
2259
2237
|
async function readConversationStats() {
|
|
2260
2238
|
return conversationStatsReportSchema.parse(await readConversationStatsFromSql());
|
|
2261
2239
|
}
|
|
2262
|
-
|
|
2263
|
-
//#region src/api/conversations/stop.ts
|
|
2240
|
+
// src/api/conversations/stop.ts
|
|
2264
2241
|
/**
|
|
2265
2242
|
* Stop the active Turn for one conversation participant.
|
|
2266
2243
|
*
|
|
@@ -2312,8 +2289,7 @@ function viewerWebMessages(messages, viewer) {
|
|
|
2312
2289
|
}] : [];
|
|
2313
2290
|
});
|
|
2314
2291
|
}
|
|
2315
|
-
|
|
2316
|
-
//#region src/api/conversations/routes.ts
|
|
2292
|
+
// src/api/conversations/routes.ts
|
|
2317
2293
|
/** Create the HTTP routes owned by the conversations API. */
|
|
2318
2294
|
function createConversationRoutes(options) {
|
|
2319
2295
|
const app = new Hono();
|
|
@@ -2413,8 +2389,7 @@ function createConversationRoutes(options) {
|
|
|
2413
2389
|
});
|
|
2414
2390
|
return app;
|
|
2415
2391
|
}
|
|
2416
|
-
|
|
2417
|
-
//#region src/api/code/overview.ts
|
|
2392
|
+
// src/api/code/overview.ts
|
|
2418
2393
|
const DAY_MS = 864e5;
|
|
2419
2394
|
const WINDOW_DAYS = 30;
|
|
2420
2395
|
/**
|
|
@@ -2833,8 +2808,7 @@ async function readPersonCodeOverview(args) {
|
|
|
2833
2808
|
windowStart: windows.windowStart.toISOString()
|
|
2834
2809
|
});
|
|
2835
2810
|
}
|
|
2836
|
-
|
|
2837
|
-
//#region src/api/code/repository.ts
|
|
2811
|
+
// src/api/code/repository.ts
|
|
2838
2812
|
/** Most recent code changes listed on one repository page. */
|
|
2839
2813
|
const REPOSITORY_CHANGE_LIMIT = 100;
|
|
2840
2814
|
/**
|
|
@@ -2877,8 +2851,7 @@ async function readCodeRepository(repositoryId, nowMs = Date.now()) {
|
|
|
2877
2851
|
workspaces
|
|
2878
2852
|
});
|
|
2879
2853
|
}
|
|
2880
|
-
|
|
2881
|
-
//#region src/api/code/routes.ts
|
|
2854
|
+
// src/api/code/routes.ts
|
|
2882
2855
|
/** Create the code analytics API. */
|
|
2883
2856
|
function createCodeRoutes() {
|
|
2884
2857
|
const app = new Hono();
|
|
@@ -2891,8 +2864,7 @@ function createCodeRoutes() {
|
|
|
2891
2864
|
});
|
|
2892
2865
|
return app;
|
|
2893
2866
|
}
|
|
2894
|
-
|
|
2895
|
-
//#region src/api/connections/routes.ts
|
|
2867
|
+
// src/api/connections/routes.ts
|
|
2896
2868
|
/**
|
|
2897
2869
|
* Create authenticated routes that list, connect, and disconnect the viewer's
|
|
2898
2870
|
* plugin accounts. Connections belong to the viewer's web actor, which is the
|
|
@@ -2923,8 +2895,7 @@ function createConnectionRoutes() {
|
|
|
2923
2895
|
});
|
|
2924
2896
|
return app;
|
|
2925
2897
|
}
|
|
2926
|
-
|
|
2927
|
-
//#region src/api/conversations/reporting.ts
|
|
2898
|
+
// src/api/conversations/reporting.ts
|
|
2928
2899
|
/** Return the dashboard label for a conversation surface. */
|
|
2929
2900
|
function surfaceLabel(surface) {
|
|
2930
2901
|
if (surface === "scheduler") return "Scheduler";
|
|
@@ -2981,8 +2952,7 @@ function summaryFromRow(row, options = {}) {
|
|
|
2981
2952
|
usage: options.metrics?.usage ?? row.usage ?? void 0
|
|
2982
2953
|
});
|
|
2983
2954
|
}
|
|
2984
|
-
|
|
2985
|
-
//#region src/api/locations/query.ts
|
|
2955
|
+
// src/api/locations/query.ts
|
|
2986
2956
|
const RECENT_LIMIT$1 = 25;
|
|
2987
2957
|
const ACTIVITY_DAYS$1 = 90;
|
|
2988
2958
|
const treeConversation = alias(juniorConversations, "location_tree_conversation");
|
|
@@ -3299,21 +3269,18 @@ async function readLocationDetailFromSql(locationId, options = {}) {
|
|
|
3299
3269
|
windowStart: activity[0] ? `${activity[0].date}T00:00:00.000Z` : end.toISOString()
|
|
3300
3270
|
};
|
|
3301
3271
|
}
|
|
3302
|
-
|
|
3303
|
-
//#region src/api/locations/detail.ts
|
|
3272
|
+
// src/api/locations/detail.ts
|
|
3304
3273
|
/** Expose operational detail for one persisted public conversation location. */
|
|
3305
3274
|
async function readLocationDetail(locationId, options = {}) {
|
|
3306
3275
|
const report = await readLocationDetailFromSql(locationId, options);
|
|
3307
3276
|
return report ? locationDetailReportSchema.parse(report) : void 0;
|
|
3308
3277
|
}
|
|
3309
|
-
|
|
3310
|
-
//#region src/api/locations/list.ts
|
|
3278
|
+
// src/api/locations/list.ts
|
|
3311
3279
|
/** Expose public conversation destinations as the dashboard's location index. */
|
|
3312
3280
|
async function readLocationDirectory() {
|
|
3313
3281
|
return locationDirectoryReportSchema.parse(await readLocationDirectoryFromSql());
|
|
3314
3282
|
}
|
|
3315
|
-
|
|
3316
|
-
//#region src/api/locations/routes.ts
|
|
3283
|
+
// src/api/locations/routes.ts
|
|
3317
3284
|
/** Create the HTTP routes owned by the locations API. */
|
|
3318
3285
|
function createLocationRoutes() {
|
|
3319
3286
|
const app = new Hono();
|
|
@@ -3327,8 +3294,7 @@ function createLocationRoutes() {
|
|
|
3327
3294
|
});
|
|
3328
3295
|
return app;
|
|
3329
3296
|
}
|
|
3330
|
-
|
|
3331
|
-
//#region src/api/people/code.ts
|
|
3297
|
+
// src/api/people/code.ts
|
|
3332
3298
|
/** Read person-scoped native code activity for one People profile. */
|
|
3333
3299
|
async function readPeopleCode(email) {
|
|
3334
3300
|
const subject = await findUserByEmail(email);
|
|
@@ -3454,8 +3420,7 @@ async function recentActorRows(email) {
|
|
|
3454
3420
|
usage: juniorConversations.usage
|
|
3455
3421
|
}).from(juniorConversations).innerJoin(juniorIdentities, eq(juniorIdentities.id, juniorConversations.actorIdentityId)).innerJoin(juniorUsers, eq(juniorUsers.id, juniorIdentities.userId)).leftJoin(juniorDestinations, eq(juniorDestinations.id, juniorConversations.destinationId)).where(verifiedActorWhere(email)).orderBy(desc(juniorConversations.lastActivityAt), asc(juniorConversations.conversationId)).limit(25);
|
|
3456
3422
|
}
|
|
3457
|
-
|
|
3458
|
-
//#region src/api/people/list.query.ts
|
|
3423
|
+
// src/api/people/list.query.ts
|
|
3459
3424
|
const DIRECTORY_ACTIVITY_DAYS = 90;
|
|
3460
3425
|
/** Day ranges need the prior equal period too (90d + prior 90d). */
|
|
3461
3426
|
const DAY_METRIC_LOOKBACK = 180;
|
|
@@ -3663,14 +3628,12 @@ async function readPeopleListFromSql() {
|
|
|
3663
3628
|
windowStart: start.toISOString()
|
|
3664
3629
|
};
|
|
3665
3630
|
}
|
|
3666
|
-
|
|
3667
|
-
//#region src/api/people/list.ts
|
|
3631
|
+
// src/api/people/list.ts
|
|
3668
3632
|
/** Load the people list from verified user identities in SQL. */
|
|
3669
3633
|
async function readPeopleList() {
|
|
3670
3634
|
return actorDirectoryReportSchema.parse(await readPeopleListFromSql());
|
|
3671
3635
|
}
|
|
3672
|
-
|
|
3673
|
-
//#region src/api/people/plugin-reports.ts
|
|
3636
|
+
// src/api/people/plugin-reports.ts
|
|
3674
3637
|
/** Read sanitized person-scoped plugin reports for one profile subject. */
|
|
3675
3638
|
async function readPeoplePluginReports(args) {
|
|
3676
3639
|
const nowMs = Date.now();
|
|
@@ -3680,7 +3643,7 @@ async function readPeoplePluginReports(args) {
|
|
|
3680
3643
|
reports: [],
|
|
3681
3644
|
source: "plugins"
|
|
3682
3645
|
});
|
|
3683
|
-
const { getPluginProfileReports } = await import("./agent-hooks-
|
|
3646
|
+
const { getPluginProfileReports } = await import("./agent-hooks-B00FaKdP.js").then((n) => n.t);
|
|
3684
3647
|
return pluginOperationalReportFeedSchema.parse({
|
|
3685
3648
|
generatedAt: new Date(nowMs).toISOString(),
|
|
3686
3649
|
reports: await getPluginProfileReports({
|
|
@@ -3691,8 +3654,7 @@ async function readPeoplePluginReports(args) {
|
|
|
3691
3654
|
source: "plugins"
|
|
3692
3655
|
});
|
|
3693
3656
|
}
|
|
3694
|
-
|
|
3695
|
-
//#region src/api/people/profile.query.ts
|
|
3657
|
+
// src/api/people/profile.query.ts
|
|
3696
3658
|
function emptyProfile(email, nowMs) {
|
|
3697
3659
|
const end = new Date(nowMs);
|
|
3698
3660
|
end.setUTCHours(0, 0, 0, 0);
|
|
@@ -3862,14 +3824,12 @@ async function readPeopleProfileFromSql(email, options = {}) {
|
|
|
3862
3824
|
windowStart: start.toISOString()
|
|
3863
3825
|
};
|
|
3864
3826
|
}
|
|
3865
|
-
|
|
3866
|
-
//#region src/api/people/profile.ts
|
|
3827
|
+
// src/api/people/profile.ts
|
|
3867
3828
|
/** Load one person profile from verified user identities in SQL. */
|
|
3868
3829
|
async function readPeopleProfile(email, options = {}) {
|
|
3869
3830
|
return actorProfileReportSchema.parse(await readPeopleProfileFromSql(email, options));
|
|
3870
3831
|
}
|
|
3871
|
-
|
|
3872
|
-
//#region src/api/people/spend.query.ts
|
|
3832
|
+
// src/api/people/spend.query.ts
|
|
3873
3833
|
const SEVEN_DAY_OFFSET = 6;
|
|
3874
3834
|
const THIRTY_DAY_OFFSET = 29;
|
|
3875
3835
|
function addUsd(current, next) {
|
|
@@ -3919,8 +3879,7 @@ async function readPersonalSpendFromSql(email, nowMs = Date.now()) {
|
|
|
3919
3879
|
windowStart: thirtyDayStart.toISOString()
|
|
3920
3880
|
};
|
|
3921
3881
|
}
|
|
3922
|
-
|
|
3923
|
-
//#region src/api/people/spend.ts
|
|
3882
|
+
// src/api/people/spend.ts
|
|
3924
3883
|
const PERSONAL_SPEND_CACHE_TTL_MS = 3e5;
|
|
3925
3884
|
/** Create an app-scoped personal-spend reader with a five-minute cache. */
|
|
3926
3885
|
function createPersonalSpendReader() {
|
|
@@ -3945,8 +3904,7 @@ function createPersonalSpendReader() {
|
|
|
3945
3904
|
}
|
|
3946
3905
|
};
|
|
3947
3906
|
}
|
|
3948
|
-
|
|
3949
|
-
//#region src/api/people/routes.ts
|
|
3907
|
+
// src/api/people/routes.ts
|
|
3950
3908
|
/** Create the HTTP routes owned by the People API. */
|
|
3951
3909
|
function createPeopleRoutes() {
|
|
3952
3910
|
const app = new Hono();
|
|
@@ -3975,8 +3933,7 @@ function createPeopleRoutes() {
|
|
|
3975
3933
|
});
|
|
3976
3934
|
return app;
|
|
3977
3935
|
}
|
|
3978
|
-
|
|
3979
|
-
//#region src/personal-tokens/store.ts
|
|
3936
|
+
// src/personal-tokens/store.ts
|
|
3980
3937
|
const TOKEN_PREFIX = "jr_pat_";
|
|
3981
3938
|
const DEFAULT_TOKEN_LIFETIME_MS = 7776e6;
|
|
3982
3939
|
function normalizeEmail(email) {
|
|
@@ -4037,8 +3994,7 @@ async function authenticatePersonalToken(token, now = /* @__PURE__ */ new Date()
|
|
|
4037
3994
|
await getDb().update(juniorApiTokens).set({ lastUsedAt: now }).where(eq(juniorApiTokens.id, match.id));
|
|
4038
3995
|
return match.ownerEmailNormalized;
|
|
4039
3996
|
}
|
|
4040
|
-
|
|
4041
|
-
//#region src/api/personal-tokens/routes.ts
|
|
3997
|
+
// src/api/personal-tokens/routes.ts
|
|
4042
3998
|
/** Create authenticated native personal-token list and action routes. */
|
|
4043
3999
|
function createPersonalTokenRoutes() {
|
|
4044
4000
|
const app = new Hono();
|
|
@@ -4065,8 +4021,67 @@ function createPersonalTokenRoutes() {
|
|
|
4065
4021
|
});
|
|
4066
4022
|
return app;
|
|
4067
4023
|
}
|
|
4068
|
-
|
|
4069
|
-
|
|
4024
|
+
// src/api/service-accounts/routes.ts
|
|
4025
|
+
/**
|
|
4026
|
+
* Public URL of the OAuth callback for one plugin's service account.
|
|
4027
|
+
*
|
|
4028
|
+
* It uses the request origin unless `JUNIOR_BASE_URL` is set, so the
|
|
4029
|
+
* provider sends the Admin back to the dashboard session that started it.
|
|
4030
|
+
*/
|
|
4031
|
+
function callbackUrl(request, provider) {
|
|
4032
|
+
const base = process.env.JUNIOR_BASE_URL?.trim() || new URL(request.url).origin;
|
|
4033
|
+
return new URL(`api/service-accounts/${encodeURIComponent(provider)}/callback`, base.endsWith("/") ? base : `${base}/`).toString();
|
|
4034
|
+
}
|
|
4035
|
+
function requirePlugin(provider) {
|
|
4036
|
+
const plugin = pluginCatalogRuntime.getDefinition(provider);
|
|
4037
|
+
if (!plugin?.manifest.accounts?.serviceAccount) throwApiError(404, "Service account not found.");
|
|
4038
|
+
return plugin;
|
|
4039
|
+
}
|
|
4040
|
+
function callbackPage(title, message, status) {
|
|
4041
|
+
return htmlCallbackResponse(escapeXml(title), escapeXml(message), status, { footerMessage: "You can close this tab and return to the dashboard." });
|
|
4042
|
+
}
|
|
4043
|
+
/**
|
|
4044
|
+
* Create admin-only routes that list, connect, and disconnect plugin service
|
|
4045
|
+
* accounts.
|
|
4046
|
+
*
|
|
4047
|
+
* Whoever signs in decides which account everyone falls back to, so every
|
|
4048
|
+
* route, including the OAuth callback, requires a Junior admin. The callback
|
|
4049
|
+
* also accepts only a sign-in that the same Admin started.
|
|
4050
|
+
*/
|
|
4051
|
+
function createServiceAccountRoutes() {
|
|
4052
|
+
const app = new Hono();
|
|
4053
|
+
app.get("/", requireAdmin, async () => jsonResponse(serviceAccountListSchema, { serviceAccounts: await Promise.all(serviceAccountPlugins(pluginCatalogRuntime.getProviders()).map(getServiceAccountStatus)) }));
|
|
4054
|
+
app.post("/:provider", requireAdmin, validateRequest("param", serviceAccountParamsSchema, "Invalid provider."), async (context) => {
|
|
4055
|
+
const { provider } = context.req.valid("param");
|
|
4056
|
+
const { authorizationUrl } = await startServiceAccountSignIn({
|
|
4057
|
+
plugin: requirePlugin(provider),
|
|
4058
|
+
redirectUrl: callbackUrl(context.req.raw, provider),
|
|
4059
|
+
startedBy: context.get("viewer").email
|
|
4060
|
+
});
|
|
4061
|
+
return jsonResponse(startServiceAccountSignInResponseSchema, { authorizationUrl: authorizationUrl.toString() });
|
|
4062
|
+
});
|
|
4063
|
+
app.get("/:provider/callback", requireAdmin, validateRequest("param", serviceAccountParamsSchema, "Invalid provider."), async (context) => {
|
|
4064
|
+
const { provider } = context.req.valid("param");
|
|
4065
|
+
const plugin = requirePlugin(provider);
|
|
4066
|
+
const viewer = context.get("viewer");
|
|
4067
|
+
const result = await finishServiceAccountSignIn({
|
|
4068
|
+
callback: new URL(context.req.url).searchParams,
|
|
4069
|
+
connectedBy: viewer.email,
|
|
4070
|
+
plugin
|
|
4071
|
+
});
|
|
4072
|
+
if (!result.ok) return callbackPage("Connection failed", result.message, 400);
|
|
4073
|
+
logInfo("dashboard.service_account.connected", { "app.credential.provider": provider });
|
|
4074
|
+
return callbackPage(`${plugin.manifest.displayName} service account connected`, `People who have not connected ${plugin.manifest.displayName} now use this account for what its policy allows.`, 200);
|
|
4075
|
+
});
|
|
4076
|
+
app.delete("/:provider", requireAdmin, validateRequest("param", serviceAccountParamsSchema, "Invalid provider."), async (context) => {
|
|
4077
|
+
const { provider } = context.req.valid("param");
|
|
4078
|
+
await disconnectServiceAccount(requirePlugin(provider));
|
|
4079
|
+
logInfo("dashboard.service_account.disconnected", { "app.credential.provider": provider });
|
|
4080
|
+
return jsonResponse(disconnectServiceAccountResponseSchema, { disconnected: true });
|
|
4081
|
+
});
|
|
4082
|
+
return app;
|
|
4083
|
+
}
|
|
4084
|
+
// src/chat/plugins/user-pages.ts
|
|
4070
4085
|
/**
|
|
4071
4086
|
* Runtime ownership for plugin user pages.
|
|
4072
4087
|
*
|
|
@@ -4109,8 +4124,7 @@ async function readPluginUserPage(input) {
|
|
|
4109
4124
|
if (content.records.some((record) => record.actions?.some((action) => !actionBelongsToPlugin(action.href, plugin.manifest.name)))) throw new Error(`Plugin user page "${plugin.manifest.name}/${page.id}" returned an action outside its API namespace.`);
|
|
4110
4125
|
return content;
|
|
4111
4126
|
}
|
|
4112
|
-
|
|
4113
|
-
//#region src/api/user-pages/routes.ts
|
|
4127
|
+
// src/api/user-pages/routes.ts
|
|
4114
4128
|
const userPageQuerySchema = z.object({
|
|
4115
4129
|
cursor: z.preprocess((value) => value || void 0, pluginUserPageCursorSchema),
|
|
4116
4130
|
filter: z.preprocess((value) => value || void 0, pluginUserPageFilterSchema),
|
|
@@ -4137,8 +4151,7 @@ function createUserPageRoutes() {
|
|
|
4137
4151
|
});
|
|
4138
4152
|
return app;
|
|
4139
4153
|
}
|
|
4140
|
-
|
|
4141
|
-
//#region src/chat/automations/edit.ts
|
|
4154
|
+
// src/chat/automations/edit.ts
|
|
4142
4155
|
/**
|
|
4143
4156
|
* Web edits. Owners and public Destination readers can edit. Creator-only
|
|
4144
4157
|
* rules still apply, and lifecycle actions stay creator-only.
|
|
@@ -4366,8 +4379,7 @@ async function changeViewerAutomationLifecycle(user, id, input) {
|
|
|
4366
4379
|
task: await saveScheduledAutomation(getDb(), next, input.revision)
|
|
4367
4380
|
}, true);
|
|
4368
4381
|
}
|
|
4369
|
-
|
|
4370
|
-
//#region src/chat/automations/editor.ts
|
|
4382
|
+
// src/chat/automations/editor.ts
|
|
4371
4383
|
/** Read-only editor support. Core owns schedules; plugins own Event choices. */
|
|
4372
4384
|
/** Return only Event types that can start a durable Automation. */
|
|
4373
4385
|
function readAutomationEventCatalog() {
|
|
@@ -4392,8 +4404,7 @@ async function previewAutomationSchedule(user, id, intent) {
|
|
|
4392
4404
|
throw error;
|
|
4393
4405
|
}
|
|
4394
4406
|
}
|
|
4395
|
-
|
|
4396
|
-
//#region src/api/automations/routes.ts
|
|
4407
|
+
// src/api/automations/routes.ts
|
|
4397
4408
|
/** Translate expected edit failures; unexpected failures stay at the API boundary. */
|
|
4398
4409
|
function editErrorResponse(error) {
|
|
4399
4410
|
if (error instanceof ViewerTaskNotFoundError) return jsonResponse(automationEditErrorSchema, {
|
|
@@ -4518,8 +4529,7 @@ function createAutomationRoutes() {
|
|
|
4518
4529
|
});
|
|
4519
4530
|
return app;
|
|
4520
4531
|
}
|
|
4521
|
-
|
|
4522
|
-
//#region src/api/workspaces/routes.ts
|
|
4532
|
+
// src/api/workspaces/routes.ts
|
|
4523
4533
|
function snapshotView(workspace) {
|
|
4524
4534
|
const recorded = workspace.snapshot;
|
|
4525
4535
|
if (!recorded) return null;
|
|
@@ -4615,8 +4625,7 @@ function createWorkspaceRoutes() {
|
|
|
4615
4625
|
});
|
|
4616
4626
|
return app;
|
|
4617
4627
|
}
|
|
4618
|
-
|
|
4619
|
-
//#region src/api/stats.ts
|
|
4628
|
+
// src/api/stats.ts
|
|
4620
4629
|
/** Read the last 90 days of named daily counters. */
|
|
4621
4630
|
async function readStatsReport() {
|
|
4622
4631
|
const now = /* @__PURE__ */ new Date();
|
|
@@ -4632,8 +4641,7 @@ async function readStatsReport() {
|
|
|
4632
4641
|
windowStart: start
|
|
4633
4642
|
});
|
|
4634
4643
|
}
|
|
4635
|
-
|
|
4636
|
-
//#region src/reporting.ts
|
|
4644
|
+
// src/reporting.ts
|
|
4637
4645
|
function readDescriptionText(home) {
|
|
4638
4646
|
try {
|
|
4639
4647
|
return readFileSync(path.join(home, "DESCRIPTION.md"), "utf8").trim() || void 0;
|
|
@@ -4643,7 +4651,7 @@ function readDescriptionText(home) {
|
|
|
4643
4651
|
}
|
|
4644
4652
|
/** Read discovered skill names for authenticated runtime diagnostics. */
|
|
4645
4653
|
async function readSkillReports() {
|
|
4646
|
-
const { discoverSkills } = await import("./skills-
|
|
4654
|
+
const { discoverSkills } = await import("./skills-CiWS5_Ub.js").then((n) => n.o);
|
|
4647
4655
|
const skills = await discoverSkills();
|
|
4648
4656
|
return skillReportsSchema.parse(skills.map((skill) => ({
|
|
4649
4657
|
name: skill.name,
|
|
@@ -4652,7 +4660,7 @@ async function readSkillReports() {
|
|
|
4652
4660
|
}
|
|
4653
4661
|
/** Read safe configured plugin metadata for authenticated runtime diagnostics. */
|
|
4654
4662
|
async function readPlugins() {
|
|
4655
|
-
const { pluginCatalogRuntime } = await import("./catalog-runtime-
|
|
4663
|
+
const { pluginCatalogRuntime } = await import("./catalog-runtime-B8SuFPGb.js").then((n) => n.t);
|
|
4656
4664
|
return pluginsSchema.parse(pluginCatalogRuntime.getProviders().map((plugin) => ({
|
|
4657
4665
|
configKeys: plugin.manifest.configKeys ?? [],
|
|
4658
4666
|
description: plugin.manifest.description,
|
|
@@ -4663,8 +4671,8 @@ async function readPlugins() {
|
|
|
4663
4671
|
/** Read authenticated runtime discovery data. */
|
|
4664
4672
|
async function readRuntimeInfoReport() {
|
|
4665
4673
|
const [{ homeDir }, { pluginCatalogRuntime }, plugins, skills] = await Promise.all([
|
|
4666
|
-
import("./package-discovery-
|
|
4667
|
-
import("./catalog-runtime-
|
|
4674
|
+
import("./package-discovery-DJBompdd.js").then((n) => n.r),
|
|
4675
|
+
import("./catalog-runtime-B8SuFPGb.js").then((n) => n.t),
|
|
4668
4676
|
readPlugins(),
|
|
4669
4677
|
readSkillReports()
|
|
4670
4678
|
]);
|
|
@@ -4681,15 +4689,14 @@ async function readRuntimeInfoReport() {
|
|
|
4681
4689
|
/** Read sanitized operational summaries contributed by plugins. */
|
|
4682
4690
|
async function readPluginOperationalReportFeed() {
|
|
4683
4691
|
const nowMs = Date.now();
|
|
4684
|
-
const { getPluginOperationalReports } = await import("./agent-hooks-
|
|
4692
|
+
const { getPluginOperationalReports } = await import("./agent-hooks-B00FaKdP.js").then((n) => n.t);
|
|
4685
4693
|
return pluginOperationalReportFeedSchema.parse({
|
|
4686
4694
|
source: "plugins",
|
|
4687
4695
|
generatedAt: new Date(nowMs).toISOString(),
|
|
4688
4696
|
reports: await getPluginOperationalReports(nowMs)
|
|
4689
4697
|
});
|
|
4690
4698
|
}
|
|
4691
|
-
|
|
4692
|
-
//#region src/api.ts
|
|
4699
|
+
// src/api.ts
|
|
4693
4700
|
/** Create Junior's production REST API for authenticated dashboard consumers. */
|
|
4694
4701
|
function createJuniorApi(options = {}) {
|
|
4695
4702
|
const app = new Hono();
|
|
@@ -4706,6 +4713,7 @@ function createJuniorApi(options = {}) {
|
|
|
4706
4713
|
app.route("/api/code", createCodeRoutes());
|
|
4707
4714
|
app.route("/api/connections", createConnectionRoutes());
|
|
4708
4715
|
app.route("/api/personal-tokens", createPersonalTokenRoutes());
|
|
4716
|
+
app.route("/api/service-accounts", createServiceAccountRoutes());
|
|
4709
4717
|
app.route("/api/people", createPeopleRoutes());
|
|
4710
4718
|
app.route("/api/locations", createLocationRoutes());
|
|
4711
4719
|
app.route("/api/user-pages", createUserPageRoutes());
|
|
@@ -4722,5 +4730,4 @@ function createJuniorApi(options = {}) {
|
|
|
4722
4730
|
});
|
|
4723
4731
|
return app;
|
|
4724
4732
|
}
|
|
4725
|
-
//#endregion
|
|
4726
4733
|
export { authenticatePersonalToken, createJuniorApi, jsonResponse, resolveViewerUser, updateViewerDisplayName };
|