switchroom 0.14.27 → 0.14.29
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 +7 -4
- package/telegram-plugin/dist/bridge/bridge.js +18 -0
- package/telegram-plugin/dist/gateway/gateway.js +2151 -1729
- package/telegram-plugin/dist/server.js +18 -0
- package/telegram-plugin/gateway/gateway.ts +464 -12
- package/telegram-plugin/history.ts +16 -4
- package/telegram-plugin/permission-title.ts +48 -0
- package/telegram-plugin/registry/subagents-schema.ts +35 -0
- package/telegram-plugin/registry/subagents.test.ts +78 -0
- package/telegram-plugin/secret-detect/patterns.ts +8 -0
- package/telegram-plugin/secret-detect/redact.ts +76 -0
- package/telegram-plugin/session-tail.ts +15 -0
- package/telegram-plugin/subagent-watcher.ts +19 -1
- package/telegram-plugin/tests/card-format.test.ts +16 -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/session-tail.test.ts +43 -0
- package/telegram-plugin/tests/worker-activity-feed.test.ts +15 -0
- package/telegram-plugin/uat/scenarios/jtbd-request-secret-dm.test.ts +101 -0
- package/telegram-plugin/worker-activity-feed.ts +5 -2
|
@@ -6557,10 +6557,10 @@ function stripMarkdown(s) {
|
|
|
6557
6557
|
out = out.replace(/__(.+?)__/g, "$1");
|
|
6558
6558
|
out = out.replace(/\*(.+?)\*/g, "$1");
|
|
6559
6559
|
out = out.replace(/(?<![A-Za-z0-9])_(.+?)_(?![A-Za-z0-9])/g, "$1");
|
|
6560
|
-
out = out.replace(/^\s{0,3}#{1,6}\s
|
|
6561
|
-
out = out.replace(/^\s{0,3}>\s
|
|
6562
|
-
out = out.replace(/^\s{0,3}[-*+]\s
|
|
6563
|
-
out = out.replace(/^\s{0,3}\d+[.)]\s
|
|
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
6564
|
out = out.replace(/\*\*/g, "");
|
|
6565
6565
|
return out.trim();
|
|
6566
6566
|
}
|
|
@@ -24866,1269 +24866,380 @@ var init_loader = __esm(() => {
|
|
|
24866
24866
|
};
|
|
24867
24867
|
});
|
|
24868
24868
|
|
|
24869
|
-
//
|
|
24870
|
-
var
|
|
24871
|
-
|
|
24872
|
-
|
|
24873
|
-
|
|
24874
|
-
|
|
24875
|
-
|
|
24876
|
-
|
|
24877
|
-
|
|
24878
|
-
|
|
24879
|
-
|
|
24880
|
-
|
|
24881
|
-
|
|
24882
|
-
|
|
24883
|
-
|
|
24884
|
-
|
|
24885
|
-
})
|
|
24886
|
-
|
|
24887
|
-
|
|
24888
|
-
|
|
24889
|
-
|
|
24890
|
-
|
|
24891
|
-
|
|
24892
|
-
|
|
24893
|
-
|
|
24894
|
-
|
|
24895
|
-
|
|
24896
|
-
|
|
24897
|
-
|
|
24898
|
-
|
|
24899
|
-
|
|
24900
|
-
|
|
24901
|
-
|
|
24902
|
-
|
|
24903
|
-
|
|
24904
|
-
|
|
24905
|
-
|
|
24906
|
-
|
|
24907
|
-
|
|
24908
|
-
|
|
24909
|
-
|
|
24910
|
-
|
|
24911
|
-
|
|
24912
|
-
|
|
24913
|
-
|
|
24914
|
-
|
|
24915
|
-
|
|
24916
|
-
|
|
24917
|
-
|
|
24918
|
-
|
|
24919
|
-
|
|
24920
|
-
|
|
24921
|
-
|
|
24922
|
-
|
|
24923
|
-
|
|
24924
|
-
|
|
24925
|
-
|
|
24926
|
-
reply_to_message_id INTEGER,
|
|
24927
|
-
reply_to_text TEXT,
|
|
24928
|
-
PRIMARY KEY (chat_id, thread_id, message_id)
|
|
24929
|
-
)
|
|
24930
|
-
`);
|
|
24931
|
-
db.exec(`
|
|
24932
|
-
CREATE INDEX IF NOT EXISTS idx_messages_recent
|
|
24933
|
-
ON messages (chat_id, thread_id, ts DESC)
|
|
24934
|
-
`);
|
|
24935
|
-
for (const column of ["reply_to_message_id INTEGER", "reply_to_text TEXT", "user_reaction TEXT"]) {
|
|
24936
|
-
try {
|
|
24937
|
-
db.exec(`ALTER TABLE messages ADD COLUMN ${column}`);
|
|
24938
|
-
} catch (err) {
|
|
24939
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
24940
|
-
if (!/duplicate column name/i.test(msg))
|
|
24941
|
-
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"
|
|
24942
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);
|
|
24943
24938
|
}
|
|
24944
|
-
|
|
24945
|
-
|
|
24946
|
-
|
|
24947
|
-
|
|
24948
|
-
|
|
24949
|
-
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);
|
|
24950
24944
|
}
|
|
24945
|
+
return h;
|
|
24951
24946
|
}
|
|
24952
|
-
|
|
24953
|
-
|
|
24954
|
-
|
|
24955
|
-
|
|
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
|
+
});
|
|
24956
24973
|
}
|
|
24974
|
+
return hits;
|
|
24957
24975
|
}
|
|
24958
|
-
|
|
24959
|
-
|
|
24960
|
-
|
|
24961
|
-
|
|
24962
|
-
|
|
24963
|
-
|
|
24964
|
-
|
|
24965
|
-
|
|
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 }];
|
|
24966
24985
|
}
|
|
24967
|
-
|
|
24968
|
-
|
|
24969
|
-
|
|
24970
|
-
|
|
24971
|
-
|
|
24972
|
-
|
|
24973
|
-
const cutoffSec = (nowSec ?? Math.floor(Date.now() / 1000)) - retentionDays * 86400;
|
|
24974
|
-
const stmt = db.prepare(`
|
|
24975
|
-
DELETE FROM messages
|
|
24976
|
-
WHERE rowid IN (
|
|
24977
|
-
SELECT rowid FROM messages WHERE ts < ? LIMIT ?
|
|
24978
|
-
)
|
|
24979
|
-
`);
|
|
24980
|
-
let total = 0;
|
|
24981
|
-
for (let i = 0;i < 1000; i++) {
|
|
24982
|
-
const result = stmt.run(cutoffSec, batchLimit);
|
|
24983
|
-
const n = result.changes ?? 0;
|
|
24984
|
-
total += n;
|
|
24985
|
-
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)
|
|
24986
24992
|
break;
|
|
24993
|
+
offset = end - OVERLAP;
|
|
24987
24994
|
}
|
|
24988
|
-
return
|
|
24989
|
-
}
|
|
24990
|
-
function requireDb() {
|
|
24991
|
-
if (db == null) {
|
|
24992
|
-
throw new Error("history: initHistory() must be called before any record/query operation");
|
|
24993
|
-
}
|
|
24994
|
-
return db;
|
|
24995
|
-
}
|
|
24996
|
-
function recordInbound(args) {
|
|
24997
|
-
if (args.message_id == null)
|
|
24998
|
-
return;
|
|
24999
|
-
const stmt = requireDb().prepare(`
|
|
25000
|
-
INSERT OR REPLACE INTO messages
|
|
25001
|
-
(chat_id, thread_id, message_id, role, user, user_id, ts, text, attachment_kind, group_id, reply_to_message_id, reply_to_text)
|
|
25002
|
-
VALUES (?, ?, ?, 'user', ?, ?, ?, ?, ?, NULL, ?, ?)
|
|
25003
|
-
`);
|
|
25004
|
-
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);
|
|
25005
|
-
}
|
|
25006
|
-
function recordOutbound(args) {
|
|
25007
|
-
if (args.message_ids.length === 0)
|
|
25008
|
-
return;
|
|
25009
|
-
const ts = args.ts ?? Math.floor(Date.now() / 1000);
|
|
25010
|
-
const groupId = args.message_ids[0];
|
|
25011
|
-
const stmt = requireDb().prepare(`
|
|
25012
|
-
INSERT OR REPLACE INTO messages
|
|
25013
|
-
(chat_id, thread_id, message_id, role, user, user_id, ts, text, attachment_kind, group_id)
|
|
25014
|
-
VALUES (?, ?, ?, 'assistant', NULL, NULL, ?, ?, ?, ?)
|
|
25015
|
-
`);
|
|
25016
|
-
const tx = requireDb().transaction((rows2) => {
|
|
25017
|
-
for (const [msgId, text, attachKind] of rows2) {
|
|
25018
|
-
stmt.run(args.chat_id, args.thread_id ?? null, msgId, ts, text, attachKind, groupId);
|
|
25019
|
-
}
|
|
25020
|
-
});
|
|
25021
|
-
const rows = args.message_ids.map((id, i) => [
|
|
25022
|
-
id,
|
|
25023
|
-
args.texts[i] ?? "",
|
|
25024
|
-
args.attachment_kinds?.[i] ?? null
|
|
25025
|
-
]);
|
|
25026
|
-
tx(rows);
|
|
24995
|
+
return out;
|
|
25027
24996
|
}
|
|
25028
|
-
|
|
25029
|
-
|
|
25030
|
-
|
|
25031
|
-
|
|
25032
|
-
|
|
25033
|
-
|
|
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);
|
|
25034
25009
|
}
|
|
25035
|
-
|
|
25036
|
-
|
|
25037
|
-
|
|
25038
|
-
|
|
25039
|
-
|
|
25040
|
-
|
|
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";
|
|
25041
25021
|
}
|
|
25042
|
-
function
|
|
25043
|
-
|
|
25044
|
-
|
|
25045
|
-
|
|
25046
|
-
|
|
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}`;
|
|
25047
25027
|
}
|
|
25048
|
-
function
|
|
25049
|
-
|
|
25050
|
-
|
|
25051
|
-
|
|
25052
|
-
|
|
25053
|
-
|
|
25054
|
-
} else {
|
|
25055
|
-
sql += " AND thread_id = ?";
|
|
25056
|
-
params.push(threadId);
|
|
25057
|
-
}
|
|
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)}`;
|
|
25058
25034
|
}
|
|
25059
|
-
|
|
25060
|
-
|
|
25061
|
-
|
|
25062
|
-
}
|
|
25063
|
-
|
|
25064
|
-
|
|
25065
|
-
if (!row)
|
|
25066
|
-
return null;
|
|
25067
|
-
return { role: row.role, text: row.text ?? "" };
|
|
25068
|
-
}
|
|
25069
|
-
function getRecentOutboundCount(chatId, withinSeconds) {
|
|
25070
|
-
const cutoff = Math.floor(Date.now() / 1000) - withinSeconds;
|
|
25071
|
-
const row = requireDb().prepare("SELECT COUNT(*) as cnt FROM messages WHERE chat_id = ? AND role = ? AND ts >= ?").get(chatId, "assistant", cutoff);
|
|
25072
|
-
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}`;
|
|
25073
25041
|
}
|
|
25074
|
-
|
|
25075
|
-
|
|
25076
|
-
|
|
25077
|
-
|
|
25078
|
-
|
|
25079
|
-
if (opts.thread_id === null) {
|
|
25080
|
-
sql += " AND thread_id IS NULL";
|
|
25081
|
-
} else {
|
|
25082
|
-
sql += " AND thread_id = ?";
|
|
25083
|
-
params.push(opts.thread_id);
|
|
25084
|
-
}
|
|
25085
|
-
}
|
|
25086
|
-
if (opts.before_message_id != null) {
|
|
25087
|
-
sql += " AND message_id < ?";
|
|
25088
|
-
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)}`;
|
|
25089
25047
|
}
|
|
25090
|
-
|
|
25091
|
-
params.push(limit);
|
|
25092
|
-
const rows = requireDb().prepare(sql).all(...params);
|
|
25093
|
-
rows.reverse();
|
|
25094
|
-
return rows;
|
|
25048
|
+
return "***";
|
|
25095
25049
|
}
|
|
25096
|
-
var DatabaseClass = null, DEFAULT_LIMIT = 10, MAX_LIMIT = 50, db = null;
|
|
25097
|
-
var init_history = () => {};
|
|
25098
25050
|
|
|
25099
|
-
//
|
|
25100
|
-
|
|
25101
|
-
|
|
25102
|
-
|
|
25103
|
-
|
|
25104
|
-
|
|
25105
|
-
|
|
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;
|
|
25106
25060
|
try {
|
|
25107
|
-
|
|
25108
|
-
return raw.length > 0 ? raw : null;
|
|
25061
|
+
u = new URL(raw);
|
|
25109
25062
|
} catch {
|
|
25110
25063
|
return null;
|
|
25111
25064
|
}
|
|
25112
|
-
|
|
25113
|
-
|
|
25114
|
-
|
|
25115
|
-
|
|
25116
|
-
|
|
25117
|
-
|
|
25118
|
-
|
|
25119
|
-
|
|
25120
|
-
|
|
25121
|
-
|
|
25122
|
-
if (v == null)
|
|
25123
|
-
return null;
|
|
25124
|
-
const n = Number(v);
|
|
25125
|
-
if (!Number.isFinite(n) || n <= 0)
|
|
25126
|
-
return null;
|
|
25127
|
-
return new Date(n * 1000);
|
|
25128
|
-
}
|
|
25129
|
-
function parseQuotaHeaders(headers) {
|
|
25130
|
-
const fiveHour = parseFloatHeader(headers, "anthropic-ratelimit-unified-5h-utilization");
|
|
25131
|
-
const sevenDay = parseFloatHeader(headers, "anthropic-ratelimit-unified-7d-utilization");
|
|
25132
|
-
if (fiveHour == null && sevenDay == null) {
|
|
25133
|
-
return {
|
|
25134
|
-
ok: false,
|
|
25135
|
-
reason: "no unified rate-limit headers in response (API token, not OAuth?)"
|
|
25136
|
-
};
|
|
25137
|
-
}
|
|
25138
|
-
return {
|
|
25139
|
-
ok: true,
|
|
25140
|
-
data: {
|
|
25141
|
-
fiveHourUtilizationPct: (fiveHour ?? 0) * 100,
|
|
25142
|
-
sevenDayUtilizationPct: (sevenDay ?? 0) * 100,
|
|
25143
|
-
fiveHourResetAt: parseEpochHeader(headers, "anthropic-ratelimit-unified-5h-reset"),
|
|
25144
|
-
sevenDayResetAt: parseEpochHeader(headers, "anthropic-ratelimit-unified-7d-reset"),
|
|
25145
|
-
representativeClaim: headers.get("anthropic-ratelimit-unified-representative-claim"),
|
|
25146
|
-
overageStatus: headers.get("anthropic-ratelimit-unified-overage-status"),
|
|
25147
|
-
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;
|
|
25148
25075
|
}
|
|
25149
|
-
};
|
|
25150
|
-
}
|
|
25151
|
-
async function fetchQuota(opts) {
|
|
25152
|
-
let token;
|
|
25153
|
-
if (opts.accessToken && opts.claudeConfigDir) {
|
|
25154
|
-
return {
|
|
25155
|
-
ok: false,
|
|
25156
|
-
reason: "pass only one of `accessToken` or `claudeConfigDir`, not both"
|
|
25157
|
-
};
|
|
25158
|
-
}
|
|
25159
|
-
if (opts.accessToken) {
|
|
25160
|
-
token = opts.accessToken.trim().length > 0 ? opts.accessToken : null;
|
|
25161
|
-
} else if (opts.claudeConfigDir) {
|
|
25162
|
-
token = readOauthToken(opts.claudeConfigDir);
|
|
25163
|
-
} else {
|
|
25164
|
-
return {
|
|
25165
|
-
ok: false,
|
|
25166
|
-
reason: "fetchQuota requires `accessToken` or `claudeConfigDir`"
|
|
25167
|
-
};
|
|
25168
25076
|
}
|
|
25169
|
-
|
|
25170
|
-
|
|
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;
|
|
25171
25104
|
}
|
|
25172
|
-
|
|
25173
|
-
|
|
25174
|
-
|
|
25175
|
-
|
|
25176
|
-
|
|
25177
|
-
|
|
25178
|
-
|
|
25179
|
-
|
|
25180
|
-
|
|
25181
|
-
|
|
25182
|
-
|
|
25183
|
-
|
|
25184
|
-
|
|
25185
|
-
|
|
25186
|
-
|
|
25187
|
-
body: JSON.stringify({
|
|
25188
|
-
model: opts.model ?? DEFAULT_PROBE_MODEL,
|
|
25189
|
-
max_tokens: 1,
|
|
25190
|
-
messages: [{ role: "user", content: "hi" }]
|
|
25191
|
-
}),
|
|
25192
|
-
signal: controller.signal
|
|
25193
|
-
});
|
|
25194
|
-
} catch (err) {
|
|
25195
|
-
const msg = err?.message ?? String(err);
|
|
25196
|
-
return { ok: false, reason: `request failed: ${msg}` };
|
|
25197
|
-
} finally {
|
|
25198
|
-
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;
|
|
25199
25120
|
}
|
|
25200
|
-
|
|
25201
|
-
|
|
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;
|
|
25202
25136
|
}
|
|
25203
|
-
|
|
25204
|
-
|
|
25205
|
-
|
|
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]);
|
|
25206
25141
|
}
|
|
25207
|
-
|
|
25208
|
-
}
|
|
25209
|
-
function formatQuotaLine(q) {
|
|
25210
|
-
const fmt = (n) => `${Math.round(n)}%`;
|
|
25211
|
-
return `${fmt(q.fiveHourUtilizationPct)} / 5h \u00b7 ${fmt(q.sevenDayUtilizationPct)} / 7d`;
|
|
25212
|
-
}
|
|
25213
|
-
function formatResetRelative(target, now = new Date) {
|
|
25214
|
-
if (!target)
|
|
25215
|
-
return "\u2014";
|
|
25216
|
-
const deltaMs = target.getTime() - now.getTime();
|
|
25217
|
-
if (deltaMs <= 0)
|
|
25218
|
-
return "resets now";
|
|
25219
|
-
const totalMin = Math.round(deltaMs / 60000);
|
|
25220
|
-
if (totalMin < 60)
|
|
25221
|
-
return `resets in ${totalMin}m`;
|
|
25222
|
-
const hours = Math.floor(totalMin / 60);
|
|
25223
|
-
const mins = totalMin % 60;
|
|
25224
|
-
if (hours < 24)
|
|
25225
|
-
return mins > 0 ? `resets in ${hours}h ${mins}m` : `resets in ${hours}h`;
|
|
25226
|
-
const days = Math.floor(hours / 24);
|
|
25227
|
-
const remH = hours % 24;
|
|
25228
|
-
return remH > 0 ? `resets in ${days}d ${remH}h` : `resets in ${days}d`;
|
|
25229
|
-
}
|
|
25230
|
-
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";
|
|
25231
|
-
var init_quota_check = () => {};
|
|
25142
|
+
exports2.binarySearch = binarySearch;
|
|
25143
|
+
});
|
|
25232
25144
|
|
|
25233
|
-
// ../
|
|
25234
|
-
|
|
25235
|
-
|
|
25236
|
-
|
|
25237
|
-
|
|
25238
|
-
|
|
25239
|
-
|
|
25240
|
-
|
|
25241
|
-
|
|
25242
|
-
|
|
25243
|
-
|
|
25244
|
-
|
|
25245
|
-
|
|
25246
|
-
|
|
25247
|
-
|
|
25248
|
-
|
|
25249
|
-
|
|
25250
|
-
|
|
25251
|
-
|
|
25252
|
-
|
|
25253
|
-
|
|
25254
|
-
|
|
25255
|
-
|
|
25256
|
-
|
|
25257
|
-
return opened;
|
|
25258
|
-
} catch (e) {
|
|
25259
|
-
errors3.push(`${name}: ${e instanceof Error ? e.message : String(e)}`);
|
|
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;
|
|
25161
|
+
}
|
|
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;
|
|
25260
25169
|
}
|
|
25170
|
+
this.indice.push(nextIndex);
|
|
25171
|
+
regexp.lastIndex = nextIndex;
|
|
25261
25172
|
}
|
|
25262
|
-
|
|
25263
|
-
|
|
25264
|
-
|
|
25265
|
-
}
|
|
25266
|
-
|
|
25267
|
-
|
|
25268
|
-
|
|
25269
|
-
|
|
25270
|
-
|
|
25271
|
-
|
|
25272
|
-
|
|
25273
|
-
|
|
25274
|
-
|
|
25275
|
-
|
|
25276
|
-
|
|
25277
|
-
|
|
25278
|
-
|
|
25279
|
-
|
|
25280
|
-
|
|
25281
|
-
|
|
25282
|
-
|
|
25283
|
-
|
|
25284
|
-
|
|
25285
|
-
|
|
25286
|
-
function isReservedAgentName(name) {
|
|
25287
|
-
return RESERVED_AGENT_NAMES.has(name);
|
|
25288
|
-
}
|
|
25289
|
-
function unlockSocketFor(dataSocketPath) {
|
|
25290
|
-
if (dataSocketPath.endsWith("/sock")) {
|
|
25291
|
-
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
|
+
}
|
|
25292
25197
|
}
|
|
25293
|
-
|
|
25294
|
-
}
|
|
25295
|
-
|
|
25296
|
-
var
|
|
25297
|
-
|
|
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);
|
|
25298
25204
|
});
|
|
25299
25205
|
|
|
25300
|
-
// ../
|
|
25301
|
-
|
|
25302
|
-
|
|
25303
|
-
|
|
25304
|
-
|
|
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);
|
|
25305
25214
|
}
|
|
25306
|
-
|
|
25307
|
-
|
|
25308
|
-
|
|
25309
|
-
|
|
25310
|
-
|
|
25311
|
-
|
|
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
|
+
}
|
|
25312
25223
|
}
|
|
25313
|
-
|
|
25314
|
-
|
|
25315
|
-
|
|
25316
|
-
|
|
25317
|
-
var init_protocol2 = __esm(() => {
|
|
25318
|
-
init_zod();
|
|
25319
|
-
init_peercred();
|
|
25320
|
-
MAX_FRAME_BYTES2 = 64 * 1024;
|
|
25321
|
-
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), {
|
|
25322
|
-
message: "agent name is reserved"
|
|
25323
|
-
});
|
|
25324
|
-
GetRequestSchema = exports_external.object({
|
|
25325
|
-
v: exports_external.literal(1),
|
|
25326
|
-
op: exports_external.literal("get"),
|
|
25327
|
-
key: exports_external.string().min(1),
|
|
25328
|
-
filename: exports_external.string().optional(),
|
|
25329
|
-
token: exports_external.string().optional()
|
|
25330
|
-
});
|
|
25331
|
-
PutRequestSchema = exports_external.object({
|
|
25332
|
-
v: exports_external.literal(1),
|
|
25333
|
-
op: exports_external.literal("put"),
|
|
25334
|
-
key: exports_external.string().min(1),
|
|
25335
|
-
entry: exports_external.union([
|
|
25336
|
-
exports_external.object({ kind: exports_external.literal("string"), value: exports_external.string() }),
|
|
25337
|
-
exports_external.object({ kind: exports_external.literal("binary"), value: exports_external.string() })
|
|
25338
|
-
]),
|
|
25339
|
-
token: exports_external.string().optional(),
|
|
25340
|
-
passphrase: exports_external.string().optional(),
|
|
25341
|
-
attest_via_posture: exports_external.boolean().optional()
|
|
25342
|
-
});
|
|
25343
|
-
ListRequestSchema = exports_external.object({
|
|
25344
|
-
v: exports_external.literal(1),
|
|
25345
|
-
op: exports_external.literal("list"),
|
|
25346
|
-
token: exports_external.string().optional()
|
|
25347
|
-
});
|
|
25348
|
-
MintGrantRequestSchema = exports_external.object({
|
|
25349
|
-
v: exports_external.literal(1),
|
|
25350
|
-
op: exports_external.literal("mint_grant"),
|
|
25351
|
-
agent: AgentNameSchema,
|
|
25352
|
-
keys: exports_external.array(exports_external.string().min(1)),
|
|
25353
|
-
ttl_seconds: exports_external.number().int().positive().nullable(),
|
|
25354
|
-
description: exports_external.string().optional(),
|
|
25355
|
-
write_keys: exports_external.array(exports_external.string().min(1)).optional(),
|
|
25356
|
-
passphrase: exports_external.string().optional(),
|
|
25357
|
-
attest_via_posture: exports_external.boolean().optional()
|
|
25358
|
-
});
|
|
25359
|
-
ListGrantsRequestSchema = exports_external.object({
|
|
25360
|
-
v: exports_external.literal(1),
|
|
25361
|
-
op: exports_external.literal("list_grants"),
|
|
25362
|
-
agent: AgentNameSchema.optional(),
|
|
25363
|
-
passphrase: exports_external.string().optional(),
|
|
25364
|
-
attest_via_posture: exports_external.boolean().optional()
|
|
25365
|
-
});
|
|
25366
|
-
RevokeGrantRequestSchema = exports_external.object({
|
|
25367
|
-
v: exports_external.literal(1),
|
|
25368
|
-
op: exports_external.literal("revoke_grant"),
|
|
25369
|
-
id: exports_external.string().min(1)
|
|
25370
|
-
});
|
|
25371
|
-
StatusRequestSchema = exports_external.object({
|
|
25372
|
-
v: exports_external.literal(1),
|
|
25373
|
-
op: exports_external.literal("status")
|
|
25374
|
-
});
|
|
25375
|
-
LockRequestSchema = exports_external.object({
|
|
25376
|
-
v: exports_external.literal(1),
|
|
25377
|
-
op: exports_external.literal("lock")
|
|
25378
|
-
});
|
|
25379
|
-
PreflightAccessRequestSchema = exports_external.object({
|
|
25380
|
-
v: exports_external.literal(1),
|
|
25381
|
-
op: exports_external.literal("preflight_access"),
|
|
25382
|
-
agent: AgentNameSchema,
|
|
25383
|
-
keys: exports_external.array(exports_external.string().min(1)).min(1).max(128)
|
|
25384
|
-
});
|
|
25385
|
-
OkPreflightAccessResponseSchema = exports_external.object({
|
|
25386
|
-
ok: exports_external.literal(true),
|
|
25387
|
-
op: exports_external.literal("preflight_access"),
|
|
25388
|
-
results: exports_external.array(exports_external.object({
|
|
25389
|
-
key: exports_external.string(),
|
|
25390
|
-
exists: exports_external.boolean(),
|
|
25391
|
-
acl_ok: exports_external.boolean(),
|
|
25392
|
-
acl_reason: exports_external.string().optional(),
|
|
25393
|
-
scope_ok: exports_external.boolean(),
|
|
25394
|
-
scope_reason: exports_external.string().optional()
|
|
25395
|
-
}))
|
|
25396
|
-
});
|
|
25397
|
-
ApprovalRequestRequestSchema = exports_external.object({
|
|
25398
|
-
v: exports_external.literal(1),
|
|
25399
|
-
op: exports_external.literal("approval_request"),
|
|
25400
|
-
agent_unit: exports_external.string().min(1),
|
|
25401
|
-
scope: exports_external.string().min(1),
|
|
25402
|
-
action: exports_external.string().min(1),
|
|
25403
|
-
approver_set: exports_external.array(exports_external.string()),
|
|
25404
|
-
why: exports_external.string().optional(),
|
|
25405
|
-
ttl_ms: exports_external.number().int().positive().optional()
|
|
25406
|
-
});
|
|
25407
|
-
ApprovalLookupRequestSchema = exports_external.object({
|
|
25408
|
-
v: exports_external.literal(1),
|
|
25409
|
-
op: exports_external.literal("approval_lookup"),
|
|
25410
|
-
agent_unit: exports_external.string().min(1),
|
|
25411
|
-
scope: exports_external.string().min(1),
|
|
25412
|
-
action: exports_external.string().min(1),
|
|
25413
|
-
current_approver_set: exports_external.array(exports_external.string())
|
|
25414
|
-
});
|
|
25415
|
-
ApprovalConsumeRequestSchema = exports_external.object({
|
|
25416
|
-
v: exports_external.literal(1),
|
|
25417
|
-
op: exports_external.literal("approval_consume"),
|
|
25418
|
-
request_id: exports_external.string().regex(/^[0-9a-f]{32}$/)
|
|
25419
|
-
});
|
|
25420
|
-
ApprovalRevokeRequestSchema = exports_external.object({
|
|
25421
|
-
v: exports_external.literal(1),
|
|
25422
|
-
op: exports_external.literal("approval_revoke"),
|
|
25423
|
-
decision_id: exports_external.string().min(1),
|
|
25424
|
-
actor: exports_external.string().min(1),
|
|
25425
|
-
reason: exports_external.string().optional()
|
|
25426
|
-
});
|
|
25427
|
-
ApprovalListRequestSchema = exports_external.object({
|
|
25428
|
-
v: exports_external.literal(1),
|
|
25429
|
-
op: exports_external.literal("approval_list"),
|
|
25430
|
-
agent_unit: exports_external.string().optional()
|
|
25431
|
-
});
|
|
25432
|
-
ApprovalDecisionModeSchema = exports_external.enum([
|
|
25433
|
-
"allow_once",
|
|
25434
|
-
"allow_always",
|
|
25435
|
-
"allow_ttl",
|
|
25436
|
-
"deny",
|
|
25437
|
-
"deny_perm"
|
|
25438
|
-
]);
|
|
25439
|
-
ApprovalRecordRequestSchema = exports_external.object({
|
|
25440
|
-
v: exports_external.literal(1),
|
|
25441
|
-
op: exports_external.literal("approval_record"),
|
|
25442
|
-
request_id: exports_external.string().regex(/^[0-9a-f]{32}$/),
|
|
25443
|
-
decision: ApprovalDecisionModeSchema,
|
|
25444
|
-
approver_set: exports_external.array(exports_external.string()),
|
|
25445
|
-
granted_by_user_id: exports_external.number().int(),
|
|
25446
|
-
ttl_ms: exports_external.number().int().positive().nullable().optional()
|
|
25447
|
-
});
|
|
25448
|
-
ApprovalConsumeRecordRequestSchema = exports_external.object({
|
|
25449
|
-
v: exports_external.literal(1),
|
|
25450
|
-
op: exports_external.literal("approval_consume_record"),
|
|
25451
|
-
request_id: exports_external.string().regex(/^[0-9a-f]{32}$/),
|
|
25452
|
-
decision: ApprovalDecisionModeSchema,
|
|
25453
|
-
approver_set: exports_external.array(exports_external.string()),
|
|
25454
|
-
granted_by_user_id: exports_external.number().int(),
|
|
25455
|
-
ttl_ms: exports_external.number().int().positive().nullable().optional()
|
|
25456
|
-
});
|
|
25457
|
-
RequestSchema2 = exports_external.discriminatedUnion("op", [
|
|
25458
|
-
GetRequestSchema,
|
|
25459
|
-
PutRequestSchema,
|
|
25460
|
-
ListRequestSchema,
|
|
25461
|
-
StatusRequestSchema,
|
|
25462
|
-
LockRequestSchema,
|
|
25463
|
-
PreflightAccessRequestSchema,
|
|
25464
|
-
MintGrantRequestSchema,
|
|
25465
|
-
ListGrantsRequestSchema,
|
|
25466
|
-
RevokeGrantRequestSchema,
|
|
25467
|
-
ApprovalRequestRequestSchema,
|
|
25468
|
-
ApprovalLookupRequestSchema,
|
|
25469
|
-
ApprovalConsumeRequestSchema,
|
|
25470
|
-
ApprovalRevokeRequestSchema,
|
|
25471
|
-
ApprovalListRequestSchema,
|
|
25472
|
-
ApprovalRecordRequestSchema,
|
|
25473
|
-
ApprovalConsumeRecordRequestSchema
|
|
25474
|
-
]);
|
|
25475
|
-
VaultEntrySchema = exports_external.union([
|
|
25476
|
-
exports_external.object({ kind: exports_external.literal("string"), value: exports_external.string() }),
|
|
25477
|
-
exports_external.object({ kind: exports_external.literal("binary"), value: exports_external.string() }),
|
|
25478
|
-
exports_external.object({
|
|
25479
|
-
kind: exports_external.literal("files"),
|
|
25480
|
-
files: exports_external.record(exports_external.string(), exports_external.object({
|
|
25481
|
-
encoding: exports_external.enum(["utf8", "base64"]),
|
|
25482
|
-
value: exports_external.string()
|
|
25483
|
-
}))
|
|
25484
|
-
})
|
|
25485
|
-
]);
|
|
25486
|
-
ErrorCode = exports_external.enum([
|
|
25487
|
-
"LOCKED",
|
|
25488
|
-
"DENIED",
|
|
25489
|
-
"UNKNOWN_KEY",
|
|
25490
|
-
"BAD_REQUEST",
|
|
25491
|
-
"INTERNAL"
|
|
25492
|
-
]);
|
|
25493
|
-
OkEntryResponseSchema = exports_external.object({
|
|
25494
|
-
ok: exports_external.literal(true),
|
|
25495
|
-
entry: VaultEntrySchema
|
|
25496
|
-
});
|
|
25497
|
-
OkKeysResponseSchema = exports_external.object({
|
|
25498
|
-
ok: exports_external.literal(true),
|
|
25499
|
-
keys: exports_external.array(exports_external.string())
|
|
25500
|
-
});
|
|
25501
|
-
BrokerStatus = exports_external.object({
|
|
25502
|
-
unlocked: exports_external.boolean(),
|
|
25503
|
-
keyCount: exports_external.number().int().nonnegative(),
|
|
25504
|
-
uptimeSec: exports_external.number().nonnegative()
|
|
25505
|
-
});
|
|
25506
|
-
OkStatusResponseSchema = exports_external.object({
|
|
25507
|
-
ok: exports_external.literal(true),
|
|
25508
|
-
status: BrokerStatus
|
|
25509
|
-
});
|
|
25510
|
-
OkLockResponseSchema = exports_external.object({
|
|
25511
|
-
ok: exports_external.literal(true),
|
|
25512
|
-
locked: exports_external.literal(true)
|
|
25513
|
-
});
|
|
25514
|
-
OkPutResponseSchema = exports_external.object({
|
|
25515
|
-
ok: exports_external.literal(true),
|
|
25516
|
-
put: exports_external.literal(true),
|
|
25517
|
-
key: exports_external.string()
|
|
25518
|
-
});
|
|
25519
|
-
OkMintGrantResponseSchema = exports_external.object({
|
|
25520
|
-
ok: exports_external.literal(true),
|
|
25521
|
-
token: exports_external.string(),
|
|
25522
|
-
id: exports_external.string(),
|
|
25523
|
-
expires_at: exports_external.number().nullable()
|
|
25524
|
-
});
|
|
25525
|
-
GrantMetaSchema = exports_external.object({
|
|
25526
|
-
id: exports_external.string(),
|
|
25527
|
-
agent_slug: exports_external.string(),
|
|
25528
|
-
key_allow: exports_external.array(exports_external.string()),
|
|
25529
|
-
write_allow: exports_external.array(exports_external.string()).default([]),
|
|
25530
|
-
expires_at: exports_external.number().nullable(),
|
|
25531
|
-
created_at: exports_external.number(),
|
|
25532
|
-
description: exports_external.string().nullable()
|
|
25533
|
-
});
|
|
25534
|
-
OkListGrantsResponseSchema = exports_external.object({
|
|
25535
|
-
ok: exports_external.literal(true),
|
|
25536
|
-
grants: exports_external.array(GrantMetaSchema)
|
|
25537
|
-
});
|
|
25538
|
-
OkRevokeGrantResponseSchema = exports_external.object({
|
|
25539
|
-
ok: exports_external.literal(true),
|
|
25540
|
-
revoked: exports_external.boolean()
|
|
25541
|
-
});
|
|
25542
|
-
OkApprovalRequestResponseSchema = exports_external.discriminatedUnion("state", [
|
|
25543
|
-
exports_external.object({
|
|
25544
|
-
ok: exports_external.literal(true),
|
|
25545
|
-
kind: exports_external.literal("approval_request"),
|
|
25546
|
-
state: exports_external.literal("pending"),
|
|
25547
|
-
request_id: exports_external.string(),
|
|
25548
|
-
expires_at: exports_external.number()
|
|
25549
|
-
}),
|
|
25550
|
-
exports_external.object({
|
|
25551
|
-
ok: exports_external.literal(true),
|
|
25552
|
-
kind: exports_external.literal("approval_request"),
|
|
25553
|
-
state: exports_external.literal("rate_limited"),
|
|
25554
|
-
retry_after_ms: exports_external.number()
|
|
25555
|
-
})
|
|
25556
|
-
]);
|
|
25557
|
-
ApprovalDecisionMetaSchema = exports_external.object({
|
|
25558
|
-
id: exports_external.string(),
|
|
25559
|
-
agent_unit: exports_external.string(),
|
|
25560
|
-
scope: exports_external.string(),
|
|
25561
|
-
action: exports_external.string(),
|
|
25562
|
-
decision: ApprovalDecisionModeSchema,
|
|
25563
|
-
granted_at: exports_external.number(),
|
|
25564
|
-
granted_by_user_id: exports_external.number(),
|
|
25565
|
-
ttl_expires_at: exports_external.number().nullable(),
|
|
25566
|
-
last_used_at: exports_external.number().nullable(),
|
|
25567
|
-
revoked_at: exports_external.number().nullable(),
|
|
25568
|
-
revoke_reason: exports_external.string().nullable()
|
|
25569
|
-
});
|
|
25570
|
-
OkApprovalLookupResponseSchema = exports_external.object({
|
|
25571
|
-
ok: exports_external.literal(true),
|
|
25572
|
-
state: exports_external.enum(["granted", "denied", "pending", "expired", "drift_revoked", "no_decision"]),
|
|
25573
|
-
decision: ApprovalDecisionMetaSchema.nullable().optional()
|
|
25574
|
-
});
|
|
25575
|
-
OkApprovalConsumeResponseSchema = exports_external.object({
|
|
25576
|
-
ok: exports_external.literal(true),
|
|
25577
|
-
consumed: exports_external.boolean(),
|
|
25578
|
-
agent_unit: exports_external.string().optional(),
|
|
25579
|
-
scope: exports_external.string().optional(),
|
|
25580
|
-
action: exports_external.string().optional(),
|
|
25581
|
-
why: exports_external.string().nullable().optional()
|
|
25582
|
-
});
|
|
25583
|
-
OkApprovalRevokeResponseSchema = exports_external.object({
|
|
25584
|
-
ok: exports_external.literal(true),
|
|
25585
|
-
revoked: exports_external.boolean()
|
|
25586
|
-
});
|
|
25587
|
-
OkApprovalListResponseSchema = exports_external.object({
|
|
25588
|
-
ok: exports_external.literal(true),
|
|
25589
|
-
decisions: exports_external.array(ApprovalDecisionMetaSchema)
|
|
25590
|
-
});
|
|
25591
|
-
OkApprovalRecordResponseSchema = exports_external.object({
|
|
25592
|
-
ok: exports_external.literal(true),
|
|
25593
|
-
decision_id: exports_external.string()
|
|
25594
|
-
});
|
|
25595
|
-
OkApprovalConsumeRecordResponseSchema = exports_external.object({
|
|
25596
|
-
ok: exports_external.literal(true),
|
|
25597
|
-
consumed: exports_external.boolean(),
|
|
25598
|
-
decision_id: exports_external.string().optional(),
|
|
25599
|
-
agent_unit: exports_external.string().optional(),
|
|
25600
|
-
scope: exports_external.string().optional(),
|
|
25601
|
-
action: exports_external.string().optional(),
|
|
25602
|
-
why: exports_external.string().nullable().optional()
|
|
25603
|
-
});
|
|
25604
|
-
ErrorResponseSchema2 = exports_external.object({
|
|
25605
|
-
ok: exports_external.literal(false),
|
|
25606
|
-
code: ErrorCode,
|
|
25607
|
-
msg: exports_external.string()
|
|
25608
|
-
});
|
|
25609
|
-
ResponseSchema2 = exports_external.union([
|
|
25610
|
-
OkEntryResponseSchema,
|
|
25611
|
-
OkKeysResponseSchema,
|
|
25612
|
-
OkStatusResponseSchema,
|
|
25613
|
-
OkLockResponseSchema,
|
|
25614
|
-
OkPreflightAccessResponseSchema,
|
|
25615
|
-
OkPutResponseSchema,
|
|
25616
|
-
OkMintGrantResponseSchema,
|
|
25617
|
-
OkListGrantsResponseSchema,
|
|
25618
|
-
OkRevokeGrantResponseSchema,
|
|
25619
|
-
OkApprovalRequestResponseSchema,
|
|
25620
|
-
OkApprovalLookupResponseSchema,
|
|
25621
|
-
OkApprovalConsumeResponseSchema,
|
|
25622
|
-
OkApprovalRevokeResponseSchema,
|
|
25623
|
-
OkApprovalListResponseSchema,
|
|
25624
|
-
OkApprovalRecordResponseSchema,
|
|
25625
|
-
OkApprovalConsumeRecordResponseSchema,
|
|
25626
|
-
ErrorResponseSchema2
|
|
25627
|
-
]);
|
|
25628
|
-
});
|
|
25629
|
-
|
|
25630
|
-
// ../src/runtime-mode.ts
|
|
25631
|
-
function isDockerRuntime() {
|
|
25632
|
-
return process.env.SWITCHROOM_RUNTIME === "docker";
|
|
25633
|
-
}
|
|
25634
|
-
|
|
25635
|
-
// ../src/vault/broker/client.ts
|
|
25636
|
-
import * as net3 from "node:net";
|
|
25637
|
-
import * as fs from "node:fs";
|
|
25638
|
-
import { homedir as homedir7 } from "node:os";
|
|
25639
|
-
import { join as join15 } from "node:path";
|
|
25640
|
-
function defaultBrokerSocketPath() {
|
|
25641
|
-
if (fs.existsSync(OPERATOR_SOCKET_PATH))
|
|
25642
|
-
return OPERATOR_SOCKET_PATH;
|
|
25643
|
-
if (isDockerRuntime())
|
|
25644
|
-
return OPERATOR_SOCKET_PATH;
|
|
25645
|
-
return LEGACY_SOCKET_PATH;
|
|
25646
|
-
}
|
|
25647
|
-
function vaultTokenFilePath(agentSlug) {
|
|
25648
|
-
return join15(homedir7(), ".switchroom", "agents", agentSlug, ".vault-token");
|
|
25649
|
-
}
|
|
25650
|
-
function readVaultTokenFile(agentSlug) {
|
|
25651
|
-
const filePath = vaultTokenFilePath(agentSlug);
|
|
25652
|
-
try {
|
|
25653
|
-
const stat = fs.statSync(filePath);
|
|
25654
|
-
const mode = stat.mode & 511;
|
|
25655
|
-
if ((mode & 63) !== 0) {
|
|
25656
|
-
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.
|
|
25657
|
-
`);
|
|
25658
|
-
return null;
|
|
25224
|
+
off(type, listener) {
|
|
25225
|
+
const listenerSet = this.#listeners.get(type);
|
|
25226
|
+
if (!listenerSet) {
|
|
25227
|
+
return;
|
|
25659
25228
|
}
|
|
25660
|
-
const
|
|
25661
|
-
|
|
25662
|
-
|
|
25663
|
-
|
|
25664
|
-
} catch (err) {
|
|
25665
|
-
const code = err.code;
|
|
25666
|
-
if (code === "ENOENT") {
|
|
25667
|
-
return null;
|
|
25229
|
+
for (const listenerSetElement of listenerSet) {
|
|
25230
|
+
if (listenerSetElement === listener) {
|
|
25231
|
+
listenerSet.delete(listener);
|
|
25232
|
+
}
|
|
25668
25233
|
}
|
|
25669
|
-
|
|
25670
|
-
|
|
25671
|
-
|
|
25672
|
-
|
|
25673
|
-
|
|
25674
|
-
|
|
25675
|
-
|
|
25676
|
-
|
|
25677
|
-
return
|
|
25678
|
-
const env = process.env.SWITCHROOM_VAULT_BROKER_SOCK;
|
|
25679
|
-
if (env)
|
|
25680
|
-
return env;
|
|
25681
|
-
if (opts?.vaultBrokerSocket)
|
|
25682
|
-
return opts.vaultBrokerSocket;
|
|
25683
|
-
return defaultBrokerSocketPath();
|
|
25684
|
-
}
|
|
25685
|
-
async function rpcRaw(req, opts) {
|
|
25686
|
-
return rpc(req, opts);
|
|
25687
|
-
}
|
|
25688
|
-
async function rpc(req, opts) {
|
|
25689
|
-
const socketPath = resolveBrokerSocketPath(opts);
|
|
25690
|
-
const timeoutMs = opts?.timeoutMs ?? DEFAULT_TIMEOUT_MS3;
|
|
25691
|
-
return new Promise((resolve5) => {
|
|
25692
|
-
let settled = false;
|
|
25693
|
-
const settle = (val) => {
|
|
25694
|
-
if (settled)
|
|
25695
|
-
return;
|
|
25696
|
-
settled = true;
|
|
25697
|
-
resolve5(val);
|
|
25698
|
-
};
|
|
25699
|
-
const client3 = new net3.Socket;
|
|
25700
|
-
const timer3 = setTimeout(() => {
|
|
25701
|
-
client3.destroy();
|
|
25702
|
-
settle({ kind: "unreachable", msg: `broker did not respond within ${timeoutMs}ms` });
|
|
25703
|
-
}, timeoutMs);
|
|
25704
|
-
client3.on("error", (err) => {
|
|
25705
|
-
clearTimeout(timer3);
|
|
25706
|
-
const code = err.code ?? "ERR";
|
|
25707
|
-
let msg;
|
|
25708
|
-
if (code === "ENOENT")
|
|
25709
|
-
msg = "broker socket not found (is the daemon running?)";
|
|
25710
|
-
else if (code === "ECONNREFUSED")
|
|
25711
|
-
msg = "broker socket exists but refused connection";
|
|
25712
|
-
else if (code === "EACCES")
|
|
25713
|
-
msg = "broker socket access denied (wrong UID?)";
|
|
25714
|
-
else
|
|
25715
|
-
msg = `broker connection failed: ${err.message}`;
|
|
25716
|
-
settle({ kind: "unreachable", msg });
|
|
25717
|
-
});
|
|
25718
|
-
let buffer = "";
|
|
25719
|
-
client3.on("data", (chunk) => {
|
|
25720
|
-
buffer += chunk.toString("utf8");
|
|
25721
|
-
const newlineIdx = buffer.indexOf(`
|
|
25722
|
-
`);
|
|
25723
|
-
if (newlineIdx !== -1) {
|
|
25724
|
-
const line = buffer.slice(0, newlineIdx).trimEnd();
|
|
25725
|
-
clearTimeout(timer3);
|
|
25726
|
-
client3.destroy();
|
|
25727
|
-
try {
|
|
25728
|
-
const resp = decodeResponse2(line);
|
|
25729
|
-
settle({ kind: "response", resp });
|
|
25730
|
-
} catch (err) {
|
|
25731
|
-
settle({
|
|
25732
|
-
kind: "unreachable",
|
|
25733
|
-
msg: `unparseable broker response: ${err instanceof Error ? err.message : String(err)}`
|
|
25734
|
-
});
|
|
25735
|
-
}
|
|
25736
|
-
}
|
|
25737
|
-
});
|
|
25738
|
-
client3.on("connect", () => {
|
|
25739
|
-
try {
|
|
25740
|
-
client3.write(encodeRequest2(req));
|
|
25741
|
-
} catch (err) {
|
|
25742
|
-
clearTimeout(timer3);
|
|
25743
|
-
client3.destroy();
|
|
25744
|
-
settle({
|
|
25745
|
-
kind: "unreachable",
|
|
25746
|
-
msg: `failed to send request: ${err instanceof Error ? err.message : String(err)}`
|
|
25747
|
-
});
|
|
25748
|
-
}
|
|
25749
|
-
});
|
|
25750
|
-
client3.connect({ path: socketPath });
|
|
25751
|
-
});
|
|
25752
|
-
}
|
|
25753
|
-
async function getViaBrokerStructured(key, opts) {
|
|
25754
|
-
const token = opts?.token;
|
|
25755
|
-
const result = await rpc({ v: 1, op: "get", key, ...token ? { token } : {} }, opts);
|
|
25756
|
-
if (result.kind === "unreachable") {
|
|
25757
|
-
return { kind: "unreachable", msg: result.msg };
|
|
25758
|
-
}
|
|
25759
|
-
const resp = result.resp;
|
|
25760
|
-
if (resp.ok && "entry" in resp) {
|
|
25761
|
-
return { kind: "ok", entry: resp.entry };
|
|
25762
|
-
}
|
|
25763
|
-
if (!resp.ok) {
|
|
25764
|
-
if (resp.code === "UNKNOWN_KEY") {
|
|
25765
|
-
return { kind: "not_found", code: resp.code, msg: resp.msg };
|
|
25766
|
-
}
|
|
25767
|
-
return { kind: "denied", code: resp.code, msg: resp.msg };
|
|
25768
|
-
}
|
|
25769
|
-
return { kind: "unreachable", msg: "unexpected broker response shape" };
|
|
25770
|
-
}
|
|
25771
|
-
async function putViaBroker(key, entry, opts) {
|
|
25772
|
-
const token = opts?.token;
|
|
25773
|
-
const passphrase = opts?.passphrase;
|
|
25774
|
-
const attestViaPosture = opts?.attest_via_posture === true;
|
|
25775
|
-
const result = await rpc({
|
|
25776
|
-
v: 1,
|
|
25777
|
-
op: "put",
|
|
25778
|
-
key,
|
|
25779
|
-
entry,
|
|
25780
|
-
...token ? { token } : {},
|
|
25781
|
-
...passphrase ? { passphrase } : {},
|
|
25782
|
-
...attestViaPosture ? { attest_via_posture: true } : {}
|
|
25783
|
-
}, opts);
|
|
25784
|
-
if (result.kind === "unreachable") {
|
|
25785
|
-
return { kind: "unreachable", msg: result.msg };
|
|
25786
|
-
}
|
|
25787
|
-
const resp = result.resp;
|
|
25788
|
-
if (resp.ok && "put" in resp) {
|
|
25789
|
-
return { kind: "ok" };
|
|
25790
|
-
}
|
|
25791
|
-
if (!resp.ok) {
|
|
25792
|
-
if (resp.code === "UNKNOWN_KEY") {
|
|
25793
|
-
return { kind: "not_found", code: resp.code, msg: resp.msg };
|
|
25794
|
-
}
|
|
25795
|
-
return { kind: "denied", code: resp.code, msg: resp.msg };
|
|
25796
|
-
}
|
|
25797
|
-
return { kind: "unreachable", msg: "unexpected broker response shape" };
|
|
25798
|
-
}
|
|
25799
|
-
var DEFAULT_TIMEOUT_MS3 = 2000, LEGACY_SOCKET_PATH, OPERATOR_SOCKET_PATH;
|
|
25800
|
-
var init_client2 = __esm(() => {
|
|
25801
|
-
init_protocol2();
|
|
25802
|
-
init_peercred();
|
|
25803
|
-
LEGACY_SOCKET_PATH = join15(homedir7(), ".switchroom", "vault-broker.sock");
|
|
25804
|
-
OPERATOR_SOCKET_PATH = join15(homedir7(), ".switchroom", "broker-operator", "sock");
|
|
25805
|
-
});
|
|
25806
|
-
|
|
25807
|
-
// ../src/drive/deep-links.ts
|
|
25808
|
-
function classifyMimeType(mimeType) {
|
|
25809
|
-
if (!mimeType)
|
|
25810
|
-
return "file";
|
|
25811
|
-
switch (mimeType) {
|
|
25812
|
-
case "application/vnd.google-apps.document":
|
|
25813
|
-
return "doc";
|
|
25814
|
-
case "application/vnd.google-apps.spreadsheet":
|
|
25815
|
-
return "spreadsheet";
|
|
25816
|
-
case "application/vnd.google-apps.presentation":
|
|
25817
|
-
return "presentation";
|
|
25818
|
-
case "application/vnd.google-apps.form":
|
|
25819
|
-
return "form";
|
|
25820
|
-
case "application/vnd.google-apps.drawing":
|
|
25821
|
-
return "drawing";
|
|
25822
|
-
case "application/vnd.google-apps.folder":
|
|
25823
|
-
return "folder";
|
|
25824
|
-
default:
|
|
25825
|
-
return "file";
|
|
25826
|
-
}
|
|
25827
|
-
}
|
|
25828
|
-
function openInDriveUrl(options) {
|
|
25829
|
-
validateDriveId2(options.fileId, "fileId");
|
|
25830
|
-
if (options.discussionId !== undefined) {
|
|
25831
|
-
validateDriveId2(options.discussionId, "discussionId");
|
|
25832
|
-
}
|
|
25833
|
-
const kind = options.isFolder ? "folder" : classifyMimeType(options.mimeType);
|
|
25834
|
-
const base = baseUrlFor(kind, options.fileId);
|
|
25835
|
-
if (options.discussionId !== undefined) {
|
|
25836
|
-
return `${base}?disco=${encodeURIComponent(options.discussionId)}`;
|
|
25837
|
-
}
|
|
25838
|
-
return base;
|
|
25839
|
-
}
|
|
25840
|
-
function baseUrlFor(kind, fileId) {
|
|
25841
|
-
switch (kind) {
|
|
25842
|
-
case "doc":
|
|
25843
|
-
return `https://docs.google.com/document/d/${fileId}/edit`;
|
|
25844
|
-
case "spreadsheet":
|
|
25845
|
-
return `https://docs.google.com/spreadsheets/d/${fileId}/edit`;
|
|
25846
|
-
case "presentation":
|
|
25847
|
-
return `https://docs.google.com/presentation/d/${fileId}/edit`;
|
|
25848
|
-
case "form":
|
|
25849
|
-
return `https://docs.google.com/forms/d/${fileId}/edit`;
|
|
25850
|
-
case "drawing":
|
|
25851
|
-
return `https://docs.google.com/drawings/d/${fileId}/edit`;
|
|
25852
|
-
case "folder":
|
|
25853
|
-
return `https://drive.google.com/drive/folders/${fileId}`;
|
|
25854
|
-
case "file":
|
|
25855
|
-
return `https://drive.google.com/file/d/${fileId}/view`;
|
|
25856
|
-
}
|
|
25857
|
-
}
|
|
25858
|
-
function validateDriveId2(id, fieldName) {
|
|
25859
|
-
if (id.length === 0) {
|
|
25860
|
-
throw new Error(`Drive ${fieldName} must not be empty`);
|
|
25861
|
-
}
|
|
25862
|
-
if (!/^[A-Za-z0-9_-]+$/.test(id)) {
|
|
25863
|
-
throw new Error(`Drive ${fieldName} '${id.slice(0, 30)}${id.length > 30 ? "\u2026" : ""}' contains invalid characters. Expected base64-url-safe (alphanumerics + - + _).`);
|
|
25864
|
-
}
|
|
25865
|
-
}
|
|
25866
|
-
function openInDriveButton(options) {
|
|
25867
|
-
return {
|
|
25868
|
-
text: "\uD83D\uDCD6 Open in Drive",
|
|
25869
|
-
url: openInDriveUrl(options)
|
|
25870
|
-
};
|
|
25871
|
-
}
|
|
25872
|
-
function scopeToOpenInDriveButton(scope, mimeTypeHint) {
|
|
25873
|
-
const parsed = parseDriveScope(scope);
|
|
25874
|
-
if (parsed === null)
|
|
25875
|
-
return null;
|
|
25876
|
-
if (parsed.target.kind === "all")
|
|
25877
|
-
return null;
|
|
25878
|
-
if (parsed.target.kind === "folder") {
|
|
25879
|
-
return openInDriveButton({ fileId: parsed.target.folder_id, isFolder: true });
|
|
25880
|
-
}
|
|
25881
|
-
return openInDriveButton({
|
|
25882
|
-
fileId: parsed.target.doc_id,
|
|
25883
|
-
mimeType: mimeTypeHint
|
|
25884
|
-
});
|
|
25885
|
-
}
|
|
25886
|
-
function parseDriveScope(scope) {
|
|
25887
|
-
if (!scope.startsWith("doc:gdrive:"))
|
|
25888
|
-
return null;
|
|
25889
|
-
let rest = scope.slice("doc:gdrive:".length);
|
|
25890
|
-
let action = "read";
|
|
25891
|
-
if (rest.startsWith("write:")) {
|
|
25892
|
-
action = "write";
|
|
25893
|
-
rest = rest.slice("write:".length);
|
|
25894
|
-
} else if (rest.startsWith("suggest:")) {
|
|
25895
|
-
action = "suggest";
|
|
25896
|
-
rest = rest.slice("suggest:".length);
|
|
25897
|
-
}
|
|
25898
|
-
if (rest === "**")
|
|
25899
|
-
return { action, target: { kind: "all" } };
|
|
25900
|
-
if (rest.startsWith("folder/")) {
|
|
25901
|
-
const tail = rest.slice("folder/".length);
|
|
25902
|
-
if (!tail.endsWith("/**"))
|
|
25903
|
-
return null;
|
|
25904
|
-
const folder_id = tail.slice(0, -"/**".length);
|
|
25905
|
-
if (!/^[A-Za-z0-9_-]+$/.test(folder_id))
|
|
25906
|
-
return null;
|
|
25907
|
-
return { action, target: { kind: "folder", folder_id } };
|
|
25908
|
-
}
|
|
25909
|
-
if (!/^[A-Za-z0-9_-]+$/.test(rest))
|
|
25910
|
-
return null;
|
|
25911
|
-
return { action, target: { kind: "doc", doc_id: rest } };
|
|
25912
|
-
}
|
|
25913
|
-
|
|
25914
|
-
// gateway/oversize-card-body.ts
|
|
25915
|
-
function truncateRawToFit(input) {
|
|
25916
|
-
const { raw, render, cap, sentinel } = input;
|
|
25917
|
-
const hardLimit = input.hardLimit ?? cap + 196;
|
|
25918
|
-
const fullBody = render(raw);
|
|
25919
|
-
if (fullBody.length <= cap) {
|
|
25920
|
-
return { body: fullBody, truncated: false };
|
|
25921
|
-
}
|
|
25922
|
-
let lo = 0;
|
|
25923
|
-
let hi = raw.length;
|
|
25924
|
-
let bestSliceLen = 0;
|
|
25925
|
-
while (lo <= hi) {
|
|
25926
|
-
const mid = lo + hi >>> 1;
|
|
25927
|
-
const candidate = raw.slice(0, mid) + sentinel;
|
|
25928
|
-
if (render(candidate).length <= cap) {
|
|
25929
|
-
bestSliceLen = mid;
|
|
25930
|
-
lo = mid + 1;
|
|
25931
|
-
} else {
|
|
25932
|
-
hi = mid - 1;
|
|
25933
|
-
}
|
|
25934
|
-
}
|
|
25935
|
-
let chosenRaw = raw.slice(0, bestSliceLen);
|
|
25936
|
-
const lastNl = chosenRaw.lastIndexOf(`
|
|
25937
|
-
`);
|
|
25938
|
-
if (lastNl > 0)
|
|
25939
|
-
chosenRaw = chosenRaw.slice(0, lastNl);
|
|
25940
|
-
let body = render(chosenRaw + sentinel);
|
|
25941
|
-
if (body.length > hardLimit) {
|
|
25942
|
-
body = body.slice(0, hardLimit - 1);
|
|
25943
|
-
}
|
|
25944
|
-
return { body, truncated: true };
|
|
25945
|
-
}
|
|
25946
|
-
|
|
25947
|
-
// secret-detect/suppressor.ts
|
|
25948
|
-
function isSuppressed(text, start, end) {
|
|
25949
|
-
const left = Math.max(0, start - WINDOW);
|
|
25950
|
-
const right = Math.min(text.length, end + WINDOW);
|
|
25951
|
-
const context = text.slice(left, start) + text.slice(end, right);
|
|
25952
|
-
return MARKER_RE.test(context);
|
|
25953
|
-
}
|
|
25954
|
-
var MARKERS, WINDOW = 40, MARKER_RE;
|
|
25955
|
-
var init_suppressor = __esm(() => {
|
|
25956
|
-
MARKERS = ["test", "mock", "example", "fixture", "dummy"];
|
|
25957
|
-
MARKER_RE = new RegExp(`\\b(?:${MARKERS.join("|")})\\b`, "i");
|
|
25958
|
-
});
|
|
25959
|
-
|
|
25960
|
-
// secret-detect/slug.ts
|
|
25961
|
-
function sanitizeKeyName(raw) {
|
|
25962
|
-
const up = raw.toUpperCase();
|
|
25963
|
-
const cleaned = up.replace(/[^A-Z0-9_]+/g, "_").replace(/_+/g, "_").replace(/^_+|_+$/g, "");
|
|
25964
|
-
return cleaned.length > 0 ? cleaned : "SECRET";
|
|
25965
|
-
}
|
|
25966
|
-
function datePart(now = new Date) {
|
|
25967
|
-
const y = now.getUTCFullYear();
|
|
25968
|
-
const m = String(now.getUTCMonth() + 1).padStart(2, "0");
|
|
25969
|
-
const d = String(now.getUTCDate()).padStart(2, "0");
|
|
25970
|
-
return `${y}${m}${d}`;
|
|
25971
|
-
}
|
|
25972
|
-
function deriveSlug(inputs, existing) {
|
|
25973
|
-
let base;
|
|
25974
|
-
if (inputs.key_name && inputs.key_name.trim().length > 0) {
|
|
25975
|
-
base = sanitizeKeyName(inputs.key_name);
|
|
25976
|
-
} else {
|
|
25977
|
-
base = `${inputs.rule_id}_${datePart(inputs.now)}`;
|
|
25978
|
-
}
|
|
25979
|
-
if (!existing.has(base))
|
|
25980
|
-
return base;
|
|
25981
|
-
let n = 2;
|
|
25982
|
-
while (existing.has(`${base}_${n}`))
|
|
25983
|
-
n++;
|
|
25984
|
-
return `${base}_${n}`;
|
|
25985
|
-
}
|
|
25986
|
-
|
|
25987
|
-
// ../node_modules/.bun/boundary@2.0.0/node_modules/boundary/lib/index.js
|
|
25988
|
-
var require_lib = __commonJS((exports2) => {
|
|
25989
|
-
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
25990
|
-
exports2.binarySearch = exports2.upperBound = exports2.lowerBound = exports2.compare = undefined;
|
|
25991
|
-
function compare(v1, v2) {
|
|
25992
|
-
return v1 < v2;
|
|
25993
|
-
}
|
|
25994
|
-
exports2.compare = compare;
|
|
25995
|
-
function upperBound(array, value, comp = compare) {
|
|
25996
|
-
let len = array.length;
|
|
25997
|
-
let i = 0;
|
|
25998
|
-
while (len) {
|
|
25999
|
-
let diff = len >>> 1;
|
|
26000
|
-
let cursor = i + diff;
|
|
26001
|
-
if (comp(value, array[cursor])) {
|
|
26002
|
-
len = diff;
|
|
26003
|
-
} else {
|
|
26004
|
-
i = cursor + 1;
|
|
26005
|
-
len -= diff + 1;
|
|
26006
|
-
}
|
|
26007
|
-
}
|
|
26008
|
-
return i;
|
|
26009
|
-
}
|
|
26010
|
-
exports2.upperBound = upperBound;
|
|
26011
|
-
function lowerBound(array, value, comp = compare) {
|
|
26012
|
-
let len = array.length;
|
|
26013
|
-
let i = 0;
|
|
26014
|
-
while (len) {
|
|
26015
|
-
let diff = len >>> 1;
|
|
26016
|
-
let cursor = i + diff;
|
|
26017
|
-
if (comp(array[cursor], value)) {
|
|
26018
|
-
i = cursor + 1;
|
|
26019
|
-
len -= diff + 1;
|
|
26020
|
-
} else {
|
|
26021
|
-
len = diff;
|
|
26022
|
-
}
|
|
26023
|
-
}
|
|
26024
|
-
return i;
|
|
26025
|
-
}
|
|
26026
|
-
exports2.lowerBound = lowerBound;
|
|
26027
|
-
function binarySearch(array, value, comp = compare) {
|
|
26028
|
-
let cursor = lowerBound(array, value, comp);
|
|
26029
|
-
return cursor !== array.length && !comp(value, array[cursor]);
|
|
26030
|
-
}
|
|
26031
|
-
exports2.binarySearch = binarySearch;
|
|
26032
|
-
});
|
|
26033
|
-
|
|
26034
|
-
// ../node_modules/.bun/structured-source@4.0.0/node_modules/structured-source/lib/structured-source.js
|
|
26035
|
-
var require_structured_source = __commonJS((exports2) => {
|
|
26036
|
-
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
26037
|
-
exports2.StructuredSource = undefined;
|
|
26038
|
-
var boundary_1 = require_lib();
|
|
26039
|
-
|
|
26040
|
-
class StructuredSource {
|
|
26041
|
-
constructor(source) {
|
|
26042
|
-
this.indice = [0];
|
|
26043
|
-
let regexp = /[\r\n\u2028\u2029]/g;
|
|
26044
|
-
const length = source.length;
|
|
26045
|
-
regexp.lastIndex = 0;
|
|
26046
|
-
while (true) {
|
|
26047
|
-
let result = regexp.exec(source);
|
|
26048
|
-
if (!result) {
|
|
26049
|
-
break;
|
|
26050
|
-
}
|
|
26051
|
-
let index = result.index;
|
|
26052
|
-
if (source.charCodeAt(index) === 13 && source.charCodeAt(index + 1) === 10) {
|
|
26053
|
-
index += 1;
|
|
26054
|
-
}
|
|
26055
|
-
let nextIndex = index + 1;
|
|
26056
|
-
if (length < nextIndex) {
|
|
26057
|
-
break;
|
|
26058
|
-
}
|
|
26059
|
-
this.indice.push(nextIndex);
|
|
26060
|
-
regexp.lastIndex = nextIndex;
|
|
26061
|
-
}
|
|
26062
|
-
}
|
|
26063
|
-
get line() {
|
|
26064
|
-
return this.indice.length;
|
|
26065
|
-
}
|
|
26066
|
-
locationToRange(loc) {
|
|
26067
|
-
return [this.positionToIndex(loc.start), this.positionToIndex(loc.end)];
|
|
26068
|
-
}
|
|
26069
|
-
rangeToLocation(range) {
|
|
26070
|
-
return {
|
|
26071
|
-
start: this.indexToPosition(range[0]),
|
|
26072
|
-
end: this.indexToPosition(range[1])
|
|
26073
|
-
};
|
|
26074
|
-
}
|
|
26075
|
-
positionToIndex(pos) {
|
|
26076
|
-
let start = this.indice[pos.line - 1];
|
|
26077
|
-
return start + pos.column;
|
|
26078
|
-
}
|
|
26079
|
-
indexToPosition(index) {
|
|
26080
|
-
const startLine = (0, boundary_1.upperBound)(this.indice, index);
|
|
26081
|
-
return {
|
|
26082
|
-
line: startLine,
|
|
26083
|
-
column: index - this.indice[startLine - 1]
|
|
26084
|
-
};
|
|
26085
|
-
}
|
|
26086
|
-
}
|
|
26087
|
-
exports2.StructuredSource = StructuredSource;
|
|
26088
|
-
});
|
|
26089
|
-
// ../node_modules/.bun/@secretlint+core@12.2.0/node_modules/@secretlint/core/module/SecretLintSourceCodeImpl.js
|
|
26090
|
-
var import_structured_source;
|
|
26091
|
-
var init_SecretLintSourceCodeImpl = __esm(() => {
|
|
26092
|
-
import_structured_source = __toESM(require_structured_source(), 1);
|
|
26093
|
-
});
|
|
26094
|
-
|
|
26095
|
-
// ../node_modules/.bun/@secretlint+core@12.2.0/node_modules/@secretlint/core/module/helper/promise-event-emitter.js
|
|
26096
|
-
class EventEmitter {
|
|
26097
|
-
#listeners = new Map;
|
|
26098
|
-
on(type, listener) {
|
|
26099
|
-
const prevSet = this.#listeners.get(type);
|
|
26100
|
-
const listenerSet = prevSet ?? new Set;
|
|
26101
|
-
listenerSet?.add(listener);
|
|
26102
|
-
this.#listeners.set(type, listenerSet);
|
|
26103
|
-
}
|
|
26104
|
-
emit(type, ...args) {
|
|
26105
|
-
const listenerSet = this.#listeners.get(type);
|
|
26106
|
-
if (!listenerSet) {
|
|
26107
|
-
return;
|
|
26108
|
-
}
|
|
26109
|
-
for (const listenerSetElement of listenerSet) {
|
|
26110
|
-
listenerSetElement(...args);
|
|
26111
|
-
}
|
|
26112
|
-
}
|
|
26113
|
-
off(type, listener) {
|
|
26114
|
-
const listenerSet = this.#listeners.get(type);
|
|
26115
|
-
if (!listenerSet) {
|
|
26116
|
-
return;
|
|
26117
|
-
}
|
|
26118
|
-
for (const listenerSetElement of listenerSet) {
|
|
26119
|
-
if (listenerSetElement === listener) {
|
|
26120
|
-
listenerSet.delete(listener);
|
|
26121
|
-
}
|
|
26122
|
-
}
|
|
26123
|
-
}
|
|
26124
|
-
removeAllListeners() {
|
|
26125
|
-
this.#listeners.clear();
|
|
26126
|
-
}
|
|
26127
|
-
listenerCount(type) {
|
|
26128
|
-
return this.#listeners.get(type)?.size ?? 0;
|
|
26129
|
-
}
|
|
26130
|
-
listeners(type) {
|
|
26131
|
-
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) ?? []);
|
|
26132
25243
|
}
|
|
26133
25244
|
}
|
|
26134
25245
|
// ../node_modules/.bun/@secretlint+core@12.2.0/node_modules/@secretlint/core/module/RuleContext.js
|
|
@@ -27665,253 +26776,1464 @@ function requireLodash_sortby() {
|
|
|
27665
26776
|
return object[key] === srcValue && (srcValue !== undefined || (key in Object(object)));
|
|
27666
26777
|
};
|
|
27667
26778
|
}
|
|
27668
|
-
var stringToPath = memoize(function(string) {
|
|
27669
|
-
string = toString(string);
|
|
27670
|
-
var result = [];
|
|
27671
|
-
if (reLeadingDot.test(string)) {
|
|
27672
|
-
result.push("");
|
|
27673
|
-
}
|
|
27674
|
-
string.replace(rePropName, function(match, number, quote, string2) {
|
|
27675
|
-
result.push(quote ? string2.replace(reEscapeChar, "$1") : number || match);
|
|
27676
|
-
});
|
|
27677
|
-
return result;
|
|
27678
|
-
});
|
|
27679
|
-
function toKey(value) {
|
|
27680
|
-
if (typeof value == "string" || isSymbol(value)) {
|
|
27681
|
-
return value;
|
|
27682
|
-
}
|
|
27683
|
-
var result = value + "";
|
|
27684
|
-
return result == "0" && 1 / value == -Infinity ? "-0" : 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;
|
|
27685
27959
|
}
|
|
27686
|
-
|
|
27687
|
-
|
|
27688
|
-
|
|
27689
|
-
|
|
27690
|
-
|
|
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 });
|
|
28008
|
+
});
|
|
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();
|
|
27691
28018
|
try {
|
|
27692
|
-
|
|
27693
|
-
|
|
27694
|
-
|
|
27695
|
-
|
|
27696
|
-
|
|
27697
|
-
|
|
27698
|
-
|
|
27699
|
-
|
|
27700
|
-
}
|
|
27701
|
-
var length = iteratees.length;
|
|
27702
|
-
if (length > 1 && isIterateeCall(collection, iteratees[0], iteratees[1])) {
|
|
27703
|
-
iteratees = [];
|
|
27704
|
-
} else if (length > 2 && isIterateeCall(iteratees[0], iteratees[1], iteratees[2])) {
|
|
27705
|
-
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
|
+
}
|
|
27706
28027
|
}
|
|
27707
|
-
return baseOrderBy(collection, baseFlatten(iteratees), []);
|
|
27708
28028
|
});
|
|
27709
|
-
|
|
27710
|
-
|
|
27711
|
-
|
|
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
|
+
});
|
|
27712
28039
|
}
|
|
27713
|
-
|
|
27714
|
-
|
|
27715
|
-
|
|
27716
|
-
return cache.get(key);
|
|
27717
|
-
}
|
|
27718
|
-
var result = func.apply(this, args);
|
|
27719
|
-
memoized.cache = cache.set(key, result);
|
|
27720
|
-
return result;
|
|
27721
|
-
};
|
|
27722
|
-
memoized.cache = new (memoize.Cache || MapCache);
|
|
27723
|
-
return memoized;
|
|
27724
|
-
}
|
|
27725
|
-
memoize.Cache = MapCache;
|
|
27726
|
-
function eq(value, other) {
|
|
27727
|
-
return value === other || value !== value && other !== other;
|
|
27728
|
-
}
|
|
27729
|
-
function isArguments(value) {
|
|
27730
|
-
return isArrayLikeObject(value) && hasOwnProperty.call(value, "callee") && (!propertyIsEnumerable.call(value, "callee") || objectToString.call(value) == argsTag);
|
|
27731
|
-
}
|
|
27732
|
-
var isArray2 = Array.isArray;
|
|
27733
|
-
function isArrayLike(value) {
|
|
27734
|
-
return value != null && isLength(value.length) && !isFunction2(value);
|
|
27735
|
-
}
|
|
27736
|
-
function isArrayLikeObject(value) {
|
|
27737
|
-
return isObjectLike(value) && isArrayLike(value);
|
|
27738
|
-
}
|
|
27739
|
-
function isFunction2(value) {
|
|
27740
|
-
var tag = isObject2(value) ? objectToString.call(value) : "";
|
|
27741
|
-
return tag == funcTag || tag == genTag;
|
|
27742
|
-
}
|
|
27743
|
-
function isLength(value) {
|
|
27744
|
-
return typeof value == "number" && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
|
|
27745
|
-
}
|
|
27746
|
-
function isObject2(value) {
|
|
27747
|
-
var type = typeof value;
|
|
27748
|
-
return !!value && (type == "object" || type == "function");
|
|
27749
|
-
}
|
|
27750
|
-
function isObjectLike(value) {
|
|
27751
|
-
return !!value && typeof value == "object";
|
|
27752
|
-
}
|
|
27753
|
-
function isSymbol(value) {
|
|
27754
|
-
return typeof value == "symbol" || isObjectLike(value) && objectToString.call(value) == symbolTag;
|
|
27755
|
-
}
|
|
27756
|
-
var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray;
|
|
27757
|
-
function toString(value) {
|
|
27758
|
-
return value == null ? "" : baseToString(value);
|
|
27759
|
-
}
|
|
27760
|
-
function get(object, path, defaultValue) {
|
|
27761
|
-
var result = object == null ? undefined : baseGet(object, path);
|
|
27762
|
-
return result === undefined ? defaultValue : result;
|
|
27763
|
-
}
|
|
27764
|
-
function hasIn(object, path) {
|
|
27765
|
-
return object != null && hasPath(object, path, baseHasIn);
|
|
27766
|
-
}
|
|
27767
|
-
function keys(object) {
|
|
27768
|
-
return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object);
|
|
27769
|
-
}
|
|
27770
|
-
function identity2(value) {
|
|
27771
|
-
return value;
|
|
27772
|
-
}
|
|
27773
|
-
function property(path) {
|
|
27774
|
-
return isKey(path) ? baseProperty(toKey(path)) : basePropertyDeep(path);
|
|
27775
|
-
}
|
|
27776
|
-
module.exports = sortBy;
|
|
27777
|
-
})(lodash_sortby, lodash_sortby.exports);
|
|
27778
|
-
return lodash_sortby.exports;
|
|
28040
|
+
});
|
|
28041
|
+
client3.connect({ path: socketPath });
|
|
28042
|
+
});
|
|
27779
28043
|
}
|
|
27780
|
-
function
|
|
27781
|
-
|
|
27782
|
-
|
|
27783
|
-
|
|
27784
|
-
|
|
27785
|
-
|
|
27786
|
-
|
|
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 };
|
|
27787
28057
|
}
|
|
27788
|
-
return
|
|
27789
|
-
}
|
|
27790
|
-
return
|
|
28058
|
+
return { kind: "denied", code: resp.code, msg: resp.msg };
|
|
28059
|
+
}
|
|
28060
|
+
return { kind: "unreachable", msg: "unexpected broker response shape" };
|
|
27791
28061
|
}
|
|
27792
|
-
function
|
|
27793
|
-
|
|
27794
|
-
|
|
27795
|
-
|
|
27796
|
-
|
|
27797
|
-
|
|
27798
|
-
|
|
27799
|
-
|
|
27800
|
-
|
|
27801
|
-
|
|
27802
|
-
|
|
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 };
|
|
27803
28085
|
}
|
|
27804
|
-
return {
|
|
27805
|
-
|
|
27806
|
-
|
|
27807
|
-
|
|
27808
|
-
|
|
27809
|
-
|
|
27810
|
-
|
|
27811
|
-
|
|
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)
|
|
27812
28161
|
};
|
|
27813
|
-
regexpParse.isRegExpString = isRegExpString;
|
|
27814
|
-
return regexpParse;
|
|
27815
28162
|
}
|
|
27816
|
-
function
|
|
27817
|
-
|
|
27818
|
-
|
|
27819
|
-
|
|
27820
|
-
(
|
|
27821
|
-
|
|
27822
|
-
|
|
27823
|
-
};
|
|
27824
|
-
|
|
27825
|
-
|
|
27826
|
-
|
|
27827
|
-
|
|
27828
|
-
|
|
27829
|
-
|
|
27830
|
-
|
|
27831
|
-
|
|
27832
|
-
|
|
27833
|
-
|
|
27834
|
-
|
|
27835
|
-
|
|
27836
|
-
|
|
27837
|
-
|
|
27838
|
-
|
|
27839
|
-
|
|
27840
|
-
|
|
27841
|
-
|
|
27842
|
-
|
|
27843
|
-
|
|
27844
|
-
|
|
27845
|
-
|
|
27846
|
-
|
|
27847
|
-
|
|
27848
|
-
|
|
27849
|
-
|
|
27850
|
-
|
|
27851
|
-
|
|
27852
|
-
|
|
27853
|
-
|
|
27854
|
-
|
|
27855
|
-
|
|
27856
|
-
var isEqualMatchPatternResult = function(a, b) {
|
|
27857
|
-
return a.startIndex === b.startIndex && a.endIndex === b.endIndex && a.match === b.match;
|
|
27858
|
-
};
|
|
27859
|
-
var matchPatterns = function(text, regExpLikeStrings) {
|
|
27860
|
-
var matchPatternResults = [];
|
|
27861
|
-
regExpLikeStrings.map(function(patternString) {
|
|
27862
|
-
return (0, exports$1.createRegExp)(patternString);
|
|
27863
|
-
}).forEach(function(regExp) {
|
|
27864
|
-
var results = text.matchAll(regExp);
|
|
27865
|
-
Array.from(results).forEach(function(result) {
|
|
27866
|
-
if (result.index === undefined) {
|
|
27867
|
-
return;
|
|
27868
|
-
}
|
|
27869
|
-
var match = result[0];
|
|
27870
|
-
var index = result.index;
|
|
27871
|
-
matchPatternResults.push({
|
|
27872
|
-
match,
|
|
27873
|
-
captures: result.slice(1),
|
|
27874
|
-
startIndex: index,
|
|
27875
|
-
endIndex: index + match.length
|
|
27876
|
-
});
|
|
27877
|
-
});
|
|
27878
|
-
});
|
|
27879
|
-
var uniqResults = (0, lodash_uniqwith_1.default)(matchPatternResults, isEqualMatchPatternResult);
|
|
27880
|
-
return (0, lodash_sortby_1.default)(uniqResults, ["startIndex", "endIndex"]);
|
|
27881
|
-
};
|
|
27882
|
-
exports$1.matchPatterns = matchPatterns;
|
|
27883
|
-
})(regexpStringMatcher);
|
|
27884
|
-
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 } };
|
|
27885
28203
|
}
|
|
27886
|
-
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;
|
|
27887
|
-
var init_module2 = __esm(() => {
|
|
27888
|
-
commonjsGlobal = typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : {};
|
|
27889
|
-
regexpStringMatcher = {};
|
|
27890
|
-
lodash_sortby = { exports: {} };
|
|
27891
|
-
lodash_sortby.exports;
|
|
27892
|
-
regexpParse = {};
|
|
27893
|
-
regexpStringMatcherExports = requireRegexpStringMatcher();
|
|
27894
|
-
OID_DATA = new Uint8Array([42, 134, 72, 134, 247, 13, 1, 7, 1]);
|
|
27895
|
-
OID_SHA1 = new Uint8Array([43, 14, 3, 2, 26]);
|
|
27896
|
-
OID_SHA256 = new Uint8Array([96, 134, 72, 1, 101, 3, 4, 2, 1]);
|
|
27897
|
-
OID_SHA384 = new Uint8Array([96, 134, 72, 1, 101, 3, 4, 2, 2]);
|
|
27898
|
-
OID_SHA512 = new Uint8Array([96, 134, 72, 1, 101, 3, 4, 2, 3]);
|
|
27899
|
-
typeMap = new Map([
|
|
27900
|
-
["ghp", "GitHub personal access tokens"],
|
|
27901
|
-
["gho", "OAuth access tokens"],
|
|
27902
|
-
["ghu", "GitHub user-to-server tokens"],
|
|
27903
|
-
["ghs", "GitHub server-to-server tokens"],
|
|
27904
|
-
["ghr", "refresh tokens"],
|
|
27905
|
-
["github_pat", "fine-grained personal access tokens"]
|
|
27906
|
-
]);
|
|
27907
|
-
});
|
|
27908
28204
|
|
|
27909
|
-
//
|
|
27910
|
-
|
|
27911
|
-
|
|
27912
|
-
|
|
27913
|
-
|
|
27914
|
-
|
|
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
|
+
}
|
|
27915
28237
|
|
|
27916
28238
|
// gateway/auth-line.ts
|
|
27917
28239
|
function escapeHtml8(s) {
|
|
@@ -32025,7 +32347,7 @@ function renderWorkerActivity(v) {
|
|
|
32025
32347
|
const toolWord = v.toolCount === 1 ? "tool" : "tools";
|
|
32026
32348
|
const header = `\uD83D\uDEE0 <b>Worker</b> \u00b7 <i>${escapeHtml(desc)}</i>`;
|
|
32027
32349
|
const finished = v.state === "done" || v.state === "failed";
|
|
32028
|
-
const steps = (v.narrativeLines ?? []).map((s) => stripMarkdown(s)).filter((s) => s.length > 0).map((s) => escapeHtml(truncate(s, STEP_MAX)));
|
|
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)));
|
|
32029
32351
|
if (finished) {
|
|
32030
32352
|
const verb = v.state === "done" ? "completed" : "failed";
|
|
32031
32353
|
const lines2 = [header, `<i>finished \u00b7 ${verb} \u00b7 ${v.toolCount} ${toolWord} \u00b7 ${elapsed}</i>`];
|
|
@@ -32043,7 +32365,7 @@ function renderWorkerActivity(v) {
|
|
|
32043
32365
|
if (steps.length > 0) {
|
|
32044
32366
|
appendStepFeed(lines, steps, false);
|
|
32045
32367
|
} else {
|
|
32046
|
-
const summary = stripMarkdown(v.latestSummary);
|
|
32368
|
+
const summary = stripMarkdown(v.latestSummary).replace(/\s+/g, " ").trim();
|
|
32047
32369
|
if (summary.length > 0) {
|
|
32048
32370
|
lines.push(`<b>\u2192 ${escapeHtml(truncate(summary, STEP_MAX))}</b>`);
|
|
32049
32371
|
} else {
|
|
@@ -41633,7 +41955,7 @@ var INLINE_PH = `${NULL}VS_INLINE`;
|
|
|
41633
41955
|
var HTML_CODE_PH = `${NULL}VS_HTMLCODE`;
|
|
41634
41956
|
var HTML_PRE_PH = `${NULL}VS_HTMLPRE`;
|
|
41635
41957
|
var URL_PH = `${NULL}VS_URL`;
|
|
41636
|
-
var
|
|
41958
|
+
var URL_RE2 = /https?:\/\/\S+/g;
|
|
41637
41959
|
function enabled4() {
|
|
41638
41960
|
const v = process.env.SWITCHROOM_DISABLE_VOICE_SCRUB;
|
|
41639
41961
|
return !(v === "1" || v === "true");
|
|
@@ -41661,7 +41983,7 @@ function park(text) {
|
|
|
41661
41983
|
parts.push({ prefix: INLINE_PH, idx, raw: m });
|
|
41662
41984
|
return `${INLINE_PH}${idx}${NULL}`;
|
|
41663
41985
|
});
|
|
41664
|
-
parked = parked.replace(
|
|
41986
|
+
parked = parked.replace(URL_RE2, (m) => {
|
|
41665
41987
|
const idx = parts.length;
|
|
41666
41988
|
parts.push({ prefix: URL_PH, idx, raw: m });
|
|
41667
41989
|
return `${URL_PH}${idx}${NULL}`;
|
|
@@ -42412,10 +42734,10 @@ class PreambleSuppressor {
|
|
|
42412
42734
|
this.setTimer = deps.setTimer ?? ((fn, ms) => setTimeout(fn, ms));
|
|
42413
42735
|
this.clearTimer = deps.clearTimer ?? ((h) => clearTimeout(h));
|
|
42414
42736
|
}
|
|
42415
|
-
onText(
|
|
42416
|
-
if (
|
|
42737
|
+
onText(chunk2) {
|
|
42738
|
+
if (chunk2.length === 0)
|
|
42417
42739
|
return;
|
|
42418
|
-
this.pendingBuffer +=
|
|
42740
|
+
this.pendingBuffer += chunk2;
|
|
42419
42741
|
if (this.pendingTimer != null)
|
|
42420
42742
|
this.clearTimer(this.pendingTimer);
|
|
42421
42743
|
this.pendingTimer = this.setTimer(() => this.flushNow(), this.bufferMs);
|
|
@@ -44667,8 +44989,8 @@ async function hostdRequest(opts, req) {
|
|
|
44667
44989
|
reject(err);
|
|
44668
44990
|
}
|
|
44669
44991
|
});
|
|
44670
|
-
socket.on("data", (
|
|
44671
|
-
buf +=
|
|
44992
|
+
socket.on("data", (chunk2) => {
|
|
44993
|
+
buf += chunk2.toString("utf8");
|
|
44672
44994
|
if (Buffer.byteLength(buf, "utf8") > MAX_FRAME_BYTES3 * 2) {
|
|
44673
44995
|
if (settled)
|
|
44674
44996
|
return;
|
|
@@ -44910,10 +45232,10 @@ function startWebhookIngestServer(opts) {
|
|
|
44910
45232
|
} catch {}
|
|
44911
45233
|
conn.end();
|
|
44912
45234
|
};
|
|
44913
|
-
conn.on("data", (
|
|
45235
|
+
conn.on("data", (chunk2) => {
|
|
44914
45236
|
if (handled)
|
|
44915
45237
|
return;
|
|
44916
|
-
buf +=
|
|
45238
|
+
buf += chunk2;
|
|
44917
45239
|
if (buf.length > MAX_REQUEST_BYTES) {
|
|
44918
45240
|
reply({ status: "error", error: "request too large" });
|
|
44919
45241
|
return;
|
|
@@ -48121,253 +48443,8 @@ function resolveShutdownMarker(prior, signal, now, maxPreserveAgeMs = REASON_PRE
|
|
|
48121
48443
|
return { ts: now, signal, reason: EXTERNAL_RESTART_FALLBACK_REASON };
|
|
48122
48444
|
}
|
|
48123
48445
|
|
|
48124
|
-
// secret-detect/
|
|
48125
|
-
|
|
48126
|
-
{ rule_id: "anthropic_api_key", regex: /\b(sk-ant-[A-Za-z0-9_-]{8,})\b/g, captureIndex: 1, slugHint: "anthropic_api_key" },
|
|
48127
|
-
{ 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" },
|
|
48128
|
-
{ rule_id: "openai_api_key", regex: /\b(sk-[A-Za-z0-9_-]{20,})\b/g, captureIndex: 1, slugHint: "openai_api_key" },
|
|
48129
|
-
{ rule_id: "github_pat_classic", regex: /\b(ghp_[A-Za-z0-9]{20,})\b/g, captureIndex: 1, slugHint: "github_pat" },
|
|
48130
|
-
{ rule_id: "github_pat_fine_grained", regex: /\b(github_pat_[A-Za-z0-9_]{20,})\b/g, captureIndex: 1, slugHint: "github_pat" },
|
|
48131
|
-
{ rule_id: "slack_token", regex: /\b(xox[baprs]-[A-Za-z0-9-]{10,})\b/g, captureIndex: 1, slugHint: "slack_token" },
|
|
48132
|
-
{ rule_id: "slack_app_token", regex: /\b(xapp-[A-Za-z0-9-]{10,})\b/g, captureIndex: 1, slugHint: "slack_app_token" },
|
|
48133
|
-
{ rule_id: "groq_api_key", regex: /\b(gsk_[A-Za-z0-9_-]{10,})\b/g, captureIndex: 1, slugHint: "groq_api_key" },
|
|
48134
|
-
{ rule_id: "google_api_key", regex: /\b(AIza[0-9A-Za-z\-_]{20,})\b/g, captureIndex: 1, slugHint: "google_api_key" },
|
|
48135
|
-
{ rule_id: "perplexity_api_key", regex: /\b(pplx-[A-Za-z0-9_-]{10,})\b/g, captureIndex: 1, slugHint: "perplexity_api_key" },
|
|
48136
|
-
{ rule_id: "npm_token", regex: /\b(npm_[A-Za-z0-9]{10,})\b/g, captureIndex: 1, slugHint: "npm_token" },
|
|
48137
|
-
{ rule_id: "telegram_bot_token_prefixed", regex: /\bbot(\d{6,}:[A-Za-z0-9_-]{20,})\b/g, captureIndex: 1, slugHint: "telegram_bot_token" },
|
|
48138
|
-
{ rule_id: "telegram_bot_token", regex: /\b(\d{6,}:[A-Za-z0-9_-]{20,})\b/g, captureIndex: 1, slugHint: "telegram_bot_token" },
|
|
48139
|
-
{ rule_id: "aws_access_key", regex: /\b(AKIA[0-9A-Z]{16})\b/g, captureIndex: 1, slugHint: "aws_access_key" },
|
|
48140
|
-
{ 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" }
|
|
48141
|
-
];
|
|
48142
|
-
var STRUCTURED_PATTERNS = [
|
|
48143
|
-
{
|
|
48144
|
-
rule_id: "env_key_value",
|
|
48145
|
-
regex: /\b([A-Z0-9_]*(?:KEY|TOKEN|SECRET|PASSWORD|PASSWD))\b\s*[=:]\s*(["']?)([^\s"'\\]+)\2/g,
|
|
48146
|
-
captureIndex: 3,
|
|
48147
|
-
slugHint: "env"
|
|
48148
|
-
},
|
|
48149
|
-
{
|
|
48150
|
-
rule_id: "json_secret_field",
|
|
48151
|
-
regex: /"(?:apiKey|token|secret|password|passwd|accessToken|refreshToken)"\s*:\s*"([^"]+)"/g,
|
|
48152
|
-
captureIndex: 1,
|
|
48153
|
-
slugHint: "json_secret"
|
|
48154
|
-
},
|
|
48155
|
-
{
|
|
48156
|
-
rule_id: "cli_flag",
|
|
48157
|
-
regex: /--(?:api[-_]?key|hook[-_]?token|token|secret|password|passwd)\s+(["']?)([^\s"']+)\1/g,
|
|
48158
|
-
captureIndex: 2,
|
|
48159
|
-
slugHint: "cli_flag"
|
|
48160
|
-
},
|
|
48161
|
-
{
|
|
48162
|
-
rule_id: "bearer_auth_header",
|
|
48163
|
-
regex: /Authorization\s*[:=]\s*Bearer\s+([A-Za-z0-9._\-+=]+)/g,
|
|
48164
|
-
captureIndex: 1,
|
|
48165
|
-
slugHint: "bearer_token"
|
|
48166
|
-
},
|
|
48167
|
-
{
|
|
48168
|
-
rule_id: "bearer_loose",
|
|
48169
|
-
regex: /\bBearer\s+([A-Za-z0-9._\-+=]{18,})\b/g,
|
|
48170
|
-
captureIndex: 1,
|
|
48171
|
-
slugHint: "bearer_token"
|
|
48172
|
-
},
|
|
48173
|
-
{
|
|
48174
|
-
rule_id: "pem_private_key",
|
|
48175
|
-
regex: /-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]+?-----END [A-Z ]*PRIVATE KEY-----/g,
|
|
48176
|
-
captureIndex: 0,
|
|
48177
|
-
slugHint: "pem_private_key"
|
|
48178
|
-
}
|
|
48179
|
-
];
|
|
48180
|
-
var ALL_PATTERNS = [...ANCHORED_PATTERNS, ...STRUCTURED_PATTERNS];
|
|
48181
|
-
|
|
48182
|
-
// secret-detect/entropy.ts
|
|
48183
|
-
function shannonEntropy(s) {
|
|
48184
|
-
if (s.length === 0)
|
|
48185
|
-
return 0;
|
|
48186
|
-
const counts = new Map;
|
|
48187
|
-
for (const ch of s) {
|
|
48188
|
-
counts.set(ch, (counts.get(ch) ?? 0) + 1);
|
|
48189
|
-
}
|
|
48190
|
-
let h = 0;
|
|
48191
|
-
const len = s.length;
|
|
48192
|
-
for (const c of counts.values()) {
|
|
48193
|
-
const p = c / len;
|
|
48194
|
-
h -= p * Math.log2(p);
|
|
48195
|
-
}
|
|
48196
|
-
return h;
|
|
48197
|
-
}
|
|
48198
|
-
|
|
48199
|
-
// secret-detect/kv-scanner.ts
|
|
48200
|
-
var KV_RE = /\b([A-Za-z_][A-Za-z0-9_-]*(?:password|passwd|token|secret|key|api[_-]?key))\s*[:=]\s*["']?([^\s"'\\]{8,})["']?/gi;
|
|
48201
|
-
var KV_ENTROPY_THRESHOLD = 4;
|
|
48202
|
-
function scanKeyValue(text) {
|
|
48203
|
-
const hits = [];
|
|
48204
|
-
KV_RE.lastIndex = 0;
|
|
48205
|
-
let m;
|
|
48206
|
-
while ((m = KV_RE.exec(text)) !== null) {
|
|
48207
|
-
const [, keyName, value] = m;
|
|
48208
|
-
if (!value)
|
|
48209
|
-
continue;
|
|
48210
|
-
const h = shannonEntropy(value);
|
|
48211
|
-
if (h < KV_ENTROPY_THRESHOLD)
|
|
48212
|
-
continue;
|
|
48213
|
-
const valueOffsetInMatch = m[0].indexOf(value, keyName.length);
|
|
48214
|
-
if (valueOffsetInMatch < 0)
|
|
48215
|
-
continue;
|
|
48216
|
-
const start = m.index + valueOffsetInMatch;
|
|
48217
|
-
const end = start + value.length;
|
|
48218
|
-
hits.push({
|
|
48219
|
-
rule_id: "kv_entropy",
|
|
48220
|
-
start,
|
|
48221
|
-
end,
|
|
48222
|
-
matched_text: value,
|
|
48223
|
-
key_name: keyName,
|
|
48224
|
-
confidence: "ambiguous"
|
|
48225
|
-
});
|
|
48226
|
-
}
|
|
48227
|
-
return hits;
|
|
48228
|
-
}
|
|
48229
|
-
|
|
48230
|
-
// secret-detect/chunker.ts
|
|
48231
|
-
var CHUNK_THRESHOLD = 32 * 1024;
|
|
48232
|
-
var WINDOW_SIZE = 16 * 1024;
|
|
48233
|
-
var OVERLAP = 1024;
|
|
48234
|
-
function chunk(text) {
|
|
48235
|
-
if (text.length <= CHUNK_THRESHOLD) {
|
|
48236
|
-
return [{ offset: 0, text }];
|
|
48237
|
-
}
|
|
48238
|
-
const out = [];
|
|
48239
|
-
let offset = 0;
|
|
48240
|
-
while (offset < text.length) {
|
|
48241
|
-
const end = Math.min(offset + WINDOW_SIZE, text.length);
|
|
48242
|
-
out.push({ offset, text: text.slice(offset, end) });
|
|
48243
|
-
if (end >= text.length)
|
|
48244
|
-
break;
|
|
48245
|
-
offset = end - OVERLAP;
|
|
48246
|
-
}
|
|
48247
|
-
return out;
|
|
48248
|
-
}
|
|
48249
|
-
|
|
48250
|
-
// secret-detect/index.ts
|
|
48251
|
-
init_suppressor();
|
|
48252
|
-
|
|
48253
|
-
// secret-detect/mask.ts
|
|
48254
|
-
function maskToken(s) {
|
|
48255
|
-
if (s.length >= 18) {
|
|
48256
|
-
return `${s.slice(0, 6)}...${s.slice(-4)}`;
|
|
48257
|
-
}
|
|
48258
|
-
return "***";
|
|
48259
|
-
}
|
|
48260
|
-
// secret-detect/url-redact.ts
|
|
48261
|
-
var SENSITIVE_PARAMS = new Set([
|
|
48262
|
-
"token",
|
|
48263
|
-
"key",
|
|
48264
|
-
"api_key",
|
|
48265
|
-
"apikey",
|
|
48266
|
-
"secret",
|
|
48267
|
-
"access_token",
|
|
48268
|
-
"password",
|
|
48269
|
-
"pass",
|
|
48270
|
-
"auth",
|
|
48271
|
-
"client_secret",
|
|
48272
|
-
"refresh_token",
|
|
48273
|
-
"signature"
|
|
48274
|
-
]);
|
|
48275
|
-
|
|
48276
|
-
// secret-detect/index.ts
|
|
48277
|
-
init_secretlint_source();
|
|
48278
|
-
function detectSecrets(text) {
|
|
48279
|
-
if (!text || text.length === 0)
|
|
48280
|
-
return [];
|
|
48281
|
-
const windows = chunk(text);
|
|
48282
|
-
const raw = [];
|
|
48283
|
-
for (const win of windows) {
|
|
48284
|
-
for (const p of ALL_PATTERNS) {
|
|
48285
|
-
const re = new RegExp(p.regex.source, p.regex.flags.includes("g") ? p.regex.flags : p.regex.flags + "g");
|
|
48286
|
-
let m;
|
|
48287
|
-
while ((m = re.exec(win.text)) !== null) {
|
|
48288
|
-
if (m[0].length === 0) {
|
|
48289
|
-
re.lastIndex++;
|
|
48290
|
-
continue;
|
|
48291
|
-
}
|
|
48292
|
-
const cap = p.captureIndex === 0 ? m[0] : m[p.captureIndex];
|
|
48293
|
-
if (!cap)
|
|
48294
|
-
continue;
|
|
48295
|
-
const matchStart = p.captureIndex === 0 ? m.index : m.index + m[0].indexOf(cap);
|
|
48296
|
-
if (matchStart < 0)
|
|
48297
|
-
continue;
|
|
48298
|
-
const globalStart = win.offset + matchStart;
|
|
48299
|
-
const globalEnd = globalStart + cap.length;
|
|
48300
|
-
const keyName = p.rule_id === "env_key_value" ? m[1] : undefined;
|
|
48301
|
-
if (p.rule_id === "env_key_value") {
|
|
48302
|
-
const ENV_KV_MIN_LEN = 12;
|
|
48303
|
-
const ENV_KV_MIN_ENTROPY = 3.5;
|
|
48304
|
-
if (cap.length < ENV_KV_MIN_LEN)
|
|
48305
|
-
continue;
|
|
48306
|
-
if (shannonEntropy(cap) < ENV_KV_MIN_ENTROPY)
|
|
48307
|
-
continue;
|
|
48308
|
-
}
|
|
48309
|
-
raw.push({
|
|
48310
|
-
rule_id: p.rule_id,
|
|
48311
|
-
start: globalStart,
|
|
48312
|
-
end: globalEnd,
|
|
48313
|
-
matched_text: cap,
|
|
48314
|
-
key_name: keyName,
|
|
48315
|
-
confidence: "high"
|
|
48316
|
-
});
|
|
48317
|
-
}
|
|
48318
|
-
}
|
|
48319
|
-
const kvHits = scanKeyValue(win.text);
|
|
48320
|
-
for (const h of kvHits) {
|
|
48321
|
-
raw.push({ ...h, start: h.start + win.offset, end: h.end + win.offset });
|
|
48322
|
-
}
|
|
48323
|
-
}
|
|
48324
|
-
const deduped = dedupeRaw(raw);
|
|
48325
|
-
const final = dropOverlaps(deduped);
|
|
48326
|
-
const existing = new Set;
|
|
48327
|
-
const out = [];
|
|
48328
|
-
for (const h of final) {
|
|
48329
|
-
const suggested_slug = deriveSlug({ key_name: h.key_name, rule_id: h.rule_id }, existing);
|
|
48330
|
-
existing.add(suggested_slug);
|
|
48331
|
-
out.push({
|
|
48332
|
-
rule_id: h.rule_id,
|
|
48333
|
-
matched_text: h.matched_text,
|
|
48334
|
-
start: h.start,
|
|
48335
|
-
end: h.end,
|
|
48336
|
-
confidence: h.confidence,
|
|
48337
|
-
suppressed: isSuppressed(text, h.start, h.end),
|
|
48338
|
-
suggested_slug,
|
|
48339
|
-
key_name: h.key_name
|
|
48340
|
-
});
|
|
48341
|
-
}
|
|
48342
|
-
out.sort((a, b) => a.start - b.start);
|
|
48343
|
-
return out;
|
|
48344
|
-
}
|
|
48345
|
-
function dedupeRaw(raw) {
|
|
48346
|
-
const seen = new Map;
|
|
48347
|
-
for (const h of raw) {
|
|
48348
|
-
const key = `${h.start}:${h.end}`;
|
|
48349
|
-
const existing = seen.get(key);
|
|
48350
|
-
if (!existing) {
|
|
48351
|
-
seen.set(key, h);
|
|
48352
|
-
continue;
|
|
48353
|
-
}
|
|
48354
|
-
if (existing.confidence === "ambiguous" && h.confidence === "high") {
|
|
48355
|
-
seen.set(key, h);
|
|
48356
|
-
}
|
|
48357
|
-
}
|
|
48358
|
-
return Array.from(seen.values());
|
|
48359
|
-
}
|
|
48360
|
-
function dropOverlaps(hits) {
|
|
48361
|
-
const sorted = [...hits].sort((a, b) => a.end - a.start - (b.end - b.start));
|
|
48362
|
-
const out = [];
|
|
48363
|
-
for (const h of sorted) {
|
|
48364
|
-
const contained = out.some((existing) => existing !== h && existing.start <= h.start && existing.end >= h.end && !(existing.start === h.start && existing.end === h.end));
|
|
48365
|
-
if (!contained)
|
|
48366
|
-
out.push(h);
|
|
48367
|
-
}
|
|
48368
|
-
out.sort((a, b) => a.start - b.start || a.end - b.end);
|
|
48369
|
-
return out;
|
|
48370
|
-
}
|
|
48446
|
+
// secret-detect/pipeline.ts
|
|
48447
|
+
init_secret_detect();
|
|
48371
48448
|
|
|
48372
48449
|
// secret-detect/rewrite.ts
|
|
48373
48450
|
function rewritePrompt(text, targets) {
|
|
@@ -48731,7 +48808,11 @@ function recentDenialsFromAuditLog(rawAuditLog, opts) {
|
|
|
48731
48808
|
}
|
|
48732
48809
|
|
|
48733
48810
|
// secret-detect/index.ts
|
|
48811
|
+
init_patterns();
|
|
48812
|
+
init_kv_scanner();
|
|
48813
|
+
init_chunker();
|
|
48734
48814
|
init_suppressor();
|
|
48815
|
+
init_url_redact();
|
|
48735
48816
|
init_secretlint_source();
|
|
48736
48817
|
function detectSecrets2(text) {
|
|
48737
48818
|
if (!text || text.length === 0)
|
|
@@ -48827,6 +48908,32 @@ function dropOverlaps2(hits) {
|
|
|
48827
48908
|
return out;
|
|
48828
48909
|
}
|
|
48829
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
|
+
|
|
48830
48937
|
// admin-commands/index.ts
|
|
48831
48938
|
var ADMIN_COMMAND_NAMES = new Set([
|
|
48832
48939
|
"agents",
|
|
@@ -49053,6 +49160,10 @@ function projectSubagentLine(line, agentId, state4) {
|
|
|
49053
49160
|
events.push({ kind: "sub_agent_text", agentId, text });
|
|
49054
49161
|
}
|
|
49055
49162
|
}
|
|
49163
|
+
const stopReason = message?.stop_reason;
|
|
49164
|
+
if (stopReason === "end_turn") {
|
|
49165
|
+
events.push({ kind: "sub_agent_turn_end", agentId });
|
|
49166
|
+
}
|
|
49056
49167
|
return events;
|
|
49057
49168
|
}
|
|
49058
49169
|
if (type === "system" && obj.subtype === "turn_duration") {
|
|
@@ -49190,6 +49301,10 @@ function redactSecrets(text) {
|
|
|
49190
49301
|
return out;
|
|
49191
49302
|
}
|
|
49192
49303
|
// registry/subagents-schema.ts
|
|
49304
|
+
function countRunningBackgroundSubagents(db2) {
|
|
49305
|
+
const row = db2.prepare("SELECT count(*) AS n FROM subagents WHERE background = 1 AND status = 'running'").get();
|
|
49306
|
+
return row?.n ?? 0;
|
|
49307
|
+
}
|
|
49193
49308
|
function recordSubagentEnd(db2, args) {
|
|
49194
49309
|
db2.prepare(`
|
|
49195
49310
|
UPDATE subagents
|
|
@@ -49899,6 +50014,15 @@ function startSubagentWatcher(config) {
|
|
|
49899
50014
|
},
|
|
49900
50015
|
getRegistry() {
|
|
49901
50016
|
return registry;
|
|
50017
|
+
},
|
|
50018
|
+
countRunningBackgroundWorkers() {
|
|
50019
|
+
if (db2 == null)
|
|
50020
|
+
return null;
|
|
50021
|
+
try {
|
|
50022
|
+
return countRunningBackgroundSubagents(db2);
|
|
50023
|
+
} catch {
|
|
50024
|
+
return null;
|
|
50025
|
+
}
|
|
49902
50026
|
}
|
|
49903
50027
|
};
|
|
49904
50028
|
}
|
|
@@ -50371,6 +50495,9 @@ var SEVERITY_RANK2 = {
|
|
|
50371
50495
|
critical: 3
|
|
50372
50496
|
};
|
|
50373
50497
|
|
|
50498
|
+
// ../src/secret-detect/redact.ts
|
|
50499
|
+
init_redact();
|
|
50500
|
+
|
|
50374
50501
|
// ../src/issues/store.ts
|
|
50375
50502
|
var ISSUES_FILE = "issues.jsonl";
|
|
50376
50503
|
var ISSUES_LOCK = "issues.lock";
|
|
@@ -50786,6 +50913,18 @@ function describeGrant(toolName, inputPreview, option) {
|
|
|
50786
50913
|
return naturalAction(toolName, inputPreview);
|
|
50787
50914
|
}
|
|
50788
50915
|
}
|
|
50916
|
+
function formatPermissionResumeMessage(opts) {
|
|
50917
|
+
const who = opts.agentName && opts.agentName.length > 0 ? `<b>${escapeTgHtml(capFirst(opts.agentName))}</b>` : `<b>Agent</b>`;
|
|
50918
|
+
const act = (opts.action ?? "").trim();
|
|
50919
|
+
const hasAction = act.length > 0;
|
|
50920
|
+
if (opts.behavior === "allow") {
|
|
50921
|
+
return hasAction ? `\u25b6\ufe0f ${who} \u2014 got it, continuing: <i>${escapeTgHtml(act)}</i>` : `\u25b6\ufe0f ${who} \u2014 got it, back to work.`;
|
|
50922
|
+
}
|
|
50923
|
+
if (opts.timeoutMinutes != null) {
|
|
50924
|
+
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.`;
|
|
50925
|
+
}
|
|
50926
|
+
return hasAction ? `\uD83D\uDEAB ${who} \u2014 noted, I won't ${escapeTgHtml(lowerFirst(act))}. Continuing without it.` : `\uD83D\uDEAB ${who} \u2014 noted, continuing without it.`;
|
|
50927
|
+
}
|
|
50789
50928
|
function resolveSkillName(input) {
|
|
50790
50929
|
return readString(input, "skill") ?? readString(input, "skill_name") ?? readString(input, "skillName") ?? readString(input, "name") ?? skillBasenameFromPath(input);
|
|
50791
50930
|
}
|
|
@@ -51520,10 +51659,10 @@ function sweepStaleTurnActiveMarker(stateDir, opts) {
|
|
|
51520
51659
|
}
|
|
51521
51660
|
|
|
51522
51661
|
// ../src/build-info.ts
|
|
51523
|
-
var VERSION = "0.14.
|
|
51524
|
-
var COMMIT_SHA = "
|
|
51525
|
-
var COMMIT_DATE = "2026-06-
|
|
51526
|
-
var LATEST_PR =
|
|
51662
|
+
var VERSION = "0.14.29";
|
|
51663
|
+
var COMMIT_SHA = "33f6300c";
|
|
51664
|
+
var COMMIT_DATE = "2026-06-01T04:54:34Z";
|
|
51665
|
+
var LATEST_PR = 2052;
|
|
51527
51666
|
var COMMITS_AHEAD_OF_TAG = 0;
|
|
51528
51667
|
|
|
51529
51668
|
// gateway/boot-version.ts
|
|
@@ -52941,6 +53080,9 @@ function finalizeStatusReaction(chatId, threadId, reason = "done") {
|
|
|
52941
53080
|
purgeReactionTracking(key);
|
|
52942
53081
|
}
|
|
52943
53082
|
function countRunningWorkers() {
|
|
53083
|
+
const dbCount = subagentWatcher?.countRunningBackgroundWorkers?.();
|
|
53084
|
+
if (dbCount != null)
|
|
53085
|
+
return dbCount;
|
|
52944
53086
|
const reg = subagentWatcher?.getRegistry();
|
|
52945
53087
|
if (reg == null)
|
|
52946
53088
|
return 0;
|
|
@@ -52957,6 +53099,31 @@ function resumeReactionAfterVerdict() {
|
|
|
52957
53099
|
return;
|
|
52958
53100
|
activeStatusReactions.get(statusKey(turn.sessionChatId, turn.sessionThreadId))?.setThinking();
|
|
52959
53101
|
}
|
|
53102
|
+
function postPermissionResumeMessage(opts) {
|
|
53103
|
+
if (process.env.SWITCHROOM_RESUME_MSG === "0")
|
|
53104
|
+
return;
|
|
53105
|
+
const text = formatPermissionResumeMessage({
|
|
53106
|
+
agentName: process.env.SWITCHROOM_AGENT_NAME ?? null,
|
|
53107
|
+
behavior: opts.behavior,
|
|
53108
|
+
action: opts.action,
|
|
53109
|
+
timeoutMinutes: opts.timeoutMinutes
|
|
53110
|
+
});
|
|
53111
|
+
const turn = currentTurn;
|
|
53112
|
+
const targets = turn != null ? [{ chatId: turn.sessionChatId, threadId: turn.sessionThreadId }] : loadAccess().allowFrom.map((chatId) => ({
|
|
53113
|
+
chatId,
|
|
53114
|
+
threadId: resolveAgentOutboundTopic({
|
|
53115
|
+
kind: "permission",
|
|
53116
|
+
turnInitiated: false,
|
|
53117
|
+
originThreadId: undefined
|
|
53118
|
+
})
|
|
53119
|
+
}));
|
|
53120
|
+
for (const { chatId, threadId } of targets) {
|
|
53121
|
+
swallowingApiCall(() => bot.api.sendMessage(chatId, text, {
|
|
53122
|
+
parse_mode: "HTML",
|
|
53123
|
+
...threadId != null ? { message_thread_id: threadId } : {}
|
|
53124
|
+
}), { chat_id: chatId, verb: "permission-resume", ...threadId != null ? { threadId } : {} });
|
|
53125
|
+
}
|
|
53126
|
+
}
|
|
52960
53127
|
function resolveThreadId(chat_id, explicit) {
|
|
52961
53128
|
if (explicit != null)
|
|
52962
53129
|
return Number(explicit);
|
|
@@ -53371,6 +53538,11 @@ var pendingStateReaper = setInterval(() => {
|
|
|
53371
53538
|
if (now - v.startedAt > PERMISSION_TTL_MS) {
|
|
53372
53539
|
dispatchPermissionVerdict({ type: "permission", requestId: k, behavior: "deny" });
|
|
53373
53540
|
resumeReactionAfterVerdict();
|
|
53541
|
+
postPermissionResumeMessage({
|
|
53542
|
+
behavior: "deny",
|
|
53543
|
+
action: naturalAction(v.tool_name, v.input_preview),
|
|
53544
|
+
timeoutMinutes: Math.round(PERMISSION_TTL_MS / 60000)
|
|
53545
|
+
});
|
|
53374
53546
|
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)
|
|
53375
53547
|
`);
|
|
53376
53548
|
pendingPermissions.delete(k);
|
|
@@ -54397,7 +54569,8 @@ var ALLOWED_TOOLS = new Set([
|
|
|
54397
54569
|
"send_sticker",
|
|
54398
54570
|
"send_gif",
|
|
54399
54571
|
"vault_request_save",
|
|
54400
|
-
"vault_request_access"
|
|
54572
|
+
"vault_request_access",
|
|
54573
|
+
"request_secret"
|
|
54401
54574
|
]);
|
|
54402
54575
|
async function executeToolCall(tool, args) {
|
|
54403
54576
|
if (!ALLOWED_TOOLS.has(tool)) {
|
|
@@ -54440,6 +54613,8 @@ async function executeToolCall(tool, args) {
|
|
|
54440
54613
|
return executeVaultRequestSave(args);
|
|
54441
54614
|
case "vault_request_access":
|
|
54442
54615
|
return executeVaultRequestAccess(args);
|
|
54616
|
+
case "request_secret":
|
|
54617
|
+
return executeRequestSecret(args);
|
|
54443
54618
|
default:
|
|
54444
54619
|
throw new Error(`unknown tool: ${tool}`);
|
|
54445
54620
|
}
|
|
@@ -54485,6 +54660,14 @@ async function executeUpdateChecklist(args) {
|
|
|
54485
54660
|
`);
|
|
54486
54661
|
return { content: [{ type: "text", text: `checklist updated (id: ${message_id})` }] };
|
|
54487
54662
|
}
|
|
54663
|
+
function redactOutboundText(text, site) {
|
|
54664
|
+
const masked = redact2(text);
|
|
54665
|
+
if (masked !== text) {
|
|
54666
|
+
process.stderr.write(`telegram gateway: outbound secret masked site=${site}
|
|
54667
|
+
`);
|
|
54668
|
+
}
|
|
54669
|
+
return masked;
|
|
54670
|
+
}
|
|
54488
54671
|
async function executeReply(args) {
|
|
54489
54672
|
const turn = currentTurn;
|
|
54490
54673
|
const chat_id = args.chat_id;
|
|
@@ -54494,6 +54677,7 @@ async function executeReply(args) {
|
|
|
54494
54677
|
if (rawText == null || rawText === "")
|
|
54495
54678
|
throw new Error("reply: text is required and cannot be empty");
|
|
54496
54679
|
let text = repairEscapedWhitespace(rawText);
|
|
54680
|
+
text = redactOutboundText(text, "reply");
|
|
54497
54681
|
{
|
|
54498
54682
|
const scrub = scrubVoice(text);
|
|
54499
54683
|
if (scrub.replaced > 0) {
|
|
@@ -54916,6 +55100,7 @@ async function executeStreamReply(args) {
|
|
|
54916
55100
|
throw new Error("stream_reply: chat_id is required");
|
|
54917
55101
|
if (args.text == null || args.text === "")
|
|
54918
55102
|
throw new Error("stream_reply: text is required and cannot be empty");
|
|
55103
|
+
args.text = redactOutboundText(args.text, "stream_reply");
|
|
54919
55104
|
{
|
|
54920
55105
|
const scrub = scrubVoice(args.text);
|
|
54921
55106
|
if (scrub.replaced > 0) {
|
|
@@ -55434,6 +55619,213 @@ async function executeVaultRequestSave(args) {
|
|
|
55434
55619
|
]
|
|
55435
55620
|
};
|
|
55436
55621
|
}
|
|
55622
|
+
var pendingSecretRequests = new Map;
|
|
55623
|
+
var armedSecretCaptures = new Map;
|
|
55624
|
+
var PENDING_SECRET_REQUEST_TTL_MS = 1800000;
|
|
55625
|
+
var ARMED_SECRET_CAPTURE_TTL_MS = 600000;
|
|
55626
|
+
function sweepSecretRequests() {
|
|
55627
|
+
const now = Date.now();
|
|
55628
|
+
for (const [k, v] of pendingSecretRequests) {
|
|
55629
|
+
if (now - v.staged_at > PENDING_SECRET_REQUEST_TTL_MS)
|
|
55630
|
+
pendingSecretRequests.delete(k);
|
|
55631
|
+
}
|
|
55632
|
+
for (const [k, v] of armedSecretCaptures) {
|
|
55633
|
+
if (now - v.armed_at > ARMED_SECRET_CAPTURE_TTL_MS)
|
|
55634
|
+
armedSecretCaptures.delete(k);
|
|
55635
|
+
}
|
|
55636
|
+
}
|
|
55637
|
+
function buildSecretRequestKeyboard(stageId) {
|
|
55638
|
+
return {
|
|
55639
|
+
inline_keyboard: [
|
|
55640
|
+
[
|
|
55641
|
+
{ text: "\uD83D\uDD10 Provide securely", callback_data: `vsp:provide:${stageId}` },
|
|
55642
|
+
{ text: "\uD83D\uDEAB Decline", callback_data: `vsp:decline:${stageId}` }
|
|
55643
|
+
]
|
|
55644
|
+
]
|
|
55645
|
+
};
|
|
55646
|
+
}
|
|
55647
|
+
function renderSecretRequestCard(req) {
|
|
55648
|
+
const lines = [
|
|
55649
|
+
`\uD83D\uDD12 <b>${escapeHtmlForTg(req.agent)}</b> needs a secret:`,
|
|
55650
|
+
`<code>${escapeHtmlForTg(req.key)}</code>`
|
|
55651
|
+
];
|
|
55652
|
+
if (req.reason)
|
|
55653
|
+
lines.push(`<i>${escapeHtmlForTg(req.reason)}</i>`);
|
|
55654
|
+
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.");
|
|
55655
|
+
return lines.join(`
|
|
55656
|
+
`);
|
|
55657
|
+
}
|
|
55658
|
+
async function executeRequestSecret(args) {
|
|
55659
|
+
const chat_id = args.chat_id;
|
|
55660
|
+
if (!chat_id)
|
|
55661
|
+
throw new Error("request_secret: chat_id is required");
|
|
55662
|
+
const key = args.key;
|
|
55663
|
+
if (!key || typeof key !== "string")
|
|
55664
|
+
throw new Error("request_secret: key is required");
|
|
55665
|
+
const reason = typeof args.reason === "string" ? args.reason : undefined;
|
|
55666
|
+
assertAllowedChat(chat_id);
|
|
55667
|
+
if (!VAULT_KEY_REGEX.test(key)) {
|
|
55668
|
+
throw new Error(`request_secret: key must match ${VAULT_KEY_REGEX_LABEL}`);
|
|
55669
|
+
}
|
|
55670
|
+
const agentSlug = process.env.SWITCHROOM_AGENT_NAME || "agent";
|
|
55671
|
+
for (const [sid, p] of pendingSecretRequests) {
|
|
55672
|
+
if (p.chat_id === chat_id && p.key === key)
|
|
55673
|
+
pendingSecretRequests.delete(sid);
|
|
55674
|
+
}
|
|
55675
|
+
const stageId = randomBytes6(4).toString("hex");
|
|
55676
|
+
const pending2 = { agent: agentSlug, chat_id, key, reason, staged_at: Date.now() };
|
|
55677
|
+
pendingSecretRequests.set(stageId, pending2);
|
|
55678
|
+
sweepSecretRequests();
|
|
55679
|
+
const text = renderSecretRequestCard(pending2);
|
|
55680
|
+
const threadId = args.message_thread_id != null ? Number(args.message_thread_id) : undefined;
|
|
55681
|
+
const sent = await retryWithThreadFallback(robustApiCall, (tid) => lockedBot.api.sendMessage(chat_id, text, {
|
|
55682
|
+
parse_mode: "HTML",
|
|
55683
|
+
reply_markup: buildSecretRequestKeyboard(stageId),
|
|
55684
|
+
...tid != null && Number.isFinite(tid) ? { message_thread_id: tid } : {}
|
|
55685
|
+
}), { threadId, chat_id, verb: "request_secret.card" });
|
|
55686
|
+
pending2.card_message_id = sent.message_id;
|
|
55687
|
+
return {
|
|
55688
|
+
content: [
|
|
55689
|
+
{
|
|
55690
|
+
type: "text",
|
|
55691
|
+
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.`
|
|
55692
|
+
}
|
|
55693
|
+
]
|
|
55694
|
+
};
|
|
55695
|
+
}
|
|
55696
|
+
async function writeRequestedSecret(key, value, chat_id) {
|
|
55697
|
+
if (VAULT_APPROVAL_AUTH_MODE === "telegram-id") {
|
|
55698
|
+
return await defaultVaultWritePosture(key, value);
|
|
55699
|
+
}
|
|
55700
|
+
const cached = vaultPassphraseCache.get(chat_id);
|
|
55701
|
+
if (!cached || cached.expiresAt <= Date.now()) {
|
|
55702
|
+
return { ok: false, output: "VAULT-LOCKED: run /vault unlock once in this chat, then have the agent re-request." };
|
|
55703
|
+
}
|
|
55704
|
+
return defaultVaultWrite(key, value, cached.passphrase);
|
|
55705
|
+
}
|
|
55706
|
+
async function captureProvidedSecret(ctx, chat_id, msgId, value) {
|
|
55707
|
+
const armed = armedSecretCaptures.get(chat_id);
|
|
55708
|
+
if (!armed || Date.now() - armed.armed_at > ARMED_SECRET_CAPTURE_TTL_MS) {
|
|
55709
|
+
if (armed)
|
|
55710
|
+
armedSecretCaptures.delete(chat_id);
|
|
55711
|
+
return false;
|
|
55712
|
+
}
|
|
55713
|
+
armedSecretCaptures.delete(chat_id);
|
|
55714
|
+
const pending2 = pendingSecretRequests.get(armed.stageId);
|
|
55715
|
+
pendingSecretRequests.delete(armed.stageId);
|
|
55716
|
+
if (msgId != null)
|
|
55717
|
+
await deleteSensitiveMessage(chat_id, msgId, "provided secret value");
|
|
55718
|
+
const write = await writeRequestedSecret(armed.key, value, chat_id);
|
|
55719
|
+
if (!write.ok) {
|
|
55720
|
+
const parsed = parseVaultCliError(write.output);
|
|
55721
|
+
const rendered = renderVaultCliError(parsed, { verb: "save", key: armed.key });
|
|
55722
|
+
const body = rendered.suppressRaw ? rendered.html : `\u26A0\uFE0F vault write failed:
|
|
55723
|
+
<pre>${escapeHtmlForTg(write.output)}</pre>`;
|
|
55724
|
+
await switchroomReply(ctx, `${body}
|
|
55725
|
+
|
|
55726
|
+
<i>The secret was NOT saved. The agent can re-request with <code>request_secret</code>.</i>`, { html: true });
|
|
55727
|
+
const fts = Date.now();
|
|
55728
|
+
const failMsg = {
|
|
55729
|
+
type: "inbound",
|
|
55730
|
+
chatId: chat_id,
|
|
55731
|
+
messageId: fts,
|
|
55732
|
+
user: "vault-broker",
|
|
55733
|
+
userId: 0,
|
|
55734
|
+
ts: fts,
|
|
55735
|
+
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.`,
|
|
55736
|
+
meta: { source: "secret_provide_failed", agent: armed.agent, key: armed.key, stage_id: armed.stageId }
|
|
55737
|
+
};
|
|
55738
|
+
const fdelivered = ipcServer.sendToAgent(armed.agent, failMsg);
|
|
55739
|
+
if (fdelivered)
|
|
55740
|
+
markClaudeBusyForInbound(failMsg);
|
|
55741
|
+
else
|
|
55742
|
+
pendingInboundBuffer.push(armed.agent, failMsg);
|
|
55743
|
+
return true;
|
|
55744
|
+
}
|
|
55745
|
+
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 });
|
|
55746
|
+
const ts = Date.now();
|
|
55747
|
+
const synthetic = {
|
|
55748
|
+
type: "inbound",
|
|
55749
|
+
chatId: chat_id,
|
|
55750
|
+
messageId: ts,
|
|
55751
|
+
user: "vault-broker",
|
|
55752
|
+
userId: 0,
|
|
55753
|
+
ts,
|
|
55754
|
+
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.`,
|
|
55755
|
+
meta: {
|
|
55756
|
+
source: "secret_provided",
|
|
55757
|
+
agent: armed.agent,
|
|
55758
|
+
key: armed.key,
|
|
55759
|
+
stage_id: armed.stageId
|
|
55760
|
+
}
|
|
55761
|
+
};
|
|
55762
|
+
const delivered = ipcServer.sendToAgent(armed.agent, synthetic);
|
|
55763
|
+
if (delivered)
|
|
55764
|
+
markClaudeBusyForInbound(synthetic);
|
|
55765
|
+
else
|
|
55766
|
+
pendingInboundBuffer.push(armed.agent, synthetic);
|
|
55767
|
+
process.stderr.write(`telegram gateway: secret_provided injection agent=${armed.agent} key=${armed.key} stage=${armed.stageId} delivered=${delivered}
|
|
55768
|
+
`);
|
|
55769
|
+
return true;
|
|
55770
|
+
}
|
|
55771
|
+
async function handleSecretRequestCallback(ctx, data) {
|
|
55772
|
+
const senderId = String(ctx.from?.id ?? "");
|
|
55773
|
+
const access = loadAccess();
|
|
55774
|
+
if (!access.allowFrom.includes(senderId)) {
|
|
55775
|
+
await ctx.answerCallbackQuery({ text: "Not authorized." }).catch(() => {});
|
|
55776
|
+
return;
|
|
55777
|
+
}
|
|
55778
|
+
const parts = data.split(":");
|
|
55779
|
+
const action = parts[1];
|
|
55780
|
+
const stageId = parts[2] ?? "";
|
|
55781
|
+
const pending2 = pendingSecretRequests.get(stageId);
|
|
55782
|
+
if (!pending2) {
|
|
55783
|
+
await ctx.answerCallbackQuery({ text: "This request expired." }).catch(() => {});
|
|
55784
|
+
return;
|
|
55785
|
+
}
|
|
55786
|
+
if (action === "provide") {
|
|
55787
|
+
armedSecretCaptures.set(pending2.chat_id, {
|
|
55788
|
+
key: pending2.key,
|
|
55789
|
+
agent: pending2.agent,
|
|
55790
|
+
stageId,
|
|
55791
|
+
armed_at: Date.now()
|
|
55792
|
+
});
|
|
55793
|
+
await ctx.answerCallbackQuery({ text: "Send the value now \u2014 it auto-deletes." }).catch(() => {});
|
|
55794
|
+
if (pending2.card_message_id != null) {
|
|
55795
|
+
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(() => {});
|
|
55796
|
+
}
|
|
55797
|
+
return;
|
|
55798
|
+
}
|
|
55799
|
+
if (action === "decline") {
|
|
55800
|
+
pendingSecretRequests.delete(stageId);
|
|
55801
|
+
armedSecretCaptures.delete(pending2.chat_id);
|
|
55802
|
+
await ctx.answerCallbackQuery({ text: "Declined." }).catch(() => {});
|
|
55803
|
+
if (pending2.card_message_id != null) {
|
|
55804
|
+
await ctx.api.editMessageText(pending2.chat_id, pending2.card_message_id, `\uD83D\uDEAB Declined \u2014 <code>${escapeHtmlForTg(pending2.key)}</code> not provided.`, {
|
|
55805
|
+
parse_mode: "HTML",
|
|
55806
|
+
reply_markup: { inline_keyboard: [] }
|
|
55807
|
+
}).catch(() => {});
|
|
55808
|
+
}
|
|
55809
|
+
const ts = Date.now();
|
|
55810
|
+
const synthetic = {
|
|
55811
|
+
type: "inbound",
|
|
55812
|
+
chatId: pending2.chat_id,
|
|
55813
|
+
messageId: ts,
|
|
55814
|
+
user: "vault-broker",
|
|
55815
|
+
userId: 0,
|
|
55816
|
+
ts,
|
|
55817
|
+
text: `\uD83D\uDEAB Operator declined your request for \`vault:${pending2.key}\`. Proceed without it or ask how they'd like to handle the task.`,
|
|
55818
|
+
meta: { source: "secret_declined", agent: pending2.agent, key: pending2.key, stage_id: stageId }
|
|
55819
|
+
};
|
|
55820
|
+
const delivered = ipcServer.sendToAgent(pending2.agent, synthetic);
|
|
55821
|
+
if (delivered)
|
|
55822
|
+
markClaudeBusyForInbound(synthetic);
|
|
55823
|
+
else
|
|
55824
|
+
pendingInboundBuffer.push(pending2.agent, synthetic);
|
|
55825
|
+
return;
|
|
55826
|
+
}
|
|
55827
|
+
await ctx.answerCallbackQuery().catch(() => {});
|
|
55828
|
+
}
|
|
55437
55829
|
function buildVaultRequestAccessKeyboard(stageId) {
|
|
55438
55830
|
return {
|
|
55439
55831
|
inline_keyboard: [
|
|
@@ -55595,6 +55987,7 @@ async function executeEditMessage(args) {
|
|
|
55595
55987
|
const editConfigMode = editAccess.parseMode ?? "html";
|
|
55596
55988
|
const editFormat = args.format ?? editConfigMode;
|
|
55597
55989
|
let editRawText = repairEscapedWhitespace(args.text);
|
|
55990
|
+
editRawText = redactOutboundText(editRawText, "edit_message");
|
|
55598
55991
|
{
|
|
55599
55992
|
const scrub = scrubVoice(editRawText);
|
|
55600
55993
|
if (scrub.replaced > 0) {
|
|
@@ -56257,6 +56650,7 @@ function handleSessionEvent(ev) {
|
|
|
56257
56650
|
const backstopChatId = chatId;
|
|
56258
56651
|
const backstopThreadId = threadId;
|
|
56259
56652
|
const backstopCtrl = ctrl;
|
|
56653
|
+
capturedText = redactOutboundText(capturedText, "turn_flush");
|
|
56260
56654
|
{
|
|
56261
56655
|
const scrub = scrubVoice(capturedText);
|
|
56262
56656
|
if (scrub.replaced > 0) {
|
|
@@ -56792,6 +57186,11 @@ async function handleInbound(ctx, text, downloadImage, attachment, extraAttachme
|
|
|
56792
57186
|
behavior
|
|
56793
57187
|
});
|
|
56794
57188
|
resumeReactionAfterVerdict();
|
|
57189
|
+
const ftDetails = pendingPermissions.get(request_id);
|
|
57190
|
+
postPermissionResumeMessage({
|
|
57191
|
+
behavior,
|
|
57192
|
+
action: ftDetails ? naturalAction(ftDetails.tool_name, ftDetails.input_preview) : ""
|
|
57193
|
+
});
|
|
56795
57194
|
if (msgId != null) {
|
|
56796
57195
|
const emoji = behavior === "allow" ? "\u2705" : "\u274C";
|
|
56797
57196
|
bot.api.setMessageReaction(chat_id, msgId, [
|
|
@@ -57002,6 +57401,11 @@ ${preBlock(write.output)}`;
|
|
|
57002
57401
|
const parsedQueue = isSteerPrefix ? { queued: false, body: parsedSteer.body } : parseQueuePrefix(text);
|
|
57003
57402
|
const isQueuedPrefix = parsedQueue.queued;
|
|
57004
57403
|
let effectiveText = isSteerPrefix ? parsedSteer.body : isQueuedPrefix ? parsedQueue.body : text;
|
|
57404
|
+
if (armedSecretCaptures.has(chat_id)) {
|
|
57405
|
+
const consumed = await captureProvidedSecret(ctx, chat_id, msgId ?? undefined, text);
|
|
57406
|
+
if (consumed)
|
|
57407
|
+
return;
|
|
57408
|
+
}
|
|
57005
57409
|
try {
|
|
57006
57410
|
const authCodeSentAt = awaitingAuthCodeAt.get(chat_id);
|
|
57007
57411
|
const isAuthFlowContext = authCodeSentAt !== undefined && Date.now() - authCodeSentAt < AUTH_CODE_CONTEXT_TTL_MS;
|
|
@@ -58535,6 +58939,10 @@ async function handlePermissionSlash(ctx, behavior) {
|
|
|
58535
58939
|
}
|
|
58536
58940
|
dispatchPermissionVerdict({ type: "permission", requestId: request_id, behavior });
|
|
58537
58941
|
resumeReactionAfterVerdict();
|
|
58942
|
+
postPermissionResumeMessage({
|
|
58943
|
+
behavior,
|
|
58944
|
+
action: naturalAction(details.tool_name, details.input_preview)
|
|
58945
|
+
});
|
|
58538
58946
|
pendingPermissions.delete(request_id);
|
|
58539
58947
|
process.stderr.write(`[telegram gateway] slash-${behavior} request_id=${request_id} tool=${details.tool_name} by=${senderId}
|
|
58540
58948
|
`);
|
|
@@ -60652,6 +61060,10 @@ ${preBlock(formatSwitchroomOutput(err.message ?? "unknown error"))}`, { html: tr
|
|
|
60652
61060
|
await handleVaultRequestAccessCallback(ctx, data);
|
|
60653
61061
|
return;
|
|
60654
61062
|
}
|
|
61063
|
+
if (data.startsWith("vsp:")) {
|
|
61064
|
+
await handleSecretRequestCallback(ctx, data);
|
|
61065
|
+
return;
|
|
61066
|
+
}
|
|
60655
61067
|
if (data.startsWith("vrd:")) {
|
|
60656
61068
|
await handleVaultRecentDenialCallback(ctx, data);
|
|
60657
61069
|
return;
|
|
@@ -60832,6 +61244,10 @@ ${preBlock(formatSwitchroomOutput(err.message ?? "unknown error"))}`, { html: tr
|
|
|
60832
61244
|
rule: chosen.rule
|
|
60833
61245
|
});
|
|
60834
61246
|
resumeReactionAfterVerdict();
|
|
61247
|
+
postPermissionResumeMessage({
|
|
61248
|
+
behavior: "allow",
|
|
61249
|
+
action: naturalAction(details.tool_name, details.input_preview)
|
|
61250
|
+
});
|
|
60835
61251
|
let durable = false;
|
|
60836
61252
|
let legacy = false;
|
|
60837
61253
|
let failReason = "";
|
|
@@ -60932,10 +61348,12 @@ ${editLabel}` : editLabel,
|
|
|
60932
61348
|
});
|
|
60933
61349
|
return;
|
|
60934
61350
|
}
|
|
61351
|
+
const resumeAction = (() => {
|
|
61352
|
+
const d = pendingPermissions.get(request_id);
|
|
61353
|
+
return d ? naturalAction(d.tool_name, d.input_preview) : "";
|
|
61354
|
+
})();
|
|
60935
61355
|
pendingPermissions.delete(request_id);
|
|
60936
|
-
const
|
|
60937
|
-
const resumeBeat = resumeAgent ? `\u25B6\uFE0F ${escapeHtmlForTg(resumeAgent)} resuming\u2026` : "\u25B6\uFE0F resuming\u2026";
|
|
60938
|
-
const label = `${behavior === "allow" ? "\u2705 Allowed" : "\u274C Denied"} \xB7 ${resumeBeat}`;
|
|
61356
|
+
const label = behavior === "allow" ? "\u2705 Allowed" : "\u274C Denied";
|
|
60939
61357
|
const msg = ctx.callbackQuery?.message;
|
|
60940
61358
|
const baseText = msg && "text" in msg && msg.text ? escapeHtmlForTg(msg.text) : "";
|
|
60941
61359
|
await finalizeCallback(ctx, {
|
|
@@ -60951,6 +61369,10 @@ ${label}` : label,
|
|
|
60951
61369
|
behavior
|
|
60952
61370
|
});
|
|
60953
61371
|
resumeReactionAfterVerdict();
|
|
61372
|
+
postPermissionResumeMessage({
|
|
61373
|
+
behavior,
|
|
61374
|
+
action: resumeAction
|
|
61375
|
+
});
|
|
60954
61376
|
}
|
|
60955
61377
|
});
|
|
60956
61378
|
});
|