@adhdev/daemon-standalone 1.0.18-rc.15 → 1.0.18-rc.17
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/index.js
CHANGED
|
@@ -29838,6 +29838,60 @@ var require_dist3 = __commonJS({
|
|
|
29838
29838
|
mod
|
|
29839
29839
|
));
|
|
29840
29840
|
var __toCommonJS2 = (mod) => __copyProps2(__defProp2({}, "__esModule", { value: true }), mod);
|
|
29841
|
+
function isKnownDangerousLaunchArg(arg) {
|
|
29842
|
+
const normalized = arg.trim();
|
|
29843
|
+
if (KNOWN_DANGEROUS_LAUNCH_ARGS.has(normalized)) return true;
|
|
29844
|
+
return normalized.startsWith("--dangerously-skip-permissions=") || normalized.startsWith("--dangerously-bypass-approvals-and-sandbox=");
|
|
29845
|
+
}
|
|
29846
|
+
function deriveAutoApproveModeRisk(mode) {
|
|
29847
|
+
return Array.isArray(mode.launchArgs) && mode.launchArgs.some(isKnownDangerousLaunchArg) ? "dangerous" : mode.risk;
|
|
29848
|
+
}
|
|
29849
|
+
function inactiveMode(modeId = "") {
|
|
29850
|
+
return { active: false, strategy: "pty-parse-default", modeId };
|
|
29851
|
+
}
|
|
29852
|
+
function resolveConfiguredMode(provider, mode, settings) {
|
|
29853
|
+
if (mode.strategy === "post-boot-command") return inactiveMode(mode.id);
|
|
29854
|
+
if (settings?.launchedByCoordinator === true && settings.delegatedWorkerDangerousModeAllow !== true && deriveAutoApproveModeRisk(mode) === "dangerous") {
|
|
29855
|
+
const fallback = provider.autoApproveModes?.modes.find((candidate) => candidate.strategy === "pty-parse-default" && deriveAutoApproveModeRisk(candidate) !== "dangerous");
|
|
29856
|
+
return fallback ? { active: true, strategy: fallback.strategy, modeId: fallback.id } : inactiveMode(mode.id);
|
|
29857
|
+
}
|
|
29858
|
+
return { active: true, strategy: mode.strategy, modeId: mode.id };
|
|
29859
|
+
}
|
|
29860
|
+
function resolveProviderAutoApproveMode(provider, settings) {
|
|
29861
|
+
const config2 = provider.autoApproveModes;
|
|
29862
|
+
const explicitModeId = settings?.autoApproveMode;
|
|
29863
|
+
if (typeof explicitModeId === "string") {
|
|
29864
|
+
const mode = config2?.modes.find((candidate) => candidate.id === explicitModeId);
|
|
29865
|
+
if (!mode) return inactiveMode(explicitModeId);
|
|
29866
|
+
return resolveConfiguredMode(provider, mode, settings);
|
|
29867
|
+
}
|
|
29868
|
+
const explicitLegacy = settings?.autoApprove;
|
|
29869
|
+
const providerLegacyDefault = provider.settings?.autoApprove?.default;
|
|
29870
|
+
const legacyActive = typeof explicitLegacy === "boolean" ? explicitLegacy : typeof providerLegacyDefault === "boolean" ? providerLegacyDefault : false;
|
|
29871
|
+
if (!legacyActive) return inactiveMode();
|
|
29872
|
+
if (!config2) {
|
|
29873
|
+
return { active: true, strategy: "pty-parse-default", modeId: "legacy" };
|
|
29874
|
+
}
|
|
29875
|
+
const defaultMode = config2.modes.find((mode) => mode.id === config2.default);
|
|
29876
|
+
if (!defaultMode) return inactiveMode(config2.default);
|
|
29877
|
+
return resolveConfiguredMode(provider, defaultMode, settings);
|
|
29878
|
+
}
|
|
29879
|
+
function findProviderAutoApproveMode(provider, modeId) {
|
|
29880
|
+
return provider?.autoApproveModes?.modes.find((mode) => mode.id === modeId);
|
|
29881
|
+
}
|
|
29882
|
+
var KNOWN_DANGEROUS_LAUNCH_ARGS;
|
|
29883
|
+
var init_auto_approve_modes = __esm2({
|
|
29884
|
+
"src/providers/auto-approve-modes.ts"() {
|
|
29885
|
+
"use strict";
|
|
29886
|
+
KNOWN_DANGEROUS_LAUNCH_ARGS = /* @__PURE__ */ new Set([
|
|
29887
|
+
"--dangerously-skip-permissions",
|
|
29888
|
+
"--dangerously-bypass-approvals-and-sandbox",
|
|
29889
|
+
"bypassPermissions",
|
|
29890
|
+
"sandbox_mode=danger-full-access",
|
|
29891
|
+
"approval_policy=never"
|
|
29892
|
+
]);
|
|
29893
|
+
}
|
|
29894
|
+
});
|
|
29841
29895
|
function normalizeMeshSchedulingStrategy(value) {
|
|
29842
29896
|
if (typeof value !== "string") return DEFAULT_MESH_SCHEDULING_STRATEGY;
|
|
29843
29897
|
const trimmed = value.trim();
|
|
@@ -29923,6 +29977,11 @@ var require_dist3 = __commonJS({
|
|
|
29923
29977
|
} else {
|
|
29924
29978
|
delete policy.autoConvergeCodeChange;
|
|
29925
29979
|
}
|
|
29980
|
+
if (policy.delegatedWorkerDangerousModeAllow === true) {
|
|
29981
|
+
policy.delegatedWorkerDangerousModeAllow = true;
|
|
29982
|
+
} else {
|
|
29983
|
+
delete policy.delegatedWorkerDangerousModeAllow;
|
|
29984
|
+
}
|
|
29926
29985
|
if (policy.coordinatorIdlePushPolicy === "auto_silent_on_dispatch") {
|
|
29927
29986
|
policy.coordinatorIdlePushPolicy = "auto_silent_on_dispatch";
|
|
29928
29987
|
} else {
|
|
@@ -29930,14 +29989,35 @@ var require_dist3 = __commonJS({
|
|
|
29930
29989
|
}
|
|
29931
29990
|
return policy;
|
|
29932
29991
|
}
|
|
29933
|
-
function resolveDelegatedWorkerAutoApprove(meshPolicy, nodePolicy) {
|
|
29992
|
+
function resolveDelegatedWorkerAutoApprove(meshPolicy, nodePolicy, provider) {
|
|
29993
|
+
let enabled = true;
|
|
29934
29994
|
if (typeof nodePolicy?.delegatedWorkerAutoApprove === "boolean") {
|
|
29935
|
-
|
|
29995
|
+
enabled = nodePolicy.delegatedWorkerAutoApprove;
|
|
29996
|
+
} else if (typeof meshPolicy?.delegatedWorkerAutoApprove === "boolean") {
|
|
29997
|
+
enabled = meshPolicy.delegatedWorkerAutoApprove;
|
|
29936
29998
|
}
|
|
29937
|
-
if (
|
|
29938
|
-
|
|
29999
|
+
if (!enabled) return false;
|
|
30000
|
+
const modes = provider?.autoApproveModes;
|
|
30001
|
+
if (!modes) return true;
|
|
30002
|
+
const defaultMode = modes.modes.find((mode) => mode.id === modes.default);
|
|
30003
|
+
if (!defaultMode || defaultMode.strategy === "post-boot-command") return false;
|
|
30004
|
+
const dangerousAllowed = resolveDelegatedWorkerDangerousModeAllow(meshPolicy, nodePolicy);
|
|
30005
|
+
if (deriveAutoApproveModeRisk(defaultMode) === "dangerous" && !dangerousAllowed) {
|
|
30006
|
+
const ptyFallback = modes.modes.find((mode) => mode.strategy === "pty-parse-default" && deriveAutoApproveModeRisk(mode) !== "dangerous");
|
|
30007
|
+
return ptyFallback?.id || false;
|
|
29939
30008
|
}
|
|
29940
|
-
return
|
|
30009
|
+
return defaultMode.id;
|
|
30010
|
+
}
|
|
30011
|
+
function resolveDelegatedWorkerDangerousModeAllow(meshPolicy, nodePolicy) {
|
|
30012
|
+
if (typeof nodePolicy?.delegatedWorkerDangerousModeAllow === "boolean") {
|
|
30013
|
+
return nodePolicy.delegatedWorkerDangerousModeAllow;
|
|
30014
|
+
}
|
|
30015
|
+
return meshPolicy?.delegatedWorkerDangerousModeAllow === true;
|
|
30016
|
+
}
|
|
30017
|
+
function delegatedWorkerAutoApproveSettings(meshPolicy, nodePolicy, provider) {
|
|
30018
|
+
const resolved = resolveDelegatedWorkerAutoApprove(meshPolicy, nodePolicy, provider);
|
|
30019
|
+
const delegatedWorkerDangerousModeAllow = resolveDelegatedWorkerDangerousModeAllow(meshPolicy, nodePolicy);
|
|
30020
|
+
return typeof resolved === "string" ? { autoApprove: void 0, autoApproveMode: resolved, delegatedWorkerDangerousModeAllow } : { autoApprove: resolved, autoApproveMode: void 0, delegatedWorkerDangerousModeAllow };
|
|
29941
30021
|
}
|
|
29942
30022
|
function resolveAllowSendKeysDestructive(meshPolicy, nodePolicy) {
|
|
29943
30023
|
if (typeof nodePolicy?.allowSendKeysDestructive === "boolean") {
|
|
@@ -29978,6 +30058,7 @@ var require_dist3 = __commonJS({
|
|
|
29978
30058
|
var init_repo_mesh_types = __esm2({
|
|
29979
30059
|
"src/repo-mesh-types.ts"() {
|
|
29980
30060
|
"use strict";
|
|
30061
|
+
init_auto_approve_modes();
|
|
29981
30062
|
MESH_SCHEDULING_STRATEGIES = [
|
|
29982
30063
|
"first_eligible",
|
|
29983
30064
|
"least_loaded",
|
|
@@ -30005,6 +30086,7 @@ var require_dist3 = __commonJS({
|
|
|
30005
30086
|
// any specific session manually; that override is preserved per-device.
|
|
30006
30087
|
spawnedSessionVisibility: "hidden",
|
|
30007
30088
|
delegatedWorkerAutoApprove: true,
|
|
30089
|
+
delegatedWorkerDangerousModeAllow: false,
|
|
30008
30090
|
sessionCleanupOnNodeRemove: "preserve",
|
|
30009
30091
|
// MAGI auto-launches a worker session per pinned replica target with no idle
|
|
30010
30092
|
// session; those stay idle-LIVE after their turn. Default ON (stop_and_delete)
|
|
@@ -30265,10 +30347,10 @@ var require_dist3 = __commonJS({
|
|
|
30265
30347
|
}
|
|
30266
30348
|
function getDaemonBuildInfo() {
|
|
30267
30349
|
if (cached2) return cached2;
|
|
30268
|
-
const commit = readInjected(true ? "
|
|
30269
|
-
const commitShort = readInjected(true ? "
|
|
30270
|
-
const version2 = readInjected(true ? "1.0.18-rc.
|
|
30271
|
-
const builtAt = readInjected(true ? "2026-07-
|
|
30350
|
+
const commit = readInjected(true ? "eeb3e1474488eb5543c443270208f3ca8958a86a" : void 0) ?? "unknown";
|
|
30351
|
+
const commitShort = readInjected(true ? "eeb3e147" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
|
|
30352
|
+
const version2 = readInjected(true ? "1.0.18-rc.17" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
|
|
30353
|
+
const builtAt = readInjected(true ? "2026-07-23T03:31:27.486Z" : void 0);
|
|
30272
30354
|
cached2 = builtAt ? { commit, commitShort, version: version2, builtAt } : { commit, commitShort, version: version2 };
|
|
30273
30355
|
return cached2;
|
|
30274
30356
|
}
|
|
@@ -46790,7 +46872,11 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
|
|
|
46790
46872
|
meshNodeFor: meshId,
|
|
46791
46873
|
meshNodeId: nodeId,
|
|
46792
46874
|
launchedByCoordinator: true,
|
|
46793
|
-
|
|
46875
|
+
...delegatedWorkerAutoApproveSettings(
|
|
46876
|
+
mesh?.policy,
|
|
46877
|
+
node?.policy,
|
|
46878
|
+
components.providerLoader?.getMeta(providerType)
|
|
46879
|
+
),
|
|
46794
46880
|
...localDaemonId ? { meshCoordinatorDaemonId: localDaemonId } : {},
|
|
46795
46881
|
// COMPLETION-PROPAGATION F5: (re)stamp the coordinator SESSION anchor from THIS
|
|
46796
46882
|
// task's sourceCoordinatorSessionId with PRIORITY — a manually-launched (or reused)
|
|
@@ -47563,8 +47649,12 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
|
|
|
47563
47649
|
spawnedSessionVisibility: mesh?.policy?.spawnedSessionVisibility || "hidden",
|
|
47564
47650
|
// Coordinator-dispatched worker: auto-approve unless mesh/node policy
|
|
47565
47651
|
// opts out (default true). Lands in settingsOverride and beats the
|
|
47566
|
-
// global per-provider-type
|
|
47567
|
-
|
|
47652
|
+
// global per-provider-type boolean/mode through explicit opposite-key clearing.
|
|
47653
|
+
...delegatedWorkerAutoApproveSettings(
|
|
47654
|
+
mesh?.policy,
|
|
47655
|
+
node?.policy,
|
|
47656
|
+
components.providerLoader?.getMeta(resolved.providerType)
|
|
47657
|
+
),
|
|
47568
47658
|
launchedByCoordinator: true,
|
|
47569
47659
|
autoLaunchedForQueueTaskId: task.id
|
|
47570
47660
|
};
|
|
@@ -49165,6 +49255,26 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
|
|
|
49165
49255
|
}
|
|
49166
49256
|
return null;
|
|
49167
49257
|
}
|
|
49258
|
+
function hasTrailingToolActivityAfterFinalAssistant(messages) {
|
|
49259
|
+
if (!Array.isArray(messages) || messages.length === 0) return false;
|
|
49260
|
+
let sawTrailingToolActivity = false;
|
|
49261
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
49262
|
+
const msg = messages[i];
|
|
49263
|
+
if (!msg) continue;
|
|
49264
|
+
const classification = classifyChatMessageVisibility(msg);
|
|
49265
|
+
if (classification.isUserFacing && (msg.role === "assistant" || msg.role === "model")) {
|
|
49266
|
+
if (flattenContent(msg.content).trim()) return sawTrailingToolActivity;
|
|
49267
|
+
return false;
|
|
49268
|
+
}
|
|
49269
|
+
if (classification.isUserFacing) {
|
|
49270
|
+
return false;
|
|
49271
|
+
}
|
|
49272
|
+
if (classification.kind === "tool" || classification.kind === "terminal") {
|
|
49273
|
+
sawTrailingToolActivity = true;
|
|
49274
|
+
}
|
|
49275
|
+
}
|
|
49276
|
+
return false;
|
|
49277
|
+
}
|
|
49168
49278
|
function canonicalizeKindHint(value) {
|
|
49169
49279
|
return value.trim().toLowerCase().replace(/[\s-]+/g, "_");
|
|
49170
49280
|
}
|
|
@@ -50416,6 +50526,7 @@ ${cleanBody}`;
|
|
|
50416
50526
|
...provider.lastDetection !== void 0 ? { lastDetection: provider.lastDetection } : {},
|
|
50417
50527
|
...provider.lastVerification !== void 0 ? { lastVerification: provider.lastVerification } : {},
|
|
50418
50528
|
...provider.meshCoordinator !== void 0 ? { meshCoordinator: provider.meshCoordinator } : {},
|
|
50529
|
+
...provider.autoApproveModes !== void 0 ? { autoApproveModes: provider.autoApproveModes } : {},
|
|
50419
50530
|
...trust ? {
|
|
50420
50531
|
trust,
|
|
50421
50532
|
trustDescription: describeTrust2(trust),
|
|
@@ -51595,7 +51706,11 @@ ${cleanBody}`;
|
|
|
51595
51706
|
spawnedSessionVisibility: mesh?.policy?.spawnedSessionVisibility || "hidden",
|
|
51596
51707
|
// Coordinator-dispatched recovery relaunch: same auto-approve
|
|
51597
51708
|
// policy as the primary worker launch path.
|
|
51598
|
-
|
|
51709
|
+
...delegatedWorkerAutoApproveSettings(
|
|
51710
|
+
mesh?.policy,
|
|
51711
|
+
node?.policy,
|
|
51712
|
+
components.providerLoader?.getMeta(recoveryContext.failedProviderType)
|
|
51713
|
+
),
|
|
51599
51714
|
launchedByCoordinator: true
|
|
51600
51715
|
}
|
|
51601
51716
|
}).catch((e) => LOG2.error("MeshRecovery", `Failed to auto-relaunch session for ${node.id}: ${e?.message}`));
|
|
@@ -52864,6 +52979,7 @@ ${cleanBody}`;
|
|
|
52864
52979
|
const messages = Array.isArray(payload.messages) ? payload.messages : [];
|
|
52865
52980
|
const evidence = extractFinalAssistantSummaryEvidence(messages);
|
|
52866
52981
|
if (!evidence.finalSummary) return null;
|
|
52982
|
+
if (hasTrailingToolActivityAfterFinalAssistant(messages)) return null;
|
|
52867
52983
|
const dispatchedAtMs = Date.parse(readNonEmptyString(row.dispatchTimestamp));
|
|
52868
52984
|
const transcriptAtMs = Date.parse(evidence.transcriptMessageAt ?? "");
|
|
52869
52985
|
if (!(Number.isFinite(dispatchedAtMs) && Number.isFinite(transcriptAtMs) && transcriptAtMs >= dispatchedAtMs)) {
|
|
@@ -53154,6 +53270,52 @@ ${cleanBody}`;
|
|
|
53154
53270
|
return false;
|
|
53155
53271
|
}
|
|
53156
53272
|
}
|
|
53273
|
+
function resolveLocalSessionPurePty(components, sessionId) {
|
|
53274
|
+
try {
|
|
53275
|
+
const instances = components.instanceManager?.getByCategory?.("cli") || [];
|
|
53276
|
+
const inst = instances.find((i) => {
|
|
53277
|
+
const sid = readNonEmptyString(i?.getState?.().instanceId);
|
|
53278
|
+
return sid && sessionIdsEquivalent(sid, sessionId);
|
|
53279
|
+
});
|
|
53280
|
+
if (!inst) return void 0;
|
|
53281
|
+
const provider = inst.provider;
|
|
53282
|
+
if (!provider || typeof provider !== "object") return void 0;
|
|
53283
|
+
return isPurePtyTranscriptProvider(provider);
|
|
53284
|
+
} catch {
|
|
53285
|
+
return void 0;
|
|
53286
|
+
}
|
|
53287
|
+
}
|
|
53288
|
+
async function evaluateEarlyIdleTranscriptArm(components, mesh, store, row, localDaemonId, selfIds = []) {
|
|
53289
|
+
const sessionId = readNonEmptyString(row.assignedSessionId);
|
|
53290
|
+
if (!sessionId) return false;
|
|
53291
|
+
const verdict = resolveSessionBusyVerdict(components, sessionId);
|
|
53292
|
+
if (verdict === "GENERATING") return false;
|
|
53293
|
+
if (verdict === "UNKNOWN") {
|
|
53294
|
+
const nodeId = readNonEmptyString(row.assignedNodeId);
|
|
53295
|
+
const node = (mesh.nodes ?? []).find((n) => n.id === nodeId);
|
|
53296
|
+
const liveStatus = nodeId ? readNonEmptyString(sessionStatusFromNodes(mesh.nodes, nodeId, sessionId).status).toLowerCase() : "";
|
|
53297
|
+
if (liveStatus && liveStatus !== "idle") return false;
|
|
53298
|
+
if (!liveStatus) {
|
|
53299
|
+
const nodeDaemonId = readNonEmptyString(node?.daemonId);
|
|
53300
|
+
const isLocalNode = !nodeDaemonId || daemonIdsEquivalent(nodeDaemonId, localDaemonId) || daemonIdListIncludes(selfIds, nodeDaemonId) || !!components.instanceManager?.getInstance?.(sessionId);
|
|
53301
|
+
const providerType = readNonEmptyString(row.assignedProviderType);
|
|
53302
|
+
const readArgs = {
|
|
53303
|
+
sessionId,
|
|
53304
|
+
targetSessionId: sessionId,
|
|
53305
|
+
tailLimit: 1,
|
|
53306
|
+
...node?.workspace ? { workspace: node.workspace } : {},
|
|
53307
|
+
...providerType ? { agentType: providerType, providerType } : {}
|
|
53308
|
+
};
|
|
53309
|
+
const probedStatus = await reprobeWorkerStatus(components, { isLocalNode, nodeDaemonId, readArgs });
|
|
53310
|
+
if (probedStatus !== "idle") return false;
|
|
53311
|
+
}
|
|
53312
|
+
}
|
|
53313
|
+
if (store.taskDeliveryConsumed(mesh.id, row.id)) return true;
|
|
53314
|
+
const localPurePty = resolveLocalSessionPurePty(components, sessionId);
|
|
53315
|
+
if (localPurePty === true) return true;
|
|
53316
|
+
if (localPurePty === false) return false;
|
|
53317
|
+
return verdict === "UNKNOWN";
|
|
53318
|
+
}
|
|
53157
53319
|
async function recoverStrandedAssignedDispatches(components, mesh, store, localDaemonId, selfIds = []) {
|
|
53158
53320
|
const meshId = mesh.id;
|
|
53159
53321
|
const assigned = getQueue(meshId, { status: ["assigned"] });
|
|
@@ -53175,7 +53337,8 @@ ${cleanBody}`;
|
|
|
53175
53337
|
if (!Number.isFinite(dispatchedAtMs)) continue;
|
|
53176
53338
|
const ageMs = nowMs - dispatchedAtMs;
|
|
53177
53339
|
const idleTranscriptStreakKey = `${meshId}::${row.id}`;
|
|
53178
|
-
|
|
53340
|
+
const earlyArm = store.taskHasConfirmedDelivery(meshId, row.id) && !findTerminalLedgerEvidenceForTask({ meshId, taskId: row.id }) && readNonEmptyString(row.assignedSessionId) ? await evaluateEarlyIdleTranscriptArm(components, mesh, store, row, localDaemonId, selfIds) : false;
|
|
53341
|
+
if (earlyArm) {
|
|
53179
53342
|
const since = assignedIdleFinalAssistantSince.get(idleTranscriptStreakKey);
|
|
53180
53343
|
if (since === void 0) {
|
|
53181
53344
|
assignedIdleFinalAssistantSince.set(idleTranscriptStreakKey, nowMs);
|
|
@@ -53932,6 +54095,7 @@ ${cleanBody}`;
|
|
|
53932
54095
|
init_mesh_reconcile_identity();
|
|
53933
54096
|
init_mesh_reconcile_config();
|
|
53934
54097
|
init_mesh_remote_event_pull();
|
|
54098
|
+
init_provider_cli_shared();
|
|
53935
54099
|
init_mesh_disk_retention();
|
|
53936
54100
|
init_mesh_completion_synthesis();
|
|
53937
54101
|
init_mesh_active_work();
|
|
@@ -54211,6 +54375,20 @@ ${cleanBody}`;
|
|
|
54211
54375
|
}
|
|
54212
54376
|
}
|
|
54213
54377
|
},
|
|
54378
|
+
autoApproveModes: {
|
|
54379
|
+
type: "object",
|
|
54380
|
+
description: "Provider-specific auto-approve choices and their launch/runtime strategy.",
|
|
54381
|
+
required: ["default", "modes"],
|
|
54382
|
+
additionalProperties: false,
|
|
54383
|
+
properties: {
|
|
54384
|
+
default: { type: "string", minLength: 1 },
|
|
54385
|
+
modes: {
|
|
54386
|
+
type: "array",
|
|
54387
|
+
minItems: 1,
|
|
54388
|
+
items: { $ref: "#/$defs/autoApproveMode" }
|
|
54389
|
+
}
|
|
54390
|
+
}
|
|
54391
|
+
},
|
|
54214
54392
|
sendDelayMs: {
|
|
54215
54393
|
type: "number",
|
|
54216
54394
|
minimum: 0,
|
|
@@ -54584,6 +54762,36 @@ ${cleanBody}`;
|
|
|
54584
54762
|
}
|
|
54585
54763
|
},
|
|
54586
54764
|
$defs: {
|
|
54765
|
+
autoApproveMode: {
|
|
54766
|
+
type: "object",
|
|
54767
|
+
required: ["id", "label", "strategy", "risk"],
|
|
54768
|
+
additionalProperties: false,
|
|
54769
|
+
properties: {
|
|
54770
|
+
id: { type: "string", minLength: 1 },
|
|
54771
|
+
label: { type: "string", minLength: 1 },
|
|
54772
|
+
strategy: { enum: ["pty-parse-default", "launch-args", "post-boot-command"] },
|
|
54773
|
+
risk: { enum: ["safe", "caution", "dangerous"] },
|
|
54774
|
+
warning: { type: "string", minLength: 1 },
|
|
54775
|
+
launchArgs: {
|
|
54776
|
+
type: "array",
|
|
54777
|
+
items: { type: "string", minLength: 1 }
|
|
54778
|
+
},
|
|
54779
|
+
removeArgs: {
|
|
54780
|
+
type: "array",
|
|
54781
|
+
items: { type: "string", minLength: 1 }
|
|
54782
|
+
}
|
|
54783
|
+
},
|
|
54784
|
+
allOf: [
|
|
54785
|
+
{
|
|
54786
|
+
if: { properties: { strategy: { const: "launch-args" } }, required: ["strategy"] },
|
|
54787
|
+
then: { required: ["launchArgs"], properties: { launchArgs: { minItems: 1 } } }
|
|
54788
|
+
},
|
|
54789
|
+
{
|
|
54790
|
+
if: { properties: { risk: { const: "dangerous" } }, required: ["risk"] },
|
|
54791
|
+
then: { required: ["warning"] }
|
|
54792
|
+
}
|
|
54793
|
+
]
|
|
54794
|
+
},
|
|
54587
54795
|
patternList: {
|
|
54588
54796
|
type: "array",
|
|
54589
54797
|
items: {
|
|
@@ -60463,6 +60671,7 @@ ${lastSnapshot}`;
|
|
|
60463
60671
|
createSessionDelivery: () => createSessionDelivery,
|
|
60464
60672
|
createWorktree: () => createWorktree,
|
|
60465
60673
|
daemonIdsEquivalent: () => daemonIdsEquivalent,
|
|
60674
|
+
delegatedWorkerAutoApproveSettings: () => delegatedWorkerAutoApproveSettings,
|
|
60466
60675
|
deleteDirectDispatchesByTaskId: () => deleteDirectDispatchesByTaskId,
|
|
60467
60676
|
deleteMesh: () => deleteMesh,
|
|
60468
60677
|
deriveMeshNodeHealthFromGit: () => deriveMeshNodeHealthFromGit,
|
|
@@ -60662,6 +60871,7 @@ ${lastSnapshot}`;
|
|
|
60662
60871
|
resolveCurrentGlobalInstallSurface: () => resolveCurrentGlobalInstallSurface,
|
|
60663
60872
|
resolveDebugRuntimeConfig: () => resolveDebugRuntimeConfig,
|
|
60664
60873
|
resolveDelegatedWorkerAutoApprove: () => resolveDelegatedWorkerAutoApprove,
|
|
60874
|
+
resolveDelegatedWorkerDangerousModeAllow: () => resolveDelegatedWorkerDangerousModeAllow,
|
|
60665
60875
|
resolveDeliveryDecision: () => resolveDeliveryDecision,
|
|
60666
60876
|
resolveEffectiveMeshNodeHealth: () => resolveEffectiveMeshNodeHealth,
|
|
60667
60877
|
resolveGitRepository: () => resolveGitRepository,
|
|
@@ -79151,6 +79361,7 @@ ${body}
|
|
|
79151
79361
|
const pad = (value) => String(value).padStart(2, "0");
|
|
79152
79362
|
return `${date5.getFullYear()}-${pad(date5.getMonth() + 1)}-${pad(date5.getDate())} ${pad(date5.getHours())}:${pad(date5.getMinutes())}:${pad(date5.getSeconds())}`;
|
|
79153
79363
|
}
|
|
79364
|
+
init_auto_approve_modes();
|
|
79154
79365
|
function approvalModalSignature(message, affirmativeAnchor) {
|
|
79155
79366
|
return [typeof message === "string" ? message.trim() : "", affirmativeAnchor].join("::");
|
|
79156
79367
|
}
|
|
@@ -81131,7 +81342,7 @@ ${body}
|
|
|
81131
81342
|
* resolveModal, so a plain turn that never saw an approval always returns false.
|
|
81132
81343
|
*/
|
|
81133
81344
|
inApprovalResumeGrace(now = Date.now()) {
|
|
81134
|
-
if (!this.isAutonomousMeshSession() || !this.
|
|
81345
|
+
if (!this.isAutonomousMeshSession() || !this.shouldUsePtyAutoApprove()) return false;
|
|
81135
81346
|
const resolvedAt = typeof this.adapter?.lastApprovalResolvedAt === "number" ? this.adapter.lastApprovalResolvedAt : 0;
|
|
81136
81347
|
if (resolvedAt <= 0) return false;
|
|
81137
81348
|
return now - resolvedAt < _CliProviderInstance.APPROVAL_RESUME_GRACE_MS;
|
|
@@ -81236,7 +81447,7 @@ ${body}
|
|
|
81236
81447
|
return;
|
|
81237
81448
|
}
|
|
81238
81449
|
const latestStatus = this.adapter.getStatus({ allowParse: false });
|
|
81239
|
-
const latestAutoApproveActive = latestStatus.status === "waiting_approval" && this.
|
|
81450
|
+
const latestAutoApproveActive = latestStatus.status === "waiting_approval" && this.shouldUsePtyAutoApprove();
|
|
81240
81451
|
const latestVisibleStatus = latestAutoApproveActive || this.autoApproveBusy ? "generating" : latestStatus.status;
|
|
81241
81452
|
LOG2.debug("CLI", `[${this.type}] flush attempt: adapterStatus=${latestStatus.status} latestVisible=${latestVisibleStatus} generatingStartedAt=${this.generatingStartedAt} isWaitingForResponse=${!!this.adapter?.isWaitingForResponse} hasPartial=${!!this.adapter.getPartialResponse?.()}`);
|
|
81242
81453
|
if (latestVisibleStatus !== "idle") {
|
|
@@ -81506,7 +81717,7 @@ ${body}
|
|
|
81506
81717
|
* session, where a human answers the prompt, is returned untouched).
|
|
81507
81718
|
*/
|
|
81508
81719
|
stabilizeFlappingApprovalStatus(adapterStatus, now = Date.now()) {
|
|
81509
|
-
if (!this.isAutonomousMeshSession() || !this.
|
|
81720
|
+
if (!this.isAutonomousMeshSession() || !this.shouldUsePtyAutoApprove()) return adapterStatus;
|
|
81510
81721
|
const rawStatus = adapterStatus?.status;
|
|
81511
81722
|
const resolvedAt = typeof this.adapter?.lastApprovalResolvedAt === "number" ? this.adapter.lastApprovalResolvedAt : 0;
|
|
81512
81723
|
if (rawStatus === "waiting_approval") {
|
|
@@ -81536,7 +81747,11 @@ ${body}
|
|
|
81536
81747
|
return adapterStatus;
|
|
81537
81748
|
}
|
|
81538
81749
|
maybeAutoApproveStatus(adapterStatus, now = Date.now()) {
|
|
81539
|
-
if (
|
|
81750
|
+
if (!this.shouldUsePtyAutoApprove()) {
|
|
81751
|
+
this.resetPtyAutoApproveState();
|
|
81752
|
+
return false;
|
|
81753
|
+
}
|
|
81754
|
+
if (adapterStatus?.status === "waiting_approval" && this.shouldUsePtyAutoApprove() && this.manualAttendance.isAttended(now)) {
|
|
81540
81755
|
this.lastAutoApprovalSignature = "";
|
|
81541
81756
|
this.pendingAutoApprovalSignature = "";
|
|
81542
81757
|
this.pendingAutoApprovalSince = 0;
|
|
@@ -81551,7 +81766,7 @@ ${body}
|
|
|
81551
81766
|
}, this.manualAttendance.remainingMs(now) + 20);
|
|
81552
81767
|
return false;
|
|
81553
81768
|
}
|
|
81554
|
-
const autoApproveActive = adapterStatus?.status === "waiting_approval" && this.
|
|
81769
|
+
const autoApproveActive = adapterStatus?.status === "waiting_approval" && this.shouldUsePtyAutoApprove();
|
|
81555
81770
|
if (!autoApproveActive) {
|
|
81556
81771
|
this.lastAutoApprovalSignature = "";
|
|
81557
81772
|
if (this.pendingAutoApprovalSince) {
|
|
@@ -82246,15 +82461,34 @@ ${buttons.join("\n")}`;
|
|
|
82246
82461
|
get cliName() {
|
|
82247
82462
|
return this.provider.name;
|
|
82248
82463
|
}
|
|
82464
|
+
resolveAutoApproveMode() {
|
|
82465
|
+
return resolveProviderAutoApproveMode(this.provider, this.settings);
|
|
82466
|
+
}
|
|
82467
|
+
/** Legacy boolean view retained for internal/test compatibility. */
|
|
82249
82468
|
shouldAutoApprove() {
|
|
82250
|
-
|
|
82251
|
-
|
|
82469
|
+
return this.resolveAutoApproveMode().active;
|
|
82470
|
+
}
|
|
82471
|
+
shouldUsePtyAutoApprove() {
|
|
82472
|
+
const resolved = this.resolveAutoApproveMode();
|
|
82473
|
+
return this.shouldAutoApprove() && resolved.strategy === "pty-parse-default";
|
|
82474
|
+
}
|
|
82475
|
+
resetPtyAutoApproveState() {
|
|
82476
|
+
this.lastAutoApprovalSignature = "";
|
|
82477
|
+
this.pendingAutoApprovalSignature = "";
|
|
82478
|
+
this.pendingAutoApprovalSince = 0;
|
|
82479
|
+
this.autoApproveInactiveSince = 0;
|
|
82480
|
+
this.autoApproveMaskSince = 0;
|
|
82481
|
+
this.stalledApprovalNudgeEpisode = 0;
|
|
82482
|
+
this.autoApproveLastModalSeenAt = 0;
|
|
82483
|
+
this.autoApproveBusy = false;
|
|
82484
|
+
if (this.autoApproveSettleTimer) {
|
|
82485
|
+
clearTimeout(this.autoApproveSettleTimer);
|
|
82486
|
+
this.autoApproveSettleTimer = null;
|
|
82252
82487
|
}
|
|
82253
|
-
|
|
82254
|
-
|
|
82255
|
-
|
|
82488
|
+
if (this.autoApproveBusyTimer) {
|
|
82489
|
+
clearTimeout(this.autoApproveBusyTimer);
|
|
82490
|
+
this.autoApproveBusyTimer = null;
|
|
82256
82491
|
}
|
|
82257
|
-
return false;
|
|
82258
82492
|
}
|
|
82259
82493
|
/** @see ProviderInstance.noteManualInteraction */
|
|
82260
82494
|
noteManualInteraction(now = Date.now(), opts) {
|
|
@@ -82270,7 +82504,7 @@ ${buttons.join("\n")}`;
|
|
|
82270
82504
|
* CLI-specific modal text.
|
|
82271
82505
|
*/
|
|
82272
82506
|
autoApproveEffectivelyActive(status, now = Date.now()) {
|
|
82273
|
-
return status === "waiting_approval" && this.
|
|
82507
|
+
return status === "waiting_approval" && this.shouldUsePtyAutoApprove() && !this.manualAttendance.isAttended(now);
|
|
82274
82508
|
}
|
|
82275
82509
|
// STATUS-MISMATCH: true once the current auto-approve episode has been masking
|
|
82276
82510
|
// waiting_approval behind `generating` for longer than AUTO_APPROVE_MASK_STALL_MS without
|
|
@@ -82280,7 +82514,7 @@ ${buttons.join("\n")}`;
|
|
|
82280
82514
|
// maybeAutoApproveStatus (driven by getState + the recheck timer during a waiting episode);
|
|
82281
82515
|
// this read is side-effect-free so getStatusMetadata can consult it too.
|
|
82282
82516
|
autoApproveMaskStalled(now = Date.now()) {
|
|
82283
|
-
return this.autoApproveMaskSince > 0 && now - this.autoApproveMaskSince > _CliProviderInstance.AUTO_APPROVE_MASK_STALL_MS;
|
|
82517
|
+
return this.shouldUsePtyAutoApprove() && this.autoApproveMaskSince > 0 && now - this.autoApproveMaskSince > _CliProviderInstance.AUTO_APPROVE_MASK_STALL_MS;
|
|
82284
82518
|
}
|
|
82285
82519
|
/**
|
|
82286
82520
|
* NOTIF-APPROVAL-MASKED (Q1b): surface a delegated worker's STALLED auto-approve modal
|
|
@@ -82304,6 +82538,7 @@ ${buttons.join("\n")}`;
|
|
|
82304
82538
|
* mask-clock value) so a modal that flaps between parsed/unparsed states is announced once.
|
|
82305
82539
|
*/
|
|
82306
82540
|
maybeEmitStalledApprovalNudge(adapterStatus, now) {
|
|
82541
|
+
if (!this.shouldUsePtyAutoApprove()) return;
|
|
82307
82542
|
if (!this.isMeshWorkerSession()) return;
|
|
82308
82543
|
if (adapterStatus?.status !== "waiting_approval") return;
|
|
82309
82544
|
if (!this.autoApproveMaskStalled(now)) return;
|
|
@@ -83836,6 +84071,7 @@ ${rawInput}` : rawInput;
|
|
|
83836
84071
|
if (!managedBy) return true;
|
|
83837
84072
|
return managedBy === managerTag;
|
|
83838
84073
|
}
|
|
84074
|
+
init_auto_approve_modes();
|
|
83839
84075
|
function isExplicitCommand(command) {
|
|
83840
84076
|
const trimmed = command.trim();
|
|
83841
84077
|
return path30.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
|
|
@@ -84062,6 +84298,24 @@ ${rawInput}` : rawInput;
|
|
|
84062
84298
|
const mapped = levelMap && typeof levelMap[raw] === "string" && levelMap[raw].trim() ? levelMap[raw].trim() : raw;
|
|
84063
84299
|
return template.map((part) => part.includes("{{level}}") ? part.replace("{{level}}", mapped) : part);
|
|
84064
84300
|
}
|
|
84301
|
+
function matchesRemovedLaunchArg(arg, removeArg) {
|
|
84302
|
+
return arg === removeArg || removeArg.startsWith("--") && arg.startsWith(`${removeArg}=`);
|
|
84303
|
+
}
|
|
84304
|
+
function applyAutoApproveModeLaunchArgs(provider, cliArgs, settings) {
|
|
84305
|
+
if (!provider) return { provider, cliArgs };
|
|
84306
|
+
const resolved = resolveProviderAutoApproveMode(provider, settings);
|
|
84307
|
+
if (!resolved.active || resolved.strategy !== "launch-args") return { provider, cliArgs };
|
|
84308
|
+
const mode = findProviderAutoApproveMode(provider, resolved.modeId);
|
|
84309
|
+
if (!mode || !Array.isArray(mode.launchArgs) || mode.launchArgs.length === 0) return { provider, cliArgs };
|
|
84310
|
+
const removeArgs = Array.isArray(mode.removeArgs) ? mode.removeArgs : [];
|
|
84311
|
+
const baseArgs = provider.spawn?.args;
|
|
84312
|
+
const filteredBaseArgs = Array.isArray(baseArgs) && removeArgs.length > 0 ? baseArgs.filter((arg) => !removeArgs.some((removeArg) => matchesRemovedLaunchArg(arg, removeArg))) : baseArgs;
|
|
84313
|
+
const launchProvider = filteredBaseArgs === baseArgs ? provider : { ...provider, spawn: { ...provider.spawn, args: filteredBaseArgs } };
|
|
84314
|
+
return {
|
|
84315
|
+
provider: launchProvider,
|
|
84316
|
+
cliArgs: [...mode.launchArgs, ...cliArgs || []]
|
|
84317
|
+
};
|
|
84318
|
+
}
|
|
84065
84319
|
function readSubcommandSessionId(args, subcommands) {
|
|
84066
84320
|
const resumeIndex = args.findIndex((arg) => subcommands.includes(arg));
|
|
84067
84321
|
if (resumeIndex < 0) return void 0;
|
|
@@ -84492,22 +84746,30 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
84492
84746
|
if (provider) {
|
|
84493
84747
|
console.log(colorize("cyan", ` \u{1F4E6} Using provider: ${provider.name} (${provider.type})`));
|
|
84494
84748
|
}
|
|
84495
|
-
const
|
|
84496
|
-
|
|
84749
|
+
const launchSettings = {
|
|
84750
|
+
...this.providerLoader.getSettings(normalizedType),
|
|
84751
|
+
...options?.settingsOverride || {}
|
|
84752
|
+
};
|
|
84753
|
+
const versionResolvedProvider = provider ? this.providerLoader.resolve(cliType, { version: cliInfo.version }) || provider : void 0;
|
|
84754
|
+
const autoApproveLaunch = applyAutoApproveModeLaunchArgs(versionResolvedProvider, cliArgs, launchSettings);
|
|
84755
|
+
const launchProvider = autoApproveLaunch.provider || provider;
|
|
84756
|
+
const cliArgsWithAutoApprove = autoApproveLaunch.cliArgs;
|
|
84757
|
+
const modelLaunchArgs = expandModelLaunchArgs(launchProvider?.modelLaunchArgs, initialModel);
|
|
84758
|
+
const cliArgsWithModel = modelLaunchArgs ? [...modelLaunchArgs, ...cliArgsWithAutoApprove || []] : cliArgsWithAutoApprove;
|
|
84497
84759
|
if (initialModel && !modelLaunchArgs) {
|
|
84498
84760
|
LOG2.warn("CLI", `[${normalizedType}] initialModel='${initialModel}' requested but provider declares no modelLaunchArgs template \u2014 launching without model selection.`);
|
|
84499
84761
|
}
|
|
84500
84762
|
const initialThinkingLevel = options?.initialThinkingLevel;
|
|
84501
|
-
const thinkingLaunchArgs = expandThinkingLaunchArgs(
|
|
84763
|
+
const thinkingLaunchArgs = expandThinkingLaunchArgs(launchProvider?.thinkingLaunchArgs, initialThinkingLevel, launchProvider?.thinkingLevelMap);
|
|
84502
84764
|
const cliArgsWithBrain = thinkingLaunchArgs ? [...thinkingLaunchArgs, ...cliArgsWithModel || []] : cliArgsWithModel;
|
|
84503
84765
|
if (initialThinkingLevel && !thinkingLaunchArgs) {
|
|
84504
84766
|
LOG2.warn("CLI", `[${normalizedType}] initialThinkingLevel='${initialThinkingLevel}' requested but provider declares no thinkingLaunchArgs template \u2014 launching without thinking-level selection.`);
|
|
84505
84767
|
}
|
|
84506
|
-
const sessionBinding = resolveCliSessionBinding(
|
|
84768
|
+
const sessionBinding = resolveCliSessionBinding(launchProvider, normalizedType, cliArgsWithBrain, options?.resumeSessionId);
|
|
84507
84769
|
const resolvedCliArgs = sessionBinding.cliArgs;
|
|
84508
84770
|
const instanceManager = this.deps.getInstanceManager();
|
|
84509
|
-
if (
|
|
84510
|
-
const resolvedProvider =
|
|
84771
|
+
if (launchProvider && instanceManager) {
|
|
84772
|
+
const resolvedProvider = launchProvider;
|
|
84511
84773
|
await this.registerCliInstance(
|
|
84512
84774
|
key2,
|
|
84513
84775
|
normalizedType,
|
|
@@ -84515,7 +84777,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
84515
84777
|
resolvedDir,
|
|
84516
84778
|
resolvedCliArgs,
|
|
84517
84779
|
resolvedProvider,
|
|
84518
|
-
|
|
84780
|
+
launchSettings,
|
|
84519
84781
|
false,
|
|
84520
84782
|
{
|
|
84521
84783
|
providerSessionId: sessionBinding.providerSessionId,
|
|
@@ -85346,6 +85608,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
85346
85608
|
var chokidar = __toESM2(require_chokidar());
|
|
85347
85609
|
init_hash();
|
|
85348
85610
|
init_logger();
|
|
85611
|
+
init_auto_approve_modes();
|
|
85349
85612
|
init_open_panel_support();
|
|
85350
85613
|
var VALID_CAPABILITY_MEDIA_TYPES = /* @__PURE__ */ new Set(["text", "image", "audio", "video", "resource"]);
|
|
85351
85614
|
var VALID_INPUT_STRATEGIES2 = /* @__PURE__ */ new Set(["native", "native_acp", "resource_link", "text_fallback", "paste", "upload"]);
|
|
@@ -85411,6 +85674,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
85411
85674
|
"providerVersion",
|
|
85412
85675
|
"status",
|
|
85413
85676
|
"details",
|
|
85677
|
+
"autoApproveModes",
|
|
85414
85678
|
"modelLaunchArgs",
|
|
85415
85679
|
"modelOptions",
|
|
85416
85680
|
"thinkingLaunchArgs",
|
|
@@ -85472,6 +85736,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
85472
85736
|
validateCapabilities(provider, controls, errors);
|
|
85473
85737
|
validateNativeHistory(provider.nativeHistory, errors);
|
|
85474
85738
|
validateMeshCoordinator(provider.meshCoordinator, errors);
|
|
85739
|
+
validateAutoApproveModes(provider.autoApproveModes, errors);
|
|
85475
85740
|
for (const control of controls) {
|
|
85476
85741
|
validateControl(control, errors);
|
|
85477
85742
|
}
|
|
@@ -85480,6 +85745,75 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
85480
85745
|
}
|
|
85481
85746
|
return { errors, warnings };
|
|
85482
85747
|
}
|
|
85748
|
+
function validateAutoApproveModes(raw, errors) {
|
|
85749
|
+
if (raw === void 0) return;
|
|
85750
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
85751
|
+
errors.push("autoApproveModes must be an object");
|
|
85752
|
+
return;
|
|
85753
|
+
}
|
|
85754
|
+
const config2 = raw;
|
|
85755
|
+
const defaultModeId = typeof config2.default === "string" ? config2.default.trim() : "";
|
|
85756
|
+
if (!defaultModeId) {
|
|
85757
|
+
errors.push("autoApproveModes.default must be a non-empty string");
|
|
85758
|
+
} else {
|
|
85759
|
+
config2.default = defaultModeId;
|
|
85760
|
+
}
|
|
85761
|
+
if (!Array.isArray(config2.modes) || config2.modes.length === 0) {
|
|
85762
|
+
errors.push("autoApproveModes.modes must be a non-empty array");
|
|
85763
|
+
return;
|
|
85764
|
+
}
|
|
85765
|
+
const ids = /* @__PURE__ */ new Set();
|
|
85766
|
+
for (const [index, rawMode] of config2.modes.entries()) {
|
|
85767
|
+
const prefix = `autoApproveModes.modes[${index}]`;
|
|
85768
|
+
if (!rawMode || typeof rawMode !== "object" || Array.isArray(rawMode)) {
|
|
85769
|
+
errors.push(`${prefix} must be an object`);
|
|
85770
|
+
continue;
|
|
85771
|
+
}
|
|
85772
|
+
const mode = rawMode;
|
|
85773
|
+
const id = typeof mode.id === "string" ? mode.id.trim() : "";
|
|
85774
|
+
if (!id) {
|
|
85775
|
+
errors.push(`${prefix}.id must be a non-empty string`);
|
|
85776
|
+
} else if (ids.has(id)) {
|
|
85777
|
+
errors.push(`${prefix}.id must be unique (duplicate: ${id})`);
|
|
85778
|
+
} else {
|
|
85779
|
+
ids.add(id);
|
|
85780
|
+
mode.id = id;
|
|
85781
|
+
}
|
|
85782
|
+
if (typeof mode.label !== "string" || !mode.label.trim()) {
|
|
85783
|
+
errors.push(`${prefix}.label must be a non-empty string`);
|
|
85784
|
+
}
|
|
85785
|
+
const strategy = mode.strategy;
|
|
85786
|
+
if (!["pty-parse-default", "launch-args", "post-boot-command"].includes(String(strategy))) {
|
|
85787
|
+
errors.push(`${prefix}.strategy must be one of: pty-parse-default, launch-args, post-boot-command`);
|
|
85788
|
+
} else if (strategy === "post-boot-command") {
|
|
85789
|
+
errors.push(`${prefix}.strategy post-boot-command is reserved and unsupported in v1`);
|
|
85790
|
+
}
|
|
85791
|
+
const risk = mode.risk;
|
|
85792
|
+
if (!["safe", "caution", "dangerous"].includes(String(risk))) {
|
|
85793
|
+
errors.push(`${prefix}.risk must be one of: safe, caution, dangerous`);
|
|
85794
|
+
}
|
|
85795
|
+
for (const field of ["launchArgs", "removeArgs"]) {
|
|
85796
|
+
const value = mode[field];
|
|
85797
|
+
if (value !== void 0 && (!Array.isArray(value) || value.some((arg) => typeof arg !== "string" || !arg.trim()))) {
|
|
85798
|
+
errors.push(`${prefix}.${field} must be an array of non-empty strings when provided`);
|
|
85799
|
+
}
|
|
85800
|
+
}
|
|
85801
|
+
if (strategy === "launch-args" && (!Array.isArray(mode.launchArgs) || mode.launchArgs.length === 0)) {
|
|
85802
|
+
errors.push(`${prefix}.launchArgs must be a non-empty array for launch-args strategy`);
|
|
85803
|
+
}
|
|
85804
|
+
if (["safe", "caution", "dangerous"].includes(String(risk)) && deriveAutoApproveModeRisk(mode) === "dangerous") {
|
|
85805
|
+
mode.risk = "dangerous";
|
|
85806
|
+
}
|
|
85807
|
+
if (mode.risk === "dangerous" && (typeof mode.warning !== "string" || !mode.warning.trim())) {
|
|
85808
|
+
errors.push(`${prefix}.warning is required for dangerous modes`);
|
|
85809
|
+
} else if (mode.warning !== void 0 && (typeof mode.warning !== "string" || !mode.warning.trim())) {
|
|
85810
|
+
errors.push(`${prefix}.warning must be a non-empty string when provided`);
|
|
85811
|
+
}
|
|
85812
|
+
}
|
|
85813
|
+
if (defaultModeId && !ids.has(defaultModeId)) {
|
|
85814
|
+
errors.push(`autoApproveModes.default must reference an existing mode id: ${defaultModeId}`);
|
|
85815
|
+
}
|
|
85816
|
+
}
|
|
85483
85817
|
function validateCapabilities(provider, controls, errors) {
|
|
85484
85818
|
const capabilities = provider.capabilities;
|
|
85485
85819
|
if (provider.contractVersion === 2) {
|