@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.js CHANGED
@@ -5799,6 +5799,55 @@ ${effect.notification.body || ""}`.trim();
5799
5799
 
5800
5800
  // src/providers/ide-provider-instance.ts
5801
5801
  init_logger();
5802
+
5803
+ // src/providers/approval-utils.ts
5804
+ var DEFAULT_APPROVAL_POSITIVE_HINTS = [
5805
+ "run",
5806
+ "approve",
5807
+ "accept",
5808
+ "allow once",
5809
+ "always allow",
5810
+ "allow",
5811
+ "yes",
5812
+ "proceed",
5813
+ "continue",
5814
+ "confirm",
5815
+ "save",
5816
+ "ok",
5817
+ "trust"
5818
+ ];
5819
+ function normalizeApprovalLabel(value) {
5820
+ return String(value || "").toLowerCase().replace(/[^\p{L}\p{N}]+/gu, " ").trim();
5821
+ }
5822
+ function getApprovalPositiveHints(provider) {
5823
+ const customHints = Array.isArray(provider?.approvalPositiveHints) ? provider.approvalPositiveHints.map((hint) => normalizeApprovalLabel(String(hint || ""))).filter(Boolean) : [];
5824
+ return customHints.length > 0 ? customHints : DEFAULT_APPROVAL_POSITIVE_HINTS;
5825
+ }
5826
+ function pickApprovalButton(buttons, provider) {
5827
+ const labels = (buttons || []).map((button) => String(button || "").trim()).filter(Boolean);
5828
+ if (labels.length === 0) {
5829
+ return { index: 0, label: "Approve" };
5830
+ }
5831
+ const normalizedButtons = labels.map((label) => normalizeApprovalLabel(label));
5832
+ const hints = getApprovalPositiveHints(provider);
5833
+ for (const hint of hints) {
5834
+ const exactIndex = normalizedButtons.findIndex((label) => label === hint);
5835
+ if (exactIndex >= 0) return { index: exactIndex, label: labels[exactIndex] };
5836
+ const prefixIndex = normalizedButtons.findIndex((label) => label.startsWith(hint));
5837
+ if (prefixIndex >= 0) return { index: prefixIndex, label: labels[prefixIndex] };
5838
+ const includeIndex = normalizedButtons.findIndex((label) => label.includes(hint));
5839
+ if (includeIndex >= 0) return { index: includeIndex, label: labels[includeIndex] };
5840
+ }
5841
+ return { index: 0, label: labels[0] };
5842
+ }
5843
+ function formatAutoApprovalMessage(modalMessage, buttonLabel) {
5844
+ const lines = [`Auto-approved${buttonLabel ? `: ${buttonLabel}` : ""}`];
5845
+ const cleanMessage = String(modalMessage || "").trim();
5846
+ if (cleanMessage) lines.push(cleanMessage);
5847
+ return lines.join("\n");
5848
+ }
5849
+
5850
+ // src/providers/ide-provider-instance.ts
5802
5851
  var IdeProviderInstance = class {
5803
5852
  type;
5804
5853
  category = "ide";
@@ -5865,6 +5914,8 @@ var IdeProviderInstance = class {
5865
5914
  }
5866
5915
  getState() {
5867
5916
  const cdp = this.context?.cdp;
5917
+ const autoApproveActive = (this.currentStatus === "waiting_approval" || this.cachedChat?.status === "waiting_approval") && this.canAutoApprove();
5918
+ const visibleStatus = autoApproveActive ? "generating" : this.currentStatus;
5868
5919
  const extensionStates = [];
5869
5920
  for (const ext of this.extensions.values()) {
5870
5921
  extensionStates.push(ext.getState());
@@ -5873,13 +5924,13 @@ var IdeProviderInstance = class {
5873
5924
  type: this.type,
5874
5925
  name: this.provider.name,
5875
5926
  category: "ide",
5876
- status: this.currentStatus,
5927
+ status: visibleStatus,
5877
5928
  activeChat: this.cachedChat ? {
5878
5929
  id: this.cachedChat.id || "active_session",
5879
5930
  title: this.cachedChat.title || this.type,
5880
- status: this.cachedChat.status || this.currentStatus,
5931
+ status: autoApproveActive && this.cachedChat.status === "waiting_approval" ? "generating" : this.cachedChat.status || visibleStatus,
5881
5932
  messages: this.mergeConversationMessages(this.cachedChat.messages || []),
5882
- activeModal: this.cachedChat.activeModal || null,
5933
+ activeModal: autoApproveActive ? null : this.cachedChat.activeModal || null,
5883
5934
  inputContent: this.cachedChat.inputContent || ""
5884
5935
  } : null,
5885
5936
  workspace: this.workspace || null,
@@ -6098,7 +6149,9 @@ var IdeProviderInstance = class {
6098
6149
  const chatStatus = chatData?.status;
6099
6150
  if (!chatStatus) return;
6100
6151
  const agentKey = `${this.type}:native`;
6101
- const agentStatus = chatStatus === "streaming" || chatStatus === "generating" ? "generating" : chatStatus === "waiting_approval" ? "waiting_approval" : "idle";
6152
+ const rawAgentStatus = chatStatus === "streaming" || chatStatus === "generating" ? "generating" : chatStatus === "waiting_approval" ? "waiting_approval" : "idle";
6153
+ const autoApproveActive = rawAgentStatus === "waiting_approval" && this.canAutoApprove();
6154
+ const agentStatus = autoApproveActive ? "generating" : rawAgentStatus;
6102
6155
  const lastMsg = Array.isArray(chatData?.messages) && chatData.messages.length > 0 ? chatData.messages[chatData.messages.length - 1] : null;
6103
6156
  const progressFingerprint = agentStatus === "generating" ? `${lastMsg?.role || ""}:${typeof lastMsg?.content === "string" ? lastMsg.content : JSON.stringify(lastMsg?.content || "")}`.slice(-2e3) : void 0;
6104
6157
  this.currentStatus = agentStatus;
@@ -6130,7 +6183,7 @@ var IdeProviderInstance = class {
6130
6183
  this.applyProviderResponse(chatData, {
6131
6184
  phase: agentStatus === "idle" && (lastStatus === "generating" || lastStatus === "waiting_approval") ? "turn_completed" : "immediate"
6132
6185
  });
6133
- if (agentStatus === "waiting_approval" && this.settings.autoApprove && !this.autoApproveBusy) {
6186
+ if (rawAgentStatus === "waiting_approval" && autoApproveActive && !this.autoApproveBusy) {
6134
6187
  this.autoApproveViaScript(chatData);
6135
6188
  }
6136
6189
  const monitorEvents = this.monitor.check(agentKey, agentStatus, now, progressFingerprint);
@@ -6281,6 +6334,9 @@ ${effect.notification.body || ""}`.trim();
6281
6334
  updateCdp(cdp) {
6282
6335
  if (this.context) this.context.cdp = cdp;
6283
6336
  }
