@adhdev/daemon-core 0.8.29 → 0.8.30

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
@@ -5714,6 +5714,55 @@ ${effect.notification.body || ""}`.trim();
5714
5714
 
5715
5715
  // src/providers/ide-provider-instance.ts
5716
5716
  init_logger();
5717
+
5718
+ // src/providers/approval-utils.ts
5719
+ var DEFAULT_APPROVAL_POSITIVE_HINTS = [
5720
+ "run",
5721
+ "approve",
5722
+ "accept",
5723
+ "allow once",
5724
+ "always allow",
5725
+ "allow",
5726
+ "yes",
5727
+ "proceed",
5728
+ "continue",
5729
+ "confirm",
5730
+ "save",
5731
+ "ok",
5732
+ "trust"
5733
+ ];
5734
+ function normalizeApprovalLabel(value) {
5735
+ return String(value || "").toLowerCase().replace(/[^\p{L}\p{N}]+/gu, " ").trim();
5736
+ }
5737
+ function getApprovalPositiveHints(provider) {
5738
+ const customHints = Array.isArray(provider?.approvalPositiveHints) ? provider.approvalPositiveHints.map((hint) => normalizeApprovalLabel(String(hint || ""))).filter(Boolean) : [];
5739
+ return customHints.length > 0 ? customHints : DEFAULT_APPROVAL_POSITIVE_HINTS;
5740
+ }
5741
+ function pickApprovalButton(buttons, provider) {
5742
+ const labels = (buttons || []).map((button) => String(button || "").trim()).filter(Boolean);
5743
+ if (labels.length === 0) {
5744
+ return { index: 0, label: "Approve" };
5745
+ }
5746
+ const normalizedButtons = labels.map((label) => normalizeApprovalLabel(label));
5747
+ const hints = getApprovalPositiveHints(provider);
5748
+ for (const hint of hints) {
5749
+ const exactIndex = normalizedButtons.findIndex((label) => label === hint);
5750
+ if (exactIndex >= 0) return { index: exactIndex, label: labels[exactIndex] };
5751
+ const prefixIndex = normalizedButtons.findIndex((label) => label.startsWith(hint));
5752
+ if (prefixIndex >= 0) return { index: prefixIndex, label: labels[prefixIndex] };
5753
+ const includeIndex = normalizedButtons.findIndex((label) => label.includes(hint));
5754
+ if (includeIndex >= 0) return { index: includeIndex, label: labels[includeIndex] };
5755
+ }
5756
+ return { index: 0, label: labels[0] };
5757
+ }
5758
+ function formatAutoApprovalMessage(modalMessage, buttonLabel) {
5759
+ const lines = [`Auto-approved${buttonLabel ? `: ${buttonLabel}` : ""}`];
5760
+ const cleanMessage = String(modalMessage || "").trim();
5761
+ if (cleanMessage) lines.push(cleanMessage);
5762
+ return lines.join("\n");
5763
+ }
5764
+
5765
+ // src/providers/ide-provider-instance.ts
5717
5766
  var IdeProviderInstance = class {
5718
5767
  type;
5719
5768
  category = "ide";
@@ -5780,6 +5829,8 @@ var IdeProviderInstance = class {
5780
5829
  }
5781
5830
  getState() {
5782
5831
  const cdp = this.context?.cdp;
5832
+ const autoApproveActive = (this.currentStatus === "waiting_approval" || this.cachedChat?.status === "waiting_approval") && this.canAutoApprove();
5833
+ const visibleStatus = autoApproveActive ? "generating" : this.currentStatus;
5783
5834
  const extensionStates = [];
5784
5835
  for (const ext of this.extensions.values()) {
5785
5836
  extensionStates.push(ext.getState());
@@ -5788,13 +5839,13 @@ var IdeProviderInstance = class {
5788
5839
  type: this.type,
5789
5840
  name: this.provider.name,
5790
5841
  category: "ide",
5791
- status: this.currentStatus,
5842
+ status: visibleStatus,
5792
5843
  activeChat: this.cachedChat ? {
5793
5844
  id: this.cachedChat.id || "active_session",
5794
5845
  title: this.cachedChat.title || this.type,
5795
- status: this.cachedChat.status || this.currentStatus,
5846
+ status: autoApproveActive && this.cachedChat.status === "waiting_approval" ? "generating" : this.cachedChat.status || visibleStatus,
5796
5847
  messages: this.mergeConversationMessages(this.cachedChat.messages || []),
5797
- activeModal: this.cachedChat.activeModal || null,
5848
+ activeModal: autoApproveActive ? null : this.cachedChat.activeModal || null,
5798
5849
  inputContent: this.cachedChat.inputContent || ""
5799
5850
  } : null,
5800
5851
  workspace: this.workspace || null,
@@ -6013,7 +6064,9 @@ var IdeProviderInstance = class {
6013
6064
  const chatStatus = chatData?.status;
6014
6065
  if (!chatStatus) return;
6015
6066
  const agentKey = `${this.type}:native`;
6016
- const agentStatus = chatStatus === "streaming" || chatStatus === "generating" ? "generating" : chatStatus === "waiting_approval" ? "waiting_approval" : "idle";
6067
+ const rawAgentStatus = chatStatus === "streaming" || chatStatus === "generating" ? "generating" : chatStatus === "waiting_approval" ? "waiting_approval" : "idle";
6068
+ const autoApproveActive = rawAgentStatus === "waiting_approval" && this.canAutoApprove();
6069
+ const agentStatus = autoApproveActive ? "generating" : rawAgentStatus;
6017
6070
  const lastMsg = Array.isArray(chatData?.messages) && chatData.messages.length > 0 ? chatData.messages[chatData.messages.length - 1] : null;
6018
6071
  const progressFingerprint = agentStatus === "generating" ? `${lastMsg?.role || ""}:${typeof lastMsg?.content === "string" ? lastMsg.content : JSON.stringify(lastMsg?.content || "")}`.slice(-2e3) : void 0;
6019
6072
  this.currentStatus = agentStatus;
@@ -6045,7 +6098,7 @@ var IdeProviderInstance = class {
6045
6098
  this.applyProviderResponse(chatData, {
6046
6099
  phase: agentStatus === "idle" && (lastStatus === "generating" || lastStatus === "waiting_approval") ? "turn_completed" : "immediate"
6047
6100
  });
6048
- if (agentStatus === "waiting_approval" && this.settings.autoApprove && !this.autoApproveBusy) {
6101
+ if (rawAgentStatus === "waiting_approval" && autoApproveActive && !this.autoApproveBusy) {
6049
6102
  this.autoApproveViaScript(chatData);
6050
6103
  }
6051
6104
  const monitorEvents = this.monitor.check(agentKey, agentStatus, now, progressFingerprint);
@@ -6196,6 +6249,9 @@ ${effect.notification.body || ""}`.trim();
6196
6249
  updateCdp(cdp) {
6197
6250
  if (this.context) this.context.cdp = cdp;
6198
6251
  }
