@rubytech/create-maxy 1.0.876 → 1.0.878
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/package.json +1 -1
- package/payload/platform/lib/graph-trash/dist/index.js +1 -1
- package/payload/platform/lib/graph-trash/dist/index.js.map +1 -1
- package/payload/platform/lib/graph-trash/src/index.ts +1 -1
- package/payload/platform/neo4j/edge-annotations.json +11 -3
- package/payload/platform/plugins/admin/hooks/__tests__/pre-tool-use-base64-guard.test.sh +204 -0
- package/payload/platform/plugins/admin/hooks/archive-ingest-surface-gate.sh +11 -5
- package/payload/platform/plugins/admin/hooks/pre-tool-use.sh +96 -0
- package/payload/platform/plugins/admin/skills/onboarding/SKILL.md +5 -1
- package/payload/platform/plugins/cloudflare/scripts/setup-tunnel.sh +88 -9
- package/payload/platform/plugins/cloudflare/skills/setup-tunnel/SKILL.md +1 -1
- package/payload/platform/plugins/docs/references/admin-session.md +80 -0
- package/payload/platform/plugins/docs/references/platform.md +3 -1
- package/payload/platform/plugins/docs/references/plugins-guide.md +1 -0
- package/payload/platform/plugins/memory/PLUGIN.md +4 -1
- package/payload/platform/plugins/memory/mcp/dist/index.js +127 -0
- package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-archive-derive-insights.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-archive-derive-insights.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-archive-derive-insights.test.js +97 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-archive-derive-insights.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-archive-enrich-rejection.test.d.ts +2 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-archive-enrich-rejection.test.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-archive-enrich-rejection.test.js +184 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/conversation-archive-enrich-rejection.test.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/conversation-archive-derive-insights.d.ts +89 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/conversation-archive-derive-insights.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/conversation-archive-derive-insights.js +542 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/conversation-archive-derive-insights.js.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/conversation-archive-enrich-rejection.d.ts +41 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/conversation-archive-enrich-rejection.d.ts.map +1 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/conversation-archive-enrich-rejection.js +116 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/conversation-archive-enrich-rejection.js.map +1 -0
- package/payload/platform/plugins/memory/skills/conversation-archive-enrich/SKILL.md +159 -0
- package/payload/platform/templates/agents/admin/IDENTITY.md +4 -0
- package/payload/platform/templates/specialists/agents/database-operator.md +3 -2
- package/payload/server/chunk-GOZP57CX.js +1373 -0
- package/payload/server/chunk-I4AQMEJA.js +11265 -0
- package/payload/server/chunk-INI2ED6U.js +2277 -0
- package/payload/server/chunk-JTZYXIUW.js +1373 -0
- package/payload/server/chunk-LQDUG4II.js +11336 -0
- package/payload/server/chunk-LU6TUP3E.js +2169 -0
- package/payload/server/chunk-RP25NRQY.js +660 -0
- package/payload/server/chunk-RRVBWC66.js +667 -0
- package/payload/server/client-pool-AIZ5QKFD.js +34 -0
- package/payload/server/client-pool-VYDOIFG7.js +34 -0
- package/payload/server/cloudflare-task-tracker-B6FXP3HI.js +20 -0
- package/payload/server/cloudflare-task-tracker-M7APAYEF.js +20 -0
- package/payload/server/maxy-edge.js +6 -5
- package/payload/server/public/assets/{Checkbox-BsqexMy3.js → Checkbox-CqsIsmEi.js} +1 -1
- package/payload/server/public/assets/admin-CZlNLb9T.js +352 -0
- package/payload/server/public/assets/data-CH-nQ7oX.js +1 -0
- package/payload/server/public/assets/graph-labels-D0qUVHtZ.js +1 -0
- package/payload/server/public/assets/graph-mpWDe4rf.js +1 -0
- package/payload/server/public/assets/{jsx-runtime-CGCRFPeX.css → jsx-runtime-Cy_HdZWV.css} +1 -1
- package/payload/server/public/assets/page-CnyySOZF.js +1 -0
- package/payload/server/public/assets/{page-qI0NJSs6.js → page-DcK36vDf.js} +2 -2
- package/payload/server/public/assets/public-SXA00FTv.js +5 -0
- package/payload/server/public/assets/{useVoiceRecorder-DVVSQc-9.js → useVoiceRecorder-DcByEBLy.js} +1 -1
- package/payload/server/public/data.html +5 -5
- package/payload/server/public/graph.html +6 -6
- package/payload/server/public/index.html +8 -8
- package/payload/server/public/public.html +5 -5
- package/payload/server/server.js +560 -448
- package/payload/server/public/assets/admin-pIeHRytz.js +0 -352
- package/payload/server/public/assets/data-rhAG7W2b.js +0 -1
- package/payload/server/public/assets/graph-DVAWZmkb.js +0 -1
- package/payload/server/public/assets/graph-labels-t_04n4zX.js +0 -1
- package/payload/server/public/assets/page-BM9O7QN8.js +0 -1
- package/payload/server/public/assets/public-oNo_2gt0.js +0 -5
- /package/payload/server/public/assets/{jsx-runtime-B8sGPXtT.js → jsx-runtime-BEjEWeaF.js} +0 -0
package/payload/server/server.js
CHANGED
|
@@ -1,19 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ACCOUNTS_DIR,
|
|
3
3
|
ATTACHMENTS_ROOT,
|
|
4
|
-
CDP_PORT,
|
|
5
|
-
COMMERCIAL_MODE,
|
|
6
4
|
Hono,
|
|
7
|
-
LOG_DIR,
|
|
8
|
-
MAXY_DIR,
|
|
9
5
|
MAX_FILES_PER_MESSAGE,
|
|
10
6
|
MAX_FILE_SIZE_BYTES,
|
|
11
7
|
PLATFORM_ROOT,
|
|
12
8
|
SUPPORTED_MIME_TYPES,
|
|
13
|
-
TELEGRAM_ADMIN_WEBHOOK_SECRET_FILE,
|
|
14
|
-
TELEGRAM_WEBHOOK_SECRET_FILE,
|
|
15
|
-
USERS_FILE,
|
|
16
|
-
WEBSOCKIFY_PORT,
|
|
17
9
|
assertSupportedMime,
|
|
18
10
|
autoDeliverPremiumPlugins,
|
|
19
11
|
browserViewerLog,
|
|
@@ -83,12 +75,22 @@ import {
|
|
|
83
75
|
vncLog,
|
|
84
76
|
waitForExit,
|
|
85
77
|
writeChromiumWrapper
|
|
86
|
-
} from "./chunk-
|
|
78
|
+
} from "./chunk-LQDUG4II.js";
|
|
87
79
|
import {
|
|
80
|
+
CDP_PORT,
|
|
81
|
+
COMMERCIAL_MODE,
|
|
82
|
+
LOG_DIR,
|
|
83
|
+
MAXY_DIR,
|
|
84
|
+
TELEGRAM_ADMIN_WEBHOOK_SECRET_FILE,
|
|
85
|
+
TELEGRAM_WEBHOOK_SECRET_FILE,
|
|
86
|
+
USERS_FILE,
|
|
87
|
+
WEBSOCKIFY_PORT,
|
|
88
88
|
agentLogStream,
|
|
89
89
|
clearSessionHistory,
|
|
90
90
|
completeGrantSetup,
|
|
91
|
+
consumeWantsPriorConversation,
|
|
91
92
|
getAccountIdForSession,
|
|
93
|
+
getActiveClient,
|
|
92
94
|
getAgentNameForSession,
|
|
93
95
|
getConversationIdForSession,
|
|
94
96
|
getGrantForSession,
|
|
@@ -100,6 +102,7 @@ import {
|
|
|
100
102
|
getVisitorIdForSession,
|
|
101
103
|
interruptClient,
|
|
102
104
|
listAdminSessionsInProgress,
|
|
105
|
+
mintAdminSessionToken,
|
|
103
106
|
preConversationLogStream,
|
|
104
107
|
registerGrantSession,
|
|
105
108
|
registerResumedSession,
|
|
@@ -107,10 +110,11 @@ import {
|
|
|
107
110
|
setAgentSessionId,
|
|
108
111
|
setConversationIdForSession,
|
|
109
112
|
setGroupContextForSession,
|
|
113
|
+
setWantsPriorConversation,
|
|
110
114
|
sigtermFlushStreamLogs,
|
|
111
115
|
unregisterSession,
|
|
112
116
|
validateSession
|
|
113
|
-
} from "./chunk-
|
|
117
|
+
} from "./chunk-JTZYXIUW.js";
|
|
114
118
|
import {
|
|
115
119
|
CLOUDFLARE_TASK_DIAGNOSTICS,
|
|
116
120
|
appendCloudflareSteps,
|
|
@@ -118,10 +122,11 @@ import {
|
|
|
118
122
|
openCloudflareTask,
|
|
119
123
|
readTunnelState,
|
|
120
124
|
resolveUnitGoneVerdict
|
|
121
|
-
} from "./chunk-
|
|
125
|
+
} from "./chunk-RP25NRQY.js";
|
|
122
126
|
import {
|
|
123
127
|
GREETING_DIRECTIVE,
|
|
124
128
|
HAIKU_MODEL,
|
|
129
|
+
backfillConversationChannelAddress,
|
|
125
130
|
backfillNullUserIdConversations,
|
|
126
131
|
bindVisitorToGroup,
|
|
127
132
|
checkGroupMembership,
|
|
@@ -137,6 +142,7 @@ import {
|
|
|
137
142
|
getAgentSessionIdForConversation,
|
|
138
143
|
getGroupParticipants,
|
|
139
144
|
getMessagesSince,
|
|
145
|
+
getMostRecentAdminConversationForUser,
|
|
140
146
|
getRecentMessages,
|
|
141
147
|
getSession,
|
|
142
148
|
getUserTimezone,
|
|
@@ -149,8 +155,9 @@ import {
|
|
|
149
155
|
runAdminUserSelfHeal,
|
|
150
156
|
verifyAndGetConversationUpdatedAt,
|
|
151
157
|
verifyConversationOwnership,
|
|
152
|
-
writeAdminUserAndPerson
|
|
153
|
-
|
|
158
|
+
writeAdminUserAndPerson,
|
|
159
|
+
writeTurnFailure
|
|
160
|
+
} from "./chunk-INI2ED6U.js";
|
|
154
161
|
import {
|
|
155
162
|
__commonJS,
|
|
156
163
|
__toESM
|
|
@@ -175,7 +182,7 @@ var require_dist = __commonJS({
|
|
|
175
182
|
Event: ["eventId"],
|
|
176
183
|
KnowledgeDocument: ["attachmentId"],
|
|
177
184
|
DigitalDocument: ["attachmentId"],
|
|
178
|
-
Conversation: ["conversationId"
|
|
185
|
+
Conversation: ["conversationId"],
|
|
179
186
|
Message: ["messageId"],
|
|
180
187
|
OnboardingState: ["accountId"],
|
|
181
188
|
Workflow: ["workflowId"],
|
|
@@ -2082,22 +2089,22 @@ async function persistWhatsAppMessage(input) {
|
|
|
2082
2089
|
const messageId = `whatsapp-live:${input.accountId}:${input.remoteJid}:${input.msgKeyId}`;
|
|
2083
2090
|
const senderTelephone = input.fromMe && input.selfPhone ? input.selfPhone : input.senderPhone;
|
|
2084
2091
|
const dateSentIso = new Date(input.timestamp * 1e3).toISOString();
|
|
2085
|
-
const scope = deriveScope(input.
|
|
2092
|
+
const scope = deriveScope(input.cacheKey);
|
|
2086
2093
|
const { givenName, familyName } = splitName(input.pushName);
|
|
2087
|
-
const prev = sessionWriteLocks.get(input.
|
|
2094
|
+
const prev = sessionWriteLocks.get(input.cacheKey);
|
|
2088
2095
|
let release;
|
|
2089
2096
|
const mine = new Promise((resolve22) => {
|
|
2090
2097
|
release = resolve22;
|
|
2091
2098
|
});
|
|
2092
2099
|
const chained = (prev ?? Promise.resolve()).then(() => mine);
|
|
2093
|
-
sessionWriteLocks.set(input.
|
|
2100
|
+
sessionWriteLocks.set(input.cacheKey, chained);
|
|
2094
2101
|
await prev;
|
|
2095
2102
|
const t0 = Date.now();
|
|
2096
2103
|
let session = null;
|
|
2097
2104
|
try {
|
|
2098
2105
|
session = getSession();
|
|
2099
2106
|
const cypher = `
|
|
2100
|
-
MATCH (c:Conversation {
|
|
2107
|
+
MATCH (c:Conversation {conversationId: $conversationId})
|
|
2101
2108
|
OPTIONAL MATCH (existingS:Person {telephone: $senderTelephone})
|
|
2102
2109
|
OPTIONAL MATCH (existingM:Message {messageId: $messageId})
|
|
2103
2110
|
WITH c,
|
|
@@ -2161,7 +2168,7 @@ async function persistWhatsAppMessage(input) {
|
|
|
2161
2168
|
senderReused AS senderReused
|
|
2162
2169
|
`;
|
|
2163
2170
|
const params = {
|
|
2164
|
-
|
|
2171
|
+
conversationId: input.conversationId,
|
|
2165
2172
|
messageId,
|
|
2166
2173
|
platformAccountId: input.platformAccountId,
|
|
2167
2174
|
senderTelephone,
|
|
@@ -2180,7 +2187,7 @@ async function persistWhatsAppMessage(input) {
|
|
|
2180
2187
|
const result = await session.run(cypher, params);
|
|
2181
2188
|
const ms = Date.now() - t0;
|
|
2182
2189
|
if (result.records.length === 0) {
|
|
2183
|
-
console.error(`${TAG7} skip reason=conversation-not-found accountId=${input.platformAccountId}
|
|
2190
|
+
console.error(`${TAG7} skip reason=conversation-not-found accountId=${input.platformAccountId} cacheKey=${input.cacheKey} messageId=${messageId}`);
|
|
2184
2191
|
return null;
|
|
2185
2192
|
}
|
|
2186
2193
|
const rec = result.records[0];
|
|
@@ -2201,7 +2208,7 @@ async function persistWhatsAppMessage(input) {
|
|
|
2201
2208
|
console.error(`${TAG7} next-skip reason=no-prior msgId=${messageId}`);
|
|
2202
2209
|
}
|
|
2203
2210
|
console.error(
|
|
2204
|
-
`${TAG7} write messageId=${messageId} accountId=${input.platformAccountId}
|
|
2211
|
+
`${TAG7} write messageId=${messageId} accountId=${input.platformAccountId} cacheKey=${input.cacheKey} fromMe=${input.fromMe} dateSent=${dateSentIso} bodyBytes=${Buffer.byteLength(input.body, "utf8")} ms=${ms}`
|
|
2205
2212
|
);
|
|
2206
2213
|
return { messageId, created: true, senderElementId };
|
|
2207
2214
|
} catch (err) {
|
|
@@ -2213,14 +2220,14 @@ async function persistWhatsAppMessage(input) {
|
|
|
2213
2220
|
return null;
|
|
2214
2221
|
} finally {
|
|
2215
2222
|
release();
|
|
2216
|
-
if (sessionWriteLocks.get(input.
|
|
2217
|
-
sessionWriteLocks.delete(input.
|
|
2223
|
+
if (sessionWriteLocks.get(input.cacheKey) === chained) {
|
|
2224
|
+
sessionWriteLocks.delete(input.cacheKey);
|
|
2218
2225
|
}
|
|
2219
2226
|
if (session) await session.close();
|
|
2220
2227
|
}
|
|
2221
2228
|
}
|
|
2222
|
-
function deriveScope(
|
|
2223
|
-
const segments =
|
|
2229
|
+
function deriveScope(cacheKey) {
|
|
2230
|
+
const segments = cacheKey.split(":");
|
|
2224
2231
|
return segments.length <= 2 ? "admin" : "public";
|
|
2225
2232
|
}
|
|
2226
2233
|
function splitName(pushName) {
|
|
@@ -2248,24 +2255,24 @@ async function ensureWhatsAppConversation(input) {
|
|
|
2248
2255
|
const result = await ensureConversation(
|
|
2249
2256
|
input.platformAccountId,
|
|
2250
2257
|
input.agentType,
|
|
2251
|
-
input.
|
|
2258
|
+
input.cacheKey
|
|
2252
2259
|
);
|
|
2253
2260
|
const ms = Date.now() - t0;
|
|
2254
2261
|
if (!result.conversationId) {
|
|
2255
2262
|
console.error(
|
|
2256
|
-
`${TAG8} conversation-merged FAIL
|
|
2263
|
+
`${TAG8} conversation-merged FAIL cacheKey=${input.cacheKey} reason=null-conversationId ms=${ms}`
|
|
2257
2264
|
);
|
|
2258
2265
|
return null;
|
|
2259
2266
|
}
|
|
2260
2267
|
console.error(
|
|
2261
|
-
`${TAG8} conversation-merged
|
|
2268
|
+
`${TAG8} conversation-merged cacheKey=${input.cacheKey} agentType=${input.agentType} channel=whatsapp created=${result.created} ms=${ms}`
|
|
2262
2269
|
);
|
|
2263
2270
|
return { conversationId: result.conversationId, created: result.created };
|
|
2264
2271
|
} catch (err) {
|
|
2265
2272
|
const ms = Date.now() - t0;
|
|
2266
2273
|
const reason = err instanceof Error ? `${err.name}:${err.message.slice(0, 200)}` : String(err).slice(0, 200);
|
|
2267
2274
|
console.error(
|
|
2268
|
-
`${TAG8} conversation-merged FAIL
|
|
2275
|
+
`${TAG8} conversation-merged FAIL cacheKey=${input.cacheKey} reason=${reason} ms=${ms}`
|
|
2269
2276
|
);
|
|
2270
2277
|
return null;
|
|
2271
2278
|
}
|
|
@@ -2776,14 +2783,14 @@ function storeMessage(storeKey, entry) {
|
|
|
2776
2783
|
console.error(`${TAG13} message store trimmed for ${storeKey}: ${trimmed} oldest messages removed`);
|
|
2777
2784
|
}
|
|
2778
2785
|
}
|
|
2779
|
-
function
|
|
2786
|
+
function deriveCacheKey(input) {
|
|
2780
2787
|
if (input.isOwnerMirror || input.agentType === "admin") {
|
|
2781
2788
|
return `whatsapp:${input.accountId}`;
|
|
2782
2789
|
}
|
|
2783
2790
|
if (input.isGroup) {
|
|
2784
2791
|
if (!input.groupJid) {
|
|
2785
2792
|
throw new Error(
|
|
2786
|
-
`
|
|
2793
|
+
`deriveCacheKey: isGroup=true requires groupJid (accountId=${input.accountId}, senderPhone=${input.senderPhone})`
|
|
2787
2794
|
);
|
|
2788
2795
|
}
|
|
2789
2796
|
return `whatsapp:${input.accountId}:group:${input.groupJid}`;
|
|
@@ -3262,14 +3269,14 @@ function monitorInbound(conn) {
|
|
|
3262
3269
|
jid: remoteJid
|
|
3263
3270
|
});
|
|
3264
3271
|
const fromMe = Boolean(msg.key.fromMe);
|
|
3265
|
-
const
|
|
3272
|
+
const cacheKeyAgentType = isGroup ? "public" : fromMe ? "admin" : checkDmAccess({
|
|
3266
3273
|
senderPhone,
|
|
3267
3274
|
selfPhone: conn.selfPhone ?? "",
|
|
3268
3275
|
config: whatsAppConfig,
|
|
3269
3276
|
accountConfig: whatsAppConfig.accounts?.[conn.accountId]
|
|
3270
3277
|
}).agentType;
|
|
3271
|
-
const
|
|
3272
|
-
agentType:
|
|
3278
|
+
const cacheKey = deriveCacheKey({
|
|
3279
|
+
agentType: cacheKeyAgentType,
|
|
3273
3280
|
accountId: conn.accountId,
|
|
3274
3281
|
senderPhone,
|
|
3275
3282
|
isGroup,
|
|
@@ -3280,8 +3287,8 @@ function monitorInbound(conn) {
|
|
|
3280
3287
|
const merged = await ensureWhatsAppConversation({
|
|
3281
3288
|
accountId: conn.accountId,
|
|
3282
3289
|
platformAccountId: conn.platformAccountId,
|
|
3283
|
-
|
|
3284
|
-
agentType:
|
|
3290
|
+
cacheKey,
|
|
3291
|
+
agentType: cacheKeyAgentType,
|
|
3285
3292
|
groupJid: isGroup ? remoteJid : void 0
|
|
3286
3293
|
});
|
|
3287
3294
|
if (merged) {
|
|
@@ -3289,7 +3296,8 @@ function monitorInbound(conn) {
|
|
|
3289
3296
|
accountId: conn.accountId,
|
|
3290
3297
|
platformAccountId: conn.platformAccountId,
|
|
3291
3298
|
remoteJid,
|
|
3292
|
-
|
|
3299
|
+
cacheKey,
|
|
3300
|
+
conversationId: merged.conversationId,
|
|
3293
3301
|
msgKeyId: msg.key.id,
|
|
3294
3302
|
fromMe,
|
|
3295
3303
|
senderPhone,
|
|
@@ -3371,7 +3379,7 @@ async function handleInboundMessage(conn, msg) {
|
|
|
3371
3379
|
isGroup: isGroup2,
|
|
3372
3380
|
groupJid: isGroup2 ? remoteJid : void 0,
|
|
3373
3381
|
reply: reply2,
|
|
3374
|
-
|
|
3382
|
+
cacheKey: deriveCacheKey({
|
|
3375
3383
|
agentType: "admin",
|
|
3376
3384
|
accountId: conn.accountId,
|
|
3377
3385
|
senderPhone: senderPhone2,
|
|
@@ -3465,7 +3473,7 @@ async function handleInboundMessage(conn, msg) {
|
|
|
3465
3473
|
if (!currentSock) throw new Error("WhatsApp disconnected \u2014 cannot reply");
|
|
3466
3474
|
await sendTextMessage(currentSock, remoteJid, text, { accountId: conn.accountId });
|
|
3467
3475
|
};
|
|
3468
|
-
const
|
|
3476
|
+
const cacheKey = deriveCacheKey({
|
|
3469
3477
|
agentType: accessResult.agentType,
|
|
3470
3478
|
accountId: conn.accountId,
|
|
3471
3479
|
senderPhone,
|
|
@@ -3482,7 +3490,7 @@ async function handleInboundMessage(conn, msg) {
|
|
|
3482
3490
|
groupJid: isGroup ? remoteJid : void 0,
|
|
3483
3491
|
groupSubject,
|
|
3484
3492
|
reply,
|
|
3485
|
-
|
|
3493
|
+
cacheKey,
|
|
3486
3494
|
mediaPath: mediaResult?.path,
|
|
3487
3495
|
mediaMimetype: mediaResult?.mimetype,
|
|
3488
3496
|
mediaType: extracted.mediaType,
|
|
@@ -3827,9 +3835,9 @@ app2.post("/", async (c) => {
|
|
|
3827
3835
|
...m.role === "user" ? { senderName: m.senderName } : {}
|
|
3828
3836
|
});
|
|
3829
3837
|
}
|
|
3830
|
-
const
|
|
3831
|
-
registerResumedSession(
|
|
3832
|
-
setGroupContextForSession(
|
|
3838
|
+
const cacheKey2 = crypto.randomUUID();
|
|
3839
|
+
registerResumedSession(cacheKey2, accountId, agentSlug, groupInfo.conversationId, agentMessages);
|
|
3840
|
+
setGroupContextForSession(cacheKey2, {
|
|
3833
3841
|
groupSlug,
|
|
3834
3842
|
groupName: groupInfo.groupName,
|
|
3835
3843
|
conversationId: groupInfo.conversationId,
|
|
@@ -3841,7 +3849,7 @@ app2.post("/", async (c) => {
|
|
|
3841
3849
|
console.log(`[session] cold-resume group=${groupSlug} visitor=${visitorId.slice(0, 8)}\u2026 messages=${uiMessages.length}`);
|
|
3842
3850
|
return withVisitorCookie(
|
|
3843
3851
|
Response.json({
|
|
3844
|
-
session_key:
|
|
3852
|
+
session_key: cacheKey2,
|
|
3845
3853
|
agent_id: agentSlug,
|
|
3846
3854
|
resumed,
|
|
3847
3855
|
...resumed ? { messages: uiMessages } : {},
|
|
@@ -3884,13 +3892,13 @@ app2.post("/", async (c) => {
|
|
|
3884
3892
|
content: m.content,
|
|
3885
3893
|
timestamp: new Date(m.createdAt).getTime() || Date.now()
|
|
3886
3894
|
}));
|
|
3887
|
-
const
|
|
3888
|
-
registerResumedSession(
|
|
3895
|
+
const cacheKey2 = crypto.randomUUID();
|
|
3896
|
+
registerResumedSession(cacheKey2, accountId, agentSlug, recent.conversationId, agentMessages);
|
|
3889
3897
|
const resumed = uiMessages.length > 0;
|
|
3890
3898
|
console.log(`[session] cold-resume visitor=${visitorId.slice(0, 8)}\u2026 conversation=${recent.conversationId.slice(0, 8)}\u2026 messages=${uiMessages.length}`);
|
|
3891
3899
|
return withVisitorCookie(
|
|
3892
3900
|
Response.json({
|
|
3893
|
-
session_key:
|
|
3901
|
+
session_key: cacheKey2,
|
|
3894
3902
|
agent_id: agentSlug,
|
|
3895
3903
|
resumed,
|
|
3896
3904
|
...resumed ? { messages: uiMessages } : {},
|
|
@@ -3902,13 +3910,13 @@ app2.post("/", async (c) => {
|
|
|
3902
3910
|
}
|
|
3903
3911
|
}
|
|
3904
3912
|
const newVisitorId = visitorId ?? crypto.randomUUID();
|
|
3905
|
-
const
|
|
3906
|
-
registerSession(
|
|
3913
|
+
const cacheKey = crypto.randomUUID();
|
|
3914
|
+
registerSession(cacheKey, "public", accountId, agentSlug);
|
|
3907
3915
|
const hasImage = agentConfig?.image ? "yes" : "no";
|
|
3908
|
-
console.log(`[session] new-session visitor=${newVisitorId.slice(0, 8)}\u2026 session=${
|
|
3916
|
+
console.log(`[session] new-session visitor=${newVisitorId.slice(0, 8)}\u2026 session=${cacheKey.slice(0, 8)}\u2026 agent=${agentSlug} image=${hasImage} showAgentName=${agentConfig?.showAgentName ?? false}`);
|
|
3909
3917
|
return withVisitorCookie(
|
|
3910
3918
|
Response.json({
|
|
3911
|
-
session_key:
|
|
3919
|
+
session_key: cacheKey,
|
|
3912
3920
|
agent_id: agentSlug,
|
|
3913
3921
|
...branding ? { branding } : {},
|
|
3914
3922
|
...agentIdentity
|
|
@@ -4501,9 +4509,9 @@ var chat_default = app3;
|
|
|
4501
4509
|
// server/routes/group.ts
|
|
4502
4510
|
var app4 = new Hono();
|
|
4503
4511
|
app4.get("/messages", async (c) => {
|
|
4504
|
-
const
|
|
4512
|
+
const cacheKey = c.req.query("session_key");
|
|
4505
4513
|
const since = c.req.query("since");
|
|
4506
|
-
if (!
|
|
4514
|
+
if (!cacheKey) {
|
|
4507
4515
|
return c.json({ error: "session_key required" }, 400);
|
|
4508
4516
|
}
|
|
4509
4517
|
if (!since) {
|
|
@@ -4513,18 +4521,18 @@ app4.get("/messages", async (c) => {
|
|
|
4513
4521
|
if (isNaN(sinceDate.getTime())) {
|
|
4514
4522
|
return c.json({ error: "Invalid since parameter \u2014 expected ISO 8601" }, 400);
|
|
4515
4523
|
}
|
|
4516
|
-
if (!validateSession(
|
|
4524
|
+
if (!validateSession(cacheKey, "public").ok) {
|
|
4517
4525
|
return c.json({ error: "Session expired" }, 401);
|
|
4518
4526
|
}
|
|
4519
|
-
const groupSlug = getGroupSlugForSession(
|
|
4527
|
+
const groupSlug = getGroupSlugForSession(cacheKey);
|
|
4520
4528
|
if (!groupSlug) {
|
|
4521
4529
|
return c.json({ error: "Not a group session" }, 400);
|
|
4522
4530
|
}
|
|
4523
|
-
const conversationId = getConversationIdForSession(
|
|
4531
|
+
const conversationId = getConversationIdForSession(cacheKey);
|
|
4524
4532
|
if (!conversationId) {
|
|
4525
4533
|
return c.json({ error: "No conversation bound" }, 400);
|
|
4526
4534
|
}
|
|
4527
|
-
const visitorId = getVisitorIdForSession(
|
|
4535
|
+
const visitorId = getVisitorIdForSession(cacheKey);
|
|
4528
4536
|
const POLL_LIMIT = 100;
|
|
4529
4537
|
try {
|
|
4530
4538
|
const messages = await getMessagesSince(conversationId, since, POLL_LIMIT);
|
|
@@ -5021,8 +5029,8 @@ app5.post("/verify-token", async (c) => {
|
|
|
5021
5029
|
}
|
|
5022
5030
|
await consumeMagicToken(result.grantId);
|
|
5023
5031
|
const accountId = result.accountId;
|
|
5024
|
-
const
|
|
5025
|
-
registerGrantSession(
|
|
5032
|
+
const cacheKey = crypto.randomUUID();
|
|
5033
|
+
registerGrantSession(cacheKey, accountId, agentSlug, {
|
|
5026
5034
|
grantId: result.grantId,
|
|
5027
5035
|
grantExpiresAt: result.expiresAt ?? void 0,
|
|
5028
5036
|
grantStatus: result.status,
|
|
@@ -5033,7 +5041,7 @@ app5.post("/verify-token", async (c) => {
|
|
|
5033
5041
|
clearAccessRateLimit(clientIp, agentSlug);
|
|
5034
5042
|
console.error(`[access-gate] verify-token ip=${clientIp} agent=${agentSlug} contact=${maskContact(result.contactValue)} result=success`);
|
|
5035
5043
|
return c.json({
|
|
5036
|
-
session_key:
|
|
5044
|
+
session_key: cacheKey,
|
|
5037
5045
|
grant: {
|
|
5038
5046
|
displayName: result.displayName,
|
|
5039
5047
|
contactValue: result.contactValue,
|
|
@@ -5101,8 +5109,8 @@ app5.post("/verify-otp", async (c) => {
|
|
|
5101
5109
|
}, remaining > 0 ? 401 : 429);
|
|
5102
5110
|
}
|
|
5103
5111
|
await consumeOtp(grant.grantId);
|
|
5104
|
-
const
|
|
5105
|
-
registerGrantSession(
|
|
5112
|
+
const cacheKey = crypto.randomUUID();
|
|
5113
|
+
registerGrantSession(cacheKey, account.accountId, agentSlug, {
|
|
5106
5114
|
grantId: grant.grantId,
|
|
5107
5115
|
grantExpiresAt: grant.expiresAt ?? void 0,
|
|
5108
5116
|
grantStatus: grant.status,
|
|
@@ -5113,7 +5121,7 @@ app5.post("/verify-otp", async (c) => {
|
|
|
5113
5121
|
clearAccessRateLimit(clientIp, agentSlug);
|
|
5114
5122
|
console.error(`[access-gate] verify-otp ip=${clientIp} agent=${agentSlug} phone=${maskContact(phone)} result=success`);
|
|
5115
5123
|
return c.json({
|
|
5116
|
-
session_key:
|
|
5124
|
+
session_key: cacheKey,
|
|
5117
5125
|
grant: {
|
|
5118
5126
|
displayName: grant.displayName,
|
|
5119
5127
|
contactValue: grant.contactValue,
|
|
@@ -5211,8 +5219,8 @@ app5.post("/login", async (c) => {
|
|
|
5211
5219
|
console.error(`[access-gate] login ip=${clientIp} agent=${agentSlug} contact=${maskContact(contact)} result=wrong_password`);
|
|
5212
5220
|
return c.json({ error: "Invalid credentials" }, 401);
|
|
5213
5221
|
}
|
|
5214
|
-
const
|
|
5215
|
-
registerGrantSession(
|
|
5222
|
+
const cacheKey = crypto.randomUUID();
|
|
5223
|
+
registerGrantSession(cacheKey, account.accountId, agentSlug, {
|
|
5216
5224
|
grantId: grant.grantId,
|
|
5217
5225
|
grantExpiresAt: grant.expiresAt ?? void 0,
|
|
5218
5226
|
grantStatus: grant.status,
|
|
@@ -5222,7 +5230,7 @@ app5.post("/login", async (c) => {
|
|
|
5222
5230
|
});
|
|
5223
5231
|
clearAccessRateLimit(clientIp, agentSlug);
|
|
5224
5232
|
console.error(`[access-gate] login ip=${clientIp} agent=${agentSlug} contact=${maskContact(contact)} result=success`);
|
|
5225
|
-
return c.json({ session_key:
|
|
5233
|
+
return c.json({ session_key: cacheKey, agent_id: agentSlug });
|
|
5226
5234
|
} catch (err) {
|
|
5227
5235
|
console.error(`[access-gate] login ip=${clientIp} agent=${agentSlug} error=${err instanceof Error ? err.message : String(err)}`);
|
|
5228
5236
|
return c.json({ error: "Internal server error" }, 500);
|
|
@@ -5381,11 +5389,11 @@ function verifyWebhookSecret(headerValue, storedSecret) {
|
|
|
5381
5389
|
}
|
|
5382
5390
|
async function handleInbound(params) {
|
|
5383
5391
|
const { chatId, senderId, text, botType, botToken, accountId, agentType } = params;
|
|
5384
|
-
const
|
|
5392
|
+
const cacheKey = `telegram:${chatId}`;
|
|
5385
5393
|
const gatewayChannel = agentType === "admin" ? "telegram-admin" : "telegram-dm";
|
|
5386
|
-
registerSession(
|
|
5394
|
+
registerSession(cacheKey, agentType, accountId);
|
|
5387
5395
|
console.error(
|
|
5388
|
-
`${TAG16} session registered:
|
|
5396
|
+
`${TAG16} session registered: cacheKey=${cacheKey} agentType=${agentType} botType=${botType} senderId=${senderId} accountId=${accountId.slice(0, 8)}\u2026`
|
|
5389
5397
|
);
|
|
5390
5398
|
const gatewayResult = await processInbound(text, gatewayChannel);
|
|
5391
5399
|
if (gatewayResult.screening.verdict === "discard") {
|
|
@@ -5399,7 +5407,7 @@ async function handleInbound(params) {
|
|
|
5399
5407
|
for await (const event of invokeAgent(
|
|
5400
5408
|
{ type: agentType },
|
|
5401
5409
|
gatewayResult.processedText,
|
|
5402
|
-
|
|
5410
|
+
cacheKey,
|
|
5403
5411
|
[],
|
|
5404
5412
|
void 0,
|
|
5405
5413
|
gatewayResult
|
|
@@ -6215,19 +6223,25 @@ app7.get("/messages", (c) => {
|
|
|
6215
6223
|
});
|
|
6216
6224
|
app7.get("/conversation-graph-state", async (c) => {
|
|
6217
6225
|
try {
|
|
6218
|
-
const
|
|
6226
|
+
const directCacheKey = c.req.query("cacheKey");
|
|
6219
6227
|
const jid = c.req.query("jid");
|
|
6220
6228
|
const accountIdQuery = c.req.query("accountId");
|
|
6221
|
-
let
|
|
6222
|
-
|
|
6223
|
-
|
|
6229
|
+
let cacheKey;
|
|
6230
|
+
let accountId;
|
|
6231
|
+
if (directCacheKey) {
|
|
6232
|
+
cacheKey = directCacheKey;
|
|
6233
|
+
const m = directCacheKey.match(/^whatsapp:([^:]+)/);
|
|
6234
|
+
if (!m) {
|
|
6235
|
+
return c.json({ error: `cacheKey=${directCacheKey} not a recognised whatsapp cacheKey shape.` }, 400);
|
|
6236
|
+
}
|
|
6237
|
+
accountId = validateAccountId(m[1] ?? accountIdQuery ?? null);
|
|
6224
6238
|
} else {
|
|
6225
6239
|
if (!jid) {
|
|
6226
|
-
return c.json({ error: "Provide either
|
|
6240
|
+
return c.json({ error: "Provide either cacheKey or jid (with optional accountId)." }, 400);
|
|
6227
6241
|
}
|
|
6228
|
-
|
|
6242
|
+
accountId = validateAccountId(accountIdQuery ?? null);
|
|
6229
6243
|
if (isGroupJid(jid)) {
|
|
6230
|
-
|
|
6244
|
+
cacheKey = deriveCacheKey({
|
|
6231
6245
|
agentType: "public",
|
|
6232
6246
|
accountId,
|
|
6233
6247
|
senderPhone: "",
|
|
@@ -6237,9 +6251,9 @@ app7.get("/conversation-graph-state", async (c) => {
|
|
|
6237
6251
|
} else {
|
|
6238
6252
|
const e164 = jid.replace(/^(\d+)(?::\d+)?@s\.whatsapp\.net$/i, "$1");
|
|
6239
6253
|
if (!/^\d+$/.test(e164)) {
|
|
6240
|
-
return c.json({ error: `Cannot derive
|
|
6254
|
+
return c.json({ error: `Cannot derive cacheKey from jid=${jid} \u2014 not a recognised user JID. Pass cacheKey explicitly.` }, 400);
|
|
6241
6255
|
}
|
|
6242
|
-
|
|
6256
|
+
cacheKey = deriveCacheKey({
|
|
6243
6257
|
agentType: "public",
|
|
6244
6258
|
accountId,
|
|
6245
6259
|
senderPhone: e164,
|
|
@@ -6247,8 +6261,9 @@ app7.get("/conversation-graph-state", async (c) => {
|
|
|
6247
6261
|
});
|
|
6248
6262
|
}
|
|
6249
6263
|
}
|
|
6264
|
+
const channelAddress = cacheKey.startsWith("whatsapp:") ? cacheKey.slice("whatsapp:".length) : cacheKey;
|
|
6250
6265
|
const cypher = `
|
|
6251
|
-
MATCH (c:Conversation {
|
|
6266
|
+
MATCH (c:Conversation {accountId: $accountId, channel: 'whatsapp', channelAddress: $channelAddress})
|
|
6252
6267
|
OPTIONAL MATCH (m:Message:WhatsAppMessage)-[:PART_OF]->(c)
|
|
6253
6268
|
RETURN
|
|
6254
6269
|
c.conversationId AS conversationId,
|
|
@@ -6265,7 +6280,7 @@ app7.get("/conversation-graph-state", async (c) => {
|
|
|
6265
6280
|
const rows = [];
|
|
6266
6281
|
try {
|
|
6267
6282
|
session = getSession();
|
|
6268
|
-
const result = await session.run(cypher, {
|
|
6283
|
+
const result = await session.run(cypher, { accountId, channelAddress });
|
|
6269
6284
|
for (const rec of result.records) {
|
|
6270
6285
|
if (conversationId === null) {
|
|
6271
6286
|
conversationId = rec.get("conversationId") ?? null;
|
|
@@ -6283,13 +6298,13 @@ app7.get("/conversation-graph-state", async (c) => {
|
|
|
6283
6298
|
}
|
|
6284
6299
|
} catch (err) {
|
|
6285
6300
|
const msg = err instanceof Error ? err.message : String(err);
|
|
6286
|
-
console.error(`${TAG18} conversation-graph-state ERR
|
|
6287
|
-
return c.json({ error: `Graph query failed: ${msg}`,
|
|
6301
|
+
console.error(`${TAG18} conversation-graph-state ERR cacheKey=${cacheKey} reason=${msg}`);
|
|
6302
|
+
return c.json({ error: `Graph query failed: ${msg}`, cacheKey, cypher: cypher.trim() }, 500);
|
|
6288
6303
|
}
|
|
6289
6304
|
const ms = Date.now() - t0;
|
|
6290
|
-
console.error(`[mcp:whatsapp] tool=whatsapp-conversation-graph-state
|
|
6305
|
+
console.error(`[mcp:whatsapp] tool=whatsapp-conversation-graph-state cacheKey=${cacheKey} graphRows=${rows.length} conversationId=${conversationId ?? "null"} ms=${ms}`);
|
|
6291
6306
|
return c.json({
|
|
6292
|
-
|
|
6307
|
+
cacheKey,
|
|
6293
6308
|
conversationId,
|
|
6294
6309
|
graphRows: rows,
|
|
6295
6310
|
cypher: cypher.trim(),
|
|
@@ -7000,8 +7015,9 @@ async function resolveUserIdentity(accountId, userId) {
|
|
|
7000
7015
|
async function createAdminSession(accountId, thinkingView, userId, userName, role, avatar) {
|
|
7001
7016
|
const account = resolveAccount();
|
|
7002
7017
|
const effectiveThinkingView = thinkingView ?? account?.config.thinkingView ?? "default";
|
|
7003
|
-
const
|
|
7004
|
-
registerSession(
|
|
7018
|
+
const cacheKey = userId ? mintAdminSessionToken({ accountId, userId }) : crypto.randomUUID();
|
|
7019
|
+
registerSession(cacheKey, "admin", accountId, void 0, userId, userName, role);
|
|
7020
|
+
if (userId) setWantsPriorConversation(cacheKey);
|
|
7005
7021
|
let onboardingComplete = true;
|
|
7006
7022
|
try {
|
|
7007
7023
|
const step = await loadOnboardingStep(accountId);
|
|
@@ -7015,10 +7031,27 @@ async function createAdminSession(accountId, thinkingView, userId, userName, rol
|
|
|
7015
7031
|
businessName = branding?.name || void 0;
|
|
7016
7032
|
} catch {
|
|
7017
7033
|
}
|
|
7018
|
-
|
|
7019
|
-
|
|
7034
|
+
let initialConversationId = null;
|
|
7035
|
+
try {
|
|
7036
|
+
const ensured = await ensureConversation(
|
|
7037
|
+
accountId,
|
|
7038
|
+
"admin",
|
|
7039
|
+
cacheKey,
|
|
7040
|
+
void 0,
|
|
7041
|
+
void 0,
|
|
7042
|
+
userId
|
|
7043
|
+
);
|
|
7044
|
+
if (ensured.conversationId) {
|
|
7045
|
+
initialConversationId = ensured.conversationId;
|
|
7046
|
+
setConversationIdForSession(cacheKey, ensured.conversationId);
|
|
7047
|
+
}
|
|
7048
|
+
} catch (err) {
|
|
7049
|
+
console.error(`[session] eager-ensureConversation FAILED at boot: ${err instanceof Error ? err.message : String(err)}`);
|
|
7050
|
+
}
|
|
7051
|
+
console.log(`[session] ${(/* @__PURE__ */ new Date()).toISOString()} admin session created: userId=${userId ?? "\u2013"} userName=${userName ?? "\u2013"} accountId=${accountId} conversationId=${initialConversationId ?? "unbound"} cacheKey=${cacheKey.slice(0, 8)}`);
|
|
7052
|
+
console.log(`[admin-session] role=${role ?? "null"} cacheKey=${cacheKey.slice(0, 8)} phase=create eager-ensured=${initialConversationId ? "true" : "false"}`);
|
|
7020
7053
|
return {
|
|
7021
|
-
session_key:
|
|
7054
|
+
session_key: cacheKey,
|
|
7022
7055
|
agent_id: "admin",
|
|
7023
7056
|
userId,
|
|
7024
7057
|
userName,
|
|
@@ -7027,16 +7060,16 @@ async function createAdminSession(accountId, thinkingView, userId, userName, rol
|
|
|
7027
7060
|
thinkingView: effectiveThinkingView,
|
|
7028
7061
|
onboardingComplete,
|
|
7029
7062
|
businessName,
|
|
7030
|
-
conversationId:
|
|
7063
|
+
conversationId: initialConversationId
|
|
7031
7064
|
};
|
|
7032
7065
|
}
|
|
7033
7066
|
var app10 = new Hono();
|
|
7034
7067
|
app10.get("/", async (c) => {
|
|
7035
|
-
const
|
|
7036
|
-
if (!
|
|
7068
|
+
const cacheKey = c.req.query("session_key");
|
|
7069
|
+
if (!cacheKey || !validateSession(cacheKey, "admin").ok) {
|
|
7037
7070
|
return c.json({ error: "Invalid or expired admin session" }, 401);
|
|
7038
7071
|
}
|
|
7039
|
-
const accountId = getAccountIdForSession(
|
|
7072
|
+
const accountId = getAccountIdForSession(cacheKey);
|
|
7040
7073
|
if (!accountId) {
|
|
7041
7074
|
return c.json({ error: "Session has no account binding" }, 401);
|
|
7042
7075
|
}
|
|
@@ -7055,21 +7088,21 @@ app10.get("/", async (c) => {
|
|
|
7055
7088
|
businessName = branding?.name || void 0;
|
|
7056
7089
|
} catch {
|
|
7057
7090
|
}
|
|
7058
|
-
const role = getRoleForSession(
|
|
7059
|
-
console.log(`[admin-session] role=${role ?? "null"}
|
|
7060
|
-
const restoredUserId = getUserIdForSession(
|
|
7061
|
-
let restoredUserName = getUserNameForSession(
|
|
7091
|
+
const role = getRoleForSession(cacheKey);
|
|
7092
|
+
console.log(`[admin-session] role=${role ?? "null"} cacheKey=${cacheKey.slice(0, 8)} phase=restore`);
|
|
7093
|
+
const restoredUserId = getUserIdForSession(cacheKey);
|
|
7094
|
+
let restoredUserName = getUserNameForSession(cacheKey);
|
|
7062
7095
|
let restoredAvatar = null;
|
|
7063
7096
|
if (restoredUserId) {
|
|
7064
7097
|
const resolved = await resolveUserIdentity(accountId, restoredUserId);
|
|
7065
7098
|
restoredUserName = resolved.userName;
|
|
7066
7099
|
restoredAvatar = resolved.avatar;
|
|
7067
7100
|
if (resolved.userName !== void 0) {
|
|
7068
|
-
registerSession(
|
|
7101
|
+
registerSession(cacheKey, "admin", accountId, void 0, restoredUserId, resolved.userName, role ?? void 0);
|
|
7069
7102
|
}
|
|
7070
7103
|
}
|
|
7071
7104
|
return c.json({
|
|
7072
|
-
session_key:
|
|
7105
|
+
session_key: cacheKey,
|
|
7073
7106
|
agent_id: "admin",
|
|
7074
7107
|
userId: restoredUserId,
|
|
7075
7108
|
userName: restoredUserName,
|
|
@@ -7078,7 +7111,7 @@ app10.get("/", async (c) => {
|
|
|
7078
7111
|
thinkingView,
|
|
7079
7112
|
onboardingComplete,
|
|
7080
7113
|
businessName,
|
|
7081
|
-
conversationId: getConversationIdForSession(
|
|
7114
|
+
conversationId: getConversationIdForSession(cacheKey) ?? null
|
|
7082
7115
|
});
|
|
7083
7116
|
});
|
|
7084
7117
|
app10.post("/", async (c) => {
|
|
@@ -7429,7 +7462,7 @@ ${inner.content}`;
|
|
|
7429
7462
|
}
|
|
7430
7463
|
function chatReject(status, error, sk) {
|
|
7431
7464
|
const keyPrefix = sk ? sk.slice(0, 8) + "\u2026" : "none";
|
|
7432
|
-
console.log(`[session] chat-reject status=${status} reason="${error}"
|
|
7465
|
+
console.log(`[session] chat-reject status=${status} reason="${error}" cacheKey=${keyPrefix}`);
|
|
7433
7466
|
return new Response(JSON.stringify({ error }), {
|
|
7434
7467
|
status,
|
|
7435
7468
|
headers: { "Content-Type": "application/json" }
|
|
@@ -7437,9 +7470,9 @@ function chatReject(status, error, sk) {
|
|
|
7437
7470
|
}
|
|
7438
7471
|
var app11 = new Hono();
|
|
7439
7472
|
app11.post("/cancel", requireAdminSession, async (c) => {
|
|
7440
|
-
const session_key = c.var.
|
|
7473
|
+
const session_key = c.var.cacheKey;
|
|
7441
7474
|
try {
|
|
7442
|
-
const { interruptClient: interruptClient2 } = await import("./client-pool-
|
|
7475
|
+
const { interruptClient: interruptClient2 } = await import("./client-pool-AIZ5QKFD.js");
|
|
7443
7476
|
await interruptClient2(session_key);
|
|
7444
7477
|
return c.json({ ok: true });
|
|
7445
7478
|
} catch (err) {
|
|
@@ -7447,7 +7480,7 @@ app11.post("/cancel", requireAdminSession, async (c) => {
|
|
|
7447
7480
|
}
|
|
7448
7481
|
});
|
|
7449
7482
|
app11.post("/", requireAdminSession, async (c) => {
|
|
7450
|
-
const session_key = c.var.
|
|
7483
|
+
const session_key = c.var.cacheKey;
|
|
7451
7484
|
const contentType = c.req.header("content-type") ?? "";
|
|
7452
7485
|
let message;
|
|
7453
7486
|
let userTimestamp;
|
|
@@ -7528,7 +7561,7 @@ app11.post("/", requireAdminSession, async (c) => {
|
|
|
7528
7561
|
try {
|
|
7529
7562
|
const authResult = await ensureAuth();
|
|
7530
7563
|
if (authResult.status === "dead" || authResult.status === "missing") {
|
|
7531
|
-
console.log(`[session] chat-reject status=401 reason="auth_expired"
|
|
7564
|
+
console.log(`[session] chat-reject status=401 reason="auth_expired" cacheKey=${session_key.slice(0, 8)}\u2026 auth_status=${authResult.status}`);
|
|
7532
7565
|
return new Response(
|
|
7533
7566
|
JSON.stringify({ error: "auth_expired", auth_status: authResult.status }),
|
|
7534
7567
|
{ status: 401, headers: { "Content-Type": "application/json" } }
|
|
@@ -7596,29 +7629,53 @@ app11.post("/", requireAdminSession, async (c) => {
|
|
|
7596
7629
|
if (!isSystemMessage) {
|
|
7597
7630
|
gatewayResult = await processInbound(message, "web-admin");
|
|
7598
7631
|
}
|
|
7632
|
+
let acquireReason = "cold";
|
|
7633
|
+
let resumedAgentSessionId = null;
|
|
7599
7634
|
let conversationId = getConversationIdForSession(session_key);
|
|
7600
|
-
if (
|
|
7635
|
+
if (conversationId) {
|
|
7636
|
+
acquireReason = getActiveClient(session_key) ? "warm" : "cold";
|
|
7637
|
+
} else {
|
|
7601
7638
|
const userId = getUserIdForSession(session_key);
|
|
7602
7639
|
const userName = getUserNameForSession(session_key);
|
|
7603
7640
|
const accountId = getAccountIdForSession(session_key);
|
|
7604
7641
|
if (!userId || !accountId) {
|
|
7605
7642
|
return chatReject(401, "Invalid or expired admin session", session_key);
|
|
7606
7643
|
}
|
|
7607
|
-
const
|
|
7608
|
-
const
|
|
7609
|
-
if (
|
|
7610
|
-
|
|
7644
|
+
const wantsPrior = consumeWantsPriorConversation(session_key);
|
|
7645
|
+
const prior = wantsPrior ? await getMostRecentAdminConversationForUser(accountId, userId) : null;
|
|
7646
|
+
if (prior) {
|
|
7647
|
+
conversationId = prior.conversationId;
|
|
7648
|
+
setConversationIdForSession(session_key, conversationId);
|
|
7649
|
+
setAgentSessionId(session_key, prior.agentSessionId);
|
|
7650
|
+
resumedAgentSessionId = prior.agentSessionId;
|
|
7651
|
+
acquireReason = "pin-rebind";
|
|
7652
|
+
console.log(`[chat-route] resume-from-prior conversationId=${conversationId.slice(0, 8)}\u2026 priorAgentSessionId=${prior.agentSessionId.slice(0, 8)}\u2026 cacheKey=${session_key.slice(0, 12)}\u2026`);
|
|
7653
|
+
} else {
|
|
7654
|
+
if (wantsPrior) {
|
|
7655
|
+
console.log(`[chat-route] prior-conversation-not-found accountId=${accountId.slice(0, 8)}\u2026 userId=${userId.slice(0, 8)}\u2026 cacheKey=${session_key.slice(0, 12)}\u2026 \u2014 cold-minting`);
|
|
7656
|
+
}
|
|
7657
|
+
const minted = randomUUID6();
|
|
7658
|
+
const created = await createNewAdminConversation(userId, accountId, session_key, userName, minted);
|
|
7659
|
+
if (!created) {
|
|
7660
|
+
return chatReject(500, "Failed to create conversation", session_key);
|
|
7661
|
+
}
|
|
7662
|
+
conversationId = created;
|
|
7663
|
+
setConversationIdForSession(session_key, conversationId);
|
|
7664
|
+
acquireReason = "cold";
|
|
7665
|
+
console.log(`[chat-route] new conversation conversationId=${conversationId} cacheKey=${session_key.slice(0, 12)}\u2026`);
|
|
7611
7666
|
}
|
|
7612
|
-
conversationId = created;
|
|
7613
|
-
setConversationIdForSession(session_key, conversationId);
|
|
7614
|
-
console.log(`[chat-route] new conversation conversationId=${conversationId} sessionKey=${session_key.slice(0, 12)}\u2026`);
|
|
7615
7667
|
}
|
|
7616
7668
|
const encoder = new TextEncoder();
|
|
7617
7669
|
const sseLogStream = agentLogStream("sse-events", account.accountDir, conversationId);
|
|
7618
7670
|
const sk = conversationId.slice(0, 8);
|
|
7619
7671
|
const teeStreamLogPath = resolve8(account.accountDir, "logs", `claude-agent-stream-${conversationId}.log`);
|
|
7620
7672
|
try {
|
|
7621
|
-
appendFileSync3(teeStreamLogPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] [chat-route-version=task965-mint-at-entry]
|
|
7673
|
+
appendFileSync3(teeStreamLogPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] [chat-route-version=task965-mint-at-entry] cacheKey=${session_key.slice(0, 12)}\u2026 conversationId=${conversationId}
|
|
7674
|
+
`);
|
|
7675
|
+
} catch {
|
|
7676
|
+
}
|
|
7677
|
+
try {
|
|
7678
|
+
appendFileSync3(teeStreamLogPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] [client-acquire] cacheKey=${session_key.slice(0, 12)}\u2026 resume=${resumedAgentSessionId ? resumedAgentSessionId.slice(0, 8) + "\u2026" : "none"} reason=${acquireReason}
|
|
7622
7679
|
`);
|
|
7623
7680
|
} catch {
|
|
7624
7681
|
}
|
|
@@ -7627,12 +7684,12 @@ app11.post("/", requireAdminSession, async (c) => {
|
|
|
7627
7684
|
incoming.on("close", () => {
|
|
7628
7685
|
const tsClose = (/* @__PURE__ */ new Date()).toISOString();
|
|
7629
7686
|
try {
|
|
7630
|
-
appendFileSync3(teeStreamLogPath, `[${tsClose}] [incoming-close]
|
|
7687
|
+
appendFileSync3(teeStreamLogPath, `[${tsClose}] [incoming-close] cacheKey=${session_key.slice(0, 12)}\u2026 complete=${incoming.complete}
|
|
7631
7688
|
`);
|
|
7632
7689
|
} catch {
|
|
7633
7690
|
}
|
|
7634
7691
|
if (incoming.complete === false) {
|
|
7635
|
-
console.error(`[${tsClose}] [incoming-close] DISCONNECT
|
|
7692
|
+
console.error(`[${tsClose}] [incoming-close] DISCONNECT cacheKey=${session_key.slice(0, 12)}\u2026`);
|
|
7636
7693
|
interruptClient(session_key).catch((err) => {
|
|
7637
7694
|
try {
|
|
7638
7695
|
appendFileSync3(teeStreamLogPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] [incoming-close] interrupt-failed: ${err instanceof Error ? err.message : String(err)}
|
|
@@ -7688,7 +7745,7 @@ app11.post("/", requireAdminSession, async (c) => {
|
|
|
7688
7745
|
const reasonStr = typeof reason === "string" ? reason : reason instanceof Error ? reason.message : "consumer-cancelled";
|
|
7689
7746
|
sseLog.write(`[${ts}] [${sk}] admin: CANCEL [stream-cancel] reason=${reasonStr}
|
|
7690
7747
|
`);
|
|
7691
|
-
console.error(`[${(/* @__PURE__ */ new Date()).toISOString()}] [stream-cancel-callback]
|
|
7748
|
+
console.error(`[${(/* @__PURE__ */ new Date()).toISOString()}] [stream-cancel-callback] cacheKey=${session_key.slice(0, 12)}\u2026 reason=${JSON.stringify(reasonStr)}`);
|
|
7692
7749
|
interruptClient(session_key).catch((err) => {
|
|
7693
7750
|
sseLog.write(`[${ts}] [${sk}] admin: ABORT [interrupt-failed] ${err instanceof Error ? err.message : String(err)}
|
|
7694
7751
|
`);
|
|
@@ -7696,7 +7753,7 @@ app11.post("/", requireAdminSession, async (c) => {
|
|
|
7696
7753
|
},
|
|
7697
7754
|
async start(controller) {
|
|
7698
7755
|
let controllerOpen = true;
|
|
7699
|
-
const sseEntry = { controller, conversationId,
|
|
7756
|
+
const sseEntry = { controller, conversationId, cacheKey: session_key };
|
|
7700
7757
|
try {
|
|
7701
7758
|
const reqSignal = c.req.raw?.signal;
|
|
7702
7759
|
if (reqSignal) {
|
|
@@ -7810,14 +7867,89 @@ app11.post("/", requireAdminSession, async (c) => {
|
|
|
7810
7867
|
});
|
|
7811
7868
|
var chat_default2 = app11;
|
|
7812
7869
|
|
|
7813
|
-
// server/routes/admin/
|
|
7870
|
+
// server/routes/admin/chat-failure.ts
|
|
7871
|
+
var MODE_VALUES = /* @__PURE__ */ new Set(["server-shutdown", "client-network-drop"]);
|
|
7872
|
+
var UUID_RE3 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
7873
|
+
var ISO_RE = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,3})?(?:Z|[+-]\d{2}:\d{2})$/;
|
|
7874
|
+
function validate(body) {
|
|
7875
|
+
if (typeof body.mode !== "string" || !MODE_VALUES.has(body.mode)) {
|
|
7876
|
+
return { ok: false, reason: "mode" };
|
|
7877
|
+
}
|
|
7878
|
+
if (typeof body.at !== "string" || !ISO_RE.test(body.at)) {
|
|
7879
|
+
return { ok: false, reason: "at" };
|
|
7880
|
+
}
|
|
7881
|
+
if (body.conversationId !== null && (typeof body.conversationId !== "string" || !UUID_RE3.test(body.conversationId))) {
|
|
7882
|
+
return { ok: false, reason: "conversationId" };
|
|
7883
|
+
}
|
|
7884
|
+
if (typeof body.prior_event_count !== "number" || !Number.isInteger(body.prior_event_count) || body.prior_event_count < 0) {
|
|
7885
|
+
return { ok: false, reason: "prior_event_count" };
|
|
7886
|
+
}
|
|
7887
|
+
return {
|
|
7888
|
+
ok: true,
|
|
7889
|
+
value: {
|
|
7890
|
+
mode: body.mode,
|
|
7891
|
+
at: body.at,
|
|
7892
|
+
conversationId: body.conversationId,
|
|
7893
|
+
priorEventCount: body.prior_event_count
|
|
7894
|
+
}
|
|
7895
|
+
};
|
|
7896
|
+
}
|
|
7814
7897
|
var app12 = new Hono();
|
|
7815
7898
|
app12.post("/", requireAdminSession, async (c) => {
|
|
7816
|
-
|
|
7899
|
+
let body;
|
|
7900
|
+
try {
|
|
7901
|
+
body = await c.req.json();
|
|
7902
|
+
} catch {
|
|
7903
|
+
console.error(`[admin-chat-failure] persist kind=? conversationId=? writer=clientReport outcome=fail reason=body-not-json`);
|
|
7904
|
+
return c.json({ ok: false, reason: "body-not-json" }, 400);
|
|
7905
|
+
}
|
|
7906
|
+
const v = validate(body);
|
|
7907
|
+
if (!v.ok) {
|
|
7908
|
+
console.error(`[admin-chat-failure] persist kind=? conversationId=? writer=clientReport outcome=fail reason=schema:${v.reason}`);
|
|
7909
|
+
return c.json({ ok: false, reason: `schema:${v.reason}` }, 400);
|
|
7910
|
+
}
|
|
7911
|
+
const cacheKey = c.var.cacheKey;
|
|
7912
|
+
const accountId = getAccountIdForSession(cacheKey);
|
|
7913
|
+
if (!accountId) {
|
|
7914
|
+
console.error(`[admin-chat-failure] persist kind=${v.value.mode} conversationId=? writer=clientReport outcome=fail reason=no-account`);
|
|
7915
|
+
return c.json({ ok: false, reason: "no-account" }, 401);
|
|
7916
|
+
}
|
|
7917
|
+
const cid = v.value.conversationId;
|
|
7918
|
+
const cidTag = cid ? cid : "null";
|
|
7919
|
+
console.error(`[admin-chat] stream-drop kind=${v.value.mode} conversationId=${cidTag} at=${v.value.at}`);
|
|
7920
|
+
if (cid === null) {
|
|
7921
|
+
console.error(`[admin-chat-failure] persist kind=${v.value.mode} conversationId=null writer=clientReport outcome=skip reason=no-cid`);
|
|
7922
|
+
return c.body(null, 204);
|
|
7923
|
+
}
|
|
7924
|
+
const result = await writeTurnFailure({
|
|
7925
|
+
conversationId: cid,
|
|
7926
|
+
accountId,
|
|
7927
|
+
mode: v.value.mode,
|
|
7928
|
+
at: v.value.at,
|
|
7929
|
+
cacheKey,
|
|
7930
|
+
priorEventCount: v.value.priorEventCount
|
|
7931
|
+
});
|
|
7932
|
+
if (!result.ok) {
|
|
7933
|
+
if (result.reason === "cid-not-found") {
|
|
7934
|
+
console.error(`[admin-chat-failure] persist kind=${v.value.mode} conversationId=${cid} writer=clientReport outcome=skip reason=cid-not-found`);
|
|
7935
|
+
return c.body(null, 204);
|
|
7936
|
+
}
|
|
7937
|
+
console.error(`[admin-chat-failure] persist kind=${v.value.mode} conversationId=${cid} writer=clientReport outcome=fail reason=${result.reason}`);
|
|
7938
|
+
return c.json({ ok: false, reason: result.reason }, 500);
|
|
7939
|
+
}
|
|
7940
|
+
console.error(`[admin-chat-failure] persist kind=${v.value.mode} conversationId=${cid} writer=clientReport outcome=ok at=${result.at}`);
|
|
7941
|
+
return c.json({ ok: true, at: result.at });
|
|
7942
|
+
});
|
|
7943
|
+
var chat_failure_default = app12;
|
|
7944
|
+
|
|
7945
|
+
// server/routes/admin/compact.ts
|
|
7946
|
+
var app13 = new Hono();
|
|
7947
|
+
app13.post("/", requireAdminSession, async (c) => {
|
|
7948
|
+
const cacheKey = c.var.cacheKey;
|
|
7817
7949
|
const encoder = new TextEncoder();
|
|
7818
7950
|
const stream = new ReadableStream({
|
|
7819
7951
|
async start(controller) {
|
|
7820
|
-
const iter = compactSession(
|
|
7952
|
+
const iter = compactSession(cacheKey);
|
|
7821
7953
|
let step = await iter.next();
|
|
7822
7954
|
while (!step.done) {
|
|
7823
7955
|
controller.enqueue(encoder.encode(`data: ${JSON.stringify({ type: "status", message: step.value })}
|
|
@@ -7839,18 +7971,18 @@ app12.post("/", requireAdminSession, async (c) => {
|
|
|
7839
7971
|
}
|
|
7840
7972
|
});
|
|
7841
7973
|
});
|
|
7842
|
-
var compact_default =
|
|
7974
|
+
var compact_default = app13;
|
|
7843
7975
|
|
|
7844
7976
|
// server/routes/admin/logs.ts
|
|
7845
7977
|
import { existsSync as existsSync12, readdirSync as readdirSync5, readFileSync as readFileSync11, statSync as statSync6 } from "fs";
|
|
7846
7978
|
import { resolve as resolve9, basename as basename2 } from "path";
|
|
7847
7979
|
var TAIL_BYTES = 8192;
|
|
7848
|
-
var
|
|
7849
|
-
|
|
7980
|
+
var app14 = new Hono();
|
|
7981
|
+
app14.get("/", async (c) => {
|
|
7850
7982
|
const fileParam = c.req.query("file");
|
|
7851
7983
|
const typeParam = c.req.query("type");
|
|
7852
7984
|
const conversationIdParam = c.req.query("conversationId");
|
|
7853
|
-
const
|
|
7985
|
+
const cacheKeyParam = c.req.query("cacheKey");
|
|
7854
7986
|
const download = c.req.query("download") === "1";
|
|
7855
7987
|
const account = resolveAccount();
|
|
7856
7988
|
const accountLogDir = account ? resolve9(account.accountDir, "logs") : null;
|
|
@@ -7897,56 +8029,29 @@ app13.get("/", async (c) => {
|
|
|
7897
8029
|
400
|
|
7898
8030
|
);
|
|
7899
8031
|
}
|
|
7900
|
-
if (!conversationIdParam && !
|
|
8032
|
+
if (!conversationIdParam && !cacheKeyParam) {
|
|
7901
8033
|
console.warn(`[admin/logs] rejected type=${typeParam} reason=no-id`);
|
|
7902
8034
|
return c.json(
|
|
7903
|
-
{ error: `type=${typeParam} requires conversationId or
|
|
8035
|
+
{ error: `type=${typeParam} requires conversationId or cacheKey`, code: "ID_REQUIRED" },
|
|
7904
8036
|
400
|
|
7905
8037
|
);
|
|
7906
8038
|
}
|
|
7907
|
-
|
|
7908
|
-
|
|
7909
|
-
if (!sessionKey && conversationId || sessionKey && !conversationId) {
|
|
7910
|
-
const neoSession = getSession();
|
|
7911
|
-
try {
|
|
7912
|
-
if (!sessionKey && conversationId) {
|
|
7913
|
-
const result = await neoSession.run(
|
|
7914
|
-
`MATCH (c:Conversation {conversationId: $conversationId})
|
|
7915
|
-
RETURN c.sessionKey AS sessionKey LIMIT 1`,
|
|
7916
|
-
{ conversationId }
|
|
7917
|
-
);
|
|
7918
|
-
const sk = result.records[0]?.get("sessionKey");
|
|
7919
|
-
if (typeof sk === "string" && sk.length > 0) sessionKey = sk;
|
|
7920
|
-
} else if (sessionKey && !conversationId) {
|
|
7921
|
-
const result = await neoSession.run(
|
|
7922
|
-
`MATCH (c:Conversation {sessionKey: $sessionKey})
|
|
7923
|
-
RETURN c.conversationId AS conversationId LIMIT 1`,
|
|
7924
|
-
{ sessionKey }
|
|
7925
|
-
);
|
|
7926
|
-
const cid = result.records[0]?.get("conversationId");
|
|
7927
|
-
if (typeof cid === "string" && cid.length > 0) conversationId = cid;
|
|
7928
|
-
}
|
|
7929
|
-
} catch (err) {
|
|
7930
|
-
const reason2 = err instanceof Error ? err.message : String(err);
|
|
7931
|
-
console.warn(`[admin/logs] id-lookup-neo4j-error sessionKey=${sessionKey ?? "none"} conversationId=${conversationId ?? "none"} reason=${reason2}`);
|
|
7932
|
-
} finally {
|
|
7933
|
-
await neoSession.close();
|
|
7934
|
-
}
|
|
7935
|
-
}
|
|
8039
|
+
const cacheKey = cacheKeyParam ?? null;
|
|
8040
|
+
const conversationId = conversationIdParam ?? null;
|
|
7936
8041
|
const MISSING_SENTINEL = ".task702-identifier-not-supplied.log";
|
|
7937
8042
|
const fullFilename = conversationId ? `${prefix}-${conversationId}.log` : MISSING_SENTINEL;
|
|
7938
|
-
const preflushFilename =
|
|
8043
|
+
const preflushFilename = cacheKey && typeParam === "public" ? `${prefix}-${preflushSliceOf(cacheKey)}.log` : MISSING_SENTINEL;
|
|
7939
8044
|
const { hits, stalePreflushPaths, tried } = resolveConversationLogPaths(
|
|
7940
8045
|
fullFilename,
|
|
7941
8046
|
preflushFilename,
|
|
7942
8047
|
logDirs
|
|
7943
8048
|
);
|
|
7944
8049
|
const stalePreflushCount = stalePreflushPaths.length;
|
|
7945
|
-
const
|
|
8050
|
+
const cacheKeySlice = cacheKey ? cacheKey.slice(0, 12) : "none";
|
|
7946
8051
|
const conversationIdSlice = conversationId ? conversationId.slice(0, 12) : "none";
|
|
7947
8052
|
if (hits.length > 0) {
|
|
7948
8053
|
const hit = hits[0];
|
|
7949
|
-
console.info(`[admin/logs] resolved
|
|
8054
|
+
console.info(`[admin/logs] resolved cacheKey=${cacheKeySlice} conversationId=${conversationIdSlice} shape=${hit.shape} stalePreflushCount=${stalePreflushCount}`);
|
|
7950
8055
|
try {
|
|
7951
8056
|
const filename = basename2(hit.path);
|
|
7952
8057
|
if (stalePreflushCount > 0 && !download) {
|
|
@@ -7976,14 +8081,14 @@ app13.get("/", async (c) => {
|
|
|
7976
8081
|
);
|
|
7977
8082
|
}
|
|
7978
8083
|
}
|
|
7979
|
-
const reason = !conversationId ? "no preflush log on disk for
|
|
7980
|
-
console.warn(`[admin/logs] not-found tried=[${tried.join(",")}]
|
|
8084
|
+
const reason = !conversationId ? "no preflush log on disk for cacheKey and conversationId not derivable" : !cacheKey ? "no full log on disk and cacheKey not derivable" : "no preflush log, no full log";
|
|
8085
|
+
console.warn(`[admin/logs] not-found tried=[${tried.join(",")}] cacheKey=${cacheKeySlice} conversationId=${conversationIdSlice} reason=${JSON.stringify(reason)}`);
|
|
7981
8086
|
return c.json(
|
|
7982
8087
|
{
|
|
7983
8088
|
error: reason,
|
|
7984
8089
|
code: "NOT_FOUND",
|
|
7985
8090
|
reason,
|
|
7986
|
-
|
|
8091
|
+
cacheKey: cacheKey ?? null,
|
|
7987
8092
|
conversationId: conversationId ?? null
|
|
7988
8093
|
},
|
|
7989
8094
|
404
|
|
@@ -8016,12 +8121,12 @@ app13.get("/", async (c) => {
|
|
|
8016
8121
|
}
|
|
8017
8122
|
return c.json({ logs });
|
|
8018
8123
|
});
|
|
8019
|
-
var logs_default =
|
|
8124
|
+
var logs_default = app14;
|
|
8020
8125
|
|
|
8021
8126
|
// server/routes/admin/claude-info.ts
|
|
8022
8127
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
8023
|
-
var
|
|
8024
|
-
|
|
8128
|
+
var app15 = new Hono();
|
|
8129
|
+
app15.get("/", (c) => {
|
|
8025
8130
|
let version = "unknown";
|
|
8026
8131
|
try {
|
|
8027
8132
|
const raw = execFileSync2("claude", ["--version"], { encoding: "utf-8", timeout: 5e3 });
|
|
@@ -8039,17 +8144,17 @@ app14.get("/", (c) => {
|
|
|
8039
8144
|
const thinkingView = resolvedAccount?.config.thinkingView ?? "default";
|
|
8040
8145
|
return c.json({ version, account, model, thinkingView });
|
|
8041
8146
|
});
|
|
8042
|
-
var claude_info_default =
|
|
8147
|
+
var claude_info_default = app15;
|
|
8043
8148
|
|
|
8044
8149
|
// server/routes/admin/attachment.ts
|
|
8045
8150
|
import { readFile as readFile2, readdir } from "fs/promises";
|
|
8046
8151
|
import { existsSync as existsSync13 } from "fs";
|
|
8047
8152
|
import { resolve as resolve10 } from "path";
|
|
8048
|
-
var
|
|
8049
|
-
|
|
8153
|
+
var app16 = new Hono();
|
|
8154
|
+
app16.get("/:attachmentId", requireAdminSession, async (c) => {
|
|
8050
8155
|
const attachmentId = c.req.param("attachmentId");
|
|
8051
|
-
const
|
|
8052
|
-
const accountId = getAccountIdForSession(
|
|
8156
|
+
const cacheKey = c.var.cacheKey;
|
|
8157
|
+
const accountId = getAccountIdForSession(cacheKey);
|
|
8053
8158
|
if (!accountId) {
|
|
8054
8159
|
return new Response("Unauthorized", { status: 401 });
|
|
8055
8160
|
}
|
|
@@ -8085,13 +8190,13 @@ app15.get("/:attachmentId", requireAdminSession, async (c) => {
|
|
|
8085
8190
|
}
|
|
8086
8191
|
});
|
|
8087
8192
|
});
|
|
8088
|
-
var attachment_default =
|
|
8193
|
+
var attachment_default = app16;
|
|
8089
8194
|
|
|
8090
8195
|
// server/routes/admin/agents.ts
|
|
8091
8196
|
import { resolve as resolve11 } from "path";
|
|
8092
8197
|
import { readdirSync as readdirSync6, readFileSync as readFileSync12, existsSync as existsSync14, rmSync } from "fs";
|
|
8093
|
-
var
|
|
8094
|
-
|
|
8198
|
+
var app17 = new Hono();
|
|
8199
|
+
app17.get("/", (c) => {
|
|
8095
8200
|
const account = resolveAccount();
|
|
8096
8201
|
if (!account) return c.json({ agents: [] });
|
|
8097
8202
|
const agentsDir = resolve11(account.accountDir, "agents");
|
|
@@ -8121,7 +8226,7 @@ app16.get("/", (c) => {
|
|
|
8121
8226
|
}
|
|
8122
8227
|
return c.json({ agents });
|
|
8123
8228
|
});
|
|
8124
|
-
|
|
8229
|
+
app17.delete("/:slug", async (c) => {
|
|
8125
8230
|
const slug = c.req.param("slug");
|
|
8126
8231
|
const account = resolveAccount();
|
|
8127
8232
|
if (!account) return c.json({ error: "No account resolved" }, 400);
|
|
@@ -8151,7 +8256,7 @@ app16.delete("/:slug", async (c) => {
|
|
|
8151
8256
|
return c.json({ error: "Failed to delete agent" }, 500);
|
|
8152
8257
|
}
|
|
8153
8258
|
});
|
|
8154
|
-
|
|
8259
|
+
app17.post("/:slug/project", async (c) => {
|
|
8155
8260
|
const slug = c.req.param("slug");
|
|
8156
8261
|
const account = resolveAccount();
|
|
8157
8262
|
if (!account) return c.json({ error: "No account resolved" }, 400);
|
|
@@ -8173,7 +8278,7 @@ app16.post("/:slug/project", async (c) => {
|
|
|
8173
8278
|
return c.json({ error: `Projection failed: ${msg}` }, 500);
|
|
8174
8279
|
}
|
|
8175
8280
|
});
|
|
8176
|
-
var agents_default =
|
|
8281
|
+
var agents_default = app17;
|
|
8177
8282
|
|
|
8178
8283
|
// server/routes/admin/sessions.ts
|
|
8179
8284
|
import crypto2 from "crypto";
|
|
@@ -8441,19 +8546,19 @@ function formatAge(updatedAtStr) {
|
|
|
8441
8546
|
return "unknown";
|
|
8442
8547
|
}
|
|
8443
8548
|
}
|
|
8444
|
-
var
|
|
8445
|
-
|
|
8446
|
-
const
|
|
8447
|
-
const accountId = getAccountIdForSession(
|
|
8549
|
+
var app18 = new Hono();
|
|
8550
|
+
app18.get("/", requireAdminSession, async (c) => {
|
|
8551
|
+
const cacheKey = c.var.cacheKey;
|
|
8552
|
+
const accountId = getAccountIdForSession(cacheKey);
|
|
8448
8553
|
if (!accountId) return c.json({ error: "Account not found for session" }, 401);
|
|
8449
|
-
const userId = getUserIdForSession(
|
|
8554
|
+
const userId = getUserIdForSession(cacheKey);
|
|
8450
8555
|
if (!userId) return c.json({ error: "User identity required \u2014 authenticate with users.json PIN" }, 401);
|
|
8451
8556
|
try {
|
|
8452
8557
|
const flushed = await listAdminSessions(accountId, userId, 20);
|
|
8453
8558
|
const inProgressRaw = listAdminSessionsInProgress(accountId, userId);
|
|
8454
8559
|
const flushedRows = flushed.map((r) => ({
|
|
8455
8560
|
conversationId: r.conversationId,
|
|
8456
|
-
|
|
8561
|
+
cacheKey: null,
|
|
8457
8562
|
name: r.name,
|
|
8458
8563
|
updatedAt: r.updatedAt,
|
|
8459
8564
|
phase: "flushed",
|
|
@@ -8461,7 +8566,7 @@ app17.get("/", requireAdminSession, async (c) => {
|
|
|
8461
8566
|
}));
|
|
8462
8567
|
const inProgressRows = inProgressRaw.map((r) => ({
|
|
8463
8568
|
conversationId: null,
|
|
8464
|
-
|
|
8569
|
+
cacheKey: r.cacheKey,
|
|
8465
8570
|
name: null,
|
|
8466
8571
|
updatedAt: new Date(r.createdAt).toISOString(),
|
|
8467
8572
|
phase: "pre-flush",
|
|
@@ -8482,52 +8587,52 @@ app17.get("/", requireAdminSession, async (c) => {
|
|
|
8482
8587
|
return c.json({ error: "Failed to fetch sessions" }, 500);
|
|
8483
8588
|
}
|
|
8484
8589
|
});
|
|
8485
|
-
|
|
8486
|
-
const
|
|
8487
|
-
const accountId = getAccountIdForSession(
|
|
8488
|
-
const userId = getUserIdForSession(
|
|
8590
|
+
app18.post("/new", requireAdminSession, async (c) => {
|
|
8591
|
+
const oldCacheKey = c.var.cacheKey;
|
|
8592
|
+
const accountId = getAccountIdForSession(oldCacheKey);
|
|
8593
|
+
const userId = getUserIdForSession(oldCacheKey);
|
|
8489
8594
|
if (!accountId || !userId) {
|
|
8490
8595
|
return c.json({ error: "Session missing account or user context" }, 400);
|
|
8491
8596
|
}
|
|
8492
|
-
const
|
|
8493
|
-
const userName = getUserNameForSession(
|
|
8494
|
-
registerSession(
|
|
8495
|
-
const previousConversationId = clearSessionHistory(
|
|
8496
|
-
unregisterSession(
|
|
8497
|
-
console.log(`[session] ${(/* @__PURE__ */ new Date()).toISOString()} session reset for new conversation:
|
|
8498
|
-
return c.json({ session_key:
|
|
8597
|
+
const newCacheKey = crypto2.randomUUID();
|
|
8598
|
+
const userName = getUserNameForSession(oldCacheKey);
|
|
8599
|
+
registerSession(newCacheKey, "admin", accountId, void 0, userId, userName);
|
|
8600
|
+
const previousConversationId = clearSessionHistory(oldCacheKey);
|
|
8601
|
+
unregisterSession(oldCacheKey);
|
|
8602
|
+
console.log(`[session] ${(/* @__PURE__ */ new Date()).toISOString()} session reset for new conversation: oldCacheKey=${oldCacheKey.slice(0, 8)}\u2026 newCacheKey=${newCacheKey.slice(0, 8)}\u2026 previousConversationId=${previousConversationId?.slice(0, 8) ?? "none"}\u2026 newConversationId=deferred`);
|
|
8603
|
+
return c.json({ session_key: newCacheKey, conversationId: null });
|
|
8499
8604
|
});
|
|
8500
|
-
|
|
8501
|
-
const
|
|
8502
|
-
const accountId = getAccountIdForSession(
|
|
8503
|
-
const userId = getUserIdForSession(
|
|
8605
|
+
app18.post("/switch", requireAdminSession, async (c) => {
|
|
8606
|
+
const cacheKey = c.var.cacheKey;
|
|
8607
|
+
const accountId = getAccountIdForSession(cacheKey);
|
|
8608
|
+
const userId = getUserIdForSession(cacheKey);
|
|
8504
8609
|
if (!accountId || !userId) {
|
|
8505
8610
|
return c.json({ error: "Session missing account or user context" }, 400);
|
|
8506
8611
|
}
|
|
8507
8612
|
const body = await c.req.json().catch(() => ({}));
|
|
8508
|
-
const
|
|
8509
|
-
if (!
|
|
8613
|
+
const targetCacheKey = typeof body.target_session_key === "string" ? body.target_session_key : "";
|
|
8614
|
+
if (!targetCacheKey) {
|
|
8510
8615
|
return c.json({ error: "target_session_key required" }, 400);
|
|
8511
8616
|
}
|
|
8512
|
-
const targetCheck = validateSession(
|
|
8617
|
+
const targetCheck = validateSession(targetCacheKey, "admin");
|
|
8513
8618
|
if (!targetCheck.ok) {
|
|
8514
|
-
console.error(`[session-switch] reject reason=${targetCheck.reason} from=${
|
|
8619
|
+
console.error(`[session-switch] reject reason=${targetCheck.reason} from=${cacheKey.slice(0, 8)} target=${targetCacheKey.slice(0, 8)}`);
|
|
8515
8620
|
return c.json({ error: "Target session not registered or wrong agent type", code: targetCheck.reason }, 404);
|
|
8516
8621
|
}
|
|
8517
|
-
const targetAccountId = getAccountIdForSession(
|
|
8518
|
-
const targetUserId = getUserIdForSession(
|
|
8622
|
+
const targetAccountId = getAccountIdForSession(targetCacheKey);
|
|
8623
|
+
const targetUserId = getUserIdForSession(targetCacheKey);
|
|
8519
8624
|
if (targetAccountId !== accountId || targetUserId !== userId) {
|
|
8520
|
-
console.error(`[session-switch] reject reason=ownership-mismatch from=${
|
|
8625
|
+
console.error(`[session-switch] reject reason=ownership-mismatch from=${cacheKey.slice(0, 8)} target=${targetCacheKey.slice(0, 8)} accountMatch=${targetAccountId === accountId} userMatch=${targetUserId === userId}`);
|
|
8521
8626
|
return c.json({ error: "Target session not owned by current operator" }, 403);
|
|
8522
8627
|
}
|
|
8523
|
-
const targetConversationId = getConversationIdForSession(
|
|
8524
|
-
console.log(`[session-switch] from=${
|
|
8525
|
-
return c.json({ session_key:
|
|
8628
|
+
const targetConversationId = getConversationIdForSession(targetCacheKey) ?? null;
|
|
8629
|
+
console.log(`[session-switch] from=${cacheKey.slice(0, 8)} to=${targetCacheKey.slice(0, 8)} targetConvId=${targetConversationId?.slice(0, 8) ?? "none"} accountId=${accountId.slice(0, 8)}`);
|
|
8630
|
+
return c.json({ session_key: targetCacheKey, conversationId: targetConversationId });
|
|
8526
8631
|
});
|
|
8527
|
-
|
|
8632
|
+
app18.delete("/:id", requireAdminSession, async (c) => {
|
|
8528
8633
|
const conversationId = c.req.param("id");
|
|
8529
|
-
const
|
|
8530
|
-
const accountId = getAccountIdForSession(
|
|
8634
|
+
const cacheKey = c.var.cacheKey;
|
|
8635
|
+
const accountId = getAccountIdForSession(cacheKey);
|
|
8531
8636
|
if (!accountId) return c.json({ error: "Account not found for session" }, 401);
|
|
8532
8637
|
const owned = await verifyConversationOwnership(conversationId, accountId);
|
|
8533
8638
|
if (!owned) return c.json({ error: "Conversation not found" }, 404);
|
|
@@ -8539,42 +8644,42 @@ app17.delete("/:id", requireAdminSession, async (c) => {
|
|
|
8539
8644
|
return c.json({ error: "Failed to delete session" }, 500);
|
|
8540
8645
|
}
|
|
8541
8646
|
});
|
|
8542
|
-
|
|
8647
|
+
app18.post("/:id/resume", async (c) => {
|
|
8543
8648
|
const conversationId = c.req.param("id");
|
|
8544
|
-
const
|
|
8545
|
-
if (!
|
|
8649
|
+
const cacheKey = c.req.query("session_key") ?? "";
|
|
8650
|
+
if (!cacheKey) {
|
|
8546
8651
|
console.error(`[session] middleware-reject status=400 code=session-missing reason="session_key required" path=${c.req.path}`);
|
|
8547
8652
|
return c.json({ error: "session_key required", code: "session-missing" }, 400);
|
|
8548
8653
|
}
|
|
8549
8654
|
let bridged = false;
|
|
8550
|
-
let result = validateSession(
|
|
8655
|
+
let result = validateSession(cacheKey, "admin");
|
|
8551
8656
|
if (!result.ok) {
|
|
8552
8657
|
if (result.reason === "session-not-registered") {
|
|
8553
|
-
const bridge = await tryCookieBridgeForConversation(c,
|
|
8658
|
+
const bridge = await tryCookieBridgeForConversation(c, cacheKey, conversationId);
|
|
8554
8659
|
if (!bridge.ok) {
|
|
8555
8660
|
if (bridge.reason === "conversation-not-found") {
|
|
8556
8661
|
return c.json({ error: "Conversation not found" }, 404);
|
|
8557
8662
|
}
|
|
8558
|
-
const tail =
|
|
8559
|
-
console.error(`[session] middleware-reject status=401 code=session-not-registered reason="cookie-bridge-rejected:${bridge.reason}" path=${c.req.path}
|
|
8663
|
+
const tail = cacheKey.slice(0, 8);
|
|
8664
|
+
console.error(`[session] middleware-reject status=401 code=session-not-registered reason="cookie-bridge-rejected:${bridge.reason}" path=${c.req.path} cacheKey=${tail}\u2026`);
|
|
8560
8665
|
return c.json({ error: "Invalid or expired admin session", code: "session-not-registered" }, 401);
|
|
8561
8666
|
}
|
|
8562
8667
|
bridged = true;
|
|
8563
|
-
result = validateSession(
|
|
8668
|
+
result = validateSession(cacheKey, "admin");
|
|
8564
8669
|
if (!result.ok) {
|
|
8565
|
-
const tail =
|
|
8566
|
-
console.error(`[session] middleware-reject status=401 code=session-not-registered reason="post-bridge re-validate failed" path=${c.req.path}
|
|
8670
|
+
const tail = cacheKey.slice(0, 8);
|
|
8671
|
+
console.error(`[session] middleware-reject status=401 code=session-not-registered reason="post-bridge re-validate failed" path=${c.req.path} cacheKey=${tail}\u2026`);
|
|
8567
8672
|
return c.json({ error: "Invalid or expired admin session", code: "session-not-registered" }, 401);
|
|
8568
8673
|
}
|
|
8569
8674
|
} else {
|
|
8570
|
-
const tail =
|
|
8675
|
+
const tail = cacheKey.slice(0, 8);
|
|
8571
8676
|
const wireCode = result.reason === "agent-type-mismatch" ? "session-not-registered" : result.reason;
|
|
8572
|
-
console.error(`[session] middleware-reject status=401 code=${wireCode} reason="invalid or expired admin session" path=${c.req.path}
|
|
8677
|
+
console.error(`[session] middleware-reject status=401 code=${wireCode} reason="invalid or expired admin session" path=${c.req.path} cacheKey=${tail}\u2026`);
|
|
8573
8678
|
return c.json({ error: "Invalid or expired admin session", code: wireCode }, 401);
|
|
8574
8679
|
}
|
|
8575
8680
|
}
|
|
8576
|
-
const accountId = getAccountIdForSession(
|
|
8577
|
-
const userId = getUserIdForSession(
|
|
8681
|
+
const accountId = getAccountIdForSession(cacheKey);
|
|
8682
|
+
const userId = getUserIdForSession(cacheKey);
|
|
8578
8683
|
if (!accountId) {
|
|
8579
8684
|
return c.json({ error: "Session missing account context" }, 400);
|
|
8580
8685
|
}
|
|
@@ -8584,9 +8689,9 @@ app17.post("/:id/resume", async (c) => {
|
|
|
8584
8689
|
const updatedAt = await verifyAndGetConversationUpdatedAt(conversationId, accountId);
|
|
8585
8690
|
if (updatedAt === null) return c.json({ error: "Conversation not found" }, 404);
|
|
8586
8691
|
const persistedAgentSessionId = await getAgentSessionIdForConversation(conversationId);
|
|
8587
|
-
setConversationIdForSession(
|
|
8692
|
+
setConversationIdForSession(cacheKey, conversationId);
|
|
8588
8693
|
if (persistedAgentSessionId) {
|
|
8589
|
-
setAgentSessionId(
|
|
8694
|
+
setAgentSessionId(cacheKey, persistedAgentSessionId);
|
|
8590
8695
|
}
|
|
8591
8696
|
const streamLogPath = resolvePath(ACCOUNTS_DIR, accountId, "logs", `claude-agent-stream-${conversationId}.log`);
|
|
8592
8697
|
const tag = persistedAgentSessionId ? `agentSessionId=${persistedAgentSessionId.slice(0, 8)}\u2026` : "agentSessionId=missing";
|
|
@@ -8611,7 +8716,7 @@ app17.post("/:id/resume", async (c) => {
|
|
|
8611
8716
|
jsonlMalformedLines = replay.malformedLines;
|
|
8612
8717
|
jsonlReplayMessages = replay.messages;
|
|
8613
8718
|
if (replay.jsonlMissing) {
|
|
8614
|
-
console.error(`[jsonl-resume-miss]
|
|
8719
|
+
console.error(`[jsonl-resume-miss] cacheKey=${cacheKey.slice(0, 8)}\u2026 conversationId=${conversationId.slice(0, 8)}\u2026 agentSessionId=${persistedAgentSessionId.slice(0, 8)}\u2026 expectedPath=${jsonlPath} configDir=${process.env.CLAUDE_CONFIG_DIR ?? "<unset>"}`);
|
|
8615
8720
|
}
|
|
8616
8721
|
} else {
|
|
8617
8722
|
jsonlMissing = true;
|
|
@@ -8774,7 +8879,7 @@ app17.post("/:id/resume", async (c) => {
|
|
|
8774
8879
|
const reason = bridged ? "post-restart" : "page-refresh";
|
|
8775
8880
|
try {
|
|
8776
8881
|
const source = jsonlMissing ? persistedAgentSessionId ? "jsonl-missing" : "neo4j-only" : "jsonl";
|
|
8777
|
-
appendFileSync4(streamLogPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] [admin-resume] reason=${reason} source=${source}
|
|
8882
|
+
appendFileSync4(streamLogPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] [admin-resume] reason=${reason} source=${source} cacheKey=${cacheKey.slice(0, 8)} conversationId=${conversationId.slice(0, 8)} ${tag} loadedMessages=${messages.length} jsonlReplayMessages=${jsonlReplayMessages.length} neo4jMessages=${neo4jMessages.length} jsonlMalformed=${jsonlMalformedLines} componentCount=${totalComponents} userAttachmentCount=${totalAttachments} syntheticHidden=${syntheticHidden}
|
|
8778
8883
|
`);
|
|
8779
8884
|
if (totalComponents > 0) {
|
|
8780
8885
|
appendFileSync4(streamLogPath, `[${(/* @__PURE__ */ new Date()).toISOString()}] [component-rehydrate] conversationId=${conversationId.slice(0, 8)} count=${totalComponents} valid=${totalValid} invalid=${totalInvalid} textRuns=${textRuns}
|
|
@@ -8791,7 +8896,7 @@ app17.post("/:id/resume", async (c) => {
|
|
|
8791
8896
|
} catch {
|
|
8792
8897
|
}
|
|
8793
8898
|
const age = formatAge(updatedAt);
|
|
8794
|
-
console.log(`[admin-resume] ${(/* @__PURE__ */ new Date()).toISOString()} reason=${reason} conversationId=${conversationId.slice(0, 8)}\u2026 age=${age} loaded=${messages.length} messages ${tag} components=${totalComponents} attachments=${totalAttachments} syntheticHidden=${syntheticHidden} jsonlMissing=${jsonlMissing} healMissing=${jsonlHealMissing}
|
|
8899
|
+
console.log(`[admin-resume] ${(/* @__PURE__ */ new Date()).toISOString()} reason=${reason} conversationId=${conversationId.slice(0, 8)}\u2026 age=${age} loaded=${messages.length} messages ${tag} components=${totalComponents} attachments=${totalAttachments} syntheticHidden=${syntheticHidden} jsonlMissing=${jsonlMissing} healMissing=${jsonlHealMissing} cacheKey=${cacheKey.slice(0, 8)}\u2026`);
|
|
8795
8900
|
return c.json({
|
|
8796
8901
|
conversationId,
|
|
8797
8902
|
messages: rehydrated,
|
|
@@ -8804,10 +8909,10 @@ app17.post("/:id/resume", async (c) => {
|
|
|
8804
8909
|
}
|
|
8805
8910
|
});
|
|
8806
8911
|
});
|
|
8807
|
-
|
|
8912
|
+
app18.post("/:id/label", requireAdminSession, async (c) => {
|
|
8808
8913
|
const conversationId = c.req.param("id");
|
|
8809
|
-
const
|
|
8810
|
-
const accountId = getAccountIdForSession(
|
|
8914
|
+
const cacheKey = c.var.cacheKey;
|
|
8915
|
+
const accountId = getAccountIdForSession(cacheKey);
|
|
8811
8916
|
if (!accountId) return c.json({ error: "Account not found for session" }, 401);
|
|
8812
8917
|
const owned = await verifyConversationOwnership(conversationId, accountId);
|
|
8813
8918
|
if (!owned) return c.json({ error: "Conversation not found" }, 404);
|
|
@@ -8831,16 +8936,16 @@ app17.post("/:id/label", requireAdminSession, async (c) => {
|
|
|
8831
8936
|
return c.json({ label: null });
|
|
8832
8937
|
}
|
|
8833
8938
|
});
|
|
8834
|
-
|
|
8939
|
+
app18.put("/:id/label", requireAdminSession, async (c) => {
|
|
8835
8940
|
const conversationId = c.req.param("id");
|
|
8836
|
-
const
|
|
8941
|
+
const cacheKey = c.var.cacheKey;
|
|
8837
8942
|
let body;
|
|
8838
8943
|
try {
|
|
8839
8944
|
body = await c.req.json();
|
|
8840
8945
|
} catch {
|
|
8841
8946
|
return c.json({ error: "Invalid JSON body" }, 400);
|
|
8842
8947
|
}
|
|
8843
|
-
const accountId = getAccountIdForSession(
|
|
8948
|
+
const accountId = getAccountIdForSession(cacheKey);
|
|
8844
8949
|
if (!accountId) return c.json({ error: "Account not found for session" }, 401);
|
|
8845
8950
|
const owned = await verifyConversationOwnership(conversationId, accountId);
|
|
8846
8951
|
if (!owned) return c.json({ error: "Conversation not found" }, 404);
|
|
@@ -8857,11 +8962,11 @@ app17.put("/:id/label", requireAdminSession, async (c) => {
|
|
|
8857
8962
|
return c.json({ error: "Failed to rename session" }, 500);
|
|
8858
8963
|
}
|
|
8859
8964
|
});
|
|
8860
|
-
var sessions_default =
|
|
8965
|
+
var sessions_default = app18;
|
|
8861
8966
|
|
|
8862
8967
|
// server/routes/admin/browser.ts
|
|
8863
|
-
var
|
|
8864
|
-
|
|
8968
|
+
var app19 = new Hono();
|
|
8969
|
+
app19.post("/launch", async (c) => {
|
|
8865
8970
|
try {
|
|
8866
8971
|
const transport = resolveBrowserTransport(c.req.raw, c.env?.incoming?.socket?.remoteAddress);
|
|
8867
8972
|
if (transport === "vnc") {
|
|
@@ -8883,7 +8988,7 @@ app18.post("/launch", async (c) => {
|
|
|
8883
8988
|
);
|
|
8884
8989
|
}
|
|
8885
8990
|
});
|
|
8886
|
-
var browser_default =
|
|
8991
|
+
var browser_default = app19;
|
|
8887
8992
|
|
|
8888
8993
|
// server/routes/admin/browser-iframe.ts
|
|
8889
8994
|
var ALLOWED_EVENTS = /* @__PURE__ */ new Set([
|
|
@@ -8900,8 +9005,8 @@ function asString(v, max = 500) {
|
|
|
8900
9005
|
function asNumber(v) {
|
|
8901
9006
|
return typeof v === "number" && Number.isFinite(v) ? v : void 0;
|
|
8902
9007
|
}
|
|
8903
|
-
var
|
|
8904
|
-
|
|
9008
|
+
var app20 = new Hono();
|
|
9009
|
+
app20.post("/event", async (c) => {
|
|
8905
9010
|
let body = {};
|
|
8906
9011
|
try {
|
|
8907
9012
|
body = await c.req.json();
|
|
@@ -8922,7 +9027,7 @@ app19.post("/event", async (c) => {
|
|
|
8922
9027
|
});
|
|
8923
9028
|
return c.body(null, 204);
|
|
8924
9029
|
});
|
|
8925
|
-
var browser_iframe_default =
|
|
9030
|
+
var browser_iframe_default = app20;
|
|
8926
9031
|
|
|
8927
9032
|
// app/lib/cdp-client.ts
|
|
8928
9033
|
var CDP_HOST = "127.0.0.1";
|
|
@@ -8965,8 +9070,8 @@ async function cdpNavigateNewTab(url, opts = {}) {
|
|
|
8965
9070
|
}
|
|
8966
9071
|
|
|
8967
9072
|
// server/routes/admin/device-browser.ts
|
|
8968
|
-
var
|
|
8969
|
-
|
|
9073
|
+
var app21 = new Hono();
|
|
9074
|
+
app21.post("/navigate", async (c) => {
|
|
8970
9075
|
const TAG19 = "[device-url:click]";
|
|
8971
9076
|
let body;
|
|
8972
9077
|
try {
|
|
@@ -9053,7 +9158,7 @@ app20.post("/navigate", async (c) => {
|
|
|
9053
9158
|
targetId: outcome.targetId
|
|
9054
9159
|
});
|
|
9055
9160
|
});
|
|
9056
|
-
var device_browser_default =
|
|
9161
|
+
var device_browser_default = app21;
|
|
9057
9162
|
|
|
9058
9163
|
// server/routes/admin/events.ts
|
|
9059
9164
|
var ALLOWED_EVENTS2 = /* @__PURE__ */ new Set([
|
|
@@ -9062,8 +9167,8 @@ var ALLOWED_EVENTS2 = /* @__PURE__ */ new Set([
|
|
|
9062
9167
|
"device-url:vnc-surface-shown",
|
|
9063
9168
|
"device-url:malformed"
|
|
9064
9169
|
]);
|
|
9065
|
-
var
|
|
9066
|
-
|
|
9170
|
+
var app22 = new Hono();
|
|
9171
|
+
app22.post("/", async (c) => {
|
|
9067
9172
|
const TAG19 = "[admin:events]";
|
|
9068
9173
|
let body;
|
|
9069
9174
|
try {
|
|
@@ -9094,7 +9199,7 @@ app21.post("/", async (c) => {
|
|
|
9094
9199
|
console.error(`[${event}] ${formatted}`);
|
|
9095
9200
|
return c.json({ ok: true });
|
|
9096
9201
|
});
|
|
9097
|
-
var events_default =
|
|
9202
|
+
var events_default = app22;
|
|
9098
9203
|
|
|
9099
9204
|
// server/routes/admin/cloudflare.ts
|
|
9100
9205
|
import { homedir as homedir2 } from "os";
|
|
@@ -9212,7 +9317,7 @@ function validateBody(body) {
|
|
|
9212
9317
|
}
|
|
9213
9318
|
return null;
|
|
9214
9319
|
}
|
|
9215
|
-
var
|
|
9320
|
+
var app23 = new Hono();
|
|
9216
9321
|
function fieldFromReason(reason) {
|
|
9217
9322
|
switch (reason) {
|
|
9218
9323
|
case "not-signed-in":
|
|
@@ -9233,15 +9338,15 @@ function fieldFromReason(reason) {
|
|
|
9233
9338
|
return "script";
|
|
9234
9339
|
}
|
|
9235
9340
|
}
|
|
9236
|
-
|
|
9341
|
+
app23.get("/domains", requireAdminSession, async (c) => {
|
|
9237
9342
|
const started = Date.now();
|
|
9238
|
-
const
|
|
9343
|
+
const cacheKey = c.var.cacheKey;
|
|
9239
9344
|
let correlationId;
|
|
9240
|
-
let
|
|
9345
|
+
let cacheKeyTail;
|
|
9241
9346
|
let streamLogPath;
|
|
9242
9347
|
function tag() {
|
|
9243
9348
|
if (!correlationId) return "";
|
|
9244
|
-
return ` conversationId=${correlationId} session_key=${
|
|
9349
|
+
return ` conversationId=${correlationId} session_key=${cacheKeyTail ?? "unknown"}`;
|
|
9245
9350
|
}
|
|
9246
9351
|
function log(line) {
|
|
9247
9352
|
console.log(`[cloudflare-domains] ${line}${tag()}`);
|
|
@@ -9269,9 +9374,9 @@ app22.get("/domains", requireAdminSession, async (c) => {
|
|
|
9269
9374
|
};
|
|
9270
9375
|
return c.json(body, 200);
|
|
9271
9376
|
}
|
|
9272
|
-
const accountId = getAccountIdForSession(
|
|
9273
|
-
correlationId = getConversationIdForSession(
|
|
9274
|
-
|
|
9377
|
+
const accountId = getAccountIdForSession(cacheKey);
|
|
9378
|
+
correlationId = getConversationIdForSession(cacheKey);
|
|
9379
|
+
cacheKeyTail = cacheKey.slice(-8);
|
|
9275
9380
|
if (!accountId) return err("session", "No account bound to session \u2014 refresh chat.");
|
|
9276
9381
|
if (!correlationId) return err("session", "No active conversation for session \u2014 refresh chat.");
|
|
9277
9382
|
streamLogPath = streamLogPathFor(accountId, correlationId).streamLogPath;
|
|
@@ -9328,15 +9433,15 @@ ${result.stderr}` : ""}`;
|
|
|
9328
9433
|
return c.json(success, 200);
|
|
9329
9434
|
});
|
|
9330
9435
|
var TUNNELS_TIMEOUT_MS = 30 * 1e3;
|
|
9331
|
-
|
|
9436
|
+
app23.get("/tunnels", requireAdminSession, async (c) => {
|
|
9332
9437
|
const started = Date.now();
|
|
9333
|
-
const
|
|
9438
|
+
const cacheKey = c.var.cacheKey;
|
|
9334
9439
|
let correlationId;
|
|
9335
|
-
let
|
|
9440
|
+
let cacheKeyTail;
|
|
9336
9441
|
let streamLogPath;
|
|
9337
9442
|
function tag() {
|
|
9338
9443
|
if (!correlationId) return "";
|
|
9339
|
-
return ` conversationId=${correlationId} session_key=${
|
|
9444
|
+
return ` conversationId=${correlationId} session_key=${cacheKeyTail ?? "unknown"}`;
|
|
9340
9445
|
}
|
|
9341
9446
|
function log(line) {
|
|
9342
9447
|
console.log(`[cloudflare-tunnels] ${line}${tag()}`);
|
|
@@ -9361,9 +9466,9 @@ app22.get("/tunnels", requireAdminSession, async (c) => {
|
|
|
9361
9466
|
const body = { ok: false, field, message, output, defaultName, correlationId, streamLogPath };
|
|
9362
9467
|
return c.json(body, 200);
|
|
9363
9468
|
}
|
|
9364
|
-
const accountId = getAccountIdForSession(
|
|
9365
|
-
correlationId = getConversationIdForSession(
|
|
9366
|
-
|
|
9469
|
+
const accountId = getAccountIdForSession(cacheKey);
|
|
9470
|
+
correlationId = getConversationIdForSession(cacheKey);
|
|
9471
|
+
cacheKeyTail = cacheKey.slice(-8);
|
|
9367
9472
|
if (!accountId) return err("session", "No account bound to session \u2014 refresh chat.");
|
|
9368
9473
|
if (!correlationId) return err("session", "No active conversation for session \u2014 refresh chat.");
|
|
9369
9474
|
streamLogPath = streamLogPathFor(accountId, correlationId).streamLogPath;
|
|
@@ -9424,15 +9529,15 @@ ${result.stderr}` : ""}`;
|
|
|
9424
9529
|
const success = { ok: true, tunnels, defaultName, correlationId, streamLogPath };
|
|
9425
9530
|
return c.json(success, 200);
|
|
9426
9531
|
});
|
|
9427
|
-
|
|
9532
|
+
app23.post("/setup", requireAdminSession, async (c) => {
|
|
9428
9533
|
const started = Date.now();
|
|
9429
|
-
const
|
|
9534
|
+
const cacheKey = c.var.cacheKey;
|
|
9430
9535
|
let correlationId;
|
|
9431
|
-
let
|
|
9536
|
+
let cacheKeyTail;
|
|
9432
9537
|
let streamLogPath;
|
|
9433
9538
|
function tag() {
|
|
9434
9539
|
if (!correlationId) return "";
|
|
9435
|
-
return ` conversationId=${correlationId} session_key=${
|
|
9540
|
+
return ` conversationId=${correlationId} session_key=${cacheKeyTail ?? "unknown"}`;
|
|
9436
9541
|
}
|
|
9437
9542
|
function log(line) {
|
|
9438
9543
|
console.log(`[cloudflare-setup] ${line}${tag()}`);
|
|
@@ -9468,9 +9573,9 @@ app22.post("/setup", requireAdminSession, async (c) => {
|
|
|
9468
9573
|
} catch {
|
|
9469
9574
|
return err("request", "Invalid JSON body");
|
|
9470
9575
|
}
|
|
9471
|
-
const accountId = getAccountIdForSession(
|
|
9472
|
-
correlationId = getConversationIdForSession(
|
|
9473
|
-
|
|
9576
|
+
const accountId = getAccountIdForSession(cacheKey);
|
|
9577
|
+
correlationId = getConversationIdForSession(cacheKey);
|
|
9578
|
+
cacheKeyTail = cacheKey.slice(-8);
|
|
9474
9579
|
if (!accountId) {
|
|
9475
9580
|
return err("request", "No account bound to session \u2014 refresh chat.");
|
|
9476
9581
|
}
|
|
@@ -9523,7 +9628,7 @@ app22.post("/setup", requireAdminSession, async (c) => {
|
|
|
9523
9628
|
try {
|
|
9524
9629
|
cloudflareTask = await openCloudflareTask({
|
|
9525
9630
|
accountId,
|
|
9526
|
-
|
|
9631
|
+
conversationId: correlationId,
|
|
9527
9632
|
inputsProvided: Object.keys(taskInputs),
|
|
9528
9633
|
inputs: taskInputs,
|
|
9529
9634
|
inputSchema: CLOUDFLARE_SETUP_FORM_SCHEMA,
|
|
@@ -9571,7 +9676,7 @@ app22.post("/setup", requireAdminSession, async (c) => {
|
|
|
9571
9676
|
taskId: cloudflareTask.taskId,
|
|
9572
9677
|
taskElementId: cloudflareTask.taskElementId,
|
|
9573
9678
|
accountId,
|
|
9574
|
-
|
|
9679
|
+
conversationId: correlationId,
|
|
9575
9680
|
status: "failed",
|
|
9576
9681
|
errorMessage: CLOUDFLARE_TASK_DIAGNOSTICS.endpointDiedPreReconcile
|
|
9577
9682
|
});
|
|
@@ -9588,7 +9693,7 @@ app22.post("/setup", requireAdminSession, async (c) => {
|
|
|
9588
9693
|
taskId: cloudflareTask.taskId,
|
|
9589
9694
|
taskElementId: cloudflareTask.taskElementId,
|
|
9590
9695
|
accountId,
|
|
9591
|
-
|
|
9696
|
+
conversationId: correlationId,
|
|
9592
9697
|
status: "failed",
|
|
9593
9698
|
errorMessage: `${CLOUDFLARE_TASK_DIAGNOSTICS.scriptExitedNonzero} exit=${status.execMainStatus}`
|
|
9594
9699
|
});
|
|
@@ -9630,7 +9735,7 @@ app22.post("/setup", requireAdminSession, async (c) => {
|
|
|
9630
9735
|
taskId: cloudflareTask.taskId,
|
|
9631
9736
|
taskElementId: cloudflareTask.taskElementId,
|
|
9632
9737
|
accountId,
|
|
9633
|
-
|
|
9738
|
+
conversationId: correlationId,
|
|
9634
9739
|
tunnelId: tunnelState?.tunnelId,
|
|
9635
9740
|
tunnelName: tunnelState?.tunnelName,
|
|
9636
9741
|
hostnames: tunnelState ? hostnameRecords : void 0,
|
|
@@ -9661,7 +9766,7 @@ actionId: ${actionId}`,
|
|
|
9661
9766
|
};
|
|
9662
9767
|
return ok(success);
|
|
9663
9768
|
});
|
|
9664
|
-
var cloudflare_default =
|
|
9769
|
+
var cloudflare_default = app23;
|
|
9665
9770
|
|
|
9666
9771
|
// server/routes/admin/files.ts
|
|
9667
9772
|
import { createReadStream as createReadStream3 } from "fs";
|
|
@@ -9721,7 +9826,7 @@ var UNIQUE_KEYS_BY_LABEL = {
|
|
|
9721
9826
|
Event: ["eventId"],
|
|
9722
9827
|
KnowledgeDocument: ["attachmentId"],
|
|
9723
9828
|
DigitalDocument: ["attachmentId"],
|
|
9724
|
-
Conversation: ["conversationId"
|
|
9829
|
+
Conversation: ["conversationId"],
|
|
9725
9830
|
Message: ["messageId"],
|
|
9726
9831
|
OnboardingState: ["accountId"],
|
|
9727
9832
|
Workflow: ["workflowId"],
|
|
@@ -9942,7 +10047,7 @@ async function restoreNode(params) {
|
|
|
9942
10047
|
}
|
|
9943
10048
|
|
|
9944
10049
|
// app/lib/file-delete-cascade.ts
|
|
9945
|
-
var
|
|
10050
|
+
var UUID_RE4 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
9946
10051
|
function parseAttachmentPath(relPath2) {
|
|
9947
10052
|
const segments = relPath2.split("/").filter(Boolean);
|
|
9948
10053
|
if (segments.length !== 4) return null;
|
|
@@ -9950,7 +10055,7 @@ function parseAttachmentPath(relPath2) {
|
|
|
9950
10055
|
const accountId = segments[1];
|
|
9951
10056
|
const attachmentId = segments[2];
|
|
9952
10057
|
const filename = segments[3];
|
|
9953
|
-
if (!
|
|
10058
|
+
if (!UUID_RE4.test(accountId) || !UUID_RE4.test(attachmentId)) return null;
|
|
9954
10059
|
const dot = filename.lastIndexOf(".");
|
|
9955
10060
|
if (dot === -1) return null;
|
|
9956
10061
|
const stem = filename.slice(0, dot);
|
|
@@ -10022,7 +10127,7 @@ async function cascadeDeleteDocument(params) {
|
|
|
10022
10127
|
}
|
|
10023
10128
|
|
|
10024
10129
|
// server/routes/admin/files.ts
|
|
10025
|
-
var
|
|
10130
|
+
var UUID_RE5 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
10026
10131
|
async function readMeta(absDir, baseName) {
|
|
10027
10132
|
try {
|
|
10028
10133
|
const raw = await readFile3(join9(absDir, `${baseName}.meta.json`), "utf8");
|
|
@@ -10044,7 +10149,7 @@ async function readAccountNames() {
|
|
|
10044
10149
|
return map;
|
|
10045
10150
|
}
|
|
10046
10151
|
for (const name of names) {
|
|
10047
|
-
if (!
|
|
10152
|
+
if (!UUID_RE5.test(name)) continue;
|
|
10048
10153
|
const configPath2 = resolve15(accountsDir, name, "account.json");
|
|
10049
10154
|
try {
|
|
10050
10155
|
const raw = await readFile3(configPath2, "utf8");
|
|
@@ -10062,7 +10167,7 @@ async function readAccountNames() {
|
|
|
10062
10167
|
return map;
|
|
10063
10168
|
}
|
|
10064
10169
|
async function enrich(absolute, entry, accountNames) {
|
|
10065
|
-
if (entry.kind === "directory" &&
|
|
10170
|
+
if (entry.kind === "directory" && UUID_RE5.test(entry.name)) {
|
|
10066
10171
|
const meta = await readMeta(join9(absolute, entry.name), entry.name);
|
|
10067
10172
|
if (meta?.filename) {
|
|
10068
10173
|
entry.displayName = meta.filename;
|
|
@@ -10078,7 +10183,7 @@ async function enrich(absolute, entry, accountNames) {
|
|
|
10078
10183
|
if (entry.kind === "file") {
|
|
10079
10184
|
const dot = entry.name.lastIndexOf(".");
|
|
10080
10185
|
const base = dot === -1 ? entry.name : entry.name.slice(0, dot);
|
|
10081
|
-
if (
|
|
10186
|
+
if (UUID_RE5.test(base)) {
|
|
10082
10187
|
const meta = await readMeta(absolute, base);
|
|
10083
10188
|
if (meta?.filename) {
|
|
10084
10189
|
entry.displayName = meta.filename;
|
|
@@ -10090,14 +10195,14 @@ async function enrich(absolute, entry, accountNames) {
|
|
|
10090
10195
|
function buildDisplayPath(relPath2, accountNames) {
|
|
10091
10196
|
if (relPath2 === "." || relPath2 === "") return [];
|
|
10092
10197
|
return relPath2.split("/").filter(Boolean).map((seg) => {
|
|
10093
|
-
const dn =
|
|
10198
|
+
const dn = UUID_RE5.test(seg) ? accountNames.get(seg) : void 0;
|
|
10094
10199
|
return dn ? { name: seg, displayName: dn } : { name: seg };
|
|
10095
10200
|
});
|
|
10096
10201
|
}
|
|
10097
|
-
var
|
|
10098
|
-
|
|
10099
|
-
const
|
|
10100
|
-
if (!getAccountIdForSession(
|
|
10202
|
+
var app24 = new Hono();
|
|
10203
|
+
app24.get("/", requireAdminSession, async (c) => {
|
|
10204
|
+
const cacheKey = c.var.cacheKey;
|
|
10205
|
+
if (!getAccountIdForSession(cacheKey)) {
|
|
10101
10206
|
console.error(`[data] auth-rejected endpoint="/api/admin/files" reason="no account for session"`);
|
|
10102
10207
|
return c.json({ error: "Account not found for session" }, 401);
|
|
10103
10208
|
}
|
|
@@ -10118,7 +10223,7 @@ app23.get("/", requireAdminSession, async (c) => {
|
|
|
10118
10223
|
const names = await readdir2(absolute);
|
|
10119
10224
|
const entries = [];
|
|
10120
10225
|
for (const name of names) {
|
|
10121
|
-
if (
|
|
10226
|
+
if (UUID_RE5.test(name.replace(/\.meta\.json$/, "")) && name.endsWith(".meta.json")) {
|
|
10122
10227
|
continue;
|
|
10123
10228
|
}
|
|
10124
10229
|
try {
|
|
@@ -10156,9 +10261,9 @@ app23.get("/", requireAdminSession, async (c) => {
|
|
|
10156
10261
|
return c.json({ error: message }, 500);
|
|
10157
10262
|
}
|
|
10158
10263
|
});
|
|
10159
|
-
|
|
10160
|
-
const
|
|
10161
|
-
if (!getAccountIdForSession(
|
|
10264
|
+
app24.get("/download", requireAdminSession, async (c) => {
|
|
10265
|
+
const cacheKey = c.var.cacheKey;
|
|
10266
|
+
if (!getAccountIdForSession(cacheKey)) {
|
|
10162
10267
|
console.error(`[data] auth-rejected endpoint="/api/admin/files/download" reason="no account for session"`);
|
|
10163
10268
|
return c.json({ error: "Account not found for session" }, 401);
|
|
10164
10269
|
}
|
|
@@ -10204,9 +10309,9 @@ app23.get("/download", requireAdminSession, async (c) => {
|
|
|
10204
10309
|
return c.json({ error: message }, 500);
|
|
10205
10310
|
}
|
|
10206
10311
|
});
|
|
10207
|
-
|
|
10208
|
-
const
|
|
10209
|
-
const accountId = getAccountIdForSession(
|
|
10312
|
+
app24.post("/upload", requireAdminSession, async (c) => {
|
|
10313
|
+
const cacheKey = c.var.cacheKey;
|
|
10314
|
+
const accountId = getAccountIdForSession(cacheKey);
|
|
10210
10315
|
if (!accountId) {
|
|
10211
10316
|
console.error(`[data] auth-rejected endpoint="/api/admin/files/upload" reason="no account for session"`);
|
|
10212
10317
|
return c.json({ error: "Account not found for session" }, 401);
|
|
@@ -10262,9 +10367,9 @@ app23.post("/upload", requireAdminSession, async (c) => {
|
|
|
10262
10367
|
mimeType: file.type
|
|
10263
10368
|
});
|
|
10264
10369
|
});
|
|
10265
|
-
|
|
10266
|
-
const
|
|
10267
|
-
const accountId = getAccountIdForSession(
|
|
10370
|
+
app24.delete("/", requireAdminSession, async (c) => {
|
|
10371
|
+
const cacheKey = c.var.cacheKey;
|
|
10372
|
+
const accountId = getAccountIdForSession(cacheKey);
|
|
10268
10373
|
if (!accountId) {
|
|
10269
10374
|
console.error(`[data] auth-rejected endpoint="DELETE /api/admin/files" reason="no account for session"`);
|
|
10270
10375
|
return c.json({ error: "Account not found for session" }, 401);
|
|
@@ -10295,7 +10400,7 @@ app23.delete("/", requireAdminSession, async (c) => {
|
|
|
10295
10400
|
}
|
|
10296
10401
|
const dot = base.lastIndexOf(".");
|
|
10297
10402
|
const stem = dot === -1 ? base : base.slice(0, dot);
|
|
10298
|
-
const sidecarPath =
|
|
10403
|
+
const sidecarPath = UUID_RE5.test(stem) && base !== `${stem}.meta.json` ? join9(dirname6(absolute), `${stem}.meta.json`) : null;
|
|
10299
10404
|
await unlink2(absolute);
|
|
10300
10405
|
if (sidecarPath) {
|
|
10301
10406
|
try {
|
|
@@ -10329,7 +10434,7 @@ app23.delete("/", requireAdminSession, async (c) => {
|
|
|
10329
10434
|
return c.json({ error: message }, 500);
|
|
10330
10435
|
}
|
|
10331
10436
|
});
|
|
10332
|
-
var files_default =
|
|
10437
|
+
var files_default = app24;
|
|
10333
10438
|
|
|
10334
10439
|
// ../lib/graph-search/src/index.ts
|
|
10335
10440
|
var import_dist = __toESM(require_dist());
|
|
@@ -10709,14 +10814,14 @@ var MAX_LIMIT = 2e3;
|
|
|
10709
10814
|
var DEFAULT_VECTOR_THRESHOLD = 0.82;
|
|
10710
10815
|
var MESSAGE_FAMILY_LABELS = ["Message", "UserMessage", "AssistantMessage", "WhatsAppMessage"];
|
|
10711
10816
|
var CONVERSATION_PARENT_LABELS = /* @__PURE__ */ new Set(["AdminConversation", "PublicConversation"]);
|
|
10712
|
-
var
|
|
10713
|
-
|
|
10714
|
-
const
|
|
10817
|
+
var app25 = new Hono();
|
|
10818
|
+
app25.get("/", requireAdminSession, async (c) => {
|
|
10819
|
+
const cacheKey = c.var.cacheKey;
|
|
10715
10820
|
const q = (c.req.query("q") ?? "").trim();
|
|
10716
10821
|
const rawLimit = c.req.query("limit");
|
|
10717
10822
|
const rawLabels = c.req.query("labels");
|
|
10718
10823
|
const rawThreshold = c.req.query("threshold");
|
|
10719
|
-
const accountId = getAccountIdForSession(
|
|
10824
|
+
const accountId = getAccountIdForSession(cacheKey);
|
|
10720
10825
|
if (!accountId) {
|
|
10721
10826
|
console.error(`[graph-search] auth-rejected endpoint="/api/admin/graph-search" reason="no account for session"`);
|
|
10722
10827
|
return c.json({ error: "Account not found for session" }, 401);
|
|
@@ -10841,7 +10946,7 @@ app24.get("/", requireAdminSession, async (c) => {
|
|
|
10841
10946
|
await session.close();
|
|
10842
10947
|
}
|
|
10843
10948
|
});
|
|
10844
|
-
var graph_search_default =
|
|
10949
|
+
var graph_search_default = app25;
|
|
10845
10950
|
|
|
10846
10951
|
// server/routes/admin/graph-subgraph.ts
|
|
10847
10952
|
import neo4j2 from "neo4j-driver";
|
|
@@ -10997,12 +11102,12 @@ var STRIPPED_PROPERTIES = /* @__PURE__ */ new Set([
|
|
|
10997
11102
|
"passwordHash",
|
|
10998
11103
|
"magicToken",
|
|
10999
11104
|
"otpCode",
|
|
11000
|
-
"
|
|
11105
|
+
"cacheKey"
|
|
11001
11106
|
]);
|
|
11002
|
-
var
|
|
11003
|
-
|
|
11004
|
-
const
|
|
11005
|
-
const accountId = getAccountIdForSession(
|
|
11107
|
+
var app26 = new Hono();
|
|
11108
|
+
app26.get("/", requireAdminSession, async (c) => {
|
|
11109
|
+
const cacheKey = c.var.cacheKey;
|
|
11110
|
+
const accountId = getAccountIdForSession(cacheKey);
|
|
11006
11111
|
if (!accountId) {
|
|
11007
11112
|
console.error('[graph-page] auth-rejected reason="no account for session"');
|
|
11008
11113
|
return c.json({ error: "Account not found for session" }, 401);
|
|
@@ -11583,14 +11688,14 @@ function pruneNode(node, warnedClasses, conversationWarnings) {
|
|
|
11583
11688
|
}
|
|
11584
11689
|
return trashed ? { id: node.id, labels, properties, trashed: true } : { id: node.id, labels, properties };
|
|
11585
11690
|
}
|
|
11586
|
-
var graph_subgraph_default =
|
|
11691
|
+
var graph_subgraph_default = app26;
|
|
11587
11692
|
|
|
11588
11693
|
// server/routes/admin/graph-delete.ts
|
|
11589
11694
|
var ALLOWED_BY = ["graph-page", "graph-drag-trash"];
|
|
11590
|
-
var
|
|
11591
|
-
|
|
11592
|
-
const
|
|
11593
|
-
const accountId = getAccountIdForSession(
|
|
11695
|
+
var app27 = new Hono();
|
|
11696
|
+
app27.post("/", requireAdminSession, async (c) => {
|
|
11697
|
+
const cacheKey = c.var.cacheKey;
|
|
11698
|
+
const accountId = getAccountIdForSession(cacheKey);
|
|
11594
11699
|
if (!accountId) {
|
|
11595
11700
|
console.error('[graph-page] delete auth-rejected reason="no account for session"');
|
|
11596
11701
|
return c.json({ error: "Account not found for session" }, 401);
|
|
@@ -11659,13 +11764,13 @@ app26.post("/", requireAdminSession, async (c) => {
|
|
|
11659
11764
|
}
|
|
11660
11765
|
}
|
|
11661
11766
|
});
|
|
11662
|
-
var graph_delete_default =
|
|
11767
|
+
var graph_delete_default = app27;
|
|
11663
11768
|
|
|
11664
11769
|
// server/routes/admin/graph-restore.ts
|
|
11665
|
-
var
|
|
11666
|
-
|
|
11667
|
-
const
|
|
11668
|
-
const accountId = getAccountIdForSession(
|
|
11770
|
+
var app28 = new Hono();
|
|
11771
|
+
app28.post("/", requireAdminSession, async (c) => {
|
|
11772
|
+
const cacheKey = c.var.cacheKey;
|
|
11773
|
+
const accountId = getAccountIdForSession(cacheKey);
|
|
11669
11774
|
if (!accountId) {
|
|
11670
11775
|
console.error('[graph-page] restore auth-rejected reason="no account for session"');
|
|
11671
11776
|
return c.json({ error: "Account not found for session" }, 401);
|
|
@@ -11727,13 +11832,13 @@ app27.post("/", requireAdminSession, async (c) => {
|
|
|
11727
11832
|
}
|
|
11728
11833
|
}
|
|
11729
11834
|
});
|
|
11730
|
-
var graph_restore_default =
|
|
11835
|
+
var graph_restore_default = app28;
|
|
11731
11836
|
|
|
11732
11837
|
// server/routes/admin/graph-labels-in-graph.ts
|
|
11733
|
-
var
|
|
11734
|
-
|
|
11735
|
-
const
|
|
11736
|
-
const accountId = getAccountIdForSession(
|
|
11838
|
+
var app29 = new Hono();
|
|
11839
|
+
app29.get("/", requireAdminSession, async (c) => {
|
|
11840
|
+
const cacheKey = c.var.cacheKey;
|
|
11841
|
+
const accountId = getAccountIdForSession(cacheKey);
|
|
11737
11842
|
if (!accountId) {
|
|
11738
11843
|
console.error('[graph-page] labels-in-graph-rejected reason="no account for session"');
|
|
11739
11844
|
return c.json({ error: "Account not found for session" }, 401);
|
|
@@ -11797,14 +11902,14 @@ var LABELS_IN_GRAPH_CYPHER = `
|
|
|
11797
11902
|
sum(halfEdges) AS relDegree
|
|
11798
11903
|
RETURN label, nodeCount, relDegree
|
|
11799
11904
|
`;
|
|
11800
|
-
var graph_labels_in_graph_default =
|
|
11905
|
+
var graph_labels_in_graph_default = app29;
|
|
11801
11906
|
|
|
11802
11907
|
// server/routes/admin/graph-default-view.ts
|
|
11803
|
-
var
|
|
11804
|
-
|
|
11805
|
-
const
|
|
11806
|
-
const accountId = getAccountIdForSession(
|
|
11807
|
-
const userId = getUserIdForSession(
|
|
11908
|
+
var app30 = new Hono();
|
|
11909
|
+
app30.get("/", requireAdminSession, async (c) => {
|
|
11910
|
+
const cacheKey = c.var.cacheKey;
|
|
11911
|
+
const accountId = getAccountIdForSession(cacheKey);
|
|
11912
|
+
const userId = getUserIdForSession(cacheKey);
|
|
11808
11913
|
if (!accountId || !userId) {
|
|
11809
11914
|
console.error('[graph-page] default-view-rejected reason="missing account or user context"');
|
|
11810
11915
|
return c.json({ error: "Account and user context required for default view" }, 401);
|
|
@@ -11839,10 +11944,10 @@ app29.get("/", requireAdminSession, async (c) => {
|
|
|
11839
11944
|
}
|
|
11840
11945
|
}
|
|
11841
11946
|
});
|
|
11842
|
-
|
|
11843
|
-
const
|
|
11844
|
-
const accountId = getAccountIdForSession(
|
|
11845
|
-
const userId = getUserIdForSession(
|
|
11947
|
+
app30.put("/", requireAdminSession, async (c) => {
|
|
11948
|
+
const cacheKey = c.var.cacheKey;
|
|
11949
|
+
const accountId = getAccountIdForSession(cacheKey);
|
|
11950
|
+
const userId = getUserIdForSession(cacheKey);
|
|
11846
11951
|
if (!accountId || !userId) {
|
|
11847
11952
|
console.error('[graph-page] default-view-rejected reason="missing account or user context"');
|
|
11848
11953
|
return c.json({ error: "Account and user context required for default view" }, 401);
|
|
@@ -11928,11 +12033,11 @@ var WRITE_CYPHER = `
|
|
|
11928
12033
|
p.updatedAt = $updatedAt
|
|
11929
12034
|
RETURN p.labels AS labels
|
|
11930
12035
|
`;
|
|
11931
|
-
var graph_default_view_default =
|
|
12036
|
+
var graph_default_view_default = app30;
|
|
11932
12037
|
|
|
11933
12038
|
// server/routes/admin/file-attach.ts
|
|
11934
|
-
var
|
|
11935
|
-
|
|
12039
|
+
var app31 = new Hono();
|
|
12040
|
+
app31.post("/", async (c) => {
|
|
11936
12041
|
try {
|
|
11937
12042
|
const body = await c.req.json();
|
|
11938
12043
|
const { filePath, accountId } = body;
|
|
@@ -11955,11 +12060,11 @@ app30.post("/", async (c) => {
|
|
|
11955
12060
|
return c.json({ error: message }, 500);
|
|
11956
12061
|
}
|
|
11957
12062
|
});
|
|
11958
|
-
var file_attach_default =
|
|
12063
|
+
var file_attach_default = app31;
|
|
11959
12064
|
|
|
11960
12065
|
// server/routes/admin/adherence.ts
|
|
11961
|
-
var
|
|
11962
|
-
|
|
12066
|
+
var app32 = new Hono();
|
|
12067
|
+
app32.get("/", requireAdminSession, async (c) => {
|
|
11963
12068
|
const agent = c.req.query("agent") ?? "admin";
|
|
11964
12069
|
const includeBlock = c.req.query("block") === "1";
|
|
11965
12070
|
const account = resolveAccount();
|
|
@@ -11980,7 +12085,7 @@ app31.get("/", requireAdminSession, async (c) => {
|
|
|
11980
12085
|
return c.json({ error: "Failed to read adherence ledger", agent }, 500);
|
|
11981
12086
|
}
|
|
11982
12087
|
});
|
|
11983
|
-
var adherence_default =
|
|
12088
|
+
var adherence_default = app32;
|
|
11984
12089
|
|
|
11985
12090
|
// server/routes/admin/sidebar-artefacts.ts
|
|
11986
12091
|
import neo4j3 from "neo4j-driver";
|
|
@@ -11990,10 +12095,10 @@ import { existsSync as existsSync18 } from "fs";
|
|
|
11990
12095
|
var LIMIT = 50;
|
|
11991
12096
|
var TEXT_MIME_PREFIXES = ["text/", "application/json", "application/markdown"];
|
|
11992
12097
|
var ADMIN_AGENT_FILES = ["IDENTITY.md", "SOUL.md", "KNOWLEDGE.md"];
|
|
11993
|
-
var
|
|
11994
|
-
|
|
11995
|
-
const
|
|
11996
|
-
const accountId = getAccountIdForSession(
|
|
12098
|
+
var app33 = new Hono();
|
|
12099
|
+
app33.get("/", requireAdminSession, async (c) => {
|
|
12100
|
+
const cacheKey = c.var.cacheKey;
|
|
12101
|
+
const accountId = getAccountIdForSession(cacheKey);
|
|
11997
12102
|
if (!accountId) {
|
|
11998
12103
|
return c.json({ error: "Account not found for session" }, 401);
|
|
11999
12104
|
}
|
|
@@ -12197,18 +12302,18 @@ function isWithin(target, root) {
|
|
|
12197
12302
|
const rel = relative2(root, target);
|
|
12198
12303
|
return !rel.startsWith("..") && !isAbsolute(rel);
|
|
12199
12304
|
}
|
|
12200
|
-
var sidebar_artefacts_default =
|
|
12305
|
+
var sidebar_artefacts_default = app33;
|
|
12201
12306
|
|
|
12202
12307
|
// server/routes/admin/sidebar-artefact-save.ts
|
|
12203
12308
|
import { mkdir as mkdir3, readdir as readdir4, stat as stat5, writeFile as writeFile4 } from "fs/promises";
|
|
12204
12309
|
import { resolve as resolve17 } from "path";
|
|
12205
12310
|
import { existsSync as existsSync19 } from "fs";
|
|
12206
12311
|
var ADMIN_AGENT_FILES2 = /* @__PURE__ */ new Set(["IDENTITY.md", "SOUL.md", "KNOWLEDGE.md"]);
|
|
12207
|
-
var
|
|
12208
|
-
var
|
|
12209
|
-
|
|
12210
|
-
const
|
|
12211
|
-
const accountId = getAccountIdForSession(
|
|
12312
|
+
var UUID_RE6 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
|
|
12313
|
+
var app34 = new Hono();
|
|
12314
|
+
app34.post("/", requireAdminSession, async (c) => {
|
|
12315
|
+
const cacheKey = c.var.cacheKey;
|
|
12316
|
+
const accountId = getAccountIdForSession(cacheKey);
|
|
12212
12317
|
if (!accountId) return c.json({ error: "Account not found for session" }, 401);
|
|
12213
12318
|
const body = await safeJson(c);
|
|
12214
12319
|
if (!body || typeof body.id !== "string" || typeof body.content !== "string") {
|
|
@@ -12264,7 +12369,7 @@ async function resolveSavePath(id, accountId, accountDir) {
|
|
|
12264
12369
|
}
|
|
12265
12370
|
return { kind: "admin-template", path: resolve17(parent, filename) };
|
|
12266
12371
|
}
|
|
12267
|
-
if (
|
|
12372
|
+
if (UUID_RE6.test(id)) {
|
|
12268
12373
|
const dir = resolve17(ATTACHMENTS_ROOT, accountId, id);
|
|
12269
12374
|
if (!existsSync19(dir)) {
|
|
12270
12375
|
return { kind: "reject", status: 400, reason: "not-found" };
|
|
@@ -12286,20 +12391,20 @@ async function resolveSavePath(id, accountId, accountDir) {
|
|
|
12286
12391
|
function relPath(absPath, root) {
|
|
12287
12392
|
return absPath.startsWith(root) ? absPath.slice(root.length + 1) : absPath;
|
|
12288
12393
|
}
|
|
12289
|
-
var sidebar_artefact_save_default =
|
|
12394
|
+
var sidebar_artefact_save_default = app34;
|
|
12290
12395
|
|
|
12291
12396
|
// server/routes/admin/sidebar-artefact-content.ts
|
|
12292
12397
|
import { readFile as readFile5, readdir as readdir5 } from "fs/promises";
|
|
12293
12398
|
import { existsSync as existsSync20 } from "fs";
|
|
12294
12399
|
import { resolve as resolve18 } from "path";
|
|
12295
|
-
var
|
|
12296
|
-
var
|
|
12297
|
-
|
|
12298
|
-
const
|
|
12299
|
-
const accountId = getAccountIdForSession(
|
|
12400
|
+
var UUID_RE7 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
|
|
12401
|
+
var app35 = new Hono();
|
|
12402
|
+
app35.get("/", requireAdminSession, async (c) => {
|
|
12403
|
+
const cacheKey = c.var.cacheKey;
|
|
12404
|
+
const accountId = getAccountIdForSession(cacheKey);
|
|
12300
12405
|
if (!accountId) return new Response("Unauthorized", { status: 401 });
|
|
12301
12406
|
const id = c.req.query("id") ?? "";
|
|
12302
|
-
if (!
|
|
12407
|
+
if (!UUID_RE7.test(id)) {
|
|
12303
12408
|
console.error(`[admin/sidebar-artefact-content] not-found id=${id.slice(0, 8)}`);
|
|
12304
12409
|
return new Response("Not found", { status: 404 });
|
|
12305
12410
|
}
|
|
@@ -12335,7 +12440,7 @@ app34.get("/", requireAdminSession, async (c) => {
|
|
|
12335
12440
|
}
|
|
12336
12441
|
});
|
|
12337
12442
|
});
|
|
12338
|
-
var sidebar_artefact_content_default =
|
|
12443
|
+
var sidebar_artefact_content_default = app35;
|
|
12339
12444
|
|
|
12340
12445
|
// server/routes/admin/health.ts
|
|
12341
12446
|
import { existsSync as existsSync21, readFileSync as readFileSync16 } from "fs";
|
|
@@ -12380,8 +12485,8 @@ async function probeConversationDb() {
|
|
|
12380
12485
|
});
|
|
12381
12486
|
}
|
|
12382
12487
|
}
|
|
12383
|
-
var
|
|
12384
|
-
|
|
12488
|
+
var app36 = new Hono();
|
|
12489
|
+
app36.get("/", async (c) => {
|
|
12385
12490
|
const version = readVersion();
|
|
12386
12491
|
const probe = await probeConversationDb();
|
|
12387
12492
|
const uptimeMs = Date.now() - new Date(PROCESS_STARTED_AT).getTime();
|
|
@@ -12403,37 +12508,38 @@ app35.get("/", async (c) => {
|
|
|
12403
12508
|
uptimeMs
|
|
12404
12509
|
});
|
|
12405
12510
|
});
|
|
12406
|
-
var health_default2 =
|
|
12511
|
+
var health_default2 = app36;
|
|
12407
12512
|
|
|
12408
12513
|
// server/routes/admin/index.ts
|
|
12409
|
-
var
|
|
12410
|
-
|
|
12411
|
-
|
|
12412
|
-
|
|
12413
|
-
|
|
12414
|
-
|
|
12415
|
-
|
|
12416
|
-
|
|
12417
|
-
|
|
12418
|
-
|
|
12419
|
-
|
|
12420
|
-
|
|
12421
|
-
|
|
12422
|
-
|
|
12423
|
-
|
|
12424
|
-
|
|
12425
|
-
|
|
12426
|
-
|
|
12427
|
-
|
|
12428
|
-
|
|
12429
|
-
|
|
12430
|
-
|
|
12431
|
-
|
|
12432
|
-
|
|
12433
|
-
|
|
12434
|
-
|
|
12435
|
-
|
|
12436
|
-
|
|
12514
|
+
var app37 = new Hono();
|
|
12515
|
+
app37.route("/session", session_default2);
|
|
12516
|
+
app37.route("/chat", chat_default2);
|
|
12517
|
+
app37.route("/chat-failure", chat_failure_default);
|
|
12518
|
+
app37.route("/compact", compact_default);
|
|
12519
|
+
app37.route("/logs", logs_default);
|
|
12520
|
+
app37.route("/claude-info", claude_info_default);
|
|
12521
|
+
app37.route("/attachment", attachment_default);
|
|
12522
|
+
app37.route("/agents", agents_default);
|
|
12523
|
+
app37.route("/sessions", sessions_default);
|
|
12524
|
+
app37.route("/browser", browser_default);
|
|
12525
|
+
app37.route("/browser-iframe", browser_iframe_default);
|
|
12526
|
+
app37.route("/device-browser", device_browser_default);
|
|
12527
|
+
app37.route("/events", events_default);
|
|
12528
|
+
app37.route("/cloudflare", cloudflare_default);
|
|
12529
|
+
app37.route("/files", files_default);
|
|
12530
|
+
app37.route("/graph-search", graph_search_default);
|
|
12531
|
+
app37.route("/graph-subgraph", graph_subgraph_default);
|
|
12532
|
+
app37.route("/graph-delete", graph_delete_default);
|
|
12533
|
+
app37.route("/graph-restore", graph_restore_default);
|
|
12534
|
+
app37.route("/graph-labels-in-graph", graph_labels_in_graph_default);
|
|
12535
|
+
app37.route("/graph-default-view", graph_default_view_default);
|
|
12536
|
+
app37.route("/file-attach", file_attach_default);
|
|
12537
|
+
app37.route("/adherence", adherence_default);
|
|
12538
|
+
app37.route("/sidebar-artefacts", sidebar_artefacts_default);
|
|
12539
|
+
app37.route("/sidebar-artefact-save", sidebar_artefact_save_default);
|
|
12540
|
+
app37.route("/sidebar-artefact-content", sidebar_artefact_content_default);
|
|
12541
|
+
app37.route("/health-brand", health_default2);
|
|
12542
|
+
var admin_default = app37;
|
|
12437
12543
|
|
|
12438
12544
|
// server/routes/sites.ts
|
|
12439
12545
|
import { existsSync as existsSync22, readFileSync as readFileSync17, realpathSync as realpathSync4, statSync as statSync7 } from "fs";
|
|
@@ -12468,8 +12574,8 @@ function getExt(p) {
|
|
|
12468
12574
|
if (idx < p.lastIndexOf("/")) return "";
|
|
12469
12575
|
return p.slice(idx).toLowerCase();
|
|
12470
12576
|
}
|
|
12471
|
-
var
|
|
12472
|
-
|
|
12577
|
+
var app38 = new Hono();
|
|
12578
|
+
app38.get("/:rel{.*}", (c) => {
|
|
12473
12579
|
const reqPath = c.req.path;
|
|
12474
12580
|
const rawRel = c.req.param("rel") ?? "";
|
|
12475
12581
|
const trimmed = rawRel.replace(/^\/+/, "").replace(/\/+$/, "");
|
|
@@ -12572,7 +12678,7 @@ app37.get("/:rel{.*}", (c) => {
|
|
|
12572
12678
|
"X-Content-Type-Options": "nosniff"
|
|
12573
12679
|
});
|
|
12574
12680
|
});
|
|
12575
|
-
var sites_default =
|
|
12681
|
+
var sites_default = app38;
|
|
12576
12682
|
|
|
12577
12683
|
// app/lib/graph-health.ts
|
|
12578
12684
|
var HOUR_MS = 60 * 60 * 1e3;
|
|
@@ -12726,9 +12832,9 @@ watchFile(ALIAS_DOMAINS_PATH2, { interval: 2e3 }, () => {
|
|
|
12726
12832
|
function isPublicHost(host) {
|
|
12727
12833
|
return host.startsWith("public.") || aliasDomains.has(host);
|
|
12728
12834
|
}
|
|
12729
|
-
var
|
|
12730
|
-
|
|
12731
|
-
|
|
12835
|
+
var app39 = new Hono();
|
|
12836
|
+
app39.use("*", clientIpMiddleware);
|
|
12837
|
+
app39.use("*", async (c, next) => {
|
|
12732
12838
|
await next();
|
|
12733
12839
|
c.header("X-Content-Type-Options", "nosniff");
|
|
12734
12840
|
c.header("Referrer-Policy", "strict-origin-when-cross-origin");
|
|
@@ -12738,7 +12844,7 @@ app38.use("*", async (c, next) => {
|
|
|
12738
12844
|
);
|
|
12739
12845
|
});
|
|
12740
12846
|
var HTTP_LOG_PATHS = /* @__PURE__ */ new Set(["/vnc-viewer.html", "/vnc-popout.html"]);
|
|
12741
|
-
|
|
12847
|
+
app39.use("*", async (c, next) => {
|
|
12742
12848
|
if (!HTTP_LOG_PATHS.has(c.req.path)) {
|
|
12743
12849
|
await next();
|
|
12744
12850
|
return;
|
|
@@ -12771,7 +12877,7 @@ var PUBLIC_ALLOWED_PREFIXES = [
|
|
|
12771
12877
|
"/sites/"
|
|
12772
12878
|
];
|
|
12773
12879
|
var PUBLIC_ALLOWED_EXACT = ["/favicon.ico"];
|
|
12774
|
-
|
|
12880
|
+
app39.use("*", async (c, next) => {
|
|
12775
12881
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
12776
12882
|
if (!isPublicHost(host)) {
|
|
12777
12883
|
await next();
|
|
@@ -12811,7 +12917,7 @@ function resolveRemoteAuthOpts() {
|
|
|
12811
12917
|
return brandLoginOpts;
|
|
12812
12918
|
}
|
|
12813
12919
|
var MAX_LOGIN_BODY = 8 * 1024;
|
|
12814
|
-
|
|
12920
|
+
app39.post("/__remote-auth/login", async (c) => {
|
|
12815
12921
|
const client = clientFrom(c);
|
|
12816
12922
|
const clientIp = client.ip || "unknown";
|
|
12817
12923
|
if (!requestIsTlsTerminated(c)) {
|
|
@@ -12856,7 +12962,7 @@ app38.post("/__remote-auth/login", async (c) => {
|
|
|
12856
12962
|
}
|
|
12857
12963
|
});
|
|
12858
12964
|
});
|
|
12859
|
-
|
|
12965
|
+
app39.get("/__remote-auth/logout", (c) => {
|
|
12860
12966
|
const client = clientFrom(c);
|
|
12861
12967
|
const clientIp = client.ip || "unknown";
|
|
12862
12968
|
console.error(`[remote-auth] logout ip=${clientIp}`);
|
|
@@ -12869,7 +12975,7 @@ app38.get("/__remote-auth/logout", (c) => {
|
|
|
12869
12975
|
}
|
|
12870
12976
|
});
|
|
12871
12977
|
});
|
|
12872
|
-
|
|
12978
|
+
app39.post("/__remote-auth/change-password", async (c) => {
|
|
12873
12979
|
const client = clientFrom(c);
|
|
12874
12980
|
const clientIp = client.ip || "unknown";
|
|
12875
12981
|
const rateLimited = checkRateLimit(client);
|
|
@@ -12920,13 +13026,13 @@ app38.post("/__remote-auth/change-password", async (c) => {
|
|
|
12920
13026
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), mode: "change", changeError: "Failed to save password", redirect }), 200);
|
|
12921
13027
|
}
|
|
12922
13028
|
});
|
|
12923
|
-
|
|
13029
|
+
app39.get("/__remote-auth/setup", (c) => {
|
|
12924
13030
|
if (isRemoteAuthConfigured()) {
|
|
12925
13031
|
return c.redirect("/");
|
|
12926
13032
|
}
|
|
12927
13033
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), mode: "setup" }), 200);
|
|
12928
13034
|
});
|
|
12929
|
-
|
|
13035
|
+
app39.post("/__remote-auth/set-initial-password", async (c) => {
|
|
12930
13036
|
if (isRemoteAuthConfigured()) {
|
|
12931
13037
|
return c.redirect("/");
|
|
12932
13038
|
}
|
|
@@ -12964,10 +13070,10 @@ app38.post("/__remote-auth/set-initial-password", async (c) => {
|
|
|
12964
13070
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), mode: "setup", setupError: "Failed to save password. Please try again." }), 200);
|
|
12965
13071
|
}
|
|
12966
13072
|
});
|
|
12967
|
-
|
|
13073
|
+
app39.get("/api/remote-auth/status", (c) => {
|
|
12968
13074
|
return c.json({ configured: isRemoteAuthConfigured() });
|
|
12969
13075
|
});
|
|
12970
|
-
|
|
13076
|
+
app39.post("/api/remote-auth/set-password", async (c) => {
|
|
12971
13077
|
let body;
|
|
12972
13078
|
try {
|
|
12973
13079
|
body = await c.req.json();
|
|
@@ -12997,9 +13103,9 @@ app38.post("/api/remote-auth/set-password", async (c) => {
|
|
|
12997
13103
|
return c.json({ error: "Failed to save password" }, 500);
|
|
12998
13104
|
}
|
|
12999
13105
|
});
|
|
13000
|
-
|
|
13106
|
+
app39.route("/api/_client-error", client_error_default);
|
|
13001
13107
|
console.log("[client-error-route] mounted");
|
|
13002
|
-
|
|
13108
|
+
app39.use("*", async (c, next) => {
|
|
13003
13109
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
13004
13110
|
const path2 = c.req.path;
|
|
13005
13111
|
if (path2 === "/favicon.ico" || path2.startsWith("/assets/") || path2.startsWith("/brand/")) {
|
|
@@ -13039,15 +13145,15 @@ app38.use("*", async (c, next) => {
|
|
|
13039
13145
|
console.error(`[remote-auth] login required ip=${clientIp} path=${path2} ${disambig}`);
|
|
13040
13146
|
return c.html(renderLoginPage({ ...resolveRemoteAuthOpts(), redirect: path2 }), 200);
|
|
13041
13147
|
});
|
|
13042
|
-
|
|
13043
|
-
|
|
13044
|
-
|
|
13045
|
-
|
|
13046
|
-
|
|
13047
|
-
|
|
13048
|
-
|
|
13049
|
-
|
|
13050
|
-
|
|
13148
|
+
app39.route("/api/health", health_default);
|
|
13149
|
+
app39.route("/api/session", session_default);
|
|
13150
|
+
app39.route("/api/chat", chat_default);
|
|
13151
|
+
app39.route("/api/group", group_default);
|
|
13152
|
+
app39.route("/api/access", access_default);
|
|
13153
|
+
app39.route("/api/telegram", telegram_default);
|
|
13154
|
+
app39.route("/api/whatsapp", whatsapp_default);
|
|
13155
|
+
app39.route("/api/onboarding", onboarding_default);
|
|
13156
|
+
app39.route("/api/admin", admin_default);
|
|
13051
13157
|
var SAFE_SLUG_RE = /^[a-z][a-z0-9-]{2,49}$/;
|
|
13052
13158
|
var SAFE_FILENAME_RE = /^[a-z0-9_][a-z0-9_.-]{0,99}$/i;
|
|
13053
13159
|
var IMAGE_MIME = {
|
|
@@ -13059,7 +13165,7 @@ var IMAGE_MIME = {
|
|
|
13059
13165
|
".svg": "image/svg+xml",
|
|
13060
13166
|
".ico": "image/x-icon"
|
|
13061
13167
|
};
|
|
13062
|
-
|
|
13168
|
+
app39.get("/agent-assets/:slug/:filename", (c) => {
|
|
13063
13169
|
const slug = c.req.param("slug");
|
|
13064
13170
|
const filename = c.req.param("filename");
|
|
13065
13171
|
if (!SAFE_SLUG_RE.test(slug)) {
|
|
@@ -13094,7 +13200,7 @@ app38.get("/agent-assets/:slug/:filename", (c) => {
|
|
|
13094
13200
|
"Cache-Control": "public, max-age=3600"
|
|
13095
13201
|
});
|
|
13096
13202
|
});
|
|
13097
|
-
|
|
13203
|
+
app39.get("/generated/:filename", (c) => {
|
|
13098
13204
|
const filename = c.req.param("filename");
|
|
13099
13205
|
if (!SAFE_FILENAME_RE.test(filename) || filename.includes("..")) {
|
|
13100
13206
|
console.error(`[generated] serve file=${filename} status=403`);
|
|
@@ -13124,7 +13230,7 @@ app38.get("/generated/:filename", (c) => {
|
|
|
13124
13230
|
"Cache-Control": "public, max-age=86400"
|
|
13125
13231
|
});
|
|
13126
13232
|
});
|
|
13127
|
-
|
|
13233
|
+
app39.route("/sites", sites_default);
|
|
13128
13234
|
var htmlCache = /* @__PURE__ */ new Map();
|
|
13129
13235
|
var brandLogoPath = "/brand/maxy-monochrome.png";
|
|
13130
13236
|
var brandIconPath = "/brand/maxy-monochrome.png";
|
|
@@ -13261,7 +13367,7 @@ function brandedPublicHtml(agentSlug) {
|
|
|
13261
13367
|
function escapeHtml(s) {
|
|
13262
13368
|
return s.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">");
|
|
13263
13369
|
}
|
|
13264
|
-
|
|
13370
|
+
app39.get("/", (c) => {
|
|
13265
13371
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
13266
13372
|
if (isPublicHost(host)) {
|
|
13267
13373
|
const defaultSlug = resolveDefaultSlug();
|
|
@@ -13269,12 +13375,12 @@ app38.get("/", (c) => {
|
|
|
13269
13375
|
}
|
|
13270
13376
|
return c.html(cachedHtml("index.html"));
|
|
13271
13377
|
});
|
|
13272
|
-
|
|
13378
|
+
app39.get("/public", (c) => {
|
|
13273
13379
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
13274
13380
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
13275
13381
|
return c.html(cachedHtml("public.html"));
|
|
13276
13382
|
});
|
|
13277
|
-
|
|
13383
|
+
app39.get("/chat", (c) => {
|
|
13278
13384
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
13279
13385
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
13280
13386
|
return c.html(cachedHtml("public.html"));
|
|
@@ -13293,9 +13399,9 @@ async function logViewerFetch(c, next) {
|
|
|
13293
13399
|
duration_ms: Date.now() - start
|
|
13294
13400
|
});
|
|
13295
13401
|
}
|
|
13296
|
-
|
|
13297
|
-
|
|
13298
|
-
|
|
13402
|
+
app39.use("/vnc-viewer.html", logViewerFetch);
|
|
13403
|
+
app39.use("/vnc-popout.html", logViewerFetch);
|
|
13404
|
+
app39.get("/vnc-popout.html", (c) => {
|
|
13299
13405
|
let html = htmlCache.get("vnc-popout.html");
|
|
13300
13406
|
if (!html) {
|
|
13301
13407
|
html = readFileSync18(resolve21(process.cwd(), "public", "vnc-popout.html"), "utf-8");
|
|
@@ -13308,7 +13414,7 @@ app38.get("/vnc-popout.html", (c) => {
|
|
|
13308
13414
|
}
|
|
13309
13415
|
return c.html(html);
|
|
13310
13416
|
});
|
|
13311
|
-
|
|
13417
|
+
app39.post("/api/vnc/client-event", async (c) => {
|
|
13312
13418
|
let body;
|
|
13313
13419
|
try {
|
|
13314
13420
|
body = await c.req.json();
|
|
@@ -13329,20 +13435,20 @@ app38.post("/api/vnc/client-event", async (c) => {
|
|
|
13329
13435
|
});
|
|
13330
13436
|
return c.json({ ok: true });
|
|
13331
13437
|
});
|
|
13332
|
-
|
|
13438
|
+
app39.get("/g/:slug", (c) => {
|
|
13333
13439
|
return c.html(brandedPublicHtml());
|
|
13334
13440
|
});
|
|
13335
|
-
|
|
13441
|
+
app39.get("/graph", (c) => {
|
|
13336
13442
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
13337
13443
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
13338
13444
|
return c.html(cachedHtml("graph.html"));
|
|
13339
13445
|
});
|
|
13340
|
-
|
|
13446
|
+
app39.get("/data", (c) => {
|
|
13341
13447
|
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
13342
13448
|
if (isPublicHost(host)) return c.text("Not found", 404);
|
|
13343
13449
|
return c.html(cachedHtml("data.html"));
|
|
13344
13450
|
});
|
|
13345
|
-
|
|
13451
|
+
app39.get("/:slug", async (c, next) => {
|
|
13346
13452
|
const slug = c.req.param("slug");
|
|
13347
13453
|
if (AGENT_SLUG_PATTERN.test(`/${slug}`)) {
|
|
13348
13454
|
const branding = loadBrandingCache(slug);
|
|
@@ -13352,15 +13458,15 @@ app38.get("/:slug", async (c, next) => {
|
|
|
13352
13458
|
await next();
|
|
13353
13459
|
});
|
|
13354
13460
|
if (brandFaviconPath !== "/favicon.ico") {
|
|
13355
|
-
|
|
13461
|
+
app39.get("/favicon.ico", (c) => {
|
|
13356
13462
|
c.header("Cache-Control", "public, max-age=300");
|
|
13357
13463
|
return c.redirect(brandFaviconPath, 302);
|
|
13358
13464
|
});
|
|
13359
13465
|
}
|
|
13360
|
-
|
|
13466
|
+
app39.use("/*", serveStatic({ root: "./public" }));
|
|
13361
13467
|
var port = parseInt(process.env.MAXY_UI_INTERNAL_PORT ?? process.env.PORT ?? "19199", 10);
|
|
13362
13468
|
var hostname = process.env.HOSTNAME ?? "127.0.0.1";
|
|
13363
|
-
var httpServer = serve({ fetch:
|
|
13469
|
+
var httpServer = serve({ fetch: app39.fetch, port, hostname });
|
|
13364
13470
|
console.log(`${BRAND.productName} listening on http://${hostname}:${port}`);
|
|
13365
13471
|
console.log("[boot] auth-mode summary: oauth=8 api-key=1 (api-key consumer: invokePublicAgent only)");
|
|
13366
13472
|
var SUBAPP_MANIFEST = [
|
|
@@ -13381,7 +13487,7 @@ for (const m of SUBAPP_MANIFEST) {
|
|
|
13381
13487
|
}
|
|
13382
13488
|
try {
|
|
13383
13489
|
const registered = [];
|
|
13384
|
-
for (const r of
|
|
13490
|
+
for (const r of app39.routes ?? []) {
|
|
13385
13491
|
if (typeof r.path !== "string" || r.path.includes(":") || r.path.includes("*")) continue;
|
|
13386
13492
|
if (AGENT_SLUG_PATTERN.test(r.path)) {
|
|
13387
13493
|
registered.push({ method: (r.method ?? "ALL").toUpperCase(), path: r.path });
|
|
@@ -13413,6 +13519,13 @@ try {
|
|
|
13413
13519
|
console.error(`[session] backfill startup failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
13414
13520
|
}
|
|
13415
13521
|
})();
|
|
13522
|
+
(async () => {
|
|
13523
|
+
try {
|
|
13524
|
+
await backfillConversationChannelAddress();
|
|
13525
|
+
} catch (err) {
|
|
13526
|
+
console.error(`[session-985] channelAddress backfill startup failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
13527
|
+
}
|
|
13528
|
+
})();
|
|
13416
13529
|
(async () => {
|
|
13417
13530
|
try {
|
|
13418
13531
|
if (!existsSync23(USERS_FILE)) return;
|
|
@@ -13467,15 +13580,14 @@ autoDeliverPremiumPlugins(bootEntitlement?.purchasedPlugins ?? void 0);
|
|
|
13467
13580
|
(async () => {
|
|
13468
13581
|
if (!bootAccount) return;
|
|
13469
13582
|
try {
|
|
13470
|
-
const { recoverRunningCloudflareTasks } = await import("./cloudflare-task-tracker-
|
|
13583
|
+
const { recoverRunningCloudflareTasks } = await import("./cloudflare-task-tracker-B6FXP3HI.js");
|
|
13471
13584
|
const result = await recoverRunningCloudflareTasks(
|
|
13472
13585
|
bootAccount.accountId,
|
|
13473
13586
|
configDirForWhatsApp,
|
|
13474
|
-
//
|
|
13475
|
-
//
|
|
13476
|
-
//
|
|
13477
|
-
// and let the
|
|
13478
|
-
// existing edge.
|
|
13587
|
+
// Task 985 — no conversationId at boot. The reconciler operates on
|
|
13588
|
+
// Tasks whose Conversation is already linked via RAISED_DURING; the
|
|
13589
|
+
// tracker resolves the conversationId off that edge when present.
|
|
13590
|
+
// Pass null and let the recovery path pick it up.
|
|
13479
13591
|
null
|
|
13480
13592
|
);
|
|
13481
13593
|
if (result.scanned > 0) {
|
|
@@ -13557,10 +13669,10 @@ init({
|
|
|
13557
13669
|
agentName = resolved.slug;
|
|
13558
13670
|
}
|
|
13559
13671
|
let enrichedText = msg.text || msg.mediaPath || msg.mediaType || msg.replyContext ? buildEnrichedText2(msg.text ?? "") : "";
|
|
13560
|
-
if (msg.
|
|
13672
|
+
if (msg.cacheKey) {
|
|
13561
13673
|
const platformAccountId = bootAccount?.accountId ?? msg.accountId;
|
|
13562
|
-
registerSession(msg.
|
|
13563
|
-
console.error(`[session] channel session registered:
|
|
13674
|
+
registerSession(msg.cacheKey, msg.agentType, platformAccountId, agentName);
|
|
13675
|
+
console.error(`[session] channel session registered: cacheKey=${msg.cacheKey.slice(0, 12)}\u2026 channel=whatsapp accountId=${platformAccountId.slice(0, 8)}\u2026`);
|
|
13564
13676
|
}
|
|
13565
13677
|
let gatewayResult;
|
|
13566
13678
|
if (msg.text) {
|
|
@@ -13584,7 +13696,7 @@ init({
|
|
|
13584
13696
|
for await (const event of invokeAgent(
|
|
13585
13697
|
{ type: msg.agentType, agentName },
|
|
13586
13698
|
enrichedText,
|
|
13587
|
-
msg.
|
|
13699
|
+
msg.cacheKey,
|
|
13588
13700
|
[],
|
|
13589
13701
|
void 0,
|
|
13590
13702
|
gatewayResult
|
|
@@ -13602,7 +13714,7 @@ init({
|
|
|
13602
13714
|
for await (const event of invokeAgent(
|
|
13603
13715
|
{ type: msg.agentType, agentName },
|
|
13604
13716
|
enrichedText,
|
|
13605
|
-
msg.
|
|
13717
|
+
msg.cacheKey,
|
|
13606
13718
|
[],
|
|
13607
13719
|
void 0,
|
|
13608
13720
|
gatewayResult
|