@codeforbreakfast/commy-mcp 0.19.0 → 0.20.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 +75 -18
package/package.json
CHANGED
package/server.js
CHANGED
|
@@ -3048,13 +3048,14 @@ var require_data = __commonJS((exports, module) => {
|
|
|
3048
3048
|
};
|
|
3049
3049
|
});
|
|
3050
3050
|
|
|
3051
|
-
// node_modules/.bun/fast-uri@4.
|
|
3051
|
+
// node_modules/.bun/fast-uri@4.1.0/node_modules/fast-uri/lib/utils.js
|
|
3052
3052
|
var require_utils = __commonJS((exports, module) => {
|
|
3053
3053
|
var isUUID = RegExp.prototype.test.bind(/^[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}$/iu);
|
|
3054
3054
|
var isIPv4 = RegExp.prototype.test.bind(/^(?:(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)$/u);
|
|
3055
3055
|
var isHexPair = RegExp.prototype.test.bind(/^[\da-f]{2}$/iu);
|
|
3056
3056
|
var isUnreserved = RegExp.prototype.test.bind(/^[\da-z\-._~]$/iu);
|
|
3057
3057
|
var isPathCharacter = RegExp.prototype.test.bind(/^[\da-z\-._~!$&'()*+,;=:@/]$/iu);
|
|
3058
|
+
var isQueryFragmentCharacter = RegExp.prototype.test.bind(/^[\da-z\-._~!$&'()*+,;=:@/?]$/iu);
|
|
3058
3059
|
function stringArrayToHexStripped(input) {
|
|
3059
3060
|
let acc = "";
|
|
3060
3061
|
let code = 0;
|
|
@@ -3198,7 +3199,7 @@ var require_utils = __commonJS((exports, module) => {
|
|
|
3198
3199
|
continue;
|
|
3199
3200
|
}
|
|
3200
3201
|
} else if (input[0] === "/") {
|
|
3201
|
-
if (input[1] === "."
|
|
3202
|
+
if (input[1] === ".") {
|
|
3202
3203
|
output.push("/");
|
|
3203
3204
|
break;
|
|
3204
3205
|
}
|
|
@@ -3340,6 +3341,47 @@ var require_utils = __commonJS((exports, module) => {
|
|
|
3340
3341
|
}
|
|
3341
3342
|
return output;
|
|
3342
3343
|
}
|
|
3344
|
+
function normalizeQueryFragmentEncoding(input) {
|
|
3345
|
+
let output = "";
|
|
3346
|
+
for (let i = 0;i < input.length; i++) {
|
|
3347
|
+
const ch = input[i];
|
|
3348
|
+
if (ch === "%" && i + 2 < input.length) {
|
|
3349
|
+
const hex = input.slice(i + 1, i + 3);
|
|
3350
|
+
if (isHexPair(hex)) {
|
|
3351
|
+
const normalizedHex = hex.toUpperCase();
|
|
3352
|
+
const decoded = String.fromCharCode(parseInt(normalizedHex, 16));
|
|
3353
|
+
if (isUnreserved(decoded)) {
|
|
3354
|
+
output += decoded;
|
|
3355
|
+
} else {
|
|
3356
|
+
output += "%" + normalizedHex;
|
|
3357
|
+
}
|
|
3358
|
+
i += 2;
|
|
3359
|
+
continue;
|
|
3360
|
+
}
|
|
3361
|
+
}
|
|
3362
|
+
if (isQueryFragmentCharacter(ch)) {
|
|
3363
|
+
output += ch;
|
|
3364
|
+
} else {
|
|
3365
|
+
const code = input.charCodeAt(i);
|
|
3366
|
+
if (code < 128) {
|
|
3367
|
+
output += isEscapeSafe(code) ? ch : BYTE_HEX[code];
|
|
3368
|
+
} else if (code < 55296 || code > 57343) {
|
|
3369
|
+
output += percentEncodeNonAscii(code);
|
|
3370
|
+
} else if (code <= 56319 && i + 1 < input.length) {
|
|
3371
|
+
const low = input.charCodeAt(i + 1);
|
|
3372
|
+
if (low >= 56320 && low <= 57343) {
|
|
3373
|
+
output += percentEncodeNonAscii(65536 + (code - 55296 << 10) + (low - 56320));
|
|
3374
|
+
i++;
|
|
3375
|
+
} else {
|
|
3376
|
+
output += percentEncodeNonAscii(65533);
|
|
3377
|
+
}
|
|
3378
|
+
} else {
|
|
3379
|
+
output += percentEncodeNonAscii(65533);
|
|
3380
|
+
}
|
|
3381
|
+
}
|
|
3382
|
+
}
|
|
3383
|
+
return output;
|
|
3384
|
+
}
|
|
3343
3385
|
function escapePreservingEscapes(input) {
|
|
3344
3386
|
let output = "";
|
|
3345
3387
|
for (let i = 0;i < input.length; i++) {
|
|
@@ -3401,6 +3443,7 @@ var require_utils = __commonJS((exports, module) => {
|
|
|
3401
3443
|
reescapeHostDelimiters,
|
|
3402
3444
|
normalizePercentEncoding,
|
|
3403
3445
|
normalizePathEncoding,
|
|
3446
|
+
normalizeQueryFragmentEncoding,
|
|
3404
3447
|
escapePreservingEscapes,
|
|
3405
3448
|
removeDotSegments,
|
|
3406
3449
|
isIPv4,
|
|
@@ -3410,7 +3453,7 @@ var require_utils = __commonJS((exports, module) => {
|
|
|
3410
3453
|
};
|
|
3411
3454
|
});
|
|
3412
3455
|
|
|
3413
|
-
// node_modules/.bun/fast-uri@4.
|
|
3456
|
+
// node_modules/.bun/fast-uri@4.1.0/node_modules/fast-uri/lib/schemes.js
|
|
3414
3457
|
var require_schemes = __commonJS((exports, module) => {
|
|
3415
3458
|
var { isUUID } = require_utils();
|
|
3416
3459
|
var URN_REG = /([\da-z][\d\-a-z]{0,31}):((?:[\w!$'()*+,\-.:;=@]|%[\da-f]{2})+)/iu;
|
|
@@ -3584,9 +3627,9 @@ var require_schemes = __commonJS((exports, module) => {
|
|
|
3584
3627
|
};
|
|
3585
3628
|
});
|
|
3586
3629
|
|
|
3587
|
-
// node_modules/.bun/fast-uri@4.
|
|
3630
|
+
// node_modules/.bun/fast-uri@4.1.0/node_modules/fast-uri/index.js
|
|
3588
3631
|
var require_fast_uri = __commonJS((exports, module) => {
|
|
3589
|
-
var { normalizeIPv6, removeDotSegments, recomposeAuthority, normalizePercentEncoding, normalizePathEncoding, escapePreservingEscapes, reescapeHostDelimiters, isIPv4, nonSimpleDomain } = require_utils();
|
|
3632
|
+
var { normalizeIPv6, removeDotSegments, recomposeAuthority, normalizePercentEncoding, normalizePathEncoding, normalizeQueryFragmentEncoding, escapePreservingEscapes, reescapeHostDelimiters, isIPv4, nonSimpleDomain } = require_utils();
|
|
3590
3633
|
var { SCHEMES, getSchemeHandler } = require_schemes();
|
|
3591
3634
|
function normalize3(uri, options5) {
|
|
3592
3635
|
if (typeof uri === "string") {
|
|
@@ -3755,7 +3798,7 @@ var require_fast_uri = __commonJS((exports, module) => {
|
|
|
3755
3798
|
}
|
|
3756
3799
|
const matches = uri.match(URI_PARSE);
|
|
3757
3800
|
if (matches) {
|
|
3758
|
-
parsed.scheme = matches[1];
|
|
3801
|
+
parsed.scheme = matches[1] === undefined ? undefined : matches[1].toLowerCase();
|
|
3759
3802
|
parsed.userinfo = matches[3];
|
|
3760
3803
|
parsed.host = matches[4];
|
|
3761
3804
|
parsed.port = parseInt(matches[5], 10);
|
|
@@ -3796,7 +3839,7 @@ var require_fast_uri = __commonJS((exports, module) => {
|
|
|
3796
3839
|
if (!options5.unicodeSupport && (!schemeHandler || !schemeHandler.unicodeSupport)) {
|
|
3797
3840
|
if (parsed.host && (options5.domainHost || schemeHandler && schemeHandler.domainHost) && isIP === false && nonSimpleDomain(parsed.host)) {
|
|
3798
3841
|
try {
|
|
3799
|
-
parsed.host = URL
|
|
3842
|
+
parsed.host = new URL("http://" + parsed.host).hostname;
|
|
3800
3843
|
} catch (e) {
|
|
3801
3844
|
parsed.error = parsed.error || "Host's domain name can not be converted to ASCII: " + e;
|
|
3802
3845
|
}
|
|
@@ -3814,12 +3857,11 @@ var require_fast_uri = __commonJS((exports, module) => {
|
|
|
3814
3857
|
if (parsed.path) {
|
|
3815
3858
|
parsed.path = normalizePathEncoding(parsed.path);
|
|
3816
3859
|
}
|
|
3860
|
+
if (parsed.query) {
|
|
3861
|
+
parsed.query = normalizeQueryFragmentEncoding(parsed.query);
|
|
3862
|
+
}
|
|
3817
3863
|
if (parsed.fragment) {
|
|
3818
|
-
|
|
3819
|
-
parsed.fragment = encodeURI(decodeURIComponent(parsed.fragment));
|
|
3820
|
-
} catch {
|
|
3821
|
-
parsed.error = parsed.error || "URI malformed";
|
|
3822
|
-
}
|
|
3864
|
+
parsed.fragment = normalizeQueryFragmentEncoding(parsed.fragment);
|
|
3823
3865
|
}
|
|
3824
3866
|
}
|
|
3825
3867
|
if (schemeHandler && schemeHandler.parse) {
|
|
@@ -47676,6 +47718,7 @@ var markReplayed = (events) => events.map((ev) => {
|
|
|
47676
47718
|
return ev;
|
|
47677
47719
|
});
|
|
47678
47720
|
var defaultRetrySchedule = exports_Schedule.exponential(exports_Duration.seconds(1)).pipe(exports_Schedule.either(exports_Schedule.spaced(exports_Duration.seconds(30))));
|
|
47721
|
+
var RESUME_VERDICT_FALLBACK = exports_Duration.seconds(60);
|
|
47679
47722
|
var skipWithLog = (line) => exports_Effect.logInfo(line).pipe(exports_Effect.as([]));
|
|
47680
47723
|
var processSingleEvent = (evt, directory, config2) => {
|
|
47681
47724
|
if (evt.type === "message") {
|
|
@@ -47707,7 +47750,7 @@ var processSingleEvent = (evt, directory, config2) => {
|
|
|
47707
47750
|
}
|
|
47708
47751
|
return exports_Effect.succeed([]);
|
|
47709
47752
|
};
|
|
47710
|
-
var inboxEvents = (config2) => exports_Stream.
|
|
47753
|
+
var inboxEvents = (config2) => exports_Stream.unwrapScoped(exports_Effect.gen(function* () {
|
|
47711
47754
|
const watermark = config2.watermarkStore ?? (yield* createWatermarkStore());
|
|
47712
47755
|
const breadcrumb = yield* exports_Ref.make({
|
|
47713
47756
|
consecutiveFailures: 0,
|
|
@@ -47720,6 +47763,9 @@ var inboxEvents = (config2) => exports_Stream.unwrap(exports_Effect.gen(function
|
|
|
47720
47763
|
return exports_Effect.void;
|
|
47721
47764
|
return exports_Ref.getAndSet(resumeReported, true).pipe(exports_Effect.flatMap((already) => already ? exports_Effect.void : onResumeOutcome(queueReplayed)));
|
|
47722
47765
|
};
|
|
47766
|
+
if (config2.onResumeOutcome !== undefined) {
|
|
47767
|
+
yield* exports_Effect.forkScoped(exports_Effect.sleep(RESUME_VERDICT_FALLBACK).pipe(exports_Effect.zipRight(reportResume(false))));
|
|
47768
|
+
}
|
|
47723
47769
|
const recordTransientFailure = (cause3) => exports_Ref.modify(breadcrumb, (s) => {
|
|
47724
47770
|
const consecutiveFailures = s.consecutiveFailures + 1;
|
|
47725
47771
|
return [consecutiveFailures, { consecutiveFailures, needsBreadcrumb: true }];
|
|
@@ -47954,6 +48000,7 @@ var sanitiseShortName = (name) => {
|
|
|
47954
48000
|
const collapsed = name.toLowerCase().replace(SHORT_NAME_PATTERN, "-");
|
|
47955
48001
|
return collapsed.replace(/^-+|-+$/g, "") || "bot";
|
|
47956
48002
|
};
|
|
48003
|
+
var ACQUIRE_MINT_TIMEOUT = exports_Duration.seconds(30);
|
|
47957
48004
|
var userSchema = exports_Schema.Struct({
|
|
47958
48005
|
user_id: exports_Schema.Int,
|
|
47959
48006
|
email: exports_Schema.String,
|
|
@@ -48226,7 +48273,7 @@ var zulipAdapter = (config2) => exports_Effect.gen(function* () {
|
|
|
48226
48273
|
}
|
|
48227
48274
|
return exports_Effect.die(new Error(`zulipAdapter: already bound to ${existing.acquiredName} — release() before acquiring ${name}`));
|
|
48228
48275
|
},
|
|
48229
|
-
onNone: () => provideMintedFor(name).pipe(exports_Effect.flatMap((minted) => exports_Effect.gen(function* () {
|
|
48276
|
+
onNone: () => provideMintedFor(name).pipe(exports_Effect.timeout(ACQUIRE_MINT_TIMEOUT), exports_Effect.flatMap((minted) => exports_Effect.gen(function* () {
|
|
48230
48277
|
const innerHttp = yield* makeZulipHttp(buildHttpConfig(config2.realmUrl, minted.email, minted.apiKey, config2.hostHeader)).pipe(exports_Effect.provideService(exports_HttpClient.HttpClient, httpClient));
|
|
48231
48278
|
const http = wrapBotHttp(innerHttp, recipientDirectory, minted.userId);
|
|
48232
48279
|
const ident = {
|
|
@@ -48360,15 +48407,25 @@ var zulipAdapter = (config2) => exports_Effect.gen(function* () {
|
|
|
48360
48407
|
})))
|
|
48361
48408
|
})))), exports_Effect.mapError((cause3) => cause3 instanceof PublisherError ? cause3 : new PublisherError({ operation, cause: cause3 })));
|
|
48362
48409
|
};
|
|
48410
|
+
const addressThread = (channel, thread) => {
|
|
48411
|
+
const resolvedTopic = applyResolvedPrefix(thread, true);
|
|
48412
|
+
return findNewestInTopic(channel, thread).pipe(exports_Effect.flatMap(exports_Option.match({
|
|
48413
|
+
onSome: () => exports_Effect.succeed({ topic: thread, resolved: false }),
|
|
48414
|
+
onNone: () => findNewestInTopic(channel, resolvedTopic).pipe(exports_Effect.map(exports_Option.match({
|
|
48415
|
+
onSome: () => ({ topic: resolvedTopic, resolved: true }),
|
|
48416
|
+
onNone: () => ({ topic: thread, resolved: false })
|
|
48417
|
+
})))
|
|
48418
|
+
})));
|
|
48419
|
+
};
|
|
48363
48420
|
const publisher = {
|
|
48364
48421
|
post: (channel, body, opts) => {
|
|
48365
48422
|
const thread = opts?.thread;
|
|
48366
|
-
return boundHttp().pipe(exports_Effect.flatMap((http) => resolvePublishChannel(channel).pipe(exports_Effect.flatMap((effective) => http.post("/messages", sentMessageSchema, {
|
|
48423
|
+
return boundHttp().pipe(exports_Effect.flatMap((http) => resolvePublishChannel(channel).pipe(exports_Effect.flatMap((effective) => (thread === undefined ? exports_Effect.succeed({ topic: "(no topic)", resolved: false }) : addressThread(effective.name, thread)).pipe(exports_Effect.flatMap((addressed) => http.post("/messages", sentMessageSchema, {
|
|
48367
48424
|
type: "channel",
|
|
48368
48425
|
to: effective.name,
|
|
48369
48426
|
content: body,
|
|
48370
|
-
topic:
|
|
48371
|
-
}).pipe(exports_Effect.flatMap((sent) => decodeMessageId(String(sent.id)).pipe(exports_Effect.map((id3) => decorateMessageRef(id3, effective, thread === undefined ? undefined : { name: thread, resolved:
|
|
48427
|
+
topic: addressed.topic
|
|
48428
|
+
}).pipe(exports_Effect.flatMap((sent) => decodeMessageId(String(sent.id)).pipe(exports_Effect.map((id3) => decorateMessageRef(id3, effective, thread === undefined ? undefined : { name: thread, resolved: addressed.resolved })))))))))), exports_Effect.mapError((cause3) => cause3 instanceof UnknownChannel ? cause3 : new PublisherError({ operation: "post", cause: cause3 })));
|
|
48372
48429
|
},
|
|
48373
48430
|
edit: (message, body) => boundHttp().pipe(exports_Effect.flatMap((http) => http.patch(`/messages/${encodeURIComponent(message.id)}`, successSchema2, {
|
|
48374
48431
|
content: body
|
|
@@ -58849,7 +58906,7 @@ class Server extends Protocol {
|
|
|
58849
58906
|
}
|
|
58850
58907
|
|
|
58851
58908
|
// packages/mcp/mcp-server.ts
|
|
58852
|
-
var PLUGIN_VERSION = "0.
|
|
58909
|
+
var PLUGIN_VERSION = "0.20.0";
|
|
58853
58910
|
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.
|
|
58854
58911
|
|
|
58855
58912
|
**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.
|