6337
+ canAutoApprove() {
6338
+ return this.settings.autoApprove !== false && typeof this.provider.scripts?.resolveAction === "function" && !!this.context?.cdp?.isConnected;
6339
+ }
6284
6340
  // ─── Auto-approve via CDP script ────────────────────
6285
6341
  async autoApproveViaScript(_chatData) {
6286
6342
  const cdp = this.context?.cdp;
@@ -6292,17 +6348,15 @@ ${effect.notification.body || ""}`.trim();
6292
6348
  }
6293
6349
  this.autoApproveBusy = true;
6294
6350
  try {
6295
- let targetButton = _chatData?.activeModal?.buttons?.[0] || "Run";
6296
- const buttons = _chatData?.activeModal?.buttons || [];
6297
- for (const b of buttons) {
6298
- const lower = String(b).toLowerCase().replace(/[^\w]/g, "");
6299
- if (/^(run|approve|accept|yes|allow|always|proceed|save)/.test(lower)) {
6300
- targetButton = b;
6301
- break;
6302
- }
6303
- }
6351
+ const { label: targetButton } = pickApprovalButton(_chatData?.activeModal?.buttons, this.provider);
6304
6352
  const script = scriptFn({ action: "approve", button: targetButton, buttonText: targetButton });
6305
6353
  if (!script) return;
6354
+ const now = Date.now();
6355
+ this.appendRuntimeSystemMessage(
6356
+ formatAutoApprovalMessage(_chatData?.activeModal?.message, targetButton),
6357
+ `auto_approval:${now}:${targetButton}`,
6358
+ now
6359
+ );
6306
6360
  LOG.info("IdeInstance", `[IdeInstance:${this.type}] autoApprove: executing resolveAction for "${targetButton}"`);
6307
6361
  let rawResult = await cdp.evaluate(script, 1e4);
6308
6362
  if (typeof rawResult === "string") {
@@ -6324,12 +6378,6 @@ ${effect.notification.body || ""}`.trim();
6324
6378
  LOG.warn("IdeInstance", `[IdeInstance:${this.type}] autoApprove: cdp.send() not available for coordinate click`);
6325
6379
  }
