@sentry/junior 0.84.1 → 0.86.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{agent-hooks-TFPY6V3T.js → agent-hooks-NWOUB3UR.js} +7 -7
- package/dist/app.js +916 -363
- package/dist/chat/conversation-privacy.d.ts +12 -2
- package/dist/chat/conversations/sql/migrations.d.ts +1 -1
- package/dist/chat/conversations/sql/store.d.ts +9 -1
- package/dist/chat/conversations/store.d.ts +13 -0
- package/dist/chat/current-instruction.d.ts +6 -0
- package/dist/chat/ingress/message-changed.d.ts +2 -0
- package/dist/chat/respond-helpers.d.ts +1 -2
- package/dist/chat/respond.d.ts +7 -1
- package/dist/chat/runtime/reply-executor.d.ts +2 -10
- package/dist/chat/runtime/slack-runtime.d.ts +5 -4
- package/dist/chat/runtime/turn.d.ts +7 -0
- package/dist/chat/services/persist-retry.d.ts +2 -0
- package/dist/chat/services/turn-session-record.d.ts +31 -2
- package/dist/chat/slack/client.d.ts +33 -2
- package/dist/chat/slack/conversation-context.d.ts +15 -0
- package/dist/chat/state/turn-session.d.ts +9 -0
- package/dist/chat/task-execution/queue.d.ts +1 -1
- package/dist/chat/task-execution/slack-work.d.ts +10 -2
- package/dist/chat/task-execution/state.d.ts +44 -4
- package/dist/chat/task-execution/store.d.ts +21 -4
- package/dist/chat/task-execution/worker.d.ts +11 -4
- package/dist/chat/tools/slack/channel-access.d.ts +29 -0
- package/dist/chat/tools/slack/thread-read.d.ts +4 -1
- package/dist/{chunk-AL6ZFV7U.js → chunk-2NFV5FMB.js} +4 -4
- package/dist/{chunk-JK7376UT.js → chunk-37B2R2QJ.js} +17 -17
- package/dist/{chunk-QWKB6NJV.js → chunk-6I6HBOQM.js} +80 -15
- package/dist/{chunk-SBYMRDH7.js → chunk-6O5UI3RG.js} +1 -1
- package/dist/{chunk-CWMMGUWM.js → chunk-BRSQQRG6.js} +1 -1
- package/dist/{chunk-FPN7NYTE.js → chunk-ENPSU7L7.js} +165 -27
- package/dist/{chunk-T2YRJZ5A.js → chunk-FPHA6GCQ.js} +905 -711
- package/dist/{chunk-MJ4E2PK7.js → chunk-GB5DFM4D.js} +1 -1
- package/dist/{chunk-BAPRSWNW.js → chunk-GGD6WK6V.js} +124 -25
- package/dist/{chunk-SVFA43LT.js → chunk-JRXCSSSU.js} +19 -4
- package/dist/{chunk-DR75T7J3.js → chunk-L7OHKDOX.js} +9 -5
- package/dist/{chunk-LSG6PQF4.js → chunk-RIB3M6YA.js} +2 -2
- package/dist/{chunk-ALL7GG6U.js → chunk-ZU2ALUVQ.js} +45 -6
- package/dist/cli/chat.js +4 -4
- package/dist/cli/plugins.js +7 -7
- package/dist/cli/snapshot-warmup.js +4 -4
- package/dist/cli/upgrade.js +10 -7
- package/dist/{db-ELRCNB4A.js → db-SZVUU7RB.js} +4 -4
- package/dist/handlers/github-webhook/issue-comment.d.ts +3 -0
- package/dist/handlers/github-webhook/pull-request-review-comment.d.ts +3 -0
- package/dist/instrumentation.js +1 -1
- package/dist/nitro.js +4 -4
- package/dist/reporting/conversations.d.ts +2 -1
- package/dist/reporting.js +110 -34
- package/dist/{runner-2XU6QQND.js → runner-HEBRPNN2.js} +27 -13
- package/package.json +5 -5
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { ConversationPrivacy } from "@/chat/conversation-privacy";
|
|
2
|
+
/** Minimal persisted-visibility port for cross-conversation read gates. */
|
|
3
|
+
export interface DestinationVisibilityReader {
|
|
4
|
+
getDestinationVisibility(args: {
|
|
5
|
+
provider: string;
|
|
6
|
+
providerDestinationId: string;
|
|
7
|
+
providerTenantId?: string;
|
|
8
|
+
}): Promise<ConversationPrivacy | undefined>;
|
|
9
|
+
}
|
|
10
|
+
export type SlackChannelReadAccess = {
|
|
11
|
+
allowed: true;
|
|
12
|
+
} | {
|
|
13
|
+
allowed: false;
|
|
14
|
+
error: string;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Decide whether the model may read Slack content from a target channel.
|
|
18
|
+
*
|
|
19
|
+
* The current conversation is always readable. Any other channel requires
|
|
20
|
+
* persisted `public` visibility in the same workspace: channel-id prefixes
|
|
21
|
+
* cannot prove a channel public (modern Slack private channels also use `C`
|
|
22
|
+
* ids), so missing or private destinations fail closed.
|
|
23
|
+
*/
|
|
24
|
+
export declare function checkSlackChannelReadAccess(args: {
|
|
25
|
+
currentChannelIds: Array<string | undefined>;
|
|
26
|
+
store?: DestinationVisibilityReader;
|
|
27
|
+
targetChannelId: string;
|
|
28
|
+
teamId: string;
|
|
29
|
+
}): Promise<SlackChannelReadAccess>;
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
import { type DestinationVisibilityReader } from "@/chat/tools/slack/channel-access";
|
|
1
2
|
import type { SlackToolContext } from "@/chat/tools/slack/context";
|
|
2
3
|
/** Create a tool that reads a Slack thread from a shared message URL or explicit coordinates. */
|
|
3
|
-
export declare function createSlackThreadReadTool(context: SlackToolContext
|
|
4
|
+
export declare function createSlackThreadReadTool(context: SlackToolContext, deps?: {
|
|
5
|
+
visibilityStore?: DestinationVisibilityReader;
|
|
6
|
+
}): import("@/chat/tools/definition").ToolDefinition<import("@sinclair/typebox").TObject<{
|
|
4
7
|
url: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
5
8
|
channel_id: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
6
9
|
ts: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createPluginLogger,
|
|
3
3
|
createPluginState
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-BRSQQRG6.js";
|
|
5
5
|
import {
|
|
6
6
|
getDb
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-6I6HBOQM.js";
|
|
8
8
|
import {
|
|
9
9
|
SANDBOX_WORKSPACE_ROOT
|
|
10
10
|
} from "./chunk-G3E7SCME.js";
|
|
@@ -13,12 +13,12 @@ import {
|
|
|
13
13
|
isConversationScopedChannel,
|
|
14
14
|
isDmChannel,
|
|
15
15
|
normalizeSlackConversationId
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-GGD6WK6V.js";
|
|
17
17
|
import {
|
|
18
18
|
botConfig,
|
|
19
19
|
completeObject,
|
|
20
20
|
embedTexts
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-ZU2ALUVQ.js";
|
|
22
22
|
import {
|
|
23
23
|
isActorUserId,
|
|
24
24
|
parseActorUserId
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
getConversationStore
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-6I6HBOQM.js";
|
|
4
4
|
import {
|
|
5
5
|
SANDBOX_DATA_ROOT,
|
|
6
6
|
SANDBOX_WORKSPACE_ROOT,
|
|
@@ -9,15 +9,16 @@ import {
|
|
|
9
9
|
import {
|
|
10
10
|
getConnectedStateContext,
|
|
11
11
|
getStateAdapter
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-GB5DFM4D.js";
|
|
13
13
|
import {
|
|
14
14
|
parseDestination
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-GGD6WK6V.js";
|
|
16
16
|
import {
|
|
17
17
|
TURN_CONTEXT_TAG,
|
|
18
18
|
botConfig,
|
|
19
|
+
escapeXml,
|
|
19
20
|
getChatConfig
|
|
20
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-ZU2ALUVQ.js";
|
|
21
22
|
import {
|
|
22
23
|
parseRequester,
|
|
23
24
|
storedSlackRequesterSchema,
|
|
@@ -658,21 +659,16 @@ async function commitMessages(args) {
|
|
|
658
659
|
};
|
|
659
660
|
}
|
|
660
661
|
|
|
661
|
-
// src/chat/xml.ts
|
|
662
|
-
function escapeXml(value) {
|
|
663
|
-
return value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
664
|
-
}
|
|
665
|
-
|
|
666
|
-
// src/chat/prompt.ts
|
|
667
|
-
import fs from "fs";
|
|
668
|
-
import path from "path";
|
|
669
|
-
|
|
670
662
|
// src/chat/interruption-marker.ts
|
|
671
663
|
var INTERRUPTED_MARKER = "\n\n[Response interrupted before completion]";
|
|
672
664
|
function getInterruptionMarker() {
|
|
673
665
|
return INTERRUPTED_MARKER;
|
|
674
666
|
}
|
|
675
667
|
|
|
668
|
+
// src/chat/prompt.ts
|
|
669
|
+
import fs from "fs";
|
|
670
|
+
import path from "path";
|
|
671
|
+
|
|
676
672
|
// src/chat/slack/status-format.ts
|
|
677
673
|
var SLACK_STATUS_MAX_LENGTH = 50;
|
|
678
674
|
function truncateStatusText(text) {
|
|
@@ -1651,7 +1647,7 @@ function buildTurnContextPrompt(params) {
|
|
|
1651
1647
|
const sections = [
|
|
1652
1648
|
`<${TURN_CONTEXT_TAG}>`,
|
|
1653
1649
|
TURN_CONTEXT_HEADER,
|
|
1654
|
-
"The current user instruction appears after this block in the same message.",
|
|
1650
|
+
"The current user instruction appears after this block in `<current-instruction>` in the same message.",
|
|
1655
1651
|
...runtimeSections,
|
|
1656
1652
|
`</${TURN_CONTEXT_TAG}>`
|
|
1657
1653
|
].filter((section) => Boolean(section));
|
|
@@ -1851,7 +1847,8 @@ async function recordConversationActivityMetadata(args) {
|
|
|
1851
1847
|
destination: args.summary.destination,
|
|
1852
1848
|
nowMs: args.nowMs,
|
|
1853
1849
|
requester: sessionLogRequester(args.summary.requester),
|
|
1854
|
-
source
|
|
1850
|
+
source,
|
|
1851
|
+
visibility: args.destinationVisibility
|
|
1855
1852
|
});
|
|
1856
1853
|
await conversationStore.recordExecution({
|
|
1857
1854
|
channelName: args.summary.channelName,
|
|
@@ -1862,7 +1859,8 @@ async function recordConversationActivityMetadata(args) {
|
|
|
1862
1859
|
lastActivityAtMs: args.summary.updatedAtMs,
|
|
1863
1860
|
requester: sessionLogRequester(args.summary.requester),
|
|
1864
1861
|
source,
|
|
1865
|
-
updatedAtMs: args.nowMs
|
|
1862
|
+
updatedAtMs: args.nowMs,
|
|
1863
|
+
visibility: args.destinationVisibility
|
|
1866
1864
|
});
|
|
1867
1865
|
} catch (error) {
|
|
1868
1866
|
logWarn(
|
|
@@ -2002,6 +2000,7 @@ async function setStoredRecord(args) {
|
|
|
2002
2000
|
await appendAgentTurnSessionSummary(summary, args.ttlMs);
|
|
2003
2001
|
await recordConversationActivityMetadata({
|
|
2004
2002
|
conversationStore: args.conversationStore,
|
|
2003
|
+
destinationVisibility: args.destinationVisibility,
|
|
2005
2004
|
nowMs: Date.now(),
|
|
2006
2005
|
summary
|
|
2007
2006
|
});
|
|
@@ -2058,6 +2057,7 @@ async function upsertAgentTurnSessionRecord(args) {
|
|
|
2058
2057
|
});
|
|
2059
2058
|
return await setStoredRecord({
|
|
2060
2059
|
conversationStore: args.conversationStore,
|
|
2060
|
+
destinationVisibility: args.destinationVisibility,
|
|
2061
2061
|
piMessages: args.piMessages,
|
|
2062
2062
|
ttlMs,
|
|
2063
2063
|
record: buildStoredRecord({
|
|
@@ -2122,6 +2122,7 @@ async function recordAgentTurnSessionSummary(args) {
|
|
|
2122
2122
|
await appendAgentTurnSessionSummary(summary, ttlMs);
|
|
2123
2123
|
await recordConversationActivityMetadata({
|
|
2124
2124
|
conversationStore: args.conversationStore,
|
|
2125
|
+
destinationVisibility: args.destinationVisibility,
|
|
2125
2126
|
nowMs,
|
|
2126
2127
|
summary
|
|
2127
2128
|
});
|
|
@@ -2189,7 +2190,6 @@ export {
|
|
|
2189
2190
|
normalizeSlackStatusText,
|
|
2190
2191
|
splitSlackReplyText,
|
|
2191
2192
|
buildSlackOutputMessage,
|
|
2192
|
-
escapeXml,
|
|
2193
2193
|
JUNIOR_PERSONALITY,
|
|
2194
2194
|
buildPluginSystemPromptContributions,
|
|
2195
2195
|
buildSystemPrompt,
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import {
|
|
2
2
|
parseDestination,
|
|
3
3
|
sameDestination
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-GGD6WK6V.js";
|
|
5
5
|
import {
|
|
6
6
|
getChatConfig
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-ZU2ALUVQ.js";
|
|
8
8
|
import {
|
|
9
9
|
parseStoredSlackRequester
|
|
10
10
|
} from "./chunk-IXTBFABZ.js";
|
|
11
11
|
|
|
12
12
|
// src/chat/conversations/sql/store.ts
|
|
13
13
|
import { randomUUID } from "crypto";
|
|
14
|
-
import { asc, desc, eq, sql as sql2 } from "drizzle-orm";
|
|
14
|
+
import { and, asc, desc, eq, sql as sql2 } from "drizzle-orm";
|
|
15
15
|
|
|
16
16
|
// src/chat/conversations/sql/migrations.ts
|
|
17
17
|
import { createHash } from "crypto";
|
|
@@ -298,8 +298,20 @@ CREATE INDEX IF NOT EXISTS junior_conversations_origin_idx
|
|
|
298
298
|
ON junior_conversations (origin_type, origin_id, last_activity_at DESC)
|
|
299
299
|
`
|
|
300
300
|
];
|
|
301
|
+
var destinationVisibilityBackfillStatements = [
|
|
302
|
+
`
|
|
303
|
+
UPDATE junior_destinations
|
|
304
|
+
SET visibility = 'private'
|
|
305
|
+
WHERE provider = 'slack'
|
|
306
|
+
AND visibility = 'public'
|
|
307
|
+
`
|
|
308
|
+
];
|
|
301
309
|
var migrations = [
|
|
302
|
-
defineMigration("0001_conversation_core", coreMetadataStatements)
|
|
310
|
+
defineMigration("0001_conversation_core", coreMetadataStatements),
|
|
311
|
+
defineMigration(
|
|
312
|
+
"0002_slack_destination_visibility_backfill",
|
|
313
|
+
destinationVisibilityBackfillStatements
|
|
314
|
+
)
|
|
303
315
|
];
|
|
304
316
|
function parseStoredMigrationRecord(value) {
|
|
305
317
|
return migrationRecordSchema.parse(value);
|
|
@@ -436,13 +448,13 @@ function destinationUpsertFromDestination(args) {
|
|
|
436
448
|
if (destination.platform === "slack") {
|
|
437
449
|
const channelId = destination.channelId;
|
|
438
450
|
const channelKind = channelId.startsWith("D") ? "dm" : channelId.startsWith("G") ? "group" : "channel";
|
|
439
|
-
const visibility = channelId.startsWith("D") ? "direct" : channelId.startsWith("G") ? "private" : "public";
|
|
440
451
|
return {
|
|
441
452
|
kind: channelKind,
|
|
442
453
|
provider: "slack",
|
|
443
454
|
providerTenantId: destination.teamId,
|
|
444
455
|
providerDestinationId: channelId,
|
|
445
|
-
visibility,
|
|
456
|
+
refreshVisibility: args.visibility !== void 0,
|
|
457
|
+
visibility: args.visibility ?? "private",
|
|
446
458
|
...args.channelName ? { displayName: args.channelName } : {},
|
|
447
459
|
metadata: { platform: "slack" }
|
|
448
460
|
};
|
|
@@ -452,6 +464,7 @@ function destinationUpsertFromDestination(args) {
|
|
|
452
464
|
provider: "local",
|
|
453
465
|
providerTenantId: localWorkspaceFromConversationId(destination.conversationId) ?? localWorkspaceFromConversationId(args.conversationId ?? ""),
|
|
454
466
|
providerDestinationId: destination.conversationId,
|
|
467
|
+
refreshVisibility: true,
|
|
455
468
|
visibility: "direct",
|
|
456
469
|
metadata: { platform: "local" }
|
|
457
470
|
};
|
|
@@ -462,7 +475,15 @@ function executionStatusFromValue(value) {
|
|
|
462
475
|
}
|
|
463
476
|
throw new Error("Conversation record execution status is invalid");
|
|
464
477
|
}
|
|
465
|
-
function
|
|
478
|
+
function privacyFromRow(row) {
|
|
479
|
+
if (row.destinationVisibility === null) {
|
|
480
|
+
return void 0;
|
|
481
|
+
}
|
|
482
|
+
return row.destinationVisibility === "public" ? "public" : "private";
|
|
483
|
+
}
|
|
484
|
+
function conversationFromRow(readRow) {
|
|
485
|
+
const row = readRow.conversation;
|
|
486
|
+
const visibility = privacyFromRow(readRow);
|
|
466
487
|
if (row.schemaVersion !== 1) {
|
|
467
488
|
throw new Error("Conversation record schema version is invalid");
|
|
468
489
|
}
|
|
@@ -496,7 +517,8 @@ function conversationFromRow(row) {
|
|
|
496
517
|
...requester ? { requester } : {},
|
|
497
518
|
...row.channelName ? { channelName: row.channelName } : {},
|
|
498
519
|
...source ? { source } : {},
|
|
499
|
-
...row.title ? { title: row.title } : {}
|
|
520
|
+
...row.title ? { title: row.title } : {},
|
|
521
|
+
...visibility ? { visibility } : {}
|
|
500
522
|
};
|
|
501
523
|
}
|
|
502
524
|
function emptyConversation(args) {
|
|
@@ -572,9 +594,10 @@ var SqlStore = class {
|
|
|
572
594
|
nowMs,
|
|
573
595
|
source: args.source
|
|
574
596
|
});
|
|
597
|
+
const { visibility: _persisted, ...currentWithoutVisibility } = current2;
|
|
575
598
|
await this.upsertConversation({
|
|
576
599
|
conversation: {
|
|
577
|
-
...
|
|
600
|
+
...currentWithoutVisibility,
|
|
578
601
|
destination: current2.destination ?? args.destination,
|
|
579
602
|
source: current2.source ?? args.source,
|
|
580
603
|
channelName: current2.channelName ?? args.channelName,
|
|
@@ -585,7 +608,8 @@ var SqlStore = class {
|
|
|
585
608
|
execution: {
|
|
586
609
|
...current2.execution,
|
|
587
610
|
updatedAtMs: current2.execution.updatedAtMs ?? nowMs
|
|
588
|
-
}
|
|
611
|
+
},
|
|
612
|
+
...args.visibility ? { visibility: args.visibility } : {}
|
|
589
613
|
}
|
|
590
614
|
});
|
|
591
615
|
});
|
|
@@ -604,13 +628,15 @@ var SqlStore = class {
|
|
|
604
628
|
...args.requester ? { requester: args.requester } : {},
|
|
605
629
|
...args.source ? { source: args.source } : {},
|
|
606
630
|
...args.title ? { title: args.title } : {},
|
|
631
|
+
...args.visibility ? { visibility: args.visibility } : {},
|
|
607
632
|
execution: args.execution
|
|
608
633
|
}
|
|
609
634
|
});
|
|
610
635
|
});
|
|
611
636
|
}
|
|
612
637
|
/** Copy one conversation record into SQL during backfill. */
|
|
613
|
-
async backfillConversation(
|
|
638
|
+
async backfillConversation(sourceConversation) {
|
|
639
|
+
const { visibility: _visibility, ...conversation } = sourceConversation;
|
|
614
640
|
await this.withConversationMutation(
|
|
615
641
|
conversation.conversationId,
|
|
616
642
|
async () => {
|
|
@@ -646,7 +672,13 @@ var SqlStore = class {
|
|
|
646
672
|
);
|
|
647
673
|
}
|
|
648
674
|
async listByActivity(args = {}) {
|
|
649
|
-
const rows = await this.executor.db().select(
|
|
675
|
+
const rows = await this.executor.db().select({
|
|
676
|
+
conversation: juniorConversations,
|
|
677
|
+
destinationVisibility: juniorDestinations.visibility
|
|
678
|
+
}).from(juniorConversations).leftJoin(
|
|
679
|
+
juniorDestinations,
|
|
680
|
+
eq(juniorDestinations.id, juniorConversations.destinationId)
|
|
681
|
+
).orderBy(
|
|
650
682
|
desc(juniorConversations.lastActivityAt),
|
|
651
683
|
asc(juniorConversations.conversationId)
|
|
652
684
|
).limit(Math.max(0, args.limit ?? 1e4)).offset(Math.max(0, args.offset ?? 0));
|
|
@@ -656,6 +688,28 @@ var SqlStore = class {
|
|
|
656
688
|
}
|
|
657
689
|
return conversations;
|
|
658
690
|
}
|
|
691
|
+
async getDestinationVisibility(args) {
|
|
692
|
+
const rows = await this.executor.db().select({
|
|
693
|
+
visibility: juniorDestinations.visibility
|
|
694
|
+
}).from(juniorDestinations).where(
|
|
695
|
+
and(
|
|
696
|
+
eq(juniorDestinations.provider, args.provider),
|
|
697
|
+
eq(
|
|
698
|
+
juniorDestinations.providerTenantId,
|
|
699
|
+
tenantId(args.providerTenantId)
|
|
700
|
+
),
|
|
701
|
+
eq(
|
|
702
|
+
juniorDestinations.providerDestinationId,
|
|
703
|
+
args.providerDestinationId
|
|
704
|
+
)
|
|
705
|
+
)
|
|
706
|
+
);
|
|
707
|
+
const row = rows[0];
|
|
708
|
+
if (!row) {
|
|
709
|
+
return void 0;
|
|
710
|
+
}
|
|
711
|
+
return row.visibility === "public" ? "public" : "private";
|
|
712
|
+
}
|
|
659
713
|
/** Serialize all durable mutations for one conversation inside a SQL transaction. */
|
|
660
714
|
async withConversationMutation(conversationId, callback) {
|
|
661
715
|
return await this.executor.withLock(
|
|
@@ -664,7 +718,13 @@ var SqlStore = class {
|
|
|
664
718
|
);
|
|
665
719
|
}
|
|
666
720
|
async readConversationRow(conversationId) {
|
|
667
|
-
const rows = await this.executor.db().select(
|
|
721
|
+
const rows = await this.executor.db().select({
|
|
722
|
+
conversation: juniorConversations,
|
|
723
|
+
destinationVisibility: juniorDestinations.visibility
|
|
724
|
+
}).from(juniorConversations).leftJoin(
|
|
725
|
+
juniorDestinations,
|
|
726
|
+
eq(juniorDestinations.id, juniorConversations.destinationId)
|
|
727
|
+
).where(eq(juniorConversations.conversationId, conversationId));
|
|
668
728
|
return rows[0];
|
|
669
729
|
}
|
|
670
730
|
/** Upsert the conversation row while preserving previously discovered nullable metadata fields. */
|
|
@@ -677,7 +737,8 @@ var SqlStore = class {
|
|
|
677
737
|
destinationUpsertFromDestination({
|
|
678
738
|
channelName: conversation.channelName,
|
|
679
739
|
conversationId: conversation.conversationId,
|
|
680
|
-
destination: conversation.destination
|
|
740
|
+
destination: conversation.destination,
|
|
741
|
+
...conversation.visibility ? { visibility: conversation.visibility } : {}
|
|
681
742
|
}),
|
|
682
743
|
conversation.updatedAtMs
|
|
683
744
|
);
|
|
@@ -779,6 +840,7 @@ var SqlStore = class {
|
|
|
779
840
|
if (!destination) {
|
|
780
841
|
return void 0;
|
|
781
842
|
}
|
|
843
|
+
const visibilityUpdate = destination.refreshVisibility ? sql2`excluded.visibility` : juniorDestinations.visibility;
|
|
782
844
|
const rows = await this.executor.db().insert(juniorDestinations).values({
|
|
783
845
|
id: randomUUID(),
|
|
784
846
|
provider: destination.provider,
|
|
@@ -800,7 +862,10 @@ var SqlStore = class {
|
|
|
800
862
|
set: {
|
|
801
863
|
kind: sql2`excluded.kind`,
|
|
802
864
|
displayName: sql2`coalesce(excluded.display_name, ${juniorDestinations.displayName})`,
|
|
803
|
-
|
|
865
|
+
// Signal-less writes insert as private but must not clobber an
|
|
866
|
+
// existing public/private value. Live source signals refresh this
|
|
867
|
+
// field so converted channels converge on the next message.
|
|
868
|
+
visibility: visibilityUpdate,
|
|
804
869
|
metadata: sql2`coalesce(excluded.metadata_json, ${juniorDestinations.metadata})`,
|
|
805
870
|
updatedAt: sql2`excluded.updated_at`
|
|
806
871
|
}
|