switchroom 0.14.26 → 0.14.28
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 +20 -4
- package/dist/host-control/main.js +2 -2
- package/package.json +1 -1
- package/telegram-plugin/bridge/bridge.ts +15 -0
- package/telegram-plugin/card-format.ts +65 -0
- package/telegram-plugin/dist/bridge/bridge.js +14 -0
- package/telegram-plugin/dist/gateway/gateway.js +2201 -1748
- package/telegram-plugin/dist/server.js +14 -0
- package/telegram-plugin/gateway/gateway.ts +458 -13
- package/telegram-plugin/gateway/worker-feed-dispatch.ts +1 -1
- package/telegram-plugin/history.ts +16 -4
- package/telegram-plugin/permission-title.ts +48 -0
- package/telegram-plugin/secret-detect/patterns.ts +8 -0
- package/telegram-plugin/secret-detect/redact.ts +76 -0
- package/telegram-plugin/tests/card-format.test.ts +96 -0
- package/telegram-plugin/tests/gateway-outbound-redact.test.ts +80 -0
- package/telegram-plugin/tests/gateway-request-secret.test.ts +78 -0
- package/telegram-plugin/tests/history.test.ts +59 -0
- package/telegram-plugin/tests/permission-title.test.ts +68 -0
- package/telegram-plugin/tests/permission-verdict-resume-guard.test.ts +35 -0
- package/telegram-plugin/tests/secret-detect-sanctum.test.ts +115 -0
- package/telegram-plugin/tests/worker-activity-feed.test.ts +110 -51
- package/telegram-plugin/uat/assertions.ts +8 -6
- package/telegram-plugin/uat/feed-matcher.test.ts +14 -8
- package/telegram-plugin/uat/scenarios/jtbd-request-secret-dm.test.ts +101 -0
- package/telegram-plugin/uat/scenarios/jtbd-worker-activity-feed-dm.test.ts +17 -6
- package/telegram-plugin/worker-activity-feed.ts +84 -46
|
@@ -6549,6 +6549,43 @@ function escapeHtml(s) {
|
|
|
6549
6549
|
function truncate(s, n) {
|
|
6550
6550
|
return s.length > n ? s.slice(0, n - 1) + "\u2026" : s;
|
|
6551
6551
|
}
|
|
6552
|
+
function stripMarkdown(s) {
|
|
6553
|
+
let out = s;
|
|
6554
|
+
out = out.replace(/`+/g, "");
|
|
6555
|
+
out = out.replace(/!?\[([^\]]*)\]\([^)]*\)/g, "$1");
|
|
6556
|
+
out = out.replace(/\*\*(.+?)\*\*/g, "$1");
|
|
6557
|
+
out = out.replace(/__(.+?)__/g, "$1");
|
|
6558
|
+
out = out.replace(/\*(.+?)\*/g, "$1");
|
|
6559
|
+
out = out.replace(/(?<![A-Za-z0-9])_(.+?)_(?![A-Za-z0-9])/g, "$1");
|
|
6560
|
+
out = out.replace(/^\s{0,3}#{1,6}\s+/gm, "");
|
|
6561
|
+
out = out.replace(/^\s{0,3}>\s?/gm, "");
|
|
6562
|
+
out = out.replace(/^\s{0,3}[-*+]\s+/gm, "");
|
|
6563
|
+
out = out.replace(/^\s{0,3}\d+[.)]\s+/gm, "");
|
|
6564
|
+
out = out.replace(/\*\*/g, "");
|
|
6565
|
+
return out.trim();
|
|
6566
|
+
}
|
|
6567
|
+
function isRuleLine(s) {
|
|
6568
|
+
return /^\s*([-_*])\1{2,}\s*$/.test(s);
|
|
6569
|
+
}
|
|
6570
|
+
function cleanWorkerResultParagraph(s) {
|
|
6571
|
+
const kept = [];
|
|
6572
|
+
let inFence = false;
|
|
6573
|
+
for (const raw of s.split(`
|
|
6574
|
+
`)) {
|
|
6575
|
+
if (/^\s*```/.test(raw)) {
|
|
6576
|
+
inFence = !inFence;
|
|
6577
|
+
continue;
|
|
6578
|
+
}
|
|
6579
|
+
if (inFence)
|
|
6580
|
+
continue;
|
|
6581
|
+
if (isRuleLine(raw))
|
|
6582
|
+
continue;
|
|
6583
|
+
const cleaned = stripMarkdown(raw);
|
|
6584
|
+
if (cleaned.length > 0)
|
|
6585
|
+
kept.push(cleaned);
|
|
6586
|
+
}
|
|
6587
|
+
return kept.join(" ").replace(/\s+/g, " ").trim();
|
|
6588
|
+
}
|
|
6552
6589
|
|
|
6553
6590
|
// ../node_modules/.bun/@grammyjs+runner@2.0.3+c6be0243b1bbec89/node_modules/@grammyjs/runner/out/mod.js
|
|
6554
6591
|
var require_mod4 = __commonJS((exports) => {
|
|
@@ -24829,1269 +24866,380 @@ var init_loader = __esm(() => {
|
|
|
24829
24866
|
};
|
|
24830
24867
|
});
|
|
24831
24868
|
|
|
24832
|
-
//
|
|
24833
|
-
var
|
|
24834
|
-
|
|
24835
|
-
|
|
24836
|
-
|
|
24837
|
-
|
|
24838
|
-
|
|
24839
|
-
|
|
24840
|
-
|
|
24841
|
-
|
|
24842
|
-
|
|
24843
|
-
|
|
24844
|
-
|
|
24845
|
-
|
|
24846
|
-
|
|
24847
|
-
|
|
24848
|
-
})
|
|
24849
|
-
|
|
24850
|
-
|
|
24851
|
-
|
|
24852
|
-
|
|
24853
|
-
|
|
24854
|
-
|
|
24855
|
-
|
|
24856
|
-
|
|
24857
|
-
|
|
24858
|
-
|
|
24859
|
-
|
|
24860
|
-
|
|
24861
|
-
|
|
24862
|
-
|
|
24863
|
-
|
|
24864
|
-
|
|
24865
|
-
|
|
24866
|
-
|
|
24867
|
-
|
|
24868
|
-
|
|
24869
|
-
|
|
24870
|
-
|
|
24871
|
-
|
|
24872
|
-
|
|
24873
|
-
|
|
24874
|
-
|
|
24875
|
-
|
|
24876
|
-
|
|
24877
|
-
|
|
24878
|
-
|
|
24879
|
-
|
|
24880
|
-
|
|
24881
|
-
|
|
24882
|
-
|
|
24883
|
-
|
|
24884
|
-
|
|
24885
|
-
|
|
24886
|
-
|
|
24887
|
-
|
|
24888
|
-
|
|
24889
|
-
reply_to_message_id INTEGER,
|
|
24890
|
-
reply_to_text TEXT,
|
|
24891
|
-
PRIMARY KEY (chat_id, thread_id, message_id)
|
|
24892
|
-
)
|
|
24893
|
-
`);
|
|
24894
|
-
db.exec(`
|
|
24895
|
-
CREATE INDEX IF NOT EXISTS idx_messages_recent
|
|
24896
|
-
ON messages (chat_id, thread_id, ts DESC)
|
|
24897
|
-
`);
|
|
24898
|
-
for (const column of ["reply_to_message_id INTEGER", "reply_to_text TEXT", "user_reaction TEXT"]) {
|
|
24899
|
-
try {
|
|
24900
|
-
db.exec(`ALTER TABLE messages ADD COLUMN ${column}`);
|
|
24901
|
-
} catch (err) {
|
|
24902
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
24903
|
-
if (!/duplicate column name/i.test(msg))
|
|
24904
|
-
throw err;
|
|
24869
|
+
// secret-detect/patterns.ts
|
|
24870
|
+
var ANCHORED_PATTERNS, STRUCTURED_PATTERNS, ALL_PATTERNS;
|
|
24871
|
+
var init_patterns = __esm(() => {
|
|
24872
|
+
ANCHORED_PATTERNS = [
|
|
24873
|
+
{ rule_id: "anthropic_api_key", regex: /\b(sk-ant-[A-Za-z0-9_-]{8,})\b/g, captureIndex: 1, slugHint: "anthropic_api_key" },
|
|
24874
|
+
{ rule_id: "anthropic_oauth_code", regex: /(?:^|\s)([A-Za-z0-9_-]{20,}#[A-Za-z0-9_-]{20,})(?=\s|$)/gm, captureIndex: 1, slugHint: "anthropic_oauth_code" },
|
|
24875
|
+
{ rule_id: "openai_api_key", regex: /\b(sk-[A-Za-z0-9_-]{20,})\b/g, captureIndex: 1, slugHint: "openai_api_key" },
|
|
24876
|
+
{ rule_id: "github_pat_classic", regex: /\b(ghp_[A-Za-z0-9]{20,})\b/g, captureIndex: 1, slugHint: "github_pat" },
|
|
24877
|
+
{ rule_id: "github_pat_fine_grained", regex: /\b(github_pat_[A-Za-z0-9_]{20,})\b/g, captureIndex: 1, slugHint: "github_pat" },
|
|
24878
|
+
{ rule_id: "slack_token", regex: /\b(xox[baprs]-[A-Za-z0-9-]{10,})\b/g, captureIndex: 1, slugHint: "slack_token" },
|
|
24879
|
+
{ rule_id: "slack_app_token", regex: /\b(xapp-[A-Za-z0-9-]{10,})\b/g, captureIndex: 1, slugHint: "slack_app_token" },
|
|
24880
|
+
{ rule_id: "groq_api_key", regex: /\b(gsk_[A-Za-z0-9_-]{10,})\b/g, captureIndex: 1, slugHint: "groq_api_key" },
|
|
24881
|
+
{ rule_id: "google_api_key", regex: /\b(AIza[0-9A-Za-z\-_]{20,})\b/g, captureIndex: 1, slugHint: "google_api_key" },
|
|
24882
|
+
{ rule_id: "perplexity_api_key", regex: /\b(pplx-[A-Za-z0-9_-]{10,})\b/g, captureIndex: 1, slugHint: "perplexity_api_key" },
|
|
24883
|
+
{ rule_id: "npm_token", regex: /\b(npm_[A-Za-z0-9]{10,})\b/g, captureIndex: 1, slugHint: "npm_token" },
|
|
24884
|
+
{ rule_id: "telegram_bot_token_prefixed", regex: /\bbot(\d{6,}:[A-Za-z0-9_-]{20,})\b/g, captureIndex: 1, slugHint: "telegram_bot_token" },
|
|
24885
|
+
{ rule_id: "telegram_bot_token", regex: /\b(\d{6,}:[A-Za-z0-9_-]{20,})\b/g, captureIndex: 1, slugHint: "telegram_bot_token" },
|
|
24886
|
+
{ rule_id: "laravel_sanctum_token", regex: /\b(\d+\|[A-Za-z0-9]{40,})\b/g, captureIndex: 1, slugHint: "api_token" },
|
|
24887
|
+
{ rule_id: "aws_access_key", regex: /\b(AKIA[0-9A-Z]{16})\b/g, captureIndex: 1, slugHint: "aws_access_key" },
|
|
24888
|
+
{ rule_id: "jwt", regex: /\b(eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,})\b/g, captureIndex: 1, slugHint: "jwt" }
|
|
24889
|
+
];
|
|
24890
|
+
STRUCTURED_PATTERNS = [
|
|
24891
|
+
{
|
|
24892
|
+
rule_id: "env_key_value",
|
|
24893
|
+
regex: /\b([A-Z0-9_]*(?:KEY|TOKEN|SECRET|PASSWORD|PASSWD))\b\s*[=:]\s*(["']?)([^\s"'\\]+)\2/g,
|
|
24894
|
+
captureIndex: 3,
|
|
24895
|
+
slugHint: "env"
|
|
24896
|
+
},
|
|
24897
|
+
{
|
|
24898
|
+
rule_id: "json_secret_field",
|
|
24899
|
+
regex: /"(?:apiKey|token|secret|password|passwd|accessToken|refreshToken)"\s*:\s*"([^"]+)"/g,
|
|
24900
|
+
captureIndex: 1,
|
|
24901
|
+
slugHint: "json_secret"
|
|
24902
|
+
},
|
|
24903
|
+
{
|
|
24904
|
+
rule_id: "cli_flag",
|
|
24905
|
+
regex: /--(?:api[-_]?key|hook[-_]?token|token|secret|password|passwd)\s+(["']?)([^\s"']+)\1/g,
|
|
24906
|
+
captureIndex: 2,
|
|
24907
|
+
slugHint: "cli_flag"
|
|
24908
|
+
},
|
|
24909
|
+
{
|
|
24910
|
+
rule_id: "bearer_auth_header",
|
|
24911
|
+
regex: /Authorization\s*[:=]\s*Bearer\s+([A-Za-z0-9._\-+=]+)/g,
|
|
24912
|
+
captureIndex: 1,
|
|
24913
|
+
slugHint: "bearer_token"
|
|
24914
|
+
},
|
|
24915
|
+
{
|
|
24916
|
+
rule_id: "bearer_loose",
|
|
24917
|
+
regex: /\bBearer\s+([A-Za-z0-9._\-+=]{18,})\b/g,
|
|
24918
|
+
captureIndex: 1,
|
|
24919
|
+
slugHint: "bearer_token"
|
|
24920
|
+
},
|
|
24921
|
+
{
|
|
24922
|
+
rule_id: "pem_private_key",
|
|
24923
|
+
regex: /-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]+?-----END [A-Z ]*PRIVATE KEY-----/g,
|
|
24924
|
+
captureIndex: 0,
|
|
24925
|
+
slugHint: "pem_private_key"
|
|
24905
24926
|
}
|
|
24927
|
+
];
|
|
24928
|
+
ALL_PATTERNS = [...ANCHORED_PATTERNS, ...STRUCTURED_PATTERNS];
|
|
24929
|
+
});
|
|
24930
|
+
|
|
24931
|
+
// secret-detect/entropy.ts
|
|
24932
|
+
function shannonEntropy(s) {
|
|
24933
|
+
if (s.length === 0)
|
|
24934
|
+
return 0;
|
|
24935
|
+
const counts = new Map;
|
|
24936
|
+
for (const ch of s) {
|
|
24937
|
+
counts.set(ch, (counts.get(ch) ?? 0) + 1);
|
|
24906
24938
|
}
|
|
24907
|
-
|
|
24908
|
-
|
|
24909
|
-
|
|
24910
|
-
|
|
24911
|
-
|
|
24912
|
-
db.prepare("DELETE FROM messages WHERE ts < ?").run(cutoff);
|
|
24939
|
+
let h = 0;
|
|
24940
|
+
const len = s.length;
|
|
24941
|
+
for (const c of counts.values()) {
|
|
24942
|
+
const p = c / len;
|
|
24943
|
+
h -= p * Math.log2(p);
|
|
24913
24944
|
}
|
|
24945
|
+
return h;
|
|
24914
24946
|
}
|
|
24915
|
-
|
|
24916
|
-
|
|
24917
|
-
|
|
24918
|
-
|
|
24947
|
+
|
|
24948
|
+
// secret-detect/kv-scanner.ts
|
|
24949
|
+
function scanKeyValue(text) {
|
|
24950
|
+
const hits = [];
|
|
24951
|
+
KV_RE.lastIndex = 0;
|
|
24952
|
+
let m;
|
|
24953
|
+
while ((m = KV_RE.exec(text)) !== null) {
|
|
24954
|
+
const [, keyName, value] = m;
|
|
24955
|
+
if (!value)
|
|
24956
|
+
continue;
|
|
24957
|
+
const h = shannonEntropy(value);
|
|
24958
|
+
if (h < KV_ENTROPY_THRESHOLD)
|
|
24959
|
+
continue;
|
|
24960
|
+
const valueOffsetInMatch = m[0].indexOf(value, keyName.length);
|
|
24961
|
+
if (valueOffsetInMatch < 0)
|
|
24962
|
+
continue;
|
|
24963
|
+
const start = m.index + valueOffsetInMatch;
|
|
24964
|
+
const end = start + value.length;
|
|
24965
|
+
hits.push({
|
|
24966
|
+
rule_id: "kv_entropy",
|
|
24967
|
+
start,
|
|
24968
|
+
end,
|
|
24969
|
+
matched_text: value,
|
|
24970
|
+
key_name: keyName,
|
|
24971
|
+
confidence: "ambiguous"
|
|
24972
|
+
});
|
|
24919
24973
|
}
|
|
24974
|
+
return hits;
|
|
24920
24975
|
}
|
|
24921
|
-
|
|
24922
|
-
|
|
24923
|
-
|
|
24924
|
-
|
|
24925
|
-
|
|
24926
|
-
|
|
24927
|
-
|
|
24928
|
-
|
|
24976
|
+
var KV_RE, KV_ENTROPY_THRESHOLD = 4;
|
|
24977
|
+
var init_kv_scanner = __esm(() => {
|
|
24978
|
+
KV_RE = /\b([A-Za-z_][A-Za-z0-9_-]*(?:password|passwd|token|secret|key|api[_-]?key))\s*[:=]\s*["']?([^\s"'\\]{8,})["']?/gi;
|
|
24979
|
+
});
|
|
24980
|
+
|
|
24981
|
+
// secret-detect/chunker.ts
|
|
24982
|
+
function chunk(text) {
|
|
24983
|
+
if (text.length <= CHUNK_THRESHOLD) {
|
|
24984
|
+
return [{ offset: 0, text }];
|
|
24929
24985
|
}
|
|
24930
|
-
|
|
24931
|
-
|
|
24932
|
-
|
|
24933
|
-
|
|
24934
|
-
|
|
24935
|
-
|
|
24936
|
-
const cutoffSec = (nowSec ?? Math.floor(Date.now() / 1000)) - retentionDays * 86400;
|
|
24937
|
-
const stmt = db.prepare(`
|
|
24938
|
-
DELETE FROM messages
|
|
24939
|
-
WHERE rowid IN (
|
|
24940
|
-
SELECT rowid FROM messages WHERE ts < ? LIMIT ?
|
|
24941
|
-
)
|
|
24942
|
-
`);
|
|
24943
|
-
let total = 0;
|
|
24944
|
-
for (let i = 0;i < 1000; i++) {
|
|
24945
|
-
const result = stmt.run(cutoffSec, batchLimit);
|
|
24946
|
-
const n = result.changes ?? 0;
|
|
24947
|
-
total += n;
|
|
24948
|
-
if (n === 0)
|
|
24986
|
+
const out = [];
|
|
24987
|
+
let offset = 0;
|
|
24988
|
+
while (offset < text.length) {
|
|
24989
|
+
const end = Math.min(offset + WINDOW_SIZE, text.length);
|
|
24990
|
+
out.push({ offset, text: text.slice(offset, end) });
|
|
24991
|
+
if (end >= text.length)
|
|
24949
24992
|
break;
|
|
24993
|
+
offset = end - OVERLAP;
|
|
24950
24994
|
}
|
|
24951
|
-
return
|
|
24952
|
-
}
|
|
24953
|
-
function requireDb() {
|
|
24954
|
-
if (db == null) {
|
|
24955
|
-
throw new Error("history: initHistory() must be called before any record/query operation");
|
|
24956
|
-
}
|
|
24957
|
-
return db;
|
|
24958
|
-
}
|
|
24959
|
-
function recordInbound(args) {
|
|
24960
|
-
if (args.message_id == null)
|
|
24961
|
-
return;
|
|
24962
|
-
const stmt = requireDb().prepare(`
|
|
24963
|
-
INSERT OR REPLACE INTO messages
|
|
24964
|
-
(chat_id, thread_id, message_id, role, user, user_id, ts, text, attachment_kind, group_id, reply_to_message_id, reply_to_text)
|
|
24965
|
-
VALUES (?, ?, ?, 'user', ?, ?, ?, ?, ?, NULL, ?, ?)
|
|
24966
|
-
`);
|
|
24967
|
-
stmt.run(args.chat_id, args.thread_id ?? null, args.message_id, args.user ?? null, args.user_id ?? null, args.ts, args.text, args.attachment_kind ?? null, args.reply_to_message_id ?? null, args.reply_to_text ?? null);
|
|
24968
|
-
}
|
|
24969
|
-
function recordOutbound(args) {
|
|
24970
|
-
if (args.message_ids.length === 0)
|
|
24971
|
-
return;
|
|
24972
|
-
const ts = args.ts ?? Math.floor(Date.now() / 1000);
|
|
24973
|
-
const groupId = args.message_ids[0];
|
|
24974
|
-
const stmt = requireDb().prepare(`
|
|
24975
|
-
INSERT OR REPLACE INTO messages
|
|
24976
|
-
(chat_id, thread_id, message_id, role, user, user_id, ts, text, attachment_kind, group_id)
|
|
24977
|
-
VALUES (?, ?, ?, 'assistant', NULL, NULL, ?, ?, ?, ?)
|
|
24978
|
-
`);
|
|
24979
|
-
const tx = requireDb().transaction((rows2) => {
|
|
24980
|
-
for (const [msgId, text, attachKind] of rows2) {
|
|
24981
|
-
stmt.run(args.chat_id, args.thread_id ?? null, msgId, ts, text, attachKind, groupId);
|
|
24982
|
-
}
|
|
24983
|
-
});
|
|
24984
|
-
const rows = args.message_ids.map((id, i) => [
|
|
24985
|
-
id,
|
|
24986
|
-
args.texts[i] ?? "",
|
|
24987
|
-
args.attachment_kinds?.[i] ?? null
|
|
24988
|
-
]);
|
|
24989
|
-
tx(rows);
|
|
24995
|
+
return out;
|
|
24990
24996
|
}
|
|
24991
|
-
|
|
24992
|
-
|
|
24993
|
-
|
|
24994
|
-
|
|
24995
|
-
|
|
24996
|
-
|
|
24997
|
+
var CHUNK_THRESHOLD, WINDOW_SIZE, OVERLAP = 1024;
|
|
24998
|
+
var init_chunker = __esm(() => {
|
|
24999
|
+
CHUNK_THRESHOLD = 32 * 1024;
|
|
25000
|
+
WINDOW_SIZE = 16 * 1024;
|
|
25001
|
+
});
|
|
25002
|
+
|
|
25003
|
+
// secret-detect/suppressor.ts
|
|
25004
|
+
function isSuppressed(text, start, end) {
|
|
25005
|
+
const left = Math.max(0, start - WINDOW);
|
|
25006
|
+
const right = Math.min(text.length, end + WINDOW);
|
|
25007
|
+
const context = text.slice(left, start) + text.slice(end, right);
|
|
25008
|
+
return MARKER_RE.test(context);
|
|
24997
25009
|
}
|
|
24998
|
-
|
|
24999
|
-
|
|
25000
|
-
|
|
25001
|
-
|
|
25002
|
-
|
|
25003
|
-
|
|
25010
|
+
var MARKERS, WINDOW = 40, MARKER_RE;
|
|
25011
|
+
var init_suppressor = __esm(() => {
|
|
25012
|
+
MARKERS = ["test", "mock", "example", "fixture", "dummy"];
|
|
25013
|
+
MARKER_RE = new RegExp(`\\b(?:${MARKERS.join("|")})\\b`, "i");
|
|
25014
|
+
});
|
|
25015
|
+
|
|
25016
|
+
// secret-detect/slug.ts
|
|
25017
|
+
function sanitizeKeyName(raw) {
|
|
25018
|
+
const up = raw.toUpperCase();
|
|
25019
|
+
const cleaned = up.replace(/[^A-Z0-9_]+/g, "_").replace(/_+/g, "_").replace(/^_+|_+$/g, "");
|
|
25020
|
+
return cleaned.length > 0 ? cleaned : "SECRET";
|
|
25004
25021
|
}
|
|
25005
|
-
function
|
|
25006
|
-
|
|
25007
|
-
|
|
25008
|
-
|
|
25009
|
-
|
|
25022
|
+
function datePart(now = new Date) {
|
|
25023
|
+
const y = now.getUTCFullYear();
|
|
25024
|
+
const m = String(now.getUTCMonth() + 1).padStart(2, "0");
|
|
25025
|
+
const d = String(now.getUTCDate()).padStart(2, "0");
|
|
25026
|
+
return `${y}${m}${d}`;
|
|
25010
25027
|
}
|
|
25011
|
-
function
|
|
25012
|
-
|
|
25013
|
-
|
|
25014
|
-
|
|
25015
|
-
|
|
25016
|
-
|
|
25017
|
-
} else {
|
|
25018
|
-
sql += " AND thread_id = ?";
|
|
25019
|
-
params.push(threadId);
|
|
25020
|
-
}
|
|
25028
|
+
function deriveSlug(inputs, existing) {
|
|
25029
|
+
let base;
|
|
25030
|
+
if (inputs.key_name && inputs.key_name.trim().length > 0) {
|
|
25031
|
+
base = sanitizeKeyName(inputs.key_name);
|
|
25032
|
+
} else {
|
|
25033
|
+
base = `${inputs.rule_id}_${datePart(inputs.now)}`;
|
|
25021
25034
|
}
|
|
25022
|
-
|
|
25023
|
-
|
|
25024
|
-
|
|
25025
|
-
}
|
|
25026
|
-
|
|
25027
|
-
|
|
25028
|
-
if (!row)
|
|
25029
|
-
return null;
|
|
25030
|
-
return { role: row.role, text: row.text ?? "" };
|
|
25031
|
-
}
|
|
25032
|
-
function getRecentOutboundCount(chatId, withinSeconds) {
|
|
25033
|
-
const cutoff = Math.floor(Date.now() / 1000) - withinSeconds;
|
|
25034
|
-
const row = requireDb().prepare("SELECT COUNT(*) as cnt FROM messages WHERE chat_id = ? AND role = ? AND ts >= ?").get(chatId, "assistant", cutoff);
|
|
25035
|
-
return row?.cnt ?? 0;
|
|
25035
|
+
if (!existing.has(base))
|
|
25036
|
+
return base;
|
|
25037
|
+
let n = 2;
|
|
25038
|
+
while (existing.has(`${base}_${n}`))
|
|
25039
|
+
n++;
|
|
25040
|
+
return `${base}_${n}`;
|
|
25036
25041
|
}
|
|
25037
|
-
|
|
25038
|
-
|
|
25039
|
-
|
|
25040
|
-
|
|
25041
|
-
|
|
25042
|
-
if (opts.thread_id === null) {
|
|
25043
|
-
sql += " AND thread_id IS NULL";
|
|
25044
|
-
} else {
|
|
25045
|
-
sql += " AND thread_id = ?";
|
|
25046
|
-
params.push(opts.thread_id);
|
|
25047
|
-
}
|
|
25048
|
-
}
|
|
25049
|
-
if (opts.before_message_id != null) {
|
|
25050
|
-
sql += " AND message_id < ?";
|
|
25051
|
-
params.push(opts.before_message_id);
|
|
25042
|
+
|
|
25043
|
+
// secret-detect/mask.ts
|
|
25044
|
+
function maskToken(s) {
|
|
25045
|
+
if (s.length >= 18) {
|
|
25046
|
+
return `${s.slice(0, 6)}...${s.slice(-4)}`;
|
|
25052
25047
|
}
|
|
25053
|
-
|
|
25054
|
-
params.push(limit);
|
|
25055
|
-
const rows = requireDb().prepare(sql).all(...params);
|
|
25056
|
-
rows.reverse();
|
|
25057
|
-
return rows;
|
|
25048
|
+
return "***";
|
|
25058
25049
|
}
|
|
25059
|
-
var DatabaseClass = null, DEFAULT_LIMIT = 10, MAX_LIMIT = 50, db = null;
|
|
25060
|
-
var init_history = () => {};
|
|
25061
25050
|
|
|
25062
|
-
//
|
|
25063
|
-
|
|
25064
|
-
|
|
25065
|
-
|
|
25066
|
-
|
|
25067
|
-
|
|
25068
|
-
|
|
25051
|
+
// secret-detect/url-redact.ts
|
|
25052
|
+
function redactUrls(text) {
|
|
25053
|
+
return text.replace(URL_RE, (m) => {
|
|
25054
|
+
const redacted = redactOne(m);
|
|
25055
|
+
return redacted ?? m;
|
|
25056
|
+
});
|
|
25057
|
+
}
|
|
25058
|
+
function redactOne(raw) {
|
|
25059
|
+
let u;
|
|
25069
25060
|
try {
|
|
25070
|
-
|
|
25071
|
-
return raw.length > 0 ? raw : null;
|
|
25061
|
+
u = new URL(raw);
|
|
25072
25062
|
} catch {
|
|
25073
25063
|
return null;
|
|
25074
25064
|
}
|
|
25075
|
-
|
|
25076
|
-
|
|
25077
|
-
|
|
25078
|
-
|
|
25079
|
-
|
|
25080
|
-
|
|
25081
|
-
|
|
25082
|
-
|
|
25083
|
-
|
|
25084
|
-
|
|
25085
|
-
if (v == null)
|
|
25086
|
-
return null;
|
|
25087
|
-
const n = Number(v);
|
|
25088
|
-
if (!Number.isFinite(n) || n <= 0)
|
|
25089
|
-
return null;
|
|
25090
|
-
return new Date(n * 1000);
|
|
25091
|
-
}
|
|
25092
|
-
function parseQuotaHeaders(headers) {
|
|
25093
|
-
const fiveHour = parseFloatHeader(headers, "anthropic-ratelimit-unified-5h-utilization");
|
|
25094
|
-
const sevenDay = parseFloatHeader(headers, "anthropic-ratelimit-unified-7d-utilization");
|
|
25095
|
-
if (fiveHour == null && sevenDay == null) {
|
|
25096
|
-
return {
|
|
25097
|
-
ok: false,
|
|
25098
|
-
reason: "no unified rate-limit headers in response (API token, not OAuth?)"
|
|
25099
|
-
};
|
|
25100
|
-
}
|
|
25101
|
-
return {
|
|
25102
|
-
ok: true,
|
|
25103
|
-
data: {
|
|
25104
|
-
fiveHourUtilizationPct: (fiveHour ?? 0) * 100,
|
|
25105
|
-
sevenDayUtilizationPct: (sevenDay ?? 0) * 100,
|
|
25106
|
-
fiveHourResetAt: parseEpochHeader(headers, "anthropic-ratelimit-unified-5h-reset"),
|
|
25107
|
-
sevenDayResetAt: parseEpochHeader(headers, "anthropic-ratelimit-unified-7d-reset"),
|
|
25108
|
-
representativeClaim: headers.get("anthropic-ratelimit-unified-representative-claim"),
|
|
25109
|
-
overageStatus: headers.get("anthropic-ratelimit-unified-overage-status"),
|
|
25110
|
-
overageDisabledReason: headers.get("anthropic-ratelimit-unified-overage-disabled-reason")
|
|
25065
|
+
let changed = false;
|
|
25066
|
+
if (u.username || u.password) {
|
|
25067
|
+
u.username = "***";
|
|
25068
|
+
u.password = "";
|
|
25069
|
+
changed = true;
|
|
25070
|
+
}
|
|
25071
|
+
for (const [key] of u.searchParams) {
|
|
25072
|
+
if (SENSITIVE_PARAMS.has(key.toLowerCase())) {
|
|
25073
|
+
u.searchParams.set(key, "***");
|
|
25074
|
+
changed = true;
|
|
25111
25075
|
}
|
|
25112
|
-
};
|
|
25113
|
-
}
|
|
25114
|
-
async function fetchQuota(opts) {
|
|
25115
|
-
let token;
|
|
25116
|
-
if (opts.accessToken && opts.claudeConfigDir) {
|
|
25117
|
-
return {
|
|
25118
|
-
ok: false,
|
|
25119
|
-
reason: "pass only one of `accessToken` or `claudeConfigDir`, not both"
|
|
25120
|
-
};
|
|
25121
|
-
}
|
|
25122
|
-
if (opts.accessToken) {
|
|
25123
|
-
token = opts.accessToken.trim().length > 0 ? opts.accessToken : null;
|
|
25124
|
-
} else if (opts.claudeConfigDir) {
|
|
25125
|
-
token = readOauthToken(opts.claudeConfigDir);
|
|
25126
|
-
} else {
|
|
25127
|
-
return {
|
|
25128
|
-
ok: false,
|
|
25129
|
-
reason: "fetchQuota requires `accessToken` or `claudeConfigDir`"
|
|
25130
|
-
};
|
|
25131
25076
|
}
|
|
25132
|
-
|
|
25133
|
-
|
|
25077
|
+
return changed ? u.toString() : null;
|
|
25078
|
+
}
|
|
25079
|
+
var SENSITIVE_PARAMS, URL_RE;
|
|
25080
|
+
var init_url_redact = __esm(() => {
|
|
25081
|
+
SENSITIVE_PARAMS = new Set([
|
|
25082
|
+
"token",
|
|
25083
|
+
"key",
|
|
25084
|
+
"api_key",
|
|
25085
|
+
"apikey",
|
|
25086
|
+
"secret",
|
|
25087
|
+
"access_token",
|
|
25088
|
+
"password",
|
|
25089
|
+
"pass",
|
|
25090
|
+
"auth",
|
|
25091
|
+
"client_secret",
|
|
25092
|
+
"refresh_token",
|
|
25093
|
+
"signature"
|
|
25094
|
+
]);
|
|
25095
|
+
URL_RE = /\b(?:https?|wss?|ftp):\/\/[^\s<>"']+/gi;
|
|
25096
|
+
});
|
|
25097
|
+
|
|
25098
|
+
// ../node_modules/.bun/boundary@2.0.0/node_modules/boundary/lib/index.js
|
|
25099
|
+
var require_lib = __commonJS((exports2) => {
|
|
25100
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
25101
|
+
exports2.binarySearch = exports2.upperBound = exports2.lowerBound = exports2.compare = undefined;
|
|
25102
|
+
function compare(v1, v2) {
|
|
25103
|
+
return v1 < v2;
|
|
25134
25104
|
}
|
|
25135
|
-
|
|
25136
|
-
|
|
25137
|
-
|
|
25138
|
-
|
|
25139
|
-
|
|
25140
|
-
|
|
25141
|
-
|
|
25142
|
-
|
|
25143
|
-
|
|
25144
|
-
|
|
25145
|
-
|
|
25146
|
-
|
|
25147
|
-
|
|
25148
|
-
|
|
25149
|
-
|
|
25150
|
-
body: JSON.stringify({
|
|
25151
|
-
model: opts.model ?? DEFAULT_PROBE_MODEL,
|
|
25152
|
-
max_tokens: 1,
|
|
25153
|
-
messages: [{ role: "user", content: "hi" }]
|
|
25154
|
-
}),
|
|
25155
|
-
signal: controller.signal
|
|
25156
|
-
});
|
|
25157
|
-
} catch (err) {
|
|
25158
|
-
const msg = err?.message ?? String(err);
|
|
25159
|
-
return { ok: false, reason: `request failed: ${msg}` };
|
|
25160
|
-
} finally {
|
|
25161
|
-
clearTimeout(timeout);
|
|
25105
|
+
exports2.compare = compare;
|
|
25106
|
+
function upperBound(array, value, comp = compare) {
|
|
25107
|
+
let len = array.length;
|
|
25108
|
+
let i = 0;
|
|
25109
|
+
while (len) {
|
|
25110
|
+
let diff = len >>> 1;
|
|
25111
|
+
let cursor = i + diff;
|
|
25112
|
+
if (comp(value, array[cursor])) {
|
|
25113
|
+
len = diff;
|
|
25114
|
+
} else {
|
|
25115
|
+
i = cursor + 1;
|
|
25116
|
+
len -= diff + 1;
|
|
25117
|
+
}
|
|
25118
|
+
}
|
|
25119
|
+
return i;
|
|
25162
25120
|
}
|
|
25163
|
-
|
|
25164
|
-
|
|
25121
|
+
exports2.upperBound = upperBound;
|
|
25122
|
+
function lowerBound(array, value, comp = compare) {
|
|
25123
|
+
let len = array.length;
|
|
25124
|
+
let i = 0;
|
|
25125
|
+
while (len) {
|
|
25126
|
+
let diff = len >>> 1;
|
|
25127
|
+
let cursor = i + diff;
|
|
25128
|
+
if (comp(array[cursor], value)) {
|
|
25129
|
+
i = cursor + 1;
|
|
25130
|
+
len -= diff + 1;
|
|
25131
|
+
} else {
|
|
25132
|
+
len = diff;
|
|
25133
|
+
}
|
|
25134
|
+
}
|
|
25135
|
+
return i;
|
|
25165
25136
|
}
|
|
25166
|
-
|
|
25167
|
-
|
|
25168
|
-
|
|
25137
|
+
exports2.lowerBound = lowerBound;
|
|
25138
|
+
function binarySearch(array, value, comp = compare) {
|
|
25139
|
+
let cursor = lowerBound(array, value, comp);
|
|
25140
|
+
return cursor !== array.length && !comp(value, array[cursor]);
|
|
25169
25141
|
}
|
|
25170
|
-
|
|
25171
|
-
}
|
|
25172
|
-
function formatQuotaLine(q) {
|
|
25173
|
-
const fmt = (n) => `${Math.round(n)}%`;
|
|
25174
|
-
return `${fmt(q.fiveHourUtilizationPct)} / 5h \u00b7 ${fmt(q.sevenDayUtilizationPct)} / 7d`;
|
|
25175
|
-
}
|
|
25176
|
-
function formatResetRelative(target, now = new Date) {
|
|
25177
|
-
if (!target)
|
|
25178
|
-
return "\u2014";
|
|
25179
|
-
const deltaMs = target.getTime() - now.getTime();
|
|
25180
|
-
if (deltaMs <= 0)
|
|
25181
|
-
return "resets now";
|
|
25182
|
-
const totalMin = Math.round(deltaMs / 60000);
|
|
25183
|
-
if (totalMin < 60)
|
|
25184
|
-
return `resets in ${totalMin}m`;
|
|
25185
|
-
const hours = Math.floor(totalMin / 60);
|
|
25186
|
-
const mins = totalMin % 60;
|
|
25187
|
-
if (hours < 24)
|
|
25188
|
-
return mins > 0 ? `resets in ${hours}h ${mins}m` : `resets in ${hours}h`;
|
|
25189
|
-
const days = Math.floor(hours / 24);
|
|
25190
|
-
const remH = hours % 24;
|
|
25191
|
-
return remH > 0 ? `resets in ${days}d ${remH}h` : `resets in ${days}d`;
|
|
25192
|
-
}
|
|
25193
|
-
var OAUTH_BETA = "oauth-2025-04-20", DEFAULT_USER_AGENT = "claude-cli/1.0.0 (external, cli)", DEFAULT_PROBE_MODEL = "claude-haiku-4-5-20251001";
|
|
25194
|
-
var init_quota_check = () => {};
|
|
25142
|
+
exports2.binarySearch = binarySearch;
|
|
25143
|
+
});
|
|
25195
25144
|
|
|
25196
|
-
// ../
|
|
25197
|
-
|
|
25198
|
-
|
|
25199
|
-
|
|
25200
|
-
|
|
25201
|
-
|
|
25202
|
-
|
|
25203
|
-
|
|
25204
|
-
|
|
25205
|
-
|
|
25206
|
-
|
|
25207
|
-
|
|
25208
|
-
|
|
25209
|
-
|
|
25210
|
-
|
|
25211
|
-
|
|
25212
|
-
returns: FFIType.i32
|
|
25145
|
+
// ../node_modules/.bun/structured-source@4.0.0/node_modules/structured-source/lib/structured-source.js
|
|
25146
|
+
var require_structured_source = __commonJS((exports2) => {
|
|
25147
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
25148
|
+
exports2.StructuredSource = undefined;
|
|
25149
|
+
var boundary_1 = require_lib();
|
|
25150
|
+
|
|
25151
|
+
class StructuredSource {
|
|
25152
|
+
constructor(source) {
|
|
25153
|
+
this.indice = [0];
|
|
25154
|
+
let regexp = /[\r\n\u2028\u2029]/g;
|
|
25155
|
+
const length = source.length;
|
|
25156
|
+
regexp.lastIndex = 0;
|
|
25157
|
+
while (true) {
|
|
25158
|
+
let result = regexp.exec(source);
|
|
25159
|
+
if (!result) {
|
|
25160
|
+
break;
|
|
25213
25161
|
}
|
|
25214
|
-
|
|
25215
|
-
|
|
25216
|
-
|
|
25217
|
-
|
|
25218
|
-
|
|
25219
|
-
|
|
25220
|
-
|
|
25221
|
-
} catch (e) {
|
|
25222
|
-
errors3.push(`${name}: ${e instanceof Error ? e.message : String(e)}`);
|
|
25162
|
+
let index = result.index;
|
|
25163
|
+
if (source.charCodeAt(index) === 13 && source.charCodeAt(index + 1) === 10) {
|
|
25164
|
+
index += 1;
|
|
25165
|
+
}
|
|
25166
|
+
let nextIndex = index + 1;
|
|
25167
|
+
if (length < nextIndex) {
|
|
25168
|
+
break;
|
|
25223
25169
|
}
|
|
25170
|
+
this.indice.push(nextIndex);
|
|
25171
|
+
regexp.lastIndex = nextIndex;
|
|
25224
25172
|
}
|
|
25225
|
-
|
|
25226
|
-
|
|
25227
|
-
|
|
25228
|
-
}
|
|
25229
|
-
|
|
25230
|
-
|
|
25231
|
-
|
|
25232
|
-
|
|
25233
|
-
|
|
25234
|
-
|
|
25235
|
-
|
|
25236
|
-
|
|
25237
|
-
|
|
25238
|
-
|
|
25239
|
-
|
|
25240
|
-
|
|
25241
|
-
|
|
25242
|
-
|
|
25243
|
-
|
|
25244
|
-
|
|
25245
|
-
|
|
25246
|
-
|
|
25247
|
-
|
|
25248
|
-
|
|
25249
|
-
function isReservedAgentName(name) {
|
|
25250
|
-
return RESERVED_AGENT_NAMES.has(name);
|
|
25251
|
-
}
|
|
25252
|
-
function unlockSocketFor(dataSocketPath) {
|
|
25253
|
-
if (dataSocketPath.endsWith("/sock")) {
|
|
25254
|
-
return dataSocketPath.slice(0, -"/sock".length) + "/unlock";
|
|
25173
|
+
}
|
|
25174
|
+
get line() {
|
|
25175
|
+
return this.indice.length;
|
|
25176
|
+
}
|
|
25177
|
+
locationToRange(loc) {
|
|
25178
|
+
return [this.positionToIndex(loc.start), this.positionToIndex(loc.end)];
|
|
25179
|
+
}
|
|
25180
|
+
rangeToLocation(range) {
|
|
25181
|
+
return {
|
|
25182
|
+
start: this.indexToPosition(range[0]),
|
|
25183
|
+
end: this.indexToPosition(range[1])
|
|
25184
|
+
};
|
|
25185
|
+
}
|
|
25186
|
+
positionToIndex(pos) {
|
|
25187
|
+
let start = this.indice[pos.line - 1];
|
|
25188
|
+
return start + pos.column;
|
|
25189
|
+
}
|
|
25190
|
+
indexToPosition(index) {
|
|
25191
|
+
const startLine = (0, boundary_1.upperBound)(this.indice, index);
|
|
25192
|
+
return {
|
|
25193
|
+
line: startLine,
|
|
25194
|
+
column: index - this.indice[startLine - 1]
|
|
25195
|
+
};
|
|
25196
|
+
}
|
|
25255
25197
|
}
|
|
25256
|
-
|
|
25257
|
-
}
|
|
25258
|
-
|
|
25259
|
-
var
|
|
25260
|
-
|
|
25198
|
+
exports2.StructuredSource = StructuredSource;
|
|
25199
|
+
});
|
|
25200
|
+
// ../node_modules/.bun/@secretlint+core@12.2.0/node_modules/@secretlint/core/module/SecretLintSourceCodeImpl.js
|
|
25201
|
+
var import_structured_source;
|
|
25202
|
+
var init_SecretLintSourceCodeImpl = __esm(() => {
|
|
25203
|
+
import_structured_source = __toESM(require_structured_source(), 1);
|
|
25261
25204
|
});
|
|
25262
25205
|
|
|
25263
|
-
// ../
|
|
25264
|
-
|
|
25265
|
-
|
|
25266
|
-
|
|
25267
|
-
|
|
25206
|
+
// ../node_modules/.bun/@secretlint+core@12.2.0/node_modules/@secretlint/core/module/helper/promise-event-emitter.js
|
|
25207
|
+
class EventEmitter {
|
|
25208
|
+
#listeners = new Map;
|
|
25209
|
+
on(type, listener) {
|
|
25210
|
+
const prevSet = this.#listeners.get(type);
|
|
25211
|
+
const listenerSet = prevSet ?? new Set;
|
|
25212
|
+
listenerSet?.add(listener);
|
|
25213
|
+
this.#listeners.set(type, listenerSet);
|
|
25268
25214
|
}
|
|
25269
|
-
|
|
25270
|
-
|
|
25271
|
-
|
|
25272
|
-
|
|
25273
|
-
|
|
25274
|
-
|
|
25215
|
+
emit(type, ...args) {
|
|
25216
|
+
const listenerSet = this.#listeners.get(type);
|
|
25217
|
+
if (!listenerSet) {
|
|
25218
|
+
return;
|
|
25219
|
+
}
|
|
25220
|
+
for (const listenerSetElement of listenerSet) {
|
|
25221
|
+
listenerSetElement(...args);
|
|
25222
|
+
}
|
|
25275
25223
|
}
|
|
25276
|
-
|
|
25277
|
-
|
|
25278
|
-
|
|
25279
|
-
|
|
25280
|
-
var init_protocol2 = __esm(() => {
|
|
25281
|
-
init_zod();
|
|
25282
|
-
init_peercred();
|
|
25283
|
-
MAX_FRAME_BYTES2 = 64 * 1024;
|
|
25284
|
-
AgentNameSchema = exports_external.string().min(1).max(64, "agent name max 64 chars").regex(/^[a-zA-Z0-9][a-zA-Z0-9_-]*$/, "agent name must be kebab-case ASCII (alnum + _- only, first char alnum)").refine((s) => !isReservedAgentName(s), {
|
|
25285
|
-
message: "agent name is reserved"
|
|
25286
|
-
});
|
|
25287
|
-
GetRequestSchema = exports_external.object({
|
|
25288
|
-
v: exports_external.literal(1),
|
|
25289
|
-
op: exports_external.literal("get"),
|
|
25290
|
-
key: exports_external.string().min(1),
|
|
25291
|
-
filename: exports_external.string().optional(),
|
|
25292
|
-
token: exports_external.string().optional()
|
|
25293
|
-
});
|
|
25294
|
-
PutRequestSchema = exports_external.object({
|
|
25295
|
-
v: exports_external.literal(1),
|
|
25296
|
-
op: exports_external.literal("put"),
|
|
25297
|
-
key: exports_external.string().min(1),
|
|
25298
|
-
entry: exports_external.union([
|
|
25299
|
-
exports_external.object({ kind: exports_external.literal("string"), value: exports_external.string() }),
|
|
25300
|
-
exports_external.object({ kind: exports_external.literal("binary"), value: exports_external.string() })
|
|
25301
|
-
]),
|
|
25302
|
-
token: exports_external.string().optional(),
|
|
25303
|
-
passphrase: exports_external.string().optional(),
|
|
25304
|
-
attest_via_posture: exports_external.boolean().optional()
|
|
25305
|
-
});
|
|
25306
|
-
ListRequestSchema = exports_external.object({
|
|
25307
|
-
v: exports_external.literal(1),
|
|
25308
|
-
op: exports_external.literal("list"),
|
|
25309
|
-
token: exports_external.string().optional()
|
|
25310
|
-
});
|
|
25311
|
-
MintGrantRequestSchema = exports_external.object({
|
|
25312
|
-
v: exports_external.literal(1),
|
|
25313
|
-
op: exports_external.literal("mint_grant"),
|
|
25314
|
-
agent: AgentNameSchema,
|
|
25315
|
-
keys: exports_external.array(exports_external.string().min(1)),
|
|
25316
|
-
ttl_seconds: exports_external.number().int().positive().nullable(),
|
|
25317
|
-
description: exports_external.string().optional(),
|
|
25318
|
-
write_keys: exports_external.array(exports_external.string().min(1)).optional(),
|
|
25319
|
-
passphrase: exports_external.string().optional(),
|
|
25320
|
-
attest_via_posture: exports_external.boolean().optional()
|
|
25321
|
-
});
|
|
25322
|
-
ListGrantsRequestSchema = exports_external.object({
|
|
25323
|
-
v: exports_external.literal(1),
|
|
25324
|
-
op: exports_external.literal("list_grants"),
|
|
25325
|
-
agent: AgentNameSchema.optional(),
|
|
25326
|
-
passphrase: exports_external.string().optional(),
|
|
25327
|
-
attest_via_posture: exports_external.boolean().optional()
|
|
25328
|
-
});
|
|
25329
|
-
RevokeGrantRequestSchema = exports_external.object({
|
|
25330
|
-
v: exports_external.literal(1),
|
|
25331
|
-
op: exports_external.literal("revoke_grant"),
|
|
25332
|
-
id: exports_external.string().min(1)
|
|
25333
|
-
});
|
|
25334
|
-
StatusRequestSchema = exports_external.object({
|
|
25335
|
-
v: exports_external.literal(1),
|
|
25336
|
-
op: exports_external.literal("status")
|
|
25337
|
-
});
|
|
25338
|
-
LockRequestSchema = exports_external.object({
|
|
25339
|
-
v: exports_external.literal(1),
|
|
25340
|
-
op: exports_external.literal("lock")
|
|
25341
|
-
});
|
|
25342
|
-
PreflightAccessRequestSchema = exports_external.object({
|
|
25343
|
-
v: exports_external.literal(1),
|
|
25344
|
-
op: exports_external.literal("preflight_access"),
|
|
25345
|
-
agent: AgentNameSchema,
|
|
25346
|
-
keys: exports_external.array(exports_external.string().min(1)).min(1).max(128)
|
|
25347
|
-
});
|
|
25348
|
-
OkPreflightAccessResponseSchema = exports_external.object({
|
|
25349
|
-
ok: exports_external.literal(true),
|
|
25350
|
-
op: exports_external.literal("preflight_access"),
|
|
25351
|
-
results: exports_external.array(exports_external.object({
|
|
25352
|
-
key: exports_external.string(),
|
|
25353
|
-
exists: exports_external.boolean(),
|
|
25354
|
-
acl_ok: exports_external.boolean(),
|
|
25355
|
-
acl_reason: exports_external.string().optional(),
|
|
25356
|
-
scope_ok: exports_external.boolean(),
|
|
25357
|
-
scope_reason: exports_external.string().optional()
|
|
25358
|
-
}))
|
|
25359
|
-
});
|
|
25360
|
-
ApprovalRequestRequestSchema = exports_external.object({
|
|
25361
|
-
v: exports_external.literal(1),
|
|
25362
|
-
op: exports_external.literal("approval_request"),
|
|
25363
|
-
agent_unit: exports_external.string().min(1),
|
|
25364
|
-
scope: exports_external.string().min(1),
|
|
25365
|
-
action: exports_external.string().min(1),
|
|
25366
|
-
approver_set: exports_external.array(exports_external.string()),
|
|
25367
|
-
why: exports_external.string().optional(),
|
|
25368
|
-
ttl_ms: exports_external.number().int().positive().optional()
|
|
25369
|
-
});
|
|
25370
|
-
ApprovalLookupRequestSchema = exports_external.object({
|
|
25371
|
-
v: exports_external.literal(1),
|
|
25372
|
-
op: exports_external.literal("approval_lookup"),
|
|
25373
|
-
agent_unit: exports_external.string().min(1),
|
|
25374
|
-
scope: exports_external.string().min(1),
|
|
25375
|
-
action: exports_external.string().min(1),
|
|
25376
|
-
current_approver_set: exports_external.array(exports_external.string())
|
|
25377
|
-
});
|
|
25378
|
-
ApprovalConsumeRequestSchema = exports_external.object({
|
|
25379
|
-
v: exports_external.literal(1),
|
|
25380
|
-
op: exports_external.literal("approval_consume"),
|
|
25381
|
-
request_id: exports_external.string().regex(/^[0-9a-f]{32}$/)
|
|
25382
|
-
});
|
|
25383
|
-
ApprovalRevokeRequestSchema = exports_external.object({
|
|
25384
|
-
v: exports_external.literal(1),
|
|
25385
|
-
op: exports_external.literal("approval_revoke"),
|
|
25386
|
-
decision_id: exports_external.string().min(1),
|
|
25387
|
-
actor: exports_external.string().min(1),
|
|
25388
|
-
reason: exports_external.string().optional()
|
|
25389
|
-
});
|
|
25390
|
-
ApprovalListRequestSchema = exports_external.object({
|
|
25391
|
-
v: exports_external.literal(1),
|
|
25392
|
-
op: exports_external.literal("approval_list"),
|
|
25393
|
-
agent_unit: exports_external.string().optional()
|
|
25394
|
-
});
|
|
25395
|
-
ApprovalDecisionModeSchema = exports_external.enum([
|
|
25396
|
-
"allow_once",
|
|
25397
|
-
"allow_always",
|
|
25398
|
-
"allow_ttl",
|
|
25399
|
-
"deny",
|
|
25400
|
-
"deny_perm"
|
|
25401
|
-
]);
|
|
25402
|
-
ApprovalRecordRequestSchema = exports_external.object({
|
|
25403
|
-
v: exports_external.literal(1),
|
|
25404
|
-
op: exports_external.literal("approval_record"),
|
|
25405
|
-
request_id: exports_external.string().regex(/^[0-9a-f]{32}$/),
|
|
25406
|
-
decision: ApprovalDecisionModeSchema,
|
|
25407
|
-
approver_set: exports_external.array(exports_external.string()),
|
|
25408
|
-
granted_by_user_id: exports_external.number().int(),
|
|
25409
|
-
ttl_ms: exports_external.number().int().positive().nullable().optional()
|
|
25410
|
-
});
|
|
25411
|
-
ApprovalConsumeRecordRequestSchema = exports_external.object({
|
|
25412
|
-
v: exports_external.literal(1),
|
|
25413
|
-
op: exports_external.literal("approval_consume_record"),
|
|
25414
|
-
request_id: exports_external.string().regex(/^[0-9a-f]{32}$/),
|
|
25415
|
-
decision: ApprovalDecisionModeSchema,
|
|
25416
|
-
approver_set: exports_external.array(exports_external.string()),
|
|
25417
|
-
granted_by_user_id: exports_external.number().int(),
|
|
25418
|
-
ttl_ms: exports_external.number().int().positive().nullable().optional()
|
|
25419
|
-
});
|
|
25420
|
-
RequestSchema2 = exports_external.discriminatedUnion("op", [
|
|
25421
|
-
GetRequestSchema,
|
|
25422
|
-
PutRequestSchema,
|
|
25423
|
-
ListRequestSchema,
|
|
25424
|
-
StatusRequestSchema,
|
|
25425
|
-
LockRequestSchema,
|
|
25426
|
-
PreflightAccessRequestSchema,
|
|
25427
|
-
MintGrantRequestSchema,
|
|
25428
|
-
ListGrantsRequestSchema,
|
|
25429
|
-
RevokeGrantRequestSchema,
|
|
25430
|
-
ApprovalRequestRequestSchema,
|
|
25431
|
-
ApprovalLookupRequestSchema,
|
|
25432
|
-
ApprovalConsumeRequestSchema,
|
|
25433
|
-
ApprovalRevokeRequestSchema,
|
|
25434
|
-
ApprovalListRequestSchema,
|
|
25435
|
-
ApprovalRecordRequestSchema,
|
|
25436
|
-
ApprovalConsumeRecordRequestSchema
|
|
25437
|
-
]);
|
|
25438
|
-
VaultEntrySchema = exports_external.union([
|
|
25439
|
-
exports_external.object({ kind: exports_external.literal("string"), value: exports_external.string() }),
|
|
25440
|
-
exports_external.object({ kind: exports_external.literal("binary"), value: exports_external.string() }),
|
|
25441
|
-
exports_external.object({
|
|
25442
|
-
kind: exports_external.literal("files"),
|
|
25443
|
-
files: exports_external.record(exports_external.string(), exports_external.object({
|
|
25444
|
-
encoding: exports_external.enum(["utf8", "base64"]),
|
|
25445
|
-
value: exports_external.string()
|
|
25446
|
-
}))
|
|
25447
|
-
})
|
|
25448
|
-
]);
|
|
25449
|
-
ErrorCode = exports_external.enum([
|
|
25450
|
-
"LOCKED",
|
|
25451
|
-
"DENIED",
|
|
25452
|
-
"UNKNOWN_KEY",
|
|
25453
|
-
"BAD_REQUEST",
|
|
25454
|
-
"INTERNAL"
|
|
25455
|
-
]);
|
|
25456
|
-
OkEntryResponseSchema = exports_external.object({
|
|
25457
|
-
ok: exports_external.literal(true),
|
|
25458
|
-
entry: VaultEntrySchema
|
|
25459
|
-
});
|
|
25460
|
-
OkKeysResponseSchema = exports_external.object({
|
|
25461
|
-
ok: exports_external.literal(true),
|
|
25462
|
-
keys: exports_external.array(exports_external.string())
|
|
25463
|
-
});
|
|
25464
|
-
BrokerStatus = exports_external.object({
|
|
25465
|
-
unlocked: exports_external.boolean(),
|
|
25466
|
-
keyCount: exports_external.number().int().nonnegative(),
|
|
25467
|
-
uptimeSec: exports_external.number().nonnegative()
|
|
25468
|
-
});
|
|
25469
|
-
OkStatusResponseSchema = exports_external.object({
|
|
25470
|
-
ok: exports_external.literal(true),
|
|
25471
|
-
status: BrokerStatus
|
|
25472
|
-
});
|
|
25473
|
-
OkLockResponseSchema = exports_external.object({
|
|
25474
|
-
ok: exports_external.literal(true),
|
|
25475
|
-
locked: exports_external.literal(true)
|
|
25476
|
-
});
|
|
25477
|
-
OkPutResponseSchema = exports_external.object({
|
|
25478
|
-
ok: exports_external.literal(true),
|
|
25479
|
-
put: exports_external.literal(true),
|
|
25480
|
-
key: exports_external.string()
|
|
25481
|
-
});
|
|
25482
|
-
OkMintGrantResponseSchema = exports_external.object({
|
|
25483
|
-
ok: exports_external.literal(true),
|
|
25484
|
-
token: exports_external.string(),
|
|
25485
|
-
id: exports_external.string(),
|
|
25486
|
-
expires_at: exports_external.number().nullable()
|
|
25487
|
-
});
|
|
25488
|
-
GrantMetaSchema = exports_external.object({
|
|
25489
|
-
id: exports_external.string(),
|
|
25490
|
-
agent_slug: exports_external.string(),
|
|
25491
|
-
key_allow: exports_external.array(exports_external.string()),
|
|
25492
|
-
write_allow: exports_external.array(exports_external.string()).default([]),
|
|
25493
|
-
expires_at: exports_external.number().nullable(),
|
|
25494
|
-
created_at: exports_external.number(),
|
|
25495
|
-
description: exports_external.string().nullable()
|
|
25496
|
-
});
|
|
25497
|
-
OkListGrantsResponseSchema = exports_external.object({
|
|
25498
|
-
ok: exports_external.literal(true),
|
|
25499
|
-
grants: exports_external.array(GrantMetaSchema)
|
|
25500
|
-
});
|
|
25501
|
-
OkRevokeGrantResponseSchema = exports_external.object({
|
|
25502
|
-
ok: exports_external.literal(true),
|
|
25503
|
-
revoked: exports_external.boolean()
|
|
25504
|
-
});
|
|
25505
|
-
OkApprovalRequestResponseSchema = exports_external.discriminatedUnion("state", [
|
|
25506
|
-
exports_external.object({
|
|
25507
|
-
ok: exports_external.literal(true),
|
|
25508
|
-
kind: exports_external.literal("approval_request"),
|
|
25509
|
-
state: exports_external.literal("pending"),
|
|
25510
|
-
request_id: exports_external.string(),
|
|
25511
|
-
expires_at: exports_external.number()
|
|
25512
|
-
}),
|
|
25513
|
-
exports_external.object({
|
|
25514
|
-
ok: exports_external.literal(true),
|
|
25515
|
-
kind: exports_external.literal("approval_request"),
|
|
25516
|
-
state: exports_external.literal("rate_limited"),
|
|
25517
|
-
retry_after_ms: exports_external.number()
|
|
25518
|
-
})
|
|
25519
|
-
]);
|
|
25520
|
-
ApprovalDecisionMetaSchema = exports_external.object({
|
|
25521
|
-
id: exports_external.string(),
|
|
25522
|
-
agent_unit: exports_external.string(),
|
|
25523
|
-
scope: exports_external.string(),
|
|
25524
|
-
action: exports_external.string(),
|
|
25525
|
-
decision: ApprovalDecisionModeSchema,
|
|
25526
|
-
granted_at: exports_external.number(),
|
|
25527
|
-
granted_by_user_id: exports_external.number(),
|
|
25528
|
-
ttl_expires_at: exports_external.number().nullable(),
|
|
25529
|
-
last_used_at: exports_external.number().nullable(),
|
|
25530
|
-
revoked_at: exports_external.number().nullable(),
|
|
25531
|
-
revoke_reason: exports_external.string().nullable()
|
|
25532
|
-
});
|
|
25533
|
-
OkApprovalLookupResponseSchema = exports_external.object({
|
|
25534
|
-
ok: exports_external.literal(true),
|
|
25535
|
-
state: exports_external.enum(["granted", "denied", "pending", "expired", "drift_revoked", "no_decision"]),
|
|
25536
|
-
decision: ApprovalDecisionMetaSchema.nullable().optional()
|
|
25537
|
-
});
|
|
25538
|
-
OkApprovalConsumeResponseSchema = exports_external.object({
|
|
25539
|
-
ok: exports_external.literal(true),
|
|
25540
|
-
consumed: exports_external.boolean(),
|
|
25541
|
-
agent_unit: exports_external.string().optional(),
|
|
25542
|
-
scope: exports_external.string().optional(),
|
|
25543
|
-
action: exports_external.string().optional(),
|
|
25544
|
-
why: exports_external.string().nullable().optional()
|
|
25545
|
-
});
|
|
25546
|
-
OkApprovalRevokeResponseSchema = exports_external.object({
|
|
25547
|
-
ok: exports_external.literal(true),
|
|
25548
|
-
revoked: exports_external.boolean()
|
|
25549
|
-
});
|
|
25550
|
-
OkApprovalListResponseSchema = exports_external.object({
|
|
25551
|
-
ok: exports_external.literal(true),
|
|
25552
|
-
decisions: exports_external.array(ApprovalDecisionMetaSchema)
|
|
25553
|
-
});
|
|
25554
|
-
OkApprovalRecordResponseSchema = exports_external.object({
|
|
25555
|
-
ok: exports_external.literal(true),
|
|
25556
|
-
decision_id: exports_external.string()
|
|
25557
|
-
});
|
|
25558
|
-
OkApprovalConsumeRecordResponseSchema = exports_external.object({
|
|
25559
|
-
ok: exports_external.literal(true),
|
|
25560
|
-
consumed: exports_external.boolean(),
|
|
25561
|
-
decision_id: exports_external.string().optional(),
|
|
25562
|
-
agent_unit: exports_external.string().optional(),
|
|
25563
|
-
scope: exports_external.string().optional(),
|
|
25564
|
-
action: exports_external.string().optional(),
|
|
25565
|
-
why: exports_external.string().nullable().optional()
|
|
25566
|
-
});
|
|
25567
|
-
ErrorResponseSchema2 = exports_external.object({
|
|
25568
|
-
ok: exports_external.literal(false),
|
|
25569
|
-
code: ErrorCode,
|
|
25570
|
-
msg: exports_external.string()
|
|
25571
|
-
});
|
|
25572
|
-
ResponseSchema2 = exports_external.union([
|
|
25573
|
-
OkEntryResponseSchema,
|
|
25574
|
-
OkKeysResponseSchema,
|
|
25575
|
-
OkStatusResponseSchema,
|
|
25576
|
-
OkLockResponseSchema,
|
|
25577
|
-
OkPreflightAccessResponseSchema,
|
|
25578
|
-
OkPutResponseSchema,
|
|
25579
|
-
OkMintGrantResponseSchema,
|
|
25580
|
-
OkListGrantsResponseSchema,
|
|
25581
|
-
OkRevokeGrantResponseSchema,
|
|
25582
|
-
OkApprovalRequestResponseSchema,
|
|
25583
|
-
OkApprovalLookupResponseSchema,
|
|
25584
|
-
OkApprovalConsumeResponseSchema,
|
|
25585
|
-
OkApprovalRevokeResponseSchema,
|
|
25586
|
-
OkApprovalListResponseSchema,
|
|
25587
|
-
OkApprovalRecordResponseSchema,
|
|
25588
|
-
OkApprovalConsumeRecordResponseSchema,
|
|
25589
|
-
ErrorResponseSchema2
|
|
25590
|
-
]);
|
|
25591
|
-
});
|
|
25592
|
-
|
|
25593
|
-
// ../src/runtime-mode.ts
|
|
25594
|
-
function isDockerRuntime() {
|
|
25595
|
-
return process.env.SWITCHROOM_RUNTIME === "docker";
|
|
25596
|
-
}
|
|
25597
|
-
|
|
25598
|
-
// ../src/vault/broker/client.ts
|
|
25599
|
-
import * as net3 from "node:net";
|
|
25600
|
-
import * as fs from "node:fs";
|
|
25601
|
-
import { homedir as homedir7 } from "node:os";
|
|
25602
|
-
import { join as join15 } from "node:path";
|
|
25603
|
-
function defaultBrokerSocketPath() {
|
|
25604
|
-
if (fs.existsSync(OPERATOR_SOCKET_PATH))
|
|
25605
|
-
return OPERATOR_SOCKET_PATH;
|
|
25606
|
-
if (isDockerRuntime())
|
|
25607
|
-
return OPERATOR_SOCKET_PATH;
|
|
25608
|
-
return LEGACY_SOCKET_PATH;
|
|
25609
|
-
}
|
|
25610
|
-
function vaultTokenFilePath(agentSlug) {
|
|
25611
|
-
return join15(homedir7(), ".switchroom", "agents", agentSlug, ".vault-token");
|
|
25612
|
-
}
|
|
25613
|
-
function readVaultTokenFile(agentSlug) {
|
|
25614
|
-
const filePath = vaultTokenFilePath(agentSlug);
|
|
25615
|
-
try {
|
|
25616
|
-
const stat = fs.statSync(filePath);
|
|
25617
|
-
const mode = stat.mode & 511;
|
|
25618
|
-
if ((mode & 63) !== 0) {
|
|
25619
|
-
process.stderr.write(`[vault-broker] Refusing to read ${filePath} with mode ${mode.toString(8).padStart(3, "0")} ` + `(must be 0600). Delete the file and re-mint with 'switchroom vault grant mint <agent>'. ` + `Falling through to peercred ACL.
|
|
25620
|
-
`);
|
|
25621
|
-
return null;
|
|
25224
|
+
off(type, listener) {
|
|
25225
|
+
const listenerSet = this.#listeners.get(type);
|
|
25226
|
+
if (!listenerSet) {
|
|
25227
|
+
return;
|
|
25622
25228
|
}
|
|
25623
|
-
const
|
|
25624
|
-
|
|
25625
|
-
|
|
25626
|
-
|
|
25627
|
-
} catch (err) {
|
|
25628
|
-
const code = err.code;
|
|
25629
|
-
if (code === "ENOENT") {
|
|
25630
|
-
return null;
|
|
25229
|
+
for (const listenerSetElement of listenerSet) {
|
|
25230
|
+
if (listenerSetElement === listener) {
|
|
25231
|
+
listenerSet.delete(listener);
|
|
25232
|
+
}
|
|
25631
25233
|
}
|
|
25632
|
-
|
|
25633
|
-
|
|
25634
|
-
|
|
25635
|
-
|
|
25636
|
-
|
|
25637
|
-
|
|
25638
|
-
|
|
25639
|
-
|
|
25640
|
-
return
|
|
25641
|
-
const env = process.env.SWITCHROOM_VAULT_BROKER_SOCK;
|
|
25642
|
-
if (env)
|
|
25643
|
-
return env;
|
|
25644
|
-
if (opts?.vaultBrokerSocket)
|
|
25645
|
-
return opts.vaultBrokerSocket;
|
|
25646
|
-
return defaultBrokerSocketPath();
|
|
25647
|
-
}
|
|
25648
|
-
async function rpcRaw(req, opts) {
|
|
25649
|
-
return rpc(req, opts);
|
|
25650
|
-
}
|
|
25651
|
-
async function rpc(req, opts) {
|
|
25652
|
-
const socketPath = resolveBrokerSocketPath(opts);
|
|
25653
|
-
const timeoutMs = opts?.timeoutMs ?? DEFAULT_TIMEOUT_MS3;
|
|
25654
|
-
return new Promise((resolve5) => {
|
|
25655
|
-
let settled = false;
|
|
25656
|
-
const settle = (val) => {
|
|
25657
|
-
if (settled)
|
|
25658
|
-
return;
|
|
25659
|
-
settled = true;
|
|
25660
|
-
resolve5(val);
|
|
25661
|
-
};
|
|
25662
|
-
const client3 = new net3.Socket;
|
|
25663
|
-
const timer3 = setTimeout(() => {
|
|
25664
|
-
client3.destroy();
|
|
25665
|
-
settle({ kind: "unreachable", msg: `broker did not respond within ${timeoutMs}ms` });
|
|
25666
|
-
}, timeoutMs);
|
|
25667
|
-
client3.on("error", (err) => {
|
|
25668
|
-
clearTimeout(timer3);
|
|
25669
|
-
const code = err.code ?? "ERR";
|
|
25670
|
-
let msg;
|
|
25671
|
-
if (code === "ENOENT")
|
|
25672
|
-
msg = "broker socket not found (is the daemon running?)";
|
|
25673
|
-
else if (code === "ECONNREFUSED")
|
|
25674
|
-
msg = "broker socket exists but refused connection";
|
|
25675
|
-
else if (code === "EACCES")
|
|
25676
|
-
msg = "broker socket access denied (wrong UID?)";
|
|
25677
|
-
else
|
|
25678
|
-
msg = `broker connection failed: ${err.message}`;
|
|
25679
|
-
settle({ kind: "unreachable", msg });
|
|
25680
|
-
});
|
|
25681
|
-
let buffer = "";
|
|
25682
|
-
client3.on("data", (chunk) => {
|
|
25683
|
-
buffer += chunk.toString("utf8");
|
|
25684
|
-
const newlineIdx = buffer.indexOf(`
|
|
25685
|
-
`);
|
|
25686
|
-
if (newlineIdx !== -1) {
|
|
25687
|
-
const line = buffer.slice(0, newlineIdx).trimEnd();
|
|
25688
|
-
clearTimeout(timer3);
|
|
25689
|
-
client3.destroy();
|
|
25690
|
-
try {
|
|
25691
|
-
const resp = decodeResponse2(line);
|
|
25692
|
-
settle({ kind: "response", resp });
|
|
25693
|
-
} catch (err) {
|
|
25694
|
-
settle({
|
|
25695
|
-
kind: "unreachable",
|
|
25696
|
-
msg: `unparseable broker response: ${err instanceof Error ? err.message : String(err)}`
|
|
25697
|
-
});
|
|
25698
|
-
}
|
|
25699
|
-
}
|
|
25700
|
-
});
|
|
25701
|
-
client3.on("connect", () => {
|
|
25702
|
-
try {
|
|
25703
|
-
client3.write(encodeRequest2(req));
|
|
25704
|
-
} catch (err) {
|
|
25705
|
-
clearTimeout(timer3);
|
|
25706
|
-
client3.destroy();
|
|
25707
|
-
settle({
|
|
25708
|
-
kind: "unreachable",
|
|
25709
|
-
msg: `failed to send request: ${err instanceof Error ? err.message : String(err)}`
|
|
25710
|
-
});
|
|
25711
|
-
}
|
|
25712
|
-
});
|
|
25713
|
-
client3.connect({ path: socketPath });
|
|
25714
|
-
});
|
|
25715
|
-
}
|
|
25716
|
-
async function getViaBrokerStructured(key, opts) {
|
|
25717
|
-
const token = opts?.token;
|
|
25718
|
-
const result = await rpc({ v: 1, op: "get", key, ...token ? { token } : {} }, opts);
|
|
25719
|
-
if (result.kind === "unreachable") {
|
|
25720
|
-
return { kind: "unreachable", msg: result.msg };
|
|
25721
|
-
}
|
|
25722
|
-
const resp = result.resp;
|
|
25723
|
-
if (resp.ok && "entry" in resp) {
|
|
25724
|
-
return { kind: "ok", entry: resp.entry };
|
|
25725
|
-
}
|
|
25726
|
-
if (!resp.ok) {
|
|
25727
|
-
if (resp.code === "UNKNOWN_KEY") {
|
|
25728
|
-
return { kind: "not_found", code: resp.code, msg: resp.msg };
|
|
25729
|
-
}
|
|
25730
|
-
return { kind: "denied", code: resp.code, msg: resp.msg };
|
|
25731
|
-
}
|
|
25732
|
-
return { kind: "unreachable", msg: "unexpected broker response shape" };
|
|
25733
|
-
}
|
|
25734
|
-
async function putViaBroker(key, entry, opts) {
|
|
25735
|
-
const token = opts?.token;
|
|
25736
|
-
const passphrase = opts?.passphrase;
|
|
25737
|
-
const attestViaPosture = opts?.attest_via_posture === true;
|
|
25738
|
-
const result = await rpc({
|
|
25739
|
-
v: 1,
|
|
25740
|
-
op: "put",
|
|
25741
|
-
key,
|
|
25742
|
-
entry,
|
|
25743
|
-
...token ? { token } : {},
|
|
25744
|
-
...passphrase ? { passphrase } : {},
|
|
25745
|
-
...attestViaPosture ? { attest_via_posture: true } : {}
|
|
25746
|
-
}, opts);
|
|
25747
|
-
if (result.kind === "unreachable") {
|
|
25748
|
-
return { kind: "unreachable", msg: result.msg };
|
|
25749
|
-
}
|
|
25750
|
-
const resp = result.resp;
|
|
25751
|
-
if (resp.ok && "put" in resp) {
|
|
25752
|
-
return { kind: "ok" };
|
|
25753
|
-
}
|
|
25754
|
-
if (!resp.ok) {
|
|
25755
|
-
if (resp.code === "UNKNOWN_KEY") {
|
|
25756
|
-
return { kind: "not_found", code: resp.code, msg: resp.msg };
|
|
25757
|
-
}
|
|
25758
|
-
return { kind: "denied", code: resp.code, msg: resp.msg };
|
|
25759
|
-
}
|
|
25760
|
-
return { kind: "unreachable", msg: "unexpected broker response shape" };
|
|
25761
|
-
}
|
|
25762
|
-
var DEFAULT_TIMEOUT_MS3 = 2000, LEGACY_SOCKET_PATH, OPERATOR_SOCKET_PATH;
|
|
25763
|
-
var init_client2 = __esm(() => {
|
|
25764
|
-
init_protocol2();
|
|
25765
|
-
init_peercred();
|
|
25766
|
-
LEGACY_SOCKET_PATH = join15(homedir7(), ".switchroom", "vault-broker.sock");
|
|
25767
|
-
OPERATOR_SOCKET_PATH = join15(homedir7(), ".switchroom", "broker-operator", "sock");
|
|
25768
|
-
});
|
|
25769
|
-
|
|
25770
|
-
// ../src/drive/deep-links.ts
|
|
25771
|
-
function classifyMimeType(mimeType) {
|
|
25772
|
-
if (!mimeType)
|
|
25773
|
-
return "file";
|
|
25774
|
-
switch (mimeType) {
|
|
25775
|
-
case "application/vnd.google-apps.document":
|
|
25776
|
-
return "doc";
|
|
25777
|
-
case "application/vnd.google-apps.spreadsheet":
|
|
25778
|
-
return "spreadsheet";
|
|
25779
|
-
case "application/vnd.google-apps.presentation":
|
|
25780
|
-
return "presentation";
|
|
25781
|
-
case "application/vnd.google-apps.form":
|
|
25782
|
-
return "form";
|
|
25783
|
-
case "application/vnd.google-apps.drawing":
|
|
25784
|
-
return "drawing";
|
|
25785
|
-
case "application/vnd.google-apps.folder":
|
|
25786
|
-
return "folder";
|
|
25787
|
-
default:
|
|
25788
|
-
return "file";
|
|
25789
|
-
}
|
|
25790
|
-
}
|
|
25791
|
-
function openInDriveUrl(options) {
|
|
25792
|
-
validateDriveId2(options.fileId, "fileId");
|
|
25793
|
-
if (options.discussionId !== undefined) {
|
|
25794
|
-
validateDriveId2(options.discussionId, "discussionId");
|
|
25795
|
-
}
|
|
25796
|
-
const kind = options.isFolder ? "folder" : classifyMimeType(options.mimeType);
|
|
25797
|
-
const base = baseUrlFor(kind, options.fileId);
|
|
25798
|
-
if (options.discussionId !== undefined) {
|
|
25799
|
-
return `${base}?disco=${encodeURIComponent(options.discussionId)}`;
|
|
25800
|
-
}
|
|
25801
|
-
return base;
|
|
25802
|
-
}
|
|
25803
|
-
function baseUrlFor(kind, fileId) {
|
|
25804
|
-
switch (kind) {
|
|
25805
|
-
case "doc":
|
|
25806
|
-
return `https://docs.google.com/document/d/${fileId}/edit`;
|
|
25807
|
-
case "spreadsheet":
|
|
25808
|
-
return `https://docs.google.com/spreadsheets/d/${fileId}/edit`;
|
|
25809
|
-
case "presentation":
|
|
25810
|
-
return `https://docs.google.com/presentation/d/${fileId}/edit`;
|
|
25811
|
-
case "form":
|
|
25812
|
-
return `https://docs.google.com/forms/d/${fileId}/edit`;
|
|
25813
|
-
case "drawing":
|
|
25814
|
-
return `https://docs.google.com/drawings/d/${fileId}/edit`;
|
|
25815
|
-
case "folder":
|
|
25816
|
-
return `https://drive.google.com/drive/folders/${fileId}`;
|
|
25817
|
-
case "file":
|
|
25818
|
-
return `https://drive.google.com/file/d/${fileId}/view`;
|
|
25819
|
-
}
|
|
25820
|
-
}
|
|
25821
|
-
function validateDriveId2(id, fieldName) {
|
|
25822
|
-
if (id.length === 0) {
|
|
25823
|
-
throw new Error(`Drive ${fieldName} must not be empty`);
|
|
25824
|
-
}
|
|
25825
|
-
if (!/^[A-Za-z0-9_-]+$/.test(id)) {
|
|
25826
|
-
throw new Error(`Drive ${fieldName} '${id.slice(0, 30)}${id.length > 30 ? "\u2026" : ""}' contains invalid characters. Expected base64-url-safe (alphanumerics + - + _).`);
|
|
25827
|
-
}
|
|
25828
|
-
}
|
|
25829
|
-
function openInDriveButton(options) {
|
|
25830
|
-
return {
|
|
25831
|
-
text: "\uD83D\uDCD6 Open in Drive",
|
|
25832
|
-
url: openInDriveUrl(options)
|
|
25833
|
-
};
|
|
25834
|
-
}
|
|
25835
|
-
function scopeToOpenInDriveButton(scope, mimeTypeHint) {
|
|
25836
|
-
const parsed = parseDriveScope(scope);
|
|
25837
|
-
if (parsed === null)
|
|
25838
|
-
return null;
|
|
25839
|
-
if (parsed.target.kind === "all")
|
|
25840
|
-
return null;
|
|
25841
|
-
if (parsed.target.kind === "folder") {
|
|
25842
|
-
return openInDriveButton({ fileId: parsed.target.folder_id, isFolder: true });
|
|
25843
|
-
}
|
|
25844
|
-
return openInDriveButton({
|
|
25845
|
-
fileId: parsed.target.doc_id,
|
|
25846
|
-
mimeType: mimeTypeHint
|
|
25847
|
-
});
|
|
25848
|
-
}
|
|
25849
|
-
function parseDriveScope(scope) {
|
|
25850
|
-
if (!scope.startsWith("doc:gdrive:"))
|
|
25851
|
-
return null;
|
|
25852
|
-
let rest = scope.slice("doc:gdrive:".length);
|
|
25853
|
-
let action = "read";
|
|
25854
|
-
if (rest.startsWith("write:")) {
|
|
25855
|
-
action = "write";
|
|
25856
|
-
rest = rest.slice("write:".length);
|
|
25857
|
-
} else if (rest.startsWith("suggest:")) {
|
|
25858
|
-
action = "suggest";
|
|
25859
|
-
rest = rest.slice("suggest:".length);
|
|
25860
|
-
}
|
|
25861
|
-
if (rest === "**")
|
|
25862
|
-
return { action, target: { kind: "all" } };
|
|
25863
|
-
if (rest.startsWith("folder/")) {
|
|
25864
|
-
const tail = rest.slice("folder/".length);
|
|
25865
|
-
if (!tail.endsWith("/**"))
|
|
25866
|
-
return null;
|
|
25867
|
-
const folder_id = tail.slice(0, -"/**".length);
|
|
25868
|
-
if (!/^[A-Za-z0-9_-]+$/.test(folder_id))
|
|
25869
|
-
return null;
|
|
25870
|
-
return { action, target: { kind: "folder", folder_id } };
|
|
25871
|
-
}
|
|
25872
|
-
if (!/^[A-Za-z0-9_-]+$/.test(rest))
|
|
25873
|
-
return null;
|
|
25874
|
-
return { action, target: { kind: "doc", doc_id: rest } };
|
|
25875
|
-
}
|
|
25876
|
-
|
|
25877
|
-
// gateway/oversize-card-body.ts
|
|
25878
|
-
function truncateRawToFit(input) {
|
|
25879
|
-
const { raw, render, cap, sentinel } = input;
|
|
25880
|
-
const hardLimit = input.hardLimit ?? cap + 196;
|
|
25881
|
-
const fullBody = render(raw);
|
|
25882
|
-
if (fullBody.length <= cap) {
|
|
25883
|
-
return { body: fullBody, truncated: false };
|
|
25884
|
-
}
|
|
25885
|
-
let lo = 0;
|
|
25886
|
-
let hi = raw.length;
|
|
25887
|
-
let bestSliceLen = 0;
|
|
25888
|
-
while (lo <= hi) {
|
|
25889
|
-
const mid = lo + hi >>> 1;
|
|
25890
|
-
const candidate = raw.slice(0, mid) + sentinel;
|
|
25891
|
-
if (render(candidate).length <= cap) {
|
|
25892
|
-
bestSliceLen = mid;
|
|
25893
|
-
lo = mid + 1;
|
|
25894
|
-
} else {
|
|
25895
|
-
hi = mid - 1;
|
|
25896
|
-
}
|
|
25897
|
-
}
|
|
25898
|
-
let chosenRaw = raw.slice(0, bestSliceLen);
|
|
25899
|
-
const lastNl = chosenRaw.lastIndexOf(`
|
|
25900
|
-
`);
|
|
25901
|
-
if (lastNl > 0)
|
|
25902
|
-
chosenRaw = chosenRaw.slice(0, lastNl);
|
|
25903
|
-
let body = render(chosenRaw + sentinel);
|
|
25904
|
-
if (body.length > hardLimit) {
|
|
25905
|
-
body = body.slice(0, hardLimit - 1);
|
|
25906
|
-
}
|
|
25907
|
-
return { body, truncated: true };
|
|
25908
|
-
}
|
|
25909
|
-
|
|
25910
|
-
// secret-detect/suppressor.ts
|
|
25911
|
-
function isSuppressed(text, start, end) {
|
|
25912
|
-
const left = Math.max(0, start - WINDOW);
|
|
25913
|
-
const right = Math.min(text.length, end + WINDOW);
|
|
25914
|
-
const context = text.slice(left, start) + text.slice(end, right);
|
|
25915
|
-
return MARKER_RE.test(context);
|
|
25916
|
-
}
|
|
25917
|
-
var MARKERS, WINDOW = 40, MARKER_RE;
|
|
25918
|
-
var init_suppressor = __esm(() => {
|
|
25919
|
-
MARKERS = ["test", "mock", "example", "fixture", "dummy"];
|
|
25920
|
-
MARKER_RE = new RegExp(`\\b(?:${MARKERS.join("|")})\\b`, "i");
|
|
25921
|
-
});
|
|
25922
|
-
|
|
25923
|
-
// secret-detect/slug.ts
|
|
25924
|
-
function sanitizeKeyName(raw) {
|
|
25925
|
-
const up = raw.toUpperCase();
|
|
25926
|
-
const cleaned = up.replace(/[^A-Z0-9_]+/g, "_").replace(/_+/g, "_").replace(/^_+|_+$/g, "");
|
|
25927
|
-
return cleaned.length > 0 ? cleaned : "SECRET";
|
|
25928
|
-
}
|
|
25929
|
-
function datePart(now = new Date) {
|
|
25930
|
-
const y = now.getUTCFullYear();
|
|
25931
|
-
const m = String(now.getUTCMonth() + 1).padStart(2, "0");
|
|
25932
|
-
const d = String(now.getUTCDate()).padStart(2, "0");
|
|
25933
|
-
return `${y}${m}${d}`;
|
|
25934
|
-
}
|
|
25935
|
-
function deriveSlug(inputs, existing) {
|
|
25936
|
-
let base;
|
|
25937
|
-
if (inputs.key_name && inputs.key_name.trim().length > 0) {
|
|
25938
|
-
base = sanitizeKeyName(inputs.key_name);
|
|
25939
|
-
} else {
|
|
25940
|
-
base = `${inputs.rule_id}_${datePart(inputs.now)}`;
|
|
25941
|
-
}
|
|
25942
|
-
if (!existing.has(base))
|
|
25943
|
-
return base;
|
|
25944
|
-
let n = 2;
|
|
25945
|
-
while (existing.has(`${base}_${n}`))
|
|
25946
|
-
n++;
|
|
25947
|
-
return `${base}_${n}`;
|
|
25948
|
-
}
|
|
25949
|
-
|
|
25950
|
-
// ../node_modules/.bun/boundary@2.0.0/node_modules/boundary/lib/index.js
|
|
25951
|
-
var require_lib = __commonJS((exports2) => {
|
|
25952
|
-
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
25953
|
-
exports2.binarySearch = exports2.upperBound = exports2.lowerBound = exports2.compare = undefined;
|
|
25954
|
-
function compare(v1, v2) {
|
|
25955
|
-
return v1 < v2;
|
|
25956
|
-
}
|
|
25957
|
-
exports2.compare = compare;
|
|
25958
|
-
function upperBound(array, value, comp = compare) {
|
|
25959
|
-
let len = array.length;
|
|
25960
|
-
let i = 0;
|
|
25961
|
-
while (len) {
|
|
25962
|
-
let diff = len >>> 1;
|
|
25963
|
-
let cursor = i + diff;
|
|
25964
|
-
if (comp(value, array[cursor])) {
|
|
25965
|
-
len = diff;
|
|
25966
|
-
} else {
|
|
25967
|
-
i = cursor + 1;
|
|
25968
|
-
len -= diff + 1;
|
|
25969
|
-
}
|
|
25970
|
-
}
|
|
25971
|
-
return i;
|
|
25972
|
-
}
|
|
25973
|
-
exports2.upperBound = upperBound;
|
|
25974
|
-
function lowerBound(array, value, comp = compare) {
|
|
25975
|
-
let len = array.length;
|
|
25976
|
-
let i = 0;
|
|
25977
|
-
while (len) {
|
|
25978
|
-
let diff = len >>> 1;
|
|
25979
|
-
let cursor = i + diff;
|
|
25980
|
-
if (comp(array[cursor], value)) {
|
|
25981
|
-
i = cursor + 1;
|
|
25982
|
-
len -= diff + 1;
|
|
25983
|
-
} else {
|
|
25984
|
-
len = diff;
|
|
25985
|
-
}
|
|
25986
|
-
}
|
|
25987
|
-
return i;
|
|
25988
|
-
}
|
|
25989
|
-
exports2.lowerBound = lowerBound;
|
|
25990
|
-
function binarySearch(array, value, comp = compare) {
|
|
25991
|
-
let cursor = lowerBound(array, value, comp);
|
|
25992
|
-
return cursor !== array.length && !comp(value, array[cursor]);
|
|
25993
|
-
}
|
|
25994
|
-
exports2.binarySearch = binarySearch;
|
|
25995
|
-
});
|
|
25996
|
-
|
|
25997
|
-
// ../node_modules/.bun/structured-source@4.0.0/node_modules/structured-source/lib/structured-source.js
|
|
25998
|
-
var require_structured_source = __commonJS((exports2) => {
|
|
25999
|
-
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
26000
|
-
exports2.StructuredSource = undefined;
|
|
26001
|
-
var boundary_1 = require_lib();
|
|
26002
|
-
|
|
26003
|
-
class StructuredSource {
|
|
26004
|
-
constructor(source) {
|
|
26005
|
-
this.indice = [0];
|
|
26006
|
-
let regexp = /[\r\n\u2028\u2029]/g;
|
|
26007
|
-
const length = source.length;
|
|
26008
|
-
regexp.lastIndex = 0;
|
|
26009
|
-
while (true) {
|
|
26010
|
-
let result = regexp.exec(source);
|
|
26011
|
-
if (!result) {
|
|
26012
|
-
break;
|
|
26013
|
-
}
|
|
26014
|
-
let index = result.index;
|
|
26015
|
-
if (source.charCodeAt(index) === 13 && source.charCodeAt(index + 1) === 10) {
|
|
26016
|
-
index += 1;
|
|
26017
|
-
}
|
|
26018
|
-
let nextIndex = index + 1;
|
|
26019
|
-
if (length < nextIndex) {
|
|
26020
|
-
break;
|
|
26021
|
-
}
|
|
26022
|
-
this.indice.push(nextIndex);
|
|
26023
|
-
regexp.lastIndex = nextIndex;
|
|
26024
|
-
}
|
|
26025
|
-
}
|
|
26026
|
-
get line() {
|
|
26027
|
-
return this.indice.length;
|
|
26028
|
-
}
|
|
26029
|
-
locationToRange(loc) {
|
|
26030
|
-
return [this.positionToIndex(loc.start), this.positionToIndex(loc.end)];
|
|
26031
|
-
}
|
|
26032
|
-
rangeToLocation(range) {
|
|
26033
|
-
return {
|
|
26034
|
-
start: this.indexToPosition(range[0]),
|
|
26035
|
-
end: this.indexToPosition(range[1])
|
|
26036
|
-
};
|
|
26037
|
-
}
|
|
26038
|
-
positionToIndex(pos) {
|
|
26039
|
-
let start = this.indice[pos.line - 1];
|
|
26040
|
-
return start + pos.column;
|
|
26041
|
-
}
|
|
26042
|
-
indexToPosition(index) {
|
|
26043
|
-
const startLine = (0, boundary_1.upperBound)(this.indice, index);
|
|
26044
|
-
return {
|
|
26045
|
-
line: startLine,
|
|
26046
|
-
column: index - this.indice[startLine - 1]
|
|
26047
|
-
};
|
|
26048
|
-
}
|
|
26049
|
-
}
|
|
26050
|
-
exports2.StructuredSource = StructuredSource;
|
|
26051
|
-
});
|
|
26052
|
-
// ../node_modules/.bun/@secretlint+core@12.2.0/node_modules/@secretlint/core/module/SecretLintSourceCodeImpl.js
|
|
26053
|
-
var import_structured_source;
|
|
26054
|
-
var init_SecretLintSourceCodeImpl = __esm(() => {
|
|
26055
|
-
import_structured_source = __toESM(require_structured_source(), 1);
|
|
26056
|
-
});
|
|
26057
|
-
|
|
26058
|
-
// ../node_modules/.bun/@secretlint+core@12.2.0/node_modules/@secretlint/core/module/helper/promise-event-emitter.js
|
|
26059
|
-
class EventEmitter {
|
|
26060
|
-
#listeners = new Map;
|
|
26061
|
-
on(type, listener) {
|
|
26062
|
-
const prevSet = this.#listeners.get(type);
|
|
26063
|
-
const listenerSet = prevSet ?? new Set;
|
|
26064
|
-
listenerSet?.add(listener);
|
|
26065
|
-
this.#listeners.set(type, listenerSet);
|
|
26066
|
-
}
|
|
26067
|
-
emit(type, ...args) {
|
|
26068
|
-
const listenerSet = this.#listeners.get(type);
|
|
26069
|
-
if (!listenerSet) {
|
|
26070
|
-
return;
|
|
26071
|
-
}
|
|
26072
|
-
for (const listenerSetElement of listenerSet) {
|
|
26073
|
-
listenerSetElement(...args);
|
|
26074
|
-
}
|
|
26075
|
-
}
|
|
26076
|
-
off(type, listener) {
|
|
26077
|
-
const listenerSet = this.#listeners.get(type);
|
|
26078
|
-
if (!listenerSet) {
|
|
26079
|
-
return;
|
|
26080
|
-
}
|
|
26081
|
-
for (const listenerSetElement of listenerSet) {
|
|
26082
|
-
if (listenerSetElement === listener) {
|
|
26083
|
-
listenerSet.delete(listener);
|
|
26084
|
-
}
|
|
26085
|
-
}
|
|
26086
|
-
}
|
|
26087
|
-
removeAllListeners() {
|
|
26088
|
-
this.#listeners.clear();
|
|
26089
|
-
}
|
|
26090
|
-
listenerCount(type) {
|
|
26091
|
-
return this.#listeners.get(type)?.size ?? 0;
|
|
26092
|
-
}
|
|
26093
|
-
listeners(type) {
|
|
26094
|
-
return Array.from(this.#listeners.get(type) ?? []);
|
|
25234
|
+
}
|
|
25235
|
+
removeAllListeners() {
|
|
25236
|
+
this.#listeners.clear();
|
|
25237
|
+
}
|
|
25238
|
+
listenerCount(type) {
|
|
25239
|
+
return this.#listeners.get(type)?.size ?? 0;
|
|
25240
|
+
}
|
|
25241
|
+
listeners(type) {
|
|
25242
|
+
return Array.from(this.#listeners.get(type) ?? []);
|
|
26095
25243
|
}
|
|
26096
25244
|
}
|
|
26097
25245
|
// ../node_modules/.bun/@secretlint+core@12.2.0/node_modules/@secretlint/core/module/RuleContext.js
|
|
@@ -27628,253 +26776,1464 @@ function requireLodash_sortby() {
|
|
|
27628
26776
|
return object[key] === srcValue && (srcValue !== undefined || (key in Object(object)));
|
|
27629
26777
|
};
|
|
27630
26778
|
}
|
|
27631
|
-
var stringToPath = memoize(function(string) {
|
|
27632
|
-
string = toString(string);
|
|
27633
|
-
var result = [];
|
|
27634
|
-
if (reLeadingDot.test(string)) {
|
|
27635
|
-
result.push("");
|
|
27636
|
-
}
|
|
27637
|
-
string.replace(rePropName, function(match, number, quote, string2) {
|
|
27638
|
-
result.push(quote ? string2.replace(reEscapeChar, "$1") : number || match);
|
|
27639
|
-
});
|
|
27640
|
-
return result;
|
|
26779
|
+
var stringToPath = memoize(function(string) {
|
|
26780
|
+
string = toString(string);
|
|
26781
|
+
var result = [];
|
|
26782
|
+
if (reLeadingDot.test(string)) {
|
|
26783
|
+
result.push("");
|
|
26784
|
+
}
|
|
26785
|
+
string.replace(rePropName, function(match, number, quote, string2) {
|
|
26786
|
+
result.push(quote ? string2.replace(reEscapeChar, "$1") : number || match);
|
|
26787
|
+
});
|
|
26788
|
+
return result;
|
|
26789
|
+
});
|
|
26790
|
+
function toKey(value) {
|
|
26791
|
+
if (typeof value == "string" || isSymbol(value)) {
|
|
26792
|
+
return value;
|
|
26793
|
+
}
|
|
26794
|
+
var result = value + "";
|
|
26795
|
+
return result == "0" && 1 / value == -Infinity ? "-0" : result;
|
|
26796
|
+
}
|
|
26797
|
+
function toSource(func) {
|
|
26798
|
+
if (func != null) {
|
|
26799
|
+
try {
|
|
26800
|
+
return funcToString.call(func);
|
|
26801
|
+
} catch (e) {}
|
|
26802
|
+
try {
|
|
26803
|
+
return func + "";
|
|
26804
|
+
} catch (e) {}
|
|
26805
|
+
}
|
|
26806
|
+
return "";
|
|
26807
|
+
}
|
|
26808
|
+
var sortBy = baseRest(function(collection, iteratees) {
|
|
26809
|
+
if (collection == null) {
|
|
26810
|
+
return [];
|
|
26811
|
+
}
|
|
26812
|
+
var length = iteratees.length;
|
|
26813
|
+
if (length > 1 && isIterateeCall(collection, iteratees[0], iteratees[1])) {
|
|
26814
|
+
iteratees = [];
|
|
26815
|
+
} else if (length > 2 && isIterateeCall(iteratees[0], iteratees[1], iteratees[2])) {
|
|
26816
|
+
iteratees = [iteratees[0]];
|
|
26817
|
+
}
|
|
26818
|
+
return baseOrderBy(collection, baseFlatten(iteratees), []);
|
|
26819
|
+
});
|
|
26820
|
+
function memoize(func, resolver) {
|
|
26821
|
+
if (typeof func != "function" || resolver && typeof resolver != "function") {
|
|
26822
|
+
throw new TypeError(FUNC_ERROR_TEXT);
|
|
26823
|
+
}
|
|
26824
|
+
var memoized = function() {
|
|
26825
|
+
var args = arguments, key = resolver ? resolver.apply(this, args) : args[0], cache = memoized.cache;
|
|
26826
|
+
if (cache.has(key)) {
|
|
26827
|
+
return cache.get(key);
|
|
26828
|
+
}
|
|
26829
|
+
var result = func.apply(this, args);
|
|
26830
|
+
memoized.cache = cache.set(key, result);
|
|
26831
|
+
return result;
|
|
26832
|
+
};
|
|
26833
|
+
memoized.cache = new (memoize.Cache || MapCache);
|
|
26834
|
+
return memoized;
|
|
26835
|
+
}
|
|
26836
|
+
memoize.Cache = MapCache;
|
|
26837
|
+
function eq(value, other) {
|
|
26838
|
+
return value === other || value !== value && other !== other;
|
|
26839
|
+
}
|
|
26840
|
+
function isArguments(value) {
|
|
26841
|
+
return isArrayLikeObject(value) && hasOwnProperty.call(value, "callee") && (!propertyIsEnumerable.call(value, "callee") || objectToString.call(value) == argsTag);
|
|
26842
|
+
}
|
|
26843
|
+
var isArray2 = Array.isArray;
|
|
26844
|
+
function isArrayLike(value) {
|
|
26845
|
+
return value != null && isLength(value.length) && !isFunction2(value);
|
|
26846
|
+
}
|
|
26847
|
+
function isArrayLikeObject(value) {
|
|
26848
|
+
return isObjectLike(value) && isArrayLike(value);
|
|
26849
|
+
}
|
|
26850
|
+
function isFunction2(value) {
|
|
26851
|
+
var tag = isObject2(value) ? objectToString.call(value) : "";
|
|
26852
|
+
return tag == funcTag || tag == genTag;
|
|
26853
|
+
}
|
|
26854
|
+
function isLength(value) {
|
|
26855
|
+
return typeof value == "number" && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
|
|
26856
|
+
}
|
|
26857
|
+
function isObject2(value) {
|
|
26858
|
+
var type = typeof value;
|
|
26859
|
+
return !!value && (type == "object" || type == "function");
|
|
26860
|
+
}
|
|
26861
|
+
function isObjectLike(value) {
|
|
26862
|
+
return !!value && typeof value == "object";
|
|
26863
|
+
}
|
|
26864
|
+
function isSymbol(value) {
|
|
26865
|
+
return typeof value == "symbol" || isObjectLike(value) && objectToString.call(value) == symbolTag;
|
|
26866
|
+
}
|
|
26867
|
+
var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray;
|
|
26868
|
+
function toString(value) {
|
|
26869
|
+
return value == null ? "" : baseToString(value);
|
|
26870
|
+
}
|
|
26871
|
+
function get(object, path, defaultValue) {
|
|
26872
|
+
var result = object == null ? undefined : baseGet(object, path);
|
|
26873
|
+
return result === undefined ? defaultValue : result;
|
|
26874
|
+
}
|
|
26875
|
+
function hasIn(object, path) {
|
|
26876
|
+
return object != null && hasPath(object, path, baseHasIn);
|
|
26877
|
+
}
|
|
26878
|
+
function keys(object) {
|
|
26879
|
+
return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object);
|
|
26880
|
+
}
|
|
26881
|
+
function identity2(value) {
|
|
26882
|
+
return value;
|
|
26883
|
+
}
|
|
26884
|
+
function property(path) {
|
|
26885
|
+
return isKey(path) ? baseProperty(toKey(path)) : basePropertyDeep(path);
|
|
26886
|
+
}
|
|
26887
|
+
module.exports = sortBy;
|
|
26888
|
+
})(lodash_sortby, lodash_sortby.exports);
|
|
26889
|
+
return lodash_sortby.exports;
|
|
26890
|
+
}
|
|
26891
|
+
function requireEscapeStringRegexp() {
|
|
26892
|
+
if (hasRequiredEscapeStringRegexp)
|
|
26893
|
+
return escapeStringRegexp;
|
|
26894
|
+
hasRequiredEscapeStringRegexp = 1;
|
|
26895
|
+
escapeStringRegexp = (string) => {
|
|
26896
|
+
if (typeof string !== "string") {
|
|
26897
|
+
throw new TypeError("Expected a string");
|
|
26898
|
+
}
|
|
26899
|
+
return string.replace(/[|\\{}()[\]^$+*?.]/g, "\\$&").replace(/-/g, "\\x2d");
|
|
26900
|
+
};
|
|
26901
|
+
return escapeStringRegexp;
|
|
26902
|
+
}
|
|
26903
|
+
function requireRegexpParse() {
|
|
26904
|
+
if (hasRequiredRegexpParse)
|
|
26905
|
+
return regexpParse;
|
|
26906
|
+
hasRequiredRegexpParse = 1;
|
|
26907
|
+
Object.defineProperty(regexpParse, "__esModule", { value: true });
|
|
26908
|
+
regexpParse.isRegExpString = regexpParse.parseRegExpString = undefined;
|
|
26909
|
+
var REGEXP_LITERAL_PATTERN = /^\/(.+)\/([guimysd]*)$/;
|
|
26910
|
+
var parseRegExpString = function(str) {
|
|
26911
|
+
var result = str.match(REGEXP_LITERAL_PATTERN);
|
|
26912
|
+
if (!result) {
|
|
26913
|
+
return null;
|
|
26914
|
+
}
|
|
26915
|
+
return {
|
|
26916
|
+
source: result[1],
|
|
26917
|
+
flagString: result[2]
|
|
26918
|
+
};
|
|
26919
|
+
};
|
|
26920
|
+
regexpParse.parseRegExpString = parseRegExpString;
|
|
26921
|
+
var isRegExpString = function(str) {
|
|
26922
|
+
return REGEXP_LITERAL_PATTERN.test(str);
|
|
26923
|
+
};
|
|
26924
|
+
regexpParse.isRegExpString = isRegExpString;
|
|
26925
|
+
return regexpParse;
|
|
26926
|
+
}
|
|
26927
|
+
function requireRegexpStringMatcher() {
|
|
26928
|
+
if (hasRequiredRegexpStringMatcher)
|
|
26929
|
+
return regexpStringMatcher;
|
|
26930
|
+
hasRequiredRegexpStringMatcher = 1;
|
|
26931
|
+
(function(exports$1) {
|
|
26932
|
+
var __importDefault = regexpStringMatcher && regexpStringMatcher.__importDefault || function(mod) {
|
|
26933
|
+
return mod && mod.__esModule ? mod : { default: mod };
|
|
26934
|
+
};
|
|
26935
|
+
Object.defineProperty(exports$1, "__esModule", { value: true });
|
|
26936
|
+
exports$1.matchPatterns = exports$1.createRegExp = undefined;
|
|
26937
|
+
var lodash_uniq_1 = __importDefault(requireLodash_uniq());
|
|
26938
|
+
var lodash_uniqwith_1 = __importDefault(requireLodash_uniqwith());
|
|
26939
|
+
var lodash_sortby_1 = __importDefault(requireLodash_sortby());
|
|
26940
|
+
var escape_string_regexp_1 = __importDefault(requireEscapeStringRegexp());
|
|
26941
|
+
var regexp_parse_1 = requireRegexpParse();
|
|
26942
|
+
var DEFAULT_FLAGS = "ug";
|
|
26943
|
+
var defaultFlags = function(flagsString) {
|
|
26944
|
+
if (flagsString.length === 0) {
|
|
26945
|
+
return DEFAULT_FLAGS;
|
|
26946
|
+
}
|
|
26947
|
+
return (0, lodash_uniq_1.default)((flagsString + DEFAULT_FLAGS).split("")).join("");
|
|
26948
|
+
};
|
|
26949
|
+
var createRegExp = function(patternString, defaultFlag) {
|
|
26950
|
+
if (defaultFlag === undefined) {
|
|
26951
|
+
defaultFlag = DEFAULT_FLAGS;
|
|
26952
|
+
}
|
|
26953
|
+
if (patternString.length === 0) {
|
|
26954
|
+
throw new Error("Empty string can not handled");
|
|
26955
|
+
}
|
|
26956
|
+
if ((0, regexp_parse_1.isRegExpString)(patternString)) {
|
|
26957
|
+
var regExpStructure = (0, regexp_parse_1.parseRegExpString)(patternString);
|
|
26958
|
+
if (regExpStructure) {
|
|
26959
|
+
return new RegExp(regExpStructure.source, defaultFlags(regExpStructure.flagString));
|
|
26960
|
+
}
|
|
26961
|
+
throw new Error('"'.concat(patternString, '" can not parse as RegExp.'));
|
|
26962
|
+
} else {
|
|
26963
|
+
return new RegExp((0, escape_string_regexp_1.default)(patternString), defaultFlag);
|
|
26964
|
+
}
|
|
26965
|
+
};
|
|
26966
|
+
exports$1.createRegExp = createRegExp;
|
|
26967
|
+
var isEqualMatchPatternResult = function(a, b) {
|
|
26968
|
+
return a.startIndex === b.startIndex && a.endIndex === b.endIndex && a.match === b.match;
|
|
26969
|
+
};
|
|
26970
|
+
var matchPatterns = function(text, regExpLikeStrings) {
|
|
26971
|
+
var matchPatternResults = [];
|
|
26972
|
+
regExpLikeStrings.map(function(patternString) {
|
|
26973
|
+
return (0, exports$1.createRegExp)(patternString);
|
|
26974
|
+
}).forEach(function(regExp) {
|
|
26975
|
+
var results = text.matchAll(regExp);
|
|
26976
|
+
Array.from(results).forEach(function(result) {
|
|
26977
|
+
if (result.index === undefined) {
|
|
26978
|
+
return;
|
|
26979
|
+
}
|
|
26980
|
+
var match = result[0];
|
|
26981
|
+
var index = result.index;
|
|
26982
|
+
matchPatternResults.push({
|
|
26983
|
+
match,
|
|
26984
|
+
captures: result.slice(1),
|
|
26985
|
+
startIndex: index,
|
|
26986
|
+
endIndex: index + match.length
|
|
26987
|
+
});
|
|
26988
|
+
});
|
|
26989
|
+
});
|
|
26990
|
+
var uniqResults = (0, lodash_uniqwith_1.default)(matchPatternResults, isEqualMatchPatternResult);
|
|
26991
|
+
return (0, lodash_sortby_1.default)(uniqResults, ["startIndex", "endIndex"]);
|
|
26992
|
+
};
|
|
26993
|
+
exports$1.matchPatterns = matchPatterns;
|
|
26994
|
+
})(regexpStringMatcher);
|
|
26995
|
+
return regexpStringMatcher;
|
|
26996
|
+
}
|
|
26997
|
+
var commonjsGlobal, regexpStringMatcher, lodash_uniq, hasRequiredLodash_uniq, lodash_uniqwith, hasRequiredLodash_uniqwith, lodash_sortby, hasRequiredLodash_sortby, escapeStringRegexp, hasRequiredEscapeStringRegexp, regexpParse, hasRequiredRegexpParse, hasRequiredRegexpStringMatcher, regexpStringMatcherExports, OID_DATA, OID_SHA1, OID_SHA256, OID_SHA384, OID_SHA512, typeMap;
|
|
26998
|
+
var init_module2 = __esm(() => {
|
|
26999
|
+
commonjsGlobal = typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : {};
|
|
27000
|
+
regexpStringMatcher = {};
|
|
27001
|
+
lodash_sortby = { exports: {} };
|
|
27002
|
+
lodash_sortby.exports;
|
|
27003
|
+
regexpParse = {};
|
|
27004
|
+
regexpStringMatcherExports = requireRegexpStringMatcher();
|
|
27005
|
+
OID_DATA = new Uint8Array([42, 134, 72, 134, 247, 13, 1, 7, 1]);
|
|
27006
|
+
OID_SHA1 = new Uint8Array([43, 14, 3, 2, 26]);
|
|
27007
|
+
OID_SHA256 = new Uint8Array([96, 134, 72, 1, 101, 3, 4, 2, 1]);
|
|
27008
|
+
OID_SHA384 = new Uint8Array([96, 134, 72, 1, 101, 3, 4, 2, 2]);
|
|
27009
|
+
OID_SHA512 = new Uint8Array([96, 134, 72, 1, 101, 3, 4, 2, 3]);
|
|
27010
|
+
typeMap = new Map([
|
|
27011
|
+
["ghp", "GitHub personal access tokens"],
|
|
27012
|
+
["gho", "OAuth access tokens"],
|
|
27013
|
+
["ghu", "GitHub user-to-server tokens"],
|
|
27014
|
+
["ghs", "GitHub server-to-server tokens"],
|
|
27015
|
+
["ghr", "refresh tokens"],
|
|
27016
|
+
["github_pat", "fine-grained personal access tokens"]
|
|
27017
|
+
]);
|
|
27018
|
+
});
|
|
27019
|
+
|
|
27020
|
+
// secret-detect/secretlint-source.ts
|
|
27021
|
+
var init_secretlint_source = __esm(() => {
|
|
27022
|
+
init_module();
|
|
27023
|
+
init_module2();
|
|
27024
|
+
init_suppressor();
|
|
27025
|
+
});
|
|
27026
|
+
|
|
27027
|
+
// secret-detect/index.ts
|
|
27028
|
+
function detectSecrets(text) {
|
|
27029
|
+
if (!text || text.length === 0)
|
|
27030
|
+
return [];
|
|
27031
|
+
const windows = chunk(text);
|
|
27032
|
+
const raw = [];
|
|
27033
|
+
for (const win of windows) {
|
|
27034
|
+
for (const p of ALL_PATTERNS) {
|
|
27035
|
+
const re = new RegExp(p.regex.source, p.regex.flags.includes("g") ? p.regex.flags : p.regex.flags + "g");
|
|
27036
|
+
let m;
|
|
27037
|
+
while ((m = re.exec(win.text)) !== null) {
|
|
27038
|
+
if (m[0].length === 0) {
|
|
27039
|
+
re.lastIndex++;
|
|
27040
|
+
continue;
|
|
27041
|
+
}
|
|
27042
|
+
const cap = p.captureIndex === 0 ? m[0] : m[p.captureIndex];
|
|
27043
|
+
if (!cap)
|
|
27044
|
+
continue;
|
|
27045
|
+
const matchStart = p.captureIndex === 0 ? m.index : m.index + m[0].indexOf(cap);
|
|
27046
|
+
if (matchStart < 0)
|
|
27047
|
+
continue;
|
|
27048
|
+
const globalStart = win.offset + matchStart;
|
|
27049
|
+
const globalEnd = globalStart + cap.length;
|
|
27050
|
+
const keyName = p.rule_id === "env_key_value" ? m[1] : undefined;
|
|
27051
|
+
if (p.rule_id === "env_key_value") {
|
|
27052
|
+
const ENV_KV_MIN_LEN = 12;
|
|
27053
|
+
const ENV_KV_MIN_ENTROPY = 3.5;
|
|
27054
|
+
if (cap.length < ENV_KV_MIN_LEN)
|
|
27055
|
+
continue;
|
|
27056
|
+
if (shannonEntropy(cap) < ENV_KV_MIN_ENTROPY)
|
|
27057
|
+
continue;
|
|
27058
|
+
}
|
|
27059
|
+
raw.push({
|
|
27060
|
+
rule_id: p.rule_id,
|
|
27061
|
+
start: globalStart,
|
|
27062
|
+
end: globalEnd,
|
|
27063
|
+
matched_text: cap,
|
|
27064
|
+
key_name: keyName,
|
|
27065
|
+
confidence: "high"
|
|
27066
|
+
});
|
|
27067
|
+
}
|
|
27068
|
+
}
|
|
27069
|
+
const kvHits = scanKeyValue(win.text);
|
|
27070
|
+
for (const h of kvHits) {
|
|
27071
|
+
raw.push({ ...h, start: h.start + win.offset, end: h.end + win.offset });
|
|
27072
|
+
}
|
|
27073
|
+
}
|
|
27074
|
+
const deduped = dedupeRaw(raw);
|
|
27075
|
+
const final = dropOverlaps(deduped);
|
|
27076
|
+
const existing = new Set;
|
|
27077
|
+
const out = [];
|
|
27078
|
+
for (const h of final) {
|
|
27079
|
+
const suggested_slug = deriveSlug({ key_name: h.key_name, rule_id: h.rule_id }, existing);
|
|
27080
|
+
existing.add(suggested_slug);
|
|
27081
|
+
out.push({
|
|
27082
|
+
rule_id: h.rule_id,
|
|
27083
|
+
matched_text: h.matched_text,
|
|
27084
|
+
start: h.start,
|
|
27085
|
+
end: h.end,
|
|
27086
|
+
confidence: h.confidence,
|
|
27087
|
+
suppressed: isSuppressed(text, h.start, h.end),
|
|
27088
|
+
suggested_slug,
|
|
27089
|
+
key_name: h.key_name
|
|
27090
|
+
});
|
|
27091
|
+
}
|
|
27092
|
+
out.sort((a, b) => a.start - b.start);
|
|
27093
|
+
return out;
|
|
27094
|
+
}
|
|
27095
|
+
function dedupeRaw(raw) {
|
|
27096
|
+
const seen = new Map;
|
|
27097
|
+
for (const h of raw) {
|
|
27098
|
+
const key = `${h.start}:${h.end}`;
|
|
27099
|
+
const existing = seen.get(key);
|
|
27100
|
+
if (!existing) {
|
|
27101
|
+
seen.set(key, h);
|
|
27102
|
+
continue;
|
|
27103
|
+
}
|
|
27104
|
+
if (existing.confidence === "ambiguous" && h.confidence === "high") {
|
|
27105
|
+
seen.set(key, h);
|
|
27106
|
+
}
|
|
27107
|
+
}
|
|
27108
|
+
return Array.from(seen.values());
|
|
27109
|
+
}
|
|
27110
|
+
function dropOverlaps(hits) {
|
|
27111
|
+
const sorted = [...hits].sort((a, b) => a.end - a.start - (b.end - b.start));
|
|
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
|
+
}
|
|
27118
|
+
out.sort((a, b) => a.start - b.start || a.end - b.end);
|
|
27119
|
+
return out;
|
|
27120
|
+
}
|
|
27121
|
+
var init_secret_detect = __esm(() => {
|
|
27122
|
+
init_patterns();
|
|
27123
|
+
init_kv_scanner();
|
|
27124
|
+
init_chunker();
|
|
27125
|
+
init_suppressor();
|
|
27126
|
+
init_url_redact();
|
|
27127
|
+
init_secretlint_source();
|
|
27128
|
+
});
|
|
27129
|
+
|
|
27130
|
+
// secret-detect/redact.ts
|
|
27131
|
+
function redact(text) {
|
|
27132
|
+
if (!text || text.length === 0)
|
|
27133
|
+
return text;
|
|
27134
|
+
const urlScrubbed = redactUrls(text);
|
|
27135
|
+
const hits = detectSecrets(urlScrubbed);
|
|
27136
|
+
if (hits.length === 0)
|
|
27137
|
+
return urlScrubbed;
|
|
27138
|
+
const sorted = [...hits].sort((a, b) => b.start - a.start);
|
|
27139
|
+
let out = urlScrubbed;
|
|
27140
|
+
for (const h of sorted) {
|
|
27141
|
+
out = out.slice(0, h.start) + redactedMarker(h.rule_id) + out.slice(h.end);
|
|
27142
|
+
}
|
|
27143
|
+
return out;
|
|
27144
|
+
}
|
|
27145
|
+
function redactedMarker(ruleId) {
|
|
27146
|
+
const trimmed = ruleId.replace(/^(kv|env)_/, "");
|
|
27147
|
+
if (!trimmed || trimmed === "key_value" || trimmed === "kv_entropy") {
|
|
27148
|
+
return REDACTED_MARKER;
|
|
27149
|
+
}
|
|
27150
|
+
return `[REDACTED:${trimmed}]`;
|
|
27151
|
+
}
|
|
27152
|
+
var REDACTED_MARKER = "[REDACTED]";
|
|
27153
|
+
var init_redact = __esm(() => {
|
|
27154
|
+
init_secret_detect();
|
|
27155
|
+
init_url_redact();
|
|
27156
|
+
});
|
|
27157
|
+
|
|
27158
|
+
// history.ts
|
|
27159
|
+
var exports_history = {};
|
|
27160
|
+
__export(exports_history, {
|
|
27161
|
+
recordReaction: () => recordReaction,
|
|
27162
|
+
recordOutbound: () => recordOutbound,
|
|
27163
|
+
recordInbound: () => recordInbound,
|
|
27164
|
+
recordEdit: () => recordEdit,
|
|
27165
|
+
query: () => query,
|
|
27166
|
+
pruneMessagesOlderThanDays: () => pruneMessagesOlderThanDays,
|
|
27167
|
+
lookupMessageRoleAndText: () => lookupMessageRoleAndText,
|
|
27168
|
+
initHistory: () => initHistory,
|
|
27169
|
+
getRecentOutboundCount: () => getRecentOutboundCount,
|
|
27170
|
+
getLatestInboundMessageId: () => getLatestInboundMessageId,
|
|
27171
|
+
deleteFromHistory: () => deleteFromHistory,
|
|
27172
|
+
checkpointWal: () => checkpointWal,
|
|
27173
|
+
_resetForTests: () => _resetForTests
|
|
27174
|
+
});
|
|
27175
|
+
import { chmodSync as chmodSync2, mkdirSync as mkdirSync9 } from "fs";
|
|
27176
|
+
import { join as join11 } from "path";
|
|
27177
|
+
function loadDatabaseClass() {
|
|
27178
|
+
if (DatabaseClass != null)
|
|
27179
|
+
return DatabaseClass;
|
|
27180
|
+
try {
|
|
27181
|
+
const metaRequire = import.meta.require;
|
|
27182
|
+
if (typeof metaRequire !== "function") {
|
|
27183
|
+
throw new Error("import.meta.require not available \u2014 Bun runtime required");
|
|
27184
|
+
}
|
|
27185
|
+
const mod = metaRequire("bun:sqlite");
|
|
27186
|
+
if (!mod.Database)
|
|
27187
|
+
throw new Error("bun:sqlite did not export Database");
|
|
27188
|
+
DatabaseClass = mod.Database;
|
|
27189
|
+
return DatabaseClass;
|
|
27190
|
+
} catch (err) {
|
|
27191
|
+
throw new Error(`history.ts requires Bun runtime (bun:sqlite). Caller: ${err.message}`);
|
|
27192
|
+
}
|
|
27193
|
+
}
|
|
27194
|
+
function initHistory(stateDir, retentionDays = 30) {
|
|
27195
|
+
if (db != null)
|
|
27196
|
+
return;
|
|
27197
|
+
const Database = loadDatabaseClass();
|
|
27198
|
+
mkdirSync9(stateDir, { recursive: true, mode: 448 });
|
|
27199
|
+
const path = join11(stateDir, "history.db");
|
|
27200
|
+
db = new Database(path, { create: true });
|
|
27201
|
+
db.exec("PRAGMA journal_mode = WAL");
|
|
27202
|
+
db.exec("PRAGMA synchronous = NORMAL");
|
|
27203
|
+
db.exec(`
|
|
27204
|
+
CREATE TABLE IF NOT EXISTS messages (
|
|
27205
|
+
chat_id TEXT NOT NULL,
|
|
27206
|
+
thread_id INTEGER,
|
|
27207
|
+
message_id INTEGER NOT NULL,
|
|
27208
|
+
role TEXT NOT NULL,
|
|
27209
|
+
user TEXT,
|
|
27210
|
+
user_id TEXT,
|
|
27211
|
+
ts INTEGER NOT NULL,
|
|
27212
|
+
text TEXT NOT NULL,
|
|
27213
|
+
attachment_kind TEXT,
|
|
27214
|
+
group_id INTEGER,
|
|
27215
|
+
reply_to_message_id INTEGER,
|
|
27216
|
+
reply_to_text TEXT,
|
|
27217
|
+
PRIMARY KEY (chat_id, thread_id, message_id)
|
|
27218
|
+
)
|
|
27219
|
+
`);
|
|
27220
|
+
db.exec(`
|
|
27221
|
+
CREATE INDEX IF NOT EXISTS idx_messages_recent
|
|
27222
|
+
ON messages (chat_id, thread_id, ts DESC)
|
|
27223
|
+
`);
|
|
27224
|
+
for (const column of ["reply_to_message_id INTEGER", "reply_to_text TEXT", "user_reaction TEXT"]) {
|
|
27225
|
+
try {
|
|
27226
|
+
db.exec(`ALTER TABLE messages ADD COLUMN ${column}`);
|
|
27227
|
+
} catch (err) {
|
|
27228
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
27229
|
+
if (!/duplicate column name/i.test(msg))
|
|
27230
|
+
throw err;
|
|
27231
|
+
}
|
|
27232
|
+
}
|
|
27233
|
+
try {
|
|
27234
|
+
chmodSync2(path, 384);
|
|
27235
|
+
} catch {}
|
|
27236
|
+
if (retentionDays > 0) {
|
|
27237
|
+
const cutoff = Math.floor(Date.now() / 1000) - retentionDays * 86400;
|
|
27238
|
+
db.prepare("DELETE FROM messages WHERE ts < ?").run(cutoff);
|
|
27239
|
+
}
|
|
27240
|
+
}
|
|
27241
|
+
function _resetForTests() {
|
|
27242
|
+
if (db != null) {
|
|
27243
|
+
db.close();
|
|
27244
|
+
db = null;
|
|
27245
|
+
}
|
|
27246
|
+
}
|
|
27247
|
+
function checkpointWal() {
|
|
27248
|
+
if (db == null)
|
|
27249
|
+
return false;
|
|
27250
|
+
try {
|
|
27251
|
+
db.prepare("PRAGMA wal_checkpoint(TRUNCATE)").run();
|
|
27252
|
+
return true;
|
|
27253
|
+
} catch {
|
|
27254
|
+
return false;
|
|
27255
|
+
}
|
|
27256
|
+
}
|
|
27257
|
+
function pruneMessagesOlderThanDays(retentionDays, nowSec, batchLimit = 5000) {
|
|
27258
|
+
if (db == null)
|
|
27259
|
+
return 0;
|
|
27260
|
+
if (retentionDays <= 0)
|
|
27261
|
+
return 0;
|
|
27262
|
+
const cutoffSec = (nowSec ?? Math.floor(Date.now() / 1000)) - retentionDays * 86400;
|
|
27263
|
+
const stmt = db.prepare(`
|
|
27264
|
+
DELETE FROM messages
|
|
27265
|
+
WHERE rowid IN (
|
|
27266
|
+
SELECT rowid FROM messages WHERE ts < ? LIMIT ?
|
|
27267
|
+
)
|
|
27268
|
+
`);
|
|
27269
|
+
let total = 0;
|
|
27270
|
+
for (let i = 0;i < 1000; i++) {
|
|
27271
|
+
const result = stmt.run(cutoffSec, batchLimit);
|
|
27272
|
+
const n = result.changes ?? 0;
|
|
27273
|
+
total += n;
|
|
27274
|
+
if (n === 0)
|
|
27275
|
+
break;
|
|
27276
|
+
}
|
|
27277
|
+
return total;
|
|
27278
|
+
}
|
|
27279
|
+
function requireDb() {
|
|
27280
|
+
if (db == null) {
|
|
27281
|
+
throw new Error("history: initHistory() must be called before any record/query operation");
|
|
27282
|
+
}
|
|
27283
|
+
return db;
|
|
27284
|
+
}
|
|
27285
|
+
function recordInbound(args) {
|
|
27286
|
+
if (args.message_id == null)
|
|
27287
|
+
return;
|
|
27288
|
+
const stmt = requireDb().prepare(`
|
|
27289
|
+
INSERT OR REPLACE INTO messages
|
|
27290
|
+
(chat_id, thread_id, message_id, role, user, user_id, ts, text, attachment_kind, group_id, reply_to_message_id, reply_to_text)
|
|
27291
|
+
VALUES (?, ?, ?, 'user', ?, ?, ?, ?, ?, NULL, ?, ?)
|
|
27292
|
+
`);
|
|
27293
|
+
stmt.run(args.chat_id, args.thread_id ?? null, args.message_id, args.user ?? null, args.user_id ?? null, args.ts, redact(args.text), args.attachment_kind ?? null, args.reply_to_message_id ?? null, args.reply_to_text != null ? redact(args.reply_to_text) : args.reply_to_text ?? null);
|
|
27294
|
+
}
|
|
27295
|
+
function recordOutbound(args) {
|
|
27296
|
+
if (args.message_ids.length === 0)
|
|
27297
|
+
return;
|
|
27298
|
+
const ts = args.ts ?? Math.floor(Date.now() / 1000);
|
|
27299
|
+
const groupId = args.message_ids[0];
|
|
27300
|
+
const stmt = requireDb().prepare(`
|
|
27301
|
+
INSERT OR REPLACE INTO messages
|
|
27302
|
+
(chat_id, thread_id, message_id, role, user, user_id, ts, text, attachment_kind, group_id)
|
|
27303
|
+
VALUES (?, ?, ?, 'assistant', NULL, NULL, ?, ?, ?, ?)
|
|
27304
|
+
`);
|
|
27305
|
+
const tx = requireDb().transaction((rows2) => {
|
|
27306
|
+
for (const [msgId, text, attachKind] of rows2) {
|
|
27307
|
+
stmt.run(args.chat_id, args.thread_id ?? null, msgId, ts, text, attachKind, groupId);
|
|
27308
|
+
}
|
|
27309
|
+
});
|
|
27310
|
+
const rows = args.message_ids.map((id, i) => [
|
|
27311
|
+
id,
|
|
27312
|
+
redact(args.texts[i] ?? ""),
|
|
27313
|
+
args.attachment_kinds?.[i] ?? null
|
|
27314
|
+
]);
|
|
27315
|
+
tx(rows);
|
|
27316
|
+
}
|
|
27317
|
+
function recordEdit(args) {
|
|
27318
|
+
requireDb().prepare(`
|
|
27319
|
+
UPDATE messages
|
|
27320
|
+
SET text = ?
|
|
27321
|
+
WHERE chat_id = ? AND message_id = ?
|
|
27322
|
+
`).run(redact(args.text), args.chat_id, args.message_id);
|
|
27323
|
+
}
|
|
27324
|
+
function recordReaction(args) {
|
|
27325
|
+
requireDb().prepare(`
|
|
27326
|
+
UPDATE messages
|
|
27327
|
+
SET user_reaction = ?
|
|
27328
|
+
WHERE chat_id = ? AND message_id = ?
|
|
27329
|
+
`).run(args.emoji, args.chat_id, args.message_id);
|
|
27330
|
+
}
|
|
27331
|
+
function deleteFromHistory(args) {
|
|
27332
|
+
requireDb().prepare(`
|
|
27333
|
+
DELETE FROM messages
|
|
27334
|
+
WHERE chat_id = ? AND message_id = ?
|
|
27335
|
+
`).run(args.chat_id, args.message_id);
|
|
27336
|
+
}
|
|
27337
|
+
function getLatestInboundMessageId(chatId, threadId) {
|
|
27338
|
+
const params = [chatId];
|
|
27339
|
+
let sql = "SELECT message_id FROM messages WHERE chat_id = ? AND role = 'user'";
|
|
27340
|
+
if (threadId !== undefined) {
|
|
27341
|
+
if (threadId === null) {
|
|
27342
|
+
sql += " AND thread_id IS NULL";
|
|
27343
|
+
} else {
|
|
27344
|
+
sql += " AND thread_id = ?";
|
|
27345
|
+
params.push(threadId);
|
|
27346
|
+
}
|
|
27347
|
+
}
|
|
27348
|
+
sql += " ORDER BY ts DESC, message_id DESC LIMIT 1";
|
|
27349
|
+
const row = requireDb().prepare(sql).get(...params);
|
|
27350
|
+
return row?.message_id ?? null;
|
|
27351
|
+
}
|
|
27352
|
+
function lookupMessageRoleAndText(chatId, messageId) {
|
|
27353
|
+
const row = requireDb().prepare(`SELECT role, text FROM messages WHERE chat_id = ? AND message_id = ? LIMIT 1`).get(chatId, messageId);
|
|
27354
|
+
if (!row)
|
|
27355
|
+
return null;
|
|
27356
|
+
return { role: row.role, text: row.text ?? "" };
|
|
27357
|
+
}
|
|
27358
|
+
function getRecentOutboundCount(chatId, withinSeconds) {
|
|
27359
|
+
const cutoff = Math.floor(Date.now() / 1000) - withinSeconds;
|
|
27360
|
+
const row = requireDb().prepare("SELECT COUNT(*) as cnt FROM messages WHERE chat_id = ? AND role = ? AND ts >= ?").get(chatId, "assistant", cutoff);
|
|
27361
|
+
return row?.cnt ?? 0;
|
|
27362
|
+
}
|
|
27363
|
+
function query(opts) {
|
|
27364
|
+
const limit = Math.min(MAX_LIMIT, Math.max(1, opts.limit ?? DEFAULT_LIMIT));
|
|
27365
|
+
const params = [opts.chat_id];
|
|
27366
|
+
let sql = "SELECT * FROM messages WHERE chat_id = ?";
|
|
27367
|
+
if (opts.thread_id !== undefined) {
|
|
27368
|
+
if (opts.thread_id === null) {
|
|
27369
|
+
sql += " AND thread_id IS NULL";
|
|
27370
|
+
} else {
|
|
27371
|
+
sql += " AND thread_id = ?";
|
|
27372
|
+
params.push(opts.thread_id);
|
|
27373
|
+
}
|
|
27374
|
+
}
|
|
27375
|
+
if (opts.before_message_id != null) {
|
|
27376
|
+
sql += " AND message_id < ?";
|
|
27377
|
+
params.push(opts.before_message_id);
|
|
27378
|
+
}
|
|
27379
|
+
sql += " ORDER BY ts DESC, message_id DESC LIMIT ?";
|
|
27380
|
+
params.push(limit);
|
|
27381
|
+
const rows = requireDb().prepare(sql).all(...params);
|
|
27382
|
+
rows.reverse();
|
|
27383
|
+
return rows;
|
|
27384
|
+
}
|
|
27385
|
+
var DatabaseClass = null, DEFAULT_LIMIT = 10, MAX_LIMIT = 50, db = null;
|
|
27386
|
+
var init_history = __esm(() => {
|
|
27387
|
+
init_redact();
|
|
27388
|
+
});
|
|
27389
|
+
|
|
27390
|
+
// quota-check.ts
|
|
27391
|
+
import { readFileSync as readFileSync8, existsSync as existsSync12 } from "fs";
|
|
27392
|
+
import { join as join12 } from "path";
|
|
27393
|
+
function readOauthToken(claudeConfigDir) {
|
|
27394
|
+
const tokenFile = join12(claudeConfigDir, ".oauth-token");
|
|
27395
|
+
if (!existsSync12(tokenFile))
|
|
27396
|
+
return null;
|
|
27397
|
+
try {
|
|
27398
|
+
const raw = readFileSync8(tokenFile, "utf-8").trim();
|
|
27399
|
+
return raw.length > 0 ? raw : null;
|
|
27400
|
+
} catch {
|
|
27401
|
+
return null;
|
|
27402
|
+
}
|
|
27403
|
+
}
|
|
27404
|
+
function parseFloatHeader(headers, name) {
|
|
27405
|
+
const v = headers.get(name);
|
|
27406
|
+
if (v == null || v.trim().length === 0)
|
|
27407
|
+
return null;
|
|
27408
|
+
const n = Number(v);
|
|
27409
|
+
return Number.isFinite(n) ? n : null;
|
|
27410
|
+
}
|
|
27411
|
+
function parseEpochHeader(headers, name) {
|
|
27412
|
+
const v = headers.get(name);
|
|
27413
|
+
if (v == null)
|
|
27414
|
+
return null;
|
|
27415
|
+
const n = Number(v);
|
|
27416
|
+
if (!Number.isFinite(n) || n <= 0)
|
|
27417
|
+
return null;
|
|
27418
|
+
return new Date(n * 1000);
|
|
27419
|
+
}
|
|
27420
|
+
function parseQuotaHeaders(headers) {
|
|
27421
|
+
const fiveHour = parseFloatHeader(headers, "anthropic-ratelimit-unified-5h-utilization");
|
|
27422
|
+
const sevenDay = parseFloatHeader(headers, "anthropic-ratelimit-unified-7d-utilization");
|
|
27423
|
+
if (fiveHour == null && sevenDay == null) {
|
|
27424
|
+
return {
|
|
27425
|
+
ok: false,
|
|
27426
|
+
reason: "no unified rate-limit headers in response (API token, not OAuth?)"
|
|
27427
|
+
};
|
|
27428
|
+
}
|
|
27429
|
+
return {
|
|
27430
|
+
ok: true,
|
|
27431
|
+
data: {
|
|
27432
|
+
fiveHourUtilizationPct: (fiveHour ?? 0) * 100,
|
|
27433
|
+
sevenDayUtilizationPct: (sevenDay ?? 0) * 100,
|
|
27434
|
+
fiveHourResetAt: parseEpochHeader(headers, "anthropic-ratelimit-unified-5h-reset"),
|
|
27435
|
+
sevenDayResetAt: parseEpochHeader(headers, "anthropic-ratelimit-unified-7d-reset"),
|
|
27436
|
+
representativeClaim: headers.get("anthropic-ratelimit-unified-representative-claim"),
|
|
27437
|
+
overageStatus: headers.get("anthropic-ratelimit-unified-overage-status"),
|
|
27438
|
+
overageDisabledReason: headers.get("anthropic-ratelimit-unified-overage-disabled-reason")
|
|
27439
|
+
}
|
|
27440
|
+
};
|
|
27441
|
+
}
|
|
27442
|
+
async function fetchQuota(opts) {
|
|
27443
|
+
let token;
|
|
27444
|
+
if (opts.accessToken && opts.claudeConfigDir) {
|
|
27445
|
+
return {
|
|
27446
|
+
ok: false,
|
|
27447
|
+
reason: "pass only one of `accessToken` or `claudeConfigDir`, not both"
|
|
27448
|
+
};
|
|
27449
|
+
}
|
|
27450
|
+
if (opts.accessToken) {
|
|
27451
|
+
token = opts.accessToken.trim().length > 0 ? opts.accessToken : null;
|
|
27452
|
+
} else if (opts.claudeConfigDir) {
|
|
27453
|
+
token = readOauthToken(opts.claudeConfigDir);
|
|
27454
|
+
} else {
|
|
27455
|
+
return {
|
|
27456
|
+
ok: false,
|
|
27457
|
+
reason: "fetchQuota requires `accessToken` or `claudeConfigDir`"
|
|
27458
|
+
};
|
|
27459
|
+
}
|
|
27460
|
+
if (!token) {
|
|
27461
|
+
return { ok: false, reason: "no OAuth token at .oauth-token" };
|
|
27462
|
+
}
|
|
27463
|
+
const controller = new AbortController;
|
|
27464
|
+
const timeout = setTimeout(() => controller.abort(), opts.timeoutMs ?? 1e4);
|
|
27465
|
+
const fetchFn = opts.fetchImpl ?? fetch;
|
|
27466
|
+
let resp;
|
|
27467
|
+
try {
|
|
27468
|
+
resp = await fetchFn("https://api.anthropic.com/v1/messages", {
|
|
27469
|
+
method: "POST",
|
|
27470
|
+
headers: {
|
|
27471
|
+
"anthropic-version": "2023-06-01",
|
|
27472
|
+
"anthropic-beta": OAUTH_BETA,
|
|
27473
|
+
authorization: `Bearer ${token}`,
|
|
27474
|
+
"x-app": "cli",
|
|
27475
|
+
"user-agent": DEFAULT_USER_AGENT,
|
|
27476
|
+
"content-type": "application/json"
|
|
27477
|
+
},
|
|
27478
|
+
body: JSON.stringify({
|
|
27479
|
+
model: opts.model ?? DEFAULT_PROBE_MODEL,
|
|
27480
|
+
max_tokens: 1,
|
|
27481
|
+
messages: [{ role: "user", content: "hi" }]
|
|
27482
|
+
}),
|
|
27483
|
+
signal: controller.signal
|
|
27484
|
+
});
|
|
27485
|
+
} catch (err) {
|
|
27486
|
+
const msg = err?.message ?? String(err);
|
|
27487
|
+
return { ok: false, reason: `request failed: ${msg}` };
|
|
27488
|
+
} finally {
|
|
27489
|
+
clearTimeout(timeout);
|
|
27490
|
+
}
|
|
27491
|
+
if (resp.status === 401 || resp.status === 403) {
|
|
27492
|
+
return { ok: false, reason: `auth rejected (HTTP ${resp.status})` };
|
|
27493
|
+
}
|
|
27494
|
+
const parsed = parseQuotaHeaders(resp.headers);
|
|
27495
|
+
if (!parsed.ok && resp.status >= 400) {
|
|
27496
|
+
return { ok: false, reason: `HTTP ${resp.status}, ${parsed.reason}` };
|
|
27497
|
+
}
|
|
27498
|
+
return parsed;
|
|
27499
|
+
}
|
|
27500
|
+
function formatQuotaLine(q) {
|
|
27501
|
+
const fmt = (n) => `${Math.round(n)}%`;
|
|
27502
|
+
return `${fmt(q.fiveHourUtilizationPct)} / 5h \u00b7 ${fmt(q.sevenDayUtilizationPct)} / 7d`;
|
|
27503
|
+
}
|
|
27504
|
+
function formatResetRelative(target, now = new Date) {
|
|
27505
|
+
if (!target)
|
|
27506
|
+
return "\u2014";
|
|
27507
|
+
const deltaMs = target.getTime() - now.getTime();
|
|
27508
|
+
if (deltaMs <= 0)
|
|
27509
|
+
return "resets now";
|
|
27510
|
+
const totalMin = Math.round(deltaMs / 60000);
|
|
27511
|
+
if (totalMin < 60)
|
|
27512
|
+
return `resets in ${totalMin}m`;
|
|
27513
|
+
const hours = Math.floor(totalMin / 60);
|
|
27514
|
+
const mins = totalMin % 60;
|
|
27515
|
+
if (hours < 24)
|
|
27516
|
+
return mins > 0 ? `resets in ${hours}h ${mins}m` : `resets in ${hours}h`;
|
|
27517
|
+
const days = Math.floor(hours / 24);
|
|
27518
|
+
const remH = hours % 24;
|
|
27519
|
+
return remH > 0 ? `resets in ${days}d ${remH}h` : `resets in ${days}d`;
|
|
27520
|
+
}
|
|
27521
|
+
var OAUTH_BETA = "oauth-2025-04-20", DEFAULT_USER_AGENT = "claude-cli/1.0.0 (external, cli)", DEFAULT_PROBE_MODEL = "claude-haiku-4-5-20251001";
|
|
27522
|
+
var init_quota_check = () => {};
|
|
27523
|
+
|
|
27524
|
+
// ../src/vault/broker/peercred-ffi.ts
|
|
27525
|
+
function getPeerCred(fd) {
|
|
27526
|
+
if (process.platform !== "linux")
|
|
27527
|
+
return null;
|
|
27528
|
+
try {
|
|
27529
|
+
const ffi = __require("bun:ffi");
|
|
27530
|
+
const { dlopen, FFIType, ptr } = ffi;
|
|
27531
|
+
const SOL_SOCKET = 1;
|
|
27532
|
+
const SO_PEERCRED = 17;
|
|
27533
|
+
const UCRED_SIZE = 12;
|
|
27534
|
+
const cache = getPeerCred;
|
|
27535
|
+
const lib = cache._lib ?? (() => {
|
|
27536
|
+
const candidates = ["libc.so.6", "libc.so"];
|
|
27537
|
+
const symbolSpec = {
|
|
27538
|
+
getsockopt: {
|
|
27539
|
+
args: [FFIType.i32, FFIType.i32, FFIType.i32, FFIType.ptr, FFIType.ptr],
|
|
27540
|
+
returns: FFIType.i32
|
|
27541
|
+
}
|
|
27542
|
+
};
|
|
27543
|
+
const errors3 = [];
|
|
27544
|
+
for (const name of candidates) {
|
|
27545
|
+
try {
|
|
27546
|
+
const opened = dlopen(name, symbolSpec);
|
|
27547
|
+
cache._lib = opened;
|
|
27548
|
+
return opened;
|
|
27549
|
+
} catch (e) {
|
|
27550
|
+
errors3.push(`${name}: ${e instanceof Error ? e.message : String(e)}`);
|
|
27551
|
+
}
|
|
27552
|
+
}
|
|
27553
|
+
process.stderr.write(`[vault-broker] peercred-ffi: dlopen failed for all libc candidates ` + `(${errors3.join("; ")}); falling back to ss-parsing.
|
|
27554
|
+
`);
|
|
27555
|
+
throw new Error("no libc candidate could be opened");
|
|
27556
|
+
})();
|
|
27557
|
+
const credBuf = new ArrayBuffer(UCRED_SIZE);
|
|
27558
|
+
const lenBuf = new Uint32Array(1);
|
|
27559
|
+
lenBuf[0] = UCRED_SIZE;
|
|
27560
|
+
const rc = lib.symbols.getsockopt(fd, SOL_SOCKET, SO_PEERCRED, ptr(credBuf), ptr(lenBuf.buffer));
|
|
27561
|
+
if (rc !== 0)
|
|
27562
|
+
return null;
|
|
27563
|
+
if (lenBuf[0] !== UCRED_SIZE)
|
|
27564
|
+
return null;
|
|
27565
|
+
const view = new DataView(credBuf);
|
|
27566
|
+
return {
|
|
27567
|
+
pid: view.getInt32(0, true),
|
|
27568
|
+
uid: view.getInt32(4, true),
|
|
27569
|
+
gid: view.getInt32(8, true)
|
|
27570
|
+
};
|
|
27571
|
+
} catch {
|
|
27572
|
+
return null;
|
|
27573
|
+
}
|
|
27574
|
+
}
|
|
27575
|
+
|
|
27576
|
+
// ../src/vault/broker/peercred.ts
|
|
27577
|
+
function isReservedAgentName(name) {
|
|
27578
|
+
return RESERVED_AGENT_NAMES.has(name);
|
|
27579
|
+
}
|
|
27580
|
+
function unlockSocketFor(dataSocketPath) {
|
|
27581
|
+
if (dataSocketPath.endsWith("/sock")) {
|
|
27582
|
+
return dataSocketPath.slice(0, -"/sock".length) + "/unlock";
|
|
27583
|
+
}
|
|
27584
|
+
return dataSocketPath.replace(/\.sock$/, ".unlock.sock");
|
|
27585
|
+
}
|
|
27586
|
+
var RESERVED_AGENT_NAMES;
|
|
27587
|
+
var init_peercred = __esm(() => {
|
|
27588
|
+
RESERVED_AGENT_NAMES = new Set(["operator", "hostd"]);
|
|
27589
|
+
});
|
|
27590
|
+
|
|
27591
|
+
// ../src/vault/broker/protocol.ts
|
|
27592
|
+
function encodeRequest2(req) {
|
|
27593
|
+
const json = JSON.stringify(req);
|
|
27594
|
+
if (Buffer.byteLength(json, "utf8") > MAX_FRAME_BYTES2) {
|
|
27595
|
+
throw new Error(`Request frame too large (${Buffer.byteLength(json, "utf8")} bytes; max ${MAX_FRAME_BYTES2})`);
|
|
27596
|
+
}
|
|
27597
|
+
return json + `
|
|
27598
|
+
`;
|
|
27599
|
+
}
|
|
27600
|
+
function decodeResponse2(line) {
|
|
27601
|
+
if (Buffer.byteLength(line, "utf8") > MAX_FRAME_BYTES2) {
|
|
27602
|
+
throw new RangeError(`Response frame too large (${Buffer.byteLength(line, "utf8")} bytes; max ${MAX_FRAME_BYTES2})`);
|
|
27603
|
+
}
|
|
27604
|
+
const obj = JSON.parse(line);
|
|
27605
|
+
return ResponseSchema2.parse(obj);
|
|
27606
|
+
}
|
|
27607
|
+
var MAX_FRAME_BYTES2, AgentNameSchema, GetRequestSchema, PutRequestSchema, ListRequestSchema, MintGrantRequestSchema, ListGrantsRequestSchema, RevokeGrantRequestSchema, StatusRequestSchema, LockRequestSchema, PreflightAccessRequestSchema, OkPreflightAccessResponseSchema, ApprovalRequestRequestSchema, ApprovalLookupRequestSchema, ApprovalConsumeRequestSchema, ApprovalRevokeRequestSchema, ApprovalListRequestSchema, ApprovalDecisionModeSchema, ApprovalRecordRequestSchema, ApprovalConsumeRecordRequestSchema, RequestSchema2, VaultEntrySchema, ErrorCode, OkEntryResponseSchema, OkKeysResponseSchema, BrokerStatus, OkStatusResponseSchema, OkLockResponseSchema, OkPutResponseSchema, OkMintGrantResponseSchema, GrantMetaSchema, OkListGrantsResponseSchema, OkRevokeGrantResponseSchema, OkApprovalRequestResponseSchema, ApprovalDecisionMetaSchema, OkApprovalLookupResponseSchema, OkApprovalConsumeResponseSchema, OkApprovalRevokeResponseSchema, OkApprovalListResponseSchema, OkApprovalRecordResponseSchema, OkApprovalConsumeRecordResponseSchema, ErrorResponseSchema2, ResponseSchema2;
|
|
27608
|
+
var init_protocol2 = __esm(() => {
|
|
27609
|
+
init_zod();
|
|
27610
|
+
init_peercred();
|
|
27611
|
+
MAX_FRAME_BYTES2 = 64 * 1024;
|
|
27612
|
+
AgentNameSchema = exports_external.string().min(1).max(64, "agent name max 64 chars").regex(/^[a-zA-Z0-9][a-zA-Z0-9_-]*$/, "agent name must be kebab-case ASCII (alnum + _- only, first char alnum)").refine((s) => !isReservedAgentName(s), {
|
|
27613
|
+
message: "agent name is reserved"
|
|
27614
|
+
});
|
|
27615
|
+
GetRequestSchema = exports_external.object({
|
|
27616
|
+
v: exports_external.literal(1),
|
|
27617
|
+
op: exports_external.literal("get"),
|
|
27618
|
+
key: exports_external.string().min(1),
|
|
27619
|
+
filename: exports_external.string().optional(),
|
|
27620
|
+
token: exports_external.string().optional()
|
|
27621
|
+
});
|
|
27622
|
+
PutRequestSchema = exports_external.object({
|
|
27623
|
+
v: exports_external.literal(1),
|
|
27624
|
+
op: exports_external.literal("put"),
|
|
27625
|
+
key: exports_external.string().min(1),
|
|
27626
|
+
entry: exports_external.union([
|
|
27627
|
+
exports_external.object({ kind: exports_external.literal("string"), value: exports_external.string() }),
|
|
27628
|
+
exports_external.object({ kind: exports_external.literal("binary"), value: exports_external.string() })
|
|
27629
|
+
]),
|
|
27630
|
+
token: exports_external.string().optional(),
|
|
27631
|
+
passphrase: exports_external.string().optional(),
|
|
27632
|
+
attest_via_posture: exports_external.boolean().optional()
|
|
27633
|
+
});
|
|
27634
|
+
ListRequestSchema = exports_external.object({
|
|
27635
|
+
v: exports_external.literal(1),
|
|
27636
|
+
op: exports_external.literal("list"),
|
|
27637
|
+
token: exports_external.string().optional()
|
|
27638
|
+
});
|
|
27639
|
+
MintGrantRequestSchema = exports_external.object({
|
|
27640
|
+
v: exports_external.literal(1),
|
|
27641
|
+
op: exports_external.literal("mint_grant"),
|
|
27642
|
+
agent: AgentNameSchema,
|
|
27643
|
+
keys: exports_external.array(exports_external.string().min(1)),
|
|
27644
|
+
ttl_seconds: exports_external.number().int().positive().nullable(),
|
|
27645
|
+
description: exports_external.string().optional(),
|
|
27646
|
+
write_keys: exports_external.array(exports_external.string().min(1)).optional(),
|
|
27647
|
+
passphrase: exports_external.string().optional(),
|
|
27648
|
+
attest_via_posture: exports_external.boolean().optional()
|
|
27649
|
+
});
|
|
27650
|
+
ListGrantsRequestSchema = exports_external.object({
|
|
27651
|
+
v: exports_external.literal(1),
|
|
27652
|
+
op: exports_external.literal("list_grants"),
|
|
27653
|
+
agent: AgentNameSchema.optional(),
|
|
27654
|
+
passphrase: exports_external.string().optional(),
|
|
27655
|
+
attest_via_posture: exports_external.boolean().optional()
|
|
27656
|
+
});
|
|
27657
|
+
RevokeGrantRequestSchema = exports_external.object({
|
|
27658
|
+
v: exports_external.literal(1),
|
|
27659
|
+
op: exports_external.literal("revoke_grant"),
|
|
27660
|
+
id: exports_external.string().min(1)
|
|
27661
|
+
});
|
|
27662
|
+
StatusRequestSchema = exports_external.object({
|
|
27663
|
+
v: exports_external.literal(1),
|
|
27664
|
+
op: exports_external.literal("status")
|
|
27665
|
+
});
|
|
27666
|
+
LockRequestSchema = exports_external.object({
|
|
27667
|
+
v: exports_external.literal(1),
|
|
27668
|
+
op: exports_external.literal("lock")
|
|
27669
|
+
});
|
|
27670
|
+
PreflightAccessRequestSchema = exports_external.object({
|
|
27671
|
+
v: exports_external.literal(1),
|
|
27672
|
+
op: exports_external.literal("preflight_access"),
|
|
27673
|
+
agent: AgentNameSchema,
|
|
27674
|
+
keys: exports_external.array(exports_external.string().min(1)).min(1).max(128)
|
|
27675
|
+
});
|
|
27676
|
+
OkPreflightAccessResponseSchema = exports_external.object({
|
|
27677
|
+
ok: exports_external.literal(true),
|
|
27678
|
+
op: exports_external.literal("preflight_access"),
|
|
27679
|
+
results: exports_external.array(exports_external.object({
|
|
27680
|
+
key: exports_external.string(),
|
|
27681
|
+
exists: exports_external.boolean(),
|
|
27682
|
+
acl_ok: exports_external.boolean(),
|
|
27683
|
+
acl_reason: exports_external.string().optional(),
|
|
27684
|
+
scope_ok: exports_external.boolean(),
|
|
27685
|
+
scope_reason: exports_external.string().optional()
|
|
27686
|
+
}))
|
|
27687
|
+
});
|
|
27688
|
+
ApprovalRequestRequestSchema = exports_external.object({
|
|
27689
|
+
v: exports_external.literal(1),
|
|
27690
|
+
op: exports_external.literal("approval_request"),
|
|
27691
|
+
agent_unit: exports_external.string().min(1),
|
|
27692
|
+
scope: exports_external.string().min(1),
|
|
27693
|
+
action: exports_external.string().min(1),
|
|
27694
|
+
approver_set: exports_external.array(exports_external.string()),
|
|
27695
|
+
why: exports_external.string().optional(),
|
|
27696
|
+
ttl_ms: exports_external.number().int().positive().optional()
|
|
27697
|
+
});
|
|
27698
|
+
ApprovalLookupRequestSchema = exports_external.object({
|
|
27699
|
+
v: exports_external.literal(1),
|
|
27700
|
+
op: exports_external.literal("approval_lookup"),
|
|
27701
|
+
agent_unit: exports_external.string().min(1),
|
|
27702
|
+
scope: exports_external.string().min(1),
|
|
27703
|
+
action: exports_external.string().min(1),
|
|
27704
|
+
current_approver_set: exports_external.array(exports_external.string())
|
|
27705
|
+
});
|
|
27706
|
+
ApprovalConsumeRequestSchema = exports_external.object({
|
|
27707
|
+
v: exports_external.literal(1),
|
|
27708
|
+
op: exports_external.literal("approval_consume"),
|
|
27709
|
+
request_id: exports_external.string().regex(/^[0-9a-f]{32}$/)
|
|
27710
|
+
});
|
|
27711
|
+
ApprovalRevokeRequestSchema = exports_external.object({
|
|
27712
|
+
v: exports_external.literal(1),
|
|
27713
|
+
op: exports_external.literal("approval_revoke"),
|
|
27714
|
+
decision_id: exports_external.string().min(1),
|
|
27715
|
+
actor: exports_external.string().min(1),
|
|
27716
|
+
reason: exports_external.string().optional()
|
|
27717
|
+
});
|
|
27718
|
+
ApprovalListRequestSchema = exports_external.object({
|
|
27719
|
+
v: exports_external.literal(1),
|
|
27720
|
+
op: exports_external.literal("approval_list"),
|
|
27721
|
+
agent_unit: exports_external.string().optional()
|
|
27722
|
+
});
|
|
27723
|
+
ApprovalDecisionModeSchema = exports_external.enum([
|
|
27724
|
+
"allow_once",
|
|
27725
|
+
"allow_always",
|
|
27726
|
+
"allow_ttl",
|
|
27727
|
+
"deny",
|
|
27728
|
+
"deny_perm"
|
|
27729
|
+
]);
|
|
27730
|
+
ApprovalRecordRequestSchema = exports_external.object({
|
|
27731
|
+
v: exports_external.literal(1),
|
|
27732
|
+
op: exports_external.literal("approval_record"),
|
|
27733
|
+
request_id: exports_external.string().regex(/^[0-9a-f]{32}$/),
|
|
27734
|
+
decision: ApprovalDecisionModeSchema,
|
|
27735
|
+
approver_set: exports_external.array(exports_external.string()),
|
|
27736
|
+
granted_by_user_id: exports_external.number().int(),
|
|
27737
|
+
ttl_ms: exports_external.number().int().positive().nullable().optional()
|
|
27738
|
+
});
|
|
27739
|
+
ApprovalConsumeRecordRequestSchema = exports_external.object({
|
|
27740
|
+
v: exports_external.literal(1),
|
|
27741
|
+
op: exports_external.literal("approval_consume_record"),
|
|
27742
|
+
request_id: exports_external.string().regex(/^[0-9a-f]{32}$/),
|
|
27743
|
+
decision: ApprovalDecisionModeSchema,
|
|
27744
|
+
approver_set: exports_external.array(exports_external.string()),
|
|
27745
|
+
granted_by_user_id: exports_external.number().int(),
|
|
27746
|
+
ttl_ms: exports_external.number().int().positive().nullable().optional()
|
|
27747
|
+
});
|
|
27748
|
+
RequestSchema2 = exports_external.discriminatedUnion("op", [
|
|
27749
|
+
GetRequestSchema,
|
|
27750
|
+
PutRequestSchema,
|
|
27751
|
+
ListRequestSchema,
|
|
27752
|
+
StatusRequestSchema,
|
|
27753
|
+
LockRequestSchema,
|
|
27754
|
+
PreflightAccessRequestSchema,
|
|
27755
|
+
MintGrantRequestSchema,
|
|
27756
|
+
ListGrantsRequestSchema,
|
|
27757
|
+
RevokeGrantRequestSchema,
|
|
27758
|
+
ApprovalRequestRequestSchema,
|
|
27759
|
+
ApprovalLookupRequestSchema,
|
|
27760
|
+
ApprovalConsumeRequestSchema,
|
|
27761
|
+
ApprovalRevokeRequestSchema,
|
|
27762
|
+
ApprovalListRequestSchema,
|
|
27763
|
+
ApprovalRecordRequestSchema,
|
|
27764
|
+
ApprovalConsumeRecordRequestSchema
|
|
27765
|
+
]);
|
|
27766
|
+
VaultEntrySchema = exports_external.union([
|
|
27767
|
+
exports_external.object({ kind: exports_external.literal("string"), value: exports_external.string() }),
|
|
27768
|
+
exports_external.object({ kind: exports_external.literal("binary"), value: exports_external.string() }),
|
|
27769
|
+
exports_external.object({
|
|
27770
|
+
kind: exports_external.literal("files"),
|
|
27771
|
+
files: exports_external.record(exports_external.string(), exports_external.object({
|
|
27772
|
+
encoding: exports_external.enum(["utf8", "base64"]),
|
|
27773
|
+
value: exports_external.string()
|
|
27774
|
+
}))
|
|
27775
|
+
})
|
|
27776
|
+
]);
|
|
27777
|
+
ErrorCode = exports_external.enum([
|
|
27778
|
+
"LOCKED",
|
|
27779
|
+
"DENIED",
|
|
27780
|
+
"UNKNOWN_KEY",
|
|
27781
|
+
"BAD_REQUEST",
|
|
27782
|
+
"INTERNAL"
|
|
27783
|
+
]);
|
|
27784
|
+
OkEntryResponseSchema = exports_external.object({
|
|
27785
|
+
ok: exports_external.literal(true),
|
|
27786
|
+
entry: VaultEntrySchema
|
|
27787
|
+
});
|
|
27788
|
+
OkKeysResponseSchema = exports_external.object({
|
|
27789
|
+
ok: exports_external.literal(true),
|
|
27790
|
+
keys: exports_external.array(exports_external.string())
|
|
27791
|
+
});
|
|
27792
|
+
BrokerStatus = exports_external.object({
|
|
27793
|
+
unlocked: exports_external.boolean(),
|
|
27794
|
+
keyCount: exports_external.number().int().nonnegative(),
|
|
27795
|
+
uptimeSec: exports_external.number().nonnegative()
|
|
27796
|
+
});
|
|
27797
|
+
OkStatusResponseSchema = exports_external.object({
|
|
27798
|
+
ok: exports_external.literal(true),
|
|
27799
|
+
status: BrokerStatus
|
|
27800
|
+
});
|
|
27801
|
+
OkLockResponseSchema = exports_external.object({
|
|
27802
|
+
ok: exports_external.literal(true),
|
|
27803
|
+
locked: exports_external.literal(true)
|
|
27804
|
+
});
|
|
27805
|
+
OkPutResponseSchema = exports_external.object({
|
|
27806
|
+
ok: exports_external.literal(true),
|
|
27807
|
+
put: exports_external.literal(true),
|
|
27808
|
+
key: exports_external.string()
|
|
27809
|
+
});
|
|
27810
|
+
OkMintGrantResponseSchema = exports_external.object({
|
|
27811
|
+
ok: exports_external.literal(true),
|
|
27812
|
+
token: exports_external.string(),
|
|
27813
|
+
id: exports_external.string(),
|
|
27814
|
+
expires_at: exports_external.number().nullable()
|
|
27815
|
+
});
|
|
27816
|
+
GrantMetaSchema = exports_external.object({
|
|
27817
|
+
id: exports_external.string(),
|
|
27818
|
+
agent_slug: exports_external.string(),
|
|
27819
|
+
key_allow: exports_external.array(exports_external.string()),
|
|
27820
|
+
write_allow: exports_external.array(exports_external.string()).default([]),
|
|
27821
|
+
expires_at: exports_external.number().nullable(),
|
|
27822
|
+
created_at: exports_external.number(),
|
|
27823
|
+
description: exports_external.string().nullable()
|
|
27824
|
+
});
|
|
27825
|
+
OkListGrantsResponseSchema = exports_external.object({
|
|
27826
|
+
ok: exports_external.literal(true),
|
|
27827
|
+
grants: exports_external.array(GrantMetaSchema)
|
|
27828
|
+
});
|
|
27829
|
+
OkRevokeGrantResponseSchema = exports_external.object({
|
|
27830
|
+
ok: exports_external.literal(true),
|
|
27831
|
+
revoked: exports_external.boolean()
|
|
27832
|
+
});
|
|
27833
|
+
OkApprovalRequestResponseSchema = exports_external.discriminatedUnion("state", [
|
|
27834
|
+
exports_external.object({
|
|
27835
|
+
ok: exports_external.literal(true),
|
|
27836
|
+
kind: exports_external.literal("approval_request"),
|
|
27837
|
+
state: exports_external.literal("pending"),
|
|
27838
|
+
request_id: exports_external.string(),
|
|
27839
|
+
expires_at: exports_external.number()
|
|
27840
|
+
}),
|
|
27841
|
+
exports_external.object({
|
|
27842
|
+
ok: exports_external.literal(true),
|
|
27843
|
+
kind: exports_external.literal("approval_request"),
|
|
27844
|
+
state: exports_external.literal("rate_limited"),
|
|
27845
|
+
retry_after_ms: exports_external.number()
|
|
27846
|
+
})
|
|
27847
|
+
]);
|
|
27848
|
+
ApprovalDecisionMetaSchema = exports_external.object({
|
|
27849
|
+
id: exports_external.string(),
|
|
27850
|
+
agent_unit: exports_external.string(),
|
|
27851
|
+
scope: exports_external.string(),
|
|
27852
|
+
action: exports_external.string(),
|
|
27853
|
+
decision: ApprovalDecisionModeSchema,
|
|
27854
|
+
granted_at: exports_external.number(),
|
|
27855
|
+
granted_by_user_id: exports_external.number(),
|
|
27856
|
+
ttl_expires_at: exports_external.number().nullable(),
|
|
27857
|
+
last_used_at: exports_external.number().nullable(),
|
|
27858
|
+
revoked_at: exports_external.number().nullable(),
|
|
27859
|
+
revoke_reason: exports_external.string().nullable()
|
|
27860
|
+
});
|
|
27861
|
+
OkApprovalLookupResponseSchema = exports_external.object({
|
|
27862
|
+
ok: exports_external.literal(true),
|
|
27863
|
+
state: exports_external.enum(["granted", "denied", "pending", "expired", "drift_revoked", "no_decision"]),
|
|
27864
|
+
decision: ApprovalDecisionMetaSchema.nullable().optional()
|
|
27865
|
+
});
|
|
27866
|
+
OkApprovalConsumeResponseSchema = exports_external.object({
|
|
27867
|
+
ok: exports_external.literal(true),
|
|
27868
|
+
consumed: exports_external.boolean(),
|
|
27869
|
+
agent_unit: exports_external.string().optional(),
|
|
27870
|
+
scope: exports_external.string().optional(),
|
|
27871
|
+
action: exports_external.string().optional(),
|
|
27872
|
+
why: exports_external.string().nullable().optional()
|
|
27873
|
+
});
|
|
27874
|
+
OkApprovalRevokeResponseSchema = exports_external.object({
|
|
27875
|
+
ok: exports_external.literal(true),
|
|
27876
|
+
revoked: exports_external.boolean()
|
|
27877
|
+
});
|
|
27878
|
+
OkApprovalListResponseSchema = exports_external.object({
|
|
27879
|
+
ok: exports_external.literal(true),
|
|
27880
|
+
decisions: exports_external.array(ApprovalDecisionMetaSchema)
|
|
27881
|
+
});
|
|
27882
|
+
OkApprovalRecordResponseSchema = exports_external.object({
|
|
27883
|
+
ok: exports_external.literal(true),
|
|
27884
|
+
decision_id: exports_external.string()
|
|
27885
|
+
});
|
|
27886
|
+
OkApprovalConsumeRecordResponseSchema = exports_external.object({
|
|
27887
|
+
ok: exports_external.literal(true),
|
|
27888
|
+
consumed: exports_external.boolean(),
|
|
27889
|
+
decision_id: exports_external.string().optional(),
|
|
27890
|
+
agent_unit: exports_external.string().optional(),
|
|
27891
|
+
scope: exports_external.string().optional(),
|
|
27892
|
+
action: exports_external.string().optional(),
|
|
27893
|
+
why: exports_external.string().nullable().optional()
|
|
27894
|
+
});
|
|
27895
|
+
ErrorResponseSchema2 = exports_external.object({
|
|
27896
|
+
ok: exports_external.literal(false),
|
|
27897
|
+
code: ErrorCode,
|
|
27898
|
+
msg: exports_external.string()
|
|
27899
|
+
});
|
|
27900
|
+
ResponseSchema2 = exports_external.union([
|
|
27901
|
+
OkEntryResponseSchema,
|
|
27902
|
+
OkKeysResponseSchema,
|
|
27903
|
+
OkStatusResponseSchema,
|
|
27904
|
+
OkLockResponseSchema,
|
|
27905
|
+
OkPreflightAccessResponseSchema,
|
|
27906
|
+
OkPutResponseSchema,
|
|
27907
|
+
OkMintGrantResponseSchema,
|
|
27908
|
+
OkListGrantsResponseSchema,
|
|
27909
|
+
OkRevokeGrantResponseSchema,
|
|
27910
|
+
OkApprovalRequestResponseSchema,
|
|
27911
|
+
OkApprovalLookupResponseSchema,
|
|
27912
|
+
OkApprovalConsumeResponseSchema,
|
|
27913
|
+
OkApprovalRevokeResponseSchema,
|
|
27914
|
+
OkApprovalListResponseSchema,
|
|
27915
|
+
OkApprovalRecordResponseSchema,
|
|
27916
|
+
OkApprovalConsumeRecordResponseSchema,
|
|
27917
|
+
ErrorResponseSchema2
|
|
27918
|
+
]);
|
|
27919
|
+
});
|
|
27920
|
+
|
|
27921
|
+
// ../src/runtime-mode.ts
|
|
27922
|
+
function isDockerRuntime() {
|
|
27923
|
+
return process.env.SWITCHROOM_RUNTIME === "docker";
|
|
27924
|
+
}
|
|
27925
|
+
|
|
27926
|
+
// ../src/vault/broker/client.ts
|
|
27927
|
+
import * as net3 from "node:net";
|
|
27928
|
+
import * as fs from "node:fs";
|
|
27929
|
+
import { homedir as homedir7 } from "node:os";
|
|
27930
|
+
import { join as join15 } from "node:path";
|
|
27931
|
+
function defaultBrokerSocketPath() {
|
|
27932
|
+
if (fs.existsSync(OPERATOR_SOCKET_PATH))
|
|
27933
|
+
return OPERATOR_SOCKET_PATH;
|
|
27934
|
+
if (isDockerRuntime())
|
|
27935
|
+
return OPERATOR_SOCKET_PATH;
|
|
27936
|
+
return LEGACY_SOCKET_PATH;
|
|
27937
|
+
}
|
|
27938
|
+
function vaultTokenFilePath(agentSlug) {
|
|
27939
|
+
return join15(homedir7(), ".switchroom", "agents", agentSlug, ".vault-token");
|
|
27940
|
+
}
|
|
27941
|
+
function readVaultTokenFile(agentSlug) {
|
|
27942
|
+
const filePath = vaultTokenFilePath(agentSlug);
|
|
27943
|
+
try {
|
|
27944
|
+
const stat = fs.statSync(filePath);
|
|
27945
|
+
const mode = stat.mode & 511;
|
|
27946
|
+
if ((mode & 63) !== 0) {
|
|
27947
|
+
process.stderr.write(`[vault-broker] Refusing to read ${filePath} with mode ${mode.toString(8).padStart(3, "0")} ` + `(must be 0600). Delete the file and re-mint with 'switchroom vault grant mint <agent>'. ` + `Falling through to peercred ACL.
|
|
27948
|
+
`);
|
|
27949
|
+
return null;
|
|
27950
|
+
}
|
|
27951
|
+
const raw = fs.readFileSync(filePath, "utf8");
|
|
27952
|
+
const token = raw.split(`
|
|
27953
|
+
`)[0].trim();
|
|
27954
|
+
return token.length > 0 ? token : null;
|
|
27955
|
+
} catch (err) {
|
|
27956
|
+
const code = err.code;
|
|
27957
|
+
if (code === "ENOENT") {
|
|
27958
|
+
return null;
|
|
27959
|
+
}
|
|
27960
|
+
const reason = code === "EACCES" ? "permission denied" : err instanceof Error ? err.message : String(err);
|
|
27961
|
+
process.stderr.write(`[vault-broker] Warning: could not read token file ${filePath}: ${reason}. ` + `Falling through to peercred ACL.
|
|
27962
|
+
`);
|
|
27963
|
+
return null;
|
|
27964
|
+
}
|
|
27965
|
+
}
|
|
27966
|
+
function resolveBrokerSocketPath(opts) {
|
|
27967
|
+
if (opts?.socket)
|
|
27968
|
+
return opts.socket;
|
|
27969
|
+
const env = process.env.SWITCHROOM_VAULT_BROKER_SOCK;
|
|
27970
|
+
if (env)
|
|
27971
|
+
return env;
|
|
27972
|
+
if (opts?.vaultBrokerSocket)
|
|
27973
|
+
return opts.vaultBrokerSocket;
|
|
27974
|
+
return defaultBrokerSocketPath();
|
|
27975
|
+
}
|
|
27976
|
+
async function rpcRaw(req, opts) {
|
|
27977
|
+
return rpc(req, opts);
|
|
27978
|
+
}
|
|
27979
|
+
async function rpc(req, opts) {
|
|
27980
|
+
const socketPath = resolveBrokerSocketPath(opts);
|
|
27981
|
+
const timeoutMs = opts?.timeoutMs ?? DEFAULT_TIMEOUT_MS3;
|
|
27982
|
+
return new Promise((resolve5) => {
|
|
27983
|
+
let settled = false;
|
|
27984
|
+
const settle = (val) => {
|
|
27985
|
+
if (settled)
|
|
27986
|
+
return;
|
|
27987
|
+
settled = true;
|
|
27988
|
+
resolve5(val);
|
|
27989
|
+
};
|
|
27990
|
+
const client3 = new net3.Socket;
|
|
27991
|
+
const timer3 = setTimeout(() => {
|
|
27992
|
+
client3.destroy();
|
|
27993
|
+
settle({ kind: "unreachable", msg: `broker did not respond within ${timeoutMs}ms` });
|
|
27994
|
+
}, timeoutMs);
|
|
27995
|
+
client3.on("error", (err) => {
|
|
27996
|
+
clearTimeout(timer3);
|
|
27997
|
+
const code = err.code ?? "ERR";
|
|
27998
|
+
let msg;
|
|
27999
|
+
if (code === "ENOENT")
|
|
28000
|
+
msg = "broker socket not found (is the daemon running?)";
|
|
28001
|
+
else if (code === "ECONNREFUSED")
|
|
28002
|
+
msg = "broker socket exists but refused connection";
|
|
28003
|
+
else if (code === "EACCES")
|
|
28004
|
+
msg = "broker socket access denied (wrong UID?)";
|
|
28005
|
+
else
|
|
28006
|
+
msg = `broker connection failed: ${err.message}`;
|
|
28007
|
+
settle({ kind: "unreachable", msg });
|
|
27641
28008
|
});
|
|
27642
|
-
|
|
27643
|
-
|
|
27644
|
-
|
|
27645
|
-
|
|
27646
|
-
|
|
27647
|
-
|
|
27648
|
-
|
|
27649
|
-
|
|
27650
|
-
|
|
27651
|
-
try {
|
|
27652
|
-
return funcToString.call(func);
|
|
27653
|
-
} catch (e) {}
|
|
28009
|
+
let buffer = "";
|
|
28010
|
+
client3.on("data", (chunk2) => {
|
|
28011
|
+
buffer += chunk2.toString("utf8");
|
|
28012
|
+
const newlineIdx = buffer.indexOf(`
|
|
28013
|
+
`);
|
|
28014
|
+
if (newlineIdx !== -1) {
|
|
28015
|
+
const line = buffer.slice(0, newlineIdx).trimEnd();
|
|
28016
|
+
clearTimeout(timer3);
|
|
28017
|
+
client3.destroy();
|
|
27654
28018
|
try {
|
|
27655
|
-
|
|
27656
|
-
|
|
27657
|
-
|
|
27658
|
-
|
|
27659
|
-
|
|
27660
|
-
|
|
27661
|
-
|
|
27662
|
-
|
|
27663
|
-
}
|
|
27664
|
-
var length = iteratees.length;
|
|
27665
|
-
if (length > 1 && isIterateeCall(collection, iteratees[0], iteratees[1])) {
|
|
27666
|
-
iteratees = [];
|
|
27667
|
-
} else if (length > 2 && isIterateeCall(iteratees[0], iteratees[1], iteratees[2])) {
|
|
27668
|
-
iteratees = [iteratees[0]];
|
|
28019
|
+
const resp = decodeResponse2(line);
|
|
28020
|
+
settle({ kind: "response", resp });
|
|
28021
|
+
} catch (err) {
|
|
28022
|
+
settle({
|
|
28023
|
+
kind: "unreachable",
|
|
28024
|
+
msg: `unparseable broker response: ${err instanceof Error ? err.message : String(err)}`
|
|
28025
|
+
});
|
|
28026
|
+
}
|
|
27669
28027
|
}
|
|
27670
|
-
return baseOrderBy(collection, baseFlatten(iteratees), []);
|
|
27671
28028
|
});
|
|
27672
|
-
|
|
27673
|
-
|
|
27674
|
-
|
|
28029
|
+
client3.on("connect", () => {
|
|
28030
|
+
try {
|
|
28031
|
+
client3.write(encodeRequest2(req));
|
|
28032
|
+
} catch (err) {
|
|
28033
|
+
clearTimeout(timer3);
|
|
28034
|
+
client3.destroy();
|
|
28035
|
+
settle({
|
|
28036
|
+
kind: "unreachable",
|
|
28037
|
+
msg: `failed to send request: ${err instanceof Error ? err.message : String(err)}`
|
|
28038
|
+
});
|
|
27675
28039
|
}
|
|
27676
|
-
|
|
27677
|
-
|
|
27678
|
-
|
|
27679
|
-
return cache.get(key);
|
|
27680
|
-
}
|
|
27681
|
-
var result = func.apply(this, args);
|
|
27682
|
-
memoized.cache = cache.set(key, result);
|
|
27683
|
-
return result;
|
|
27684
|
-
};
|
|
27685
|
-
memoized.cache = new (memoize.Cache || MapCache);
|
|
27686
|
-
return memoized;
|
|
27687
|
-
}
|
|
27688
|
-
memoize.Cache = MapCache;
|
|
27689
|
-
function eq(value, other) {
|
|
27690
|
-
return value === other || value !== value && other !== other;
|
|
27691
|
-
}
|
|
27692
|
-
function isArguments(value) {
|
|
27693
|
-
return isArrayLikeObject(value) && hasOwnProperty.call(value, "callee") && (!propertyIsEnumerable.call(value, "callee") || objectToString.call(value) == argsTag);
|
|
27694
|
-
}
|
|
27695
|
-
var isArray2 = Array.isArray;
|
|
27696
|
-
function isArrayLike(value) {
|
|
27697
|
-
return value != null && isLength(value.length) && !isFunction2(value);
|
|
27698
|
-
}
|
|
27699
|
-
function isArrayLikeObject(value) {
|
|
27700
|
-
return isObjectLike(value) && isArrayLike(value);
|
|
27701
|
-
}
|
|
27702
|
-
function isFunction2(value) {
|
|
27703
|
-
var tag = isObject2(value) ? objectToString.call(value) : "";
|
|
27704
|
-
return tag == funcTag || tag == genTag;
|
|
27705
|
-
}
|
|
27706
|
-
function isLength(value) {
|
|
27707
|
-
return typeof value == "number" && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
|
|
27708
|
-
}
|
|
27709
|
-
function isObject2(value) {
|
|
27710
|
-
var type = typeof value;
|
|
27711
|
-
return !!value && (type == "object" || type == "function");
|
|
27712
|
-
}
|
|
27713
|
-
function isObjectLike(value) {
|
|
27714
|
-
return !!value && typeof value == "object";
|
|
27715
|
-
}
|
|
27716
|
-
function isSymbol(value) {
|
|
27717
|
-
return typeof value == "symbol" || isObjectLike(value) && objectToString.call(value) == symbolTag;
|
|
27718
|
-
}
|
|
27719
|
-
var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray;
|
|
27720
|
-
function toString(value) {
|
|
27721
|
-
return value == null ? "" : baseToString(value);
|
|
27722
|
-
}
|
|
27723
|
-
function get(object, path, defaultValue) {
|
|
27724
|
-
var result = object == null ? undefined : baseGet(object, path);
|
|
27725
|
-
return result === undefined ? defaultValue : result;
|
|
27726
|
-
}
|
|
27727
|
-
function hasIn(object, path) {
|
|
27728
|
-
return object != null && hasPath(object, path, baseHasIn);
|
|
27729
|
-
}
|
|
27730
|
-
function keys(object) {
|
|
27731
|
-
return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object);
|
|
27732
|
-
}
|
|
27733
|
-
function identity2(value) {
|
|
27734
|
-
return value;
|
|
27735
|
-
}
|
|
27736
|
-
function property(path) {
|
|
27737
|
-
return isKey(path) ? baseProperty(toKey(path)) : basePropertyDeep(path);
|
|
27738
|
-
}
|
|
27739
|
-
module.exports = sortBy;
|
|
27740
|
-
})(lodash_sortby, lodash_sortby.exports);
|
|
27741
|
-
return lodash_sortby.exports;
|
|
28040
|
+
});
|
|
28041
|
+
client3.connect({ path: socketPath });
|
|
28042
|
+
});
|
|
27742
28043
|
}
|
|
27743
|
-
function
|
|
27744
|
-
|
|
27745
|
-
|
|
27746
|
-
|
|
27747
|
-
|
|
27748
|
-
|
|
27749
|
-
|
|
28044
|
+
async function getViaBrokerStructured(key, opts) {
|
|
28045
|
+
const token = opts?.token;
|
|
28046
|
+
const result = await rpc({ v: 1, op: "get", key, ...token ? { token } : {} }, opts);
|
|
28047
|
+
if (result.kind === "unreachable") {
|
|
28048
|
+
return { kind: "unreachable", msg: result.msg };
|
|
28049
|
+
}
|
|
28050
|
+
const resp = result.resp;
|
|
28051
|
+
if (resp.ok && "entry" in resp) {
|
|
28052
|
+
return { kind: "ok", entry: resp.entry };
|
|
28053
|
+
}
|
|
28054
|
+
if (!resp.ok) {
|
|
28055
|
+
if (resp.code === "UNKNOWN_KEY") {
|
|
28056
|
+
return { kind: "not_found", code: resp.code, msg: resp.msg };
|
|
27750
28057
|
}
|
|
27751
|
-
return
|
|
27752
|
-
}
|
|
27753
|
-
return
|
|
28058
|
+
return { kind: "denied", code: resp.code, msg: resp.msg };
|
|
28059
|
+
}
|
|
28060
|
+
return { kind: "unreachable", msg: "unexpected broker response shape" };
|
|
27754
28061
|
}
|
|
27755
|
-
function
|
|
27756
|
-
|
|
27757
|
-
|
|
27758
|
-
|
|
27759
|
-
|
|
27760
|
-
|
|
27761
|
-
|
|
27762
|
-
|
|
27763
|
-
|
|
27764
|
-
|
|
27765
|
-
|
|
28062
|
+
async function putViaBroker(key, entry, opts) {
|
|
28063
|
+
const token = opts?.token;
|
|
28064
|
+
const passphrase = opts?.passphrase;
|
|
28065
|
+
const attestViaPosture = opts?.attest_via_posture === true;
|
|
28066
|
+
const result = await rpc({
|
|
28067
|
+
v: 1,
|
|
28068
|
+
op: "put",
|
|
28069
|
+
key,
|
|
28070
|
+
entry,
|
|
28071
|
+
...token ? { token } : {},
|
|
28072
|
+
...passphrase ? { passphrase } : {},
|
|
28073
|
+
...attestViaPosture ? { attest_via_posture: true } : {}
|
|
28074
|
+
}, opts);
|
|
28075
|
+
if (result.kind === "unreachable") {
|
|
28076
|
+
return { kind: "unreachable", msg: result.msg };
|
|
28077
|
+
}
|
|
28078
|
+
const resp = result.resp;
|
|
28079
|
+
if (resp.ok && "put" in resp) {
|
|
28080
|
+
return { kind: "ok" };
|
|
28081
|
+
}
|
|
28082
|
+
if (!resp.ok) {
|
|
28083
|
+
if (resp.code === "UNKNOWN_KEY") {
|
|
28084
|
+
return { kind: "not_found", code: resp.code, msg: resp.msg };
|
|
27766
28085
|
}
|
|
27767
|
-
return {
|
|
27768
|
-
|
|
27769
|
-
|
|
27770
|
-
|
|
27771
|
-
|
|
27772
|
-
|
|
27773
|
-
|
|
27774
|
-
|
|
28086
|
+
return { kind: "denied", code: resp.code, msg: resp.msg };
|
|
28087
|
+
}
|
|
28088
|
+
return { kind: "unreachable", msg: "unexpected broker response shape" };
|
|
28089
|
+
}
|
|
28090
|
+
var DEFAULT_TIMEOUT_MS3 = 2000, LEGACY_SOCKET_PATH, OPERATOR_SOCKET_PATH;
|
|
28091
|
+
var init_client2 = __esm(() => {
|
|
28092
|
+
init_protocol2();
|
|
28093
|
+
init_peercred();
|
|
28094
|
+
LEGACY_SOCKET_PATH = join15(homedir7(), ".switchroom", "vault-broker.sock");
|
|
28095
|
+
OPERATOR_SOCKET_PATH = join15(homedir7(), ".switchroom", "broker-operator", "sock");
|
|
28096
|
+
});
|
|
28097
|
+
|
|
28098
|
+
// ../src/drive/deep-links.ts
|
|
28099
|
+
function classifyMimeType(mimeType) {
|
|
28100
|
+
if (!mimeType)
|
|
28101
|
+
return "file";
|
|
28102
|
+
switch (mimeType) {
|
|
28103
|
+
case "application/vnd.google-apps.document":
|
|
28104
|
+
return "doc";
|
|
28105
|
+
case "application/vnd.google-apps.spreadsheet":
|
|
28106
|
+
return "spreadsheet";
|
|
28107
|
+
case "application/vnd.google-apps.presentation":
|
|
28108
|
+
return "presentation";
|
|
28109
|
+
case "application/vnd.google-apps.form":
|
|
28110
|
+
return "form";
|
|
28111
|
+
case "application/vnd.google-apps.drawing":
|
|
28112
|
+
return "drawing";
|
|
28113
|
+
case "application/vnd.google-apps.folder":
|
|
28114
|
+
return "folder";
|
|
28115
|
+
default:
|
|
28116
|
+
return "file";
|
|
28117
|
+
}
|
|
28118
|
+
}
|
|
28119
|
+
function openInDriveUrl(options) {
|
|
28120
|
+
validateDriveId2(options.fileId, "fileId");
|
|
28121
|
+
if (options.discussionId !== undefined) {
|
|
28122
|
+
validateDriveId2(options.discussionId, "discussionId");
|
|
28123
|
+
}
|
|
28124
|
+
const kind = options.isFolder ? "folder" : classifyMimeType(options.mimeType);
|
|
28125
|
+
const base = baseUrlFor(kind, options.fileId);
|
|
28126
|
+
if (options.discussionId !== undefined) {
|
|
28127
|
+
return `${base}?disco=${encodeURIComponent(options.discussionId)}`;
|
|
28128
|
+
}
|
|
28129
|
+
return base;
|
|
28130
|
+
}
|
|
28131
|
+
function baseUrlFor(kind, fileId) {
|
|
28132
|
+
switch (kind) {
|
|
28133
|
+
case "doc":
|
|
28134
|
+
return `https://docs.google.com/document/d/${fileId}/edit`;
|
|
28135
|
+
case "spreadsheet":
|
|
28136
|
+
return `https://docs.google.com/spreadsheets/d/${fileId}/edit`;
|
|
28137
|
+
case "presentation":
|
|
28138
|
+
return `https://docs.google.com/presentation/d/${fileId}/edit`;
|
|
28139
|
+
case "form":
|
|
28140
|
+
return `https://docs.google.com/forms/d/${fileId}/edit`;
|
|
28141
|
+
case "drawing":
|
|
28142
|
+
return `https://docs.google.com/drawings/d/${fileId}/edit`;
|
|
28143
|
+
case "folder":
|
|
28144
|
+
return `https://drive.google.com/drive/folders/${fileId}`;
|
|
28145
|
+
case "file":
|
|
28146
|
+
return `https://drive.google.com/file/d/${fileId}/view`;
|
|
28147
|
+
}
|
|
28148
|
+
}
|
|
28149
|
+
function validateDriveId2(id, fieldName) {
|
|
28150
|
+
if (id.length === 0) {
|
|
28151
|
+
throw new Error(`Drive ${fieldName} must not be empty`);
|
|
28152
|
+
}
|
|
28153
|
+
if (!/^[A-Za-z0-9_-]+$/.test(id)) {
|
|
28154
|
+
throw new Error(`Drive ${fieldName} '${id.slice(0, 30)}${id.length > 30 ? "\u2026" : ""}' contains invalid characters. Expected base64-url-safe (alphanumerics + - + _).`);
|
|
28155
|
+
}
|
|
28156
|
+
}
|
|
28157
|
+
function openInDriveButton(options) {
|
|
28158
|
+
return {
|
|
28159
|
+
text: "\uD83D\uDCD6 Open in Drive",
|
|
28160
|
+
url: openInDriveUrl(options)
|
|
27775
28161
|
};
|
|
27776
|
-
regexpParse.isRegExpString = isRegExpString;
|
|
27777
|
-
return regexpParse;
|
|
27778
28162
|
}
|
|
27779
|
-
function
|
|
27780
|
-
|
|
27781
|
-
|
|
27782
|
-
|
|
27783
|
-
(
|
|
27784
|
-
|
|
27785
|
-
|
|
27786
|
-
};
|
|
27787
|
-
|
|
27788
|
-
|
|
27789
|
-
|
|
27790
|
-
|
|
27791
|
-
|
|
27792
|
-
|
|
27793
|
-
|
|
27794
|
-
|
|
27795
|
-
|
|
27796
|
-
|
|
27797
|
-
|
|
27798
|
-
|
|
27799
|
-
|
|
27800
|
-
|
|
27801
|
-
|
|
27802
|
-
|
|
27803
|
-
|
|
27804
|
-
|
|
27805
|
-
|
|
27806
|
-
|
|
27807
|
-
|
|
27808
|
-
|
|
27809
|
-
|
|
27810
|
-
|
|
27811
|
-
|
|
27812
|
-
|
|
27813
|
-
|
|
27814
|
-
|
|
27815
|
-
|
|
27816
|
-
|
|
27817
|
-
|
|
27818
|
-
|
|
27819
|
-
var isEqualMatchPatternResult = function(a, b) {
|
|
27820
|
-
return a.startIndex === b.startIndex && a.endIndex === b.endIndex && a.match === b.match;
|
|
27821
|
-
};
|
|
27822
|
-
var matchPatterns = function(text, regExpLikeStrings) {
|
|
27823
|
-
var matchPatternResults = [];
|
|
27824
|
-
regExpLikeStrings.map(function(patternString) {
|
|
27825
|
-
return (0, exports$1.createRegExp)(patternString);
|
|
27826
|
-
}).forEach(function(regExp) {
|
|
27827
|
-
var results = text.matchAll(regExp);
|
|
27828
|
-
Array.from(results).forEach(function(result) {
|
|
27829
|
-
if (result.index === undefined) {
|
|
27830
|
-
return;
|
|
27831
|
-
}
|
|
27832
|
-
var match = result[0];
|
|
27833
|
-
var index = result.index;
|
|
27834
|
-
matchPatternResults.push({
|
|
27835
|
-
match,
|
|
27836
|
-
captures: result.slice(1),
|
|
27837
|
-
startIndex: index,
|
|
27838
|
-
endIndex: index + match.length
|
|
27839
|
-
});
|
|
27840
|
-
});
|
|
27841
|
-
});
|
|
27842
|
-
var uniqResults = (0, lodash_uniqwith_1.default)(matchPatternResults, isEqualMatchPatternResult);
|
|
27843
|
-
return (0, lodash_sortby_1.default)(uniqResults, ["startIndex", "endIndex"]);
|
|
27844
|
-
};
|
|
27845
|
-
exports$1.matchPatterns = matchPatterns;
|
|
27846
|
-
})(regexpStringMatcher);
|
|
27847
|
-
return regexpStringMatcher;
|
|
28163
|
+
function scopeToOpenInDriveButton(scope, mimeTypeHint) {
|
|
28164
|
+
const parsed = parseDriveScope(scope);
|
|
28165
|
+
if (parsed === null)
|
|
28166
|
+
return null;
|
|
28167
|
+
if (parsed.target.kind === "all")
|
|
28168
|
+
return null;
|
|
28169
|
+
if (parsed.target.kind === "folder") {
|
|
28170
|
+
return openInDriveButton({ fileId: parsed.target.folder_id, isFolder: true });
|
|
28171
|
+
}
|
|
28172
|
+
return openInDriveButton({
|
|
28173
|
+
fileId: parsed.target.doc_id,
|
|
28174
|
+
mimeType: mimeTypeHint
|
|
28175
|
+
});
|
|
28176
|
+
}
|
|
28177
|
+
function parseDriveScope(scope) {
|
|
28178
|
+
if (!scope.startsWith("doc:gdrive:"))
|
|
28179
|
+
return null;
|
|
28180
|
+
let rest = scope.slice("doc:gdrive:".length);
|
|
28181
|
+
let action = "read";
|
|
28182
|
+
if (rest.startsWith("write:")) {
|
|
28183
|
+
action = "write";
|
|
28184
|
+
rest = rest.slice("write:".length);
|
|
28185
|
+
} else if (rest.startsWith("suggest:")) {
|
|
28186
|
+
action = "suggest";
|
|
28187
|
+
rest = rest.slice("suggest:".length);
|
|
28188
|
+
}
|
|
28189
|
+
if (rest === "**")
|
|
28190
|
+
return { action, target: { kind: "all" } };
|
|
28191
|
+
if (rest.startsWith("folder/")) {
|
|
28192
|
+
const tail = rest.slice("folder/".length);
|
|
28193
|
+
if (!tail.endsWith("/**"))
|
|
28194
|
+
return null;
|
|
28195
|
+
const folder_id = tail.slice(0, -"/**".length);
|
|
28196
|
+
if (!/^[A-Za-z0-9_-]+$/.test(folder_id))
|
|
28197
|
+
return null;
|
|
28198
|
+
return { action, target: { kind: "folder", folder_id } };
|
|
28199
|
+
}
|
|
28200
|
+
if (!/^[A-Za-z0-9_-]+$/.test(rest))
|
|
28201
|
+
return null;
|
|
28202
|
+
return { action, target: { kind: "doc", doc_id: rest } };
|
|
27848
28203
|
}
|
|
27849
|
-
var commonjsGlobal, regexpStringMatcher, lodash_uniq, hasRequiredLodash_uniq, lodash_uniqwith, hasRequiredLodash_uniqwith, lodash_sortby, hasRequiredLodash_sortby, escapeStringRegexp, hasRequiredEscapeStringRegexp, regexpParse, hasRequiredRegexpParse, hasRequiredRegexpStringMatcher, regexpStringMatcherExports, OID_DATA, OID_SHA1, OID_SHA256, OID_SHA384, OID_SHA512, typeMap;
|
|
27850
|
-
var init_module2 = __esm(() => {
|
|
27851
|
-
commonjsGlobal = typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : {};
|
|
27852
|
-
regexpStringMatcher = {};
|
|
27853
|
-
lodash_sortby = { exports: {} };
|
|
27854
|
-
lodash_sortby.exports;
|
|
27855
|
-
regexpParse = {};
|
|
27856
|
-
regexpStringMatcherExports = requireRegexpStringMatcher();
|
|
27857
|
-
OID_DATA = new Uint8Array([42, 134, 72, 134, 247, 13, 1, 7, 1]);
|
|
27858
|
-
OID_SHA1 = new Uint8Array([43, 14, 3, 2, 26]);
|
|
27859
|
-
OID_SHA256 = new Uint8Array([96, 134, 72, 1, 101, 3, 4, 2, 1]);
|
|
27860
|
-
OID_SHA384 = new Uint8Array([96, 134, 72, 1, 101, 3, 4, 2, 2]);
|
|
27861
|
-
OID_SHA512 = new Uint8Array([96, 134, 72, 1, 101, 3, 4, 2, 3]);
|
|
27862
|
-
typeMap = new Map([
|
|
27863
|
-
["ghp", "GitHub personal access tokens"],
|
|
27864
|
-
["gho", "OAuth access tokens"],
|
|
27865
|
-
["ghu", "GitHub user-to-server tokens"],
|
|
27866
|
-
["ghs", "GitHub server-to-server tokens"],
|
|
27867
|
-
["ghr", "refresh tokens"],
|
|
27868
|
-
["github_pat", "fine-grained personal access tokens"]
|
|
27869
|
-
]);
|
|
27870
|
-
});
|
|
27871
28204
|
|
|
27872
|
-
//
|
|
27873
|
-
|
|
27874
|
-
|
|
27875
|
-
|
|
27876
|
-
|
|
27877
|
-
|
|
28205
|
+
// gateway/oversize-card-body.ts
|
|
28206
|
+
function truncateRawToFit(input) {
|
|
28207
|
+
const { raw, render, cap, sentinel } = input;
|
|
28208
|
+
const hardLimit = input.hardLimit ?? cap + 196;
|
|
28209
|
+
const fullBody = render(raw);
|
|
28210
|
+
if (fullBody.length <= cap) {
|
|
28211
|
+
return { body: fullBody, truncated: false };
|
|
28212
|
+
}
|
|
28213
|
+
let lo = 0;
|
|
28214
|
+
let hi = raw.length;
|
|
28215
|
+
let bestSliceLen = 0;
|
|
28216
|
+
while (lo <= hi) {
|
|
28217
|
+
const mid = lo + hi >>> 1;
|
|
28218
|
+
const candidate = raw.slice(0, mid) + sentinel;
|
|
28219
|
+
if (render(candidate).length <= cap) {
|
|
28220
|
+
bestSliceLen = mid;
|
|
28221
|
+
lo = mid + 1;
|
|
28222
|
+
} else {
|
|
28223
|
+
hi = mid - 1;
|
|
28224
|
+
}
|
|
28225
|
+
}
|
|
28226
|
+
let chosenRaw = raw.slice(0, bestSliceLen);
|
|
28227
|
+
const lastNl = chosenRaw.lastIndexOf(`
|
|
28228
|
+
`);
|
|
28229
|
+
if (lastNl > 0)
|
|
28230
|
+
chosenRaw = chosenRaw.slice(0, lastNl);
|
|
28231
|
+
let body = render(chosenRaw + sentinel);
|
|
28232
|
+
if (body.length > hardLimit) {
|
|
28233
|
+
body = body.slice(0, hardLimit - 1);
|
|
28234
|
+
}
|
|
28235
|
+
return { body, truncated: true };
|
|
28236
|
+
}
|
|
27878
28237
|
|
|
27879
28238
|
// gateway/auth-line.ts
|
|
27880
28239
|
function escapeHtml8(s) {
|
|
@@ -31966,37 +32325,51 @@ function isWorkerActivityFeedEnabled(envVal) {
|
|
|
31966
32325
|
return envVal !== "0";
|
|
31967
32326
|
}
|
|
31968
32327
|
var DESC_MAX = 80;
|
|
31969
|
-
var
|
|
31970
|
-
var
|
|
32328
|
+
var STEP_MAX = 100;
|
|
32329
|
+
var RESULT_MAX = 320;
|
|
32330
|
+
var RULE = "\u2500\u2500\u2500\u2500\u2500";
|
|
31971
32331
|
var NARRATIVE_MAX_LINES = 6;
|
|
32332
|
+
function appendStepFeed(lines, steps, allDone) {
|
|
32333
|
+
if (steps.length === 0)
|
|
32334
|
+
return;
|
|
32335
|
+
const shown = steps.slice(-NARRATIVE_MAX_LINES);
|
|
32336
|
+
const hidden = steps.length - shown.length;
|
|
32337
|
+
if (hidden > 0)
|
|
32338
|
+
lines.push(`<i>\u2713 +${hidden} earlier\u2026</i>`);
|
|
32339
|
+
const lastIdx = shown.length - 1;
|
|
32340
|
+
shown.forEach((s, i) => {
|
|
32341
|
+
lines.push(!allDone && i === lastIdx ? `<b>\u2192 ${s}</b>` : `<i>\u2713 ${s}</i>`);
|
|
32342
|
+
});
|
|
32343
|
+
}
|
|
31972
32344
|
function renderWorkerActivity(v) {
|
|
31973
|
-
const desc = truncate(v.description.trim() || "background task", DESC_MAX);
|
|
32345
|
+
const desc = truncate(stripMarkdown(v.description).trim() || "background task", DESC_MAX);
|
|
31974
32346
|
const elapsed = formatDuration(v.elapsedMs);
|
|
31975
32347
|
const toolWord = v.toolCount === 1 ? "tool" : "tools";
|
|
31976
|
-
|
|
31977
|
-
|
|
31978
|
-
|
|
31979
|
-
|
|
31980
|
-
|
|
31981
|
-
|
|
31982
|
-
|
|
31983
|
-
|
|
31984
|
-
|
|
31985
|
-
|
|
31986
|
-
|
|
31987
|
-
|
|
31988
|
-
|
|
31989
|
-
|
|
31990
|
-
|
|
31991
|
-
|
|
31992
|
-
|
|
31993
|
-
|
|
31994
|
-
|
|
31995
|
-
}
|
|
32348
|
+
const header = `\uD83D\uDEE0 <b>Worker</b> \u00b7 <i>${escapeHtml(desc)}</i>`;
|
|
32349
|
+
const finished = v.state === "done" || v.state === "failed";
|
|
32350
|
+
const steps = (v.narrativeLines ?? []).map((s) => stripMarkdown(s).replace(/\s+/g, " ").trim()).filter((s) => s.length > 0).map((s) => escapeHtml(truncate(s, STEP_MAX)));
|
|
32351
|
+
if (finished) {
|
|
32352
|
+
const verb = v.state === "done" ? "completed" : "failed";
|
|
32353
|
+
const lines2 = [header, `<i>finished \u00b7 ${verb} \u00b7 ${v.toolCount} ${toolWord} \u00b7 ${elapsed}</i>`];
|
|
32354
|
+
appendStepFeed(lines2, steps, true);
|
|
32355
|
+
const result = cleanWorkerResultParagraph(v.latestSummary);
|
|
32356
|
+
if (result.length > 0) {
|
|
32357
|
+
const emoji = v.state === "done" ? "\u2705" : "\u26a0\ufe0f";
|
|
32358
|
+
lines2.push(RULE);
|
|
32359
|
+
lines2.push(`${emoji} <i>${escapeHtml(truncate(result, RESULT_MAX))}</i>`);
|
|
32360
|
+
}
|
|
32361
|
+
return lines2.join(`
|
|
32362
|
+
`);
|
|
32363
|
+
}
|
|
32364
|
+
const lines = [header, `<i>running \u00b7 ${elapsed} \u00b7 ${v.toolCount} ${toolWord}</i>`];
|
|
32365
|
+
if (steps.length > 0) {
|
|
32366
|
+
appendStepFeed(lines, steps, false);
|
|
31996
32367
|
} else {
|
|
31997
|
-
const summary = v.latestSummary.trim();
|
|
32368
|
+
const summary = stripMarkdown(v.latestSummary).replace(/\s+/g, " ").trim();
|
|
31998
32369
|
if (summary.length > 0) {
|
|
31999
|
-
lines.push(
|
|
32370
|
+
lines.push(`<b>\u2192 ${escapeHtml(truncate(summary, STEP_MAX))}</b>`);
|
|
32371
|
+
} else {
|
|
32372
|
+
lines.push("<i>starting\u2026</i>");
|
|
32000
32373
|
}
|
|
32001
32374
|
}
|
|
32002
32375
|
return lines.join(`
|
|
@@ -32085,7 +32458,7 @@ function createWorkerActivityFeed(opts) {
|
|
|
32085
32458
|
if (nowFn() < h.cooldownUntil) {
|
|
32086
32459
|
return;
|
|
32087
32460
|
}
|
|
32088
|
-
const body = renderWorkerActivity(view);
|
|
32461
|
+
const body = renderWorkerActivity({ ...view, narrativeLines: h.narrative });
|
|
32089
32462
|
if (body === h.lastBody)
|
|
32090
32463
|
return;
|
|
32091
32464
|
try {
|
|
@@ -41582,7 +41955,7 @@ var INLINE_PH = `${NULL}VS_INLINE`;
|
|
|
41582
41955
|
var HTML_CODE_PH = `${NULL}VS_HTMLCODE`;
|
|
41583
41956
|
var HTML_PRE_PH = `${NULL}VS_HTMLPRE`;
|
|
41584
41957
|
var URL_PH = `${NULL}VS_URL`;
|
|
41585
|
-
var
|
|
41958
|
+
var URL_RE2 = /https?:\/\/\S+/g;
|
|
41586
41959
|
function enabled4() {
|
|
41587
41960
|
const v = process.env.SWITCHROOM_DISABLE_VOICE_SCRUB;
|
|
41588
41961
|
return !(v === "1" || v === "true");
|
|
@@ -41610,7 +41983,7 @@ function park(text) {
|
|
|
41610
41983
|
parts.push({ prefix: INLINE_PH, idx, raw: m });
|
|
41611
41984
|
return `${INLINE_PH}${idx}${NULL}`;
|
|
41612
41985
|
});
|
|
41613
|
-
parked = parked.replace(
|
|
41986
|
+
parked = parked.replace(URL_RE2, (m) => {
|
|
41614
41987
|
const idx = parts.length;
|
|
41615
41988
|
parts.push({ prefix: URL_PH, idx, raw: m });
|
|
41616
41989
|
return `${URL_PH}${idx}${NULL}`;
|
|
@@ -42361,10 +42734,10 @@ class PreambleSuppressor {
|
|
|
42361
42734
|
this.setTimer = deps.setTimer ?? ((fn, ms) => setTimeout(fn, ms));
|
|
42362
42735
|
this.clearTimer = deps.clearTimer ?? ((h) => clearTimeout(h));
|
|
42363
42736
|
}
|
|
42364
|
-
onText(
|
|
42365
|
-
if (
|
|
42737
|
+
onText(chunk2) {
|
|
42738
|
+
if (chunk2.length === 0)
|
|
42366
42739
|
return;
|
|
42367
|
-
this.pendingBuffer +=
|
|
42740
|
+
this.pendingBuffer += chunk2;
|
|
42368
42741
|
if (this.pendingTimer != null)
|
|
42369
42742
|
this.clearTimer(this.pendingTimer);
|
|
42370
42743
|
this.pendingTimer = this.setTimer(() => this.flushNow(), this.bufferMs);
|
|
@@ -44616,8 +44989,8 @@ async function hostdRequest(opts, req) {
|
|
|
44616
44989
|
reject(err);
|
|
44617
44990
|
}
|
|
44618
44991
|
});
|
|
44619
|
-
socket.on("data", (
|
|
44620
|
-
buf +=
|
|
44992
|
+
socket.on("data", (chunk2) => {
|
|
44993
|
+
buf += chunk2.toString("utf8");
|
|
44621
44994
|
if (Buffer.byteLength(buf, "utf8") > MAX_FRAME_BYTES3 * 2) {
|
|
44622
44995
|
if (settled)
|
|
44623
44996
|
return;
|
|
@@ -44859,10 +45232,10 @@ function startWebhookIngestServer(opts) {
|
|
|
44859
45232
|
} catch {}
|
|
44860
45233
|
conn.end();
|
|
44861
45234
|
};
|
|
44862
|
-
conn.on("data", (
|
|
45235
|
+
conn.on("data", (chunk2) => {
|
|
44863
45236
|
if (handled)
|
|
44864
45237
|
return;
|
|
44865
|
-
buf +=
|
|
45238
|
+
buf += chunk2;
|
|
44866
45239
|
if (buf.length > MAX_REQUEST_BYTES) {
|
|
44867
45240
|
reply({ status: "error", error: "request too large" });
|
|
44868
45241
|
return;
|
|
@@ -48070,253 +48443,8 @@ function resolveShutdownMarker(prior, signal, now, maxPreserveAgeMs = REASON_PRE
|
|
|
48070
48443
|
return { ts: now, signal, reason: EXTERNAL_RESTART_FALLBACK_REASON };
|
|
48071
48444
|
}
|
|
48072
48445
|
|
|
48073
|
-
// secret-detect/
|
|
48074
|
-
|
|
48075
|
-
{ rule_id: "anthropic_api_key", regex: /\b(sk-ant-[A-Za-z0-9_-]{8,})\b/g, captureIndex: 1, slugHint: "anthropic_api_key" },
|
|
48076
|
-
{ rule_id: "anthropic_oauth_code", regex: /(?:^|\s)([A-Za-z0-9_-]{20,}#[A-Za-z0-9_-]{20,})(?=\s|$)/gm, captureIndex: 1, slugHint: "anthropic_oauth_code" },
|
|
48077
|
-
{ rule_id: "openai_api_key", regex: /\b(sk-[A-Za-z0-9_-]{20,})\b/g, captureIndex: 1, slugHint: "openai_api_key" },
|
|
48078
|
-
{ rule_id: "github_pat_classic", regex: /\b(ghp_[A-Za-z0-9]{20,})\b/g, captureIndex: 1, slugHint: "github_pat" },
|
|
48079
|
-
{ rule_id: "github_pat_fine_grained", regex: /\b(github_pat_[A-Za-z0-9_]{20,})\b/g, captureIndex: 1, slugHint: "github_pat" },
|
|
48080
|
-
{ rule_id: "slack_token", regex: /\b(xox[baprs]-[A-Za-z0-9-]{10,})\b/g, captureIndex: 1, slugHint: "slack_token" },
|
|
48081
|
-
{ rule_id: "slack_app_token", regex: /\b(xapp-[A-Za-z0-9-]{10,})\b/g, captureIndex: 1, slugHint: "slack_app_token" },
|
|
48082
|
-
{ rule_id: "groq_api_key", regex: /\b(gsk_[A-Za-z0-9_-]{10,})\b/g, captureIndex: 1, slugHint: "groq_api_key" },
|
|
48083
|
-
{ rule_id: "google_api_key", regex: /\b(AIza[0-9A-Za-z\-_]{20,})\b/g, captureIndex: 1, slugHint: "google_api_key" },
|
|
48084
|
-
{ rule_id: "perplexity_api_key", regex: /\b(pplx-[A-Za-z0-9_-]{10,})\b/g, captureIndex: 1, slugHint: "perplexity_api_key" },
|
|
48085
|
-
{ rule_id: "npm_token", regex: /\b(npm_[A-Za-z0-9]{10,})\b/g, captureIndex: 1, slugHint: "npm_token" },
|
|
48086
|
-
{ rule_id: "telegram_bot_token_prefixed", regex: /\bbot(\d{6,}:[A-Za-z0-9_-]{20,})\b/g, captureIndex: 1, slugHint: "telegram_bot_token" },
|
|
48087
|
-
{ rule_id: "telegram_bot_token", regex: /\b(\d{6,}:[A-Za-z0-9_-]{20,})\b/g, captureIndex: 1, slugHint: "telegram_bot_token" },
|
|
48088
|
-
{ rule_id: "aws_access_key", regex: /\b(AKIA[0-9A-Z]{16})\b/g, captureIndex: 1, slugHint: "aws_access_key" },
|
|
48089
|
-
{ rule_id: "jwt", regex: /\b(eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,})\b/g, captureIndex: 1, slugHint: "jwt" }
|
|
48090
|
-
];
|
|
48091
|
-
var STRUCTURED_PATTERNS = [
|
|
48092
|
-
{
|
|
48093
|
-
rule_id: "env_key_value",
|
|
48094
|
-
regex: /\b([A-Z0-9_]*(?:KEY|TOKEN|SECRET|PASSWORD|PASSWD))\b\s*[=:]\s*(["']?)([^\s"'\\]+)\2/g,
|
|
48095
|
-
captureIndex: 3,
|
|
48096
|
-
slugHint: "env"
|
|
48097
|
-
},
|
|
48098
|
-
{
|
|
48099
|
-
rule_id: "json_secret_field",
|
|
48100
|
-
regex: /"(?:apiKey|token|secret|password|passwd|accessToken|refreshToken)"\s*:\s*"([^"]+)"/g,
|
|
48101
|
-
captureIndex: 1,
|
|
48102
|
-
slugHint: "json_secret"
|
|
48103
|
-
},
|
|
48104
|
-
{
|
|
48105
|
-
rule_id: "cli_flag",
|
|
48106
|
-
regex: /--(?:api[-_]?key|hook[-_]?token|token|secret|password|passwd)\s+(["']?)([^\s"']+)\1/g,
|
|
48107
|
-
captureIndex: 2,
|
|
48108
|
-
slugHint: "cli_flag"
|
|
48109
|
-
},
|
|
48110
|
-
{
|
|
48111
|
-
rule_id: "bearer_auth_header",
|
|
48112
|
-
regex: /Authorization\s*[:=]\s*Bearer\s+([A-Za-z0-9._\-+=]+)/g,
|
|
48113
|
-
captureIndex: 1,
|
|
48114
|
-
slugHint: "bearer_token"
|
|
48115
|
-
},
|
|
48116
|
-
{
|
|
48117
|
-
rule_id: "bearer_loose",
|
|
48118
|
-
regex: /\bBearer\s+([A-Za-z0-9._\-+=]{18,})\b/g,
|
|
48119
|
-
captureIndex: 1,
|
|
48120
|
-
slugHint: "bearer_token"
|
|
48121
|
-
},
|
|
48122
|
-
{
|
|
48123
|
-
rule_id: "pem_private_key",
|
|
48124
|
-
regex: /-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]+?-----END [A-Z ]*PRIVATE KEY-----/g,
|
|
48125
|
-
captureIndex: 0,
|
|
48126
|
-
slugHint: "pem_private_key"
|
|
48127
|
-
}
|
|
48128
|
-
];
|
|
48129
|
-
var ALL_PATTERNS = [...ANCHORED_PATTERNS, ...STRUCTURED_PATTERNS];
|
|
48130
|
-
|
|
48131
|
-
// secret-detect/entropy.ts
|
|
48132
|
-
function shannonEntropy(s) {
|
|
48133
|
-
if (s.length === 0)
|
|
48134
|
-
return 0;
|
|
48135
|
-
const counts = new Map;
|
|
48136
|
-
for (const ch of s) {
|
|
48137
|
-
counts.set(ch, (counts.get(ch) ?? 0) + 1);
|
|
48138
|
-
}
|
|
48139
|
-
let h = 0;
|
|
48140
|
-
const len = s.length;
|
|
48141
|
-
for (const c of counts.values()) {
|
|
48142
|
-
const p = c / len;
|
|
48143
|
-
h -= p * Math.log2(p);
|
|
48144
|
-
}
|
|
48145
|
-
return h;
|
|
48146
|
-
}
|
|
48147
|
-
|
|
48148
|
-
// secret-detect/kv-scanner.ts
|
|
48149
|
-
var KV_RE = /\b([A-Za-z_][A-Za-z0-9_-]*(?:password|passwd|token|secret|key|api[_-]?key))\s*[:=]\s*["']?([^\s"'\\]{8,})["']?/gi;
|
|
48150
|
-
var KV_ENTROPY_THRESHOLD = 4;
|
|
48151
|
-
function scanKeyValue(text) {
|
|
48152
|
-
const hits = [];
|
|
48153
|
-
KV_RE.lastIndex = 0;
|
|
48154
|
-
let m;
|
|
48155
|
-
while ((m = KV_RE.exec(text)) !== null) {
|
|
48156
|
-
const [, keyName, value] = m;
|
|
48157
|
-
if (!value)
|
|
48158
|
-
continue;
|
|
48159
|
-
const h = shannonEntropy(value);
|
|
48160
|
-
if (h < KV_ENTROPY_THRESHOLD)
|
|
48161
|
-
continue;
|
|
48162
|
-
const valueOffsetInMatch = m[0].indexOf(value, keyName.length);
|
|
48163
|
-
if (valueOffsetInMatch < 0)
|
|
48164
|
-
continue;
|
|
48165
|
-
const start = m.index + valueOffsetInMatch;
|
|
48166
|
-
const end = start + value.length;
|
|
48167
|
-
hits.push({
|
|
48168
|
-
rule_id: "kv_entropy",
|
|
48169
|
-
start,
|
|
48170
|
-
end,
|
|
48171
|
-
matched_text: value,
|
|
48172
|
-
key_name: keyName,
|
|
48173
|
-
confidence: "ambiguous"
|
|
48174
|
-
});
|
|
48175
|
-
}
|
|
48176
|
-
return hits;
|
|
48177
|
-
}
|
|
48178
|
-
|
|
48179
|
-
// secret-detect/chunker.ts
|
|
48180
|
-
var CHUNK_THRESHOLD = 32 * 1024;
|
|
48181
|
-
var WINDOW_SIZE = 16 * 1024;
|
|
48182
|
-
var OVERLAP = 1024;
|
|
48183
|
-
function chunk(text) {
|
|
48184
|
-
if (text.length <= CHUNK_THRESHOLD) {
|
|
48185
|
-
return [{ offset: 0, text }];
|
|
48186
|
-
}
|
|
48187
|
-
const out = [];
|
|
48188
|
-
let offset = 0;
|
|
48189
|
-
while (offset < text.length) {
|
|
48190
|
-
const end = Math.min(offset + WINDOW_SIZE, text.length);
|
|
48191
|
-
out.push({ offset, text: text.slice(offset, end) });
|
|
48192
|
-
if (end >= text.length)
|
|
48193
|
-
break;
|
|
48194
|
-
offset = end - OVERLAP;
|
|
48195
|
-
}
|
|
48196
|
-
return out;
|
|
48197
|
-
}
|
|
48198
|
-
|
|
48199
|
-
// secret-detect/index.ts
|
|
48200
|
-
init_suppressor();
|
|
48201
|
-
|
|
48202
|
-
// secret-detect/mask.ts
|
|
48203
|
-
function maskToken(s) {
|
|
48204
|
-
if (s.length >= 18) {
|
|
48205
|
-
return `${s.slice(0, 6)}...${s.slice(-4)}`;
|
|
48206
|
-
}
|
|
48207
|
-
return "***";
|
|
48208
|
-
}
|
|
48209
|
-
// secret-detect/url-redact.ts
|
|
48210
|
-
var SENSITIVE_PARAMS = new Set([
|
|
48211
|
-
"token",
|
|
48212
|
-
"key",
|
|
48213
|
-
"api_key",
|
|
48214
|
-
"apikey",
|
|
48215
|
-
"secret",
|
|
48216
|
-
"access_token",
|
|
48217
|
-
"password",
|
|
48218
|
-
"pass",
|
|
48219
|
-
"auth",
|
|
48220
|
-
"client_secret",
|
|
48221
|
-
"refresh_token",
|
|
48222
|
-
"signature"
|
|
48223
|
-
]);
|
|
48224
|
-
|
|
48225
|
-
// secret-detect/index.ts
|
|
48226
|
-
init_secretlint_source();
|
|
48227
|
-
function detectSecrets(text) {
|
|
48228
|
-
if (!text || text.length === 0)
|
|
48229
|
-
return [];
|
|
48230
|
-
const windows = chunk(text);
|
|
48231
|
-
const raw = [];
|
|
48232
|
-
for (const win of windows) {
|
|
48233
|
-
for (const p of ALL_PATTERNS) {
|
|
48234
|
-
const re = new RegExp(p.regex.source, p.regex.flags.includes("g") ? p.regex.flags : p.regex.flags + "g");
|
|
48235
|
-
let m;
|
|
48236
|
-
while ((m = re.exec(win.text)) !== null) {
|
|
48237
|
-
if (m[0].length === 0) {
|
|
48238
|
-
re.lastIndex++;
|
|
48239
|
-
continue;
|
|
48240
|
-
}
|
|
48241
|
-
const cap = p.captureIndex === 0 ? m[0] : m[p.captureIndex];
|
|
48242
|
-
if (!cap)
|
|
48243
|
-
continue;
|
|
48244
|
-
const matchStart = p.captureIndex === 0 ? m.index : m.index + m[0].indexOf(cap);
|
|
48245
|
-
if (matchStart < 0)
|
|
48246
|
-
continue;
|
|
48247
|
-
const globalStart = win.offset + matchStart;
|
|
48248
|
-
const globalEnd = globalStart + cap.length;
|
|
48249
|
-
const keyName = p.rule_id === "env_key_value" ? m[1] : undefined;
|
|
48250
|
-
if (p.rule_id === "env_key_value") {
|
|
48251
|
-
const ENV_KV_MIN_LEN = 12;
|
|
48252
|
-
const ENV_KV_MIN_ENTROPY = 3.5;
|
|
48253
|
-
if (cap.length < ENV_KV_MIN_LEN)
|
|
48254
|
-
continue;
|
|
48255
|
-
if (shannonEntropy(cap) < ENV_KV_MIN_ENTROPY)
|
|
48256
|
-
continue;
|
|
48257
|
-
}
|
|
48258
|
-
raw.push({
|
|
48259
|
-
rule_id: p.rule_id,
|
|
48260
|
-
start: globalStart,
|
|
48261
|
-
end: globalEnd,
|
|
48262
|
-
matched_text: cap,
|
|
48263
|
-
key_name: keyName,
|
|
48264
|
-
confidence: "high"
|
|
48265
|
-
});
|
|
48266
|
-
}
|
|
48267
|
-
}
|
|
48268
|
-
const kvHits = scanKeyValue(win.text);
|
|
48269
|
-
for (const h of kvHits) {
|
|
48270
|
-
raw.push({ ...h, start: h.start + win.offset, end: h.end + win.offset });
|
|
48271
|
-
}
|
|
48272
|
-
}
|
|
48273
|
-
const deduped = dedupeRaw(raw);
|
|
48274
|
-
const final = dropOverlaps(deduped);
|
|
48275
|
-
const existing = new Set;
|
|
48276
|
-
const out = [];
|
|
48277
|
-
for (const h of final) {
|
|
48278
|
-
const suggested_slug = deriveSlug({ key_name: h.key_name, rule_id: h.rule_id }, existing);
|
|
48279
|
-
existing.add(suggested_slug);
|
|
48280
|
-
out.push({
|
|
48281
|
-
rule_id: h.rule_id,
|
|
48282
|
-
matched_text: h.matched_text,
|
|
48283
|
-
start: h.start,
|
|
48284
|
-
end: h.end,
|
|
48285
|
-
confidence: h.confidence,
|
|
48286
|
-
suppressed: isSuppressed(text, h.start, h.end),
|
|
48287
|
-
suggested_slug,
|
|
48288
|
-
key_name: h.key_name
|
|
48289
|
-
});
|
|
48290
|
-
}
|
|
48291
|
-
out.sort((a, b) => a.start - b.start);
|
|
48292
|
-
return out;
|
|
48293
|
-
}
|
|
48294
|
-
function dedupeRaw(raw) {
|
|
48295
|
-
const seen = new Map;
|
|
48296
|
-
for (const h of raw) {
|
|
48297
|
-
const key = `${h.start}:${h.end}`;
|
|
48298
|
-
const existing = seen.get(key);
|
|
48299
|
-
if (!existing) {
|
|
48300
|
-
seen.set(key, h);
|
|
48301
|
-
continue;
|
|
48302
|
-
}
|
|
48303
|
-
if (existing.confidence === "ambiguous" && h.confidence === "high") {
|
|
48304
|
-
seen.set(key, h);
|
|
48305
|
-
}
|
|
48306
|
-
}
|
|
48307
|
-
return Array.from(seen.values());
|
|
48308
|
-
}
|
|
48309
|
-
function dropOverlaps(hits) {
|
|
48310
|
-
const sorted = [...hits].sort((a, b) => a.end - a.start - (b.end - b.start));
|
|
48311
|
-
const out = [];
|
|
48312
|
-
for (const h of sorted) {
|
|
48313
|
-
const contained = out.some((existing) => existing !== h && existing.start <= h.start && existing.end >= h.end && !(existing.start === h.start && existing.end === h.end));
|
|
48314
|
-
if (!contained)
|
|
48315
|
-
out.push(h);
|
|
48316
|
-
}
|
|
48317
|
-
out.sort((a, b) => a.start - b.start || a.end - b.end);
|
|
48318
|
-
return out;
|
|
48319
|
-
}
|
|
48446
|
+
// secret-detect/pipeline.ts
|
|
48447
|
+
init_secret_detect();
|
|
48320
48448
|
|
|
48321
48449
|
// secret-detect/rewrite.ts
|
|
48322
48450
|
function rewritePrompt(text, targets) {
|
|
@@ -48680,7 +48808,11 @@ function recentDenialsFromAuditLog(rawAuditLog, opts) {
|
|
|
48680
48808
|
}
|
|
48681
48809
|
|
|
48682
48810
|
// secret-detect/index.ts
|
|
48811
|
+
init_patterns();
|
|
48812
|
+
init_kv_scanner();
|
|
48813
|
+
init_chunker();
|
|
48683
48814
|
init_suppressor();
|
|
48815
|
+
init_url_redact();
|
|
48684
48816
|
init_secretlint_source();
|
|
48685
48817
|
function detectSecrets2(text) {
|
|
48686
48818
|
if (!text || text.length === 0)
|
|
@@ -48776,6 +48908,32 @@ function dropOverlaps2(hits) {
|
|
|
48776
48908
|
return out;
|
|
48777
48909
|
}
|
|
48778
48910
|
|
|
48911
|
+
// secret-detect/redact.ts
|
|
48912
|
+
init_secret_detect();
|
|
48913
|
+
init_url_redact();
|
|
48914
|
+
var REDACTED_MARKER2 = "[REDACTED]";
|
|
48915
|
+
function redact2(text) {
|
|
48916
|
+
if (!text || text.length === 0)
|
|
48917
|
+
return text;
|
|
48918
|
+
const urlScrubbed = redactUrls(text);
|
|
48919
|
+
const hits = detectSecrets(urlScrubbed);
|
|
48920
|
+
if (hits.length === 0)
|
|
48921
|
+
return urlScrubbed;
|
|
48922
|
+
const sorted = [...hits].sort((a, b) => b.start - a.start);
|
|
48923
|
+
let out = urlScrubbed;
|
|
48924
|
+
for (const h of sorted) {
|
|
48925
|
+
out = out.slice(0, h.start) + redactedMarker2(h.rule_id) + out.slice(h.end);
|
|
48926
|
+
}
|
|
48927
|
+
return out;
|
|
48928
|
+
}
|
|
48929
|
+
function redactedMarker2(ruleId) {
|
|
48930
|
+
const trimmed = ruleId.replace(/^(kv|env)_/, "");
|
|
48931
|
+
if (!trimmed || trimmed === "key_value" || trimmed === "kv_entropy") {
|
|
48932
|
+
return REDACTED_MARKER2;
|
|
48933
|
+
}
|
|
48934
|
+
return `[REDACTED:${trimmed}]`;
|
|
48935
|
+
}
|
|
48936
|
+
|
|
48779
48937
|
// admin-commands/index.ts
|
|
48780
48938
|
var ADMIN_COMMAND_NAMES = new Set([
|
|
48781
48939
|
"agents",
|
|
@@ -50320,6 +50478,9 @@ var SEVERITY_RANK2 = {
|
|
|
50320
50478
|
critical: 3
|
|
50321
50479
|
};
|
|
50322
50480
|
|
|
50481
|
+
// ../src/secret-detect/redact.ts
|
|
50482
|
+
init_redact();
|
|
50483
|
+
|
|
50323
50484
|
// ../src/issues/store.ts
|
|
50324
50485
|
var ISSUES_FILE = "issues.jsonl";
|
|
50325
50486
|
var ISSUES_LOCK = "issues.lock";
|
|
@@ -50735,6 +50896,18 @@ function describeGrant(toolName, inputPreview, option) {
|
|
|
50735
50896
|
return naturalAction(toolName, inputPreview);
|
|
50736
50897
|
}
|
|
50737
50898
|
}
|
|
50899
|
+
function formatPermissionResumeMessage(opts) {
|
|
50900
|
+
const who = opts.agentName && opts.agentName.length > 0 ? `<b>${escapeTgHtml(capFirst(opts.agentName))}</b>` : `<b>Agent</b>`;
|
|
50901
|
+
const act = (opts.action ?? "").trim();
|
|
50902
|
+
const hasAction = act.length > 0;
|
|
50903
|
+
if (opts.behavior === "allow") {
|
|
50904
|
+
return hasAction ? `\u25b6\ufe0f ${who} \u2014 got it, continuing: <i>${escapeTgHtml(act)}</i>` : `\u25b6\ufe0f ${who} \u2014 got it, back to work.`;
|
|
50905
|
+
}
|
|
50906
|
+
if (opts.timeoutMinutes != null) {
|
|
50907
|
+
return hasAction ? `\uD83D\uDEAB ${who} \u2014 no answer in ${opts.timeoutMinutes}m, continuing without it (<i>${escapeTgHtml(act)}</i>).` : `\uD83D\uDEAB ${who} \u2014 no answer in ${opts.timeoutMinutes}m, continuing without it.`;
|
|
50908
|
+
}
|
|
50909
|
+
return hasAction ? `\uD83D\uDEAB ${who} \u2014 noted, I won't ${escapeTgHtml(lowerFirst(act))}. Continuing without it.` : `\uD83D\uDEAB ${who} \u2014 noted, continuing without it.`;
|
|
50910
|
+
}
|
|
50738
50911
|
function resolveSkillName(input) {
|
|
50739
50912
|
return readString(input, "skill") ?? readString(input, "skill_name") ?? readString(input, "skillName") ?? readString(input, "name") ?? skillBasenameFromPath(input);
|
|
50740
50913
|
}
|
|
@@ -51469,10 +51642,10 @@ function sweepStaleTurnActiveMarker(stateDir, opts) {
|
|
|
51469
51642
|
}
|
|
51470
51643
|
|
|
51471
51644
|
// ../src/build-info.ts
|
|
51472
|
-
var VERSION = "0.14.
|
|
51473
|
-
var COMMIT_SHA = "
|
|
51474
|
-
var COMMIT_DATE = "2026-06-
|
|
51475
|
-
var LATEST_PR =
|
|
51645
|
+
var VERSION = "0.14.28";
|
|
51646
|
+
var COMMIT_SHA = "cb64351f";
|
|
51647
|
+
var COMMIT_DATE = "2026-06-01T04:23:25Z";
|
|
51648
|
+
var LATEST_PR = 2049;
|
|
51476
51649
|
var COMMITS_AHEAD_OF_TAG = 0;
|
|
51477
51650
|
|
|
51478
51651
|
// gateway/boot-version.ts
|
|
@@ -52906,6 +53079,31 @@ function resumeReactionAfterVerdict() {
|
|
|
52906
53079
|
return;
|
|
52907
53080
|
activeStatusReactions.get(statusKey(turn.sessionChatId, turn.sessionThreadId))?.setThinking();
|
|
52908
53081
|
}
|
|
53082
|
+
function postPermissionResumeMessage(opts) {
|
|
53083
|
+
if (process.env.SWITCHROOM_RESUME_MSG === "0")
|
|
53084
|
+
return;
|
|
53085
|
+
const text = formatPermissionResumeMessage({
|
|
53086
|
+
agentName: process.env.SWITCHROOM_AGENT_NAME ?? null,
|
|
53087
|
+
behavior: opts.behavior,
|
|
53088
|
+
action: opts.action,
|
|
53089
|
+
timeoutMinutes: opts.timeoutMinutes
|
|
53090
|
+
});
|
|
53091
|
+
const turn = currentTurn;
|
|
53092
|
+
const targets = turn != null ? [{ chatId: turn.sessionChatId, threadId: turn.sessionThreadId }] : loadAccess().allowFrom.map((chatId) => ({
|
|
53093
|
+
chatId,
|
|
53094
|
+
threadId: resolveAgentOutboundTopic({
|
|
53095
|
+
kind: "permission",
|
|
53096
|
+
turnInitiated: false,
|
|
53097
|
+
originThreadId: undefined
|
|
53098
|
+
})
|
|
53099
|
+
}));
|
|
53100
|
+
for (const { chatId, threadId } of targets) {
|
|
53101
|
+
swallowingApiCall(() => bot.api.sendMessage(chatId, text, {
|
|
53102
|
+
parse_mode: "HTML",
|
|
53103
|
+
...threadId != null ? { message_thread_id: threadId } : {}
|
|
53104
|
+
}), { chat_id: chatId, verb: "permission-resume", ...threadId != null ? { threadId } : {} });
|
|
53105
|
+
}
|
|
53106
|
+
}
|
|
52909
53107
|
function resolveThreadId(chat_id, explicit) {
|
|
52910
53108
|
if (explicit != null)
|
|
52911
53109
|
return Number(explicit);
|
|
@@ -53320,6 +53518,11 @@ var pendingStateReaper = setInterval(() => {
|
|
|
53320
53518
|
if (now - v.startedAt > PERMISSION_TTL_MS) {
|
|
53321
53519
|
dispatchPermissionVerdict({ type: "permission", requestId: k, behavior: "deny" });
|
|
53322
53520
|
resumeReactionAfterVerdict();
|
|
53521
|
+
postPermissionResumeMessage({
|
|
53522
|
+
behavior: "deny",
|
|
53523
|
+
action: naturalAction(v.tool_name, v.input_preview),
|
|
53524
|
+
timeoutMinutes: Math.round(PERMISSION_TTL_MS / 60000)
|
|
53525
|
+
});
|
|
53323
53526
|
process.stderr.write(`telegram gateway: permission TTL expired \u2014 auto-deny request=${k} tool=${v.tool_name} (no operator response in ${Math.round(PERMISSION_TTL_MS / 60000)}m)
|
|
53324
53527
|
`);
|
|
53325
53528
|
pendingPermissions.delete(k);
|
|
@@ -54346,7 +54549,8 @@ var ALLOWED_TOOLS = new Set([
|
|
|
54346
54549
|
"send_sticker",
|
|
54347
54550
|
"send_gif",
|
|
54348
54551
|
"vault_request_save",
|
|
54349
|
-
"vault_request_access"
|
|
54552
|
+
"vault_request_access",
|
|
54553
|
+
"request_secret"
|
|
54350
54554
|
]);
|
|
54351
54555
|
async function executeToolCall(tool, args) {
|
|
54352
54556
|
if (!ALLOWED_TOOLS.has(tool)) {
|
|
@@ -54389,6 +54593,8 @@ async function executeToolCall(tool, args) {
|
|
|
54389
54593
|
return executeVaultRequestSave(args);
|
|
54390
54594
|
case "vault_request_access":
|
|
54391
54595
|
return executeVaultRequestAccess(args);
|
|
54596
|
+
case "request_secret":
|
|
54597
|
+
return executeRequestSecret(args);
|
|
54392
54598
|
default:
|
|
54393
54599
|
throw new Error(`unknown tool: ${tool}`);
|
|
54394
54600
|
}
|
|
@@ -54434,6 +54640,14 @@ async function executeUpdateChecklist(args) {
|
|
|
54434
54640
|
`);
|
|
54435
54641
|
return { content: [{ type: "text", text: `checklist updated (id: ${message_id})` }] };
|
|
54436
54642
|
}
|
|
54643
|
+
function redactOutboundText(text, site) {
|
|
54644
|
+
const masked = redact2(text);
|
|
54645
|
+
if (masked !== text) {
|
|
54646
|
+
process.stderr.write(`telegram gateway: outbound secret masked site=${site}
|
|
54647
|
+
`);
|
|
54648
|
+
}
|
|
54649
|
+
return masked;
|
|
54650
|
+
}
|
|
54437
54651
|
async function executeReply(args) {
|
|
54438
54652
|
const turn = currentTurn;
|
|
54439
54653
|
const chat_id = args.chat_id;
|
|
@@ -54443,6 +54657,7 @@ async function executeReply(args) {
|
|
|
54443
54657
|
if (rawText == null || rawText === "")
|
|
54444
54658
|
throw new Error("reply: text is required and cannot be empty");
|
|
54445
54659
|
let text = repairEscapedWhitespace(rawText);
|
|
54660
|
+
text = redactOutboundText(text, "reply");
|
|
54446
54661
|
{
|
|
54447
54662
|
const scrub = scrubVoice(text);
|
|
54448
54663
|
if (scrub.replaced > 0) {
|
|
@@ -54865,6 +55080,7 @@ async function executeStreamReply(args) {
|
|
|
54865
55080
|
throw new Error("stream_reply: chat_id is required");
|
|
54866
55081
|
if (args.text == null || args.text === "")
|
|
54867
55082
|
throw new Error("stream_reply: text is required and cannot be empty");
|
|
55083
|
+
args.text = redactOutboundText(args.text, "stream_reply");
|
|
54868
55084
|
{
|
|
54869
55085
|
const scrub = scrubVoice(args.text);
|
|
54870
55086
|
if (scrub.replaced > 0) {
|
|
@@ -55383,6 +55599,213 @@ async function executeVaultRequestSave(args) {
|
|
|
55383
55599
|
]
|
|
55384
55600
|
};
|
|
55385
55601
|
}
|
|
55602
|
+
var pendingSecretRequests = new Map;
|
|
55603
|
+
var armedSecretCaptures = new Map;
|
|
55604
|
+
var PENDING_SECRET_REQUEST_TTL_MS = 1800000;
|
|
55605
|
+
var ARMED_SECRET_CAPTURE_TTL_MS = 600000;
|
|
55606
|
+
function sweepSecretRequests() {
|
|
55607
|
+
const now = Date.now();
|
|
55608
|
+
for (const [k, v] of pendingSecretRequests) {
|
|
55609
|
+
if (now - v.staged_at > PENDING_SECRET_REQUEST_TTL_MS)
|
|
55610
|
+
pendingSecretRequests.delete(k);
|
|
55611
|
+
}
|
|
55612
|
+
for (const [k, v] of armedSecretCaptures) {
|
|
55613
|
+
if (now - v.armed_at > ARMED_SECRET_CAPTURE_TTL_MS)
|
|
55614
|
+
armedSecretCaptures.delete(k);
|
|
55615
|
+
}
|
|
55616
|
+
}
|
|
55617
|
+
function buildSecretRequestKeyboard(stageId) {
|
|
55618
|
+
return {
|
|
55619
|
+
inline_keyboard: [
|
|
55620
|
+
[
|
|
55621
|
+
{ text: "\uD83D\uDD10 Provide securely", callback_data: `vsp:provide:${stageId}` },
|
|
55622
|
+
{ text: "\uD83D\uDEAB Decline", callback_data: `vsp:decline:${stageId}` }
|
|
55623
|
+
]
|
|
55624
|
+
]
|
|
55625
|
+
};
|
|
55626
|
+
}
|
|
55627
|
+
function renderSecretRequestCard(req) {
|
|
55628
|
+
const lines = [
|
|
55629
|
+
`\uD83D\uDD12 <b>${escapeHtmlForTg(req.agent)}</b> needs a secret:`,
|
|
55630
|
+
`<code>${escapeHtmlForTg(req.key)}</code>`
|
|
55631
|
+
];
|
|
55632
|
+
if (req.reason)
|
|
55633
|
+
lines.push(`<i>${escapeHtmlForTg(req.reason)}</i>`);
|
|
55634
|
+
lines.push("", "Tap <b>Provide securely</b>, then send the value as your next message. I\u2019ll delete it instantly and store it in the vault \u2014 it is never shown in chat or to the agent.");
|
|
55635
|
+
return lines.join(`
|
|
55636
|
+
`);
|
|
55637
|
+
}
|
|
55638
|
+
async function executeRequestSecret(args) {
|
|
55639
|
+
const chat_id = args.chat_id;
|
|
55640
|
+
if (!chat_id)
|
|
55641
|
+
throw new Error("request_secret: chat_id is required");
|
|
55642
|
+
const key = args.key;
|
|
55643
|
+
if (!key || typeof key !== "string")
|
|
55644
|
+
throw new Error("request_secret: key is required");
|
|
55645
|
+
const reason = typeof args.reason === "string" ? args.reason : undefined;
|
|
55646
|
+
assertAllowedChat(chat_id);
|
|
55647
|
+
if (!VAULT_KEY_REGEX.test(key)) {
|
|
55648
|
+
throw new Error(`request_secret: key must match ${VAULT_KEY_REGEX_LABEL}`);
|
|
55649
|
+
}
|
|
55650
|
+
const agentSlug = process.env.SWITCHROOM_AGENT_NAME || "agent";
|
|
55651
|
+
for (const [sid, p] of pendingSecretRequests) {
|
|
55652
|
+
if (p.chat_id === chat_id && p.key === key)
|
|
55653
|
+
pendingSecretRequests.delete(sid);
|
|
55654
|
+
}
|
|
55655
|
+
const stageId = randomBytes6(4).toString("hex");
|
|
55656
|
+
const pending2 = { agent: agentSlug, chat_id, key, reason, staged_at: Date.now() };
|
|
55657
|
+
pendingSecretRequests.set(stageId, pending2);
|
|
55658
|
+
sweepSecretRequests();
|
|
55659
|
+
const text = renderSecretRequestCard(pending2);
|
|
55660
|
+
const threadId = args.message_thread_id != null ? Number(args.message_thread_id) : undefined;
|
|
55661
|
+
const sent = await retryWithThreadFallback(robustApiCall, (tid) => lockedBot.api.sendMessage(chat_id, text, {
|
|
55662
|
+
parse_mode: "HTML",
|
|
55663
|
+
reply_markup: buildSecretRequestKeyboard(stageId),
|
|
55664
|
+
...tid != null && Number.isFinite(tid) ? { message_thread_id: tid } : {}
|
|
55665
|
+
}), { threadId, chat_id, verb: "request_secret.card" });
|
|
55666
|
+
pending2.card_message_id = sent.message_id;
|
|
55667
|
+
return {
|
|
55668
|
+
content: [
|
|
55669
|
+
{
|
|
55670
|
+
type: "text",
|
|
55671
|
+
text: `request_secret: card sent (stage_id=${stageId}, key=${key}). END YOUR TURN now and wait \u2014 a fresh inbound message arrives once the operator provides (or declines) the secret. Do NOT ask them to paste it as a normal message; the card handles it securely.`
|
|
55672
|
+
}
|
|
55673
|
+
]
|
|
55674
|
+
};
|
|
55675
|
+
}
|
|
55676
|
+
async function writeRequestedSecret(key, value, chat_id) {
|
|
55677
|
+
if (VAULT_APPROVAL_AUTH_MODE === "telegram-id") {
|
|
55678
|
+
return await defaultVaultWritePosture(key, value);
|
|
55679
|
+
}
|
|
55680
|
+
const cached = vaultPassphraseCache.get(chat_id);
|
|
55681
|
+
if (!cached || cached.expiresAt <= Date.now()) {
|
|
55682
|
+
return { ok: false, output: "VAULT-LOCKED: run /vault unlock once in this chat, then have the agent re-request." };
|
|
55683
|
+
}
|
|
55684
|
+
return defaultVaultWrite(key, value, cached.passphrase);
|
|
55685
|
+
}
|
|
55686
|
+
async function captureProvidedSecret(ctx, chat_id, msgId, value) {
|
|
55687
|
+
const armed = armedSecretCaptures.get(chat_id);
|
|
55688
|
+
if (!armed || Date.now() - armed.armed_at > ARMED_SECRET_CAPTURE_TTL_MS) {
|
|
55689
|
+
if (armed)
|
|
55690
|
+
armedSecretCaptures.delete(chat_id);
|
|
55691
|
+
return false;
|
|
55692
|
+
}
|
|
55693
|
+
armedSecretCaptures.delete(chat_id);
|
|
55694
|
+
const pending2 = pendingSecretRequests.get(armed.stageId);
|
|
55695
|
+
pendingSecretRequests.delete(armed.stageId);
|
|
55696
|
+
if (msgId != null)
|
|
55697
|
+
await deleteSensitiveMessage(chat_id, msgId, "provided secret value");
|
|
55698
|
+
const write = await writeRequestedSecret(armed.key, value, chat_id);
|
|
55699
|
+
if (!write.ok) {
|
|
55700
|
+
const parsed = parseVaultCliError(write.output);
|
|
55701
|
+
const rendered = renderVaultCliError(parsed, { verb: "save", key: armed.key });
|
|
55702
|
+
const body = rendered.suppressRaw ? rendered.html : `\u26A0\uFE0F vault write failed:
|
|
55703
|
+
<pre>${escapeHtmlForTg(write.output)}</pre>`;
|
|
55704
|
+
await switchroomReply(ctx, `${body}
|
|
55705
|
+
|
|
55706
|
+
<i>The secret was NOT saved. The agent can re-request with <code>request_secret</code>.</i>`, { html: true });
|
|
55707
|
+
const fts = Date.now();
|
|
55708
|
+
const failMsg = {
|
|
55709
|
+
type: "inbound",
|
|
55710
|
+
chatId: chat_id,
|
|
55711
|
+
messageId: fts,
|
|
55712
|
+
user: "vault-broker",
|
|
55713
|
+
userId: 0,
|
|
55714
|
+
ts: fts,
|
|
55715
|
+
text: `\u26A0\uFE0F The secret you requested for \`vault:${armed.key}\` could NOT be saved (vault write failed). Do not assume it is available; tell the operator or try request_secret again.`,
|
|
55716
|
+
meta: { source: "secret_provide_failed", agent: armed.agent, key: armed.key, stage_id: armed.stageId }
|
|
55717
|
+
};
|
|
55718
|
+
const fdelivered = ipcServer.sendToAgent(armed.agent, failMsg);
|
|
55719
|
+
if (fdelivered)
|
|
55720
|
+
markClaudeBusyForInbound(failMsg);
|
|
55721
|
+
else
|
|
55722
|
+
pendingInboundBuffer.push(armed.agent, failMsg);
|
|
55723
|
+
return true;
|
|
55724
|
+
}
|
|
55725
|
+
await switchroomReply(ctx, `\u2705 saved as <code>vault:${escapeHtmlForTg(armed.key)}</code> (masked: <code>${escapeHtmlForTg(maskToken2(value))}</code>). The agent can now reference it.`, { html: true });
|
|
55726
|
+
const ts = Date.now();
|
|
55727
|
+
const synthetic = {
|
|
55728
|
+
type: "inbound",
|
|
55729
|
+
chatId: chat_id,
|
|
55730
|
+
messageId: ts,
|
|
55731
|
+
user: "vault-broker",
|
|
55732
|
+
userId: 0,
|
|
55733
|
+
ts,
|
|
55734
|
+
text: `\u2705 Operator provided the secret you requested. It is saved as ` + `\`vault:${armed.key}\` \u2014 reference it the usual way. Resume the task ` + `that was waiting on this credential. Do NOT ask the operator to paste it.`,
|
|
55735
|
+
meta: {
|
|
55736
|
+
source: "secret_provided",
|
|
55737
|
+
agent: armed.agent,
|
|
55738
|
+
key: armed.key,
|
|
55739
|
+
stage_id: armed.stageId
|
|
55740
|
+
}
|
|
55741
|
+
};
|
|
55742
|
+
const delivered = ipcServer.sendToAgent(armed.agent, synthetic);
|
|
55743
|
+
if (delivered)
|
|
55744
|
+
markClaudeBusyForInbound(synthetic);
|
|
55745
|
+
else
|
|
55746
|
+
pendingInboundBuffer.push(armed.agent, synthetic);
|
|
55747
|
+
process.stderr.write(`telegram gateway: secret_provided injection agent=${armed.agent} key=${armed.key} stage=${armed.stageId} delivered=${delivered}
|
|
55748
|
+
`);
|
|
55749
|
+
return true;
|
|
55750
|
+
}
|
|
55751
|
+
async function handleSecretRequestCallback(ctx, data) {
|
|
55752
|
+
const senderId = String(ctx.from?.id ?? "");
|
|
55753
|
+
const access = loadAccess();
|
|
55754
|
+
if (!access.allowFrom.includes(senderId)) {
|
|
55755
|
+
await ctx.answerCallbackQuery({ text: "Not authorized." }).catch(() => {});
|
|
55756
|
+
return;
|
|
55757
|
+
}
|
|
55758
|
+
const parts = data.split(":");
|
|
55759
|
+
const action = parts[1];
|
|
55760
|
+
const stageId = parts[2] ?? "";
|
|
55761
|
+
const pending2 = pendingSecretRequests.get(stageId);
|
|
55762
|
+
if (!pending2) {
|
|
55763
|
+
await ctx.answerCallbackQuery({ text: "This request expired." }).catch(() => {});
|
|
55764
|
+
return;
|
|
55765
|
+
}
|
|
55766
|
+
if (action === "provide") {
|
|
55767
|
+
armedSecretCaptures.set(pending2.chat_id, {
|
|
55768
|
+
key: pending2.key,
|
|
55769
|
+
agent: pending2.agent,
|
|
55770
|
+
stageId,
|
|
55771
|
+
armed_at: Date.now()
|
|
55772
|
+
});
|
|
55773
|
+
await ctx.answerCallbackQuery({ text: "Send the value now \u2014 it auto-deletes." }).catch(() => {});
|
|
55774
|
+
if (pending2.card_message_id != null) {
|
|
55775
|
+
await ctx.api.editMessageText(pending2.chat_id, pending2.card_message_id, `\uD83D\uDD10 Send the value for <code>${escapeHtmlForTg(pending2.key)}</code> as your next message \u2014 a single message, exactly as-is (don't add other text). I\u2019ll delete it instantly and store it in the vault.`, { parse_mode: "HTML", reply_markup: { inline_keyboard: [] } }).catch(() => {});
|
|
55776
|
+
}
|
|
55777
|
+
return;
|
|
55778
|
+
}
|
|
55779
|
+
if (action === "decline") {
|
|
55780
|
+
pendingSecretRequests.delete(stageId);
|
|
55781
|
+
armedSecretCaptures.delete(pending2.chat_id);
|
|
55782
|
+
await ctx.answerCallbackQuery({ text: "Declined." }).catch(() => {});
|
|
55783
|
+
if (pending2.card_message_id != null) {
|
|
55784
|
+
await ctx.api.editMessageText(pending2.chat_id, pending2.card_message_id, `\uD83D\uDEAB Declined \u2014 <code>${escapeHtmlForTg(pending2.key)}</code> not provided.`, {
|
|
55785
|
+
parse_mode: "HTML",
|
|
55786
|
+
reply_markup: { inline_keyboard: [] }
|
|
55787
|
+
}).catch(() => {});
|
|
55788
|
+
}
|
|
55789
|
+
const ts = Date.now();
|
|
55790
|
+
const synthetic = {
|
|
55791
|
+
type: "inbound",
|
|
55792
|
+
chatId: pending2.chat_id,
|
|
55793
|
+
messageId: ts,
|
|
55794
|
+
user: "vault-broker",
|
|
55795
|
+
userId: 0,
|
|
55796
|
+
ts,
|
|
55797
|
+
text: `\uD83D\uDEAB Operator declined your request for \`vault:${pending2.key}\`. Proceed without it or ask how they'd like to handle the task.`,
|
|
55798
|
+
meta: { source: "secret_declined", agent: pending2.agent, key: pending2.key, stage_id: stageId }
|
|
55799
|
+
};
|
|
55800
|
+
const delivered = ipcServer.sendToAgent(pending2.agent, synthetic);
|
|
55801
|
+
if (delivered)
|
|
55802
|
+
markClaudeBusyForInbound(synthetic);
|
|
55803
|
+
else
|
|
55804
|
+
pendingInboundBuffer.push(pending2.agent, synthetic);
|
|
55805
|
+
return;
|
|
55806
|
+
}
|
|
55807
|
+
await ctx.answerCallbackQuery().catch(() => {});
|
|
55808
|
+
}
|
|
55386
55809
|
function buildVaultRequestAccessKeyboard(stageId) {
|
|
55387
55810
|
return {
|
|
55388
55811
|
inline_keyboard: [
|
|
@@ -55544,6 +55967,7 @@ async function executeEditMessage(args) {
|
|
|
55544
55967
|
const editConfigMode = editAccess.parseMode ?? "html";
|
|
55545
55968
|
const editFormat = args.format ?? editConfigMode;
|
|
55546
55969
|
let editRawText = repairEscapedWhitespace(args.text);
|
|
55970
|
+
editRawText = redactOutboundText(editRawText, "edit_message");
|
|
55547
55971
|
{
|
|
55548
55972
|
const scrub = scrubVoice(editRawText);
|
|
55549
55973
|
if (scrub.replaced > 0) {
|
|
@@ -56206,6 +56630,7 @@ function handleSessionEvent(ev) {
|
|
|
56206
56630
|
const backstopChatId = chatId;
|
|
56207
56631
|
const backstopThreadId = threadId;
|
|
56208
56632
|
const backstopCtrl = ctrl;
|
|
56633
|
+
capturedText = redactOutboundText(capturedText, "turn_flush");
|
|
56209
56634
|
{
|
|
56210
56635
|
const scrub = scrubVoice(capturedText);
|
|
56211
56636
|
if (scrub.replaced > 0) {
|
|
@@ -56741,6 +57166,11 @@ async function handleInbound(ctx, text, downloadImage, attachment, extraAttachme
|
|
|
56741
57166
|
behavior
|
|
56742
57167
|
});
|
|
56743
57168
|
resumeReactionAfterVerdict();
|
|
57169
|
+
const ftDetails = pendingPermissions.get(request_id);
|
|
57170
|
+
postPermissionResumeMessage({
|
|
57171
|
+
behavior,
|
|
57172
|
+
action: ftDetails ? naturalAction(ftDetails.tool_name, ftDetails.input_preview) : ""
|
|
57173
|
+
});
|
|
56744
57174
|
if (msgId != null) {
|
|
56745
57175
|
const emoji = behavior === "allow" ? "\u2705" : "\u274C";
|
|
56746
57176
|
bot.api.setMessageReaction(chat_id, msgId, [
|
|
@@ -56951,6 +57381,11 @@ ${preBlock(write.output)}`;
|
|
|
56951
57381
|
const parsedQueue = isSteerPrefix ? { queued: false, body: parsedSteer.body } : parseQueuePrefix(text);
|
|
56952
57382
|
const isQueuedPrefix = parsedQueue.queued;
|
|
56953
57383
|
let effectiveText = isSteerPrefix ? parsedSteer.body : isQueuedPrefix ? parsedQueue.body : text;
|
|
57384
|
+
if (armedSecretCaptures.has(chat_id)) {
|
|
57385
|
+
const consumed = await captureProvidedSecret(ctx, chat_id, msgId ?? undefined, text);
|
|
57386
|
+
if (consumed)
|
|
57387
|
+
return;
|
|
57388
|
+
}
|
|
56954
57389
|
try {
|
|
56955
57390
|
const authCodeSentAt = awaitingAuthCodeAt.get(chat_id);
|
|
56956
57391
|
const isAuthFlowContext = authCodeSentAt !== undefined && Date.now() - authCodeSentAt < AUTH_CODE_CONTEXT_TTL_MS;
|
|
@@ -58484,6 +58919,10 @@ async function handlePermissionSlash(ctx, behavior) {
|
|
|
58484
58919
|
}
|
|
58485
58920
|
dispatchPermissionVerdict({ type: "permission", requestId: request_id, behavior });
|
|
58486
58921
|
resumeReactionAfterVerdict();
|
|
58922
|
+
postPermissionResumeMessage({
|
|
58923
|
+
behavior,
|
|
58924
|
+
action: naturalAction(details.tool_name, details.input_preview)
|
|
58925
|
+
});
|
|
58487
58926
|
pendingPermissions.delete(request_id);
|
|
58488
58927
|
process.stderr.write(`[telegram gateway] slash-${behavior} request_id=${request_id} tool=${details.tool_name} by=${senderId}
|
|
58489
58928
|
`);
|
|
@@ -60601,6 +61040,10 @@ ${preBlock(formatSwitchroomOutput(err.message ?? "unknown error"))}`, { html: tr
|
|
|
60601
61040
|
await handleVaultRequestAccessCallback(ctx, data);
|
|
60602
61041
|
return;
|
|
60603
61042
|
}
|
|
61043
|
+
if (data.startsWith("vsp:")) {
|
|
61044
|
+
await handleSecretRequestCallback(ctx, data);
|
|
61045
|
+
return;
|
|
61046
|
+
}
|
|
60604
61047
|
if (data.startsWith("vrd:")) {
|
|
60605
61048
|
await handleVaultRecentDenialCallback(ctx, data);
|
|
60606
61049
|
return;
|
|
@@ -60781,6 +61224,10 @@ ${preBlock(formatSwitchroomOutput(err.message ?? "unknown error"))}`, { html: tr
|
|
|
60781
61224
|
rule: chosen.rule
|
|
60782
61225
|
});
|
|
60783
61226
|
resumeReactionAfterVerdict();
|
|
61227
|
+
postPermissionResumeMessage({
|
|
61228
|
+
behavior: "allow",
|
|
61229
|
+
action: naturalAction(details.tool_name, details.input_preview)
|
|
61230
|
+
});
|
|
60784
61231
|
let durable = false;
|
|
60785
61232
|
let legacy = false;
|
|
60786
61233
|
let failReason = "";
|
|
@@ -60881,10 +61328,12 @@ ${editLabel}` : editLabel,
|
|
|
60881
61328
|
});
|
|
60882
61329
|
return;
|
|
60883
61330
|
}
|
|
61331
|
+
const resumeAction = (() => {
|
|
61332
|
+
const d = pendingPermissions.get(request_id);
|
|
61333
|
+
return d ? naturalAction(d.tool_name, d.input_preview) : "";
|
|
61334
|
+
})();
|
|
60884
61335
|
pendingPermissions.delete(request_id);
|
|
60885
|
-
const
|
|
60886
|
-
const resumeBeat = resumeAgent ? `\u25B6\uFE0F ${escapeHtmlForTg(resumeAgent)} resuming\u2026` : "\u25B6\uFE0F resuming\u2026";
|
|
60887
|
-
const label = `${behavior === "allow" ? "\u2705 Allowed" : "\u274C Denied"} \xB7 ${resumeBeat}`;
|
|
61336
|
+
const label = behavior === "allow" ? "\u2705 Allowed" : "\u274C Denied";
|
|
60888
61337
|
const msg = ctx.callbackQuery?.message;
|
|
60889
61338
|
const baseText = msg && "text" in msg && msg.text ? escapeHtmlForTg(msg.text) : "";
|
|
60890
61339
|
await finalizeCallback(ctx, {
|
|
@@ -60900,6 +61349,10 @@ ${label}` : label,
|
|
|
60900
61349
|
behavior
|
|
60901
61350
|
});
|
|
60902
61351
|
resumeReactionAfterVerdict();
|
|
61352
|
+
postPermissionResumeMessage({
|
|
61353
|
+
behavior,
|
|
61354
|
+
action: resumeAction
|
|
61355
|
+
});
|
|
60903
61356
|
}
|
|
60904
61357
|
});
|
|
60905
61358
|
});
|