@adhdev/daemon-core 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.mjs CHANGED
@@ -25,6 +25,62 @@ var __copyProps = (to, from, except, desc) => {
25
25
  };
26
26
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
27
27
 
28
+ // src/providers/auto-approve-modes.ts
29
+ function isKnownDangerousLaunchArg(arg) {
30
+ const normalized = arg.trim();
31
+ if (KNOWN_DANGEROUS_LAUNCH_ARGS.has(normalized)) return true;
32
+ return normalized.startsWith("--dangerously-skip-permissions=") || normalized.startsWith("--dangerously-bypass-approvals-and-sandbox=");
33
+ }
34
+ function deriveAutoApproveModeRisk(mode) {
35
+ return Array.isArray(mode.launchArgs) && mode.launchArgs.some(isKnownDangerousLaunchArg) ? "dangerous" : mode.risk;
36
+ }
37
+ function inactiveMode(modeId = "") {
38
+ return { active: false, strategy: "pty-parse-default", modeId };
39
+ }
40
+ function resolveConfiguredMode(provider, mode, settings) {
41
+ if (mode.strategy === "post-boot-command") return inactiveMode(mode.id);
42
+ if (settings?.launchedByCoordinator === true && settings.delegatedWorkerDangerousModeAllow !== true && deriveAutoApproveModeRisk(mode) === "dangerous") {
43
+ const fallback = provider.autoApproveModes?.modes.find((candidate) => candidate.strategy === "pty-parse-default" && deriveAutoApproveModeRisk(candidate) !== "dangerous");
44
+ return fallback ? { active: true, strategy: fallback.strategy, modeId: fallback.id } : inactiveMode(mode.id);
45
+ }
46
+ return { active: true, strategy: mode.strategy, modeId: mode.id };
47
+ }
48
+ function resolveProviderAutoApproveMode(provider, settings) {
49
+ const config = provider.autoApproveModes;
50
+ const explicitModeId = settings?.autoApproveMode;
51
+ if (typeof explicitModeId === "string") {
52
+ const mode = config?.modes.find((candidate) => candidate.id === explicitModeId);
53
+ if (!mode) return inactiveMode(explicitModeId);
54
+ return resolveConfiguredMode(provider, mode, settings);
55
+ }
56
+ const explicitLegacy = settings?.autoApprove;
57
+ const providerLegacyDefault = provider.settings?.autoApprove?.default;
58
+ const legacyActive = typeof explicitLegacy === "boolean" ? explicitLegacy : typeof providerLegacyDefault === "boolean" ? providerLegacyDefault : false;
59
+ if (!legacyActive) return inactiveMode();
60
+ if (!config) {
61
+ return { active: true, strategy: "pty-parse-default", modeId: "legacy" };
62
+ }
63
+ const defaultMode = config.modes.find((mode) => mode.id === config.default);
64
+ if (!defaultMode) return inactiveMode(config.default);
65
+ return resolveConfiguredMode(provider, defaultMode, settings);
66
+ }
67
+ function findProviderAutoApproveMode(provider, modeId) {
68
+ return provider?.autoApproveModes?.modes.find((mode) => mode.id === modeId);
69
+ }
70
+ var KNOWN_DANGEROUS_LAUNCH_ARGS;
71
+ var init_auto_approve_modes = __esm({
72
+ "src/providers/auto-approve-modes.ts"() {
73
+ "use strict";
74
+ KNOWN_DANGEROUS_LAUNCH_ARGS = /* @__PURE__ */ new Set([
75
+ "--dangerously-skip-permissions",
76
+ "--dangerously-bypass-approvals-and-sandbox",
77
+ "bypassPermissions",
78
+ "sandbox_mode=danger-full-access",
79
+ "approval_policy=never"
80
+ ]);
81
+ }
82
+ });
83
+
28
84
  // src/repo-mesh-types.ts
