switchroom 0.14.30 → 0.14.31
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/cli/switchroom.js +98 -11
- package/dist/host-control/main.js +87 -9
- package/package.json +1 -1
- package/telegram-plugin/dist/gateway/gateway.js +142 -22
- package/telegram-plugin/gateway/gateway.ts +27 -0
- package/telegram-plugin/hooks/hooks.json +9 -0
- package/telegram-plugin/hooks/sentinel-reply-guard-pretool.mjs +114 -0
- package/telegram-plugin/hooks/silent-end-scan.mjs +61 -5
- package/telegram-plugin/secret-detect/generic-entropy.ts +87 -0
- package/telegram-plugin/secret-detect/index.ts +42 -23
- package/telegram-plugin/secret-detect/patterns.ts +64 -2
- package/telegram-plugin/secret-detect/redact.ts +10 -1
- package/telegram-plugin/tests/secret-detect-generic-entropy.test.ts +94 -0
- package/telegram-plugin/tests/secret-detect-providers.test.ts +74 -0
- package/telegram-plugin/tests/secret-detect-secretlint.test.ts +8 -4
- package/telegram-plugin/tests/sentinel-reply-guard-pretool.test.ts +109 -0
- package/telegram-plugin/tests/silent-end-interrupt-stop-scan.test.ts +118 -0
- package/telegram-plugin/tests/turn-flush-safety.test.ts +41 -0
- package/telegram-plugin/turn-flush-safety.ts +41 -0
package/dist/cli/switchroom.js
CHANGED
|
@@ -49420,8 +49420,8 @@ var {
|
|
|
49420
49420
|
} = import__.default;
|
|
49421
49421
|
|
|
49422
49422
|
// src/build-info.ts
|
|
49423
|
-
var VERSION = "0.14.
|
|
49424
|
-
var COMMIT_SHA = "
|
|
49423
|
+
var VERSION = "0.14.31";
|
|
49424
|
+
var COMMIT_SHA = "1aa03b91";
|
|
49425
49425
|
|
|
49426
49426
|
// src/cli/agent.ts
|
|
49427
49427
|
init_source();
|
|
@@ -51839,6 +51839,15 @@ function buildSettingsHooksBlock(p) {
|
|
|
51839
51839
|
}
|
|
51840
51840
|
]
|
|
51841
51841
|
},
|
|
51842
|
+
{
|
|
51843
|
+
hooks: [
|
|
51844
|
+
{
|
|
51845
|
+
type: "command",
|
|
51846
|
+
command: wrap("hook:sentinel-reply-guard-pretool", `node "${join8(DOCKER_HOOKS_PATH, "sentinel-reply-guard-pretool.mjs")}"`),
|
|
51847
|
+
timeout: 5
|
|
51848
|
+
}
|
|
51849
|
+
]
|
|
51850
|
+
},
|
|
51842
51851
|
{
|
|
51843
51852
|
matcher: "^(Agent|Task)$",
|
|
51844
51853
|
hooks: [
|
|
@@ -74020,7 +74029,39 @@ var STRUCTURED_PATTERNS = [
|
|
|
74020
74029
|
slugHint: "pem_private_key"
|
|
74021
74030
|
}
|
|
74022
74031
|
];
|
|
74023
|
-
var
|
|
74032
|
+
var PROVIDER_PATTERNS = [
|
|
74033
|
+
{ rule_id: "slack_webhook", regex: /(https:\/\/hooks\.slack\.com\/services\/[A-Za-z0-9_/]+)/g, captureIndex: 1, slugHint: "slack_webhook" },
|
|
74034
|
+
{ rule_id: "stripe_live_secret", regex: /\b(sk_live_[A-Za-z0-9]{24,})\b/g, captureIndex: 1, slugHint: "stripe_key" },
|
|
74035
|
+
{ rule_id: "stripe_restricted", regex: /\b(rk_live_[A-Za-z0-9]{24,})\b/g, captureIndex: 1, slugHint: "stripe_key" },
|
|
74036
|
+
{ rule_id: "sendgrid_api_key", regex: /\b(SG\.[A-Za-z0-9_-]{22}\.[A-Za-z0-9_-]{43})\b/g, captureIndex: 1, slugHint: "sendgrid_key" },
|
|
74037
|
+
{ rule_id: "gitlab_pat", regex: /\b(glpat-[A-Za-z0-9_-]{20})\b/g, captureIndex: 1, slugHint: "gitlab_pat" },
|
|
74038
|
+
{ rule_id: "huggingface_token", regex: /\b(hf_[A-Za-z0-9]{34,})\b/g, captureIndex: 1, slugHint: "huggingface_token" },
|
|
74039
|
+
{ rule_id: "twilio_api_key", regex: /\b(SK[0-9a-f]{32})\b/g, captureIndex: 1, slugHint: "twilio_api_key" },
|
|
74040
|
+
{ rule_id: "mailgun_key", regex: /\b(key-[0-9a-f]{32})\b/g, captureIndex: 1, slugHint: "mailgun_key" },
|
|
74041
|
+
{ rule_id: "digitalocean_pat", regex: /\b(dop_v1_[a-f0-9]{64})\b/g, captureIndex: 1, slugHint: "digitalocean_token" },
|
|
74042
|
+
{ rule_id: "digitalocean_oauth", regex: /\b(doo_v1_[a-f0-9]{64})\b/g, captureIndex: 1, slugHint: "digitalocean_token" },
|
|
74043
|
+
{ rule_id: "digitalocean_refresh", regex: /\b(dor_v1_[a-f0-9]{64})\b/g, captureIndex: 1, slugHint: "digitalocean_token" },
|
|
74044
|
+
{ rule_id: "doppler_token", regex: /\b(dp\.(?:pt|st|ct|sa|scim|audit)\.[A-Za-z0-9]{40,44})\b/g, captureIndex: 1, slugHint: "doppler_token" },
|
|
74045
|
+
{ rule_id: "linear_api_key", regex: /\b(lin_api_[A-Za-z0-9]{40})\b/g, captureIndex: 1, slugHint: "linear_api_key" },
|
|
74046
|
+
{ rule_id: "shopify_access_token", regex: /\b(shpat_[a-fA-F0-9]{32})\b/g, captureIndex: 1, slugHint: "shopify_token" },
|
|
74047
|
+
{ rule_id: "shopify_shared_secret", regex: /\b(shpss_[a-fA-F0-9]{32})\b/g, captureIndex: 1, slugHint: "shopify_token" },
|
|
74048
|
+
{ rule_id: "shopify_private_app", regex: /\b(shppa_[a-fA-F0-9]{32})\b/g, captureIndex: 1, slugHint: "shopify_token" },
|
|
74049
|
+
{ rule_id: "square_access_token", regex: /\b(sq0atp-[A-Za-z0-9_-]{22})\b/g, captureIndex: 1, slugHint: "square_token" },
|
|
74050
|
+
{ rule_id: "square_oauth_secret", regex: /\b(sq0csp-[A-Za-z0-9_-]{43})\b/g, captureIndex: 1, slugHint: "square_token" },
|
|
74051
|
+
{ rule_id: "newrelic_key", regex: /\b(NRAK-[A-Z0-9]{27})\b/g, captureIndex: 1, slugHint: "newrelic_key" },
|
|
74052
|
+
{ rule_id: "notion_token", regex: /\b(ntn_[A-Za-z0-9]{46})\b/g, captureIndex: 1, slugHint: "notion_token" },
|
|
74053
|
+
{ rule_id: "planetscale_password", regex: /\b(pscale_pw_[A-Za-z0-9_.-]{43})\b/g, captureIndex: 1, slugHint: "planetscale_token" },
|
|
74054
|
+
{ rule_id: "planetscale_token", regex: /\b(pscale_tkn_[A-Za-z0-9_.-]{43})\b/g, captureIndex: 1, slugHint: "planetscale_token" },
|
|
74055
|
+
{ rule_id: "supabase_service_key", regex: /\b(sbp_[a-f0-9]{40})\b/g, captureIndex: 1, slugHint: "supabase_key" },
|
|
74056
|
+
{ rule_id: "atlassian_token", regex: /\b(ATATT[A-Za-z0-9_\-=]{20,})\b/g, captureIndex: 1, slugHint: "atlassian_token" },
|
|
74057
|
+
{ rule_id: "dropbox_token", regex: /\b(sl\.[A-Za-z0-9_-]{130,})/g, captureIndex: 1, slugHint: "dropbox_token" },
|
|
74058
|
+
{ rule_id: "databricks_token", regex: /\b(dapi[a-f0-9]{32})\b/g, captureIndex: 1, slugHint: "databricks_token" },
|
|
74059
|
+
{ rule_id: "grafana_service_account", regex: /\b(glsa_[A-Za-z0-9]{32}_[a-fA-F0-9]{8})\b/g, captureIndex: 1, slugHint: "grafana_token" },
|
|
74060
|
+
{ rule_id: "pypi_token", regex: /\b(pypi-AgEIcHlwaS[A-Za-z0-9_-]{50,})/g, captureIndex: 1, slugHint: "pypi_token" },
|
|
74061
|
+
{ rule_id: "aws_temp_access_key", regex: /\b(ASIA[0-9A-Z]{16})\b/g, captureIndex: 1, slugHint: "aws_access_key" },
|
|
74062
|
+
{ rule_id: "gcp_oauth_token", regex: /\b(ya29\.[A-Za-z0-9_-]{30,})/g, captureIndex: 1, slugHint: "gcp_oauth_token" }
|
|
74063
|
+
];
|
|
74064
|
+
var ALL_PATTERNS = [...ANCHORED_PATTERNS, ...PROVIDER_PATTERNS, ...STRUCTURED_PATTERNS];
|
|
74024
74065
|
|
|
74025
74066
|
// telegram-plugin/secret-detect/entropy.ts
|
|
74026
74067
|
function shannonEntropy(s) {
|
|
@@ -74070,6 +74111,54 @@ function scanKeyValue(text) {
|
|
|
74070
74111
|
return hits;
|
|
74071
74112
|
}
|
|
74072
74113
|
|
|
74114
|
+
// telegram-plugin/secret-detect/generic-entropy.ts
|
|
74115
|
+
var CANDIDATE_RE = /[A-Za-z0-9]{28,}/g;
|
|
74116
|
+
var GENERIC_MIN_DISTINCT = 18;
|
|
74117
|
+
var MAX_GENERIC_HITS = 20;
|
|
74118
|
+
function hasDistinctChars(tok, n) {
|
|
74119
|
+
const seen = new Uint8Array(128);
|
|
74120
|
+
let distinct = 0;
|
|
74121
|
+
for (let i = 0;i < tok.length; i++) {
|
|
74122
|
+
const c = tok.charCodeAt(i);
|
|
74123
|
+
if (seen[c] === 0) {
|
|
74124
|
+
seen[c] = 1;
|
|
74125
|
+
if (++distinct >= n)
|
|
74126
|
+
return true;
|
|
74127
|
+
}
|
|
74128
|
+
}
|
|
74129
|
+
return false;
|
|
74130
|
+
}
|
|
74131
|
+
function hasDigit(tok) {
|
|
74132
|
+
for (let i = 0;i < tok.length; i++) {
|
|
74133
|
+
const c = tok.charCodeAt(i);
|
|
74134
|
+
if (c >= 48 && c <= 57)
|
|
74135
|
+
return true;
|
|
74136
|
+
}
|
|
74137
|
+
return false;
|
|
74138
|
+
}
|
|
74139
|
+
function scanGenericSecrets(text) {
|
|
74140
|
+
const hits = [];
|
|
74141
|
+
CANDIDATE_RE.lastIndex = 0;
|
|
74142
|
+
let m;
|
|
74143
|
+
while ((m = CANDIDATE_RE.exec(text)) !== null) {
|
|
74144
|
+
if (hits.length >= MAX_GENERIC_HITS)
|
|
74145
|
+
break;
|
|
74146
|
+
const tok = m[0];
|
|
74147
|
+
if (!hasDigit(tok))
|
|
74148
|
+
continue;
|
|
74149
|
+
if (!hasDistinctChars(tok, GENERIC_MIN_DISTINCT))
|
|
74150
|
+
continue;
|
|
74151
|
+
hits.push({
|
|
74152
|
+
rule_id: "generic_high_entropy",
|
|
74153
|
+
start: m.index,
|
|
74154
|
+
end: m.index + tok.length,
|
|
74155
|
+
matched_text: tok,
|
|
74156
|
+
confidence: "ambiguous"
|
|
74157
|
+
});
|
|
74158
|
+
}
|
|
74159
|
+
return hits;
|
|
74160
|
+
}
|
|
74161
|
+
|
|
74073
74162
|
// telegram-plugin/secret-detect/chunker.ts
|
|
74074
74163
|
var CHUNK_THRESHOLD = 32 * 1024;
|
|
74075
74164
|
var WINDOW_SIZE = 16 * 1024;
|
|
@@ -74184,6 +74273,10 @@ function detectSecrets(text) {
|
|
|
74184
74273
|
for (const h of kvHits) {
|
|
74185
74274
|
raw.push({ ...h, start: h.start + win.offset, end: h.end + win.offset });
|
|
74186
74275
|
}
|
|
74276
|
+
const genHits = scanGenericSecrets(win.text);
|
|
74277
|
+
for (const h of genHits) {
|
|
74278
|
+
raw.push({ ...h, start: h.start + win.offset, end: h.end + win.offset });
|
|
74279
|
+
}
|
|
74187
74280
|
}
|
|
74188
74281
|
const deduped = dedupeRaw(raw);
|
|
74189
74282
|
const final = dropOverlaps(deduped);
|
|
@@ -74222,13 +74315,7 @@ function dedupeRaw(raw) {
|
|
|
74222
74315
|
return Array.from(seen.values());
|
|
74223
74316
|
}
|
|
74224
74317
|
function dropOverlaps(hits) {
|
|
74225
|
-
const
|
|
74226
|
-
const out = [];
|
|
74227
|
-
for (const h of sorted) {
|
|
74228
|
-
const contained = out.some((existing) => existing !== h && existing.start <= h.start && existing.end >= h.end && !(existing.start === h.start && existing.end === h.end));
|
|
74229
|
-
if (!contained)
|
|
74230
|
-
out.push(h);
|
|
74231
|
-
}
|
|
74318
|
+
const out = hits.filter((h) => !(h.confidence === "ambiguous" && hits.some((o) => o !== h && o.start <= h.start && o.end >= h.end && !(o.start === h.start && o.end === h.end))));
|
|
74232
74319
|
out.sort((a, b) => a.start - b.start || a.end - b.end);
|
|
74233
74320
|
return out;
|
|
74234
74321
|
}
|
|
@@ -74239,7 +74326,7 @@ function redact(text) {
|
|
|
74239
74326
|
if (!text || text.length === 0)
|
|
74240
74327
|
return text;
|
|
74241
74328
|
const urlScrubbed = redactUrls(text);
|
|
74242
|
-
const hits = detectSecrets(urlScrubbed);
|
|
74329
|
+
const hits = detectSecrets(urlScrubbed).filter((h) => h.rule_id !== "generic_high_entropy");
|
|
74243
74330
|
if (hits.length === 0)
|
|
74244
74331
|
return urlScrubbed;
|
|
74245
74332
|
const sorted = [...hits].sort((a, b) => b.start - a.start);
|
|
@@ -19908,7 +19908,39 @@ var STRUCTURED_PATTERNS = [
|
|
|
19908
19908
|
slugHint: "pem_private_key"
|
|
19909
19909
|
}
|
|
19910
19910
|
];
|
|
19911
|
-
var
|
|
19911
|
+
var PROVIDER_PATTERNS = [
|
|
19912
|
+
{ rule_id: "slack_webhook", regex: /(https:\/\/hooks\.slack\.com\/services\/[A-Za-z0-9_/]+)/g, captureIndex: 1, slugHint: "slack_webhook" },
|
|
19913
|
+
{ rule_id: "stripe_live_secret", regex: /\b(sk_live_[A-Za-z0-9]{24,})\b/g, captureIndex: 1, slugHint: "stripe_key" },
|
|
19914
|
+
{ rule_id: "stripe_restricted", regex: /\b(rk_live_[A-Za-z0-9]{24,})\b/g, captureIndex: 1, slugHint: "stripe_key" },
|
|
19915
|
+
{ rule_id: "sendgrid_api_key", regex: /\b(SG\.[A-Za-z0-9_-]{22}\.[A-Za-z0-9_-]{43})\b/g, captureIndex: 1, slugHint: "sendgrid_key" },
|
|
19916
|
+
{ rule_id: "gitlab_pat", regex: /\b(glpat-[A-Za-z0-9_-]{20})\b/g, captureIndex: 1, slugHint: "gitlab_pat" },
|
|
19917
|
+
{ rule_id: "huggingface_token", regex: /\b(hf_[A-Za-z0-9]{34,})\b/g, captureIndex: 1, slugHint: "huggingface_token" },
|
|
19918
|
+
{ rule_id: "twilio_api_key", regex: /\b(SK[0-9a-f]{32})\b/g, captureIndex: 1, slugHint: "twilio_api_key" },
|
|
19919
|
+
{ rule_id: "mailgun_key", regex: /\b(key-[0-9a-f]{32})\b/g, captureIndex: 1, slugHint: "mailgun_key" },
|
|
19920
|
+
{ rule_id: "digitalocean_pat", regex: /\b(dop_v1_[a-f0-9]{64})\b/g, captureIndex: 1, slugHint: "digitalocean_token" },
|
|
19921
|
+
{ rule_id: "digitalocean_oauth", regex: /\b(doo_v1_[a-f0-9]{64})\b/g, captureIndex: 1, slugHint: "digitalocean_token" },
|
|
19922
|
+
{ rule_id: "digitalocean_refresh", regex: /\b(dor_v1_[a-f0-9]{64})\b/g, captureIndex: 1, slugHint: "digitalocean_token" },
|
|
19923
|
+
{ rule_id: "doppler_token", regex: /\b(dp\.(?:pt|st|ct|sa|scim|audit)\.[A-Za-z0-9]{40,44})\b/g, captureIndex: 1, slugHint: "doppler_token" },
|
|
19924
|
+
{ rule_id: "linear_api_key", regex: /\b(lin_api_[A-Za-z0-9]{40})\b/g, captureIndex: 1, slugHint: "linear_api_key" },
|
|
19925
|
+
{ rule_id: "shopify_access_token", regex: /\b(shpat_[a-fA-F0-9]{32})\b/g, captureIndex: 1, slugHint: "shopify_token" },
|
|
19926
|
+
{ rule_id: "shopify_shared_secret", regex: /\b(shpss_[a-fA-F0-9]{32})\b/g, captureIndex: 1, slugHint: "shopify_token" },
|
|
19927
|
+
{ rule_id: "shopify_private_app", regex: /\b(shppa_[a-fA-F0-9]{32})\b/g, captureIndex: 1, slugHint: "shopify_token" },
|
|
19928
|
+
{ rule_id: "square_access_token", regex: /\b(sq0atp-[A-Za-z0-9_-]{22})\b/g, captureIndex: 1, slugHint: "square_token" },
|
|
19929
|
+
{ rule_id: "square_oauth_secret", regex: /\b(sq0csp-[A-Za-z0-9_-]{43})\b/g, captureIndex: 1, slugHint: "square_token" },
|
|
19930
|
+
{ rule_id: "newrelic_key", regex: /\b(NRAK-[A-Z0-9]{27})\b/g, captureIndex: 1, slugHint: "newrelic_key" },
|
|
19931
|
+
{ rule_id: "notion_token", regex: /\b(ntn_[A-Za-z0-9]{46})\b/g, captureIndex: 1, slugHint: "notion_token" },
|
|
19932
|
+
{ rule_id: "planetscale_password", regex: /\b(pscale_pw_[A-Za-z0-9_.-]{43})\b/g, captureIndex: 1, slugHint: "planetscale_token" },
|
|
19933
|
+
{ rule_id: "planetscale_token", regex: /\b(pscale_tkn_[A-Za-z0-9_.-]{43})\b/g, captureIndex: 1, slugHint: "planetscale_token" },
|
|
19934
|
+
{ rule_id: "supabase_service_key", regex: /\b(sbp_[a-f0-9]{40})\b/g, captureIndex: 1, slugHint: "supabase_key" },
|
|
19935
|
+
{ rule_id: "atlassian_token", regex: /\b(ATATT[A-Za-z0-9_\-=]{20,})\b/g, captureIndex: 1, slugHint: "atlassian_token" },
|
|
19936
|
+
{ rule_id: "dropbox_token", regex: /\b(sl\.[A-Za-z0-9_-]{130,})/g, captureIndex: 1, slugHint: "dropbox_token" },
|
|
19937
|
+
{ rule_id: "databricks_token", regex: /\b(dapi[a-f0-9]{32})\b/g, captureIndex: 1, slugHint: "databricks_token" },
|
|
19938
|
+
{ rule_id: "grafana_service_account", regex: /\b(glsa_[A-Za-z0-9]{32}_[a-fA-F0-9]{8})\b/g, captureIndex: 1, slugHint: "grafana_token" },
|
|
19939
|
+
{ rule_id: "pypi_token", regex: /\b(pypi-AgEIcHlwaS[A-Za-z0-9_-]{50,})/g, captureIndex: 1, slugHint: "pypi_token" },
|
|
19940
|
+
{ rule_id: "aws_temp_access_key", regex: /\b(ASIA[0-9A-Z]{16})\b/g, captureIndex: 1, slugHint: "aws_access_key" },
|
|
19941
|
+
{ rule_id: "gcp_oauth_token", regex: /\b(ya29\.[A-Za-z0-9_-]{30,})/g, captureIndex: 1, slugHint: "gcp_oauth_token" }
|
|
19942
|
+
];
|
|
19943
|
+
var ALL_PATTERNS = [...ANCHORED_PATTERNS, ...PROVIDER_PATTERNS, ...STRUCTURED_PATTERNS];
|
|
19912
19944
|
|
|
19913
19945
|
// telegram-plugin/secret-detect/entropy.ts
|
|
19914
19946
|
function shannonEntropy(s) {
|
|
@@ -19958,6 +19990,54 @@ function scanKeyValue(text) {
|
|
|
19958
19990
|
return hits;
|
|
19959
19991
|
}
|
|
19960
19992
|
|
|
19993
|
+
// telegram-plugin/secret-detect/generic-entropy.ts
|
|
19994
|
+
var CANDIDATE_RE = /[A-Za-z0-9]{28,}/g;
|
|
19995
|
+
var GENERIC_MIN_DISTINCT = 18;
|
|
19996
|
+
var MAX_GENERIC_HITS = 20;
|
|
19997
|
+
function hasDistinctChars(tok, n) {
|
|
19998
|
+
const seen = new Uint8Array(128);
|
|
19999
|
+
let distinct = 0;
|
|
20000
|
+
for (let i = 0;i < tok.length; i++) {
|
|
20001
|
+
const c = tok.charCodeAt(i);
|
|
20002
|
+
if (seen[c] === 0) {
|
|
20003
|
+
seen[c] = 1;
|
|
20004
|
+
if (++distinct >= n)
|
|
20005
|
+
return true;
|
|
20006
|
+
}
|
|
20007
|
+
}
|
|
20008
|
+
return false;
|
|
20009
|
+
}
|
|
20010
|
+
function hasDigit(tok) {
|
|
20011
|
+
for (let i = 0;i < tok.length; i++) {
|
|
20012
|
+
const c = tok.charCodeAt(i);
|
|
20013
|
+
if (c >= 48 && c <= 57)
|
|
20014
|
+
return true;
|
|
20015
|
+
}
|
|
20016
|
+
return false;
|
|
20017
|
+
}
|
|
20018
|
+
function scanGenericSecrets(text) {
|
|
20019
|
+
const hits = [];
|
|
20020
|
+
CANDIDATE_RE.lastIndex = 0;
|
|
20021
|
+
let m;
|
|
20022
|
+
while ((m = CANDIDATE_RE.exec(text)) !== null) {
|
|
20023
|
+
if (hits.length >= MAX_GENERIC_HITS)
|
|
20024
|
+
break;
|
|
20025
|
+
const tok = m[0];
|
|
20026
|
+
if (!hasDigit(tok))
|
|
20027
|
+
continue;
|
|
20028
|
+
if (!hasDistinctChars(tok, GENERIC_MIN_DISTINCT))
|
|
20029
|
+
continue;
|
|
20030
|
+
hits.push({
|
|
20031
|
+
rule_id: "generic_high_entropy",
|
|
20032
|
+
start: m.index,
|
|
20033
|
+
end: m.index + tok.length,
|
|
20034
|
+
matched_text: tok,
|
|
20035
|
+
confidence: "ambiguous"
|
|
20036
|
+
});
|
|
20037
|
+
}
|
|
20038
|
+
return hits;
|
|
20039
|
+
}
|
|
20040
|
+
|
|
19961
20041
|
// telegram-plugin/secret-detect/chunker.ts
|
|
19962
20042
|
var CHUNK_THRESHOLD = 32 * 1024;
|
|
19963
20043
|
var WINDOW_SIZE = 16 * 1024;
|
|
@@ -20072,6 +20152,10 @@ function detectSecrets(text) {
|
|
|
20072
20152
|
for (const h of kvHits) {
|
|
20073
20153
|
raw.push({ ...h, start: h.start + win.offset, end: h.end + win.offset });
|
|
20074
20154
|
}
|
|
20155
|
+
const genHits = scanGenericSecrets(win.text);
|
|
20156
|
+
for (const h of genHits) {
|
|
20157
|
+
raw.push({ ...h, start: h.start + win.offset, end: h.end + win.offset });
|
|
20158
|
+
}
|
|
20075
20159
|
}
|
|
20076
20160
|
const deduped = dedupeRaw(raw);
|
|
20077
20161
|
const final = dropOverlaps(deduped);
|
|
@@ -20110,13 +20194,7 @@ function dedupeRaw(raw) {
|
|
|
20110
20194
|
return Array.from(seen.values());
|
|
20111
20195
|
}
|
|
20112
20196
|
function dropOverlaps(hits) {
|
|
20113
|
-
const
|
|
20114
|
-
const out = [];
|
|
20115
|
-
for (const h of sorted) {
|
|
20116
|
-
const contained = out.some((existing) => existing !== h && existing.start <= h.start && existing.end >= h.end && !(existing.start === h.start && existing.end === h.end));
|
|
20117
|
-
if (!contained)
|
|
20118
|
-
out.push(h);
|
|
20119
|
-
}
|
|
20197
|
+
const out = hits.filter((h) => !(h.confidence === "ambiguous" && hits.some((o) => o !== h && o.start <= h.start && o.end >= h.end && !(o.start === h.start && o.end === h.end))));
|
|
20120
20198
|
out.sort((a, b) => a.start - b.start || a.end - b.end);
|
|
20121
20199
|
return out;
|
|
20122
20200
|
}
|
|
@@ -20127,7 +20205,7 @@ function redact(text) {
|
|
|
20127
20205
|
if (!text || text.length === 0)
|
|
20128
20206
|
return text;
|
|
20129
20207
|
const urlScrubbed = redactUrls(text);
|
|
20130
|
-
const hits = detectSecrets(urlScrubbed);
|
|
20208
|
+
const hits = detectSecrets(urlScrubbed).filter((h) => h.rule_id !== "generic_high_entropy");
|
|
20131
20209
|
if (hits.length === 0)
|
|
20132
20210
|
return urlScrubbed;
|
|
20133
20211
|
const sorted = [...hits].sort((a, b) => b.start - a.start);
|
package/package.json
CHANGED
|
@@ -24867,7 +24867,7 @@ var init_loader = __esm(() => {
|
|
|
24867
24867
|
});
|
|
24868
24868
|
|
|
24869
24869
|
// secret-detect/patterns.ts
|
|
24870
|
-
var ANCHORED_PATTERNS, STRUCTURED_PATTERNS, ALL_PATTERNS;
|
|
24870
|
+
var ANCHORED_PATTERNS, STRUCTURED_PATTERNS, PROVIDER_PATTERNS, ALL_PATTERNS;
|
|
24871
24871
|
var init_patterns = __esm(() => {
|
|
24872
24872
|
ANCHORED_PATTERNS = [
|
|
24873
24873
|
{ rule_id: "anthropic_api_key", regex: /\b(sk-ant-[A-Za-z0-9_-]{8,})\b/g, captureIndex: 1, slugHint: "anthropic_api_key" },
|
|
@@ -24925,7 +24925,39 @@ var init_patterns = __esm(() => {
|
|
|
24925
24925
|
slugHint: "pem_private_key"
|
|
24926
24926
|
}
|
|
24927
24927
|
];
|
|
24928
|
-
|
|
24928
|
+
PROVIDER_PATTERNS = [
|
|
24929
|
+
{ rule_id: "slack_webhook", regex: /(https:\/\/hooks\.slack\.com\/services\/[A-Za-z0-9_/]+)/g, captureIndex: 1, slugHint: "slack_webhook" },
|
|
24930
|
+
{ rule_id: "stripe_live_secret", regex: /\b(sk_live_[A-Za-z0-9]{24,})\b/g, captureIndex: 1, slugHint: "stripe_key" },
|
|
24931
|
+
{ rule_id: "stripe_restricted", regex: /\b(rk_live_[A-Za-z0-9]{24,})\b/g, captureIndex: 1, slugHint: "stripe_key" },
|
|
24932
|
+
{ rule_id: "sendgrid_api_key", regex: /\b(SG\.[A-Za-z0-9_-]{22}\.[A-Za-z0-9_-]{43})\b/g, captureIndex: 1, slugHint: "sendgrid_key" },
|
|
24933
|
+
{ rule_id: "gitlab_pat", regex: /\b(glpat-[A-Za-z0-9_-]{20})\b/g, captureIndex: 1, slugHint: "gitlab_pat" },
|
|
24934
|
+
{ rule_id: "huggingface_token", regex: /\b(hf_[A-Za-z0-9]{34,})\b/g, captureIndex: 1, slugHint: "huggingface_token" },
|
|
24935
|
+
{ rule_id: "twilio_api_key", regex: /\b(SK[0-9a-f]{32})\b/g, captureIndex: 1, slugHint: "twilio_api_key" },
|
|
24936
|
+
{ rule_id: "mailgun_key", regex: /\b(key-[0-9a-f]{32})\b/g, captureIndex: 1, slugHint: "mailgun_key" },
|
|
24937
|
+
{ rule_id: "digitalocean_pat", regex: /\b(dop_v1_[a-f0-9]{64})\b/g, captureIndex: 1, slugHint: "digitalocean_token" },
|
|
24938
|
+
{ rule_id: "digitalocean_oauth", regex: /\b(doo_v1_[a-f0-9]{64})\b/g, captureIndex: 1, slugHint: "digitalocean_token" },
|
|
24939
|
+
{ rule_id: "digitalocean_refresh", regex: /\b(dor_v1_[a-f0-9]{64})\b/g, captureIndex: 1, slugHint: "digitalocean_token" },
|
|
24940
|
+
{ rule_id: "doppler_token", regex: /\b(dp\.(?:pt|st|ct|sa|scim|audit)\.[A-Za-z0-9]{40,44})\b/g, captureIndex: 1, slugHint: "doppler_token" },
|
|
24941
|
+
{ rule_id: "linear_api_key", regex: /\b(lin_api_[A-Za-z0-9]{40})\b/g, captureIndex: 1, slugHint: "linear_api_key" },
|
|
24942
|
+
{ rule_id: "shopify_access_token", regex: /\b(shpat_[a-fA-F0-9]{32})\b/g, captureIndex: 1, slugHint: "shopify_token" },
|
|
24943
|
+
{ rule_id: "shopify_shared_secret", regex: /\b(shpss_[a-fA-F0-9]{32})\b/g, captureIndex: 1, slugHint: "shopify_token" },
|
|
24944
|
+
{ rule_id: "shopify_private_app", regex: /\b(shppa_[a-fA-F0-9]{32})\b/g, captureIndex: 1, slugHint: "shopify_token" },
|
|
24945
|
+
{ rule_id: "square_access_token", regex: /\b(sq0atp-[A-Za-z0-9_-]{22})\b/g, captureIndex: 1, slugHint: "square_token" },
|
|
24946
|
+
{ rule_id: "square_oauth_secret", regex: /\b(sq0csp-[A-Za-z0-9_-]{43})\b/g, captureIndex: 1, slugHint: "square_token" },
|
|
24947
|
+
{ rule_id: "newrelic_key", regex: /\b(NRAK-[A-Z0-9]{27})\b/g, captureIndex: 1, slugHint: "newrelic_key" },
|
|
24948
|
+
{ rule_id: "notion_token", regex: /\b(ntn_[A-Za-z0-9]{46})\b/g, captureIndex: 1, slugHint: "notion_token" },
|
|
24949
|
+
{ rule_id: "planetscale_password", regex: /\b(pscale_pw_[A-Za-z0-9_.-]{43})\b/g, captureIndex: 1, slugHint: "planetscale_token" },
|
|
24950
|
+
{ rule_id: "planetscale_token", regex: /\b(pscale_tkn_[A-Za-z0-9_.-]{43})\b/g, captureIndex: 1, slugHint: "planetscale_token" },
|
|
24951
|
+
{ rule_id: "supabase_service_key", regex: /\b(sbp_[a-f0-9]{40})\b/g, captureIndex: 1, slugHint: "supabase_key" },
|
|
24952
|
+
{ rule_id: "atlassian_token", regex: /\b(ATATT[A-Za-z0-9_\-=]{20,})\b/g, captureIndex: 1, slugHint: "atlassian_token" },
|
|
24953
|
+
{ rule_id: "dropbox_token", regex: /\b(sl\.[A-Za-z0-9_-]{130,})/g, captureIndex: 1, slugHint: "dropbox_token" },
|
|
24954
|
+
{ rule_id: "databricks_token", regex: /\b(dapi[a-f0-9]{32})\b/g, captureIndex: 1, slugHint: "databricks_token" },
|
|
24955
|
+
{ rule_id: "grafana_service_account", regex: /\b(glsa_[A-Za-z0-9]{32}_[a-fA-F0-9]{8})\b/g, captureIndex: 1, slugHint: "grafana_token" },
|
|
24956
|
+
{ rule_id: "pypi_token", regex: /\b(pypi-AgEIcHlwaS[A-Za-z0-9_-]{50,})/g, captureIndex: 1, slugHint: "pypi_token" },
|
|
24957
|
+
{ rule_id: "aws_temp_access_key", regex: /\b(ASIA[0-9A-Z]{16})\b/g, captureIndex: 1, slugHint: "aws_access_key" },
|
|
24958
|
+
{ rule_id: "gcp_oauth_token", regex: /\b(ya29\.[A-Za-z0-9_-]{30,})/g, captureIndex: 1, slugHint: "gcp_oauth_token" }
|
|
24959
|
+
];
|
|
24960
|
+
ALL_PATTERNS = [...ANCHORED_PATTERNS, ...PROVIDER_PATTERNS, ...STRUCTURED_PATTERNS];
|
|
24929
24961
|
});
|
|
24930
24962
|
|
|
24931
24963
|
// secret-detect/entropy.ts
|
|
@@ -24978,6 +25010,55 @@ var init_kv_scanner = __esm(() => {
|
|
|
24978
25010
|
KV_RE = /\b([A-Za-z_][A-Za-z0-9_-]*(?:password|passwd|token|secret|key|api[_-]?key))\s*[:=]\s*["']?([^\s"'\\]{8,})["']?/gi;
|
|
24979
25011
|
});
|
|
24980
25012
|
|
|
25013
|
+
// secret-detect/generic-entropy.ts
|
|
25014
|
+
function hasDistinctChars(tok, n) {
|
|
25015
|
+
const seen = new Uint8Array(128);
|
|
25016
|
+
let distinct = 0;
|
|
25017
|
+
for (let i = 0;i < tok.length; i++) {
|
|
25018
|
+
const c = tok.charCodeAt(i);
|
|
25019
|
+
if (seen[c] === 0) {
|
|
25020
|
+
seen[c] = 1;
|
|
25021
|
+
if (++distinct >= n)
|
|
25022
|
+
return true;
|
|
25023
|
+
}
|
|
25024
|
+
}
|
|
25025
|
+
return false;
|
|
25026
|
+
}
|
|
25027
|
+
function hasDigit(tok) {
|
|
25028
|
+
for (let i = 0;i < tok.length; i++) {
|
|
25029
|
+
const c = tok.charCodeAt(i);
|
|
25030
|
+
if (c >= 48 && c <= 57)
|
|
25031
|
+
return true;
|
|
25032
|
+
}
|
|
25033
|
+
return false;
|
|
25034
|
+
}
|
|
25035
|
+
function scanGenericSecrets(text) {
|
|
25036
|
+
const hits = [];
|
|
25037
|
+
CANDIDATE_RE.lastIndex = 0;
|
|
25038
|
+
let m;
|
|
25039
|
+
while ((m = CANDIDATE_RE.exec(text)) !== null) {
|
|
25040
|
+
if (hits.length >= MAX_GENERIC_HITS)
|
|
25041
|
+
break;
|
|
25042
|
+
const tok = m[0];
|
|
25043
|
+
if (!hasDigit(tok))
|
|
25044
|
+
continue;
|
|
25045
|
+
if (!hasDistinctChars(tok, GENERIC_MIN_DISTINCT))
|
|
25046
|
+
continue;
|
|
25047
|
+
hits.push({
|
|
25048
|
+
rule_id: "generic_high_entropy",
|
|
25049
|
+
start: m.index,
|
|
25050
|
+
end: m.index + tok.length,
|
|
25051
|
+
matched_text: tok,
|
|
25052
|
+
confidence: "ambiguous"
|
|
25053
|
+
});
|
|
25054
|
+
}
|
|
25055
|
+
return hits;
|
|
25056
|
+
}
|
|
25057
|
+
var CANDIDATE_RE, GENERIC_MIN_DISTINCT = 18, MAX_GENERIC_HITS = 20;
|
|
25058
|
+
var init_generic_entropy = __esm(() => {
|
|
25059
|
+
CANDIDATE_RE = /[A-Za-z0-9]{28,}/g;
|
|
25060
|
+
});
|
|
25061
|
+
|
|
24981
25062
|
// secret-detect/chunker.ts
|
|
24982
25063
|
function chunk(text) {
|
|
24983
25064
|
if (text.length <= CHUNK_THRESHOLD) {
|
|
@@ -27070,6 +27151,10 @@ function detectSecrets(text) {
|
|
|
27070
27151
|
for (const h of kvHits) {
|
|
27071
27152
|
raw.push({ ...h, start: h.start + win.offset, end: h.end + win.offset });
|
|
27072
27153
|
}
|
|
27154
|
+
const genHits = scanGenericSecrets(win.text);
|
|
27155
|
+
for (const h of genHits) {
|
|
27156
|
+
raw.push({ ...h, start: h.start + win.offset, end: h.end + win.offset });
|
|
27157
|
+
}
|
|
27073
27158
|
}
|
|
27074
27159
|
const deduped = dedupeRaw(raw);
|
|
27075
27160
|
const final = dropOverlaps(deduped);
|
|
@@ -27108,19 +27193,14 @@ function dedupeRaw(raw) {
|
|
|
27108
27193
|
return Array.from(seen.values());
|
|
27109
27194
|
}
|
|
27110
27195
|
function dropOverlaps(hits) {
|
|
27111
|
-
const
|
|
27112
|
-
const out = [];
|
|
27113
|
-
for (const h of sorted) {
|
|
27114
|
-
const contained = out.some((existing) => existing !== h && existing.start <= h.start && existing.end >= h.end && !(existing.start === h.start && existing.end === h.end));
|
|
27115
|
-
if (!contained)
|
|
27116
|
-
out.push(h);
|
|
27117
|
-
}
|
|
27196
|
+
const out = hits.filter((h) => !(h.confidence === "ambiguous" && hits.some((o) => o !== h && o.start <= h.start && o.end >= h.end && !(o.start === h.start && o.end === h.end))));
|
|
27118
27197
|
out.sort((a, b) => a.start - b.start || a.end - b.end);
|
|
27119
27198
|
return out;
|
|
27120
27199
|
}
|
|
27121
27200
|
var init_secret_detect = __esm(() => {
|
|
27122
27201
|
init_patterns();
|
|
27123
27202
|
init_kv_scanner();
|
|
27203
|
+
init_generic_entropy();
|
|
27124
27204
|
init_chunker();
|
|
27125
27205
|
init_suppressor();
|
|
27126
27206
|
init_url_redact();
|
|
@@ -27132,7 +27212,7 @@ function redact(text) {
|
|
|
27132
27212
|
if (!text || text.length === 0)
|
|
27133
27213
|
return text;
|
|
27134
27214
|
const urlScrubbed = redactUrls(text);
|
|
27135
|
-
const hits = detectSecrets(urlScrubbed);
|
|
27215
|
+
const hits = detectSecrets(urlScrubbed).filter((h) => h.rule_id !== "generic_high_entropy");
|
|
27136
27216
|
if (hits.length === 0)
|
|
27137
27217
|
return urlScrubbed;
|
|
27138
27218
|
const sorted = [...hits].sort((a, b) => b.start - a.start);
|
|
@@ -30521,6 +30601,7 @@ var init_materialize_bot_token = __esm(() => {
|
|
|
30521
30601
|
var exports_tmux = {};
|
|
30522
30602
|
__export(exports_tmux, {
|
|
30523
30603
|
sendAgentInterrupt: () => sendAgentInterrupt,
|
|
30604
|
+
clearAgentComposer: () => clearAgentComposer,
|
|
30524
30605
|
captureAgentPane: () => captureAgentPane
|
|
30525
30606
|
});
|
|
30526
30607
|
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
@@ -30616,6 +30697,22 @@ function sendAgentInterrupt(opts) {
|
|
|
30616
30697
|
}
|
|
30617
30698
|
return { error: lastError ?? "tmux send-keys C-c failed" };
|
|
30618
30699
|
}
|
|
30700
|
+
function clearAgentComposer(opts) {
|
|
30701
|
+
const { agentName: agentName3 } = opts;
|
|
30702
|
+
const socket = `switchroom-${agentName3}`;
|
|
30703
|
+
const args = ["-L", socket, "send-keys", "-t", agentName3, "C-u", "C-a", "C-k"];
|
|
30704
|
+
try {
|
|
30705
|
+
execFileSync4("tmux", args, {
|
|
30706
|
+
timeout: 3000,
|
|
30707
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
30708
|
+
});
|
|
30709
|
+
return { ok: true };
|
|
30710
|
+
} catch (err) {
|
|
30711
|
+
const msg = `tmux send-keys composer-clear failed: ${err.message}`;
|
|
30712
|
+
console.error(`[tmux-composer-clear] ${agentName3}: ${msg}`);
|
|
30713
|
+
return { error: msg };
|
|
30714
|
+
}
|
|
30715
|
+
}
|
|
30619
30716
|
function sleepSync2(ms) {
|
|
30620
30717
|
const sab = new SharedArrayBuffer(4);
|
|
30621
30718
|
const view = new Int32Array(sab);
|
|
@@ -42495,6 +42592,15 @@ function isCompositeSilentNoise(text) {
|
|
|
42495
42592
|
return false;
|
|
42496
42593
|
return lines.every((l) => isSilentFlushMarker2(l) || isTrivialConfirmationLine(l));
|
|
42497
42594
|
}
|
|
42595
|
+
function endsWithSilentMarker(text) {
|
|
42596
|
+
if (typeof text !== "string")
|
|
42597
|
+
return false;
|
|
42598
|
+
const lines = text.split(`
|
|
42599
|
+
`).map((l) => l.trim()).filter((l) => l.length > 0);
|
|
42600
|
+
if (lines.length === 0)
|
|
42601
|
+
return false;
|
|
42602
|
+
return isSilentFlushMarker2(lines[lines.length - 1]);
|
|
42603
|
+
}
|
|
42498
42604
|
function decideTurnFlush(input) {
|
|
42499
42605
|
const flushEnabled = input.flushEnabled !== false;
|
|
42500
42606
|
if (!flushEnabled)
|
|
@@ -42511,6 +42617,8 @@ function decideTurnFlush(input) {
|
|
|
42511
42617
|
return { kind: "skip", reason: "silent-marker" };
|
|
42512
42618
|
if (isCompositeSilentNoise(joined))
|
|
42513
42619
|
return { kind: "skip", reason: "silent-marker" };
|
|
42620
|
+
if (endsWithSilentMarker(joined))
|
|
42621
|
+
return { kind: "skip", reason: "silent-marker" };
|
|
42514
42622
|
return { kind: "flush", text: joined };
|
|
42515
42623
|
}
|
|
42516
42624
|
function isTurnFlushSafetyEnabled(env = process.env) {
|
|
@@ -48810,6 +48918,7 @@ function recentDenialsFromAuditLog(rawAuditLog, opts) {
|
|
|
48810
48918
|
// secret-detect/index.ts
|
|
48811
48919
|
init_patterns();
|
|
48812
48920
|
init_kv_scanner();
|
|
48921
|
+
init_generic_entropy();
|
|
48813
48922
|
init_chunker();
|
|
48814
48923
|
init_suppressor();
|
|
48815
48924
|
init_url_redact();
|
|
@@ -48859,6 +48968,10 @@ function detectSecrets2(text) {
|
|
|
48859
48968
|
for (const h of kvHits) {
|
|
48860
48969
|
raw.push({ ...h, start: h.start + win.offset, end: h.end + win.offset });
|
|
48861
48970
|
}
|
|
48971
|
+
const genHits = scanGenericSecrets(win.text);
|
|
48972
|
+
for (const h of genHits) {
|
|
48973
|
+
raw.push({ ...h, start: h.start + win.offset, end: h.end + win.offset });
|
|
48974
|
+
}
|
|
48862
48975
|
}
|
|
48863
48976
|
const deduped = dedupeRaw2(raw);
|
|
48864
48977
|
const final = dropOverlaps2(deduped);
|
|
@@ -48897,13 +49010,7 @@ function dedupeRaw2(raw) {
|
|
|
48897
49010
|
return Array.from(seen.values());
|
|
48898
49011
|
}
|
|
48899
49012
|
function dropOverlaps2(hits) {
|
|
48900
|
-
const
|
|
48901
|
-
const out = [];
|
|
48902
|
-
for (const h of sorted) {
|
|
48903
|
-
const contained = out.some((existing) => existing !== h && existing.start <= h.start && existing.end >= h.end && !(existing.start === h.start && existing.end === h.end));
|
|
48904
|
-
if (!contained)
|
|
48905
|
-
out.push(h);
|
|
48906
|
-
}
|
|
49013
|
+
const out = hits.filter((h) => !(h.confidence === "ambiguous" && hits.some((o) => o !== h && o.start <= h.start && o.end >= h.end && !(o.start === h.start && o.end === h.end))));
|
|
48907
49014
|
out.sort((a, b) => a.start - b.start || a.end - b.end);
|
|
48908
49015
|
return out;
|
|
48909
49016
|
}
|
|
@@ -48916,7 +49023,7 @@ function redact2(text) {
|
|
|
48916
49023
|
if (!text || text.length === 0)
|
|
48917
49024
|
return text;
|
|
48918
49025
|
const urlScrubbed = redactUrls(text);
|
|
48919
|
-
const hits = detectSecrets(urlScrubbed);
|
|
49026
|
+
const hits = detectSecrets(urlScrubbed).filter((h) => h.rule_id !== "generic_high_entropy");
|
|
48920
49027
|
if (hits.length === 0)
|
|
48921
49028
|
return urlScrubbed;
|
|
48922
49029
|
const sorted = [...hits].sort((a, b) => b.start - a.start);
|
|
@@ -51659,10 +51766,10 @@ function sweepStaleTurnActiveMarker(stateDir, opts) {
|
|
|
51659
51766
|
}
|
|
51660
51767
|
|
|
51661
51768
|
// ../src/build-info.ts
|
|
51662
|
-
var VERSION = "0.14.
|
|
51663
|
-
var COMMIT_SHA = "
|
|
51664
|
-
var COMMIT_DATE = "2026-06-01T06:
|
|
51665
|
-
var LATEST_PR =
|
|
51769
|
+
var VERSION = "0.14.31";
|
|
51770
|
+
var COMMIT_SHA = "1aa03b91";
|
|
51771
|
+
var COMMIT_DATE = "2026-06-01T06:45:00Z";
|
|
51772
|
+
var LATEST_PR = 2060;
|
|
51666
51773
|
var COMMITS_AHEAD_OF_TAG = 0;
|
|
51667
51774
|
|
|
51668
51775
|
// gateway/boot-version.ts
|
|
@@ -57717,6 +57824,19 @@ ${preBlock(write.output)}`;
|
|
|
57717
57824
|
`);
|
|
57718
57825
|
return;
|
|
57719
57826
|
}
|
|
57827
|
+
if (selfAgent) {
|
|
57828
|
+
try {
|
|
57829
|
+
const { clearAgentComposer: clearAgentComposer2 } = await Promise.resolve().then(() => (init_tmux(), exports_tmux));
|
|
57830
|
+
const cleared = clearAgentComposer2({ agentName: selfAgent });
|
|
57831
|
+
if ("error" in cleared) {
|
|
57832
|
+
process.stderr.write(`telegram gateway: pre-send composer-clear soft-failed agent=${selfAgent}: ${cleared.error} \u2014 delivering anyway
|
|
57833
|
+
`);
|
|
57834
|
+
}
|
|
57835
|
+
} catch (err) {
|
|
57836
|
+
process.stderr.write(`telegram gateway: pre-send composer-clear threw agent=${selfAgent}: ${err.message} \u2014 delivering anyway
|
|
57837
|
+
`);
|
|
57838
|
+
}
|
|
57839
|
+
}
|
|
57720
57840
|
const delivered = ipcServer.sendToAgent(selfAgent, inboundMsg);
|
|
57721
57841
|
if (delivered)
|
|
57722
57842
|
markClaudeBusyForInbound(inboundMsg);
|
|
@@ -10515,6 +10515,33 @@ async function handleInbound(
|
|
|
10515
10515
|
return
|
|
10516
10516
|
}
|
|
10517
10517
|
|
|
10518
|
+
// Pre-send composer clear (the marko wedge). The inbound is about to be
|
|
10519
|
+
// delivered as an MCP `notifications/claude/channel` notification, which
|
|
10520
|
+
// the unmodified CLI appends into its composer and auto-submits ONLY when
|
|
10521
|
+
// the composer is empty + idle. The #1556 gate above guarantees idle, but
|
|
10522
|
+
// NOT empty: stale typed-ahead / ghost text stranded in the composer
|
|
10523
|
+
// (observed live on agent `marko`: "Yes, go ahead on both") makes the
|
|
10524
|
+
// appended inbound fail to submit and silently swallows every subsequent
|
|
10525
|
+
// queued inbound until a hard restart. Wipe the composer first so the
|
|
10526
|
+
// notification lands at a clean line. Soft-fail by contract — a clear
|
|
10527
|
+
// failure (no tmux session under legacy_pty, socket missing, timeout)
|
|
10528
|
+
// must NEVER block delivery; log and proceed.
|
|
10529
|
+
if (selfAgent) {
|
|
10530
|
+
try {
|
|
10531
|
+
const { clearAgentComposer } = await import('../../src/agents/tmux.js')
|
|
10532
|
+
const cleared = clearAgentComposer({ agentName: selfAgent })
|
|
10533
|
+
if ('error' in cleared) {
|
|
10534
|
+
process.stderr.write(
|
|
10535
|
+
`telegram gateway: pre-send composer-clear soft-failed agent=${selfAgent}: ${cleared.error} — delivering anyway\n`,
|
|
10536
|
+
)
|
|
10537
|
+
}
|
|
10538
|
+
} catch (err) {
|
|
10539
|
+
process.stderr.write(
|
|
10540
|
+
`telegram gateway: pre-send composer-clear threw agent=${selfAgent}: ${(err as Error).message} — delivering anyway\n`,
|
|
10541
|
+
)
|
|
10542
|
+
}
|
|
10543
|
+
}
|
|
10544
|
+
|
|
10518
10545
|
const delivered = ipcServer.sendToAgent(selfAgent, inboundMsg)
|
|
10519
10546
|
if (delivered) markClaudeBusyForInbound(inboundMsg)
|
|
10520
10547
|
if (!delivered) {
|