6252
+ canAutoApprove() {
6253
+ return this.settings.autoApprove !== false && typeof this.provider.scripts?.resolveAction === "function" && !!this.context?.cdp?.isConnected;
6254
+ }
6199
6255
  // ─── Auto-approve via CDP script ────────────────────
6200
6256
  async autoApproveViaScript(_chatData) {
6201
6257
  const cdp = this.context?.cdp;
@@ -6207,17 +6263,15 @@ ${effect.notification.body || ""}`.trim();
6207
6263
  }
6208
6264
  this.autoApproveBusy = true;
6209
6265
  try {
6210
- let targetButton = _chatData?.activeModal?.buttons?.[0] || "Run";
6211
- const buttons = _chatData?.activeModal?.buttons || [];
6212
- for (const b of buttons) {
6213
- const lower = String(b).toLowerCase().replace(/[^\w]/g, "");
6214
- if (/^(run|approve|accept|yes|allow|always|proceed|save)/.test(lower)) {
6215
- targetButton = b;
6216
- break;
6217
- }
6218
- }
6266
+ const { label: targetButton } = pickApprovalButton(_chatData?.activeModal?.buttons, this.provider);
6219
6267
  const script = scriptFn({ action: "approve", button: targetButton, buttonText: targetButton });
6220
6268
  if (!script) return;
6269
+ const now = Date.now();
6270
+ this.appendRuntimeSystemMessage(
6271
+ formatAutoApprovalMessage(_chatData?.activeModal?.message, targetButton),
6272
+ `auto_approval:${now}:${targetButton}`,
6273
+ now
6274
+ );
6221
6275
  LOG.info("IdeInstance", `[IdeInstance:${this.type}] autoApprove: executing resolveAction for "${targetButton}"`);
6222
6276
  let rawResult = await cdp.evaluate(script, 1e4);
6223
6277
  if (typeof rawResult === "string") {
@@ -6239,12 +6293,6 @@ ${effect.notification.body || ""}`.trim();
6239
6293
  LOG.warn("IdeInstance", `[IdeInstance:${this.type}] autoApprove: cdp.send() not available for coordinate click`);
6240
6294
  }