29
85
  function normalizeMeshSchedulingStrategy(value) {
30
86
  if (typeof value !== "string") return DEFAULT_MESH_SCHEDULING_STRATEGY;
@@ -111,6 +167,11 @@ function mergeAndNormalizePolicy(base, patch) {
111
167
  } else {
112
168
  delete policy.autoConvergeCodeChange;
113
169
  }
170
+ if (policy.delegatedWorkerDangerousModeAllow === true) {
171
+ policy.delegatedWorkerDangerousModeAllow = true;
172
+ } else {
173
+ delete policy.delegatedWorkerDangerousModeAllow;
174
+ }
114
175
  if (policy.coordinatorIdlePushPolicy === "auto_silent_on_dispatch") {
115
176
  policy.coordinatorIdlePushPolicy = "auto_silent_on_dispatch";
116
177
  } else {
@@ -118,14 +179,35 @@ function mergeAndNormalizePolicy(base, patch) {
118
179
  }
119
180
  return policy;
120
181
  }
121
- function resolveDelegatedWorkerAutoApprove(meshPolicy, nodePolicy) {
182
+ function resolveDelegatedWorkerAutoApprove(meshPolicy, nodePolicy, provider) {
183
+ let enabled = true;
122
184
  if (typeof nodePolicy?.delegatedWorkerAutoApprove === "boolean") {
123
- return nodePolicy.delegatedWorkerAutoApprove;
185
+ enabled = nodePolicy.delegatedWorkerAutoApprove;
186
+ } else if (typeof meshPolicy?.delegatedWorkerAutoApprove === "boolean") {
187
+ enabled = meshPolicy.delegatedWorkerAutoApprove;
124
188
  }
125
- if (typeof meshPolicy?.delegatedWorkerAutoApprove === "boolean") {
126
- return meshPolicy.delegatedWorkerAutoApprove;
189
+ if (!enabled) return false;
190
+ const modes = provider?.autoApproveModes;
191
+ if (!modes) return true;
192
+ const defaultMode = modes.modes.find((mode) => mode.id === modes.default);
193
+ if (!defaultMode || defaultMode.strategy === "post-boot-command") return false;
194
+ const dangerousAllowed = resolveDelegatedWorkerDangerousModeAllow(meshPolicy, nodePolicy);
195
+ if (deriveAutoApproveModeRisk(defaultMode) === "dangerous" && !dangerousAllowed) {
196
+ const ptyFallback = modes.modes.find((mode) => mode.strategy === "pty-parse-default" && deriveAutoApproveModeRisk(mode) !== "dangerous");
197
+ return ptyFallback?.id || false;
127
198
  }
128
- return true;
199
+ return defaultMode.id;
200
+ }
201
+ function resolveDelegatedWorkerDangerousModeAllow(meshPolicy, nodePolicy) {
202
+ if (typeof nodePolicy?.delegatedWorkerDangerousModeAllow === "boolean") {
203
+ return nodePolicy.delegatedWorkerDangerousModeAllow;
204
+ }
205
+ return meshPolicy?.delegatedWorkerDangerousModeAllow === true;
206
+ }
207
+ function delegatedWorkerAutoApproveSettings(meshPolicy, nodePolicy, provider) {
208
+ const resolved = resolveDelegatedWorkerAutoApprove(meshPolicy, nodePolicy, provider);
209
+ const delegatedWorkerDangerousModeAllow = resolveDelegatedWorkerDangerousModeAllow(meshPolicy, nodePolicy);
210
+ return typeof resolved === "string" ? { autoApprove: void 0, autoApproveMode: resolved, delegatedWorkerDangerousModeAllow } : { autoApprove: resolved, autoApproveMode: void 0, delegatedWorkerDangerousModeAllow };
129
211
  }
130
212
  function resolveAllowSendKeysDestructive(meshPolicy, nodePolicy) {
131
213
  if (typeof nodePolicy?.allowSendKeysDestructive === "boolean") {
@@ -155,6 +237,7 @@ var MESH_SCHEDULING_STRATEGIES, DEFAULT_MESH_SCHEDULING_STRATEGY, MESH_CONVERGE_
155
237
  var init_repo_mesh_types = __esm({
156
238
  "src/repo-mesh-types.ts"() {
157
239
  "use strict";
240
+ init_auto_approve_modes();
158
241
  MESH_SCHEDULING_STRATEGIES = [
159
242
  "first_eligible",
160
243
  "least_loaded",
@@ -182,6 +265,7 @@ var init_repo_mesh_types = __esm({
182
265
  // any specific session manually; that override is preserved per-device.
183
266
  spawnedSessionVisibility: "hidden",
184
267
  delegatedWorkerAutoApprove: true,
268
+ delegatedWorkerDangerousModeAllow: false,
185
269
  sessionCleanupOnNodeRemove: "preserve",
186
270
  // MAGI auto-launches a worker session per pinned replica target with no idle
187
271
  // session; those stay idle-LIVE after their turn. Default ON (stop_and_delete)
@@ -437,10 +521,10 @@ function readInjected(value) {
437
521
  }
438
522
  function getDaemonBuildInfo() {
439
523
  if (cached) return cached;
440
- const commit = readInjected(true ? "64f056340da99d3b28464efcf5c05fe643e5db63" : void 0) ?? "unknown";
441
- const commitShort = readInjected(true ? "64f05634" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
442
- const version = readInjected(true ? "1.0.18-rc.15" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
443
- const builtAt = readInjected(true ? "2026-07-23T00:51:36.808Z" : void 0);
524
+ const commit = readInjected(true ? "eeb3e1474488eb5543c443270208f3ca8958a86a" : void 0) ?? "unknown";
525
+ const commitShort = readInjected(true ? "eeb3e147" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
526
+ const version = readInjected(true ? "1.0.18-rc.17" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
527
+ const builtAt = readInjected(true ? "2026-07-23T03:30:50.962Z" : void 0);
444
528
  cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
445
529
  return cached;
446
530
  }
@@ -16835,7 +16919,11 @@ function tryAssignQueueTask(components, meshId, nodeId, sessionId, providerType)
16835
16919
  meshNodeFor: meshId,
16836
16920
  meshNodeId: nodeId,
16837
16921
  launchedByCoordinator: true,
16838
- autoApprove: resolveDelegatedWorkerAutoApprove(mesh?.policy, node?.policy),
16922
+ ...delegatedWorkerAutoApproveSettings(
16923
+ mesh?.policy,
16924
+ node?.policy,
16925
+ components.providerLoader?.getMeta(providerType)
16926
+ ),
16839
16927
  ...localDaemonId ? { meshCoordinatorDaemonId: localDaemonId } : {},
16840
16928
  // COMPLETION-PROPAGATION F5: (re)stamp the coordinator SESSION anchor from THIS
16841
16929
  // task's sourceCoordinatorSessionId with PRIORITY — a manually-launched (or reused)
@@ -17608,8 +17696,12 @@ async function maybeAutoLaunchOneQueueSession(components, meshId, mesh) {
17608
17696
  spawnedSessionVisibility: mesh?.policy?.spawnedSessionVisibility || "hidden",
17609
17697
  // Coordinator-dispatched worker: auto-approve unless mesh/node policy
17610
17698
  // opts out (default true). Lands in settingsOverride and beats the
17611
- // global per-provider-type autoApprove config (see shouldAutoApprove).
17612
- autoApprove: resolveDelegatedWorkerAutoApprove(mesh?.policy, node?.policy),
17699
+ // global per-provider-type boolean/mode through explicit opposite-key clearing.
17700
+ ...delegatedWorkerAutoApproveSettings(
17701
+ mesh?.policy,
17702
+ node?.policy,
17703
+ components.providerLoader?.getMeta(resolved.providerType)
17704
+ ),
17613
17705
  launchedByCoordinator: true,
17614
17706
  autoLaunchedForQueueTaskId: task.id
17615
17707
  };
@@ -19184,6 +19276,26 @@ function selectFinalAssistantTurnEndMessage(messages) {
19184
19276
  }
19185
19277
  return null;
19186
19278
  }
19279
+ function hasTrailingToolActivityAfterFinalAssistant(messages) {
19280
+ if (!Array.isArray(messages) || messages.length === 0) return false;
19281
+ let sawTrailingToolActivity = false;
19282
+ for (let i = messages.length - 1; i >= 0; i--) {
19283
+ const msg = messages[i];
19284
+ if (!msg) continue;
19285
+ const classification = classifyChatMessageVisibility(msg);
19286
+ if (classification.isUserFacing && (msg.role === "assistant" || msg.role === "model")) {
19287
+ if (flattenContent(msg.content).trim()) return sawTrailingToolActivity;
19288
+ return false;
19289
+ }
19290
+ if (classification.isUserFacing) {
19291
+ return false;
19292
+ }
19293
+ if (classification.kind === "tool" || classification.kind === "terminal") {
19294
+ sawTrailingToolActivity = true;
19295
+ }
19296
+ }
19297
+ return false;
19298
+ }
19187
19299
  function canonicalizeKindHint(value) {
19188
19300
  return value.trim().toLowerCase().replace(/[\s-]+/g, "_");
19189
19301
  }
@@ -20429,6 +20541,7 @@ function buildAvailableProviders(providerLoader) {
20429
20541
  ...provider.lastDetection !== void 0 ? { lastDetection: provider.lastDetection } : {},
20430
20542
  ...provider.lastVerification !== void 0 ? { lastVerification: provider.lastVerification } : {},
20431
20543
  ...provider.meshCoordinator !== void 0 ? { meshCoordinator: provider.meshCoordinator } : {},
20544
+ ...provider.autoApproveModes !== void 0 ? { autoApproveModes: provider.autoApproveModes } : {},
20432
20545
  ...trust ? {
20433
20546
  trust,
20434
20547
  trustDescription: describeTrust2(trust),
@@ -21607,7 +21720,11 @@ function injectMeshSystemMessage(components, args) {
21607
21720
  spawnedSessionVisibility: mesh?.policy?.spawnedSessionVisibility || "hidden",
21608
21721
  // Coordinator-dispatched recovery relaunch: same auto-approve
21609
21722
  // policy as the primary worker launch path.
21610
- autoApprove: resolveDelegatedWorkerAutoApprove(mesh?.policy, node?.policy),
21723
+ ...delegatedWorkerAutoApproveSettings(
21724
+ mesh?.policy,
21725
+ node?.policy,
21726
+ components.providerLoader?.getMeta(recoveryContext.failedProviderType)
21727
+ ),
21611
21728
  launchedByCoordinator: true
21612
21729
  }
21613
21730
  }).catch((e) => LOG.error("MeshRecovery", `Failed to auto-relaunch session for ${node.id}: ${e?.message}`));
@@ -22881,6 +22998,7 @@ async function pollAssignedTaskTerminalEvidence(components, mesh, row) {
22881
22998
  const messages = Array.isArray(payload.messages) ? payload.messages : [];
22882
22999
  const evidence = extractFinalAssistantSummaryEvidence(messages);
22883
23000
  if (!evidence.finalSummary) return null;
23001
+ if (hasTrailingToolActivityAfterFinalAssistant(messages)) return null;
22884
23002
  const dispatchedAtMs = Date.parse(readNonEmptyString(row.dispatchTimestamp));
22885
23003
  const transcriptAtMs = Date.parse(evidence.transcriptMessageAt ?? "");
22886
23004
  if (!(Number.isFinite(dispatchedAtMs) && Number.isFinite(transcriptAtMs) && transcriptAtMs >= dispatchedAtMs)) {
@@ -23173,6 +23291,52 @@ function assignedRowLiveStatusIsAwaitingApproval(mesh, nodeId, sessionId) {
23173
23291
  return false;
23174
23292
  }
23175
23293
  }
23294
+ function resolveLocalSessionPurePty(components, sessionId) {
23295
+ try {
23296
+ const instances = components.instanceManager?.getByCategory?.("cli") || [];
23297
+ const inst = instances.find((i) => {
23298
+ const sid = readNonEmptyString(i?.getState?.().instanceId);
23299
+ return sid && sessionIdsEquivalent(sid, sessionId);
23300
+ });
23301
+ if (!inst) return void 0;
23302
+ const provider = inst.provider;
23303
+ if (!provider || typeof provider !== "object") return void 0;
23304
+ return isPurePtyTranscriptProvider(provider);
23305
+ } catch {
23306
+ return void 0;
23307
+ }
23308
+ }
23309
+ async function evaluateEarlyIdleTranscriptArm(components, mesh, store, row, localDaemonId, selfIds = []) {
23310
+ const sessionId = readNonEmptyString(row.assignedSessionId);
23311
+ if (!sessionId) return false;
23312
+ const verdict = resolveSessionBusyVerdict(components, sessionId);
23313
+ if (verdict === "GENERATING") return false;
23314
+ if (verdict === "UNKNOWN") {
23315
+ const nodeId = readNonEmptyString(row.assignedNodeId);
23316
+ const node = (mesh.nodes ?? []).find((n) => n.id === nodeId);
23317
+ const liveStatus = nodeId ? readNonEmptyString(sessionStatusFromNodes(mesh.nodes, nodeId, sessionId).status).toLowerCase() : "";
23318
+ if (liveStatus && liveStatus !== "idle") return false;
23319
+ if (!liveStatus) {
23320
+ const nodeDaemonId = readNonEmptyString(node?.daemonId);
23321
+ const isLocalNode = !nodeDaemonId || daemonIdsEquivalent(nodeDaemonId, localDaemonId) || daemonIdListIncludes(selfIds, nodeDaemonId) || !!components.instanceManager?.getInstance?.(sessionId);
23322
+ const providerType = readNonEmptyString(row.assignedProviderType);
23323
+ const readArgs = {
23324
+ sessionId,
23325
+ targetSessionId: sessionId,
23326
+ tailLimit: 1,
23327
+ ...node?.workspace ? { workspace: node.workspace } : {},
23328
+ ...providerType ? { agentType: providerType, providerType } : {}
23329
+ };
23330
+ const probedStatus = await reprobeWorkerStatus(components, { isLocalNode, nodeDaemonId, readArgs });
23331
+ if (probedStatus !== "idle") return false;
23332
+ }
23333
+ }
23334
+ if (store.taskDeliveryConsumed(mesh.id, row.id)) return true;
23335
+ const localPurePty = resolveLocalSessionPurePty(components, sessionId);
23336
+ if (localPurePty === true) return true;
23337
+ if (localPurePty === false) return false;
23338
+ return verdict === "UNKNOWN";
23339
+ }
23176
23340
  async function recoverStrandedAssignedDispatches(components, mesh, store, localDaemonId, selfIds = []) {
23177
23341
  const meshId = mesh.id;
23178
23342
  const assigned = getQueue(meshId, { status: ["assigned"] });
@@ -23194,7 +23358,8 @@ async function recoverStrandedAssignedDispatches(components, mesh, store, localD
23194
23358
  if (!Number.isFinite(dispatchedAtMs)) continue;
23195
23359
  const ageMs = nowMs - dispatchedAtMs;
23196
23360
  const idleTranscriptStreakKey = `${meshId}::${row.id}`;
23197
- if (store.taskHasConfirmedDelivery(meshId, row.id) && !findTerminalLedgerEvidenceForTask({ meshId, taskId: row.id }) && readNonEmptyString(row.assignedSessionId) && resolveSessionBusyVerdict(components, row.assignedSessionId) !== "GENERATING") {
23361
+ const earlyArm = store.taskHasConfirmedDelivery(meshId, row.id) && !findTerminalLedgerEvidenceForTask({ meshId, taskId: row.id }) && readNonEmptyString(row.assignedSessionId) ? await evaluateEarlyIdleTranscriptArm(components, mesh, store, row, localDaemonId, selfIds) : false;
23362
+ if (earlyArm) {
23198
23363
  const since = assignedIdleFinalAssistantSince.get(idleTranscriptStreakKey);
23199
23364
  if (since === void 0) {
23200
23365
  assignedIdleFinalAssistantSince.set(idleTranscriptStreakKey, nowMs);
@@ -23933,6 +24098,7 @@ var init_mesh_reconcile_loop = __esm({
23933
24098
  init_mesh_reconcile_identity();
23934
24099
  init_mesh_reconcile_config();
23935
24100
  init_mesh_remote_event_pull();
24101
+ init_provider_cli_shared();
23936
24102
  init_mesh_disk_retention();
23937
24103
  init_mesh_completion_synthesis();
23938
24104
  init_mesh_active_work();
@@ -24218,6 +24384,20 @@ var init_provider_schema = __esm({
24218
24384
  }
24219
24385
  }
24220
24386
  },
24387
+ autoApproveModes: {
24388
+ type: "object",
24389
+ description: "Provider-specific auto-approve choices and their launch/runtime strategy.",
24390
+ required: ["default", "modes"],
24391
+ additionalProperties: false,
24392
+ properties: {
24393
+ default: { type: "string", minLength: 1 },
24394
+ modes: {
24395
+ type: "array",
24396
+ minItems: 1,
24397
+ items: { $ref: "#/$defs/autoApproveMode" }
24398
+ }
24399
+ }
24400
+ },
24221
24401
  sendDelayMs: {
24222
24402
  type: "number",
24223
24403
  minimum: 0,
@@ -24591,6 +24771,36 @@ var init_provider_schema = __esm({
24591
24771
  }
24592
24772
  },
24593
24773
  $defs: {
24774
+ autoApproveMode: {
24775
+ type: "object",
24776
+ required: ["id", "label", "strategy", "risk"],
24777
+ additionalProperties: false,
24778
+ properties: {
24779
+ id: { type: "string", minLength: 1 },
24780
+ label: { type: "string", minLength: 1 },
24781
+ strategy: { enum: ["pty-parse-default", "launch-args", "post-boot-command"] },
24782
+ risk: { enum: ["safe", "caution", "dangerous"] },
24783
+ warning: { type: "string", minLength: 1 },
24784
+ launchArgs: {
24785
+ type: "array",
24786
+ items: { type: "string", minLength: 1 }
24787
+ },
24788
+ removeArgs: {
24789
+ type: "array",
24790
+ items: { type: "string", minLength: 1 }
24791
+ }
24792
+ },
24793
+ allOf: [
24794
+ {
24795
+ if: { properties: { strategy: { const: "launch-args" } }, required: ["strategy"] },
24796
+ then: { required: ["launchArgs"], properties: { launchArgs: { minItems: 1 } } }
24797
+ },
24798
+ {
24799
+ if: { properties: { risk: { const: "dangerous" } }, required: ["risk"] },
24800
+ then: { required: ["warning"] }
24801
+ }
24802
+ ]
24803
+ },
24594
24804
  patternList: {
24595
24805
  type: "array",
24596
24806
  items: {
@@ -48936,6 +49146,7 @@ function formatMarkerTimestamp(timestamp) {
48936
49146
  }
48937
49147
 
48938
49148
  // src/providers/cli-provider-instance.ts
49149
+ init_auto_approve_modes();
48939
49150
  function approvalModalSignature(message, affirmativeAnchor) {
48940
49151
  return [typeof message === "string" ? message.trim() : "", affirmativeAnchor].join("::");
48941
49152
  }
@@ -50916,7 +51127,7 @@ var CliProviderInstance = class _CliProviderInstance {
50916
51127
  * resolveModal, so a plain turn that never saw an approval always returns false.
50917
51128
  */
50918
51129
  inApprovalResumeGrace(now = Date.now()) {
50919
- if (!this.isAutonomousMeshSession() || !this.shouldAutoApprove()) return false;
51130
+ if (!this.isAutonomousMeshSession() || !this.shouldUsePtyAutoApprove()) return false;
50920
51131
  const resolvedAt = typeof this.adapter?.lastApprovalResolvedAt === "number" ? this.adapter.lastApprovalResolvedAt : 0;
50921
51132
  if (resolvedAt <= 0) return false;
50922
51133
  return now - resolvedAt < _CliProviderInstance.APPROVAL_RESUME_GRACE_MS;
@@ -51021,7 +51232,7 @@ var CliProviderInstance = class _CliProviderInstance {
51021
51232
  return;
51022
51233
  }
51023
51234
  const latestStatus = this.adapter.getStatus({ allowParse: false });
51024
- const latestAutoApproveActive = latestStatus.status === "waiting_approval" && this.shouldAutoApprove();
51235
+ const latestAutoApproveActive = latestStatus.status === "waiting_approval" && this.shouldUsePtyAutoApprove();
51025
51236
  const latestVisibleStatus = latestAutoApproveActive || this.autoApproveBusy ? "generating" : latestStatus.status;
51026
51237
  LOG.debug("CLI", `[${this.type}] flush attempt: adapterStatus=${latestStatus.status} latestVisible=${latestVisibleStatus} generatingStartedAt=${this.generatingStartedAt} isWaitingForResponse=${!!this.adapter?.isWaitingForResponse} hasPartial=${!!this.adapter.getPartialResponse?.()}`);
51027
51238
  if (latestVisibleStatus !== "idle") {
@@ -51291,7 +51502,7 @@ var CliProviderInstance = class _CliProviderInstance {
51291
51502
  * session, where a human answers the prompt, is returned untouched).
51292
51503
  */
51293
51504
  stabilizeFlappingApprovalStatus(adapterStatus, now = Date.now()) {
51294
- if (!this.isAutonomousMeshSession() || !this.shouldAutoApprove()) return adapterStatus;
51505
+ if (!this.isAutonomousMeshSession() || !this.shouldUsePtyAutoApprove()) return adapterStatus;
51295
51506
  const rawStatus = adapterStatus?.status;
51296
51507
  const resolvedAt = typeof this.adapter?.lastApprovalResolvedAt === "number" ? this.adapter.lastApprovalResolvedAt : 0;
51297
51508
  if (rawStatus === "waiting_approval") {
@@ -51321,7 +51532,11 @@ var CliProviderInstance = class _CliProviderInstance {
51321
51532
  return adapterStatus;
51322
51533
  }
51323
51534
  maybeAutoApproveStatus(adapterStatus, now = Date.now()) {
51324
- if (adapterStatus?.status === "waiting_approval" && this.shouldAutoApprove() && this.manualAttendance.isAttended(now)) {
51535
+ if (!this.shouldUsePtyAutoApprove()) {
51536
+ this.resetPtyAutoApproveState();
51537
+ return false;
51538
+ }
51539
+ if (adapterStatus?.status === "waiting_approval" && this.shouldUsePtyAutoApprove() && this.manualAttendance.isAttended(now)) {
51325
51540
  this.lastAutoApprovalSignature = "";
51326
51541
  this.pendingAutoApprovalSignature = "";
51327
51542
  this.pendingAutoApprovalSince = 0;
@@ -51336,7 +51551,7 @@ var CliProviderInstance = class _CliProviderInstance {
51336
51551
  }, this.manualAttendance.remainingMs(now) + 20);
51337
51552
  return false;
51338
51553
  }
51339
- const autoApproveActive = adapterStatus?.status === "waiting_approval" && this.shouldAutoApprove();
51554
+ const autoApproveActive = adapterStatus?.status === "waiting_approval" && this.shouldUsePtyAutoApprove();
51340
51555
  if (!autoApproveActive) {
51341
51556
  this.lastAutoApprovalSignature = "";
51342
51557
  if (this.pendingAutoApprovalSince) {
@@ -52031,15 +52246,34 @@ ${buttons.join("\n")}`;
52031
52246
  get cliName() {
52032
52247
  return this.provider.name;
52033
52248
  }
52249
+ resolveAutoApproveMode() {
52250
+ return resolveProviderAutoApproveMode(this.provider, this.settings);
52251
+ }
52252
+ /** Legacy boolean view retained for internal/test compatibility. */
52034
52253
  shouldAutoApprove() {
52035
- if (typeof this.settings.autoApprove === "boolean") {
52036
- return this.settings.autoApprove;
52254
+ return this.resolveAutoApproveMode().active;
52255
+ }
52256
+ shouldUsePtyAutoApprove() {
52257
+ const resolved = this.resolveAutoApproveMode();
52258
+ return this.shouldAutoApprove() && resolved.strategy === "pty-parse-default";
52259
+ }
52260
+ resetPtyAutoApproveState() {
52261
+ this.lastAutoApprovalSignature = "";
52262
+ this.pendingAutoApprovalSignature = "";
52263
+ this.pendingAutoApprovalSince = 0;
52264
+ this.autoApproveInactiveSince = 0;
52265
+ this.autoApproveMaskSince = 0;
52266
+ this.stalledApprovalNudgeEpisode = 0;
52267
+ this.autoApproveLastModalSeenAt = 0;
52268
+ this.autoApproveBusy = false;
52269
+ if (this.autoApproveSettleTimer) {
52270
+ clearTimeout(this.autoApproveSettleTimer);
52271
+ this.autoApproveSettleTimer = null;
52037
52272
  }
52038
- const providerDefault = this.provider.settings?.autoApprove?.default;
52039
- if (typeof providerDefault === "boolean") {
52040
- return providerDefault;
52273
+ if (this.autoApproveBusyTimer) {
52274
+ clearTimeout(this.autoApproveBusyTimer);
52275
+ this.autoApproveBusyTimer = null;
52041
52276
  }
52042
- return false;
52043
52277
  }
52044
52278
  /** @see ProviderInstance.noteManualInteraction */
52045
52279
  noteManualInteraction(now = Date.now(), opts) {
@@ -52055,7 +52289,7 @@ ${buttons.join("\n")}`;
52055
52289
  * CLI-specific modal text.
52056
52290
  */
52057
52291
  autoApproveEffectivelyActive(status, now = Date.now()) {
52058
- return status === "waiting_approval" && this.shouldAutoApprove() && !this.manualAttendance.isAttended(now);
52292
+ return status === "waiting_approval" && this.shouldUsePtyAutoApprove() && !this.manualAttendance.isAttended(now);
52059
52293
  }
52060
52294
  // STATUS-MISMATCH: true once the current auto-approve episode has been masking
52061
52295
  // waiting_approval behind `generating` for longer than AUTO_APPROVE_MASK_STALL_MS without
@@ -52065,7 +52299,7 @@ ${buttons.join("\n")}`;
52065
52299
  // maybeAutoApproveStatus (driven by getState + the recheck timer during a waiting episode);
52066
52300
  // this read is side-effect-free so getStatusMetadata can consult it too.
52067
52301
  autoApproveMaskStalled(now = Date.now()) {
52068
- return this.autoApproveMaskSince > 0 && now - this.autoApproveMaskSince > _CliProviderInstance.AUTO_APPROVE_MASK_STALL_MS;
52302
+ return this.shouldUsePtyAutoApprove() && this.autoApproveMaskSince > 0 && now - this.autoApproveMaskSince > _CliProviderInstance.AUTO_APPROVE_MASK_STALL_MS;
52069
52303
  }
52070
52304
  /**
52071
52305
  * NOTIF-APPROVAL-MASKED (Q1b): surface a delegated worker's STALLED auto-approve modal
@@ -52089,6 +52323,7 @@ ${buttons.join("\n")}`;
52089
52323
  * mask-clock value) so a modal that flaps between parsed/unparsed states is announced once.
52090
52324
  */
52091
52325
  maybeEmitStalledApprovalNudge(adapterStatus, now) {
52326
+ if (!this.shouldUsePtyAutoApprove()) return;
52092
52327
  if (!this.isMeshWorkerSession()) return;
52093
52328
  if (adapterStatus?.status !== "waiting_approval") return;
52094
52329
  if (!this.autoApproveMaskStalled(now)) return;
@@ -53634,6 +53869,7 @@ function shouldRestoreHostedRuntime(record, managerTag) {
53634
53869
  }
53635
53870
 
53636
53871
  // src/commands/cli-manager.ts
53872
+ init_auto_approve_modes();
53637
53873
  function isExplicitCommand(command) {
53638
53874
  const trimmed = command.trim();
53639
53875
  return path30.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
@@ -53860,6 +54096,24 @@ function expandThinkingLaunchArgs(template, level, levelMap) {
53860
54096
  const mapped = levelMap && typeof levelMap[raw] === "string" && levelMap[raw].trim() ? levelMap[raw].trim() : raw;
53861
54097
  return template.map((part) => part.includes("{{level}}") ? part.replace("{{level}}", mapped) : part);
53862
54098
  }
54099
+ function matchesRemovedLaunchArg(arg, removeArg) {
54100
+ return arg === removeArg || removeArg.startsWith("--") && arg.startsWith(`${removeArg}=`);
54101
+ }
54102
+ function applyAutoApproveModeLaunchArgs(provider, cliArgs, settings) {
54103
+ if (!provider) return { provider, cliArgs };
54104
+ const resolved = resolveProviderAutoApproveMode(provider, settings);
54105
+ if (!resolved.active || resolved.strategy !== "launch-args") return { provider, cliArgs };
54106
+ const mode = findProviderAutoApproveMode(provider, resolved.modeId);
54107
+ if (!mode || !Array.isArray(mode.launchArgs) || mode.launchArgs.length === 0) return { provider, cliArgs };
54108
+ const removeArgs = Array.isArray(mode.removeArgs) ? mode.removeArgs : [];
54109
+ const baseArgs = provider.spawn?.args;
54110
+ const filteredBaseArgs = Array.isArray(baseArgs) && removeArgs.length > 0 ? baseArgs.filter((arg) => !removeArgs.some((removeArg) => matchesRemovedLaunchArg(arg, removeArg))) : baseArgs;
54111
+ const launchProvider = filteredBaseArgs === baseArgs ? provider : { ...provider, spawn: { ...provider.spawn, args: filteredBaseArgs } };
54112
+ return {
54113
+ provider: launchProvider,
54114
+ cliArgs: [...mode.launchArgs, ...cliArgs || []]
54115
+ };
54116
+ }
53863
54117
  function readSubcommandSessionId(args, subcommands) {
53864
54118
  const resumeIndex = args.findIndex((arg) => subcommands.includes(arg));
53865
54119
  if (resumeIndex < 0) return void 0;
@@ -54290,22 +54544,30 @@ Run 'adhdev doctor' for detailed diagnostics.`
54290
54544
  if (provider) {
54291
54545
  console.log(colorize("cyan", ` \u{1F4E6} Using provider: ${provider.name} (${provider.type})`));
54292
54546
  }
54293
- const modelLaunchArgs = expandModelLaunchArgs(provider?.modelLaunchArgs, initialModel);
54294
- const cliArgsWithModel = modelLaunchArgs ? [...modelLaunchArgs, ...cliArgs || []] : cliArgs;
54547
+ const launchSettings = {
54548
+ ...this.providerLoader.getSettings(normalizedType),
54549
+ ...options?.settingsOverride || {}
54550
+ };
54551
+ const versionResolvedProvider = provider ? this.providerLoader.resolve(cliType, { version: cliInfo.version }) || provider : void 0;
54552
+ const autoApproveLaunch = applyAutoApproveModeLaunchArgs(versionResolvedProvider, cliArgs, launchSettings);
54553
+ const launchProvider = autoApproveLaunch.provider || provider;
54554
+ const cliArgsWithAutoApprove = autoApproveLaunch.cliArgs;
54555
+ const modelLaunchArgs = expandModelLaunchArgs(launchProvider?.modelLaunchArgs, initialModel);
54556
+ const cliArgsWithModel = modelLaunchArgs ? [...modelLaunchArgs, ...cliArgsWithAutoApprove || []] : cliArgsWithAutoApprove;
54295
54557
  if (initialModel && !modelLaunchArgs) {
54296
54558
  LOG.warn("CLI", `[${normalizedType}] initialModel='${initialModel}' requested but provider declares no modelLaunchArgs template \u2014 launching without model selection.`);
54297
54559
  }
54298
54560
  const initialThinkingLevel = options?.initialThinkingLevel;
54299
- const thinkingLaunchArgs = expandThinkingLaunchArgs(provider?.thinkingLaunchArgs, initialThinkingLevel, provider?.thinkingLevelMap);
54561
+ const thinkingLaunchArgs = expandThinkingLaunchArgs(launchProvider?.thinkingLaunchArgs, initialThinkingLevel, launchProvider?.thinkingLevelMap);
54300
54562
  const cliArgsWithBrain = thinkingLaunchArgs ? [...thinkingLaunchArgs, ...cliArgsWithModel || []] : cliArgsWithModel;
54301
54563
  if (initialThinkingLevel && !thinkingLaunchArgs) {
54302
54564
  LOG.warn("CLI", `[${normalizedType}] initialThinkingLevel='${initialThinkingLevel}' requested but provider declares no thinkingLaunchArgs template \u2014 launching without thinking-level selection.`);
54303
54565
  }
54304
- const sessionBinding = resolveCliSessionBinding(provider, normalizedType, cliArgsWithBrain, options?.resumeSessionId);
54566
+ const sessionBinding = resolveCliSessionBinding(launchProvider, normalizedType, cliArgsWithBrain, options?.resumeSessionId);
54305
54567
  const resolvedCliArgs = sessionBinding.cliArgs;
54306
54568
  const instanceManager = this.deps.getInstanceManager();
54307
- if (provider && instanceManager) {
54308
- const resolvedProvider = this.providerLoader.resolve(cliType, { version: cliInfo.version }) || provider;
54569
+ if (launchProvider && instanceManager) {
54570
+ const resolvedProvider = launchProvider;
54309
54571
  await this.registerCliInstance(
54310
54572
  key2,
54311
54573
  normalizedType,
@@ -54313,7 +54575,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
54313
54575
  resolvedDir,
54314
54576
  resolvedCliArgs,
54315
54577
  resolvedProvider,
54316
- { ...this.providerLoader.getSettings(normalizedType), ...options?.settingsOverride || {} },
54578
+ launchSettings,
54317
54579
  false,
54318
54580
  {
54319
54581
  providerSessionId: sessionBinding.providerSessionId,
@@ -55152,6 +55414,7 @@ init_hash();
55152
55414
  init_logger();
55153
55415
 
55154
55416
  // src/providers/provider-schema.ts
55417
+ init_auto_approve_modes();
55155
55418
  init_open_panel_support();
55156
55419
  var VALID_CAPABILITY_MEDIA_TYPES = /* @__PURE__ */ new Set(["text", "image", "audio", "video", "resource"]);
55157
55420
  var VALID_INPUT_STRATEGIES2 = /* @__PURE__ */ new Set(["native", "native_acp", "resource_link", "text_fallback", "paste", "upload"]);
@@ -55217,6 +55480,7 @@ var KNOWN_PROVIDER_FIELDS = /* @__PURE__ */ new Set([
55217
55480
  "providerVersion",
55218
55481
  "status",
55219
55482
  "details",
55483
+ "autoApproveModes",
55220
55484
  "modelLaunchArgs",
55221
55485
  "modelOptions",
55222
55486
  "thinkingLaunchArgs",
@@ -55278,6 +55542,7 @@ function validateProviderDefinition(raw) {
55278
55542
  validateCapabilities(provider, controls, errors);
55279
55543
  validateNativeHistory(provider.nativeHistory, errors);
55280
55544
  validateMeshCoordinator(provider.meshCoordinator, errors);
55545
+ validateAutoApproveModes(provider.autoApproveModes, errors);
55281
55546
  for (const control of controls) {
55282
55547
  validateControl(control, errors);
55283
55548
  }
@@ -55286,6 +55551,75 @@ function validateProviderDefinition(raw) {
55286
55551
  }
55287
55552
  return { errors, warnings };
55288
55553
  }
55554
+ function validateAutoApproveModes(raw, errors) {
55555
+ if (raw === void 0) return;
55556
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
55557
+ errors.push("autoApproveModes must be an object");
55558
+ return;
55559
+ }
55560
+ const config = raw;
55561
+ const defaultModeId = typeof config.default === "string" ? config.default.trim() : "";
55562
+ if (!defaultModeId) {
55563
+ errors.push("autoApproveModes.default must be a non-empty string");
55564
+ } else {
55565
+ config.default = defaultModeId;
55566
+ }
55567
+ if (!Array.isArray(config.modes) || config.modes.length === 0) {
55568
+ errors.push("autoApproveModes.modes must be a non-empty array");
55569
+ return;
55570
+ }
55571
+ const ids = /* @__PURE__ */ new Set();
55572
+ for (const [index, rawMode] of config.modes.entries()) {
55573
+ const prefix = `autoApproveModes.modes[${index}]`;
55574
+ if (!rawMode || typeof rawMode !== "object" || Array.isArray(rawMode)) {
55575
+ errors.push(`${prefix} must be an object`);
55576
+ continue;
55577
+ }
55578
+ const mode = rawMode;
55579
+ const id = typeof mode.id === "string" ? mode.id.trim() : "";
55580
+ if (!id) {
55581
+ errors.push(`${prefix}.id must be a non-empty string`);
55582
+ } else if (ids.has(id)) {
55583
+ errors.push(`${prefix}.id must be unique (duplicate: ${id})`);
55584
+ } else {
55585
+ ids.add(id);
55586
+ mode.id = id;
55587
+ }
55588
+ if (typeof mode.label !== "string" || !mode.label.trim()) {
55589
+ errors.push(`${prefix}.label must be a non-empty string`);
55590
+ }
55591
+ const strategy = mode.strategy;
55592
+ if (!["pty-parse-default", "launch-args", "post-boot-command"].includes(String(strategy))) {
55593
+ errors.push(`${prefix}.strategy must be one of: pty-parse-default, launch-args, post-boot-command`);
55594
+ } else if (strategy === "post-boot-command") {
55595
+ errors.push(`${prefix}.strategy post-boot-command is reserved and unsupported in v1`);
55596
+ }
55597
+ const risk = mode.risk;
55598
+ if (!["safe", "caution", "dangerous"].includes(String(risk))) {
55599
+ errors.push(`${prefix}.risk must be one of: safe, caution, dangerous`);
55600
+ }
55601
+ for (const field of ["launchArgs", "removeArgs"]) {
55602
+ const value = mode[field];
55603
+ if (value !== void 0 && (!Array.isArray(value) || value.some((arg) => typeof arg !== "string" || !arg.trim()))) {
55604
+ errors.push(`${prefix}.${field} must be an array of non-empty strings when provided`);
55605
+ }
55606
+ }
55607
+ if (strategy === "launch-args" && (!Array.isArray(mode.launchArgs) || mode.launchArgs.length === 0)) {
55608
+ errors.push(`${prefix}.launchArgs must be a non-empty array for launch-args strategy`);
55609
+ }
55610
+ if (["safe", "caution", "dangerous"].includes(String(risk)) && deriveAutoApproveModeRisk(mode) === "dangerous") {
55611
+ mode.risk = "dangerous";
55612
+ }
55613
+ if (mode.risk === "dangerous" && (typeof mode.warning !== "string" || !mode.warning.trim())) {
55614
+ errors.push(`${prefix}.warning is required for dangerous modes`);
55615
+ } else if (mode.warning !== void 0 && (typeof mode.warning !== "string" || !mode.warning.trim())) {
55616
+ errors.push(`${prefix}.warning must be a non-empty string when provided`);
55617
+ }
55618
+ }
55619
+ if (defaultModeId && !ids.has(defaultModeId)) {
55620
+ errors.push(`autoApproveModes.default must reference an existing mode id: ${defaultModeId}`);
55621
+ }
55622
+ }
55289
55623
  function validateCapabilities(provider, controls, errors) {
55290
55624
  const capabilities = provider.capabilities;
55291
55625
  if (provider.contractVersion === 2) {
@@ -76136,6 +76470,7 @@ export {
76136
76470
  createSessionDelivery,
76137
76471
  createWorktree,
76138
76472
  daemonIdsEquivalent,
76473
+ delegatedWorkerAutoApproveSettings,
76139
76474
  deleteDirectDispatchesByTaskId,
76140
76475
  deleteMesh,
76141
76476
  deriveMeshNodeHealthFromGit,
@@ -76335,6 +76670,7 @@ export {
76335
76670
  resolveCurrentGlobalInstallSurface,
76336
76671
  resolveDebugRuntimeConfig,
76337
76672
  resolveDelegatedWorkerAutoApprove,
76673
+ resolveDelegatedWorkerDangerousModeAllow,
76338
76674
  resolveDeliveryDecision,
76339
76675
  resolveEffectiveMeshNodeHealth,
76340
76676
  resolveGitRepository,