@rudderhq/server 0.7.24-canary.21 → 0.7.24-canary.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bootstrap/register-api-routes.d.ts.map +1 -1
- package/dist/bootstrap/register-api-routes.js +2 -2
- package/dist/bootstrap/register-api-routes.js.map +1 -1
- package/dist/routes/approvals.d.ts +2 -1
- package/dist/routes/approvals.d.ts.map +1 -1
- package/dist/routes/approvals.js +49 -4
- package/dist/routes/approvals.js.map +1 -1
- package/dist/routes/chats.d.ts +2 -1
- package/dist/routes/chats.d.ts.map +1 -1
- package/dist/routes/chats.js +3 -3
- package/dist/routes/chats.js.map +1 -1
- package/dist/routes/chats.stream-routes.d.ts.map +1 -1
- package/dist/routes/chats.stream-routes.js +1 -0
- package/dist/routes/chats.stream-routes.js.map +1 -1
- package/dist/routes/organization-rust-foundation-routes.d.ts.map +1 -1
- package/dist/routes/organization-rust-foundation-routes.js +27 -14
- package/dist/routes/organization-rust-foundation-routes.js.map +1 -1
- package/dist/routes/orgs.d.ts +1 -1
- package/dist/routes/orgs.d.ts.map +1 -1
- package/dist/routes/orgs.js +23 -2
- package/dist/routes/orgs.js.map +1 -1
- package/dist/services/chat-organization-branding-rust-idempotency.test.d.ts +2 -0
- package/dist/services/chat-organization-branding-rust-idempotency.test.d.ts.map +1 -0
- package/dist/services/chat-organization-branding-rust-idempotency.test.js +367 -0
- package/dist/services/chat-organization-branding-rust-idempotency.test.js.map +1 -0
- package/dist/services/chat-organization-branding.d.ts +78 -0
- package/dist/services/chat-organization-branding.d.ts.map +1 -0
- package/dist/services/chat-organization-branding.js +212 -0
- package/dist/services/chat-organization-branding.js.map +1 -0
- package/dist/services/chats.d.ts +24 -6
- package/dist/services/chats.d.ts.map +1 -1
- package/dist/services/chats.js +76 -86
- package/dist/services/chats.js.map +1 -1
- package/dist/services/organization-branding-fence.d.ts +4 -3
- package/dist/services/organization-branding-fence.d.ts.map +1 -1
- package/dist/services/organization-branding-fence.js +4 -3
- package/dist/services/organization-branding-fence.js.map +1 -1
- package/dist/services/orgs.d.ts +1 -0
- package/dist/services/orgs.d.ts.map +1 -1
- package/dist/services/orgs.js +11 -2
- package/dist/services/orgs.js.map +1 -1
- package/dist/services/rust-foundation-bridge.d.ts +3 -0
- package/dist/services/rust-foundation-bridge.d.ts.map +1 -1
- package/dist/services/rust-foundation-bridge.js +160 -26
- package/dist/services/rust-foundation-bridge.js.map +1 -1
- package/dist/services/rust-foundation-bridge.test.js +164 -3
- package/dist/services/rust-foundation-bridge.test.js.map +1 -1
- package/dist/services/workspace-backups.d.ts +0 -1
- package/dist/services/workspace-backups.d.ts.map +1 -1
- package/dist/services/workspace-backups.js +0 -11
- package/dist/services/workspace-backups.js.map +1 -1
- package/package.json +13 -13
- package/resources/bundled-skills/rudder-docs/references/cli-reference.md +1 -1
- package/resources/native/aarch64-apple-darwin/rudder-server-foundation +0 -0
- package/resources/native/aarch64-pc-windows-msvc/migration-preflight.exe +0 -0
- package/resources/native/aarch64-pc-windows-msvc/rudder-server-foundation.exe +0 -0
- package/resources/native/aarch64-unknown-linux-gnu/rudder-server-foundation +0 -0
- package/resources/native/x86_64-apple-darwin/rudder-server-foundation +0 -0
- package/resources/native/x86_64-pc-windows-msvc/migration-preflight.exe +0 -0
- package/resources/native/x86_64-pc-windows-msvc/rudder-server-foundation.exe +0 -0
- package/resources/native/x86_64-unknown-linux-gnu/rudder-server-foundation +0 -0
- package/skills/rudder-docs/references/cli-reference.md +1 -1
- package/ui-dist/assets/{LibraryLiveSurface-Bs8V_pMU.js → LibraryLiveSurface-CodApFW-.js} +1 -1
- package/ui-dist/assets/{abnfDiagram-VRR7QNED-DneqWru9.js → abnfDiagram-VRR7QNED-BDz58rQS.js} +1 -1
- package/ui-dist/assets/{addon-fit-DCRNyXYv.js → addon-fit-DZOvRzIT.js} +1 -1
- package/ui-dist/assets/{arc-D_2I_R5Z.js → arc-C9TMZvvd.js} +1 -1
- package/ui-dist/assets/{architectureDiagram-ZJ3FMSHR-C0ANAv78.js → architectureDiagram-ZJ3FMSHR-D4twxoE1.js} +1 -1
- package/ui-dist/assets/{blockDiagram-677ZJIJ3-BqFGOix5.js → blockDiagram-677ZJIJ3-DJs0gNG4.js} +1 -1
- package/ui-dist/assets/{c4Diagram-LMCZKHZV-82LfEi1P.js → c4Diagram-LMCZKHZV-6oq8lq8q.js} +1 -1
- package/ui-dist/assets/channel-CmUGU_Az.js +1 -0
- package/ui-dist/assets/{chunk-2Q5K7J3B-DijvvGcl.js → chunk-2Q5K7J3B-m2MTxaYE.js} +1 -1
- package/ui-dist/assets/{chunk-32BRIVSS-Z09s337w.js → chunk-32BRIVSS-BYbeAqiG.js} +1 -1
- package/ui-dist/assets/{chunk-5VM5RSS4-DgQWkO6B.js → chunk-5VM5RSS4-Dy6Af71u.js} +1 -1
- package/ui-dist/assets/{chunk-EX3LRPZG-UTEQqeds.js → chunk-EX3LRPZG-DBbU0fB6.js} +1 -1
- package/ui-dist/assets/{chunk-JWPE2WC7-DAaSu1vD.js → chunk-JWPE2WC7-D3_gHXg6.js} +1 -1
- package/ui-dist/assets/{chunk-MOJQB5TN-D_fTXJM3.js → chunk-MOJQB5TN-Di4_CsSE.js} +1 -1
- package/ui-dist/assets/{chunk-RYQCIY6F-C7H_axhC.js → chunk-RYQCIY6F-CnLAkiBe.js} +1 -1
- package/ui-dist/assets/{chunk-V7JOEXUC-B2toa05O.js → chunk-V7JOEXUC-D3UVXcJk.js} +1 -1
- package/ui-dist/assets/{chunk-VR4S4FIN-CkRvPkE2.js → chunk-VR4S4FIN-BJHYVSXv.js} +1 -1
- package/ui-dist/assets/{chunk-XXDRQBXY-DOO_r0VK.js → chunk-XXDRQBXY-C4VVlQgO.js} +1 -1
- package/ui-dist/assets/classDiagram-OUVF2IWQ-Dy5r3CRw.js +1 -0
- package/ui-dist/assets/classDiagram-v2-EOCWNBFH-Dy5r3CRw.js +1 -0
- package/ui-dist/assets/{cose-bilkent-JH36ORCC-BzYjE_M-.js → cose-bilkent-JH36ORCC-2YJ4B2bE.js} +1 -1
- package/ui-dist/assets/{cynefin-VYW2F7L2-Dcf0eQJ5.js → cynefin-VYW2F7L2-293DKtI3.js} +1 -1
- package/ui-dist/assets/{cynefinDiagram-TSTJHNR4-Cs_Lv8Ua.js → cynefinDiagram-TSTJHNR4-d23XGkDy.js} +1 -1
- package/ui-dist/assets/{dagre-VKFMJZFB-B8oZME7g.js → dagre-VKFMJZFB-EJXBSBZ7.js} +1 -1
- package/ui-dist/assets/{diagram-FQU43EPY-DFHkB-_t.js → diagram-FQU43EPY-CcQzLlPj.js} +1 -1
- package/ui-dist/assets/{diagram-G47NLZAW-FGxRm1A-.js → diagram-G47NLZAW-Bke8VP0c.js} +1 -1
- package/ui-dist/assets/{diagram-NH7WQ7WH-Ot83ScOb.js → diagram-NH7WQ7WH-CDVrkJeo.js} +1 -1
- package/ui-dist/assets/{diagram-OA4YK3LP-CkiHNUvw.js → diagram-OA4YK3LP-Dw_uKvbb.js} +1 -1
- package/ui-dist/assets/{diagram-WEI45ONY-CxM3g_L3.js → diagram-WEI45ONY-DmhFc8DI.js} +1 -1
- package/ui-dist/assets/{ebnfDiagram-CCIWWBDH-DbcqsHcY.js → ebnfDiagram-CCIWWBDH-CdqBJkjm.js} +1 -1
- package/ui-dist/assets/{erDiagram-Q63AITRT-DLROlxDN.js → erDiagram-Q63AITRT-DOkjjwWL.js} +1 -1
- package/ui-dist/assets/{flowDiagram-23GEKE2U-DphM_YLM.js → flowDiagram-23GEKE2U-DG8rqW-P.js} +1 -1
- package/ui-dist/assets/{ganttDiagram-NO4QXBWP--QIRtWYP.js → ganttDiagram-NO4QXBWP-BEkgTSEf.js} +1 -1
- package/ui-dist/assets/{gitGraphDiagram-IHSO6WYX-Bg3QwNvE.js → gitGraphDiagram-IHSO6WYX-BjXwkXS6.js} +1 -1
- package/ui-dist/assets/{graph-B_1y14m_.js → graph-D3KzI4sR.js} +1 -1
- package/ui-dist/assets/{index-E2v-0TkN.js → index-B2UcZ_IJ.js} +1 -1
- package/ui-dist/assets/{index-Bi9I1TFJ.js → index-BDH__Lgs.js} +5 -5
- package/ui-dist/assets/{index-CcWXJMSa.js → index-BIQKbQUa.js} +1 -1
- package/ui-dist/assets/{index-XWYyP2hU.js → index-BIwzh-U4.js} +1 -1
- package/ui-dist/assets/{index-BlFoD6Gg.js → index-BNdZbjyn.js} +1 -1
- package/ui-dist/assets/{index-B-yeMW3t.js → index-BONjSnI2.js} +1 -1
- package/ui-dist/assets/{index-Aj3Mi7R6.js → index-BrgGIOAR.js} +1 -1
- package/ui-dist/assets/{index-CS2TW9nf.js → index-By6wVGNY.js} +1 -1
- package/ui-dist/assets/{index-BABow2kh.js → index-C6RzrVdO.js} +1 -1
- package/ui-dist/assets/{index-BueQLOw6.js → index-ChpzeG1B.js} +1 -1
- package/ui-dist/assets/{index-6O1Ef9oA.js → index-D-jdXuoy.js} +1 -1
- package/ui-dist/assets/{index-CdAtz86o.js → index-D2RUPIgv.js} +1 -1
- package/ui-dist/assets/{index-BEgTumxB.js → index-D3MTazer.js} +1 -1
- package/ui-dist/assets/{index-CMUgKK2j.js → index-DepPPcF2.js} +1 -1
- package/ui-dist/assets/{index-BQheb_6L.js → index-fZqqDrca.js} +1 -1
- package/ui-dist/assets/{infoDiagram-FWYZ7A6U-BxygKDVp.js → infoDiagram-FWYZ7A6U-sxoY23rO.js} +1 -1
- package/ui-dist/assets/{ishikawaDiagram-FXEZZL3T-47zucfG2.js → ishikawaDiagram-FXEZZL3T-DS6bgeAA.js} +1 -1
- package/ui-dist/assets/{journeyDiagram-5HDEW3XC-D8cyI8aY.js → journeyDiagram-5HDEW3XC-DzVKXP7n.js} +1 -1
- package/ui-dist/assets/{kanban-definition-HUTT4EX6-CrxRNese.js → kanban-definition-HUTT4EX6--VTcXs7-.js} +1 -1
- package/ui-dist/assets/{layout-OyZo5VN3.js → layout-DMOyxlK9.js} +1 -1
- package/ui-dist/assets/{linear-CuiwlwQB.js → linear-C76BMUjd.js} +1 -1
- package/ui-dist/assets/{map-rixHzQ5d.js → map-CeACQf-M.js} +1 -1
- package/ui-dist/assets/{mermaid.core-BBG92fxH.js → mermaid.core-C39RyJW7.js} +4 -4
- package/ui-dist/assets/{mindmap-definition-LN4V7U3C-CivqbhCV.js → mindmap-definition-LN4V7U3C-CC5aZy3e.js} +1 -1
- package/ui-dist/assets/{pegDiagram-2B236MQR-JrPSWk9k.js → pegDiagram-2B236MQR-Pfr90o3u.js} +1 -1
- package/ui-dist/assets/{pieDiagram-ENE6RG2P-F4HEWR5n.js → pieDiagram-ENE6RG2P-cFuaxMwf.js} +1 -1
- package/ui-dist/assets/{quadrantDiagram-ABIIQ3AL-BJNly8dn.js → quadrantDiagram-ABIIQ3AL-CcQ7rg5U.js} +1 -1
- package/ui-dist/assets/{railroadDiagram-RFXS5EU6-DNORDnb2.js → railroadDiagram-RFXS5EU6-Dn0G1sUQ.js} +1 -1
- package/ui-dist/assets/{requirementDiagram-TGXJPOKE-710xtGEU.js → requirementDiagram-TGXJPOKE-C55Bzmxm.js} +1 -1
- package/ui-dist/assets/{sankeyDiagram-HTMAVEWB-BmWJHmHA.js → sankeyDiagram-HTMAVEWB-rC-F0WZY.js} +1 -1
- package/ui-dist/assets/{sequenceDiagram-DBY2YBRQ-A73TFc3V.js → sequenceDiagram-DBY2YBRQ-DKnrOS-d.js} +1 -1
- package/ui-dist/assets/{sizeCapture-X5ZJPWSS-B8otrPI2.js → sizeCapture-X5ZJPWSS-CftJxMqM.js} +1 -1
- package/ui-dist/assets/{stateDiagram-2N3HPSRC-BZ9k729q.js → stateDiagram-2N3HPSRC-BWk2fDZE.js} +1 -1
- package/ui-dist/assets/stateDiagram-v2-6OUMAXLB-CAKipX8h.js +1 -0
- package/ui-dist/assets/{swimlanes-5IMT3BWC-W_CH_z9Z.js → swimlanes-5IMT3BWC-DEOS3o8Q.js} +2 -2
- package/ui-dist/assets/swimlanesDiagram-G3AALYLV-BICPV_pK.js +8 -0
- package/ui-dist/assets/{timeline-definition-FHXFAJF6-CcXbC6J1.js → timeline-definition-FHXFAJF6-_6-BAwLW.js} +1 -1
- package/ui-dist/assets/{vennDiagram-L72KCM5P-BMHmsQqg.js → vennDiagram-L72KCM5P-BjCktz3U.js} +1 -1
- package/ui-dist/assets/{wardleyDiagram-EHGQE667-Bq2-CEvU.js → wardleyDiagram-EHGQE667-DrmL6CAw.js} +1 -1
- package/ui-dist/assets/{xterm-8vrqRuWm.js → xterm-Jvo0xPzf.js} +1 -1
- package/ui-dist/assets/{xychartDiagram-FW5EYKEG-De3RUAME.js → xychartDiagram-FW5EYKEG-DyJoUa3f.js} +1 -1
- package/ui-dist/index.html +1 -1
- package/ui-dist/assets/channel-DjvWm5jR.js +0 -1
- package/ui-dist/assets/classDiagram-OUVF2IWQ-CNSRItW2.js +0 -1
- package/ui-dist/assets/classDiagram-v2-EOCWNBFH-CNSRItW2.js +0 -1
- package/ui-dist/assets/stateDiagram-v2-6OUMAXLB-DepHJpk7.js +0 -1
- package/ui-dist/assets/swimlanesDiagram-G3AALYLV-BRL-ddud.js +0 -8
package/dist/services/chats.js
CHANGED
|
@@ -3,6 +3,7 @@ import { parseShortRef, sanitizeChatStructuredPayload } from "@rudderhq/shared";
|
|
|
3
3
|
import { withChatTranscriptGenerationProvenance } from "@rudderhq/shared/chat-transcript-provenance";
|
|
4
4
|
import { and, asc, desc, eq, gt, inArray, isNotNull, isNull, lt, lte, or, sql } from "drizzle-orm";
|
|
5
5
|
import { randomUUID } from "node:crypto";
|
|
6
|
+
import { isDeepStrictEqual } from "node:util";
|
|
6
7
|
import { conflict, HttpError, notFound, unprocessable } from "../errors.js";
|
|
7
8
|
import { logActivity } from "./activity-log.js";
|
|
8
9
|
import { agentService } from "./agents.js";
|
|
@@ -11,6 +12,7 @@ import { ensureChatFamilyGroup } from "./chat-family-groups.js";
|
|
|
11
12
|
import { chatGenerationProtocolService } from "./chat-generation-protocol.js";
|
|
12
13
|
import { validateCanonicalChatInlineAnnotations } from "./chat-inline-annotation-validation.js";
|
|
13
14
|
import { selectedChatMessageBranchCondition } from "./chat-message-branch.js";
|
|
15
|
+
import { createChatOrganizationBrandingService } from "./chat-organization-branding.js";
|
|
14
16
|
import { hydrateQueuedMessage, materializeQueuedUserMessage, normalizeQueuedMessagePayload, QUEUED_ANNOTATION_ASSETS_KEY, queuedAnnotationAssetState, queuedMessageMutationFingerprint, withQueuedAnnotationAssetState, } from "./chat-queued-message-materialization.js";
|
|
15
17
|
import { compareChatGenerationSelection, listChatGenerationTranscripts, listDetachedChatTranscripts, listDetachedChatTranscriptSummaries, loadChatTranscripts, replaceDetachedChatTranscript, selectChatTranscript, transcriptSummaryFromSources, } from "./chat-transcript-persistence.js";
|
|
16
18
|
import { createChatAnnotationMessagePersistence, createChatMessageMutationLookup } from "./chats.annotation-persistence.js";
|
|
@@ -34,7 +36,7 @@ const CHAT_TITLE_MAX_LENGTH = 200;
|
|
|
34
36
|
class InvalidQueueDeliveryActionLinkError extends Error {
|
|
35
37
|
}
|
|
36
38
|
import { createConversationUserStateInitializer } from "./chats.user-state-initialization.js";
|
|
37
|
-
export function chatService(db, storage) {
|
|
39
|
+
export function chatService(db, storage, rustFoundationBridge) {
|
|
38
40
|
const generationProtocol = chatGenerationProtocolService(db);
|
|
39
41
|
const QUEUED_MESSAGE_CLAIM_LEASE_MS = 2 * 60 * 1000;
|
|
40
42
|
const issuesSvc = issueService(db, storage);
|
|
@@ -44,6 +46,15 @@ export function chatService(db, storage) {
|
|
|
44
46
|
const agentsSvc = agentService(db);
|
|
45
47
|
const addUserChatMessage = createChatAnnotationMessagePersistence(db, getMessage);
|
|
46
48
|
const getUserMessageMutationByClientMutationId = createChatMessageMutationLookup(db, getMessage);
|
|
49
|
+
const organizationBrandingSvc = createChatOrganizationBrandingService({
|
|
50
|
+
db,
|
|
51
|
+
organizationsSvc,
|
|
52
|
+
agentsSvc,
|
|
53
|
+
bridge: rustFoundationBridge,
|
|
54
|
+
getMessage,
|
|
55
|
+
updateMessageStructuredPayload,
|
|
56
|
+
addMessage,
|
|
57
|
+
});
|
|
47
58
|
const ensureConversationUserStates = createConversationUserStateInitializer(db);
|
|
48
59
|
async function listConversationUserStates(orgId, userId, conversationIds) {
|
|
49
60
|
if (conversationIds.length === 0)
|
|
@@ -3233,10 +3244,8 @@ export function chatService(db, storage) {
|
|
|
3233
3244
|
const sanitizedPayload = sanitizeChatStructuredPayload(input.structuredPayload ?? null);
|
|
3234
3245
|
const transcriptFromPayload = chatTranscriptFromPayload(sanitizedPayload);
|
|
3235
3246
|
const transcript = input.transcript ?? transcriptFromPayload;
|
|
3236
|
-
const { message } = await db.transaction(async (tx) => {
|
|
3237
|
-
const
|
|
3238
|
-
.insert(chatMessages)
|
|
3239
|
-
.values({
|
|
3247
|
+
const { message, created } = await db.transaction(async (tx) => {
|
|
3248
|
+
const values = {
|
|
3240
3249
|
orgId: input.orgId,
|
|
3241
3250
|
conversationId,
|
|
3242
3251
|
role: input.role,
|
|
@@ -3247,24 +3256,51 @@ export function chatService(db, storage) {
|
|
|
3247
3256
|
approvalId: input.approvalId ?? null,
|
|
3248
3257
|
runId: input.runId ?? null,
|
|
3249
3258
|
replyingAgentId: input.replyingAgentId ?? null,
|
|
3259
|
+
clientMutationId: input.clientMutationId ?? null,
|
|
3250
3260
|
chatTurnId: input.chatTurnId ?? null,
|
|
3251
3261
|
turnVariant: input.turnVariant ?? 0,
|
|
3252
|
-
}
|
|
3253
|
-
|
|
3254
|
-
|
|
3262
|
+
};
|
|
3263
|
+
const [inserted] = input.clientMutationId
|
|
3264
|
+
? await tx.insert(chatMessages).values(values).onConflictDoNothing().returning()
|
|
3265
|
+
: await tx.insert(chatMessages).values(values).returning();
|
|
3266
|
+
if (inserted) {
|
|
3267
|
+
if (transcript.length > 0) {
|
|
3268
|
+
await replaceDetachedChatTranscript(tx, {
|
|
3269
|
+
orgId: input.orgId,
|
|
3270
|
+
messageId: inserted.id,
|
|
3271
|
+
entries: transcript,
|
|
3272
|
+
});
|
|
3273
|
+
}
|
|
3274
|
+
return { message: inserted, created: true };
|
|
3275
|
+
}
|
|
3276
|
+
if (!input.clientMutationId)
|
|
3255
3277
|
throw new Error("Failed to create chat message");
|
|
3256
3278
|
if (transcript.length > 0) {
|
|
3257
|
-
|
|
3258
|
-
orgId: input.orgId,
|
|
3259
|
-
messageId: inserted.id,
|
|
3260
|
-
entries: transcript,
|
|
3261
|
-
});
|
|
3279
|
+
throw conflict("Idempotent Chat system events cannot replace transcript content");
|
|
3262
3280
|
}
|
|
3263
|
-
|
|
3281
|
+
const existing = await tx
|
|
3282
|
+
.select()
|
|
3283
|
+
.from(chatMessages)
|
|
3284
|
+
.where(and(eq(chatMessages.conversationId, conversationId), eq(chatMessages.clientMutationId, input.clientMutationId)))
|
|
3285
|
+
.then((rows) => rows[0] ?? null);
|
|
3286
|
+
if (!existing)
|
|
3287
|
+
throw new Error("Chat message idempotency key conflicted without a matching message");
|
|
3288
|
+
if (existing.orgId !== values.orgId
|
|
3289
|
+
|| existing.role !== values.role
|
|
3290
|
+
|| existing.kind !== values.kind
|
|
3291
|
+
|| existing.status !== values.status
|
|
3292
|
+
|| existing.body !== values.body
|
|
3293
|
+
|| existing.approvalId !== values.approvalId
|
|
3294
|
+
|| existing.runId !== values.runId
|
|
3295
|
+
|| existing.replyingAgentId !== values.replyingAgentId
|
|
3296
|
+
|| !isDeepStrictEqual(existing.structuredPayload, values.structuredPayload)) {
|
|
3297
|
+
throw conflict("Chat message idempotency key was reused with different content");
|
|
3298
|
+
}
|
|
3299
|
+
return { message: existing, created: false };
|
|
3264
3300
|
});
|
|
3265
3301
|
if (!message)
|
|
3266
3302
|
throw new Error("Failed to create chat message");
|
|
3267
|
-
if (input.role === "user" || isVisibleIncomingChatMessage(message)) {
|
|
3303
|
+
if (created && (input.role === "user" || isVisibleIncomingChatMessage(message))) {
|
|
3268
3304
|
await refreshConversationTouch(conversationId, message.createdAt);
|
|
3269
3305
|
}
|
|
3270
3306
|
const [hydrated] = await hydrateMessages([message]);
|
|
@@ -3631,9 +3667,6 @@ export function chatService(db, storage) {
|
|
|
3631
3667
|
throw unprocessable("This operation proposal is managed through approvals");
|
|
3632
3668
|
}
|
|
3633
3669
|
const currentState = operationProposalDecisionStatusFromPayload(message.structuredPayload);
|
|
3634
|
-
if (currentState.status !== "pending") {
|
|
3635
|
-
throw unprocessable("Only pending lightweight changes can be resolved");
|
|
3636
|
-
}
|
|
3637
3670
|
const proposal = operationProposalFromPayload(message.structuredPayload);
|
|
3638
3671
|
if (!proposal) {
|
|
3639
3672
|
throw unprocessable("Chat operation proposal payload was incomplete");
|
|
@@ -3647,52 +3680,25 @@ export function chatService(db, storage) {
|
|
|
3647
3680
|
throw unprocessable("Agent lightweight changes must target an agent in the same organization");
|
|
3648
3681
|
}
|
|
3649
3682
|
}
|
|
3683
|
+
if (input.action === "approve" && proposal.targetType === "organization") {
|
|
3684
|
+
return organizationBrandingSvc.resolveOperationProposal({
|
|
3685
|
+
conversationId,
|
|
3686
|
+
messageId,
|
|
3687
|
+
orgId: conversation.orgId,
|
|
3688
|
+
messagePayload: message.structuredPayload,
|
|
3689
|
+
proposal: { ...proposal, targetType: "organization" },
|
|
3690
|
+
currentState,
|
|
3691
|
+
actorUserId: input.actorUserId,
|
|
3692
|
+
actor: input.actor,
|
|
3693
|
+
decisionNote: input.decisionNote,
|
|
3694
|
+
});
|
|
3695
|
+
}
|
|
3696
|
+
if (currentState.status !== "pending") {
|
|
3697
|
+
throw unprocessable("Only pending lightweight changes can be resolved");
|
|
3698
|
+
}
|
|
3650
3699
|
const decisionNote = safeTrim(input.decisionNote);
|
|
3651
3700
|
const decidedAtIso = new Date().toISOString();
|
|
3652
3701
|
if (input.action === "approve") {
|
|
3653
|
-
if (proposal.targetType === "organization") {
|
|
3654
|
-
const updated = await organizationsSvc.update(proposal.targetId, proposal.patch);
|
|
3655
|
-
if (!updated)
|
|
3656
|
-
throw notFound("Organization not found");
|
|
3657
|
-
const updatedMessage = await updateMessageStructuredPayload(conversationId, messageId, withOperationProposalDecisionState(message.structuredPayload, {
|
|
3658
|
-
status: "approved",
|
|
3659
|
-
decisionNote,
|
|
3660
|
-
decidedByUserId: input.actorUserId,
|
|
3661
|
-
decidedAt: decidedAtIso,
|
|
3662
|
-
}));
|
|
3663
|
-
if (!updatedMessage) {
|
|
3664
|
-
throw notFound("Operation proposal not found");
|
|
3665
|
-
}
|
|
3666
|
-
const systemMessage = await addMessage(conversationId, {
|
|
3667
|
-
orgId: conversation.orgId,
|
|
3668
|
-
role: "system",
|
|
3669
|
-
kind: "system_event",
|
|
3670
|
-
body: `Applied lightweight change: ${proposal.summary}.`,
|
|
3671
|
-
structuredPayload: {
|
|
3672
|
-
eventType: "operation_applied",
|
|
3673
|
-
source: "chat",
|
|
3674
|
-
sourceMessageId: messageId,
|
|
3675
|
-
targetType: "organization",
|
|
3676
|
-
targetId: proposal.targetId,
|
|
3677
|
-
decisionNote,
|
|
3678
|
-
},
|
|
3679
|
-
});
|
|
3680
|
-
await logActivity(db, {
|
|
3681
|
-
orgId: conversation.orgId,
|
|
3682
|
-
actorType: "user",
|
|
3683
|
-
actorId: input.actorUserId ?? "board",
|
|
3684
|
-
action: "organization.updated",
|
|
3685
|
-
entityType: "organization",
|
|
3686
|
-
entityId: proposal.targetId,
|
|
3687
|
-
details: {
|
|
3688
|
-
source: "chat_lightweight_change",
|
|
3689
|
-
sourceMessageId: messageId,
|
|
3690
|
-
decisionNote,
|
|
3691
|
-
...proposal.patch,
|
|
3692
|
-
},
|
|
3693
|
-
});
|
|
3694
|
-
return { message: updatedMessage, systemMessage };
|
|
3695
|
-
}
|
|
3696
3702
|
const updated = await agentsSvc.update(proposal.targetId, proposal.patch);
|
|
3697
3703
|
if (!updated || updated.orgId !== conversation.orgId) {
|
|
3698
3704
|
throw notFound("Agent not found");
|
|
@@ -3763,7 +3769,7 @@ export function chatService(db, storage) {
|
|
|
3763
3769
|
});
|
|
3764
3770
|
return { message: updatedMessage, systemMessage };
|
|
3765
3771
|
}
|
|
3766
|
-
async function applyApprovedApproval(approval, actorUserId) {
|
|
3772
|
+
async function applyApprovedApproval(approval, actorUserId, actor, options = {}) {
|
|
3767
3773
|
if (approval.type !== "chat_issue_creation" && approval.type !== "chat_operation") {
|
|
3768
3774
|
return null;
|
|
3769
3775
|
}
|
|
@@ -3866,31 +3872,14 @@ export function chatService(db, storage) {
|
|
|
3866
3872
|
}
|
|
3867
3873
|
}
|
|
3868
3874
|
if (proposal.targetType === "organization") {
|
|
3869
|
-
|
|
3870
|
-
|
|
3871
|
-
|
|
3872
|
-
|
|
3873
|
-
|
|
3874
|
-
|
|
3875
|
-
|
|
3876
|
-
body: `Applied approved organization change: ${proposal.summary}.`,
|
|
3877
|
-
structuredPayload: {
|
|
3878
|
-
eventType: "operation_applied",
|
|
3879
|
-
approvalId: approval.id,
|
|
3880
|
-
targetType: "organization",
|
|
3881
|
-
targetId: proposal.targetId,
|
|
3882
|
-
},
|
|
3883
|
-
});
|
|
3884
|
-
await logActivity(db, {
|
|
3885
|
-
orgId: approval.orgId,
|
|
3886
|
-
actorType: "user",
|
|
3887
|
-
actorId: actorUserId ?? "board",
|
|
3888
|
-
action: "organization.updated",
|
|
3889
|
-
entityType: "organization",
|
|
3890
|
-
entityId: proposal.targetId,
|
|
3891
|
-
details: proposal.patch,
|
|
3875
|
+
return organizationBrandingSvc.applyApprovedApproval({
|
|
3876
|
+
approval,
|
|
3877
|
+
actorUserId,
|
|
3878
|
+
actor,
|
|
3879
|
+
recoveryOnly: options.recoveryOnly ?? false,
|
|
3880
|
+
conversationId,
|
|
3881
|
+
proposal: { ...proposal, targetType: "organization" },
|
|
3892
3882
|
});
|
|
3893
|
-
return updated;
|
|
3894
3883
|
}
|
|
3895
3884
|
const updated = await agentsSvc.update(proposal.targetId, proposal.patch);
|
|
3896
3885
|
if (!updated)
|
|
@@ -4005,6 +3994,7 @@ export function chatService(db, storage) {
|
|
|
4005
3994
|
getMessage,
|
|
4006
3995
|
getUserMessageMutationByClientMutationId,
|
|
4007
3996
|
applyApprovedApproval,
|
|
3997
|
+
validateApprovedApproval: organizationBrandingSvc.validateApprovedApproval,
|
|
4008
3998
|
createProposalApproval,
|
|
4009
3999
|
resolveOperationProposal,
|
|
4010
4000
|
};
|