openmausbot 0.1.82 → 0.1.84
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/assets/index-BbU5REzd.js +310 -0
- package/dist/assets/{index-CKysBq-V.css → index-CLGfYlx_.css} +1 -1
- package/dist/assets/{index-5HVwp5m2.js → index-DNa2umw-.js} +1 -1
- package/dist/index.html +2 -2
- package/dist-server/container-mcp.js +20 -4
- package/dist-server/drivers/agents-proxy.js +30 -4
- package/dist-server/index.js +1716 -581
- package/dist-server/mcp-gate.js +2 -1
- package/dist-server/openmausbot.js +224 -63
- package/dist-server/pair-cli.js +224 -63
- package/dist-server/server/auto-approve.js +15 -1
- package/dist-server/server/auto-vm-claims.js +22 -0
- package/dist-server/server/browser-bundle-release.js +8 -7
- package/dist-server/server/browser-engine.js +1 -1
- package/dist-server/server/channel-queue.js +58 -0
- package/dist-server/server/checkpoints.js +9 -5
- package/dist-server/server/chief-of-staff.js +5 -2
- package/dist-server/server/computer-wait.js +33 -0
- package/dist-server/server/config.js +58 -3
- package/dist-server/server/contracts.js +0 -7
- package/dist-server/server/delta-context.js +258 -0
- package/dist-server/server/drivers/acp/gemini.js +11 -1
- package/dist-server/server/drivers/acp/qwen.js +16 -1
- package/dist-server/server/drivers/agents-proxy.js +32 -4
- package/dist-server/server/drivers/claude.js +26 -8
- package/dist-server/server/drivers/codex.js +79 -6
- package/dist-server/server/drivers/pi.js +2 -1
- package/dist-server/server/env-path.js +6 -1
- package/dist-server/server/incidents.js +104 -0
- package/dist-server/server/index.js +886 -134
- package/dist-server/server/local-routing.js +10 -4
- package/dist-server/server/notify.js +3 -1
- package/dist-server/server/peer-roster.js +37 -1
- package/dist-server/server/recent-work.js +4 -1
- package/dist-server/server/redact.js +5 -48
- package/dist-server/server/room-handoffs.js +79 -16
- package/dist-server/server/skill-fetch.js +1 -1
- package/dist-server/server/steer-queue.js +29 -0
- package/dist-server/server/store.js +43 -3
- package/dist-server/server/thread-retention.js +50 -0
- package/dist-server/server/turn-context.js +7 -0
- package/dist-server/server/turn-resources.js +6 -0
- package/dist-server/shared/approval-mode.js +8 -5
- package/dist-server/shared/inspector.js +1 -0
- package/dist-server/shared/json.js +1 -0
- package/dist-server/shared/notification.js +1 -0
- package/dist-server/shared/redact.js +61 -0
- package/dist-server/shared/routines.js +1 -0
- package/dist-server/shared/runtime-events.js +1 -0
- package/dist-server/shared/webhooks.js +1 -0
- package/dist-server/shared/wire.js +8 -0
- package/dist-server/vps-container-mcp.js +20 -4
- package/package.json +1 -1
- package/dist/assets/index-BLLsDK2F.js +0 -309
package/dist-server/pair-cli.js
CHANGED
|
@@ -17568,15 +17568,23 @@ var init_image_generation = __esm({
|
|
|
17568
17568
|
}
|
|
17569
17569
|
});
|
|
17570
17570
|
|
|
17571
|
+
// shared/wire.ts
|
|
17572
|
+
var EFFORT_LEVELS;
|
|
17573
|
+
var init_wire = __esm({
|
|
17574
|
+
"shared/wire.ts"() {
|
|
17575
|
+
"use strict";
|
|
17576
|
+
EFFORT_LEVELS = ["none", "low", "medium", "high", "xhigh", "max"];
|
|
17577
|
+
}
|
|
17578
|
+
});
|
|
17579
|
+
|
|
17571
17580
|
// server/contracts.ts
|
|
17572
17581
|
function isModelVariant(value) {
|
|
17573
17582
|
return typeof value === "string" && value.length > 0 && value.length <= 256 && value.trim() === value && !new RegExp("\\p{Cc}", "u").test(value);
|
|
17574
17583
|
}
|
|
17575
|
-
var
|
|
17584
|
+
var eventCounter, newEventId, newId;
|
|
17576
17585
|
var init_contracts = __esm({
|
|
17577
17586
|
"server/contracts.ts"() {
|
|
17578
17587
|
"use strict";
|
|
17579
|
-
EFFORT_LEVELS = ["none", "low", "medium", "high", "xhigh", "max"];
|
|
17580
17588
|
eventCounter = 0;
|
|
17581
17589
|
newEventId = () => `ev-${Date.now().toString(36)}-${(eventCounter++).toString(36)}`;
|
|
17582
17590
|
newId = () => crypto.randomUUID();
|
|
@@ -17863,6 +17871,17 @@ function saveConfig(patch, options = {}) {
|
|
|
17863
17871
|
}
|
|
17864
17872
|
disk.instances = diskInstances;
|
|
17865
17873
|
}
|
|
17874
|
+
if (checkedPatch.openaiCompat?.url !== void 0 && checkedPatch.instances?.openaiCompat === void 0) {
|
|
17875
|
+
const instances = jsonObjectSchema.safeParse(disk.instances);
|
|
17876
|
+
const entry = jsonObjectSchema.safeParse(instances.success ? instances.data.openaiCompat : void 0);
|
|
17877
|
+
const config2 = jsonObjectSchema.safeParse(entry.success ? entry.data.config : void 0);
|
|
17878
|
+
const environment = jsonObjectSchema.safeParse(entry.success ? entry.data.environment : void 0);
|
|
17879
|
+
if (entry.success && entry.data.driver === "openai-compat" && config2.success && !config2.data.key && (!config2.data.apiKeyEnv || config2.data.apiKeyEnv === "OPENAI_COMPAT_API_KEY") && !(environment.success && Object.hasOwn(environment.data, "OPENAI_COMPAT_API_KEY"))) {
|
|
17880
|
+
const nextConfig = { ...config2.data };
|
|
17881
|
+
delete nextConfig.url;
|
|
17882
|
+
disk.instances.openaiCompat = { ...entry.data, config: nextConfig };
|
|
17883
|
+
}
|
|
17884
|
+
}
|
|
17866
17885
|
mkdirSync6(DATA_DIR, { recursive: true });
|
|
17867
17886
|
writeFileAtomic(p, JSON.stringify(disk, null, 2), { mode: 384 });
|
|
17868
17887
|
}
|
|
@@ -17937,13 +17956,14 @@ function instanceConfigs(cfg) {
|
|
|
17937
17956
|
}
|
|
17938
17957
|
return map3;
|
|
17939
17958
|
}
|
|
17940
|
-
var optionalText, SSH_ALIAS, LEGACY_BROWSER_PROFILE_ID, BROWSER_PROFILE_ID, MIN_ROOM_TURN_TIMEOUT_MINUTES, MAX_ROOM_TURN_TIMEOUT_MINUTES, MAX_CONCURRENT_BOT_THREADS, MIN_THREAD_EVENT_LOG_BYTES, MAX_THREAD_EVENT_LOG_BYTES, MIN_LOCAL_VM_MAX_INSTANCES, MAX_LOCAL_VM_MAX_INSTANCES, vpsConfigSchema, roomConfigSchema, localVmConfigSchema, browserProfileSchema, legacyBrowserProfileSchema, legacyBrowserProfilesSchema, storedBrowserProfilesSchema, browserProfilesSchema, featureConfigSchema, onboardingConfigSchema, instanceConfigSchema, instanceConfigMapSchema, defaultModelSelectionSchema, appConfigSchema, storedAppConfigSchema, appConfigPatchSchema, jsonObjectSchema, DATA_DIR, LEGACY_DATA_DIR, EVENTS_DIR, NATIVE_DIR, WORKSPACE_CREDENTIAL_ENV, PROVIDER_CREDENTIAL_ENV;
|
|
17959
|
+
var optionalText, SSH_ALIAS, LEGACY_BROWSER_PROFILE_ID, BROWSER_PROFILE_ID, MIN_ROOM_TURN_TIMEOUT_MINUTES, MAX_ROOM_TURN_TIMEOUT_MINUTES, DEFAULT_ROOM_HANDOFF_LIFETIME_MINUTES, DEFAULT_ROOM_HANDOFF_MIN_RUNWAY_MINUTES, DEFAULT_ROOM_HANDOFF_HARD_CAP_MINUTES, MAX_CONCURRENT_BOT_THREADS, MIN_THREAD_EVENT_LOG_BYTES, MAX_THREAD_EVENT_LOG_BYTES, MIN_LOCAL_VM_MAX_INSTANCES, MAX_LOCAL_VM_MAX_INSTANCES, vpsConfigSchema, roomConfigSchema, localVmConfigSchema, browserProfileSchema, legacyBrowserProfileSchema, legacyBrowserProfilesSchema, storedBrowserProfilesSchema, browserProfilesSchema, featureConfigSchema, onboardingConfigSchema, instanceConfigSchema, instanceConfigMapSchema, defaultModelSelectionSchema, appConfigSchema, storedAppConfigSchema, appConfigPatchSchema, jsonObjectSchema, DATA_DIR, LEGACY_DATA_DIR, EVENTS_DIR, NATIVE_DIR, WORKSPACE_CREDENTIAL_ENV, PROVIDER_CREDENTIAL_ENV;
|
|
17941
17960
|
var init_config = __esm({
|
|
17942
17961
|
"server/config.ts"() {
|
|
17943
17962
|
"use strict";
|
|
17944
17963
|
init_zod();
|
|
17945
17964
|
init_image_generation();
|
|
17946
17965
|
init_atomic();
|
|
17966
|
+
init_wire();
|
|
17947
17967
|
init_contracts();
|
|
17948
17968
|
init_mcp_registry();
|
|
17949
17969
|
init_schema();
|
|
@@ -17953,6 +17973,9 @@ var init_config = __esm({
|
|
|
17953
17973
|
BROWSER_PROFILE_ID = /^[a-z0-9_-]{1,40}$/;
|
|
17954
17974
|
MIN_ROOM_TURN_TIMEOUT_MINUTES = 1;
|
|
17955
17975
|
MAX_ROOM_TURN_TIMEOUT_MINUTES = 1440;
|
|
17976
|
+
DEFAULT_ROOM_HANDOFF_LIFETIME_MINUTES = 30;
|
|
17977
|
+
DEFAULT_ROOM_HANDOFF_MIN_RUNWAY_MINUTES = 10;
|
|
17978
|
+
DEFAULT_ROOM_HANDOFF_HARD_CAP_MINUTES = 240;
|
|
17956
17979
|
MAX_CONCURRENT_BOT_THREADS = 10;
|
|
17957
17980
|
MIN_THREAD_EVENT_LOG_BYTES = 256 * 1024;
|
|
17958
17981
|
MAX_THREAD_EVENT_LOG_BYTES = 4 * 1024 * 1024 * 1024;
|
|
@@ -17964,8 +17987,16 @@ var init_config = __esm({
|
|
|
17964
17987
|
}).optional()
|
|
17965
17988
|
});
|
|
17966
17989
|
roomConfigSchema = external_exports.object({
|
|
17967
|
-
turnTimeoutMinutes: external_exports.number().int().min(MIN_ROOM_TURN_TIMEOUT_MINUTES).max(MAX_ROOM_TURN_TIMEOUT_MINUTES)
|
|
17968
|
-
|
|
17990
|
+
turnTimeoutMinutes: external_exports.number().int().min(MIN_ROOM_TURN_TIMEOUT_MINUTES).max(MAX_ROOM_TURN_TIMEOUT_MINUTES),
|
|
17991
|
+
/** Room handoff tree lifetime. Active execution pauses this clock; the
|
|
17992
|
+
* hard cap is wall-clock and bounds trees that never stop executing. */
|
|
17993
|
+
handoffLifetimeMinutes: external_exports.number().int().min(1).max(MAX_ROOM_TURN_TIMEOUT_MINUTES).optional(),
|
|
17994
|
+
handoffMinRunwayMinutes: external_exports.number().int().min(1).max(MAX_ROOM_TURN_TIMEOUT_MINUTES).optional(),
|
|
17995
|
+
handoffHardCapMinutes: external_exports.number().int().min(1).max(7 * MAX_ROOM_TURN_TIMEOUT_MINUTES).optional()
|
|
17996
|
+
}).refine(
|
|
17997
|
+
(rooms) => (rooms.handoffMinRunwayMinutes ?? DEFAULT_ROOM_HANDOFF_MIN_RUNWAY_MINUTES) <= (rooms.handoffLifetimeMinutes ?? DEFAULT_ROOM_HANDOFF_LIFETIME_MINUTES) && (rooms.handoffLifetimeMinutes ?? DEFAULT_ROOM_HANDOFF_LIFETIME_MINUTES) <= (rooms.handoffHardCapMinutes ?? DEFAULT_ROOM_HANDOFF_HARD_CAP_MINUTES),
|
|
17998
|
+
{ message: "rooms handoff bounds must satisfy handoffMinRunwayMinutes <= handoffLifetimeMinutes <= handoffHardCapMinutes" }
|
|
17999
|
+
);
|
|
17969
18000
|
localVmConfigSchema = external_exports.object({
|
|
17970
18001
|
mode: external_exports.enum(["shared", "per-bot"]).optional(),
|
|
17971
18002
|
maxInstances: external_exports.number().int().min(MIN_LOCAL_VM_MAX_INSTANCES).max(MAX_LOCAL_VM_MAX_INSTANCES).optional()
|
|
@@ -18137,7 +18168,10 @@ var init_config = __esm({
|
|
|
18137
18168
|
maxConcurrentPerBot: external_exports.number().int().min(1).max(MAX_CONCURRENT_BOT_THREADS),
|
|
18138
18169
|
/** Cap each per-thread events/ and native/ NDJSON log at this many
|
|
18139
18170
|
* bytes; absent (the default) keeps today's unbounded growth (#1280). */
|
|
18140
|
-
eventLogMaxBytes: external_exports.number().int().min(MIN_THREAD_EVENT_LOG_BYTES).max(MAX_THREAD_EVENT_LOG_BYTES).optional()
|
|
18171
|
+
eventLogMaxBytes: external_exports.number().int().min(MIN_THREAD_EVENT_LOG_BYTES).max(MAX_THREAD_EVENT_LOG_BYTES).optional(),
|
|
18172
|
+
/** Days a closed or archived thread's event logs survive (#1280).
|
|
18173
|
+
* Absent keeps them forever. */
|
|
18174
|
+
eventLogRetentionDays: external_exports.number().int().min(1).max(3650).optional()
|
|
18141
18175
|
}).strict().optional(),
|
|
18142
18176
|
localVm: localVmConfigSchema.optional(),
|
|
18143
18177
|
features: featureConfigSchema.optional(),
|
|
@@ -18246,7 +18280,7 @@ function ownerPredatesThisBoot(owner) {
|
|
|
18246
18280
|
return false;
|
|
18247
18281
|
}
|
|
18248
18282
|
function ownerIsAlive(owner) {
|
|
18249
|
-
return !ownerPredatesThisBoot(owner) && processIsAlive2(owner.pid);
|
|
18283
|
+
return !ownerPredatesThisBoot(owner) && processIsAlive2(owner.pid) && ownerIdentityMatches(owner);
|
|
18250
18284
|
}
|
|
18251
18285
|
function isLeaseOwner(value) {
|
|
18252
18286
|
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
@@ -18296,6 +18330,51 @@ function processIsAlive2(pid) {
|
|
|
18296
18330
|
throw leaseError("OpenMausBot could not verify the data-directory lease owner; refusing to start.", error51);
|
|
18297
18331
|
}
|
|
18298
18332
|
}
|
|
18333
|
+
function parseWmiDateTime(value) {
|
|
18334
|
+
const raw = String(value).trim();
|
|
18335
|
+
const match = /^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})\.(\d{6})([+-]\d{3})$/.exec(raw);
|
|
18336
|
+
if (!match) return null;
|
|
18337
|
+
const [_, year, month, day, hour, minute, second, micro, offset] = match;
|
|
18338
|
+
const ms = Date.UTC(
|
|
18339
|
+
Number(year),
|
|
18340
|
+
Number(month) - 1,
|
|
18341
|
+
Number(day),
|
|
18342
|
+
Number(hour),
|
|
18343
|
+
Number(minute),
|
|
18344
|
+
Number(second),
|
|
18345
|
+
Math.floor(Number(micro) / 1e3)
|
|
18346
|
+
);
|
|
18347
|
+
const offsetMinutes = Number(offset);
|
|
18348
|
+
return ms - offsetMinutes * 60 * 1e3;
|
|
18349
|
+
}
|
|
18350
|
+
function processCreationTimeMs(pid) {
|
|
18351
|
+
if (process.platform !== "win32") return null;
|
|
18352
|
+
try {
|
|
18353
|
+
const output = execFileSync2(
|
|
18354
|
+
"wmic",
|
|
18355
|
+
["process", "where", `ProcessId=${pid}`, "get", "CreationDate", "/format:csv"],
|
|
18356
|
+
{ encoding: "utf8", timeout: 5e3, stdio: ["ignore", "pipe", "ignore"] }
|
|
18357
|
+
);
|
|
18358
|
+
for (const line of output.split(/\r?\n/)) {
|
|
18359
|
+
const trimmed = line.trim();
|
|
18360
|
+
if (!trimmed) continue;
|
|
18361
|
+
const lower = trimmed.toLowerCase();
|
|
18362
|
+
if (lower === "node,creationdate" || lower.startsWith("node,")) continue;
|
|
18363
|
+
const parts = trimmed.split(",");
|
|
18364
|
+
const raw = parts[parts.length - 1].trim();
|
|
18365
|
+
const parsed = parseWmiDateTime(raw);
|
|
18366
|
+
if (parsed !== null) return parsed;
|
|
18367
|
+
}
|
|
18368
|
+
} catch {
|
|
18369
|
+
}
|
|
18370
|
+
return null;
|
|
18371
|
+
}
|
|
18372
|
+
function ownerIdentityMatches(owner) {
|
|
18373
|
+
if (process.platform !== "win32") return true;
|
|
18374
|
+
const created = processCreationTimeMs(owner.pid);
|
|
18375
|
+
if (created === null) return true;
|
|
18376
|
+
return created < owner.createdAt;
|
|
18377
|
+
}
|
|
18299
18378
|
function unlinkExact(path3, message2) {
|
|
18300
18379
|
try {
|
|
18301
18380
|
unlinkSync2(path3);
|
|
@@ -18701,7 +18780,8 @@ function parseCmdShim(shim, env) {
|
|
|
18701
18780
|
return null;
|
|
18702
18781
|
}
|
|
18703
18782
|
const dir = dirname4(shim);
|
|
18704
|
-
const
|
|
18783
|
+
const npmEntry = /^SET "NP[MX]_CLI_JS=%~dp0\\([^"]+)"/im.exec(text4);
|
|
18784
|
+
const targets = [...npmEntry ? [npmEntry] : [], ...text4.matchAll(/"%~?dp0%?\\?([^"]+)"/g)].map((m) => join8(dir, m[1])).filter((p) => isFile(p) && basename2(p).toLowerCase() !== "node.exe");
|
|
18705
18785
|
const script = targets.find((p) => /\.[cm]?js$/i.test(p));
|
|
18706
18786
|
if (script) {
|
|
18707
18787
|
const node = nodeExe(dir, env);
|
|
@@ -19574,9 +19654,9 @@ var init_local_inject = __esm({
|
|
|
19574
19654
|
// shared/approval-mode.ts
|
|
19575
19655
|
function supportsApprovalMode(driverKind, mode) {
|
|
19576
19656
|
if (mode === "custom") return driverKind === "codex";
|
|
19577
|
-
if (mode === "edits") return ["claudeAgent", "grokAgent", "antigravityAgent"].includes(driverKind ?? "");
|
|
19657
|
+
if (mode === "edits") return ["claudeAgent", "grokAgent", "antigravityAgent", "qwenAgent", "geminiAgent"].includes(driverKind ?? "");
|
|
19578
19658
|
if (mode !== "full") return true;
|
|
19579
|
-
return ["codex", "claudeAgent", "antigravityAgent", "cursorAgent", "grokAgent", "opencodeGo"].includes(driverKind ?? "");
|
|
19659
|
+
return ["codex", "claudeAgent", "antigravityAgent", "cursorAgent", "grokAgent", "opencodeGo", "qwenAgent", "geminiAgent"].includes(driverKind ?? "");
|
|
19580
19660
|
}
|
|
19581
19661
|
var init_approval_mode = __esm({
|
|
19582
19662
|
"shared/approval-mode.ts"() {
|
|
@@ -19584,12 +19664,7 @@ var init_approval_mode = __esm({
|
|
|
19584
19664
|
}
|
|
19585
19665
|
});
|
|
19586
19666
|
|
|
19587
|
-
//
|
|
19588
|
-
function isSecretName(name) {
|
|
19589
|
-
const lower = name.toLowerCase();
|
|
19590
|
-
if (SECRET_KEY_PARTS.some((part) => lower.includes(part))) return true;
|
|
19591
|
-
return /(^|[_.-])keys?$/.test(lower);
|
|
19592
|
-
}
|
|
19667
|
+
// shared/redact.ts
|
|
19593
19668
|
function redactSecretsInText(text4) {
|
|
19594
19669
|
if (!text4 || text4.length < 8) return text4;
|
|
19595
19670
|
let out = text4;
|
|
@@ -19604,33 +19679,10 @@ ${close}`);
|
|
|
19604
19679
|
out = out.replace(URL_USERINFO, (_m, lead, secret, at) => `${lead}${mask(secret)}${at}`);
|
|
19605
19680
|
return out;
|
|
19606
19681
|
}
|
|
19607
|
-
|
|
19608
|
-
if (typeof input === "string") return redactSecretsInText(input);
|
|
19609
|
-
if (depth > 12 || input === null || typeof input !== "object") return input;
|
|
19610
|
-
if (Array.isArray(input)) {
|
|
19611
|
-
return input.map((item) => {
|
|
19612
|
-
if (item !== null && typeof item === "object" && !Array.isArray(item) && typeof item.name === "string" && typeof item.value === "string") {
|
|
19613
|
-
const entry = item;
|
|
19614
|
-
return isSecretName(entry.name) ? { ...entry, value: mask(entry.value) } : { ...entry, value: redactSecretsInText(entry.value) };
|
|
19615
|
-
}
|
|
19616
|
-
return redactSecrets(item, depth + 1);
|
|
19617
|
-
});
|
|
19618
|
-
}
|
|
19619
|
-
const out = {};
|
|
19620
|
-
for (const [key, value] of Object.entries(input)) {
|
|
19621
|
-
if (typeof value === "string" && isSecretName(key)) {
|
|
19622
|
-
out[key] = mask(value);
|
|
19623
|
-
continue;
|
|
19624
|
-
}
|
|
19625
|
-
out[key] = redactSecrets(value, depth + 1);
|
|
19626
|
-
}
|
|
19627
|
-
return out;
|
|
19628
|
-
}
|
|
19629
|
-
var SECRET_KEY_PARTS, REDACTION_MARKER, mask, KEY_PREFIXES, BEARER, PEM_BLOCK, KEY_VALUE, KEY_SUFFIX_ASSIGNMENT, SECRET_FLAG, URL_USERINFO;
|
|
19682
|
+
var REDACTION_MARKER, mask, KEY_PREFIXES, BEARER, PEM_BLOCK, KEY_VALUE, KEY_SUFFIX_ASSIGNMENT, SECRET_FLAG, URL_USERINFO;
|
|
19630
19683
|
var init_redact = __esm({
|
|
19631
|
-
"
|
|
19684
|
+
"shared/redact.ts"() {
|
|
19632
19685
|
"use strict";
|
|
19633
|
-
SECRET_KEY_PARTS = ["token", "secret", "password", "passwd", "apikey", "api_key", "authorization", "auth_token"];
|
|
19634
19686
|
REDACTION_MARKER = /^«redacted \d+ chars»$/;
|
|
19635
19687
|
mask = (value) => REDACTION_MARKER.test(value) ? value : `\xABredacted ${value.length} chars\xBB`;
|
|
19636
19688
|
KEY_PREFIXES = [
|
|
@@ -19668,6 +19720,44 @@ var init_redact = __esm({
|
|
|
19668
19720
|
}
|
|
19669
19721
|
});
|
|
19670
19722
|
|
|
19723
|
+
// server/redact.ts
|
|
19724
|
+
function isSecretName(name) {
|
|
19725
|
+
const lower = name.toLowerCase();
|
|
19726
|
+
if (SECRET_KEY_PARTS.some((part) => lower.includes(part))) return true;
|
|
19727
|
+
return /(^|[_.-])keys?$/.test(lower);
|
|
19728
|
+
}
|
|
19729
|
+
function redactSecrets(input, depth = 0) {
|
|
19730
|
+
if (typeof input === "string") return redactSecretsInText(input);
|
|
19731
|
+
if (depth > 12 || input === null || typeof input !== "object") return input;
|
|
19732
|
+
if (Array.isArray(input)) {
|
|
19733
|
+
return input.map((item) => {
|
|
19734
|
+
if (item !== null && typeof item === "object" && !Array.isArray(item) && typeof item.name === "string" && typeof item.value === "string") {
|
|
19735
|
+
const entry = item;
|
|
19736
|
+
return isSecretName(entry.name) ? { ...entry, value: mask(entry.value) } : { ...entry, value: redactSecretsInText(entry.value) };
|
|
19737
|
+
}
|
|
19738
|
+
return redactSecrets(item, depth + 1);
|
|
19739
|
+
});
|
|
19740
|
+
}
|
|
19741
|
+
const out = {};
|
|
19742
|
+
for (const [key, value] of Object.entries(input)) {
|
|
19743
|
+
if (typeof value === "string" && isSecretName(key)) {
|
|
19744
|
+
out[key] = mask(value);
|
|
19745
|
+
continue;
|
|
19746
|
+
}
|
|
19747
|
+
out[key] = redactSecrets(value, depth + 1);
|
|
19748
|
+
}
|
|
19749
|
+
return out;
|
|
19750
|
+
}
|
|
19751
|
+
var SECRET_KEY_PARTS;
|
|
19752
|
+
var init_redact2 = __esm({
|
|
19753
|
+
"server/redact.ts"() {
|
|
19754
|
+
"use strict";
|
|
19755
|
+
init_redact();
|
|
19756
|
+
init_redact();
|
|
19757
|
+
SECRET_KEY_PARTS = ["token", "secret", "password", "passwd", "apikey", "api_key", "authorization", "auth_token"];
|
|
19758
|
+
}
|
|
19759
|
+
});
|
|
19760
|
+
|
|
19671
19761
|
// server/thread-log-rotation.ts
|
|
19672
19762
|
import { closeSync as closeSync4, fstatSync, openSync as openSync4, readSync as readSync2, renameSync as renameSync5, rmSync as rmSync4, statSync as statSync3, writeSync } from "node:fs";
|
|
19673
19763
|
function currentThreadLogCap() {
|
|
@@ -19753,7 +19843,7 @@ var init_native = __esm({
|
|
|
19753
19843
|
"server/drivers/native.ts"() {
|
|
19754
19844
|
"use strict";
|
|
19755
19845
|
init_config();
|
|
19756
|
-
|
|
19846
|
+
init_redact2();
|
|
19757
19847
|
init_thread_log_rotation();
|
|
19758
19848
|
}
|
|
19759
19849
|
});
|
|
@@ -19816,7 +19906,7 @@ var QUESTION_LIMIT, LIMIT, cut;
|
|
|
19816
19906
|
var init_tool_summary = __esm({
|
|
19817
19907
|
"server/tool-summary.ts"() {
|
|
19818
19908
|
"use strict";
|
|
19819
|
-
|
|
19909
|
+
init_redact2();
|
|
19820
19910
|
QUESTION_LIMIT = 300;
|
|
19821
19911
|
LIMIT = 200;
|
|
19822
19912
|
cut = (text4, limit) => redactSecretsInText(text4).trim().slice(0, limit);
|
|
@@ -23360,7 +23450,10 @@ var init_claude = __esm({
|
|
|
23360
23450
|
const turnId = logicalTurnId ?? newId();
|
|
23361
23451
|
const retryAbort = new AbortController();
|
|
23362
23452
|
const retry = retryState.get(threadId) ?? { attempt: 0, cancelled: false };
|
|
23363
|
-
if (!relaunch)
|
|
23453
|
+
if (!relaunch) {
|
|
23454
|
+
retry.cancelled = false;
|
|
23455
|
+
retry.rebuilt = false;
|
|
23456
|
+
}
|
|
23364
23457
|
retryState.set(threadId, retry);
|
|
23365
23458
|
const retryScale = Number(process.env.FAKE_CLAUDE_RETRY_SCALE ?? "1");
|
|
23366
23459
|
const sessionId = typeof turn.resumeCursor === "string" ? turn.resumeCursor : null;
|
|
@@ -23688,7 +23781,7 @@ var init_claude = __esm({
|
|
|
23688
23781
|
session.sawInit = true;
|
|
23689
23782
|
session.nativePermissionMode = typeof o.permissionMode === "string" ? o.permissionMode : null;
|
|
23690
23783
|
if (typeof o.session_id === "string") session.sessionId = o.session_id;
|
|
23691
|
-
emit({ ...base2(threadId, currentTurnId()), type: "session.started", sessionId: o.session_id, model: o.model });
|
|
23784
|
+
emit({ ...base2(threadId, currentTurnId()), type: "session.started", sessionId: o.session_id, model: o.model, ...retry.rebuilt ? { rebuilt: true } : {} });
|
|
23692
23785
|
} else if (o.subtype === "thinking_tokens") {
|
|
23693
23786
|
emit({ ...base2(threadId, currentTurnId()), type: "item.updated", itemType: "reasoning", tokens: o.estimated_tokens });
|
|
23694
23787
|
}
|
|
@@ -23715,11 +23808,12 @@ var init_claude = __esm({
|
|
|
23715
23808
|
break;
|
|
23716
23809
|
}
|
|
23717
23810
|
if (text4.trim()) {
|
|
23811
|
+
const synthetic = o.is_api_error_message === true || typeof o.error === "string" ? { synthetic: true } : {};
|
|
23718
23812
|
if (!session.turn?.sawStreamDelta) {
|
|
23719
|
-
emit({ ...base2(threadId, currentTurnId()), type: "content.delta", streamKind: "assistant_text", delta: text4 });
|
|
23813
|
+
emit({ ...base2(threadId, currentTurnId()), ...synthetic, type: "content.delta", streamKind: "assistant_text", delta: text4 });
|
|
23720
23814
|
}
|
|
23721
23815
|
if (session.turn) session.turn.sawStreamDelta = false;
|
|
23722
|
-
emit({ ...base2(threadId, currentTurnId()), type: "item.completed", itemType: "assistant_text", text: text4 });
|
|
23816
|
+
emit({ ...base2(threadId, currentTurnId()), ...synthetic, type: "item.completed", itemType: "assistant_text", text: text4 });
|
|
23723
23817
|
}
|
|
23724
23818
|
for (const b of Array.isArray(msg.content) ? msg.content : []) {
|
|
23725
23819
|
if (b.type === "tool_use") {
|
|
@@ -23901,6 +23995,7 @@ var init_claude = __esm({
|
|
|
23901
23995
|
}
|
|
23902
23996
|
sessions.delete(threadId);
|
|
23903
23997
|
session.turn = null;
|
|
23998
|
+
retry2.rebuilt = recovery.replayed;
|
|
23904
23999
|
retryState.set(threadId, retry2);
|
|
23905
24000
|
active.set(threadId, { stop: () => {
|
|
23906
24001
|
retry2.cancelled = true;
|
|
@@ -23968,8 +24063,8 @@ var init_claude = __esm({
|
|
|
23968
24063
|
};
|
|
23969
24064
|
const steer = async (threadId, text4) => {
|
|
23970
24065
|
const s = sessions.get(threadId);
|
|
23971
|
-
if (!s || !s.turn || s.turn.settled || s.closing || s.child.exitCode !== null) return
|
|
23972
|
-
return writeUser(s, threadId, claudeUserMessage(text4, void 0));
|
|
24066
|
+
if (!s || !s.turn || s.turn.settled || s.closing || s.child.exitCode !== null) return "refused";
|
|
24067
|
+
return await writeUser(s, threadId, claudeUserMessage(text4, void 0)) ? "steered" : "refused";
|
|
23973
24068
|
};
|
|
23974
24069
|
const login = new ClaudeLoginController({ cli: config2.cli, environment, onAuthenticated: async () => {
|
|
23975
24070
|
await refreshModels();
|
|
@@ -24066,6 +24161,15 @@ var init_claude = __esm({
|
|
|
24066
24161
|
nativeImageInput: true,
|
|
24067
24162
|
effortLevels: ["low", "medium", "high", "xhigh", "max"],
|
|
24068
24163
|
queueing: true,
|
|
24164
|
+
// Only while this CLI can be told to refresh a resumed session's
|
|
24165
|
+
// recorded system prompt (--system-prompt-snapshot). Keeping a
|
|
24166
|
+
// session across an update from outside it means the harness keeps
|
|
24167
|
+
// its prompt too; an older CLI would answer a delegated return with
|
|
24168
|
+
// the instructions of the turn that started the session, where a
|
|
24169
|
+
// fresh session rebuilt them. Unknown version: not yet.
|
|
24170
|
+
get strictResume() {
|
|
24171
|
+
return cliVersionChecked && cliVersion !== null && claudeCliSupports(cliVersion, "--system-prompt-snapshot");
|
|
24172
|
+
},
|
|
24069
24173
|
// Harness turns reassert a per-bot mode and restore the broker even
|
|
24070
24174
|
// when an old instance was configured with bypassPermissions.
|
|
24071
24175
|
localComputerMcp: true
|
|
@@ -25482,9 +25586,23 @@ var init_codex = __esm({
|
|
|
25482
25586
|
return stopped;
|
|
25483
25587
|
});
|
|
25484
25588
|
let completeStoppedTurn;
|
|
25589
|
+
let interruptRequested = false;
|
|
25485
25590
|
const stop = async () => {
|
|
25486
25591
|
stopRequested = true;
|
|
25487
25592
|
stopSignal.abort();
|
|
25593
|
+
if (!state.settled && !interruptRequested && codexThreadId && codexTurnId && child.exitCode === null && child.signalCode === null) {
|
|
25594
|
+
interruptRequested = true;
|
|
25595
|
+
const graceMs = Math.max(1, Number(process.env.FAKE_CODEX_INTERRUPT_GRACE_MS ?? 750) || 750);
|
|
25596
|
+
try {
|
|
25597
|
+
await request("turn/interrupt", { threadId: codexThreadId, turnId: codexTurnId }, graceMs);
|
|
25598
|
+
} catch {
|
|
25599
|
+
}
|
|
25600
|
+
const deadline = Date.now() + graceMs;
|
|
25601
|
+
while (!state.settled && Date.now() < deadline) {
|
|
25602
|
+
await new Promise((wake) => setTimeout(wake, 15));
|
|
25603
|
+
}
|
|
25604
|
+
if (state.settled) return true;
|
|
25605
|
+
}
|
|
25488
25606
|
const stopped = await terminate();
|
|
25489
25607
|
if (stopped) completeStoppedTurn?.();
|
|
25490
25608
|
return stopped;
|
|
@@ -25505,6 +25623,23 @@ var init_codex = __esm({
|
|
|
25505
25623
|
emit({ ...base2(threadId, turnId), type: "runtime.error", message: "codex did not shut down after termination was requested" });
|
|
25506
25624
|
}
|
|
25507
25625
|
};
|
|
25626
|
+
const steerActiveTurn = async (text4) => {
|
|
25627
|
+
if (state.settled || abandoned || stopRequested || !codexThreadId || !codexTurnId) return "refused";
|
|
25628
|
+
if (child.exitCode !== null || child.signalCode !== null) return "refused";
|
|
25629
|
+
try {
|
|
25630
|
+
const steerTimeoutMs = Math.max(1, Number(process.env.FAKE_CODEX_STEER_TIMEOUT_MS ?? 1e4) || 1e4);
|
|
25631
|
+
await request("turn/steer", {
|
|
25632
|
+
threadId: codexThreadId,
|
|
25633
|
+
input: [{ type: "text", text: text4 }],
|
|
25634
|
+
expectedTurnId: codexTurnId
|
|
25635
|
+
}, steerTimeoutMs);
|
|
25636
|
+
return "steered";
|
|
25637
|
+
} catch (error51) {
|
|
25638
|
+
const message2 = error51 instanceof Error ? error51.message : String(error51);
|
|
25639
|
+
if (state.settled || message2.includes("timed out")) return "indeterminate";
|
|
25640
|
+
return "refused";
|
|
25641
|
+
}
|
|
25642
|
+
};
|
|
25508
25643
|
const controlsHost = turn.integrations?.localComputer?.scope === "local-computer";
|
|
25509
25644
|
const handleServerRequest = (msg) => {
|
|
25510
25645
|
const method = msg.method;
|
|
@@ -25794,6 +25929,10 @@ var init_codex = __esm({
|
|
|
25794
25929
|
void stop();
|
|
25795
25930
|
return;
|
|
25796
25931
|
}
|
|
25932
|
+
if (stopRequested) {
|
|
25933
|
+
void settle(false, "interrupted");
|
|
25934
|
+
return;
|
|
25935
|
+
}
|
|
25797
25936
|
const recentStderr = stderrSinceOutput.trim();
|
|
25798
25937
|
const hadStreamedOutput = codexTurnId !== null || state.sawStreamDelta;
|
|
25799
25938
|
const verdict = signal !== null ? { transient: false, reason: "interrupted" } : classifyError({ exitCode: code, stderr: recentStderr });
|
|
@@ -25832,7 +25971,7 @@ var init_codex = __esm({
|
|
|
25832
25971
|
});
|
|
25833
25972
|
void settle(false, "exit_before_result");
|
|
25834
25973
|
});
|
|
25835
|
-
active.set(threadId, { stop, turnId, asks });
|
|
25974
|
+
active.set(threadId, { stop, turnId, asks, steer: steerActiveTurn });
|
|
25836
25975
|
if (attempt === 0) emit({ ...base2(threadId, turnId), type: "turn.started" });
|
|
25837
25976
|
try {
|
|
25838
25977
|
await request("initialize", {
|
|
@@ -25864,6 +26003,7 @@ var init_codex = __esm({
|
|
|
25864
26003
|
const cursor3 = typeof turn.resumeCursor === "string" ? turn.resumeCursor : null;
|
|
25865
26004
|
let startedModel = null;
|
|
25866
26005
|
let resumedNativeThread = false;
|
|
26006
|
+
let rebuiltFromReplay = false;
|
|
25867
26007
|
let promptText = turn.text;
|
|
25868
26008
|
if (cursor3) {
|
|
25869
26009
|
const resumeThread = () => request("thread/resume", {
|
|
@@ -25889,9 +26029,11 @@ var init_codex = __esm({
|
|
|
25889
26029
|
promptSubmitted,
|
|
25890
26030
|
producedOutput: state.sawStreamDelta
|
|
25891
26031
|
});
|
|
25892
|
-
if (!config2.managed || recoveredMissingSession || stopRequested || state.settled || !turn.recoveryText?.trim() || !missingNativeCodexThread(error51, cursor3) || !mayReplay(failure)) throw error51;
|
|
26032
|
+
if (!config2.managed && !turn.recoveryIsReplay || recoveredMissingSession || stopRequested || state.settled || !turn.recoveryText?.trim() || !missingNativeCodexThread(error51, cursor3) || !mayReplay(failure)) throw error51;
|
|
25893
26033
|
recoveredMissingSession = true;
|
|
25894
|
-
|
|
26034
|
+
const rebuild = recoveryPromptFor({ recoveryText: turn.recoveryText, currentText: turn.text, failure });
|
|
26035
|
+
rebuiltFromReplay = rebuild.replayed;
|
|
26036
|
+
promptText = rebuild.text;
|
|
25895
26037
|
}
|
|
25896
26038
|
}
|
|
25897
26039
|
if (!codexThreadId) {
|
|
@@ -25917,7 +26059,7 @@ var init_codex = __esm({
|
|
|
25917
26059
|
}
|
|
25918
26060
|
if (!codexThreadId) throw new Error("Codex did not return a native thread id");
|
|
25919
26061
|
await syncCodexInstructions(threadId, codexThreadId, developerInstructions, resumedNativeThread, request);
|
|
25920
|
-
emit({ ...base2(threadId, turnId), type: "session.started", sessionId: codexThreadId, model: startedModel ?? turn.model ?? null });
|
|
26062
|
+
emit({ ...base2(threadId, turnId), type: "session.started", sessionId: codexThreadId, model: startedModel ?? turn.model ?? null, ...rebuiltFromReplay ? { rebuilt: true } : {} });
|
|
25921
26063
|
const turnInput = [
|
|
25922
26064
|
...promptText ? [{ type: "text", text: promptText }] : [],
|
|
25923
26065
|
...(turn.images ?? []).map((image) => ({ type: "localImage", path: image.path }))
|
|
@@ -26041,6 +26183,7 @@ ${stderr ?? ""}`))
|
|
|
26041
26183
|
provider: DRIVER_KIND3,
|
|
26042
26184
|
capabilities: {
|
|
26043
26185
|
sessionModelSwitch: "unsupported",
|
|
26186
|
+
queueing: true,
|
|
26044
26187
|
computerMcp: true,
|
|
26045
26188
|
localComputerMcp: true,
|
|
26046
26189
|
composioMcp: true,
|
|
@@ -26050,12 +26193,17 @@ ${stderr ?? ""}`))
|
|
|
26050
26193
|
browserMcp: true,
|
|
26051
26194
|
images: true,
|
|
26052
26195
|
nativeImageInput: true,
|
|
26053
|
-
effortLevels: ["low", "medium", "high", "xhigh", "max"]
|
|
26196
|
+
effortLevels: ["low", "medium", "high", "xhigh", "max"],
|
|
26197
|
+
strictResume: true
|
|
26054
26198
|
},
|
|
26055
26199
|
sendTurn,
|
|
26056
26200
|
interruptTurn: async (threadId) => {
|
|
26057
26201
|
await active.get(threadId)?.stop();
|
|
26058
26202
|
},
|
|
26203
|
+
steer: async (threadId, text4) => {
|
|
26204
|
+
const turn = active.get(threadId);
|
|
26205
|
+
return turn?.steer ? await turn.steer(text4) : "refused";
|
|
26206
|
+
},
|
|
26059
26207
|
respondToRequest: async (threadId, requestId, decision) => {
|
|
26060
26208
|
const turn = active.get(threadId);
|
|
26061
26209
|
const finish = turn?.asks.get(requestId);
|
|
@@ -34674,7 +34822,7 @@ var init_openai_chat = __esm({
|
|
|
34674
34822
|
"server/drivers/openai-chat.ts"() {
|
|
34675
34823
|
"use strict";
|
|
34676
34824
|
init_contracts();
|
|
34677
|
-
|
|
34825
|
+
init_redact2();
|
|
34678
34826
|
init_tool_summary();
|
|
34679
34827
|
init_chat_mcp_tools();
|
|
34680
34828
|
init_chat_tool_approval();
|
|
@@ -35013,6 +35161,11 @@ function liveOauthCredential() {
|
|
|
35013
35161
|
function geminiIsAuthenticated(env) {
|
|
35014
35162
|
return nonBlank(env.GEMINI_API_KEY) || nonBlank(env.GOOGLE_API_KEY) || existsSync12(join24(homedir15(), ".gemini", "oauth_creds.json")) && liveOauthCredential();
|
|
35015
35163
|
}
|
|
35164
|
+
function geminiApprovalArgs(fullAuto, approvalMode) {
|
|
35165
|
+
if (fullAuto) return ["--yolo"];
|
|
35166
|
+
if (approvalMode === "edits") return ["--approval-mode", "auto_edit"];
|
|
35167
|
+
return [];
|
|
35168
|
+
}
|
|
35016
35169
|
var AUTH_PREFERENCE, nonBlank, support3, GeminiAgentDriver;
|
|
35017
35170
|
var init_gemini = __esm({
|
|
35018
35171
|
"server/drivers/acp/gemini.ts"() {
|
|
@@ -35035,7 +35188,7 @@ var init_gemini = __esm({
|
|
|
35035
35188
|
loginNote: "Gemini CLI needs a GEMINI_API_KEY, a Vertex AI setup, or an enterprise Code Assist login \u2014 consumer Google logins stopped working on 2026-06-18 (use the Antigravity engine for those accounts)",
|
|
35036
35189
|
// --acp is the stable Gemini CLI surface. --experimental-acp remains an
|
|
35037
35190
|
// alias for older releases, but using it now emits a deprecation warning.
|
|
35038
|
-
spawnArgs: (
|
|
35191
|
+
spawnArgs: (config2, turn) => ["--acp", ...geminiApprovalArgs(config2.fullAuto, turn.approvalMode), ...turn.model ? ["-m", turn.model] : []],
|
|
35039
35192
|
credentialEnv: ["GEMINI_API_KEY", "GOOGLE_API_KEY"],
|
|
35040
35193
|
pickAuthMethod: (methods) => {
|
|
35041
35194
|
const ids = methods.map((m) => m.id).filter((id) => typeof id === "string");
|
|
@@ -36468,6 +36621,12 @@ function resolveQwenTurnModel(model, env) {
|
|
|
36468
36621
|
if (!matches.length) throw new Error("This Qwen model is no longer configured. Refresh models and select it again.");
|
|
36469
36622
|
return matches[0].id;
|
|
36470
36623
|
}
|
|
36624
|
+
function qwenApprovalArgs(fullAuto, approvalMode) {
|
|
36625
|
+
if (fullAuto) return ["--yolo"];
|
|
36626
|
+
if (approvalMode === "auto") return ["--approval-mode", "auto"];
|
|
36627
|
+
if (approvalMode === "edits") return ["--approval-mode", "auto-edit"];
|
|
36628
|
+
return [];
|
|
36629
|
+
}
|
|
36471
36630
|
var EMPTY, PROTOCOLS, support8, QwenAgentDriver;
|
|
36472
36631
|
var init_qwen = __esm({
|
|
36473
36632
|
"server/drivers/acp/qwen.ts"() {
|
|
@@ -36496,7 +36655,7 @@ var init_qwen = __esm({
|
|
|
36496
36655
|
},
|
|
36497
36656
|
// A raw -m only changes the model within the saved provider. ACP switches
|
|
36498
36657
|
// the complete route and confirms it before any prompt leaves OMB.
|
|
36499
|
-
spawnArgs: () => ["--acp"],
|
|
36658
|
+
spawnArgs: (config2, turn) => ["--acp", ...qwenApprovalArgs(config2.fullAuto, turn.approvalMode)],
|
|
36500
36659
|
selectModel: { configId: "model" },
|
|
36501
36660
|
pickAuthMethod: () => null,
|
|
36502
36661
|
authFailure: "continue",
|
|
@@ -44122,6 +44281,7 @@ var init_pi = __esm({
|
|
|
44122
44281
|
init_procs();
|
|
44123
44282
|
init_proxy_paths();
|
|
44124
44283
|
init_tool_summary();
|
|
44284
|
+
init_wire();
|
|
44125
44285
|
init_contracts();
|
|
44126
44286
|
init_local_inject();
|
|
44127
44287
|
init_native();
|
|
@@ -45205,12 +45365,13 @@ var init_browser_bundle_release = __esm({
|
|
|
45205
45365
|
"server/browser-bundle-release.ts"() {
|
|
45206
45366
|
"use strict";
|
|
45207
45367
|
init_browser_engine_release();
|
|
45208
|
-
CHROME_VERSION = "
|
|
45368
|
+
CHROME_VERSION = "153.0.8010.47";
|
|
45209
45369
|
CHROME_ASSETS = {
|
|
45210
|
-
"darwin-arm64": { platform: "mac-arm64", bytes:
|
|
45211
|
-
"darwin-x64": { platform: "mac-x64", bytes:
|
|
45212
|
-
"linux-
|
|
45213
|
-
"
|
|
45370
|
+
"darwin-arm64": { platform: "mac-arm64", bytes: 98668949, sha256: "6d28839675b6f22dbd7ba8775dbdabcae7a5be37b482380b27b12f05b748b955", executableSha256: "111ee425ea5b0a01dcb19fda16452a9be0319749cba374b1c987d2437d8dcedb" },
|
|
45371
|
+
"darwin-x64": { platform: "mac-x64", bytes: 103712919, sha256: "aa178547f9751fbcf413e0f57915ddb72e83064d4d1c4a29dc1719b169f9cc2f", executableSha256: "33452695b1b6f18db2f796a422eca69b69ca8aacce36d1ff8c6f5d69eac1a635" },
|
|
45372
|
+
"linux-arm64": { platform: "linux-arm64", bytes: 120245582, sha256: "af0931a58d6bab688112d5ca1f7abd6d95c0b8a296ef34637f272795787774d7", executableSha256: "b6a9f0483c976fddc72c34ce1c983a1275163cdfb95576874bfed5ff07c53807" },
|
|
45373
|
+
"linux-x64": { platform: "linux64", bytes: 119695587, sha256: "7728775cf4a35464cd81c8eea2d44d6d32ccc0bd1edfa75aea7f32d146963d63", executableSha256: "ea90dee9cbd7b17f197eb6c386bd9f1ff636734ee99753cd2408658c45358bf2" },
|
|
45374
|
+
"win32-x64": { platform: "win64", bytes: 120466147, sha256: "9f405cfaf7bc08bf9e046e653cd3086c0faa1d4e25907de857f7e7f093a20122", executableSha256: "01176f6928faeb37ff018bc8884bbca8a0197f51b659d467f2501ab2c64f9fcf" }
|
|
45214
45375
|
};
|
|
45215
45376
|
}
|
|
45216
45377
|
});
|
|
@@ -45592,7 +45753,7 @@ function agentBrowserIntegration(input) {
|
|
|
45592
45753
|
for (const name of ["PATH", "AGENT_BROWSER_EXECUTABLE_PATH"]) {
|
|
45593
45754
|
if (sourceEnv[name]) env[name] = sourceEnv[name];
|
|
45594
45755
|
}
|
|
45595
|
-
const bundle = packagedBrowser({ env: sourceEnv });
|
|
45756
|
+
const bundle = packagedBrowser({ env: sourceEnv, platform: input.platform, arch: input.arch });
|
|
45596
45757
|
if (!env.AGENT_BROWSER_EXECUTABLE_PATH && bundle && resolve10(input.binaryPath) === bundle.engine && completePackage(bundle, existsSync18)) {
|
|
45597
45758
|
env.AGENT_BROWSER_EXECUTABLE_PATH = bundle.chrome;
|
|
45598
45759
|
}
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
// verdict the app synthesizes is Full access, because that level is the
|
|
8
8
|
// person's explicit, separately confirmed grant to answer every prompt.
|
|
9
9
|
// Questions never come through here: a bot's question always reaches a human.
|
|
10
|
+
import { supportsApprovalMode } from "../shared/approval-mode.js";
|
|
10
11
|
/** A failed delivery is a runtime error, not another permission decision.
|
|
11
12
|
* An expired ask must never become a fresh Allow/Deny card. */
|
|
12
13
|
export async function deliverFullAccessApproval(adapter, threadId, requestId, turnId, isCurrent = () => false) {
|
|
@@ -24,7 +25,9 @@ export async function deliverFullAccessApproval(adapter, threadId, requestId, tu
|
|
|
24
25
|
}
|
|
25
26
|
}
|
|
26
27
|
/** Full access is the person's explicit grant to this receiving bot, including
|
|
27
|
-
* delegated work. It never inherits the sender's mode or elevates another bot
|
|
28
|
+
* delegated work. It never inherits the sender's mode or elevates another bot
|
|
29
|
+
* — with the one exception below (delegationInheritsFullAccess), applied
|
|
30
|
+
* where a Chief's delegated thread is created rather than here.
|
|
28
31
|
* Custom is a provider-config choice rather than an app Full-access grant, so
|
|
29
32
|
* peer-started Custom turns use Auto. Provider support and grant confirmation
|
|
30
33
|
* are checked by the caller. */
|
|
@@ -33,6 +36,17 @@ export function approvalModeForOrigin(mode, origin) {
|
|
|
33
36
|
return "auto";
|
|
34
37
|
return mode;
|
|
35
38
|
}
|
|
39
|
+
/** Whether work a bot hands to a teammate runs with Full access. Only a Chief
|
|
40
|
+
* of Staff passes access on, and only the Full access the person gave it for
|
|
41
|
+
* the conversation it is delegating from: the Chief exists to get the team's
|
|
42
|
+
* work done without the person answering every card, and a teammate stopping
|
|
43
|
+
* that work to ask defeats the grant. The recipient's engine has to implement
|
|
44
|
+
* Full, or the work keeps the recipient's own level. A bot never elevates
|
|
45
|
+
* itself this way. */
|
|
46
|
+
export function delegationInheritsFullAccess(input) {
|
|
47
|
+
return input.senderIsChief && input.senderHasFullAccess && !input.sameBot
|
|
48
|
+
&& supportsApprovalMode(input.recipientDriverKind, "full");
|
|
49
|
+
}
|
|
36
50
|
// Tools that ask a PERSON something. A question exists so that a human
|
|
37
51
|
// decides; any mode answering one on their behalf defeats the only reason
|
|
38
52
|
// it was asked. They normally arrive typed as questions and never reach a
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/** Lazy exclusive claims for auto-resolved Local VM attaches (issue #1361).
|
|
2
|
+
* The table is keyed by thread and owned by the dispatch generation; the
|
|
3
|
+
* claim closure itself lives in index.ts next to the turn state it needs.
|
|
4
|
+
* Kept free of index.ts imports so the fire-once semantics stay unit-testable. */
|
|
5
|
+
/** Fire a thread's lazy claim exactly once, fenced by the dispatch
|
|
6
|
+
* generation. A rejected claim KEEPS the slot and marks it failed: the
|
|
7
|
+
* computer-control gate then keeps answering held for that generation, so
|
|
8
|
+
* the bridge refuses every later screen call instead of forwarding it onto
|
|
9
|
+
* a VM this turn never claimed. `begin` staying set means the claim never
|
|
10
|
+
* re-fires; turn settle (releaseTurnResources / releaseLocalVmThread in
|
|
11
|
+
* index.ts) clears the slot, fenced by owner generation. A rejection
|
|
12
|
+
* mutates only the slot it fired from, so a stale claim can never remove
|
|
13
|
+
* or mark a newer generation's slot on the same thread. */
|
|
14
|
+
export function startAutoVmClaim(table, threadId, generation) {
|
|
15
|
+
const slot = table.get(threadId);
|
|
16
|
+
if (!slot || slot.owner.threadId !== threadId || slot.owner.generation !== generation || slot.begin)
|
|
17
|
+
return;
|
|
18
|
+
slot.begin = slot.claim().then(() => { slot.claimed = true; }, (error) => {
|
|
19
|
+
slot.failed = true;
|
|
20
|
+
slot.failure = error instanceof Error ? error.message : String(error);
|
|
21
|
+
});
|
|
22
|
+
}
|