@codeforbreakfast/commy-mcp 0.15.0 → 0.16.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/package.json +1 -1
- package/server.js +289 -167
package/package.json
CHANGED
package/server.js
CHANGED
|
@@ -45359,6 +45359,9 @@ var MessageIdSchema = exports_Schema.NonEmptyString.pipe(exports_Schema.brand("M
|
|
|
45359
45359
|
var decodeMessageId = exports_Schema.decodeUnknown(MessageIdSchema);
|
|
45360
45360
|
var ThreadNameSchema = exports_Schema.NonEmptyString.pipe(exports_Schema.brand("ThreadName"));
|
|
45361
45361
|
var decodeThreadName = exports_Schema.decodeUnknown(ThreadNameSchema);
|
|
45362
|
+
var ChannelPermalinkSchema = exports_Schema.NonEmptyString.pipe(exports_Schema.brand("ChannelPermalink"));
|
|
45363
|
+
var ThreadPermalinkSchema = exports_Schema.NonEmptyString.pipe(exports_Schema.brand("ThreadPermalink"));
|
|
45364
|
+
var MessagePermalinkSchema = exports_Schema.NonEmptyString.pipe(exports_Schema.brand("MessagePermalink"));
|
|
45362
45365
|
var TimestampSchema = exports_Schema.NonNegative.pipe(exports_Schema.brand("Timestamp"));
|
|
45363
45366
|
var decodeTimestamp = exports_Schema.decodeUnknown(TimestampSchema);
|
|
45364
45367
|
var MessageBodySchema = exports_Schema.NonEmptyString.pipe(exports_Schema.brand("MessageBody"));
|
|
@@ -45379,6 +45382,22 @@ var decodeMessageBodySync = exports_Schema.decodeSync(MessageBodySchema);
|
|
|
45379
45382
|
var decodeDisplayNameSync = exports_Schema.decodeSync(DisplayNameSchema);
|
|
45380
45383
|
var decodeBotNameSync = exports_Schema.decodeSync(BotNameSchema);
|
|
45381
45384
|
var decodeEmojiSync = exports_Schema.decodeSync(EmojiSchema);
|
|
45385
|
+
var ChannelRefSchema = exports_Schema.Struct({
|
|
45386
|
+
id: ChannelIdSchema,
|
|
45387
|
+
name: ChannelNameSchema,
|
|
45388
|
+
permalink: ChannelPermalinkSchema
|
|
45389
|
+
});
|
|
45390
|
+
var ObservedThreadSchema = exports_Schema.Struct({
|
|
45391
|
+
name: ThreadNameSchema,
|
|
45392
|
+
resolved: exports_Schema.Boolean,
|
|
45393
|
+
permalink: ThreadPermalinkSchema
|
|
45394
|
+
});
|
|
45395
|
+
var MessageRefSchema = exports_Schema.Struct({
|
|
45396
|
+
id: MessageIdSchema,
|
|
45397
|
+
channel: ChannelRefSchema,
|
|
45398
|
+
thread: exports_Schema.OptionFromSelf(ObservedThreadSchema),
|
|
45399
|
+
permalink: MessagePermalinkSchema
|
|
45400
|
+
});
|
|
45382
45401
|
|
|
45383
45402
|
class DirectoryError extends exports_Data.TaggedError("DirectoryError") {
|
|
45384
45403
|
get message() {
|
|
@@ -47425,23 +47444,40 @@ var HASH_REPLACEMENTS = {
|
|
|
47425
47444
|
var encodeHashComponent = (value5) => encodeURIComponent(value5).replace(/[%!'()*.]/g, (matched) => HASH_REPLACEMENTS[matched] ?? matched);
|
|
47426
47445
|
var permalinkBase = (config2) => config2.hostHeader === undefined ? config2.realmUrl.replace(/\/+$/, "") : `https://${config2.hostHeader}`;
|
|
47427
47446
|
var channelSlug = (channel) => `${channel.id}-${encodeHashComponent(channel.name.replaceAll(" ", "-"))}`;
|
|
47428
|
-
var channelPermalink = (base, channel) => `${base}/#narrow/channel/${channelSlug(channel)}
|
|
47429
|
-
var topicPermalink = (base, channel, topic) => `${channelPermalink(base, channel)}/topic/${encodeHashComponent(topic)}
|
|
47430
|
-
var messagePermalink = (base,
|
|
47447
|
+
var channelPermalink = (base, channel) => ChannelPermalinkSchema.make(`${base}/#narrow/channel/${channelSlug(channel)}`);
|
|
47448
|
+
var topicPermalink = (base, channel, topic, anchor) => ThreadPermalinkSchema.make(`${channelPermalink(base, channel)}/topic/${encodeHashComponent(topic)}/with/${anchor}`);
|
|
47449
|
+
var messagePermalink = (base, id3) => MessagePermalinkSchema.make(`${base}/#narrow/id/${id3}`);
|
|
47431
47450
|
var withChannelPermalink = (base, channel) => ({ ...channel, permalink: channelPermalink(base, channel) });
|
|
47432
|
-
var buildMessageRef = (base, id3, channel,
|
|
47451
|
+
var buildMessageRef = (base, id3, channel, thread) => {
|
|
47433
47452
|
const decoratedChannel = withChannelPermalink(base, channel);
|
|
47434
|
-
|
|
47453
|
+
const permalink = messagePermalink(base, id3);
|
|
47454
|
+
return thread === undefined ? {
|
|
47435
47455
|
id: id3,
|
|
47436
47456
|
channel: decoratedChannel,
|
|
47437
|
-
thread:
|
|
47438
|
-
|
|
47439
|
-
|
|
47440
|
-
|
|
47441
|
-
|
|
47457
|
+
thread: exports_Option.none(),
|
|
47458
|
+
permalink
|
|
47459
|
+
} : {
|
|
47460
|
+
id: id3,
|
|
47461
|
+
channel: decoratedChannel,
|
|
47462
|
+
thread: exports_Option.some({
|
|
47463
|
+
name: thread.name,
|
|
47464
|
+
resolved: thread.resolved,
|
|
47465
|
+
permalink: topicPermalink(base, decoratedChannel, thread.name, id3)
|
|
47466
|
+
}),
|
|
47467
|
+
permalink
|
|
47442
47468
|
};
|
|
47443
47469
|
};
|
|
47444
47470
|
|
|
47471
|
+
// packages/zulip/resolved-topic.ts
|
|
47472
|
+
var RESOLVED_TOPIC_PREFIX = "✔ ";
|
|
47473
|
+
var isResolvedTopic = (topic) => topic.startsWith(RESOLVED_TOPIC_PREFIX);
|
|
47474
|
+
var stripResolvedPrefix = (topic) => isResolvedTopic(topic) ? topic.slice(RESOLVED_TOPIC_PREFIX.length) : topic;
|
|
47475
|
+
var splitTopic = (rawTopic) => {
|
|
47476
|
+
const stripped = stripResolvedPrefix(rawTopic);
|
|
47477
|
+
return isResolvedTopic(rawTopic) && stripped.length > 0 ? { name: stripped, resolved: true } : { name: rawTopic, resolved: false };
|
|
47478
|
+
};
|
|
47479
|
+
var applyResolvedPrefix = (name, resolved) => resolved ? isResolvedTopic(name) ? name : RESOLVED_TOPIC_PREFIX + name : stripResolvedPrefix(name);
|
|
47480
|
+
|
|
47445
47481
|
// packages/zulip/events.ts
|
|
47446
47482
|
var createMessageRefCache = (maxSize = 1e4) => {
|
|
47447
47483
|
const map32 = new Map;
|
|
@@ -47535,8 +47571,9 @@ var decodeMessageRef = (message, base) => exports_Effect.gen(function* () {
|
|
|
47535
47571
|
const id3 = yield* decodeMessageId(String(message.id));
|
|
47536
47572
|
const channelId = yield* decodeChannelId(String(message.stream_id));
|
|
47537
47573
|
const channelName = yield* decodeChannelName(message.display_recipient);
|
|
47538
|
-
const
|
|
47539
|
-
|
|
47574
|
+
const { name, resolved } = splitTopic(message.subject);
|
|
47575
|
+
const threadName3 = yield* decodeThreadName(name);
|
|
47576
|
+
return buildMessageRef(base, id3, { id: channelId, name: channelName }, { name: threadName3, resolved });
|
|
47540
47577
|
});
|
|
47541
47578
|
var decodeSenderIdentity = (message, directory) => {
|
|
47542
47579
|
const cached4 = directory.byId.get(message.sender_id);
|
|
@@ -47934,6 +47971,8 @@ var historicalReactionSchema = exports_Schema.Struct({
|
|
|
47934
47971
|
});
|
|
47935
47972
|
var historicalMessageRawSchema = exports_Schema.Struct({
|
|
47936
47973
|
id: exports_Schema.Int,
|
|
47974
|
+
stream_id: exports_Schema.Int,
|
|
47975
|
+
display_recipient: exports_Schema.String,
|
|
47937
47976
|
sender_id: exports_Schema.Int,
|
|
47938
47977
|
sender_full_name: exports_Schema.String,
|
|
47939
47978
|
subject: exports_Schema.NonEmptyString,
|
|
@@ -47942,19 +47981,27 @@ var historicalMessageRawSchema = exports_Schema.Struct({
|
|
|
47942
47981
|
reactions: exports_Schema.optional(exports_Schema.Array(historicalReactionSchema))
|
|
47943
47982
|
});
|
|
47944
47983
|
var toHistoricalReaction = (r) => ({ userId: ZulipUserRef(r.user_id), emojiName: r.emoji_name });
|
|
47945
|
-
var toHistoricalMessage = (m) =>
|
|
47946
|
-
|
|
47947
|
-
|
|
47948
|
-
|
|
47949
|
-
|
|
47950
|
-
|
|
47951
|
-
|
|
47952
|
-
|
|
47953
|
-
subject,
|
|
47954
|
-
|
|
47955
|
-
|
|
47956
|
-
|
|
47957
|
-
|
|
47984
|
+
var toHistoricalMessage = (m) => {
|
|
47985
|
+
const { name, resolved } = splitTopic(m.subject);
|
|
47986
|
+
return exports_Effect.all({
|
|
47987
|
+
id: decodeMessageId(String(m.id)),
|
|
47988
|
+
channelId: decodeChannelId(String(m.stream_id)),
|
|
47989
|
+
channelName: decodeChannelName(m.display_recipient),
|
|
47990
|
+
subject: decodeThreadName(name),
|
|
47991
|
+
ts: decodeTimestamp(m.timestamp)
|
|
47992
|
+
}).pipe(exports_Effect.map(({ id: id3, channelId, channelName, subject, ts }) => ({
|
|
47993
|
+
id: id3,
|
|
47994
|
+
channelId,
|
|
47995
|
+
channelName,
|
|
47996
|
+
senderId: ZulipUserRef(m.sender_id),
|
|
47997
|
+
senderFullName: m.sender_full_name,
|
|
47998
|
+
subject,
|
|
47999
|
+
resolved,
|
|
48000
|
+
content: m.content,
|
|
48001
|
+
ts,
|
|
48002
|
+
reactions: (m.reactions ?? []).map(toHistoricalReaction)
|
|
48003
|
+
})));
|
|
48004
|
+
};
|
|
47958
48005
|
var messagesResponseSchema = exports_Schema.Struct({
|
|
47959
48006
|
result: exports_Schema.Literal("success"),
|
|
47960
48007
|
messages: exports_Schema.Array(historicalMessageRawSchema)
|
|
@@ -48002,17 +48049,17 @@ var toIdentity = (u) => exports_Effect.all({
|
|
|
48002
48049
|
kind: u.is_bot ? "agent" : "human"
|
|
48003
48050
|
})));
|
|
48004
48051
|
var isActiveOfKind = (kind) => (u) => u.is_active && (kind === "agent" ? u.is_bot : !u.is_bot);
|
|
48005
|
-
var streamIsListening = (state,
|
|
48052
|
+
var streamIsListening = (state, channelName) => exports_HashSet.has(state.subscribedChannels, channelName) || exports_HashSet.has(state.newTopicsChannels, channelName);
|
|
48006
48053
|
var currentMode = (state) => state.mentionsSubscribed && exports_HashSet.size(state.subscribedChannels) === 0 && exports_HashSet.size(state.newTopicsChannels) === 0 ? "mentions" : "all";
|
|
48007
|
-
var observeNewTopic = (state,
|
|
48008
|
-
const seen = exports_HashMap.get(state.seenTopicsByChannel,
|
|
48054
|
+
var observeNewTopic = (state, channelName, threadName3) => {
|
|
48055
|
+
const seen = exports_HashMap.get(state.seenTopicsByChannel, channelName).pipe(exports_Option.getOrElse(() => exports_HashSet.empty()));
|
|
48009
48056
|
if (exports_HashSet.has(seen, threadName3))
|
|
48010
48057
|
return [false, state];
|
|
48011
48058
|
return [
|
|
48012
48059
|
true,
|
|
48013
48060
|
{
|
|
48014
48061
|
...state,
|
|
48015
|
-
seenTopicsByChannel: exports_HashMap.set(state.seenTopicsByChannel,
|
|
48062
|
+
seenTopicsByChannel: exports_HashMap.set(state.seenTopicsByChannel, channelName, exports_HashSet.add(seen, threadName3))
|
|
48016
48063
|
}
|
|
48017
48064
|
];
|
|
48018
48065
|
};
|
|
@@ -48076,7 +48123,8 @@ var zulipAdapter = (config2) => exports_Effect.gen(function* () {
|
|
|
48076
48123
|
}
|
|
48077
48124
|
return out;
|
|
48078
48125
|
});
|
|
48079
|
-
const mapHistoricalMessage = (m,
|
|
48126
|
+
const mapHistoricalMessage = (m, directory2) => exports_Effect.gen(function* () {
|
|
48127
|
+
const channel = decorateChannel({ id: m.channelId, name: m.channelName });
|
|
48080
48128
|
const cached4 = directory2.byId.get(m.senderId);
|
|
48081
48129
|
const sender = cached4 ?? (yield* exports_Effect.all({
|
|
48082
48130
|
id: decodeIdentityId(String(m.senderId)),
|
|
@@ -48085,7 +48133,7 @@ var zulipAdapter = (config2) => exports_Effect.gen(function* () {
|
|
|
48085
48133
|
const body = yield* decodeMessageBody(m.content);
|
|
48086
48134
|
const reactions = yield* mapHistoricalReactions(m.reactions, directory2);
|
|
48087
48135
|
return {
|
|
48088
|
-
ref: decorateMessageRef(m.id, channel, m.subject),
|
|
48136
|
+
ref: decorateMessageRef(m.id, channel, { name: m.subject, resolved: m.resolved }),
|
|
48089
48137
|
sender,
|
|
48090
48138
|
body,
|
|
48091
48139
|
ts: m.ts,
|
|
@@ -48093,7 +48141,7 @@ var zulipAdapter = (config2) => exports_Effect.gen(function* () {
|
|
|
48093
48141
|
reactions
|
|
48094
48142
|
};
|
|
48095
48143
|
});
|
|
48096
|
-
const readMessages = (
|
|
48144
|
+
const readMessages = (range5, narrow) => exports_Effect.all([
|
|
48097
48145
|
buildDirectoryLookup(),
|
|
48098
48146
|
minterHttp.get("/messages", messagesResponseSchema, {
|
|
48099
48147
|
anchor: "newest",
|
|
@@ -48102,11 +48150,11 @@ var zulipAdapter = (config2) => exports_Effect.gen(function* () {
|
|
|
48102
48150
|
narrow: JSON.stringify(narrow),
|
|
48103
48151
|
apply_markdown: false
|
|
48104
48152
|
})
|
|
48105
|
-
], { concurrency: 2 }).pipe(exports_Effect.flatMap(([directory2, res]) => exports_Effect.forEach(res.messages, toHistoricalMessage).pipe(exports_Effect.map((historical) => historical.filter(inRange(range5))), exports_Effect.flatMap((inRangeMessages) => exports_Effect.forEach(inRangeMessages, (m) => mapHistoricalMessage(m,
|
|
48153
|
+
], { concurrency: 2 }).pipe(exports_Effect.flatMap(([directory2, res]) => exports_Effect.forEach(res.messages, toHistoricalMessage).pipe(exports_Effect.map((historical) => historical.filter(inRange(range5))), exports_Effect.flatMap((inRangeMessages) => exports_Effect.forEach(inRangeMessages, (m) => mapHistoricalMessage(m, directory2))))));
|
|
48106
48154
|
const realmHost = new URL(config2.realmUrl).hostname;
|
|
48107
48155
|
const base = permalinkBase(config2);
|
|
48108
48156
|
const decorateChannel = (channel) => withChannelPermalink(base, channel);
|
|
48109
|
-
const decorateMessageRef = (id3, channel,
|
|
48157
|
+
const decorateMessageRef = (id3, channel, thread) => buildMessageRef(base, id3, channel, thread);
|
|
48110
48158
|
const buildBotEmail = (shortName) => BotEmail(`${shortName}-bot@${realmHost}`);
|
|
48111
48159
|
const findAnyBotByName = (name) => minterHttp.get("/users", usersSchema).pipe(exports_Effect.map((res) => exports_Option.fromNullable(res.members.find((u) => u.full_name === name && u.is_bot))));
|
|
48112
48160
|
const mintBot = (name) => {
|
|
@@ -48262,11 +48310,42 @@ var zulipAdapter = (config2) => exports_Effect.gen(function* () {
|
|
|
48262
48310
|
onNone: () => refreshKnownStreams(),
|
|
48263
48311
|
onSome: exports_Effect.succeed
|
|
48264
48312
|
})), exports_Effect.flatMap((map32) => map32.has(name) ? exports_Effect.succeed(map32) : refreshKnownStreams()), exports_Effect.map((map32) => exports_Option.fromNullable(map32.get(name))));
|
|
48265
|
-
const resolvePublishChannel = (requested) => lookupChannel(requested
|
|
48266
|
-
onNone: () => exports_Effect.fail(new UnknownChannel({ channel: requested
|
|
48313
|
+
const resolvePublishChannel = (requested) => lookupChannel(requested).pipe(exports_Effect.flatMap(exports_Option.match({
|
|
48314
|
+
onNone: () => exports_Effect.fail(new UnknownChannel({ channel: requested, substrate: "zulip" })),
|
|
48267
48315
|
onSome: exports_Effect.succeed
|
|
48268
48316
|
})));
|
|
48269
48317
|
const listKnownChannels = () => refreshKnownStreams().pipe(exports_Effect.map((map32) => [...map32.values()]));
|
|
48318
|
+
const findNewestInTopic = (channel, topic) => minterHttp.get("/messages", messagesResponseSchema, {
|
|
48319
|
+
anchor: "newest",
|
|
48320
|
+
num_before: 1,
|
|
48321
|
+
num_after: 0,
|
|
48322
|
+
narrow: JSON.stringify([
|
|
48323
|
+
{ operator: "channel", operand: channel },
|
|
48324
|
+
{ operator: "topic", operand: topic }
|
|
48325
|
+
]),
|
|
48326
|
+
apply_markdown: false
|
|
48327
|
+
}).pipe(exports_Effect.flatMap((res) => exports_Array.last(res.messages).pipe(exports_Option.match({
|
|
48328
|
+
onNone: () => exports_Effect.succeed(exports_Option.none()),
|
|
48329
|
+
onSome: (m) => decodeMessageId(String(m.id)).pipe(exports_Effect.map(exports_Option.some))
|
|
48330
|
+
}))));
|
|
48331
|
+
const setThreadResolved = (channel, thread, resolved) => {
|
|
48332
|
+
const operation = resolved ? "resolveThread" : "unresolveThread";
|
|
48333
|
+
const sourceTopic = applyResolvedPrefix(thread, !resolved);
|
|
48334
|
+
const targetTopic = applyResolvedPrefix(thread, resolved);
|
|
48335
|
+
return boundHttp().pipe(exports_Effect.flatMap((http) => findNewestInTopic(channel, sourceTopic).pipe(exports_Effect.flatMap(exports_Option.match({
|
|
48336
|
+
onSome: (id3) => http.patch(`/messages/${encodeURIComponent(id3)}`, successSchema2, {
|
|
48337
|
+
topic: targetTopic,
|
|
48338
|
+
propagate_mode: "change_all"
|
|
48339
|
+
}).pipe(exports_Effect.asVoid),
|
|
48340
|
+
onNone: () => findNewestInTopic(channel, targetTopic).pipe(exports_Effect.flatMap(exports_Option.match({
|
|
48341
|
+
onSome: () => exports_Effect.void,
|
|
48342
|
+
onNone: () => exports_Effect.fail(new PublisherError({
|
|
48343
|
+
operation,
|
|
48344
|
+
cause: new Error(`no thread '${thread}' in ${channel} to ${resolved ? "resolve" : "unresolve"}`)
|
|
48345
|
+
}))
|
|
48346
|
+
})))
|
|
48347
|
+
})))), exports_Effect.mapError((cause3) => cause3 instanceof PublisherError ? cause3 : new PublisherError({ operation, cause: cause3 })));
|
|
48348
|
+
};
|
|
48270
48349
|
const publisher = {
|
|
48271
48350
|
post: (channel, body, opts) => {
|
|
48272
48351
|
const thread = opts?.thread;
|
|
@@ -48274,8 +48353,8 @@ var zulipAdapter = (config2) => exports_Effect.gen(function* () {
|
|
|
48274
48353
|
type: "channel",
|
|
48275
48354
|
to: effective.name,
|
|
48276
48355
|
content: body,
|
|
48277
|
-
topic: thread
|
|
48278
|
-
}).pipe(exports_Effect.flatMap((sent) => decodeMessageId(String(sent.id)).pipe(exports_Effect.map((id3) => decorateMessageRef(id3, effective, thread
|
|
48356
|
+
topic: thread ?? "(no topic)"
|
|
48357
|
+
}).pipe(exports_Effect.flatMap((sent) => decodeMessageId(String(sent.id)).pipe(exports_Effect.map((id3) => decorateMessageRef(id3, effective, thread === undefined ? undefined : { name: thread, resolved: false })))))))), exports_Effect.mapError((cause3) => cause3 instanceof UnknownChannel ? cause3 : new PublisherError({ operation: "post", cause: cause3 })));
|
|
48279
48358
|
},
|
|
48280
48359
|
edit: (message, body) => boundHttp().pipe(exports_Effect.flatMap((http) => http.patch(`/messages/${encodeURIComponent(message.id)}`, successSchema2, {
|
|
48281
48360
|
content: body
|
|
@@ -48285,7 +48364,9 @@ var zulipAdapter = (config2) => exports_Effect.gen(function* () {
|
|
|
48285
48364
|
})), exports_Effect.asVoid, exports_Effect.mapError((cause3) => new PublisherError({ operation: "react", cause: cause3 }))),
|
|
48286
48365
|
unreact: (message, emoji) => boundHttp().pipe(exports_Effect.flatMap((http) => http.delete(`/messages/${encodeURIComponent(message.id)}/reactions`, successSchema2, {
|
|
48287
48366
|
emoji_name: emoji
|
|
48288
|
-
})), exports_Effect.asVoid, exports_Effect.mapError((cause3) => new PublisherError({ operation: "unreact", cause: cause3 })))
|
|
48367
|
+
})), exports_Effect.asVoid, exports_Effect.mapError((cause3) => new PublisherError({ operation: "unreact", cause: cause3 }))),
|
|
48368
|
+
resolveThread: (channel, thread) => setThreadResolved(channel, thread, true),
|
|
48369
|
+
unresolveThread: (channel, thread) => setThreadResolved(channel, thread, false)
|
|
48289
48370
|
};
|
|
48290
48371
|
const inboxRef = yield* exports_SynchronizedRef.make({
|
|
48291
48372
|
mentionsSubscribed: false,
|
|
@@ -48300,15 +48381,18 @@ var zulipAdapter = (config2) => exports_Effect.gen(function* () {
|
|
|
48300
48381
|
if (event.kind !== "message-posted")
|
|
48301
48382
|
return exports_Effect.succeed(true);
|
|
48302
48383
|
const message = event.message;
|
|
48303
|
-
const
|
|
48384
|
+
const cname = message.ref.channel.name;
|
|
48304
48385
|
const thread = message.ref.thread;
|
|
48305
48386
|
return exports_SynchronizedRef.get(boundRef).pipe(exports_Effect.flatMap((current2) => {
|
|
48306
48387
|
const me = exports_Option.getOrUndefined(current2)?.identity;
|
|
48307
48388
|
return exports_SynchronizedRef.modify(inboxRef, (state) => {
|
|
48308
|
-
if (!exports_HashSet.has(state.newTopicsChannels,
|
|
48389
|
+
if (!exports_HashSet.has(state.newTopicsChannels, cname))
|
|
48309
48390
|
return [true, state];
|
|
48310
|
-
const [isFirstOfTopic, ticked] = thread
|
|
48311
|
-
|
|
48391
|
+
const [isFirstOfTopic, ticked] = exports_Option.match(thread, {
|
|
48392
|
+
onNone: () => [false, state],
|
|
48393
|
+
onSome: (t) => observeNewTopic(state, cname, t.name)
|
|
48394
|
+
});
|
|
48395
|
+
if (exports_HashSet.has(state.subscribedChannels, cname))
|
|
48312
48396
|
return [true, ticked];
|
|
48313
48397
|
if (state.mentionsSubscribed && me !== undefined && message.mentions.some((m) => m.id === me.id)) {
|
|
48314
48398
|
return [true, ticked];
|
|
@@ -48339,18 +48423,18 @@ var zulipAdapter = (config2) => exports_Effect.gen(function* () {
|
|
|
48339
48423
|
if (channel === undefined)
|
|
48340
48424
|
return ensureQueueRegistered();
|
|
48341
48425
|
return exports_SynchronizedRef.modify(inboxRef, (state) => {
|
|
48342
|
-
const wasListening = streamIsListening(state, channel
|
|
48426
|
+
const wasListening = streamIsListening(state, channel);
|
|
48343
48427
|
const next4 = exports_Predicate.hasProperty(target, "kind") ? {
|
|
48344
48428
|
...state,
|
|
48345
|
-
newTopicsChannels: exports_HashSet.add(state.newTopicsChannels, channel
|
|
48429
|
+
newTopicsChannels: exports_HashSet.add(state.newTopicsChannels, channel)
|
|
48346
48430
|
} : {
|
|
48347
48431
|
...state,
|
|
48348
|
-
subscribedChannels: exports_HashSet.add(state.subscribedChannels, channel
|
|
48432
|
+
subscribedChannels: exports_HashSet.add(state.subscribedChannels, channel)
|
|
48349
48433
|
};
|
|
48350
48434
|
return [wasListening, next4];
|
|
48351
48435
|
}).pipe(exports_Effect.flatMap((wasListening) => {
|
|
48352
48436
|
const subscribeRemote = wasListening ? exports_Effect.void : minterHttp.post("/users/me/subscriptions", subscriptionsResponseSchema, {
|
|
48353
|
-
subscriptions: JSON.stringify([{ name: channel
|
|
48437
|
+
subscriptions: JSON.stringify([{ name: channel }])
|
|
48354
48438
|
}).pipe(exports_Effect.asVoid);
|
|
48355
48439
|
return subscribeRemote.pipe(exports_Effect.andThen(ensureQueueRegistered()));
|
|
48356
48440
|
}));
|
|
@@ -48368,15 +48452,15 @@ var zulipAdapter = (config2) => exports_Effect.gen(function* () {
|
|
|
48368
48452
|
return exports_SynchronizedRef.modify(inboxRef, (state) => {
|
|
48369
48453
|
const next4 = exports_Predicate.hasProperty(target, "kind") ? {
|
|
48370
48454
|
...state,
|
|
48371
|
-
newTopicsChannels: exports_HashSet.remove(state.newTopicsChannels, channel
|
|
48372
|
-
seenTopicsByChannel: exports_HashMap.remove(state.seenTopicsByChannel, channel
|
|
48455
|
+
newTopicsChannels: exports_HashSet.remove(state.newTopicsChannels, channel),
|
|
48456
|
+
seenTopicsByChannel: exports_HashMap.remove(state.seenTopicsByChannel, channel)
|
|
48373
48457
|
} : {
|
|
48374
48458
|
...state,
|
|
48375
|
-
subscribedChannels: exports_HashSet.remove(state.subscribedChannels, channel
|
|
48459
|
+
subscribedChannels: exports_HashSet.remove(state.subscribedChannels, channel)
|
|
48376
48460
|
};
|
|
48377
|
-
return [streamIsListening(next4, channel
|
|
48461
|
+
return [streamIsListening(next4, channel), next4];
|
|
48378
48462
|
}).pipe(exports_Effect.flatMap((stillListening) => stillListening ? exports_Effect.void : minterHttp.delete("/users/me/subscriptions", subscriptionsResponseSchema, {
|
|
48379
|
-
subscriptions: JSON.stringify([channel
|
|
48463
|
+
subscriptions: JSON.stringify([channel])
|
|
48380
48464
|
}).pipe(exports_Effect.asVoid)));
|
|
48381
48465
|
}).pipe(exports_Effect.mapError((cause3) => new InboxError({ operation: "unsubscribe", cause: cause3 }))),
|
|
48382
48466
|
events: () => exports_Stream.unwrap(exports_Effect.all([exports_SynchronizedRef.get(boundRef), exports_SynchronizedRef.get(inboxRef)]).pipe(exports_Effect.map(([current2, state]) => inboxEvents({
|
|
@@ -48426,11 +48510,14 @@ var zulipAdapter = (config2) => exports_Effect.gen(function* () {
|
|
|
48426
48510
|
}
|
|
48427
48511
|
};
|
|
48428
48512
|
const history = {
|
|
48429
|
-
readChannel: (channel, range5) => readMessages(
|
|
48430
|
-
readThread: (channel, threadName3, range5) =>
|
|
48431
|
-
|
|
48432
|
-
|
|
48433
|
-
|
|
48513
|
+
readChannel: (channel, range5) => readMessages(range5, [{ operator: "channel", operand: channel }]).pipe(exports_Effect.mapError((cause3) => new HistoryError({ operation: "readChannel", cause: cause3 }))),
|
|
48514
|
+
readThread: (channel, threadName3, range5) => {
|
|
48515
|
+
const readTopic = (topic) => readMessages(range5 ?? {}, [
|
|
48516
|
+
{ operator: "channel", operand: channel },
|
|
48517
|
+
{ operator: "topic", operand: topic }
|
|
48518
|
+
]);
|
|
48519
|
+
return readTopic(threadName3).pipe(exports_Effect.flatMap((messages) => messages.length > 0 ? exports_Effect.succeed(messages) : readTopic(applyResolvedPrefix(threadName3, true))), exports_Effect.mapError((cause3) => new HistoryError({ operation: "readThread", cause: cause3 })));
|
|
48520
|
+
},
|
|
48434
48521
|
recentThreads: (sender, opts) => {
|
|
48435
48522
|
const limit = opts?.limit ?? RECENT_THREADS_DEFAULT_LIMIT;
|
|
48436
48523
|
return buildDirectoryLookup().pipe(exports_Effect.flatMap((lookup) => {
|
|
@@ -48449,7 +48536,7 @@ var zulipAdapter = (config2) => exports_Effect.gen(function* () {
|
|
|
48449
48536
|
let seen = exports_HashMap.empty();
|
|
48450
48537
|
for (const m of res.messages) {
|
|
48451
48538
|
const channel = yield* decodeChannelName(m.display_recipient);
|
|
48452
|
-
const thread = yield* decodeThreadName(m.subject);
|
|
48539
|
+
const thread = yield* decodeThreadName(splitTopic(m.subject).name);
|
|
48453
48540
|
const key = threadKey(channel, thread);
|
|
48454
48541
|
if (!exports_HashMap.has(seen, key)) {
|
|
48455
48542
|
seen = exports_HashMap.set(seen, key, {
|
|
@@ -48467,7 +48554,7 @@ var zulipAdapter = (config2) => exports_Effect.gen(function* () {
|
|
|
48467
48554
|
})));
|
|
48468
48555
|
}), exports_Effect.mapError((cause3) => new HistoryError({ operation: "recentThreads", cause: cause3 })));
|
|
48469
48556
|
},
|
|
48470
|
-
messagePermalink: (id3, hint) => (hint === undefined ? fetchMessageRef(minterHttp, Number(id3), base).pipe(exports_Effect.map(exports_Option.
|
|
48557
|
+
messagePermalink: (id3, hint) => (hint === undefined ? fetchMessageRef(minterHttp, Number(id3), base).pipe(exports_Effect.map(exports_Option.map((ref) => ref.permalink))) : lookupChannel(hint.channel).pipe(exports_Effect.map(exports_Option.map((channel) => buildMessageRef(base, id3, channel, hint.thread === undefined ? undefined : { name: hint.thread, resolved: false }).permalink)))).pipe(exports_Effect.mapError((cause3) => new HistoryError({ operation: "messagePermalink", cause: cause3 })))
|
|
48471
48558
|
};
|
|
48472
48559
|
const reconcileMinter = () => reconcileMinterSubscriptions({
|
|
48473
48560
|
listUnsubscribedPublicStreams: () => minterHttp.get("/streams", streamsListResponseSchema, {
|
|
@@ -56706,16 +56793,16 @@ var parseSubscribeTarget = (token) => exports_Effect.gen(function* () {
|
|
|
56706
56793
|
});
|
|
56707
56794
|
});
|
|
56708
56795
|
var intentToTarget = (intent) => exports_Match.value(intent).pipe(exports_Match.discriminatorsExhaustive("kind")({
|
|
56709
|
-
mentions: () =>
|
|
56710
|
-
channel: ({ channelName }) =>
|
|
56711
|
-
"new-topics-in-channel": ({ channelName }) =>
|
|
56796
|
+
mentions: () => "mentions",
|
|
56797
|
+
channel: ({ channelName }) => channelName,
|
|
56798
|
+
"new-topics-in-channel": ({ channelName }) => ({
|
|
56712
56799
|
kind: "new-topics-in-channel",
|
|
56713
|
-
channel:
|
|
56714
|
-
})
|
|
56715
|
-
thread: ({ channelName, threadName: threadName3 }) =>
|
|
56716
|
-
channel:
|
|
56717
|
-
thread:
|
|
56718
|
-
})
|
|
56800
|
+
channel: channelName
|
|
56801
|
+
}),
|
|
56802
|
+
thread: ({ channelName, threadName: threadName3 }) => ({
|
|
56803
|
+
channel: channelName,
|
|
56804
|
+
thread: threadName3
|
|
56805
|
+
})
|
|
56719
56806
|
}));
|
|
56720
56807
|
|
|
56721
56808
|
// packages/mcp/bootstrap.ts
|
|
@@ -56739,7 +56826,7 @@ var parseBotName = (raw3) => {
|
|
|
56739
56826
|
};
|
|
56740
56827
|
var placeholderShape = /^\$\{[^}]+\}$/;
|
|
56741
56828
|
var userConfigPlaceholderShape = /^\$\{user_config\.[^}]+\}$/;
|
|
56742
|
-
var placeholderMessage = (key, raw3) => `${key} value is an unsubstituted placeholder${raw3 === undefined ? "" : ` (${raw3})`} — ` + `the host did not expand it. ` + `Claude Code only substitutes \${user_config.X} (and \${CLAUDE_PLUGIN_ROOT} in args) ` + `in .mcp.json; host-env vars like \${CLAUDE_CODE_SESSION_ID} must be inherited from ` + `the parent environment instead
|
|
56829
|
+
var placeholderMessage = (key, raw3) => `${key} value is an unsubstituted placeholder${raw3 === undefined ? "" : ` (${raw3})`} — ` + `the host did not expand it. ` + `Claude Code only substitutes \${user_config.X} (and \${CLAUDE_PLUGIN_ROOT} in args) ` + `in .mcp.json; host-env vars like \${CLAUDE_CODE_SESSION_ID} must be inherited from ` + `the parent environment instead.`;
|
|
56743
56830
|
var rejectPlaceholder = (key) => exports_Config.validate({
|
|
56744
56831
|
message: placeholderMessage(key),
|
|
56745
56832
|
validation: (value5) => !placeholderShape.test(value5)
|
|
@@ -56786,15 +56873,6 @@ var optionalNonNegativeInt = (key) => optionalUserConfig(key).pipe(exports_Confi
|
|
|
56786
56873
|
return Number.isInteger(parsed) && parsed >= 0 ? exports_Either.right(exports_Option.some(parsed)) : exports_Either.left(exports_ConfigError.InvalidData([key], `${key} must be a non-negative integer — received: ${raw3}`));
|
|
56787
56874
|
}
|
|
56788
56875
|
})));
|
|
56789
|
-
var optionalSessionId = (key) => exports_Config.option(exports_Config.string(key).pipe(exports_Config.mapOrFail((value5) => {
|
|
56790
|
-
if (value5.length === 0) {
|
|
56791
|
-
return exports_Either.left(exports_ConfigError.MissingData([key], `${key} is unset`));
|
|
56792
|
-
}
|
|
56793
|
-
if (placeholderShape.test(value5)) {
|
|
56794
|
-
return exports_Either.left(exports_ConfigError.InvalidData([key], placeholderMessage(key, value5)));
|
|
56795
|
-
}
|
|
56796
|
-
return exports_Either.fromOption(parseSessionId(value5), () => exports_ConfigError.InvalidData([key], `${key} must be a UUID — received: ${value5}`));
|
|
56797
|
-
})));
|
|
56798
56876
|
var optionalBotName = (key) => optionalNonEmpty(key).pipe(exports_Config.mapOrFail((option7) => exports_Option.match(option7, {
|
|
56799
56877
|
onNone: () => exports_Either.right(exports_Option.none()),
|
|
56800
56878
|
onSome: (raw3) => exports_Either.fromOption(parseBotName(raw3), () => exports_ConfigError.InvalidData([key], `${key} must be substrate-safe (lowercase ASCII, digits, dashes, underscores; starts with letter; max 40 chars) — received: ${raw3}`)).pipe(exports_Either.map(exports_Option.some))
|
|
@@ -56817,8 +56895,7 @@ var envConfig = exports_Config.all({
|
|
|
56817
56895
|
botApiKey: optionalApiKey("COMMY_BOT_API_KEY"),
|
|
56818
56896
|
subscribe: optionalUserConfig("COMMY_SUBSCRIBE"),
|
|
56819
56897
|
project: optionalNonEmpty("COMMY_PROJECT"),
|
|
56820
|
-
catchupWindowSeconds: optionalNonNegativeInt("COMMY_CATCHUP_WINDOW_SECONDS")
|
|
56821
|
-
sessionId: optionalSessionId("CLAUDE_CODE_SESSION_ID")
|
|
56898
|
+
catchupWindowSeconds: optionalNonNegativeInt("COMMY_CATCHUP_WINDOW_SECONDS")
|
|
56822
56899
|
}).pipe(exports_Config.mapOrFail((raw3) => {
|
|
56823
56900
|
if (exports_Option.isSome(raw3.botApiKey) && exports_Option.isNone(raw3.botName)) {
|
|
56824
56901
|
return exports_Either.left(exports_ConfigError.InvalidData(["COMMY_BOT_API_KEY"], "COMMY_BOT_API_KEY requires COMMY_BOT_NAME — the key identifies which provisioned persona to attach to"));
|
|
@@ -56834,10 +56911,6 @@ var envConfig = exports_Config.all({
|
|
|
56834
56911
|
onNone: () => ({}),
|
|
56835
56912
|
onSome: (subscribe4) => ({ subscribe: subscribe4 })
|
|
56836
56913
|
}),
|
|
56837
|
-
...exports_Option.match(raw3.sessionId, {
|
|
56838
|
-
onNone: () => ({}),
|
|
56839
|
-
onSome: (sessionId) => ({ sessionId })
|
|
56840
|
-
}),
|
|
56841
56914
|
...exports_Option.match(project3, { onNone: () => ({}), onSome: (slug) => ({ project: slug }) }),
|
|
56842
56915
|
...exports_Option.match(raw3.catchupWindowSeconds, {
|
|
56843
56916
|
onNone: () => ({}),
|
|
@@ -56911,7 +56984,7 @@ var ZulipAdapterLive = substrateAdapterLayer(exports_Effect.gen(function* () {
|
|
|
56911
56984
|
var subscribeFromEnv = (inbox, narrowSet, parsed) => {
|
|
56912
56985
|
if (parsed.subscribe === undefined)
|
|
56913
56986
|
return exports_Effect.succeed([]);
|
|
56914
|
-
return exports_Effect.forEach(parsed.subscribe.split(","), (raw3) => parseSubscribeTarget(raw3.trim()).pipe(exports_Effect.tap((intent) => exports_Effect.sync(() => narrowSet.add(intent))), exports_Effect.flatMap((intent) => intentToTarget(intent).pipe(exports_Effect.
|
|
56987
|
+
return exports_Effect.forEach(parsed.subscribe.split(","), (raw3) => parseSubscribeTarget(raw3.trim()).pipe(exports_Effect.tap((intent) => exports_Effect.sync(() => narrowSet.add(intent))), exports_Effect.flatMap((intent) => inbox.subscribe(intentToTarget(intent)).pipe(exports_Effect.as(intent)))));
|
|
56915
56988
|
};
|
|
56916
56989
|
|
|
56917
56990
|
// packages/mcp/events.ts
|
|
@@ -56928,11 +57001,11 @@ var formatMessage = (event, botIdentityId) => {
|
|
|
56928
57001
|
const meta2 = buildMeta([
|
|
56929
57002
|
["channel_id", ref.channel.id],
|
|
56930
57003
|
["channel_name", ref.channel.name],
|
|
56931
|
-
["thread", ref.thread
|
|
57004
|
+
["thread", exports_Option.getOrUndefined(exports_Option.map(ref.thread, (t) => t.name))],
|
|
56932
57005
|
["message_id", ref.id],
|
|
56933
57006
|
["permalink", ref.permalink],
|
|
56934
57007
|
["channel_permalink", ref.channel.permalink],
|
|
56935
|
-
["thread_permalink", ref.thread
|
|
57008
|
+
["thread_permalink", exports_Option.getOrUndefined(exports_Option.map(ref.thread, (t) => t.permalink))],
|
|
56936
57009
|
["sender_id", sender.id],
|
|
56937
57010
|
["sender_name", sender.name],
|
|
56938
57011
|
["sender_kind", sender.kind],
|
|
@@ -56950,7 +57023,7 @@ var formatReaction = (event, observedAt) => {
|
|
|
56950
57023
|
const meta2 = buildMeta([
|
|
56951
57024
|
["target_message_id", event.target.id],
|
|
56952
57025
|
["target_channel_name", event.target.channel.name],
|
|
56953
|
-
["target_thread", event.target.thread
|
|
57026
|
+
["target_thread", exports_Option.getOrUndefined(exports_Option.map(event.target.thread, (t) => t.name))],
|
|
56954
57027
|
["target_permalink", event.target.permalink],
|
|
56955
57028
|
["reaction_emoji", event.emoji],
|
|
56956
57029
|
["reaction_action", action],
|
|
@@ -56994,7 +57067,6 @@ var catchUpMentions = (deps) => exports_Effect.gen(function* () {
|
|
|
56994
57067
|
});
|
|
56995
57068
|
|
|
56996
57069
|
// packages/mcp/channels-catch-up.ts
|
|
56997
|
-
var channelRefFromName = (name) => decodeChannelId(name).pipe(exports_Effect.map((id3) => ({ id: id3, name })), exports_Effect.orDie);
|
|
56998
57070
|
var clampedSince = (now2, windowSeconds) => decodeTimestamp(Math.max(0, now2 - windowSeconds)).pipe(exports_Effect.orDie);
|
|
56999
57071
|
var firstMessagePerTopic = (messages) => {
|
|
57000
57072
|
const seen = new Set;
|
|
@@ -57002,20 +57074,20 @@ var firstMessagePerTopic = (messages) => {
|
|
|
57002
57074
|
const ordered = exports_Array.sort(messages, exports_Order.mapInput(exports_Order.number, (m) => m.ts));
|
|
57003
57075
|
for (const m of ordered) {
|
|
57004
57076
|
const thread = m.ref.thread;
|
|
57005
|
-
if (thread
|
|
57077
|
+
if (exports_Option.isNone(thread))
|
|
57006
57078
|
continue;
|
|
57007
|
-
if (seen.has(thread.name))
|
|
57079
|
+
if (seen.has(thread.value.name))
|
|
57008
57080
|
continue;
|
|
57009
|
-
seen.add(thread.name);
|
|
57081
|
+
seen.add(thread.value.name);
|
|
57010
57082
|
out.push(m);
|
|
57011
57083
|
}
|
|
57012
57084
|
return out;
|
|
57013
57085
|
};
|
|
57014
57086
|
var fetchForIntent = (intent, history, defaultSince, newTopicsSince) => exports_Match.value(intent).pipe(exports_Match.discriminatorsExhaustive("kind")({
|
|
57015
57087
|
mentions: () => exports_Effect.succeed([]),
|
|
57016
|
-
channel: (i) =>
|
|
57017
|
-
"new-topics-in-channel": (i) =>
|
|
57018
|
-
thread: (i) =>
|
|
57088
|
+
channel: (i) => history.readChannel(i.channelName, { since: defaultSince }),
|
|
57089
|
+
"new-topics-in-channel": (i) => history.readChannel(i.channelName, { since: newTopicsSince }).pipe(exports_Effect.map(firstMessagePerTopic)),
|
|
57090
|
+
thread: (i) => history.readThread(i.channelName, i.threadName, { since: defaultSince })
|
|
57019
57091
|
}));
|
|
57020
57092
|
var catchUpChannels = (deps) => exports_Effect.gen(function* () {
|
|
57021
57093
|
if (deps.intents.length === 0)
|
|
@@ -58658,12 +58730,12 @@ class Server extends Protocol {
|
|
|
58658
58730
|
}
|
|
58659
58731
|
|
|
58660
58732
|
// packages/mcp/mcp-server.ts
|
|
58661
|
-
var PLUGIN_VERSION = "0.
|
|
58733
|
+
var PLUGIN_VERSION = "0.16.0";
|
|
58662
58734
|
var COMMY_INSTRUCTIONS = `**Substrate.** commy is the inter-agent channel: agents and humans coordinate here. If you run it alongside other agent-messaging tools, keep one substrate canonical and don't fan the same message across all of them.
|
|
58663
58735
|
|
|
58664
58736
|
**Channels.** Each project has one channel: \`#<project-slug>\` where the slug is resolved per session as \`COMMY_PROJECT\` env > git remote \`origin\` basename > git root basename. Sessions launched outside a git repo (e.g. \`/tmp\`, \`$HOME\`) have no project channel and should post to \`#general\` instead. Don't invent a channel name from a metaphor — never post to a literal \`#home\`, \`#project\`, or \`#<project>\`. Use \`list_channels\` to enumerate what actually exists in the realm; posting to a non-existent channel throws \`UnknownChannel\` rather than silently routing to Notification Bot.
|
|
58665
58737
|
|
|
58666
|
-
**Topics.** A topic is a logical thread of conversation within a channel; the \`post\` tool's \`thread\` argument names it (Zulip calls these "topics"). Open a new topic when the work shifts — a fresh task, a new question, a different incident — and reply into an existing one when you're continuing the same line of work. Name topics by the work, not the speaker: \`payments-migration\`, \`auth-token-refresh\`, \`events-queue-expiry\` — not \`bot-debugging\` or \`
|
|
58738
|
+
**Topics.** A topic is a logical thread of conversation within a channel; the \`post\` tool's \`thread\` argument names it (Zulip calls these "topics"). Open a new topic when the work shifts — a fresh task, a new question, a different incident — and reply into an existing one when you're continuing the same line of work. Name topics by the work, not the speaker: \`payments-migration\`, \`auth-token-refresh\`, \`events-queue-expiry\` — not \`bot-debugging\` or \`alice-asked\`. Top-level channel chatter (omit \`thread\`) is for terse status pings only; anything substantive deserves a topic.
|
|
58667
58739
|
|
|
58668
58740
|
**Subscriptions.** Be on your project channel and \`#general\` only — not on other projects' channels. Boot-time defaults come from the plugin's \`COMMY_SUBSCRIBE\` userConfig (tokens: \`channel:<name>\`, \`thread:<channel>/<thread>\`, \`new-topics:<channel>\`, \`mentions\`); adjust the live set via \`subscribe\`/\`unsubscribe\` at runtime. Inbound matches arrive as \`<channel source="commy" ...>\` blocks. If one arrives from a channel you aren't subscribed to, treat it as background context and don't reply — only post into your project channel, into \`#general\`, or into threads you've explicitly joined. **Refer to peers by name** — the \`sender_name\` (and reaction \`by_name\`) in those blocks — never by a bare number; reserve numbers for message ids, which otherwise collide with identity in a thread.
|
|
58669
58741
|
|
|
@@ -58709,7 +58781,7 @@ var keyToIntent = (key) => exports_Match.value(key).pipe(exports_Match.discrimin
|
|
|
58709
58781
|
}));
|
|
58710
58782
|
var channelKey = (ref) => channelKeyOf(ref.channel.name);
|
|
58711
58783
|
var newTopicsKey = (ref) => newTopicsKeyOf(ref.channel.name);
|
|
58712
|
-
var threadKey = (ref) => exports_Option.
|
|
58784
|
+
var threadKey = (ref) => exports_Option.map(ref.thread, (thread) => threadKeyOf(ref.channel.name, thread.name));
|
|
58713
58785
|
var refMatches = (ref, intents) => exports_HashSet.has(intents, channelKey(ref)) || exports_Option.exists(threadKey(ref), (tk) => exports_HashSet.has(intents, tk));
|
|
58714
58786
|
var mentionsMatches = (intents, mentions, botIdentityId) => {
|
|
58715
58787
|
if (botIdentityId === undefined)
|
|
@@ -58759,11 +58831,18 @@ var DEFAULT_TIMEOUT_MS = 5000;
|
|
|
58759
58831
|
var raceReleaseAgainstTimeout = (release, timeoutMs = DEFAULT_TIMEOUT_MS) => release.pipe(exports_Effect.tapDefect((cause3) => exports_Effect.logError(`release failed: ${exports_Cause.pretty(cause3)}`)), exports_Effect.catchAllDefect(() => exports_Effect.void), exports_Effect.timeoutOption(exports_Duration.millis(timeoutMs)), exports_Effect.flatMap((result) => exports_Option.isNone(result) ? exports_Effect.logError(`release timed out after ${timeoutMs}ms`) : exports_Effect.void));
|
|
58760
58832
|
|
|
58761
58833
|
// packages/mcp/subscription-restore.ts
|
|
58762
|
-
var applyRestored = (deps, intents) => exports_Effect.sync(() => deps.narrowSet.replace(intents)).pipe(exports_Effect.zipRight(exports_Effect.forEach(intents, (intent) =>
|
|
58763
|
-
|
|
58834
|
+
var applyRestored = (deps, intents) => exports_Effect.sync(() => deps.narrowSet.replace(intents)).pipe(exports_Effect.zipRight(exports_Effect.forEach(intents, (intent) => deps.inbox.subscribe(intentToTarget(intent)), {
|
|
58835
|
+
discard: true
|
|
58836
|
+
})));
|
|
58837
|
+
var seedDefaultsIfFresh = (deps, sessionId, project3) => deps.subscriptionStore.read(sessionId).pipe(exports_Effect.flatMap(exports_Option.match({
|
|
58764
58838
|
onNone: () => deps.registerDefaults(project3),
|
|
58839
|
+
onSome: () => exports_Effect.void
|
|
58840
|
+
})));
|
|
58841
|
+
var restoreSubscriptions = (deps, sessionId) => deps.subscriptionStore.read(sessionId).pipe(exports_Effect.flatMap(exports_Option.match({
|
|
58842
|
+
onNone: () => exports_Effect.void,
|
|
58765
58843
|
onSome: (intents) => applyRestored(deps, intents)
|
|
58766
58844
|
})));
|
|
58845
|
+
var makeSessionRestore = (deps) => exports_Effect.map(exports_Deferred.make(), (known) => (sessionId) => exports_Deferred.succeed(known, sessionId).pipe(exports_Effect.flatMap((won) => won ? restoreSubscriptions(deps, sessionId) : exports_Effect.void)));
|
|
58767
58846
|
var persistSubscriptions = (store, narrowSet, sessionId) => store.write(sessionId, narrowSet.intents());
|
|
58768
58847
|
|
|
58769
58848
|
// packages/mcp/subscription-store.ts
|
|
@@ -58815,11 +58894,6 @@ var identityShape = (identity6) => ({
|
|
|
58815
58894
|
name: identity6.name,
|
|
58816
58895
|
kind: identity6.kind
|
|
58817
58896
|
});
|
|
58818
|
-
var channelShape = (channel) => ({
|
|
58819
|
-
id: channel.id,
|
|
58820
|
-
name: channel.name,
|
|
58821
|
-
permalink: channel.permalink ?? null
|
|
58822
|
-
});
|
|
58823
58897
|
var createCache = () => {
|
|
58824
58898
|
const identityById = new Map;
|
|
58825
58899
|
const channelByName = new Map;
|
|
@@ -58852,7 +58926,7 @@ class UnknownMessageError extends exports_Data.TaggedError("UnknownMessage") {
|
|
|
58852
58926
|
return `no MessageRef cached for id=${this.id}; pass channel_name (and thread for thread-scoped messages) to reconstruct`;
|
|
58853
58927
|
}
|
|
58854
58928
|
}
|
|
58855
|
-
var reconstructMessageRef = (cache, rawId, channelNameArg
|
|
58929
|
+
var reconstructMessageRef = (cache, rawId, channelNameArg) => exports_Effect.gen(function* () {
|
|
58856
58930
|
const id3 = yield* decodeMessageId(rawId);
|
|
58857
58931
|
const cached5 = cache.messageById.get(id3);
|
|
58858
58932
|
if (cached5 !== undefined)
|
|
@@ -58860,11 +58934,8 @@ var reconstructMessageRef = (cache, rawId, channelNameArg, threadNameArg) => exp
|
|
|
58860
58934
|
if (channelNameArg === undefined) {
|
|
58861
58935
|
return yield* new UnknownMessageError({ id: rawId });
|
|
58862
58936
|
}
|
|
58863
|
-
const channel = yield*
|
|
58864
|
-
|
|
58865
|
-
return { id: id3, channel, thread: { name: yield* decodeThreadName(threadNameArg) } };
|
|
58866
|
-
}
|
|
58867
|
-
return { id: id3, channel };
|
|
58937
|
+
const channel = yield* addressChannel(cache, yield* decodeChannelName(channelNameArg));
|
|
58938
|
+
return { id: id3, channel, thread: exports_Option.none(), permalink: yield* decodeMessagePermalink(id3) };
|
|
58868
58939
|
});
|
|
58869
58940
|
var resolveMentions = (cache, mentionIds) => exports_Effect.forEach(mentionIds, (raw3) => exports_Effect.gen(function* () {
|
|
58870
58941
|
const identity6 = cache.identityById.get(yield* decodeIdentityId(raw3));
|
|
@@ -58873,15 +58944,20 @@ var resolveMentions = (cache, mentionIds) => exports_Effect.forEach(mentionIds,
|
|
|
58873
58944
|
}
|
|
58874
58945
|
return identity6;
|
|
58875
58946
|
}));
|
|
58876
|
-
var
|
|
58947
|
+
var encodeThreadFacet = exports_Schema.encode(exports_Schema.OptionFromNullOr(ObservedThreadSchema));
|
|
58948
|
+
var encodeChannel = exports_Schema.encode(ChannelRefSchema);
|
|
58949
|
+
var encodeMessagePermalink = exports_Schema.encode(MessagePermalinkSchema);
|
|
58950
|
+
var decodeChannelPermalink = exports_Schema.decode(ChannelPermalinkSchema);
|
|
58951
|
+
var decodeMessagePermalink = exports_Schema.decode(MessagePermalinkSchema);
|
|
58952
|
+
var messageShape = (m) => exports_Effect.all({
|
|
58953
|
+
channel: encodeChannel(m.ref.channel),
|
|
58954
|
+
thread: encodeThreadFacet(m.ref.thread),
|
|
58955
|
+
permalink: encodeMessagePermalink(m.ref.permalink)
|
|
58956
|
+
}).pipe(exports_Effect.map(({ channel, thread, permalink }) => ({
|
|
58877
58957
|
id: m.ref.id,
|
|
58878
|
-
channel
|
|
58879
|
-
|
|
58880
|
-
|
|
58881
|
-
permalink: m.ref.channel.permalink ?? null
|
|
58882
|
-
},
|
|
58883
|
-
thread: m.ref.thread === undefined ? null : { name: m.ref.thread.name, permalink: m.ref.thread.permalink ?? null },
|
|
58884
|
-
permalink: m.ref.permalink ?? null,
|
|
58958
|
+
channel,
|
|
58959
|
+
thread,
|
|
58960
|
+
permalink,
|
|
58885
58961
|
sender: identityShape(m.sender),
|
|
58886
58962
|
body: m.body,
|
|
58887
58963
|
ts: m.ts,
|
|
@@ -58890,14 +58966,16 @@ var messageShape = (m) => ({
|
|
|
58890
58966
|
emoji: r.emoji,
|
|
58891
58967
|
by: r.by.map(identityShape)
|
|
58892
58968
|
}))
|
|
58893
|
-
});
|
|
58894
|
-
var
|
|
58895
|
-
const name = yield* decodeChannelName(rawName);
|
|
58969
|
+
})));
|
|
58970
|
+
var addressChannel = (cache, name) => exports_Effect.gen(function* () {
|
|
58896
58971
|
const cached5 = cache.channelByName.get(name);
|
|
58897
58972
|
if (cached5 !== undefined)
|
|
58898
58973
|
return cached5;
|
|
58899
|
-
|
|
58900
|
-
|
|
58974
|
+
return {
|
|
58975
|
+
id: yield* decodeChannelId(name),
|
|
58976
|
+
name,
|
|
58977
|
+
permalink: yield* decodeChannelPermalink(name)
|
|
58978
|
+
};
|
|
58901
58979
|
});
|
|
58902
58980
|
var parseRange = (range5) => exports_Effect.gen(function* () {
|
|
58903
58981
|
const out = {};
|
|
@@ -58946,6 +59024,10 @@ var ReadThreadArgs = exports_Schema.Struct({
|
|
|
58946
59024
|
thread: exports_Schema.String,
|
|
58947
59025
|
...RangeArgs
|
|
58948
59026
|
});
|
|
59027
|
+
var ThreadResolutionArgs = exports_Schema.Struct({
|
|
59028
|
+
channel_name: exports_Schema.String,
|
|
59029
|
+
thread: exports_Schema.String
|
|
59030
|
+
});
|
|
58949
59031
|
var MessageLinkArgs = exports_Schema.Struct({
|
|
58950
59032
|
message_id: exports_Schema.String,
|
|
58951
59033
|
channel_name: exports_Schema.optional(exports_Schema.String),
|
|
@@ -58959,11 +59041,11 @@ var buildToolDefs = (deps, cache) => {
|
|
|
58959
59041
|
const projectForCwd = deps.projectForCwd ?? (() => exports_Effect.succeed(undefined));
|
|
58960
59042
|
const sessionIdField = {
|
|
58961
59043
|
type: "string",
|
|
58962
|
-
description: "Per-conversation identifier (UUID). In Claude Code, the plugin's PreToolUse hook injects this from the harness session id; non-CC MCP clients must supply a UUID (e.g. via crypto.randomUUID()). Anything that fails UUID validation is treated as missing — the server returns the unbound-stub error rather than minting a malformed cc-* identity
|
|
59044
|
+
description: "Per-conversation identifier (UUID). In Claude Code, the plugin's PreToolUse hook injects this from the harness session id; non-CC MCP clients must supply a UUID (e.g. via crypto.randomUUID()). Anything that fails UUID validation is treated as missing — the server returns the unbound-stub error rather than minting a malformed cc-* identity. Drives ephemeral identity minting."
|
|
58963
59045
|
};
|
|
58964
59046
|
const cwdField = {
|
|
58965
59047
|
type: "string",
|
|
58966
|
-
description: "Calling session's working directory. In Claude Code, the PreToolUse hook injects this from the harness cwd; non-CC MCP clients may supply their own. Drives the project component of ephemeral cc-<project>-<8> names
|
|
59048
|
+
description: "Calling session's working directory. In Claude Code, the PreToolUse hook injects this from the harness cwd; non-CC MCP clients may supply their own. Drives the project component of ephemeral cc-<project>-<8> names — without this the minted name falls back to bare cc-<8> (or the operator-forced COMMY_PROJECT slug)."
|
|
58967
59049
|
};
|
|
58968
59050
|
const readSessionId = (args2) => exports_Option.getOrUndefined(parseSessionId(args2["session_id"]));
|
|
58969
59051
|
const readCwd = (args2) => {
|
|
@@ -58971,16 +59053,16 @@ var buildToolDefs = (deps, cache) => {
|
|
|
58971
59053
|
return exports_Predicate.isString(raw3) ? raw3 : undefined;
|
|
58972
59054
|
};
|
|
58973
59055
|
const projectForArgs = (args2) => projectForCwd(readCwd(args2));
|
|
58974
|
-
const stickyThreadEngagement = async (
|
|
58975
|
-
if (
|
|
59056
|
+
const stickyThreadEngagement = async (channel, threadName3) => {
|
|
59057
|
+
if (exports_Option.isNone(threadName3))
|
|
58976
59058
|
return;
|
|
58977
59059
|
const intent = {
|
|
58978
59060
|
kind: "thread",
|
|
58979
|
-
channelName:
|
|
58980
|
-
threadName:
|
|
59061
|
+
channelName: channel.name,
|
|
59062
|
+
threadName: threadName3.value
|
|
58981
59063
|
};
|
|
58982
59064
|
narrowSet.add(intent);
|
|
58983
|
-
await runEdge(
|
|
59065
|
+
await runEdge(adapter4.inbox.subscribe(intentToTarget(intent)));
|
|
58984
59066
|
};
|
|
58985
59067
|
const coreTools = [
|
|
58986
59068
|
{
|
|
@@ -59068,12 +59150,12 @@ var buildToolDefs = (deps, cache) => {
|
|
|
59068
59150
|
const channels = await runEdge(adapter4.directory.listChannels());
|
|
59069
59151
|
for (const c of channels)
|
|
59070
59152
|
cache.rememberChannel(c);
|
|
59071
|
-
return { channels:
|
|
59153
|
+
return { channels: await runEdge(exports_Effect.forEach(channels, (c) => encodeChannel(c))) };
|
|
59072
59154
|
}
|
|
59073
59155
|
},
|
|
59074
59156
|
{
|
|
59075
59157
|
name: "post",
|
|
59076
|
-
description: "Post a message to a channel by name. Optional thread (topic), mentions (identity ids the bot has seen), and reply_to (message id). To ping someone on Zulip, write the @**Name** markup inline in body where you want it rendered — the mentions array is notification metadata only and does
|
|
59158
|
+
description: "Post a message to a channel by name. Optional thread (topic), mentions (identity ids the bot has seen), and reply_to (message id). To ping someone on Zulip, write the @**Name** markup inline in body where you want it rendered — the mentions array is notification metadata only and does not modify body. Returns {message_id, channel_id, channel_name, thread, permalink}. When you show a human this message afterwards, link it by the returned permalink — never a bare name or message id.",
|
|
59077
59159
|
inputSchema: {
|
|
59078
59160
|
type: "object",
|
|
59079
59161
|
properties: {
|
|
@@ -59102,28 +59184,31 @@ var buildToolDefs = (deps, cache) => {
|
|
|
59102
59184
|
await runEdge(exports_Effect.flatMap(projectForArgs(args2), (project3) => identityCache.ensureBoundFor(readSessionId(args2), project3)).pipe(exports_Effect.flatMap((ensureBound) => ensureBound())));
|
|
59103
59185
|
const ref = await runEdge(exports_Effect.gen(function* () {
|
|
59104
59186
|
const { channel_name, body, thread, mentions, reply_to } = yield* exports_Schema.decodeUnknown(PostArgs)(args2);
|
|
59105
|
-
const channel = yield*
|
|
59187
|
+
const channel = yield* decodeChannelName(channel_name);
|
|
59106
59188
|
const messageBody = yield* decodeMessageBody(body);
|
|
59107
59189
|
const opts = {};
|
|
59108
59190
|
if (thread !== undefined) {
|
|
59109
|
-
opts.thread =
|
|
59191
|
+
opts.thread = yield* decodeThreadName(thread);
|
|
59110
59192
|
}
|
|
59111
59193
|
if (mentions !== undefined) {
|
|
59112
59194
|
opts.mentions = yield* resolveMentions(cache, mentions);
|
|
59113
59195
|
}
|
|
59114
59196
|
if (reply_to !== undefined) {
|
|
59115
|
-
opts.replyTo = yield* reconstructMessageRef(cache, reply_to, channel_name
|
|
59197
|
+
opts.replyTo = yield* reconstructMessageRef(cache, reply_to, channel_name);
|
|
59116
59198
|
}
|
|
59117
59199
|
return yield* adapter4.publisher.post(channel, messageBody, opts);
|
|
59118
59200
|
}));
|
|
59119
59201
|
cache.rememberMessage(ref);
|
|
59120
|
-
await stickyThreadEngagement(ref);
|
|
59202
|
+
await stickyThreadEngagement(ref.channel, exports_Option.map(ref.thread, (t) => t.name));
|
|
59121
59203
|
return {
|
|
59122
59204
|
message_id: ref.id,
|
|
59123
59205
|
channel_id: ref.channel.id,
|
|
59124
59206
|
channel_name: ref.channel.name,
|
|
59125
|
-
thread: ref.thread
|
|
59126
|
-
|
|
59207
|
+
thread: exports_Option.match(ref.thread, {
|
|
59208
|
+
onNone: () => null,
|
|
59209
|
+
onSome: (t) => ({ name: t.name })
|
|
59210
|
+
}),
|
|
59211
|
+
permalink: ref.permalink
|
|
59127
59212
|
};
|
|
59128
59213
|
}
|
|
59129
59214
|
},
|
|
@@ -59152,8 +59237,8 @@ var buildToolDefs = (deps, cache) => {
|
|
|
59152
59237
|
handler: async (args2) => {
|
|
59153
59238
|
await runEdge(exports_Effect.flatMap(projectForArgs(args2), (project3) => identityCache.ensureBoundFor(readSessionId(args2), project3)).pipe(exports_Effect.flatMap((ensureBound) => ensureBound())));
|
|
59154
59239
|
const ref = await runEdge(exports_Effect.gen(function* () {
|
|
59155
|
-
const { message_id, body, channel_name
|
|
59156
|
-
const target = yield* reconstructMessageRef(cache, message_id, channel_name
|
|
59240
|
+
const { message_id, body, channel_name } = yield* exports_Schema.decodeUnknown(EditMessageArgs)(args2);
|
|
59241
|
+
const target = yield* reconstructMessageRef(cache, message_id, channel_name);
|
|
59157
59242
|
yield* adapter4.publisher.edit(target, yield* decodeMessageBody(body));
|
|
59158
59243
|
return target;
|
|
59159
59244
|
}));
|
|
@@ -59185,14 +59270,16 @@ var buildToolDefs = (deps, cache) => {
|
|
|
59185
59270
|
},
|
|
59186
59271
|
handler: async (args2) => {
|
|
59187
59272
|
await runEdge(exports_Effect.flatMap(projectForArgs(args2), (project3) => identityCache.ensureBoundFor(readSessionId(args2), project3)).pipe(exports_Effect.flatMap((ensureBound) => ensureBound())));
|
|
59188
|
-
const ref = await runEdge(exports_Effect.gen(function* () {
|
|
59273
|
+
const { ref, threadName: threadName3 } = await runEdge(exports_Effect.gen(function* () {
|
|
59189
59274
|
const { message_id, emoji: emoji2, channel_name, thread } = yield* exports_Schema.decodeUnknown(ReactArgs)(args2);
|
|
59190
|
-
const target = yield* reconstructMessageRef(cache, message_id, channel_name
|
|
59275
|
+
const target = yield* reconstructMessageRef(cache, message_id, channel_name);
|
|
59191
59276
|
yield* adapter4.publisher.react(target, yield* decodeEmoji(emoji2));
|
|
59192
|
-
|
|
59277
|
+
const argThread = yield* exports_Effect.transposeMapOption(exports_Option.fromNullable(thread), decodeThreadName);
|
|
59278
|
+
const threadName4 = exports_Option.orElse(exports_Option.map(target.thread, (t) => t.name), () => argThread);
|
|
59279
|
+
return { ref: target, threadName: threadName4 };
|
|
59193
59280
|
}));
|
|
59194
59281
|
cache.rememberMessage(ref);
|
|
59195
|
-
await stickyThreadEngagement(ref);
|
|
59282
|
+
await stickyThreadEngagement(ref.channel, threadName3);
|
|
59196
59283
|
return {};
|
|
59197
59284
|
}
|
|
59198
59285
|
},
|
|
@@ -59215,8 +59302,8 @@ var buildToolDefs = (deps, cache) => {
|
|
|
59215
59302
|
handler: async (args2) => {
|
|
59216
59303
|
await runEdge(exports_Effect.flatMap(projectForArgs(args2), (project3) => identityCache.ensureBoundFor(readSessionId(args2), project3)).pipe(exports_Effect.flatMap((ensureBound) => ensureBound())));
|
|
59217
59304
|
await runEdge(exports_Effect.gen(function* () {
|
|
59218
|
-
const { message_id, emoji: emoji2, channel_name
|
|
59219
|
-
const ref = yield* reconstructMessageRef(cache, message_id, channel_name
|
|
59305
|
+
const { message_id, emoji: emoji2, channel_name } = yield* exports_Schema.decodeUnknown(ReactArgs)(args2);
|
|
59306
|
+
const ref = yield* reconstructMessageRef(cache, message_id, channel_name);
|
|
59220
59307
|
yield* adapter4.publisher.unreact(ref, yield* decodeEmoji(emoji2));
|
|
59221
59308
|
}));
|
|
59222
59309
|
return {};
|
|
@@ -59247,8 +59334,7 @@ var buildToolDefs = (deps, cache) => {
|
|
|
59247
59334
|
yield* deps.ensureSessionSubscriptions(sessionId, yield* projectForArgs(args2));
|
|
59248
59335
|
}
|
|
59249
59336
|
narrowSet.add(intent);
|
|
59250
|
-
|
|
59251
|
-
yield* adapter4.inbox.subscribe(target);
|
|
59337
|
+
yield* adapter4.inbox.subscribe(intentToTarget(intent));
|
|
59252
59338
|
if (sessionId !== undefined && deps.persistSessionSubscriptions !== undefined) {
|
|
59253
59339
|
yield* deps.persistSessionSubscriptions(sessionId);
|
|
59254
59340
|
}
|
|
@@ -59281,8 +59367,7 @@ var buildToolDefs = (deps, cache) => {
|
|
|
59281
59367
|
yield* deps.ensureSessionSubscriptions(sessionId, yield* projectForArgs(args2));
|
|
59282
59368
|
}
|
|
59283
59369
|
narrowSet.remove(intent);
|
|
59284
|
-
|
|
59285
|
-
yield* adapter4.inbox.unsubscribe(target);
|
|
59370
|
+
yield* adapter4.inbox.unsubscribe(intentToTarget(intent));
|
|
59286
59371
|
if (sessionId !== undefined && deps.persistSessionSubscriptions !== undefined) {
|
|
59287
59372
|
yield* deps.persistSessionSubscriptions(sessionId);
|
|
59288
59373
|
}
|
|
@@ -59305,14 +59390,14 @@ var buildToolDefs = (deps, cache) => {
|
|
|
59305
59390
|
handler: async (args2) => {
|
|
59306
59391
|
const messages = await runEdge(exports_Effect.gen(function* () {
|
|
59307
59392
|
const parsed = yield* exports_Schema.decodeUnknown(ReadChannelArgs)(args2);
|
|
59308
|
-
const
|
|
59309
|
-
return yield* adapter4.history.readChannel(
|
|
59393
|
+
const channel = yield* decodeChannelName(parsed.channel_name);
|
|
59394
|
+
return yield* adapter4.history.readChannel(channel, yield* parseRange(parsed));
|
|
59310
59395
|
}));
|
|
59311
59396
|
for (const m of messages) {
|
|
59312
59397
|
cache.rememberChannel(m.ref.channel);
|
|
59313
59398
|
cache.rememberIdentity(m.sender);
|
|
59314
59399
|
}
|
|
59315
|
-
return { messages:
|
|
59400
|
+
return { messages: await runEdge(exports_Effect.forEach(messages, messageShape)) };
|
|
59316
59401
|
}
|
|
59317
59402
|
},
|
|
59318
59403
|
{
|
|
@@ -59331,14 +59416,54 @@ var buildToolDefs = (deps, cache) => {
|
|
|
59331
59416
|
handler: async (args2) => {
|
|
59332
59417
|
const messages = await runEdge(exports_Effect.gen(function* () {
|
|
59333
59418
|
const parsed = yield* exports_Schema.decodeUnknown(ReadThreadArgs)(args2);
|
|
59334
|
-
const
|
|
59335
|
-
return yield* adapter4.history.readThread(
|
|
59419
|
+
const channel = yield* decodeChannelName(parsed.channel_name);
|
|
59420
|
+
return yield* adapter4.history.readThread(channel, yield* decodeThreadName(parsed.thread), yield* parseRange(parsed));
|
|
59336
59421
|
}));
|
|
59337
59422
|
for (const m of messages) {
|
|
59338
59423
|
cache.rememberChannel(m.ref.channel);
|
|
59339
59424
|
cache.rememberIdentity(m.sender);
|
|
59340
59425
|
}
|
|
59341
|
-
return { messages:
|
|
59426
|
+
return { messages: await runEdge(exports_Effect.forEach(messages, messageShape)) };
|
|
59427
|
+
}
|
|
59428
|
+
},
|
|
59429
|
+
{
|
|
59430
|
+
name: "resolve_thread",
|
|
59431
|
+
description: "Mark a thread resolved (channel_name + thread, like read_thread). Idempotent — resolving an already-resolved thread is a no-op. Resolution is a status kept separate from the thread name; read it back as a message's thread.resolved via read_thread / read_channel. Use unresolve_thread to clear it.",
|
|
59432
|
+
inputSchema: {
|
|
59433
|
+
type: "object",
|
|
59434
|
+
properties: {
|
|
59435
|
+
channel_name: { type: "string", description: "Channel the thread lives in" },
|
|
59436
|
+
thread: { type: "string", description: "Thread / topic name within the channel" }
|
|
59437
|
+
},
|
|
59438
|
+
required: ["channel_name", "thread"],
|
|
59439
|
+
additionalProperties: false
|
|
59440
|
+
},
|
|
59441
|
+
handler: async (args2) => {
|
|
59442
|
+
await runEdge(exports_Effect.gen(function* () {
|
|
59443
|
+
const parsed = yield* exports_Schema.decodeUnknown(ThreadResolutionArgs)(args2);
|
|
59444
|
+
yield* adapter4.publisher.resolveThread(yield* decodeChannelName(parsed.channel_name), yield* decodeThreadName(parsed.thread));
|
|
59445
|
+
}));
|
|
59446
|
+
return {};
|
|
59447
|
+
}
|
|
59448
|
+
},
|
|
59449
|
+
{
|
|
59450
|
+
name: "unresolve_thread",
|
|
59451
|
+
description: "Clear a thread's resolved status (channel_name + thread, like read_thread). Idempotent — unresolving a thread that is not resolved is a no-op. The inverse of resolve_thread.",
|
|
59452
|
+
inputSchema: {
|
|
59453
|
+
type: "object",
|
|
59454
|
+
properties: {
|
|
59455
|
+
channel_name: { type: "string", description: "Channel the thread lives in" },
|
|
59456
|
+
thread: { type: "string", description: "Thread / topic name within the channel" }
|
|
59457
|
+
},
|
|
59458
|
+
required: ["channel_name", "thread"],
|
|
59459
|
+
additionalProperties: false
|
|
59460
|
+
},
|
|
59461
|
+
handler: async (args2) => {
|
|
59462
|
+
await runEdge(exports_Effect.gen(function* () {
|
|
59463
|
+
const parsed = yield* exports_Schema.decodeUnknown(ThreadResolutionArgs)(args2);
|
|
59464
|
+
yield* adapter4.publisher.unresolveThread(yield* decodeChannelName(parsed.channel_name), yield* decodeThreadName(parsed.thread));
|
|
59465
|
+
}));
|
|
59466
|
+
return {};
|
|
59342
59467
|
}
|
|
59343
59468
|
},
|
|
59344
59469
|
{
|
|
@@ -59365,7 +59490,7 @@ var buildToolDefs = (deps, cache) => {
|
|
|
59365
59490
|
const parsed = yield* exports_Schema.decodeUnknown(MessageLinkArgs)(args2);
|
|
59366
59491
|
const id3 = yield* decodeMessageId(parsed.message_id);
|
|
59367
59492
|
const cached5 = cache.messageById.get(id3);
|
|
59368
|
-
if (cached5
|
|
59493
|
+
if (cached5 !== undefined)
|
|
59369
59494
|
return cached5.permalink;
|
|
59370
59495
|
const hint = parsed.channel_name === undefined ? undefined : {
|
|
59371
59496
|
channel: yield* decodeChannelName(parsed.channel_name),
|
|
@@ -59515,7 +59640,7 @@ var forkIdleSweep = (cache, intervalMs) => {
|
|
|
59515
59640
|
return exports_Effect.asVoid(exports_Effect.forkScoped(exports_Effect.repeat(sweep, exports_Schedule.spaced(exports_Duration.millis(intervalMs)))));
|
|
59516
59641
|
};
|
|
59517
59642
|
var createType2DefaultsOnAcquire = (narrowSet, inbox) => {
|
|
59518
|
-
const registerIntent = (intent) => exports_Effect.sync(() => narrowSet.add(intent)).pipe(exports_Effect.zipRight(
|
|
59643
|
+
const registerIntent = (intent) => exports_Effect.sync(() => narrowSet.add(intent)).pipe(exports_Effect.zipRight(inbox.subscribe(intentToTarget(intent))));
|
|
59519
59644
|
return (project3) => registerIntent({ kind: "mentions" }).pipe(exports_Effect.zipRight(project3 !== undefined ? exports_Effect.all([decodeChannelName(project3), decodeThreadName("general")]).pipe(exports_Effect.flatMap(([channelName, threadName3]) => registerIntent({ kind: "thread", channelName, threadName: threadName3 }))) : exports_Effect.void), exports_Effect.catchAll((err) => exports_Effect.logError(`commy plugin: Type-2 default narrow registration failed: ${exports_Cause.pretty(exports_Cause.fail(err))}`)));
|
|
59520
59645
|
};
|
|
59521
59646
|
var logType1Failure = (err) => exports_Effect.logError(`commy plugin: Type-1 default narrow registration failed: ${exports_Cause.pretty(exports_Cause.fail(err))}`);
|
|
@@ -59523,7 +59648,7 @@ var registerType1DefaultsOnBoot = (inbox, narrowSet, project3) => (project3 !==
|
|
|
59523
59648
|
{ kind: "mentions" },
|
|
59524
59649
|
{ kind: "new-topics-in-channel", channelName },
|
|
59525
59650
|
{ kind: "thread", channelName, threadName: threadName3 }
|
|
59526
|
-
])) : exports_Effect.succeed([{ kind: "mentions" }])).pipe(exports_Effect.flatMap((intents) => exports_Effect.forEach(intents, (intent) => exports_Effect.sync(() => narrowSet.add(intent)).pipe(exports_Effect.zipRight(
|
|
59651
|
+
])) : exports_Effect.succeed([{ kind: "mentions" }])).pipe(exports_Effect.flatMap((intents) => exports_Effect.forEach(intents, (intent) => exports_Effect.sync(() => narrowSet.add(intent)).pipe(exports_Effect.zipRight(inbox.subscribe(intentToTarget(intent))))).pipe(exports_Effect.as(intents), exports_Effect.catchAll((err) => logType1Failure(err).pipe(exports_Effect.as(intents))))), exports_Effect.catchAll((err) => logType1Failure(err).pipe(exports_Effect.as([{ kind: "mentions" }]))));
|
|
59527
59652
|
var DEFAULT_CATCHUP_WINDOW_SECONDS = 4 * 3600;
|
|
59528
59653
|
var buildIdentityCache = (adapter4, botName, ephemeralOnAcquire) => {
|
|
59529
59654
|
if (botName !== undefined) {
|
|
@@ -59569,14 +59694,11 @@ var makeProgram = (params = {}) => exports_Effect.scoped(exports_Effect.gen(func
|
|
|
59569
59694
|
const mcp = buildMcpServer();
|
|
59570
59695
|
const notifier = params.notifier ?? channelNotifier(mcp);
|
|
59571
59696
|
const registerType2Defaults = parsed.botName === undefined ? createType2DefaultsOnAcquire(narrowSet, adapter4.inbox) : undefined;
|
|
59572
|
-
const
|
|
59697
|
+
const sessionRestoreFeed = parsed.botName === undefined ? yield* makeSessionRestore({ subscriptionStore, narrowSet, inbox: adapter4.inbox }) : undefined;
|
|
59573
59698
|
const seedDefaults = (project3) => registerType2Defaults !== undefined ? registerType2Defaults(project3) : exports_Effect.void;
|
|
59574
|
-
const
|
|
59575
|
-
|
|
59576
|
-
|
|
59577
|
-
inbox: adapter4.inbox,
|
|
59578
|
-
registerDefaults: seedDefaults
|
|
59579
|
-
}, sessionId, project3).pipe(exports_Effect.catchAll((err) => exports_Effect.logError(`commy plugin: subscription restore failed for ${sessionId}: ${exports_Predicate.isError(err) ? err.message : String(err)}`).pipe(exports_Effect.zipRight(seedDefaults(project3)))), exports_Effect.provide(loggerLayer), exports_Effect.as(exports_HashSet.add(seen, sessionId))));
|
|
59699
|
+
const feedSession = (sessionId) => sessionRestoreFeed === undefined ? exports_Effect.void : sessionRestoreFeed(sessionId).pipe(exports_Effect.catchAll((err) => exports_Effect.logError(`commy plugin: subscription restore failed for ${sessionId}: ${exports_Predicate.isError(err) ? err.message : String(err)}`)), exports_Effect.provide(loggerLayer));
|
|
59700
|
+
const seedIfFresh = (sessionId, project3) => parsed.botName !== undefined ? exports_Effect.void : seedDefaultsIfFresh({ subscriptionStore, registerDefaults: seedDefaults }, sessionId, project3).pipe(exports_Effect.catchAll((err) => exports_Effect.logError(`commy plugin: subscription seed check failed for ${sessionId}: ${exports_Predicate.isError(err) ? err.message : String(err)}`).pipe(exports_Effect.zipRight(seedDefaults(project3)))), exports_Effect.provide(loggerLayer));
|
|
59701
|
+
const ensureSessionSubscriptions = (sessionId, project3) => feedSession(sessionId).pipe(exports_Effect.zipRight(seedIfFresh(sessionId, project3)));
|
|
59580
59702
|
const persistSessionSubscriptions = (sessionId) => parsed.botName !== undefined ? exports_Effect.void : persistSubscriptions(subscriptionStore, narrowSet, sessionId).pipe(exports_Effect.catchAll((err) => exports_Effect.logError(`commy plugin: subscription persist failed for ${sessionId}: ${exports_Predicate.isError(err) ? err.message : String(err)}`)), exports_Effect.provide(loggerLayer));
|
|
59581
59703
|
const ephemeralOnAcquire = parsed.botName === undefined ? (acquired, project3, sessionId) => ensureSessionSubscriptions(sessionId, project3).pipe(exports_Effect.zipRight(catchUpMentions({
|
|
59582
59704
|
cursorStore,
|