6241
6295
  }
6242
- this.pushEvent({
6243
- event: "agent:auto_approved",
6244
- chatTitle: _chatData?.title || this.provider.name,
6245
- timestamp: Date.now(),
6246
- ideType: this.type
6247
- });
6248
6296
  } catch (e) {
6249
6297
  LOG.warn("IdeInstance", `[IdeInstance:${this.type}] autoApprove error: ${e?.message}`);
6250
6298
  } finally {
@@ -9412,6 +9460,8 @@ var CliProviderInstance = class {
9412
9460
  getState() {
9413
9461
  const adapterStatus = this.adapter.getStatus();
9414
9462
  const parsedStatus = this.adapter.getScriptParsedStatus?.() || null;
9463
+ const autoApproveActive = adapterStatus.status === "waiting_approval" && this.shouldAutoApprove();
9464
+ const visibleStatus = autoApproveActive ? "generating" : adapterStatus.status;
9415
9465
  const parsedProviderSessionId = typeof parsedStatus?.providerSessionId === "string" ? parsedStatus.providerSessionId.trim() : "";
9416
9466
  if (parsedProviderSessionId) {
9417
9467
  this.promoteProviderSessionId(parsedProviderSessionId);
@@ -9451,14 +9501,14 @@ var CliProviderInstance = class {
9451
9501
  type: this.type,
9452
9502
  name: this.provider.name,
9453
9503
  category: "cli",
9454
- status: adapterStatus.status,
9504
+ status: visibleStatus,
9455
9505
  mode: this.presentationMode,
9456
9506
  activeChat: {
9457
9507
  id: `${this.type}_${this.workingDir}`,
9458
9508
  title: parsedStatus?.title || dirName,
9459
- status: parsedStatus?.status || adapterStatus.status,
9509
+ status: autoApproveActive && parsedStatus?.status === "waiting_approval" ? "generating" : parsedStatus?.status || visibleStatus,
9460
9510
  messages: mergedMessages,
9461
- activeModal: parsedStatus?.activeModal ?? adapterStatus.activeModal,
9511
+ activeModal: autoApproveActive ? null : parsedStatus?.activeModal ?? adapterStatus.activeModal,
9462
9512
  inputContent: ""
9463
9513
  },
9464
9514
  workspace: this.workingDir,
@@ -9522,7 +9572,16 @@ var CliProviderInstance = class {
9522
9572
  const now = Date.now();
9523
9573
  const adapterStatus = this.adapter.getStatus();
9524
9574
  const parsedStatus = this.adapter.getScriptParsedStatus?.() || null;
9525
- const newStatus = adapterStatus.status;
9575
+ const rawStatus = adapterStatus.status;
9576
+ const autoApproveActive = rawStatus === "waiting_approval" && this.shouldAutoApprove();
9577
+ if (autoApproveActive) {
9578
+ const { index: buttonIndex, label: buttonLabel } = pickApprovalButton(adapterStatus.activeModal?.buttons, this.provider);
9579
+ this.recordAutoApproval(adapterStatus.activeModal?.message, buttonLabel, now);
9580
+ setTimeout(() => {
9581
+ this.adapter.resolveModal(buttonIndex);
9582
+ }, 0);
9583
+ }
9584
+ const newStatus = autoApproveActive ? "generating" : rawStatus;
9526
9585
  const dirName = this.workingDir.split("/").filter(Boolean).pop() || "session";
9527
9586
  const chatTitle = `${this.provider.name} \xB7 ${dirName}`;
9528
9587
  const partial = this.adapter.getPartialResponse();
@@ -9732,6 +9791,16 @@ ${effect.notification.body || ""}`.trim();
9732
9791
  get cliName() {
9733
9792
  return this.provider.name;
9734
9793
  }
9794
+ shouldAutoApprove() {
9795
+ return this.settings.autoApprove !== false;
9796
+ }
9797
+ recordAutoApproval(modalMessage, buttonLabel, now = Date.now()) {
9798
+ this.appendRuntimeSystemMessage(
9799
+ formatAutoApprovalMessage(modalMessage, buttonLabel),
9800
+ `auto_approval:${now}:${buttonLabel || "approve"}`,
9801
+ now
9802
+ );
9803
+ }
9735
9804
  recordApprovalSelection(buttonText) {
9736
9805
  const cleanButton = String(buttonText || "").trim();
9737
9806
  if (!cleanButton) return;
@@ -10310,8 +10379,10 @@ var AcpProviderInstance = class {
10310
10379
  input: tc.rawInput ? typeof tc.rawInput === "string" ? tc.rawInput : JSON.stringify(tc.rawInput) : void 0
10311
10380
  });
10312
10381
  }
10313
- if (this.settings.autoApprove) {
10314
- this.log.info(`[${this.type}] Auto-approving: ${tc.title || tc.toolCallId}`);
10382
+ if (this.settings.autoApprove !== false) {
10383
+ const toolTitle = tc.title || tc.toolCallId || "tool call";
10384
+ this.log.info(`[${this.type}] Auto-approving: ${toolTitle}`);
10385
+ this.appendSystemMessage(`Auto-approved: ${toolTitle}`);
10315
10386
  const allowOption = params.options.find((o) => o.kind === "allow_once") || params.options.find((o) => o.kind === "allow_always");
10316
10387
  if (allowOption) {
10317
10388
  return { outcome: { outcome: "selected", optionId: allowOption.optionId } };
@@ -10763,6 +10834,18 @@ var AcpProviderInstance = class {
10763
10834
  this.events.push(event);
10764
10835
  if (this.events.length > 50) this.events = this.events.slice(-50);
10765
10836
  }
10837
+ appendSystemMessage(content, timestamp = Date.now()) {
10838
+ const normalizedContent = String(content || "").trim();
10839
+ if (!normalizedContent) return;
10840
+ this.messages.push({
10841
+ role: "system",
10842
+ content: normalizedContent,
10843
+ timestamp
10844
+ });
10845
+ if (this.messages.length > 200) {
10846
+ this.messages = this.messages.slice(-100);
10847
+ }
10848
+ }
10766
10849
  flushEvents() {
10767
10850
  const events = [...this.events];
10768
10851
  this.events = [];
@@ -12337,7 +12420,7 @@ var ProviderLoader = class _ProviderLoader {
12337
12420
  */
12338
12421
  getSettingValue(type, key) {
12339
12422
  const schemaDef = this.getSettingsSchema(type)[key];
12340
- const defaultVal = schemaDef ? schemaDef.default : void 0;
12423
+ const defaultVal = schemaDef ? key === "autoApprove" && schemaDef.type === "boolean" ? true : schemaDef.default : void 0;
12341
12424
  try {
12342
12425
  const { loadConfig: loadConfig2 } = (init_config(), __toCommonJS(config_exports));
12343
12426
  const config = loadConfig2();
@@ -12396,13 +12479,32 @@ var ProviderLoader = class _ProviderLoader {
12396
12479
  getSettingsSchema(type) {
12397
12480
  const provider = this.providers.get(type);
12398
12481
  if (!provider) return {};
12399
- return {
12482
+ const result = {
12400
12483
  ...this.getSyntheticSettings(type, provider),
12401
12484
  ...provider.settings || {}
12402
12485
  };
12486
+ if (result.autoApprove?.type === "boolean") {
12487
+ result.autoApprove = {
12488
+ ...result.autoApprove,
12489
+ default: true,
12490
+ public: true,
12491
+ label: result.autoApprove.label || "Auto Approve",
12492
+ description: result.autoApprove.description || "Automatically approve actionable prompts without sending approval alerts."
12493
+ };
12494
+ }
12495
+ return result;
12403
12496
  }
12404
12497
  getSyntheticSettings(type, provider) {
12405
12498
  const result = {};
12499
+ if (!provider.settings?.autoApprove) {
12500
+ result.autoApprove = {
12501
+ type: "boolean",
12502
+ default: true,
12503
+ public: true,
12504
+ label: "Auto Approve",
12505
+ description: "Automatically approve actionable prompts without sending approval alerts."
12506
+ };
12507
+ }
12406
12508
  if ((provider.category === "cli" || provider.category === "acp") && provider.spawn?.command && !provider.settings?.executablePath) {
12407
12509
  result.executablePath = {
12408
12510
  type: "string",
@@ -14888,7 +14990,43 @@ var AgentStreamPoller = class {
14888
14990
  }
14889
14991
  try {
14890
14992
  await agentStreamManager.syncActiveSession(cdp, parentSessionId);
14891
- const stream = await agentStreamManager.collectActiveSession(cdp, parentSessionId);
14993
+ let stream = await agentStreamManager.collectActiveSession(cdp, parentSessionId);
14994
+ if (stream?.status === "waiting_approval") {
14995
+ const autoApprove = providerLoader.getSettings(stream.agentType).autoApprove !== false;
14996
+ if (autoApprove && resolvedActiveSessionId) {
14997
+ const provider = providerLoader.getMeta(stream.agentType);
14998
+ const { label: buttonLabel } = pickApprovalButton(stream.activeModal?.buttons, provider);
14999
+ const approved = await agentStreamManager.resolveSessionAction(cdp, resolvedActiveSessionId, "approve", buttonLabel);
15000
+ if (approved) {
15001
+ const effectId = [
15002
+ "auto_approval",
15003
+ resolvedActiveSessionId,
15004
+ String(stream.messages?.length || 0),
15005
+ buttonLabel,
15006
+ String(stream.activeModal?.message || "").trim()
15007
+ ].join(":");
15008
+ stream = {
15009
+ ...stream,
15010
+ status: "streaming",
15011
+ activeModal: void 0,
15012
+ effects: [
15013
+ ...stream.effects || [],
15014
+ {
15015
+ type: "message",
15016
+ id: effectId,
15017
+ persist: true,
15018
+ message: {
15019
+ role: "system",
15020
+ senderName: "System",
15021
+ kind: "system",
15022
+ content: formatAutoApprovalMessage(stream.activeModal?.message, buttonLabel)
15023
+ }
15024
+ }
15025
+ ]
15026
+ };
15027
+ }
15028
+ }
15029
+ }
14892
15030
  this.deps.onStreamsUpdated?.(ideType, stream ? [stream] : []);
14893
15031
  } catch {
14894
15032
  }