6326
6380
  }
6327
- this.pushEvent({
6328
- event: "agent:auto_approved",
6329
- chatTitle: _chatData?.title || this.provider.name,
6330
- timestamp: Date.now(),
6331
- ideType: this.type
6332
- });
6333
6381
  } catch (e) {
6334
6382
  LOG.warn("IdeInstance", `[IdeInstance:${this.type}] autoApprove error: ${e?.message}`);
6335
6383
  } finally {
@@ -9497,6 +9545,8 @@ var CliProviderInstance = class {
9497
9545
  getState() {
9498
9546
  const adapterStatus = this.adapter.getStatus();
9499
9547
  const parsedStatus = this.adapter.getScriptParsedStatus?.() || null;
9548
+ const autoApproveActive = adapterStatus.status === "waiting_approval" && this.shouldAutoApprove();
9549
+ const visibleStatus = autoApproveActive ? "generating" : adapterStatus.status;
9500
9550
  const parsedProviderSessionId = typeof parsedStatus?.providerSessionId === "string" ? parsedStatus.providerSessionId.trim() : "";
9501
9551
  if (parsedProviderSessionId) {
9502
9552
  this.promoteProviderSessionId(parsedProviderSessionId);
@@ -9536,14 +9586,14 @@ var CliProviderInstance = class {
9536
9586
  type: this.type,
9537
9587
  name: this.provider.name,
9538
9588
  category: "cli",
9539
- status: adapterStatus.status,
9589
+ status: visibleStatus,
9540
9590
  mode: this.presentationMode,
9541
9591
  activeChat: {
9542
9592
  id: `${this.type}_${this.workingDir}`,
9543
9593
  title: parsedStatus?.title || dirName,
9544
- status: parsedStatus?.status || adapterStatus.status,
9594
+ status: autoApproveActive && parsedStatus?.status === "waiting_approval" ? "generating" : parsedStatus?.status || visibleStatus,
9545
9595
  messages: mergedMessages,
9546
- activeModal: parsedStatus?.activeModal ?? adapterStatus.activeModal,
9596
+ activeModal: autoApproveActive ? null : parsedStatus?.activeModal ?? adapterStatus.activeModal,
9547
9597
  inputContent: ""
9548
9598
  },
9549
9599
  workspace: this.workingDir,
@@ -9607,7 +9657,16 @@ var CliProviderInstance = class {
9607
9657
  const now = Date.now();
9608
9658
  const adapterStatus = this.adapter.getStatus();
9609
9659
  const parsedStatus = this.adapter.getScriptParsedStatus?.() || null;
9610
- const newStatus = adapterStatus.status;
9660
+ const rawStatus = adapterStatus.status;
9661
+ const autoApproveActive = rawStatus === "waiting_approval" && this.shouldAutoApprove();
9662
+ if (autoApproveActive) {
9663
+ const { index: buttonIndex, label: buttonLabel } = pickApprovalButton(adapterStatus.activeModal?.buttons, this.provider);
9664
+ this.recordAutoApproval(adapterStatus.activeModal?.message, buttonLabel, now);
9665
+ setTimeout(() => {
9666
+ this.adapter.resolveModal(buttonIndex);
9667
+ }, 0);
9668
+ }
9669
+ const newStatus = autoApproveActive ? "generating" : rawStatus;
9611
9670
  const dirName = this.workingDir.split("/").filter(Boolean).pop() || "session";
9612
9671
  const chatTitle = `${this.provider.name} \xB7 ${dirName}`;
9613
9672
  const partial = this.adapter.getPartialResponse();
@@ -9817,6 +9876,16 @@ ${effect.notification.body || ""}`.trim();
9817
9876
  get cliName() {
9818
9877
  return this.provider.name;
9819
9878
  }
9879
+ shouldAutoApprove() {
9880
+ return this.settings.autoApprove !== false;
9881
+ }
9882
+ recordAutoApproval(modalMessage, buttonLabel, now = Date.now()) {
9883
+ this.appendRuntimeSystemMessage(
9884
+ formatAutoApprovalMessage(modalMessage, buttonLabel),
9885
+ `auto_approval:${now}:${buttonLabel || "approve"}`,
9886
+ now
9887
+ );
9888
+ }
9820
9889
  recordApprovalSelection(buttonText) {
9821
9890
  const cleanButton = String(buttonText || "").trim();
9822
9891
  if (!cleanButton) return;
@@ -10390,8 +10459,10 @@ var AcpProviderInstance = class {
10390
10459
  input: tc.rawInput ? typeof tc.rawInput === "string" ? tc.rawInput : JSON.stringify(tc.rawInput) : void 0
10391
10460
  });
10392
10461
  }
10393
- if (this.settings.autoApprove) {
10394
- this.log.info(`[${this.type}] Auto-approving: ${tc.title || tc.toolCallId}`);
10462
+ if (this.settings.autoApprove !== false) {
10463
+ const toolTitle = tc.title || tc.toolCallId || "tool call";
10464
+ this.log.info(`[${this.type}] Auto-approving: ${toolTitle}`);
10465
+ this.appendSystemMessage(`Auto-approved: ${toolTitle}`);
10395
10466
  const allowOption = params.options.find((o) => o.kind === "allow_once") || params.options.find((o) => o.kind === "allow_always");
10396
10467
  if (allowOption) {
10397
10468
  return { outcome: { outcome: "selected", optionId: allowOption.optionId } };
@@ -10843,6 +10914,18 @@ var AcpProviderInstance = class {
10843
10914
  this.events.push(event);
10844
10915
  if (this.events.length > 50) this.events = this.events.slice(-50);
10845
10916
  }
10917
+ appendSystemMessage(content, timestamp = Date.now()) {
10918
+ const normalizedContent = String(content || "").trim();
10919
+ if (!normalizedContent) return;
10920
+ this.messages.push({
10921
+ role: "system",
10922
+ content: normalizedContent,
10923
+ timestamp
10924
+ });
10925
+ if (this.messages.length > 200) {
10926
+ this.messages = this.messages.slice(-100);
10927
+ }
10928
+ }
10846
10929
  flushEvents() {
10847
10930
  const events = [...this.events];
10848
10931
  this.events = [];
@@ -12417,7 +12500,7 @@ var ProviderLoader = class _ProviderLoader {
12417
12500
  */
12418
12501
  getSettingValue(type, key) {
12419
12502
  const schemaDef = this.getSettingsSchema(type)[key];
12420
- const defaultVal = schemaDef ? schemaDef.default : void 0;
12503
+ const defaultVal = schemaDef ? key === "autoApprove" && schemaDef.type === "boolean" ? true : schemaDef.default : void 0;
12421
12504
  try {
12422
12505
  const { loadConfig: loadConfig2 } = (init_config(), __toCommonJS(config_exports));
12423
12506
  const config = loadConfig2();
@@ -12476,13 +12559,32 @@ var ProviderLoader = class _ProviderLoader {
12476
12559
  getSettingsSchema(type) {
12477
12560
  const provider = this.providers.get(type);
12478
12561
  if (!provider) return {};
12479
- return {
12562
+ const result = {
12480
12563
  ...this.getSyntheticSettings(type, provider),
12481
12564
  ...provider.settings || {}
12482
12565
  };
12566
+ if (result.autoApprove?.type === "boolean") {
12567
+ result.autoApprove = {
12568
+ ...result.autoApprove,
12569
+ default: true,
12570
+ public: true,
12571
+ label: result.autoApprove.label || "Auto Approve",
12572
+ description: result.autoApprove.description || "Automatically approve actionable prompts without sending approval alerts."
12573
+ };
12574
+ }
12575
+ return result;
12483
12576
  }
12484
12577
  getSyntheticSettings(type, provider) {
12485
12578
  const result = {};
12579
+ if (!provider.settings?.autoApprove) {
12580
+ result.autoApprove = {
12581
+ type: "boolean",
12582
+ default: true,
12583
+ public: true,
12584
+ label: "Auto Approve",
12585
+ description: "Automatically approve actionable prompts without sending approval alerts."
12586
+ };
12587
+ }
12486
12588
  if ((provider.category === "cli" || provider.category === "acp") && provider.spawn?.command && !provider.settings?.executablePath) {
12487
12589
  result.executablePath = {
12488
12590
  type: "string",
@@ -14968,7 +15070,43 @@ var AgentStreamPoller = class {
14968
15070
  }
14969
15071
  try {
14970
15072
  await agentStreamManager.syncActiveSession(cdp, parentSessionId);
14971
- const stream = await agentStreamManager.collectActiveSession(cdp, parentSessionId);
15073
+ let stream = await agentStreamManager.collectActiveSession(cdp, parentSessionId);
15074
+ if (stream?.status === "waiting_approval") {
15075
+ const autoApprove = providerLoader.getSettings(stream.agentType).autoApprove !== false;
15076
+ if (autoApprove && resolvedActiveSessionId) {
15077
+ const provider = providerLoader.getMeta(stream.agentType);
15078
+ const { label: buttonLabel } = pickApprovalButton(stream.activeModal?.buttons, provider);
15079
+ const approved = await agentStreamManager.resolveSessionAction(cdp, resolvedActiveSessionId, "approve", buttonLabel);
15080
+ if (approved) {
15081
+ const effectId = [
15082
+ "auto_approval",
15083
+ resolvedActiveSessionId,
15084
+ String(stream.messages?.length || 0),
15085
+ buttonLabel,
15086
+ String(stream.activeModal?.message || "").trim()
15087
+ ].join(":");
15088
+ stream = {
15089
+ ...stream,
15090
+ status: "streaming",
15091
+ activeModal: void 0,
15092
+ effects: [
15093
+ ...stream.effects || [],
15094
+ {
15095
+ type: "message",
15096
+ id: effectId,
15097
+ persist: true,
15098
+ message: {
15099
+ role: "system",
15100
+ senderName: "System",
15101
+ kind: "system",
15102
+ content: formatAutoApprovalMessage(stream.activeModal?.message, buttonLabel)
15103
+ }
15104
+ }
15105
+ ]
15106
+ };
15107
+ }
15108
+ }
15109
+ }
14972
15110
  this.deps.onStreamsUpdated?.(ideType, stream ? [stream] : []);
14973
15111
  } catch {
14974
15112
  }