@sentry/junior 0.147.0 → 0.149.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-HS6VGUPM.js → agent-hooks-CWMCXAMT.js} +10 -10
- package/dist/api/conversations/access.d.ts +2 -1
- package/dist/api/conversations/aggregate.d.ts +2 -0
- package/dist/api/conversations/archive.d.ts +3 -5
- package/dist/api/conversations/create.d.ts +6 -0
- package/dist/api/conversations/detail.d.ts +2 -296
- package/dist/api/conversations/event-list.d.ts +2 -193
- package/dist/api/conversations/list.d.ts +4 -66
- package/dist/api/conversations/pending-messages.d.ts +15 -0
- package/dist/api/conversations/routes.d.ts +1 -1
- package/dist/api/conversations/stats.d.ts +0 -54
- package/dist/api/http.d.ts +2 -6
- package/dist/api/locations/detail.d.ts +3 -111
- package/dist/api/locations/list.d.ts +0 -45
- package/dist/api/locations/query.d.ts +2 -1
- package/dist/api/locations/routes.d.ts +1 -1
- package/dist/api/people/list.d.ts +0 -29
- package/dist/api/people/profile.d.ts +2 -106
- package/dist/api/people/profile.query.d.ts +2 -1
- package/dist/api/people/routes.d.ts +1 -1
- package/dist/api/people/shared.d.ts +3 -1
- package/dist/api/people/spend.d.ts +3 -4
- package/dist/api/personal-tokens/routes.d.ts +2 -2
- package/dist/api/route.d.ts +8 -14
- package/dist/api/schema/conversation.d.ts +130 -25
- package/dist/api/schema/location.d.ts +4 -0
- package/dist/api/schema/person.d.ts +7 -3
- package/dist/api/schema.d.ts +2 -2
- package/dist/api/schema.js +13 -1
- package/dist/api/stats.d.ts +0 -13
- package/dist/api/validation.d.ts +7 -0
- package/dist/api/viewer.d.ts +3 -0
- package/dist/api.d.ts +2 -1
- package/dist/api.js +772 -561
- package/dist/app.js +241 -204
- package/dist/{catalog-runtime-M6ZTPYRV.js → catalog-runtime-GAW5APVI.js} +5 -5
- package/dist/chat/actor.d.ts +4 -1
- package/dist/chat/agent/request.d.ts +2 -0
- package/dist/chat/agent/resume.d.ts +1 -0
- package/dist/chat/agent-dispatch/context.d.ts +2 -2
- package/dist/chat/agent-invocations/types.d.ts +52 -0
- package/dist/chat/api-turns/work.d.ts +108 -0
- package/dist/chat/app/services.d.ts +1 -1
- package/dist/chat/conversations/history.d.ts +60 -0
- package/dist/chat/conversations/provenance.d.ts +6 -0
- package/dist/chat/conversations/sql/actor-identity.d.ts +19 -0
- package/dist/chat/conversations/store.d.ts +1 -1
- package/dist/chat/resource-events/store.d.ts +1 -1
- package/dist/chat/runtime/reply-executor.d.ts +1 -3
- package/dist/chat/runtime/slack-runtime.d.ts +2 -1
- package/dist/chat/runtime/turn-preparation.d.ts +9 -0
- package/dist/chat/scheduled-tasks/tool-support.d.ts +5 -5
- package/dist/chat/scheduled-tasks/tools/create.d.ts +2 -2
- package/dist/chat/scheduled-tasks/tools/delete.d.ts +2 -2
- package/dist/chat/scheduled-tasks/tools/list.d.ts +2 -2
- package/dist/chat/scheduled-tasks/tools/run-now.d.ts +2 -2
- package/dist/chat/scheduled-tasks/tools/update.d.ts +2 -2
- package/dist/chat/services/conversation-memory.d.ts +2 -2
- package/dist/chat/services/conversation-title.d.ts +20 -0
- package/dist/chat/slack/assistant-thread/title.d.ts +10 -27
- package/dist/chat/slack/channel.d.ts +26 -0
- package/dist/chat/slack/dispatch-turn.d.ts +1 -0
- package/dist/chat/slack/timestamp-param.d.ts +0 -2
- package/dist/chat/slack/{tools → tool-support}/canvas/api.d.ts +1 -1
- package/dist/chat/slack/{tools → tool-support}/canvas/context.d.ts +3 -0
- package/dist/chat/slack/tool-support/channel-access.d.ts +42 -0
- package/dist/chat/slack/tool-support/channel-target.d.ts +27 -0
- package/dist/chat/slack/tool-support/list/params.d.ts +5 -0
- package/dist/chat/slack/tools/canvas/create.d.ts +1 -1
- package/dist/chat/slack/tools/channel-join.d.ts +28 -0
- package/dist/chat/slack/tools/channel-list-messages.d.ts +3 -2
- package/dist/chat/slack/tools/conversation-message-search.d.ts +2 -8
- package/dist/chat/slack/tools/message-add-reaction.d.ts +1 -1
- package/dist/chat/slack/tools/public-search.d.ts +63 -2
- package/dist/chat/slack/tools/send-files.d.ts +1 -1
- package/dist/chat/slack/tools/thread-read.d.ts +2 -5
- package/dist/chat/source.d.ts +2 -0
- package/dist/chat/state/conversation.d.ts +1 -0
- package/dist/chat/task-execution/checkpoint.d.ts +1 -0
- package/dist/chat/task-execution/state.d.ts +9 -4
- package/dist/chat/task-execution/store.d.ts +3 -2
- package/dist/chat/task-execution/turn-cursor.d.ts +2 -0
- package/dist/chat/task-execution/worker.d.ts +2 -0
- package/dist/chat/tasks/read.d.ts +1 -1
- package/dist/chat/tools/search-conversation-events.d.ts +1 -1
- package/dist/chat/tools/types.d.ts +11 -4
- package/dist/chat/tools/watch-resource-events.d.ts +2 -2
- package/dist/{chunk-ORO3PWKQ.js → chunk-25SC7D6Z.js} +1 -1
- package/dist/{chunk-GGB4WL5A.js → chunk-2JHKISQA.js} +1 -1
- package/dist/{chunk-AVZDSUFB.js → chunk-2P6BQQER.js} +4 -4
- package/dist/{chunk-7NVJVJID.js → chunk-32CXPIZE.js} +2 -2
- package/dist/{chunk-YSB2N563.js → chunk-3GYZ5YEH.js} +121 -87
- package/dist/{chunk-DU74WPIC.js → chunk-3I2IVWSZ.js} +1 -1
- package/dist/{chunk-SVHUEHUL.js → chunk-3JVUWLR7.js} +65 -4
- package/dist/{chunk-RXBVB2JM.js → chunk-3KGQOKIG.js} +1 -1
- package/dist/{chunk-YBVXBNSV.js → chunk-4JGM7FXO.js} +2 -2
- package/dist/{chunk-AZ7EAOBE.js → chunk-4YKPOYRV.js} +5 -5
- package/dist/chunk-5CWUQXXT.js +806 -0
- package/dist/{chunk-DLDRQHG5.js → chunk-6G5RCDKP.js} +1 -1
- package/dist/{chunk-AYU72WO7.js → chunk-75DSYFFB.js} +47 -70
- package/dist/{chunk-YHDERDRO.js → chunk-7BH46NB4.js} +91 -75
- package/dist/{chunk-745QJ3ZA.js → chunk-ALJG73MQ.js} +2 -2
- package/dist/chunk-ART7P442.js +48 -0
- package/dist/{chunk-7A4M7PCV.js → chunk-DK5UT6PQ.js} +1180 -556
- package/dist/{chunk-AIOK6LAG.js → chunk-EW2LNCRL.js} +813 -44
- package/dist/chunk-EXW76GW4.js +36 -0
- package/dist/chunk-GDFF3BQG.js +136 -0
- package/dist/{chunk-7UQIVT6G.js → chunk-JMH3DBM5.js} +6 -6
- package/dist/{chunk-CWP5RHVX.js → chunk-JMSMXXED.js} +12 -5
- package/dist/{chunk-CSZINQJ2.js → chunk-MEMURSBG.js} +1 -1
- package/dist/{chunk-YNTTROJT.js → chunk-QIW7OQEO.js} +1 -1
- package/dist/{chunk-Q4R73I43.js → chunk-RB26T3LU.js} +58 -28
- package/dist/{chunk-4LJO56OJ.js → chunk-RLVZIWNQ.js} +1 -1
- package/dist/{chunk-SGZO7UWH.js → chunk-SWHPVZBV.js} +2 -2
- package/dist/{chunk-PVNG6UMU.js → chunk-TFBNBXPU.js} +22 -10
- package/dist/{chunk-EFLJ2WJH.js → chunk-URDCZAL4.js} +5 -5
- package/dist/{chunk-6H5SZR24.js → chunk-UZGASGOD.js} +300 -383
- package/dist/{chunk-YEO3VX72.js → chunk-W7UONUIZ.js} +8 -6
- package/dist/{chunk-JUUKWRBE.js → chunk-X22XXSZA.js} +1 -1
- package/dist/{chunk-X5UY34KT.js → chunk-XPYWWMHR.js} +8 -8
- package/dist/{chunk-IIOOO4FQ.js → chunk-ZYMYLLWG.js} +2 -1
- package/dist/cli/chat.js +32 -35
- package/dist/cli/check.js +6 -6
- package/dist/cli/plugins.js +13 -13
- package/dist/cli/snapshot-create.js +9 -9
- package/dist/cli/upgrade.js +7 -7
- package/dist/db/schema/agent-invocations.d.ts +20 -0
- package/dist/db/schema/conversation-annotations.d.ts +2 -2
- package/dist/db/schema.d.ts +22 -2
- package/dist/{db-CSEW4RII.js → db-JBZLRIVY.js} +7 -7
- package/dist/instrumentation.js +4 -4
- package/dist/nitro.js +2 -2
- package/dist/{oauth-callback-server-FUEV5HNG.js → oauth-callback-server-MNTVYY2I.js} +24 -26
- package/dist/{runner-U3XHSKSH.js → runner-K24BWZSZ.js} +23 -25
- package/dist/{skills-AKE6W3WI.js → skills-AU5ST2CG.js} +6 -6
- package/dist/spawn-6PO7CVJ6.js +38 -0
- package/dist/{validation-WDTAULUF.js → validation-IXGZCFRO.js} +6 -6
- package/dist/version.js +1 -1
- package/dist/{work-C3HAO2BG.js → work-WCZIYILX.js} +18 -19
- package/dist/{worker-LNP4YKBM.js → worker-U2AACBEY.js} +11 -10
- package/package.json +6 -5
- package/dist/api/health.d.ts +0 -7
- package/dist/api/personal-tokens/create.d.ts +0 -11
- package/dist/api/personal-tokens/list.d.ts +0 -12
- package/dist/api/personal-tokens/revoke.d.ts +0 -5
- package/dist/api/plugin-reports.d.ts +0 -63
- package/dist/api/plugins.d.ts +0 -8
- package/dist/api/runtime.d.ts +0 -24
- package/dist/api/skills.d.ts +0 -6
- package/dist/chat/slack/tools/channel-access.d.ts +0 -30
- package/dist/chunk-34GS7B6L.js +0 -115
- package/dist/chunk-AVOCH2Z5.js +0 -285
- package/dist/chunk-HLXXQI5Q.js +0 -238
- package/dist/chunk-K4SZAP3K.js +0 -67
- package/dist/chunk-R776HKPK.js +0 -81
- package/dist/chunk-Z4YU7Z4L.js +0 -76
- package/dist/spawn-B6GDTWJ4.js +0 -39
- /package/dist/chat/slack/{tools → tool-support}/canvas/markdown.d.ts +0 -0
- /package/dist/chat/slack/{tools → tool-support}/channel-capabilities.d.ts +0 -0
- /package/dist/chat/slack/{tools → tool-support}/context.d.ts +0 -0
- /package/dist/chat/slack/{tools → tool-support}/list/api.d.ts +0 -0
- /package/dist/chat/slack/{tools → tool-support}/slack-message-url.d.ts +0 -0
package/dist/api.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
acceptedConversationMessageSchema,
|
|
2
3
|
activityDays,
|
|
3
4
|
actorDirectoryReportSchema,
|
|
4
5
|
actorProfileReportSchema,
|
|
@@ -12,8 +13,11 @@ import {
|
|
|
12
13
|
conversationFeedQuerySchema,
|
|
13
14
|
conversationFeedSchema,
|
|
14
15
|
conversationParamsSchema,
|
|
16
|
+
conversationPendingMessagesReportSchema,
|
|
15
17
|
conversationReportEventSchema,
|
|
16
18
|
conversationStatsReportSchema,
|
|
19
|
+
createConversationBodySchema,
|
|
20
|
+
createConversationMessageBodySchema,
|
|
17
21
|
createPersonalTokenBodySchema,
|
|
18
22
|
createdPersonalTokenSchema,
|
|
19
23
|
locationDetailReportSchema,
|
|
@@ -29,15 +33,21 @@ import {
|
|
|
29
33
|
taskListSchema,
|
|
30
34
|
taskParamsSchema,
|
|
31
35
|
taskRunListSchema
|
|
32
|
-
} from "./chunk-
|
|
36
|
+
} from "./chunk-3JVUWLR7.js";
|
|
33
37
|
import {
|
|
38
|
+
appendAndEnqueueApiConversationMessage,
|
|
39
|
+
createAndEnqueueApiConversation,
|
|
34
40
|
formatSlackConversationRedactedLabel,
|
|
35
41
|
readHealthReport,
|
|
36
|
-
resolveSlackConversationContextFromThreadId
|
|
37
|
-
|
|
42
|
+
resolveSlackConversationContextFromThreadId,
|
|
43
|
+
webActorFromEmail
|
|
44
|
+
} from "./chunk-5CWUQXXT.js";
|
|
38
45
|
import {
|
|
39
46
|
buildSentryConversationUrl
|
|
40
47
|
} from "./chunk-4CODA7P5.js";
|
|
48
|
+
import {
|
|
49
|
+
getConversation
|
|
50
|
+
} from "./chunk-JMSMXXED.js";
|
|
41
51
|
import {
|
|
42
52
|
readTaskExecutionByConversationId,
|
|
43
53
|
readTaskExecutionDays,
|
|
@@ -45,7 +55,8 @@ import {
|
|
|
45
55
|
readTaskExecutionSummaries,
|
|
46
56
|
readTaskExecutions,
|
|
47
57
|
readTaskRuns
|
|
48
|
-
} from "./chunk-
|
|
58
|
+
} from "./chunk-UZGASGOD.js";
|
|
59
|
+
import "./chunk-4YKPOYRV.js";
|
|
49
60
|
import {
|
|
50
61
|
healthReportSchema,
|
|
51
62
|
pluginOperationalReportFeedSchema,
|
|
@@ -53,6 +64,11 @@ import {
|
|
|
53
64
|
runtimeInfoReportSchema,
|
|
54
65
|
skillReportsSchema
|
|
55
66
|
} from "./chunk-UTL3MHPC.js";
|
|
67
|
+
import {
|
|
68
|
+
getVercelConversationWorkQueue
|
|
69
|
+
} from "./chunk-WR76IVA5.js";
|
|
70
|
+
import "./chunk-JAL3CH4G.js";
|
|
71
|
+
import "./chunk-5I6ORJUY.js";
|
|
56
72
|
import {
|
|
57
73
|
createSchedulerSqlStore,
|
|
58
74
|
deleteEventTask,
|
|
@@ -64,18 +80,17 @@ import {
|
|
|
64
80
|
listPublicEventTasksForTeams,
|
|
65
81
|
listPublicScheduledTasksForTeams,
|
|
66
82
|
readStats
|
|
67
|
-
} from "./chunk-
|
|
83
|
+
} from "./chunk-URDCZAL4.js";
|
|
68
84
|
import {
|
|
69
85
|
parseSlackThreadId
|
|
70
|
-
} from "./chunk-
|
|
71
|
-
import {
|
|
72
|
-
fallbackShortTitle
|
|
73
|
-
} from "./chunk-Z4YU7Z4L.js";
|
|
86
|
+
} from "./chunk-MEMURSBG.js";
|
|
74
87
|
import {
|
|
75
88
|
agentTurnUsageSchema,
|
|
89
|
+
fallbackShortTitle,
|
|
76
90
|
hasAgentTurnUsage,
|
|
77
91
|
renderJuniorNativeConversationEvent
|
|
78
|
-
} from "./chunk-
|
|
92
|
+
} from "./chunk-EW2LNCRL.js";
|
|
93
|
+
import "./chunk-3Y47VMHV.js";
|
|
79
94
|
import "./chunk-PDO5BLNM.js";
|
|
80
95
|
import {
|
|
81
96
|
createPluginLogger,
|
|
@@ -83,56 +98,73 @@ import {
|
|
|
83
98
|
listConversationAnnotations,
|
|
84
99
|
renderPluginConversationEvent,
|
|
85
100
|
resolveViewerUser
|
|
86
|
-
} from "./chunk-
|
|
101
|
+
} from "./chunk-7BH46NB4.js";
|
|
87
102
|
import {
|
|
88
103
|
getSlackClient,
|
|
89
104
|
withSlackRetries
|
|
90
|
-
} from "./chunk-
|
|
105
|
+
} from "./chunk-SWHPVZBV.js";
|
|
91
106
|
import {
|
|
92
107
|
decodeStoredConversationEvent,
|
|
108
|
+
getConversationStore,
|
|
93
109
|
getDb,
|
|
94
110
|
getSqlExecutor,
|
|
95
111
|
locationFromRow,
|
|
96
112
|
parseSessionSource
|
|
97
|
-
} from "./chunk-
|
|
113
|
+
} from "./chunk-3GYZ5YEH.js";
|
|
98
114
|
import {
|
|
99
115
|
juniorApiTokens,
|
|
100
116
|
juniorConversationEvents,
|
|
101
117
|
juniorConversations,
|
|
102
118
|
juniorIdentities,
|
|
103
119
|
juniorUsers
|
|
104
|
-
} from "./chunk-
|
|
120
|
+
} from "./chunk-3I2IVWSZ.js";
|
|
105
121
|
import "./chunk-EM225ITJ.js";
|
|
106
|
-
import "./chunk-
|
|
107
|
-
import "./chunk-
|
|
122
|
+
import "./chunk-25SC7D6Z.js";
|
|
123
|
+
import "./chunk-32CXPIZE.js";
|
|
108
124
|
import {
|
|
109
125
|
juniorDestinations
|
|
110
126
|
} from "./chunk-VFUK3X5B.js";
|
|
111
127
|
import {
|
|
112
128
|
canExposeConversationPayload
|
|
113
|
-
} from "./chunk-
|
|
129
|
+
} from "./chunk-3KGQOKIG.js";
|
|
130
|
+
import "./chunk-RUIXF3YQ.js";
|
|
114
131
|
import "./chunk-HZF5P5UN.js";
|
|
115
132
|
import {
|
|
116
133
|
parseSlackChannelId,
|
|
117
134
|
parseSlackMessageTs,
|
|
118
135
|
parseSlackTeamId
|
|
119
136
|
} from "./chunk-F3B2YJ76.js";
|
|
120
|
-
import
|
|
137
|
+
import {
|
|
138
|
+
logException
|
|
139
|
+
} from "./chunk-RLVZIWNQ.js";
|
|
121
140
|
import "./chunk-6GWA276C.js";
|
|
122
|
-
import "./chunk-
|
|
123
|
-
import "./chunk-
|
|
141
|
+
import "./chunk-6G5RCDKP.js";
|
|
142
|
+
import "./chunk-ZYMYLLWG.js";
|
|
124
143
|
import "./chunk-MLKGABMK.js";
|
|
125
144
|
|
|
126
145
|
// src/api.ts
|
|
127
146
|
import { Hono as Hono7 } from "hono";
|
|
147
|
+
import { HTTPException as HTTPException2 } from "hono/http-exception";
|
|
128
148
|
|
|
129
149
|
// src/api/conversations/routes.ts
|
|
130
150
|
import { Hono } from "hono";
|
|
131
151
|
|
|
132
152
|
// src/api/http.ts
|
|
133
153
|
import { HTTPException } from "hono/http-exception";
|
|
154
|
+
var NO_STORE_HEADERS = { "cache-control": "no-store" };
|
|
155
|
+
function noStoreInit(init) {
|
|
156
|
+
if (!init) return { headers: NO_STORE_HEADERS };
|
|
157
|
+
const headers = new Headers(init.headers);
|
|
158
|
+
if (!headers.has("cache-control")) {
|
|
159
|
+
headers.set("cache-control", "no-store");
|
|
160
|
+
}
|
|
161
|
+
return { ...init, headers };
|
|
162
|
+
}
|
|
134
163
|
function jsonResponse(schema, value, init) {
|
|
135
|
-
return Response.json(schema.parse(value), init);
|
|
164
|
+
return Response.json(schema.parse(value), noStoreInit(init));
|
|
165
|
+
}
|
|
166
|
+
function emptyResponse(status = 204) {
|
|
167
|
+
return new Response(null, noStoreInit({ status }));
|
|
136
168
|
}
|
|
137
169
|
function throwApiError(status, message2, cause) {
|
|
138
170
|
throw new HTTPException(status, {
|
|
@@ -141,35 +173,25 @@ function throwApiError(status, message2, cause) {
|
|
|
141
173
|
res: jsonResponse(apiErrorSchema, { error: message2 }, { status })
|
|
142
174
|
});
|
|
143
175
|
}
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
if (result.success) return result.data;
|
|
152
|
-
return throwApiError(400, "Invalid query parameters.", result.error);
|
|
153
|
-
}
|
|
154
|
-
function parseBody(schema, body) {
|
|
155
|
-
const result = schema.safeParse(body);
|
|
156
|
-
if (result.success) return result.data;
|
|
157
|
-
return throwApiError(400, "Invalid request body.", result.error);
|
|
176
|
+
|
|
177
|
+
// src/api/validation.ts
|
|
178
|
+
import { zValidator } from "@hono/zod-validator";
|
|
179
|
+
function validateRequest(target, schema, message2) {
|
|
180
|
+
return zValidator(target, schema, (result) => {
|
|
181
|
+
if (!result.success) throwApiError(400, message2, result.error);
|
|
182
|
+
});
|
|
158
183
|
}
|
|
159
184
|
|
|
160
|
-
// src/api/
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
route.path,
|
|
169
|
-
async (context) => jsonResponse(route.responseSchema, await route.handler(context))
|
|
170
|
-
);
|
|
185
|
+
// src/api/viewer.ts
|
|
186
|
+
import { createMiddleware } from "hono/factory";
|
|
187
|
+
var requireViewer = createMiddleware(
|
|
188
|
+
async (context, next) => {
|
|
189
|
+
if (!context.get("viewer")) {
|
|
190
|
+
throwApiError(401, "Authentication required.");
|
|
191
|
+
}
|
|
192
|
+
await next();
|
|
171
193
|
}
|
|
172
|
-
|
|
194
|
+
);
|
|
173
195
|
|
|
174
196
|
// src/api/conversations/archive.ts
|
|
175
197
|
import { and, eq, isNotNull } from "drizzle-orm";
|
|
@@ -190,32 +212,134 @@ async function archiveIfUnchanged(args) {
|
|
|
190
212
|
if (!args.archived && existing.archivedAt === null) return "updated";
|
|
191
213
|
return "conflict";
|
|
192
214
|
}
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
215
|
+
async function archiveConversation(conversationId, body) {
|
|
216
|
+
const result = await archiveIfUnchanged({ ...body, conversationId });
|
|
217
|
+
if (result === "not_found") {
|
|
218
|
+
throwApiError(404, "Conversation not found.");
|
|
219
|
+
}
|
|
220
|
+
if (result === "conflict") {
|
|
221
|
+
throwApiError(409, "Conversation received new activity.");
|
|
222
|
+
}
|
|
223
|
+
return { archived: body.archived };
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// src/api/conversations/access.ts
|
|
227
|
+
import { eq as eq2, inArray } from "drizzle-orm";
|
|
228
|
+
import { alias } from "drizzle-orm/pg-core";
|
|
229
|
+
var rootConversation = alias(juniorConversations, "access_root_conversation");
|
|
230
|
+
var rootDestination = alias(juniorDestinations, "access_root_destination");
|
|
231
|
+
var rootIdentity = alias(juniorIdentities, "access_root_identity");
|
|
232
|
+
async function readConversationAccessFromSql(db, conversationIds, viewer) {
|
|
233
|
+
if (conversationIds.length === 0) return /* @__PURE__ */ new Map();
|
|
234
|
+
const normalizedViewerEmail = viewer?.email.trim().toLowerCase() || void 0;
|
|
235
|
+
const rows = await db.select({
|
|
236
|
+
conversationId: juniorConversations.conversationId,
|
|
237
|
+
parentConversationId: juniorConversations.parentConversationId,
|
|
238
|
+
storedRootConversationId: juniorConversations.rootConversationId,
|
|
239
|
+
rootConversationId: rootConversation.conversationId,
|
|
240
|
+
rootParentConversationId: rootConversation.parentConversationId,
|
|
241
|
+
rootRootConversationId: rootConversation.rootConversationId,
|
|
242
|
+
visibility: rootDestination.visibility,
|
|
243
|
+
rootEmailNormalized: rootIdentity.emailNormalized,
|
|
244
|
+
rootEmailVerified: rootIdentity.emailVerified,
|
|
245
|
+
rootUserId: rootIdentity.userId
|
|
246
|
+
}).from(juniorConversations).leftJoin(
|
|
247
|
+
rootConversation,
|
|
248
|
+
eq2(
|
|
249
|
+
rootConversation.conversationId,
|
|
250
|
+
juniorConversations.rootConversationId
|
|
251
|
+
)
|
|
252
|
+
).leftJoin(
|
|
253
|
+
rootDestination,
|
|
254
|
+
eq2(rootDestination.id, rootConversation.destinationId)
|
|
255
|
+
).leftJoin(
|
|
256
|
+
rootIdentity,
|
|
257
|
+
eq2(rootIdentity.id, rootConversation.actorIdentityId)
|
|
258
|
+
).where(inArray(juniorConversations.conversationId, [...conversationIds]));
|
|
259
|
+
return new Map(
|
|
260
|
+
rows.map((row) => {
|
|
261
|
+
const hasValidRoot = row.rootConversationId !== null && row.rootConversationId === row.storedRootConversationId && row.rootRootConversationId === row.rootConversationId && row.rootParentConversationId === null && (row.parentConversationId !== null || row.storedRootConversationId === row.conversationId);
|
|
262
|
+
const validRootConversationId = hasValidRoot ? row.rootConversationId ?? void 0 : void 0;
|
|
263
|
+
const visibility = validRootConversationId === void 0 ? null : row.visibility;
|
|
264
|
+
const isParticipant = validRootConversationId !== void 0 && viewer !== void 0 && (row.rootUserId === viewer.id || normalizedViewerEmail !== void 0 && row.rootEmailVerified === true && row.rootEmailNormalized === normalizedViewerEmail);
|
|
265
|
+
const canViewPrivateContent = isParticipant || validRootConversationId !== void 0 && canExposeConversationPayload({
|
|
266
|
+
visibility: visibility ?? void 0
|
|
267
|
+
});
|
|
268
|
+
return [
|
|
269
|
+
row.conversationId,
|
|
270
|
+
{
|
|
271
|
+
canViewPrivateContent,
|
|
272
|
+
isParticipant,
|
|
273
|
+
visibility
|
|
274
|
+
}
|
|
275
|
+
];
|
|
276
|
+
})
|
|
277
|
+
);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// src/api/conversations/create.ts
|
|
281
|
+
function actorFromViewer(viewer) {
|
|
282
|
+
const normalized = viewer.email.trim().toLowerCase();
|
|
283
|
+
return webActorFromEmail(normalized, {
|
|
284
|
+
...viewer.displayName ? { fullName: viewer.displayName } : {},
|
|
285
|
+
userName: normalized.split("@")[0] || normalized
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
async function createConversationForViewer(viewer, body) {
|
|
289
|
+
try {
|
|
290
|
+
return await createAndEnqueueApiConversation(
|
|
291
|
+
{
|
|
292
|
+
actor: actorFromViewer(viewer),
|
|
293
|
+
idempotencyKey: body.idempotencyKey,
|
|
294
|
+
message: body.message,
|
|
295
|
+
...body.visibility ? { visibility: body.visibility } : {}
|
|
296
|
+
},
|
|
297
|
+
{
|
|
298
|
+
conversationStore: getConversationStore(),
|
|
299
|
+
queue: getVercelConversationWorkQueue()
|
|
300
|
+
}
|
|
201
301
|
);
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
input = await c.req.json();
|
|
205
|
-
} catch (error) {
|
|
206
|
-
throwApiError(400, "Invalid request body.", error);
|
|
207
|
-
}
|
|
208
|
-
const body = parseBody(archiveConversationBodySchema, input);
|
|
209
|
-
const result = await archiveIfUnchanged({ ...body, conversationId });
|
|
210
|
-
if (result === "not_found") {
|
|
211
|
-
throwApiError(404, "Conversation not found.");
|
|
212
|
-
}
|
|
213
|
-
if (result === "conflict") {
|
|
214
|
-
throwApiError(409, "Conversation received new activity.");
|
|
215
|
-
}
|
|
216
|
-
return { archived: body.archived };
|
|
302
|
+
} catch (error) {
|
|
303
|
+
throwApiError(500, "Unable to create conversation.", error);
|
|
217
304
|
}
|
|
218
|
-
}
|
|
305
|
+
}
|
|
306
|
+
async function appendConversationMessageForViewer(viewer, conversationId, body) {
|
|
307
|
+
const conversation = await getConversationStore().get({
|
|
308
|
+
conversationId
|
|
309
|
+
});
|
|
310
|
+
if (!conversation) {
|
|
311
|
+
throwApiError(404, "Conversation not found.");
|
|
312
|
+
}
|
|
313
|
+
const destinationPlatform = conversation.destination?.platform;
|
|
314
|
+
const acceptsApiMessages = destinationPlatform === "local" && conversationId.startsWith("local:web:") || destinationPlatform === "slack";
|
|
315
|
+
if (!acceptsApiMessages) {
|
|
316
|
+
throwApiError(409, "Conversation does not accept API messages.");
|
|
317
|
+
}
|
|
318
|
+
const access = await readConversationAccessFromSql(
|
|
319
|
+
getDb(),
|
|
320
|
+
[conversationId],
|
|
321
|
+
viewer
|
|
322
|
+
);
|
|
323
|
+
if (!access.get(conversationId)?.isParticipant) {
|
|
324
|
+
throwApiError(403, "Only conversation participants can add messages.");
|
|
325
|
+
}
|
|
326
|
+
try {
|
|
327
|
+
return await appendAndEnqueueApiConversationMessage(
|
|
328
|
+
{
|
|
329
|
+
actor: actorFromViewer(viewer),
|
|
330
|
+
conversationId,
|
|
331
|
+
idempotencyKey: body.idempotencyKey,
|
|
332
|
+
message: body.message
|
|
333
|
+
},
|
|
334
|
+
{
|
|
335
|
+
conversationStore: getConversationStore(),
|
|
336
|
+
queue: getVercelConversationWorkQueue()
|
|
337
|
+
}
|
|
338
|
+
);
|
|
339
|
+
} catch (error) {
|
|
340
|
+
throwApiError(500, "Unable to append message.", error);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
219
343
|
|
|
220
344
|
// src/chat/slack/source-link.ts
|
|
221
345
|
function parseSlackTeamDomain(value) {
|
|
@@ -332,7 +456,7 @@ async function resolveSlackTeamDomains(teamIds) {
|
|
|
332
456
|
}
|
|
333
457
|
|
|
334
458
|
// src/chat/pi/sql-model-usage.ts
|
|
335
|
-
import { and as and2, eq as
|
|
459
|
+
import { and as and2, eq as eq3, sql } from "drizzle-orm";
|
|
336
460
|
var message = sql`${juniorConversationEvents.payload}`;
|
|
337
461
|
var usage = sql`${message}->'usage'`;
|
|
338
462
|
var cost = sql`${usage}->'cost'`;
|
|
@@ -426,14 +550,14 @@ async function readConversationModelUsageFromSql(executor, options) {
|
|
|
426
550
|
costTotal: summedCost(nonnegativeNumber(cost, "total"))
|
|
427
551
|
}).from(juniorConversationEvents).innerJoin(
|
|
428
552
|
juniorConversations,
|
|
429
|
-
|
|
553
|
+
eq3(
|
|
430
554
|
juniorConversations.conversationId,
|
|
431
555
|
juniorConversationEvents.conversationId
|
|
432
556
|
)
|
|
433
557
|
).where(
|
|
434
558
|
and2(
|
|
435
|
-
options.includeDescendants ?
|
|
436
|
-
|
|
559
|
+
options.includeDescendants ? eq3(juniorConversations.rootConversationId, options.conversationId) : eq3(juniorConversationEvents.conversationId, options.conversationId),
|
|
560
|
+
eq3(juniorConversationEvents.type, "assistant_message"),
|
|
437
561
|
sql`jsonb_typeof(${message}->'provider') = 'string'`,
|
|
438
562
|
sql`jsonb_typeof(${message}->'model') = 'string'`,
|
|
439
563
|
sql`coalesce(${message}->>'provider', '') <> ''`,
|
|
@@ -498,9 +622,9 @@ import {
|
|
|
498
622
|
and as and3,
|
|
499
623
|
asc,
|
|
500
624
|
desc,
|
|
501
|
-
eq as
|
|
625
|
+
eq as eq4,
|
|
502
626
|
getTableColumns,
|
|
503
|
-
inArray,
|
|
627
|
+
inArray as inArray2,
|
|
504
628
|
lt,
|
|
505
629
|
sql as sql2
|
|
506
630
|
} from "drizzle-orm";
|
|
@@ -705,6 +829,7 @@ function reportEventData(args) {
|
|
|
705
829
|
type: "message",
|
|
706
830
|
messageId: data.messageId,
|
|
707
831
|
role: data.role,
|
|
832
|
+
...data.meta?.source === "web" ? { source: "web" } : {},
|
|
708
833
|
...actorIdentity ? { actorIdentity } : {},
|
|
709
834
|
...typeof data.meta?.eventType === "string" ? { eventType: data.meta.eventType } : {},
|
|
710
835
|
...args.canExposePayload ? { text: data.text } : { redacted: true }
|
|
@@ -912,17 +1037,17 @@ async function readConversationEventRows(executor, args) {
|
|
|
912
1037
|
end`
|
|
913
1038
|
}).from(juniorConversationEvents).where(
|
|
914
1039
|
and3(
|
|
915
|
-
|
|
1040
|
+
eq4(juniorConversationEvents.conversationId, args.conversationId),
|
|
916
1041
|
args.beforeSeq === void 0 ? void 0 : lt(juniorConversationEvents.seq, args.beforeSeq),
|
|
917
|
-
|
|
1042
|
+
inArray2(
|
|
918
1043
|
juniorConversationEvents.type,
|
|
919
1044
|
args.types ?? [...conversationReportSourceEventTypes]
|
|
920
1045
|
),
|
|
921
|
-
args.subagentInvocationIds === void 0 ? void 0 :
|
|
1046
|
+
args.subagentInvocationIds === void 0 ? void 0 : inArray2(
|
|
922
1047
|
sql2`${juniorConversationEvents.payload}->>'subagentInvocationId'`,
|
|
923
1048
|
args.subagentInvocationIds
|
|
924
1049
|
),
|
|
925
|
-
args.toolCallIds === void 0 ? void 0 :
|
|
1050
|
+
args.toolCallIds === void 0 ? void 0 : inArray2(
|
|
926
1051
|
sql2`${juniorConversationEvents.payload}->>'toolCallId'`,
|
|
927
1052
|
args.toolCallIds
|
|
928
1053
|
)
|
|
@@ -1043,8 +1168,8 @@ function surfaceFromConversationId(conversationId) {
|
|
|
1043
1168
|
return "internal";
|
|
1044
1169
|
}
|
|
1045
1170
|
function surfaceFromSource(source, conversationId) {
|
|
1046
|
-
if (source === "slack" || source === "api" || source === "scheduler") {
|
|
1047
|
-
return source;
|
|
1171
|
+
if (source === "slack" || source === "api" || source === "web" || source === "scheduler") {
|
|
1172
|
+
return source === "web" ? "api" : source;
|
|
1048
1173
|
}
|
|
1049
1174
|
return surfaceFromConversationId(conversationId);
|
|
1050
1175
|
}
|
|
@@ -1165,6 +1290,7 @@ function conversationSummaryFromStoredConversation(args) {
|
|
|
1165
1290
|
visibility
|
|
1166
1291
|
}),
|
|
1167
1292
|
isParticipant: args.access?.isParticipant ?? false,
|
|
1293
|
+
...visibility ? { visibility } : {},
|
|
1168
1294
|
lastProgressAt: new Date(
|
|
1169
1295
|
conversation.execution.updatedAtMs ?? conversation.updatedAtMs
|
|
1170
1296
|
).toISOString(),
|
|
@@ -1184,59 +1310,6 @@ function conversationSummaryFromStoredConversation(args) {
|
|
|
1184
1310
|
};
|
|
1185
1311
|
}
|
|
1186
1312
|
|
|
1187
|
-
// src/api/conversations/access.ts
|
|
1188
|
-
import { eq as eq4, inArray as inArray2 } from "drizzle-orm";
|
|
1189
|
-
import { alias } from "drizzle-orm/pg-core";
|
|
1190
|
-
var rootConversation = alias(juniorConversations, "access_root_conversation");
|
|
1191
|
-
var rootDestination = alias(juniorDestinations, "access_root_destination");
|
|
1192
|
-
var rootIdentity = alias(juniorIdentities, "access_root_identity");
|
|
1193
|
-
async function readConversationAccessFromSql(db, conversationIds, verifiedViewerEmail) {
|
|
1194
|
-
if (conversationIds.length === 0) return /* @__PURE__ */ new Map();
|
|
1195
|
-
const normalizedViewerEmail = verifiedViewerEmail?.trim().toLowerCase() || void 0;
|
|
1196
|
-
const rows = await db.select({
|
|
1197
|
-
conversationId: juniorConversations.conversationId,
|
|
1198
|
-
parentConversationId: juniorConversations.parentConversationId,
|
|
1199
|
-
storedRootConversationId: juniorConversations.rootConversationId,
|
|
1200
|
-
rootConversationId: rootConversation.conversationId,
|
|
1201
|
-
rootParentConversationId: rootConversation.parentConversationId,
|
|
1202
|
-
rootRootConversationId: rootConversation.rootConversationId,
|
|
1203
|
-
visibility: rootDestination.visibility,
|
|
1204
|
-
rootEmailNormalized: rootIdentity.emailNormalized,
|
|
1205
|
-
rootEmailVerified: rootIdentity.emailVerified
|
|
1206
|
-
}).from(juniorConversations).leftJoin(
|
|
1207
|
-
rootConversation,
|
|
1208
|
-
eq4(
|
|
1209
|
-
rootConversation.conversationId,
|
|
1210
|
-
juniorConversations.rootConversationId
|
|
1211
|
-
)
|
|
1212
|
-
).leftJoin(
|
|
1213
|
-
rootDestination,
|
|
1214
|
-
eq4(rootDestination.id, rootConversation.destinationId)
|
|
1215
|
-
).leftJoin(
|
|
1216
|
-
rootIdentity,
|
|
1217
|
-
eq4(rootIdentity.id, rootConversation.actorIdentityId)
|
|
1218
|
-
).where(inArray2(juniorConversations.conversationId, [...conversationIds]));
|
|
1219
|
-
return new Map(
|
|
1220
|
-
rows.map((row) => {
|
|
1221
|
-
const hasValidRoot = row.rootConversationId !== null && row.rootConversationId === row.storedRootConversationId && row.rootRootConversationId === row.rootConversationId && row.rootParentConversationId === null && (row.parentConversationId !== null || row.storedRootConversationId === row.conversationId);
|
|
1222
|
-
const validRootConversationId = hasValidRoot ? row.rootConversationId ?? void 0 : void 0;
|
|
1223
|
-
const visibility = validRootConversationId === void 0 ? null : row.visibility;
|
|
1224
|
-
const isParticipant = validRootConversationId !== void 0 && normalizedViewerEmail !== void 0 && row.rootEmailVerified === true && row.rootEmailNormalized === normalizedViewerEmail;
|
|
1225
|
-
const canViewPrivateContent = isParticipant || validRootConversationId !== void 0 && canExposeConversationPayload({
|
|
1226
|
-
visibility: visibility ?? void 0
|
|
1227
|
-
});
|
|
1228
|
-
return [
|
|
1229
|
-
row.conversationId,
|
|
1230
|
-
{
|
|
1231
|
-
canViewPrivateContent,
|
|
1232
|
-
isParticipant,
|
|
1233
|
-
visibility
|
|
1234
|
-
}
|
|
1235
|
-
];
|
|
1236
|
-
})
|
|
1237
|
-
);
|
|
1238
|
-
}
|
|
1239
|
-
|
|
1240
1313
|
// src/api/conversations/usage.ts
|
|
1241
1314
|
import { and as and4, eq as eq5, inArray as inArray3, isNull, sql as sql3 } from "drizzle-orm";
|
|
1242
1315
|
import { alias as alias2 } from "drizzle-orm/pg-core";
|
|
@@ -1565,11 +1638,7 @@ async function readConversationFeedFromSql(options = {}) {
|
|
|
1565
1638
|
metricsByRoot,
|
|
1566
1639
|
teamDomainByTeamId
|
|
1567
1640
|
] = await Promise.all([
|
|
1568
|
-
readConversationAccessFromSql(
|
|
1569
|
-
db,
|
|
1570
|
-
conversationIds,
|
|
1571
|
-
options.verifiedViewerEmail
|
|
1572
|
-
),
|
|
1641
|
+
readConversationAccessFromSql(db, conversationIds, options.viewer),
|
|
1573
1642
|
readConversationAuxiliaryCostsFromSql(db, conversationIds, {
|
|
1574
1643
|
includeDescendants: true
|
|
1575
1644
|
}),
|
|
@@ -1603,22 +1672,6 @@ async function readConversationFeed(options = {}) {
|
|
|
1603
1672
|
await readConversationFeedFromSql(options)
|
|
1604
1673
|
);
|
|
1605
1674
|
}
|
|
1606
|
-
var list_default = defineApiRoute({
|
|
1607
|
-
method: "get",
|
|
1608
|
-
path: "/",
|
|
1609
|
-
responseSchema: conversationFeedSchema,
|
|
1610
|
-
handler: async (c) => {
|
|
1611
|
-
const { actorEmail } = parseQuery(
|
|
1612
|
-
conversationFeedQuerySchema,
|
|
1613
|
-
c.req.query()
|
|
1614
|
-
);
|
|
1615
|
-
const verifiedViewerEmail = c.get("verifiedViewerEmail");
|
|
1616
|
-
return readConversationFeed({
|
|
1617
|
-
...actorEmail ? { actorEmail } : {},
|
|
1618
|
-
...verifiedViewerEmail ? { verifiedViewerEmail } : {}
|
|
1619
|
-
});
|
|
1620
|
-
}
|
|
1621
|
-
});
|
|
1622
1675
|
|
|
1623
1676
|
// src/chat/tasks/read.ts
|
|
1624
1677
|
import { and as and7, eq as eq8, or as or2 } from "drizzle-orm";
|
|
@@ -2086,12 +2139,9 @@ async function readConversationSourceTask(args) {
|
|
|
2086
2139
|
conversationId: args.conversationId
|
|
2087
2140
|
});
|
|
2088
2141
|
if (!execution) return void 0;
|
|
2089
|
-
|
|
2090
|
-
if (!email) return { kind: execution.kind };
|
|
2091
|
-
const user = await resolveViewerUser(email);
|
|
2092
|
-
if (!user) return { kind: execution.kind };
|
|
2142
|
+
if (!args.viewer) return { kind: execution.kind };
|
|
2093
2143
|
const candidate = await resolveViewerTaskCandidate(
|
|
2094
|
-
|
|
2144
|
+
args.viewer,
|
|
2095
2145
|
execution.kind,
|
|
2096
2146
|
execution.taskId
|
|
2097
2147
|
);
|
|
@@ -2199,11 +2249,7 @@ async function readConversationDetailFromSql(conversationId, options) {
|
|
|
2199
2249
|
sourceTask,
|
|
2200
2250
|
teamDomainByTeamId
|
|
2201
2251
|
] = await Promise.all([
|
|
2202
|
-
readConversationAccessFromSql(
|
|
2203
|
-
getDb(),
|
|
2204
|
-
[conversationId],
|
|
2205
|
-
options.verifiedViewerEmail
|
|
2206
|
-
),
|
|
2252
|
+
readConversationAccessFromSql(getDb(), [conversationId], options.viewer),
|
|
2207
2253
|
listConversationAnnotations(getDb(), conversationId),
|
|
2208
2254
|
readConversationAuxiliaryCostsFromSql(getDb(), [conversationId], {
|
|
2209
2255
|
includeDescendants: includeDescendantMetrics
|
|
@@ -2218,7 +2264,7 @@ async function readConversationDetailFromSql(conversationId, options) {
|
|
|
2218
2264
|
),
|
|
2219
2265
|
readConversationSourceTask({
|
|
2220
2266
|
conversationId,
|
|
2221
|
-
...options.
|
|
2267
|
+
...options.viewer ? { viewer: options.viewer } : {}
|
|
2222
2268
|
}),
|
|
2223
2269
|
resolveSlackTeamDomains(
|
|
2224
2270
|
record.conversation.sessionSource?.platform === "slack" ? [record.conversation.sessionSource.teamId] : []
|
|
@@ -2252,25 +2298,6 @@ async function readConversationDetail(conversationId, options = {}) {
|
|
|
2252
2298
|
});
|
|
2253
2299
|
return report ? conversationDetailReportSchema.parse(report) : void 0;
|
|
2254
2300
|
}
|
|
2255
|
-
var detail_default = defineApiRoute({
|
|
2256
|
-
method: "get",
|
|
2257
|
-
path: "/:conversationId",
|
|
2258
|
-
responseSchema: conversationDetailReportSchema,
|
|
2259
|
-
handler: async (c) => {
|
|
2260
|
-
const { conversationId } = parseParams(
|
|
2261
|
-
conversationParamsSchema,
|
|
2262
|
-
c.req.param()
|
|
2263
|
-
);
|
|
2264
|
-
const query = parseQuery(conversationDetailQuerySchema, c.req.query());
|
|
2265
|
-
const verifiedViewerEmail = c.get("verifiedViewerEmail");
|
|
2266
|
-
const report = await readConversationDetail(conversationId, {
|
|
2267
|
-
...query,
|
|
2268
|
-
...verifiedViewerEmail ? { verifiedViewerEmail } : {}
|
|
2269
|
-
});
|
|
2270
|
-
if (!report) throwApiError(404, "Conversation not found.");
|
|
2271
|
-
return report;
|
|
2272
|
-
}
|
|
2273
|
-
});
|
|
2274
2301
|
|
|
2275
2302
|
// src/api/conversations/event-list.ts
|
|
2276
2303
|
async function readConversationEvents(conversationId, beforeValue, options = {}) {
|
|
@@ -2284,7 +2311,7 @@ async function readConversationEvents(conversationId, beforeValue, options = {})
|
|
|
2284
2311
|
const accessByConversation = await readConversationAccessFromSql(
|
|
2285
2312
|
getDb(),
|
|
2286
2313
|
[conversationId],
|
|
2287
|
-
options.
|
|
2314
|
+
options.viewer
|
|
2288
2315
|
);
|
|
2289
2316
|
const access = accessByConversation.get(conversationId);
|
|
2290
2317
|
const canExposePayload = access?.canViewPrivateContent ?? false;
|
|
@@ -2310,28 +2337,119 @@ async function readConversationEvents(conversationId, beforeValue, options = {})
|
|
|
2310
2337
|
generatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
2311
2338
|
});
|
|
2312
2339
|
}
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2340
|
+
|
|
2341
|
+
// src/api/conversations/pending-messages.ts
|
|
2342
|
+
import { z as z4 } from "zod";
|
|
2343
|
+
var apiTurnMailboxMetadataSchema = z4.object({
|
|
2344
|
+
authorEmail: z4.string().email(),
|
|
2345
|
+
authorFullName: z4.string().min(1).optional(),
|
|
2346
|
+
authorUserId: z4.string().min(1),
|
|
2347
|
+
authorUserName: z4.string().min(1).optional(),
|
|
2348
|
+
kind: z4.literal("api_turn"),
|
|
2349
|
+
messageId: z4.string().min(1)
|
|
2350
|
+
}).strict();
|
|
2351
|
+
var slackMailboxAuthorSchema = z4.object({
|
|
2352
|
+
userId: z4.string(),
|
|
2353
|
+
userName: z4.string().optional(),
|
|
2354
|
+
fullName: z4.string().optional(),
|
|
2355
|
+
isMe: z4.boolean().optional()
|
|
2356
|
+
}).passthrough();
|
|
2357
|
+
var slackMailboxMessageSchema = z4.object({
|
|
2358
|
+
author: slackMailboxAuthorSchema,
|
|
2359
|
+
id: z4.string().min(1)
|
|
2360
|
+
}).passthrough();
|
|
2361
|
+
var slackMailboxMetadataSchema = z4.object({
|
|
2362
|
+
message: slackMailboxMessageSchema,
|
|
2363
|
+
platform: z4.literal("slack")
|
|
2364
|
+
}).passthrough();
|
|
2365
|
+
function isoFromMs(value) {
|
|
2366
|
+
return new Date(value).toISOString();
|
|
2367
|
+
}
|
|
2368
|
+
function actorIdentityFromApiMetadata(metadata2) {
|
|
2369
|
+
return {
|
|
2370
|
+
email: metadata2.authorEmail.trim().toLowerCase(),
|
|
2371
|
+
...metadata2.authorFullName ? { fullName: metadata2.authorFullName } : {}
|
|
2372
|
+
};
|
|
2373
|
+
}
|
|
2374
|
+
function actorIdentityFromSlackMetadata(metadata2) {
|
|
2375
|
+
if (metadata2.message.author.isMe === true) return void 0;
|
|
2376
|
+
const slackUserId = metadata2.message.author.userId.trim();
|
|
2377
|
+
if (!slackUserId) return void 0;
|
|
2378
|
+
const slackUserName = metadata2.message.author.userName?.trim();
|
|
2379
|
+
const fullName = metadata2.message.author.fullName?.trim();
|
|
2380
|
+
return {
|
|
2381
|
+
slackUserId,
|
|
2382
|
+
...slackUserName ? { slackUserName } : {},
|
|
2383
|
+
...fullName ? { fullName } : {}
|
|
2384
|
+
};
|
|
2385
|
+
}
|
|
2386
|
+
function projectPendingMessage(message2, canExposePayload) {
|
|
2387
|
+
if (message2.source === "web") {
|
|
2388
|
+
const metadata2 = apiTurnMailboxMetadataSchema.safeParse(
|
|
2389
|
+
message2.input.metadata
|
|
2321
2390
|
);
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2391
|
+
if (!metadata2.success) return void 0;
|
|
2392
|
+
const text = message2.input.text.trim();
|
|
2393
|
+
if (!text) return void 0;
|
|
2394
|
+
return {
|
|
2395
|
+
createdAt: isoFromMs(message2.createdAtMs),
|
|
2396
|
+
delivery: message2.delivery,
|
|
2397
|
+
inboundMessageId: message2.inboundMessageId,
|
|
2398
|
+
messageId: metadata2.data.messageId,
|
|
2399
|
+
receivedAt: isoFromMs(message2.receivedAtMs),
|
|
2400
|
+
role: "user",
|
|
2401
|
+
source: "web",
|
|
2402
|
+
...canExposePayload ? {
|
|
2403
|
+
actorIdentity: actorIdentityFromApiMetadata(metadata2.data),
|
|
2404
|
+
text
|
|
2405
|
+
} : { redacted: true }
|
|
2406
|
+
};
|
|
2407
|
+
}
|
|
2408
|
+
if (message2.source === "slack") {
|
|
2409
|
+
const metadata2 = slackMailboxMetadataSchema.safeParse(
|
|
2410
|
+
message2.input.metadata
|
|
2325
2411
|
);
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2412
|
+
if (!metadata2.success) return void 0;
|
|
2413
|
+
if (metadata2.data.message.author.isMe === true) return void 0;
|
|
2414
|
+
const text = message2.input.text.trim();
|
|
2415
|
+
if (!text) return void 0;
|
|
2416
|
+
const actorIdentity = actorIdentityFromSlackMetadata(metadata2.data);
|
|
2417
|
+
return {
|
|
2418
|
+
createdAt: isoFromMs(message2.createdAtMs),
|
|
2419
|
+
delivery: message2.delivery,
|
|
2420
|
+
inboundMessageId: message2.inboundMessageId,
|
|
2421
|
+
messageId: metadata2.data.message.id,
|
|
2422
|
+
receivedAt: isoFromMs(message2.receivedAtMs),
|
|
2423
|
+
role: "user",
|
|
2424
|
+
source: "slack",
|
|
2425
|
+
...canExposePayload ? {
|
|
2426
|
+
...actorIdentity ? { actorIdentity } : {},
|
|
2427
|
+
text
|
|
2428
|
+
} : { redacted: true }
|
|
2429
|
+
};
|
|
2333
2430
|
}
|
|
2334
|
-
|
|
2431
|
+
return void 0;
|
|
2432
|
+
}
|
|
2433
|
+
async function readConversationPendingMessages(conversationId, options = {}) {
|
|
2434
|
+
const conversation = await getConversationStore().get({ conversationId });
|
|
2435
|
+
if (!conversation) return void 0;
|
|
2436
|
+
const access = (await readConversationAccessFromSql(getDb(), [conversationId], options.viewer)).get(conversationId);
|
|
2437
|
+
const canExposePayload = access?.canViewPrivateContent ?? false;
|
|
2438
|
+
const work = await getConversation({ conversationId });
|
|
2439
|
+
const messages = (work?.execution.pendingMessages ?? []).map((message2) => projectPendingMessage(message2, canExposePayload)).filter(
|
|
2440
|
+
(message2) => Boolean(message2)
|
|
2441
|
+
);
|
|
2442
|
+
return conversationPendingMessagesReportSchema.parse({
|
|
2443
|
+
conversationId,
|
|
2444
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2445
|
+
messages
|
|
2446
|
+
});
|
|
2447
|
+
}
|
|
2448
|
+
async function requireConversationPendingMessages(conversationId, options = {}) {
|
|
2449
|
+
const report = await readConversationPendingMessages(conversationId, options);
|
|
2450
|
+
if (!report) throwApiError(404, "Conversation not found.");
|
|
2451
|
+
return report;
|
|
2452
|
+
}
|
|
2335
2453
|
|
|
2336
2454
|
// src/api/conversations/stats.query.ts
|
|
2337
2455
|
import { and as and8, eq as eq9, gte, isNull as isNull4, lte, sql as sql6 } from "drizzle-orm";
|
|
@@ -2339,6 +2457,13 @@ import { alias as alias4 } from "drizzle-orm/pg-core";
|
|
|
2339
2457
|
|
|
2340
2458
|
// src/api/conversations/aggregate.ts
|
|
2341
2459
|
import { sql as sql5 } from "drizzle-orm";
|
|
2460
|
+
function usageTokenValue(source, field) {
|
|
2461
|
+
return sql5`CASE
|
|
2462
|
+
WHEN ${source.usage}->>${field} IS NOT NULL
|
|
2463
|
+
THEN (${source.usage}->>${field})::double precision
|
|
2464
|
+
ELSE NULL
|
|
2465
|
+
END`;
|
|
2466
|
+
}
|
|
2342
2467
|
function tokenValue(source) {
|
|
2343
2468
|
return sql5`
|
|
2344
2469
|
CASE
|
|
@@ -2386,11 +2511,13 @@ function conversationAggregateColumns(sources) {
|
|
|
2386
2511
|
WHERE ${roots.executionStatus} NOT IN ('idle', 'failed')
|
|
2387
2512
|
)::integer`,
|
|
2388
2513
|
conversations: sql5`${conversationCount}::integer`,
|
|
2514
|
+
cachedInputTokens: sql5`SUM(${usageTokenValue(metrics, "cachedInputTokens")})::double precision`,
|
|
2389
2515
|
costUsd: sql5`SUM(${costValue(metrics)})::double precision`,
|
|
2390
2516
|
durationMs: sql5`COALESCE(SUM(${metrics.durationMs}), 0)::double precision`,
|
|
2391
2517
|
failed: sql5`${conversationCount} FILTER (
|
|
2392
2518
|
WHERE ${roots.executionStatus} = 'failed'
|
|
2393
2519
|
)::integer`,
|
|
2520
|
+
inputTokens: sql5`SUM(${usageTokenValue(metrics, "inputTokens")})::double precision`,
|
|
2394
2521
|
tokens: sql5`SUM(${tokenValue(metrics)})::double precision`
|
|
2395
2522
|
};
|
|
2396
2523
|
}
|
|
@@ -2432,7 +2559,7 @@ function actorLabel(row) {
|
|
|
2432
2559
|
}
|
|
2433
2560
|
function surfaceLabel(source) {
|
|
2434
2561
|
if (source === "scheduler") return "Scheduler";
|
|
2435
|
-
if (source === "api") return "
|
|
2562
|
+
if (source === "api" || source === "web") return "Web";
|
|
2436
2563
|
if (source === "internal" || source === "local") return "Internal";
|
|
2437
2564
|
return "Conversation";
|
|
2438
2565
|
}
|
|
@@ -2496,7 +2623,9 @@ function metricDays(rows, endMs) {
|
|
|
2496
2623
|
conversations: row?.conversations ?? 0,
|
|
2497
2624
|
date,
|
|
2498
2625
|
durationMs: row?.durationMs ?? 0,
|
|
2626
|
+
...row?.cachedInputTokens !== null && row?.cachedInputTokens !== void 0 ? { cachedInputTokens: row.cachedInputTokens } : {},
|
|
2499
2627
|
...row?.costUsd !== null && row?.costUsd !== void 0 ? { costUsd: addUsd(void 0, row.costUsd) } : {},
|
|
2628
|
+
...row?.inputTokens !== null && row?.inputTokens !== void 0 ? { inputTokens: row.inputTokens } : {},
|
|
2500
2629
|
...row?.tokens !== null && row?.tokens !== void 0 ? { tokens: row.tokens } : {}
|
|
2501
2630
|
});
|
|
2502
2631
|
}
|
|
@@ -2607,10 +2736,12 @@ async function aggregateStats(db, start, end) {
|
|
|
2607
2736
|
juniorDestinations.visibility
|
|
2608
2737
|
),
|
|
2609
2738
|
db.select({
|
|
2739
|
+
cachedInputTokens: treeAggregateColumns.cachedInputTokens,
|
|
2610
2740
|
conversations: treeAggregateColumns.conversations,
|
|
2611
2741
|
costUsd: treeAggregateColumns.costUsd,
|
|
2612
2742
|
date: activityDate,
|
|
2613
2743
|
durationMs: treeAggregateColumns.durationMs,
|
|
2744
|
+
inputTokens: treeAggregateColumns.inputTokens,
|
|
2614
2745
|
tokens: treeAggregateColumns.tokens
|
|
2615
2746
|
}).from(juniorConversations).innerJoin(
|
|
2616
2747
|
treeConversation,
|
|
@@ -2666,6 +2797,7 @@ async function readConversationStatsFromSql() {
|
|
|
2666
2797
|
}
|
|
2667
2798
|
return {
|
|
2668
2799
|
active: totals?.active ?? 0,
|
|
2800
|
+
...totals?.cachedInputTokens !== null && totals?.cachedInputTokens !== void 0 ? { cachedInputTokens: totals.cachedInputTokens } : {},
|
|
2669
2801
|
conversations: totals?.conversations ?? 0,
|
|
2670
2802
|
durationMs: totals?.durationMs ?? 0,
|
|
2671
2803
|
failed: totals?.failed ?? 0,
|
|
@@ -2676,6 +2808,7 @@ async function readConversationStatsFromSql() {
|
|
|
2676
2808
|
actors: statsItems(actors),
|
|
2677
2809
|
source: "conversation_index",
|
|
2678
2810
|
...totals?.costUsd !== null && totals?.costUsd !== void 0 ? { costUsd: addUsd(void 0, totals.costUsd) } : {},
|
|
2811
|
+
...totals?.inputTokens !== null && totals?.inputTokens !== void 0 ? { inputTokens: totals.inputTokens } : {},
|
|
2679
2812
|
...totals?.tokens !== null && totals?.tokens !== void 0 ? { tokens: totals.tokens } : {},
|
|
2680
2813
|
windowEnd: end.toISOString(),
|
|
2681
2814
|
windowStart: start.toISOString()
|
|
@@ -2688,93 +2821,162 @@ async function readConversationStats() {
|
|
|
2688
2821
|
await readConversationStatsFromSql()
|
|
2689
2822
|
);
|
|
2690
2823
|
}
|
|
2691
|
-
var stats_default = defineApiRoute({
|
|
2692
|
-
method: "get",
|
|
2693
|
-
path: "/stats",
|
|
2694
|
-
responseSchema: conversationStatsReportSchema,
|
|
2695
|
-
handler: readConversationStats
|
|
2696
|
-
});
|
|
2697
2824
|
|
|
2698
2825
|
// src/api/conversations/routes.ts
|
|
2699
|
-
var routes = [
|
|
2700
|
-
list_default,
|
|
2701
|
-
stats_default,
|
|
2702
|
-
archive_default,
|
|
2703
|
-
event_list_default,
|
|
2704
|
-
detail_default
|
|
2705
|
-
];
|
|
2706
2826
|
function createConversationRoutes() {
|
|
2707
2827
|
const app = new Hono();
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
|
|
2718
|
-
|
|
2719
|
-
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
}
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
return skillReportsSchema.parse(
|
|
2727
|
-
skills.map((skill) => ({
|
|
2728
|
-
name: skill.name,
|
|
2729
|
-
pluginProvider: skill.pluginProvider
|
|
2730
|
-
}))
|
|
2828
|
+
app.get(
|
|
2829
|
+
"/",
|
|
2830
|
+
validateRequest(
|
|
2831
|
+
"query",
|
|
2832
|
+
conversationFeedQuerySchema,
|
|
2833
|
+
"Invalid query parameters."
|
|
2834
|
+
),
|
|
2835
|
+
async (context) => {
|
|
2836
|
+
const { actorEmail } = context.req.valid("query");
|
|
2837
|
+
const viewer = context.get("viewer");
|
|
2838
|
+
return jsonResponse(
|
|
2839
|
+
conversationFeedSchema,
|
|
2840
|
+
await readConversationFeed({
|
|
2841
|
+
...actorEmail ? { actorEmail } : {},
|
|
2842
|
+
...viewer ? { viewer } : {}
|
|
2843
|
+
})
|
|
2844
|
+
);
|
|
2845
|
+
}
|
|
2731
2846
|
);
|
|
2732
|
-
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
return pluginsSchema.parse(
|
|
2736
|
-
pluginCatalogRuntime.getProviders().map((plugin) => ({
|
|
2737
|
-
configKeys: plugin.manifest.configKeys ?? [],
|
|
2738
|
-
description: plugin.manifest.description,
|
|
2739
|
-
displayName: plugin.manifest.displayName,
|
|
2740
|
-
name: plugin.manifest.name
|
|
2741
|
-
}))
|
|
2847
|
+
app.get(
|
|
2848
|
+
"/stats",
|
|
2849
|
+
async () => jsonResponse(conversationStatsReportSchema, await readConversationStats())
|
|
2742
2850
|
);
|
|
2851
|
+
app.post(
|
|
2852
|
+
"/",
|
|
2853
|
+
requireViewer,
|
|
2854
|
+
validateRequest(
|
|
2855
|
+
"json",
|
|
2856
|
+
createConversationBodySchema,
|
|
2857
|
+
"Invalid request body."
|
|
2858
|
+
),
|
|
2859
|
+
async (context) => {
|
|
2860
|
+
const viewer = context.get("viewer");
|
|
2861
|
+
const body = context.req.valid("json");
|
|
2862
|
+
return jsonResponse(
|
|
2863
|
+
acceptedConversationMessageSchema,
|
|
2864
|
+
await createConversationForViewer(viewer, body)
|
|
2865
|
+
);
|
|
2866
|
+
}
|
|
2867
|
+
);
|
|
2868
|
+
app.post(
|
|
2869
|
+
"/:conversationId/messages",
|
|
2870
|
+
requireViewer,
|
|
2871
|
+
validateRequest(
|
|
2872
|
+
"param",
|
|
2873
|
+
conversationParamsSchema,
|
|
2874
|
+
"Invalid route parameters."
|
|
2875
|
+
),
|
|
2876
|
+
validateRequest(
|
|
2877
|
+
"json",
|
|
2878
|
+
createConversationMessageBodySchema,
|
|
2879
|
+
"Invalid request body."
|
|
2880
|
+
),
|
|
2881
|
+
async (context) => {
|
|
2882
|
+
const viewer = context.get("viewer");
|
|
2883
|
+
const { conversationId } = context.req.valid("param");
|
|
2884
|
+
const body = context.req.valid("json");
|
|
2885
|
+
return jsonResponse(
|
|
2886
|
+
acceptedConversationMessageSchema,
|
|
2887
|
+
await appendConversationMessageForViewer(viewer, conversationId, body)
|
|
2888
|
+
);
|
|
2889
|
+
}
|
|
2890
|
+
);
|
|
2891
|
+
app.patch(
|
|
2892
|
+
"/:conversationId/archive",
|
|
2893
|
+
validateRequest(
|
|
2894
|
+
"param",
|
|
2895
|
+
conversationParamsSchema,
|
|
2896
|
+
"Invalid route parameters."
|
|
2897
|
+
),
|
|
2898
|
+
validateRequest(
|
|
2899
|
+
"json",
|
|
2900
|
+
archiveConversationBodySchema,
|
|
2901
|
+
"Invalid request body."
|
|
2902
|
+
),
|
|
2903
|
+
async (context) => {
|
|
2904
|
+
const { conversationId } = context.req.valid("param");
|
|
2905
|
+
const body = context.req.valid("json");
|
|
2906
|
+
return jsonResponse(
|
|
2907
|
+
archiveConversationResponseSchema,
|
|
2908
|
+
await archiveConversation(conversationId, body)
|
|
2909
|
+
);
|
|
2910
|
+
}
|
|
2911
|
+
);
|
|
2912
|
+
app.get(
|
|
2913
|
+
"/:conversationId/events",
|
|
2914
|
+
validateRequest(
|
|
2915
|
+
"param",
|
|
2916
|
+
conversationParamsSchema,
|
|
2917
|
+
"Invalid route parameters."
|
|
2918
|
+
),
|
|
2919
|
+
validateRequest(
|
|
2920
|
+
"query",
|
|
2921
|
+
conversationEventsQuerySchema,
|
|
2922
|
+
"Invalid query parameters."
|
|
2923
|
+
),
|
|
2924
|
+
async (context) => {
|
|
2925
|
+
const { conversationId } = context.req.valid("param");
|
|
2926
|
+
const { before, limit } = context.req.valid("query");
|
|
2927
|
+
const viewer = context.get("viewer");
|
|
2928
|
+
const report = await readConversationEvents(conversationId, before, {
|
|
2929
|
+
limit,
|
|
2930
|
+
...viewer ? { viewer } : {}
|
|
2931
|
+
});
|
|
2932
|
+
if (!report) throwApiError(404, "Conversation not found.");
|
|
2933
|
+
return jsonResponse(conversationEventPageSchema, report);
|
|
2934
|
+
}
|
|
2935
|
+
);
|
|
2936
|
+
app.get(
|
|
2937
|
+
"/:conversationId/pending-messages",
|
|
2938
|
+
validateRequest(
|
|
2939
|
+
"param",
|
|
2940
|
+
conversationParamsSchema,
|
|
2941
|
+
"Invalid route parameters."
|
|
2942
|
+
),
|
|
2943
|
+
async (context) => {
|
|
2944
|
+
const { conversationId } = context.req.valid("param");
|
|
2945
|
+
const viewer = context.get("viewer");
|
|
2946
|
+
return jsonResponse(
|
|
2947
|
+
conversationPendingMessagesReportSchema,
|
|
2948
|
+
await requireConversationPendingMessages(conversationId, {
|
|
2949
|
+
viewer
|
|
2950
|
+
})
|
|
2951
|
+
);
|
|
2952
|
+
}
|
|
2953
|
+
);
|
|
2954
|
+
app.get(
|
|
2955
|
+
"/:conversationId",
|
|
2956
|
+
validateRequest(
|
|
2957
|
+
"param",
|
|
2958
|
+
conversationParamsSchema,
|
|
2959
|
+
"Invalid route parameters."
|
|
2960
|
+
),
|
|
2961
|
+
validateRequest(
|
|
2962
|
+
"query",
|
|
2963
|
+
conversationDetailQuerySchema,
|
|
2964
|
+
"Invalid query parameters."
|
|
2965
|
+
),
|
|
2966
|
+
async (context) => {
|
|
2967
|
+
const { conversationId } = context.req.valid("param");
|
|
2968
|
+
const query = context.req.valid("query");
|
|
2969
|
+
const viewer = context.get("viewer");
|
|
2970
|
+
const report = await readConversationDetail(conversationId, {
|
|
2971
|
+
...query,
|
|
2972
|
+
...viewer ? { viewer } : {}
|
|
2973
|
+
});
|
|
2974
|
+
if (!report) throwApiError(404, "Conversation not found.");
|
|
2975
|
+
return jsonResponse(conversationDetailReportSchema, report);
|
|
2976
|
+
}
|
|
2977
|
+
);
|
|
2978
|
+
return app;
|
|
2743
2979
|
}
|
|
2744
|
-
async function readRuntimeInfoReport() {
|
|
2745
|
-
const [{ homeDir }, { pluginCatalogRuntime }, plugins, skills] = await Promise.all([
|
|
2746
|
-
import("./discovery-GUFTFBTL.js"),
|
|
2747
|
-
import("./catalog-runtime-M6ZTPYRV.js"),
|
|
2748
|
-
readPlugins(),
|
|
2749
|
-
readSkillReports()
|
|
2750
|
-
]);
|
|
2751
|
-
const home = homeDir();
|
|
2752
|
-
return runtimeInfoReportSchema.parse({
|
|
2753
|
-
cwd: process.cwd(),
|
|
2754
|
-
homeDir: home,
|
|
2755
|
-
descriptionText: readDescriptionText(home),
|
|
2756
|
-
providers: plugins.map((plugin) => plugin.name),
|
|
2757
|
-
skills,
|
|
2758
|
-
packagedContent: pluginCatalogRuntime.getPackageContent()
|
|
2759
|
-
});
|
|
2760
|
-
}
|
|
2761
|
-
async function readPluginOperationalReportFeed() {
|
|
2762
|
-
const nowMs = Date.now();
|
|
2763
|
-
const { getPluginOperationalReports } = await import("./agent-hooks-HS6VGUPM.js");
|
|
2764
|
-
return pluginOperationalReportFeedSchema.parse({
|
|
2765
|
-
source: "plugins",
|
|
2766
|
-
generatedAt: new Date(nowMs).toISOString(),
|
|
2767
|
-
reports: await getPluginOperationalReports(nowMs)
|
|
2768
|
-
});
|
|
2769
|
-
}
|
|
2770
|
-
|
|
2771
|
-
// src/api/health.ts
|
|
2772
|
-
var health_default = defineApiRoute({
|
|
2773
|
-
method: "get",
|
|
2774
|
-
path: "/api/health",
|
|
2775
|
-
responseSchema: healthReportSchema,
|
|
2776
|
-
handler: readHealthReport
|
|
2777
|
-
});
|
|
2778
2980
|
|
|
2779
2981
|
// src/api/locations/routes.ts
|
|
2780
2982
|
import { Hono as Hono2 } from "hono";
|
|
@@ -3175,7 +3377,7 @@ async function readLocationDetailFromSql(locationId, options = {}) {
|
|
|
3175
3377
|
readConversationAccessFromSql(
|
|
3176
3378
|
getDb(),
|
|
3177
3379
|
recentConversationIds,
|
|
3178
|
-
options.
|
|
3380
|
+
options.viewer
|
|
3179
3381
|
),
|
|
3180
3382
|
readRootConversationMetricsFromSql(getDb(), recentConversationIds)
|
|
3181
3383
|
]);
|
|
@@ -3203,21 +3405,6 @@ async function readLocationDetail(locationId, options = {}) {
|
|
|
3203
3405
|
const report = await readLocationDetailFromSql(locationId, options);
|
|
3204
3406
|
return report ? locationDetailReportSchema.parse(report) : void 0;
|
|
3205
3407
|
}
|
|
3206
|
-
var detail_default2 = defineApiRoute({
|
|
3207
|
-
method: "get",
|
|
3208
|
-
path: "/:locationId",
|
|
3209
|
-
responseSchema: locationDetailReportSchema,
|
|
3210
|
-
handler: async (c) => {
|
|
3211
|
-
const { locationId } = parseParams(locationParamsSchema, c.req.param());
|
|
3212
|
-
const verifiedViewerEmail = c.get("verifiedViewerEmail");
|
|
3213
|
-
const report = await readLocationDetail(
|
|
3214
|
-
locationId,
|
|
3215
|
-
verifiedViewerEmail ? { verifiedViewerEmail } : {}
|
|
3216
|
-
);
|
|
3217
|
-
if (!report) throwApiError(404, "Location not found.");
|
|
3218
|
-
return report;
|
|
3219
|
-
}
|
|
3220
|
-
});
|
|
3221
3408
|
|
|
3222
3409
|
// src/api/locations/list.ts
|
|
3223
3410
|
async function readLocationDirectory() {
|
|
@@ -3225,18 +3412,32 @@ async function readLocationDirectory() {
|
|
|
3225
3412
|
await readLocationDirectoryFromSql()
|
|
3226
3413
|
);
|
|
3227
3414
|
}
|
|
3228
|
-
var list_default2 = defineApiRoute({
|
|
3229
|
-
method: "get",
|
|
3230
|
-
path: "/",
|
|
3231
|
-
responseSchema: locationDirectoryReportSchema,
|
|
3232
|
-
handler: readLocationDirectory
|
|
3233
|
-
});
|
|
3234
3415
|
|
|
3235
3416
|
// src/api/locations/routes.ts
|
|
3236
|
-
var routes2 = [list_default2, detail_default2];
|
|
3237
3417
|
function createLocationRoutes() {
|
|
3238
3418
|
const app = new Hono2();
|
|
3239
|
-
|
|
3419
|
+
app.get(
|
|
3420
|
+
"/",
|
|
3421
|
+
async () => jsonResponse(locationDirectoryReportSchema, await readLocationDirectory())
|
|
3422
|
+
);
|
|
3423
|
+
app.get(
|
|
3424
|
+
"/:locationId",
|
|
3425
|
+
validateRequest(
|
|
3426
|
+
"param",
|
|
3427
|
+
locationParamsSchema,
|
|
3428
|
+
"Invalid route parameters."
|
|
3429
|
+
),
|
|
3430
|
+
async (context) => {
|
|
3431
|
+
const { locationId } = context.req.valid("param");
|
|
3432
|
+
const viewer = context.get("viewer");
|
|
3433
|
+
const report = await readLocationDetail(
|
|
3434
|
+
locationId,
|
|
3435
|
+
viewer ? { viewer } : {}
|
|
3436
|
+
);
|
|
3437
|
+
if (!report) throwApiError(404, "Location not found.");
|
|
3438
|
+
return jsonResponse(locationDetailReportSchema, report);
|
|
3439
|
+
}
|
|
3440
|
+
);
|
|
3240
3441
|
return app;
|
|
3241
3442
|
}
|
|
3242
3443
|
|
|
@@ -3474,12 +3675,6 @@ async function readPeopleListFromSql() {
|
|
|
3474
3675
|
async function readPeopleList() {
|
|
3475
3676
|
return actorDirectoryReportSchema.parse(await readPeopleListFromSql());
|
|
3476
3677
|
}
|
|
3477
|
-
var list_default3 = defineApiRoute({
|
|
3478
|
-
method: "get",
|
|
3479
|
-
path: "/",
|
|
3480
|
-
responseSchema: actorDirectoryReportSchema,
|
|
3481
|
-
handler: readPeopleList
|
|
3482
|
-
});
|
|
3483
3678
|
|
|
3484
3679
|
// src/api/people/profile.query.ts
|
|
3485
3680
|
import { and as and12, eq as eq13, gte as gte4, sql as sql10 } from "drizzle-orm";
|
|
@@ -3631,7 +3826,7 @@ async function readPeopleProfileFromSql(email, options = {}) {
|
|
|
3631
3826
|
readConversationAccessFromSql(
|
|
3632
3827
|
getDb(),
|
|
3633
3828
|
recentConversationIds,
|
|
3634
|
-
options.
|
|
3829
|
+
options.viewer
|
|
3635
3830
|
),
|
|
3636
3831
|
readRootConversationMetricsFromSql(getDb(), recentConversationIds)
|
|
3637
3832
|
]);
|
|
@@ -3667,19 +3862,6 @@ async function readPeopleProfile(email, options = {}) {
|
|
|
3667
3862
|
await readPeopleProfileFromSql(email, options)
|
|
3668
3863
|
);
|
|
3669
3864
|
}
|
|
3670
|
-
var profile_default = defineApiRoute({
|
|
3671
|
-
method: "get",
|
|
3672
|
-
path: "/:email",
|
|
3673
|
-
responseSchema: actorProfileReportSchema,
|
|
3674
|
-
handler: async (c) => {
|
|
3675
|
-
const { email } = parseParams(personParamsSchema, c.req.param());
|
|
3676
|
-
const verifiedViewerEmail = c.get("verifiedViewerEmail");
|
|
3677
|
-
return readPeopleProfile(
|
|
3678
|
-
email,
|
|
3679
|
-
verifiedViewerEmail ? { verifiedViewerEmail } : {}
|
|
3680
|
-
);
|
|
3681
|
-
}
|
|
3682
|
-
});
|
|
3683
3865
|
|
|
3684
3866
|
// src/api/people/spend.query.ts
|
|
3685
3867
|
import { and as and13, eq as eq14, gte as gte5, lte as lte2, sql as sql11 } from "drizzle-orm";
|
|
@@ -3741,9 +3923,9 @@ async function readPersonalSpendFromSql(email, nowMs = Date.now()) {
|
|
|
3741
3923
|
|
|
3742
3924
|
// src/api/people/spend.ts
|
|
3743
3925
|
var PERSONAL_SPEND_CACHE_TTL_MS = 5 * 6e4;
|
|
3744
|
-
function
|
|
3926
|
+
function createPersonalSpendReader() {
|
|
3745
3927
|
const cache = /* @__PURE__ */ new Map();
|
|
3746
|
-
async function
|
|
3928
|
+
return async function readPersonalSpend(email) {
|
|
3747
3929
|
const normalizedEmail = email.trim().toLowerCase();
|
|
3748
3930
|
const nowMs = Date.now();
|
|
3749
3931
|
const cached = cache.get(normalizedEmail);
|
|
@@ -3763,39 +3945,39 @@ function createPersonalSpendRoute() {
|
|
|
3763
3945
|
if (cache.get(normalizedEmail) === entry) cache.delete(normalizedEmail);
|
|
3764
3946
|
throw error;
|
|
3765
3947
|
}
|
|
3766
|
-
}
|
|
3767
|
-
return defineApiRoute({
|
|
3768
|
-
method: "get",
|
|
3769
|
-
path: "/me/spend",
|
|
3770
|
-
responseSchema: personalSpendReportSchema,
|
|
3771
|
-
handler: async (context) => {
|
|
3772
|
-
const email = context.get("verifiedViewerEmail");
|
|
3773
|
-
if (!email) throwApiError(403, "Verified viewer email required.");
|
|
3774
|
-
return read(email);
|
|
3775
|
-
}
|
|
3776
|
-
});
|
|
3948
|
+
};
|
|
3777
3949
|
}
|
|
3778
3950
|
|
|
3779
3951
|
// src/api/people/routes.ts
|
|
3780
3952
|
function createPeopleRoutes() {
|
|
3781
3953
|
const app = new Hono3();
|
|
3782
|
-
const
|
|
3783
|
-
|
|
3784
|
-
|
|
3785
|
-
|
|
3786
|
-
|
|
3787
|
-
|
|
3954
|
+
const readPersonalSpend = createPersonalSpendReader();
|
|
3955
|
+
app.get("/me/spend", requireViewer, async (context) => {
|
|
3956
|
+
const viewer = context.get("viewer");
|
|
3957
|
+
return jsonResponse(
|
|
3958
|
+
personalSpendReportSchema,
|
|
3959
|
+
await readPersonalSpend(viewer.email)
|
|
3960
|
+
);
|
|
3961
|
+
});
|
|
3962
|
+
app.get(
|
|
3963
|
+
"/",
|
|
3964
|
+
async () => jsonResponse(actorDirectoryReportSchema, await readPeopleList())
|
|
3965
|
+
);
|
|
3966
|
+
app.get(
|
|
3967
|
+
"/:email",
|
|
3968
|
+
validateRequest("param", personParamsSchema, "Invalid route parameters."),
|
|
3969
|
+
async (context) => {
|
|
3970
|
+
const { email } = context.req.valid("param");
|
|
3971
|
+
const viewer = context.get("viewer");
|
|
3972
|
+
return jsonResponse(
|
|
3973
|
+
actorProfileReportSchema,
|
|
3974
|
+
await readPeopleProfile(email, viewer ? { viewer } : {})
|
|
3975
|
+
);
|
|
3976
|
+
}
|
|
3977
|
+
);
|
|
3788
3978
|
return app;
|
|
3789
3979
|
}
|
|
3790
3980
|
|
|
3791
|
-
// src/api/plugin-reports.ts
|
|
3792
|
-
var plugin_reports_default = defineApiRoute({
|
|
3793
|
-
method: "get",
|
|
3794
|
-
path: "/api/plugin-reports",
|
|
3795
|
-
responseSchema: pluginOperationalReportFeedSchema,
|
|
3796
|
-
handler: readPluginOperationalReportFeed
|
|
3797
|
-
});
|
|
3798
|
-
|
|
3799
3981
|
// src/api/personal-tokens/routes.ts
|
|
3800
3982
|
import { Hono as Hono4 } from "hono";
|
|
3801
3983
|
|
|
@@ -3874,63 +4056,57 @@ async function authenticatePersonalToken(token2, now = /* @__PURE__ */ new Date(
|
|
|
3874
4056
|
return match.ownerEmailNormalized;
|
|
3875
4057
|
}
|
|
3876
4058
|
|
|
3877
|
-
// src/api/personal-tokens/create.ts
|
|
3878
|
-
var create_default = defineApiRoute({
|
|
3879
|
-
method: "post",
|
|
3880
|
-
path: "/",
|
|
3881
|
-
responseSchema: createdPersonalTokenSchema,
|
|
3882
|
-
handler: async (c) => {
|
|
3883
|
-
const email = c.get("verifiedViewerEmail");
|
|
3884
|
-
if (!email) throwApiError(403, "Verified viewer email required.");
|
|
3885
|
-
let input;
|
|
3886
|
-
try {
|
|
3887
|
-
input = await c.req.json();
|
|
3888
|
-
} catch (error) {
|
|
3889
|
-
throwApiError(400, "Invalid request body.", error);
|
|
3890
|
-
}
|
|
3891
|
-
const body = parseBody(createPersonalTokenBodySchema, input);
|
|
3892
|
-
return createPersonalToken({ email, name: body.name });
|
|
3893
|
-
}
|
|
3894
|
-
});
|
|
3895
|
-
|
|
3896
|
-
// src/api/personal-tokens/list.ts
|
|
3897
|
-
var list_default4 = defineApiRoute({
|
|
3898
|
-
method: "get",
|
|
3899
|
-
path: "/",
|
|
3900
|
-
responseSchema: personalTokenListSchema,
|
|
3901
|
-
handler: async (c) => {
|
|
3902
|
-
const email = c.get("verifiedViewerEmail");
|
|
3903
|
-
if (!email) throwApiError(403, "Verified viewer email required.");
|
|
3904
|
-
return { tokens: await listPersonalTokens(email) };
|
|
3905
|
-
}
|
|
3906
|
-
});
|
|
3907
|
-
|
|
3908
|
-
// src/api/personal-tokens/revoke.ts
|
|
3909
|
-
var revoke_default = defineApiRoute({
|
|
3910
|
-
method: "delete",
|
|
3911
|
-
path: "/:id",
|
|
3912
|
-
responseSchema: revokePersonalTokenResponseSchema,
|
|
3913
|
-
handler: async (c) => {
|
|
3914
|
-
const email = c.get("verifiedViewerEmail");
|
|
3915
|
-
if (!email) throwApiError(403, "Verified viewer email required.");
|
|
3916
|
-
const { id } = parseParams(personalTokenParamsSchema, c.req.param());
|
|
3917
|
-
if (!await revokePersonalToken({ email, id })) {
|
|
3918
|
-
throwApiError(404, "Personal API token not found.");
|
|
3919
|
-
}
|
|
3920
|
-
return { revoked: true };
|
|
3921
|
-
}
|
|
3922
|
-
});
|
|
3923
|
-
|
|
3924
4059
|
// src/api/personal-tokens/routes.ts
|
|
3925
|
-
var routes3 = [list_default4, create_default, revoke_default];
|
|
3926
4060
|
function createPersonalTokenRoutes() {
|
|
3927
4061
|
const app = new Hono4();
|
|
3928
|
-
|
|
4062
|
+
app.get("/", requireViewer, async (context) => {
|
|
4063
|
+
const viewer = context.get("viewer");
|
|
4064
|
+
return jsonResponse(personalTokenListSchema, {
|
|
4065
|
+
tokens: await listPersonalTokens(viewer.email)
|
|
4066
|
+
});
|
|
4067
|
+
});
|
|
4068
|
+
app.post(
|
|
4069
|
+
"/",
|
|
4070
|
+
requireViewer,
|
|
4071
|
+
validateRequest(
|
|
4072
|
+
"json",
|
|
4073
|
+
createPersonalTokenBodySchema,
|
|
4074
|
+
"Invalid request body."
|
|
4075
|
+
),
|
|
4076
|
+
async (context) => {
|
|
4077
|
+
const viewer = context.get("viewer");
|
|
4078
|
+
const body = context.req.valid("json");
|
|
4079
|
+
return jsonResponse(
|
|
4080
|
+
createdPersonalTokenSchema,
|
|
4081
|
+
await createPersonalToken({ email: viewer.email, name: body.name })
|
|
4082
|
+
);
|
|
4083
|
+
}
|
|
4084
|
+
);
|
|
4085
|
+
app.delete(
|
|
4086
|
+
"/:id",
|
|
4087
|
+
requireViewer,
|
|
4088
|
+
validateRequest(
|
|
4089
|
+
"param",
|
|
4090
|
+
personalTokenParamsSchema,
|
|
4091
|
+
"Invalid route parameters."
|
|
4092
|
+
),
|
|
4093
|
+
async (context) => {
|
|
4094
|
+
const viewer = context.get("viewer");
|
|
4095
|
+
const { id } = context.req.valid("param");
|
|
4096
|
+
if (!await revokePersonalToken({ email: viewer.email, id })) {
|
|
4097
|
+
throwApiError(404, "Personal API token not found.");
|
|
4098
|
+
}
|
|
4099
|
+
return jsonResponse(revokePersonalTokenResponseSchema, {
|
|
4100
|
+
revoked: true
|
|
4101
|
+
});
|
|
4102
|
+
}
|
|
4103
|
+
);
|
|
3929
4104
|
return app;
|
|
3930
4105
|
}
|
|
3931
4106
|
|
|
3932
4107
|
// src/api/user-pages/routes.ts
|
|
3933
4108
|
import { Hono as Hono5 } from "hono";
|
|
4109
|
+
import { z as z5 } from "zod";
|
|
3934
4110
|
import {
|
|
3935
4111
|
pluginUserPageContentSchema as pluginUserPageContentSchema2,
|
|
3936
4112
|
pluginUserPageInputSchema,
|
|
@@ -3968,8 +4144,8 @@ async function readPluginUserPage(input) {
|
|
|
3968
4144
|
(candidate) => candidate.id === input.pageId
|
|
3969
4145
|
);
|
|
3970
4146
|
if (!plugin || !page) return void 0;
|
|
3971
|
-
const
|
|
3972
|
-
if (!
|
|
4147
|
+
const viewer = await resolveViewerUser(input.email);
|
|
4148
|
+
if (!viewer) {
|
|
3973
4149
|
throw new Error("Authenticated viewer user could not be resolved");
|
|
3974
4150
|
}
|
|
3975
4151
|
const content = pluginUserPageContentSchema.parse(
|
|
@@ -3978,7 +4154,7 @@ async function readPluginUserPage(input) {
|
|
|
3978
4154
|
db: getDb(),
|
|
3979
4155
|
log: createPluginLogger(plugin.manifest.name),
|
|
3980
4156
|
plugin: { name: plugin.manifest.name },
|
|
3981
|
-
viewer
|
|
4157
|
+
viewer
|
|
3982
4158
|
},
|
|
3983
4159
|
input.query
|
|
3984
4160
|
)
|
|
@@ -3996,167 +4172,114 @@ async function readPluginUserPage(input) {
|
|
|
3996
4172
|
}
|
|
3997
4173
|
|
|
3998
4174
|
// src/api/user-pages/routes.ts
|
|
4175
|
+
var userPageQuerySchema = z5.object({
|
|
4176
|
+
cursor: z5.preprocess(
|
|
4177
|
+
(value) => value || void 0,
|
|
4178
|
+
pluginUserPageInputSchema.shape.cursor
|
|
4179
|
+
),
|
|
4180
|
+
filter: z5.preprocess(
|
|
4181
|
+
(value) => value || void 0,
|
|
4182
|
+
pluginUserPageInputSchema.shape.filter
|
|
4183
|
+
),
|
|
4184
|
+
limit: z5.preprocess(
|
|
4185
|
+
(value) => value === "" ? void 0 : value,
|
|
4186
|
+
z5.coerce.number().int().min(1).max(50).default(20)
|
|
4187
|
+
),
|
|
4188
|
+
q: z5.preprocess(
|
|
4189
|
+
(value) => value || void 0,
|
|
4190
|
+
pluginUserPageInputSchema.shape.query
|
|
4191
|
+
)
|
|
4192
|
+
});
|
|
3999
4193
|
function createUserPageRoutes() {
|
|
4000
4194
|
const app = new Hono5();
|
|
4001
4195
|
app.get(
|
|
4002
4196
|
"/",
|
|
4003
4197
|
() => jsonResponse(pluginUserPageLinksSchema2, readPluginUserPageLinks())
|
|
4004
4198
|
);
|
|
4005
|
-
app.get(
|
|
4006
|
-
|
|
4007
|
-
|
|
4008
|
-
|
|
4009
|
-
|
|
4010
|
-
|
|
4011
|
-
|
|
4012
|
-
|
|
4013
|
-
|
|
4014
|
-
|
|
4015
|
-
|
|
4016
|
-
|
|
4017
|
-
|
|
4018
|
-
|
|
4019
|
-
});
|
|
4020
|
-
if (!pageInput.success) {
|
|
4021
|
-
return jsonResponse(
|
|
4199
|
+
app.get(
|
|
4200
|
+
"/:pluginName/:pageId",
|
|
4201
|
+
requireViewer,
|
|
4202
|
+
validateRequest("query", userPageQuerySchema, "Invalid user page query."),
|
|
4203
|
+
async (context) => {
|
|
4204
|
+
const viewer = context.get("viewer");
|
|
4205
|
+
const { q, ...query } = context.req.valid("query");
|
|
4206
|
+
const page = await readPluginUserPage({
|
|
4207
|
+
email: viewer.email,
|
|
4208
|
+
pageId: context.req.param("pageId"),
|
|
4209
|
+
pluginName: context.req.param("pluginName"),
|
|
4210
|
+
query: { ...query, ...q === void 0 ? {} : { query: q } }
|
|
4211
|
+
});
|
|
4212
|
+
return page ? jsonResponse(pluginUserPageContentSchema2, page) : jsonResponse(
|
|
4022
4213
|
apiErrorSchema,
|
|
4023
|
-
{ error: "
|
|
4024
|
-
{ status:
|
|
4214
|
+
{ error: "User page not found." },
|
|
4215
|
+
{ status: 404 }
|
|
4025
4216
|
);
|
|
4026
4217
|
}
|
|
4027
|
-
|
|
4028
|
-
email,
|
|
4029
|
-
pageId: context.req.param("pageId"),
|
|
4030
|
-
pluginName: context.req.param("pluginName"),
|
|
4031
|
-
query: pageInput.data
|
|
4032
|
-
});
|
|
4033
|
-
return page ? jsonResponse(pluginUserPageContentSchema2, page) : jsonResponse(
|
|
4034
|
-
apiErrorSchema,
|
|
4035
|
-
{ error: "User page not found." },
|
|
4036
|
-
{ status: 404 }
|
|
4037
|
-
);
|
|
4038
|
-
});
|
|
4218
|
+
);
|
|
4039
4219
|
return app;
|
|
4040
4220
|
}
|
|
4041
4221
|
|
|
4042
4222
|
// src/api/tasks/routes.ts
|
|
4043
4223
|
import { Hono as Hono6 } from "hono";
|
|
4044
|
-
async function viewer(context) {
|
|
4045
|
-
const email = context.get("verifiedViewerEmail")?.trim();
|
|
4046
|
-
return email ? await resolveViewerUser(email) : void 0;
|
|
4047
|
-
}
|
|
4048
4224
|
function createTaskRoutes() {
|
|
4049
4225
|
const app = new Hono6();
|
|
4050
|
-
app.get("/", async (context) => {
|
|
4051
|
-
const user =
|
|
4052
|
-
return
|
|
4053
|
-
apiErrorSchema,
|
|
4054
|
-
{ error: "Authentication required." },
|
|
4055
|
-
{ status: 401 }
|
|
4056
|
-
);
|
|
4226
|
+
app.get("/", requireViewer, async (context) => {
|
|
4227
|
+
const user = context.get("viewer");
|
|
4228
|
+
return jsonResponse(taskListSchema, await readViewerTasks(user));
|
|
4057
4229
|
});
|
|
4058
|
-
app.get("/runs", async (context) => {
|
|
4059
|
-
const user =
|
|
4060
|
-
return
|
|
4061
|
-
apiErrorSchema,
|
|
4062
|
-
{ error: "Authentication required." },
|
|
4063
|
-
{ status: 401 }
|
|
4064
|
-
);
|
|
4230
|
+
app.get("/runs", requireViewer, async (context) => {
|
|
4231
|
+
const user = context.get("viewer");
|
|
4232
|
+
return jsonResponse(taskRunListSchema, await readViewerTaskRuns(user));
|
|
4065
4233
|
});
|
|
4066
|
-
app.get(
|
|
4067
|
-
|
|
4068
|
-
|
|
4069
|
-
|
|
4070
|
-
|
|
4071
|
-
|
|
4072
|
-
|
|
4073
|
-
|
|
4074
|
-
}
|
|
4075
|
-
const params = taskParamsSchema.safeParse(context.req.param());
|
|
4076
|
-
if (!params.success) {
|
|
4077
|
-
return jsonResponse(
|
|
4078
|
-
apiErrorSchema,
|
|
4079
|
-
{ error: "Invalid task." },
|
|
4080
|
-
{ status: 400 }
|
|
4081
|
-
);
|
|
4082
|
-
}
|
|
4083
|
-
try {
|
|
4084
|
-
return jsonResponse(
|
|
4085
|
-
taskExecutionListSchema,
|
|
4086
|
-
await readViewerTaskExecutions(user, params.data.kind, params.data.id)
|
|
4087
|
-
);
|
|
4088
|
-
} catch (error) {
|
|
4089
|
-
if (error instanceof ViewerTaskNotFoundError) {
|
|
4234
|
+
app.get(
|
|
4235
|
+
"/:kind/:id/executions",
|
|
4236
|
+
requireViewer,
|
|
4237
|
+
validateRequest("param", taskParamsSchema, "Invalid task."),
|
|
4238
|
+
async (context) => {
|
|
4239
|
+
const user = context.get("viewer");
|
|
4240
|
+
const params = context.req.valid("param");
|
|
4241
|
+
try {
|
|
4090
4242
|
return jsonResponse(
|
|
4091
|
-
|
|
4092
|
-
|
|
4093
|
-
{ status: 404 }
|
|
4243
|
+
taskExecutionListSchema,
|
|
4244
|
+
await readViewerTaskExecutions(user, params.kind, params.id)
|
|
4094
4245
|
);
|
|
4246
|
+
} catch (error) {
|
|
4247
|
+
if (error instanceof ViewerTaskNotFoundError) {
|
|
4248
|
+
return jsonResponse(
|
|
4249
|
+
apiErrorSchema,
|
|
4250
|
+
{ error: error.message },
|
|
4251
|
+
{ status: 404 }
|
|
4252
|
+
);
|
|
4253
|
+
}
|
|
4254
|
+
throw error;
|
|
4095
4255
|
}
|
|
4096
|
-
throw error;
|
|
4097
4256
|
}
|
|
4098
|
-
|
|
4099
|
-
app.delete(
|
|
4100
|
-
|
|
4101
|
-
|
|
4102
|
-
|
|
4103
|
-
|
|
4104
|
-
|
|
4105
|
-
|
|
4106
|
-
|
|
4107
|
-
|
|
4108
|
-
|
|
4109
|
-
|
|
4110
|
-
|
|
4111
|
-
|
|
4112
|
-
|
|
4113
|
-
|
|
4114
|
-
|
|
4115
|
-
|
|
4116
|
-
|
|
4117
|
-
|
|
4118
|
-
return new Response(null, {
|
|
4119
|
-
headers: { "cache-control": "no-store" },
|
|
4120
|
-
status: 204
|
|
4121
|
-
});
|
|
4122
|
-
} catch (error) {
|
|
4123
|
-
if (error instanceof ViewerTaskNotFoundError) {
|
|
4124
|
-
return jsonResponse(
|
|
4125
|
-
apiErrorSchema,
|
|
4126
|
-
{ error: error.message },
|
|
4127
|
-
{ status: 404 }
|
|
4128
|
-
);
|
|
4257
|
+
);
|
|
4258
|
+
app.delete(
|
|
4259
|
+
"/:kind/:id",
|
|
4260
|
+
requireViewer,
|
|
4261
|
+
validateRequest("param", taskParamsSchema, "Invalid task."),
|
|
4262
|
+
async (context) => {
|
|
4263
|
+
const user = context.get("viewer");
|
|
4264
|
+
const params = context.req.valid("param");
|
|
4265
|
+
try {
|
|
4266
|
+
await deleteViewerTask(user, params.kind, params.id);
|
|
4267
|
+
return emptyResponse();
|
|
4268
|
+
} catch (error) {
|
|
4269
|
+
if (error instanceof ViewerTaskNotFoundError) {
|
|
4270
|
+
return jsonResponse(
|
|
4271
|
+
apiErrorSchema,
|
|
4272
|
+
{ error: error.message },
|
|
4273
|
+
{ status: 404 }
|
|
4274
|
+
);
|
|
4275
|
+
}
|
|
4276
|
+
throw error;
|
|
4129
4277
|
}
|
|
4130
|
-
throw error;
|
|
4131
4278
|
}
|
|
4132
|
-
|
|
4279
|
+
);
|
|
4133
4280
|
return app;
|
|
4134
4281
|
}
|
|
4135
4282
|
|
|
4136
|
-
// src/api/plugins.ts
|
|
4137
|
-
var plugins_default = defineApiRoute({
|
|
4138
|
-
method: "get",
|
|
4139
|
-
path: "/api/plugins",
|
|
4140
|
-
responseSchema: pluginsSchema,
|
|
4141
|
-
handler: readPlugins
|
|
4142
|
-
});
|
|
4143
|
-
|
|
4144
|
-
// src/api/runtime.ts
|
|
4145
|
-
var runtime_default = defineApiRoute({
|
|
4146
|
-
method: "get",
|
|
4147
|
-
path: "/api/runtime",
|
|
4148
|
-
responseSchema: runtimeInfoReportSchema,
|
|
4149
|
-
handler: readRuntimeInfoReport
|
|
4150
|
-
});
|
|
4151
|
-
|
|
4152
|
-
// src/api/skills.ts
|
|
4153
|
-
var skills_default = defineApiRoute({
|
|
4154
|
-
method: "get",
|
|
4155
|
-
path: "/api/skills",
|
|
4156
|
-
responseSchema: skillReportsSchema,
|
|
4157
|
-
handler: readSkillReports
|
|
4158
|
-
});
|
|
4159
|
-
|
|
4160
4283
|
// src/api/stats.ts
|
|
4161
4284
|
var WINDOW_DAYS2 = 90;
|
|
4162
4285
|
async function readStatsReport() {
|
|
@@ -4173,25 +4296,96 @@ async function readStatsReport() {
|
|
|
4173
4296
|
windowStart: start
|
|
4174
4297
|
});
|
|
4175
4298
|
}
|
|
4176
|
-
|
|
4177
|
-
|
|
4178
|
-
|
|
4179
|
-
|
|
4180
|
-
|
|
4181
|
-
|
|
4299
|
+
|
|
4300
|
+
// src/reporting.ts
|
|
4301
|
+
import { readFileSync } from "fs";
|
|
4302
|
+
import path from "path";
|
|
4303
|
+
function readDescriptionText(home) {
|
|
4304
|
+
try {
|
|
4305
|
+
const raw = readFileSync(path.join(home, "DESCRIPTION.md"), "utf8").trim();
|
|
4306
|
+
return raw || void 0;
|
|
4307
|
+
} catch {
|
|
4308
|
+
return void 0;
|
|
4309
|
+
}
|
|
4310
|
+
}
|
|
4311
|
+
async function readSkillReports() {
|
|
4312
|
+
const { discoverSkills } = await import("./skills-AU5ST2CG.js");
|
|
4313
|
+
const skills = await discoverSkills();
|
|
4314
|
+
return skillReportsSchema.parse(
|
|
4315
|
+
skills.map((skill) => ({
|
|
4316
|
+
name: skill.name,
|
|
4317
|
+
pluginProvider: skill.pluginProvider
|
|
4318
|
+
}))
|
|
4319
|
+
);
|
|
4320
|
+
}
|
|
4321
|
+
async function readPlugins() {
|
|
4322
|
+
const { pluginCatalogRuntime } = await import("./catalog-runtime-GAW5APVI.js");
|
|
4323
|
+
return pluginsSchema.parse(
|
|
4324
|
+
pluginCatalogRuntime.getProviders().map((plugin) => ({
|
|
4325
|
+
configKeys: plugin.manifest.configKeys ?? [],
|
|
4326
|
+
description: plugin.manifest.description,
|
|
4327
|
+
displayName: plugin.manifest.displayName,
|
|
4328
|
+
name: plugin.manifest.name
|
|
4329
|
+
}))
|
|
4330
|
+
);
|
|
4331
|
+
}
|
|
4332
|
+
async function readRuntimeInfoReport() {
|
|
4333
|
+
const [{ homeDir }, { pluginCatalogRuntime }, plugins, skills] = await Promise.all([
|
|
4334
|
+
import("./discovery-GUFTFBTL.js"),
|
|
4335
|
+
import("./catalog-runtime-GAW5APVI.js"),
|
|
4336
|
+
readPlugins(),
|
|
4337
|
+
readSkillReports()
|
|
4338
|
+
]);
|
|
4339
|
+
const home = homeDir();
|
|
4340
|
+
return runtimeInfoReportSchema.parse({
|
|
4341
|
+
cwd: process.cwd(),
|
|
4342
|
+
homeDir: home,
|
|
4343
|
+
descriptionText: readDescriptionText(home),
|
|
4344
|
+
providers: plugins.map((plugin) => plugin.name),
|
|
4345
|
+
skills,
|
|
4346
|
+
packagedContent: pluginCatalogRuntime.getPackageContent()
|
|
4347
|
+
});
|
|
4348
|
+
}
|
|
4349
|
+
async function readPluginOperationalReportFeed() {
|
|
4350
|
+
const nowMs = Date.now();
|
|
4351
|
+
const { getPluginOperationalReports } = await import("./agent-hooks-CWMCXAMT.js");
|
|
4352
|
+
return pluginOperationalReportFeedSchema.parse({
|
|
4353
|
+
source: "plugins",
|
|
4354
|
+
generatedAt: new Date(nowMs).toISOString(),
|
|
4355
|
+
reports: await getPluginOperationalReports(nowMs)
|
|
4356
|
+
});
|
|
4357
|
+
}
|
|
4182
4358
|
|
|
4183
4359
|
// src/api.ts
|
|
4184
|
-
var routes4 = [
|
|
4185
|
-
health_default,
|
|
4186
|
-
runtime_default,
|
|
4187
|
-
plugins_default,
|
|
4188
|
-
skills_default,
|
|
4189
|
-
plugin_reports_default,
|
|
4190
|
-
stats_default2
|
|
4191
|
-
];
|
|
4192
4360
|
function createJuniorApi() {
|
|
4193
4361
|
const app = new Hono7();
|
|
4194
|
-
|
|
4362
|
+
app.get(
|
|
4363
|
+
"/api/health",
|
|
4364
|
+
async () => jsonResponse(healthReportSchema, readHealthReport())
|
|
4365
|
+
);
|
|
4366
|
+
app.get(
|
|
4367
|
+
"/api/runtime",
|
|
4368
|
+
async () => jsonResponse(runtimeInfoReportSchema, await readRuntimeInfoReport())
|
|
4369
|
+
);
|
|
4370
|
+
app.get(
|
|
4371
|
+
"/api/plugins",
|
|
4372
|
+
async () => jsonResponse(pluginsSchema, await readPlugins())
|
|
4373
|
+
);
|
|
4374
|
+
app.get(
|
|
4375
|
+
"/api/skills",
|
|
4376
|
+
async () => jsonResponse(skillReportsSchema, await readSkillReports())
|
|
4377
|
+
);
|
|
4378
|
+
app.get(
|
|
4379
|
+
"/api/plugin-reports",
|
|
4380
|
+
async () => jsonResponse(
|
|
4381
|
+
pluginOperationalReportFeedSchema,
|
|
4382
|
+
await readPluginOperationalReportFeed()
|
|
4383
|
+
)
|
|
4384
|
+
);
|
|
4385
|
+
app.get(
|
|
4386
|
+
"/api/stats",
|
|
4387
|
+
async () => jsonResponse(statsReportSchema, await readStatsReport())
|
|
4388
|
+
);
|
|
4195
4389
|
app.route("/api/conversations", createConversationRoutes());
|
|
4196
4390
|
app.route("/api/personal-tokens", createPersonalTokenRoutes());
|
|
4197
4391
|
app.route("/api/people", createPeopleRoutes());
|
|
@@ -4207,10 +4401,27 @@ function createJuniorApi() {
|
|
|
4207
4401
|
}
|
|
4208
4402
|
)
|
|
4209
4403
|
);
|
|
4404
|
+
app.onError((error, _context) => {
|
|
4405
|
+
if (error instanceof HTTPException2) {
|
|
4406
|
+
if (error.res) return error.res;
|
|
4407
|
+
return jsonResponse(
|
|
4408
|
+
apiErrorSchema,
|
|
4409
|
+
{ error: error.message || "Request failed." },
|
|
4410
|
+
{ status: error.status }
|
|
4411
|
+
);
|
|
4412
|
+
}
|
|
4413
|
+
logException(error, "api.unhandled.exception");
|
|
4414
|
+
return jsonResponse(
|
|
4415
|
+
apiErrorSchema,
|
|
4416
|
+
{ error: "Internal Server Error" },
|
|
4417
|
+
{ status: 500 }
|
|
4418
|
+
);
|
|
4419
|
+
});
|
|
4210
4420
|
return app;
|
|
4211
4421
|
}
|
|
4212
4422
|
export {
|
|
4213
4423
|
authenticatePersonalToken,
|
|
4214
4424
|
createJuniorApi,
|
|
4215
|
-
jsonResponse
|
|
4425
|
+
jsonResponse,
|
|
4426
|
+
resolveViewerUser
|
|
4216
4427
|
};
|