@adhdev/daemon-core 0.6.40 → 0.6.42

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adhdev/daemon-core",
3
- "version": "0.6.40",
3
+ "version": "0.6.42",
4
4
  "description": "ADHDev daemon core — CDP, IDE detection, providers, command execution",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -149,7 +149,7 @@ export class DaemonAgentStreamManager {
149
149
  const evaluate: AgentEvaluateFn = (expr, timeout) =>
150
150
  cdp.evaluateInSessionFrame(agent.sessionId, expr, timeout);
151
151
  const state = await agent.adapter.readChat(evaluate);
152
- this.logFn(`[AgentStream] readChat(${type}) result: status=${state.status} msgs=${state.messages?.length || 0} model=${state.model || ''}${state.status === 'error' ? ' error=' + JSON.stringify((state as any).error || (state as any)._error || 'unknown') : ''}`);
152
+ LOG.debug('AgentStream', `[AgentStream] readChat(${type}) result: status=${state.status} msgs=${state.messages?.length || 0} model=${state.model || ''}${state.status === 'error' ? ' error=' + JSON.stringify((state as any).error || (state as any)._error || 'unknown') : ''}`);
153
153
  agent.lastState = state;
154
154
  agent.lastError = null;
155
155
  if (state.status === 'panel_hidden') {
@@ -61,6 +61,7 @@ export class DaemonCdpManager {
61
61
  private _targetId: string | null = null; // Connect to specific targetId (multi-window support)
62
62
  private _pageTitle: string = ''; // Connected page title
63
63
  private _targetFilter: CdpTargetFilter; // Provider-configurable target selection
64
+ private _lastDiscoveredTargets?: Set<string>;
64
65
 
65
66
  constructor(port = 9333, logFn?: (msg: string) => void, targetId?: string, targetFilter?: CdpTargetFilter) {
66
67
  this.port = port;
@@ -799,11 +800,15 @@ export class DaemonCdpManager {
799
800
  agentType: known.agentType,
800
801
  url: url,
801
802
  });
802
- this.log(`[CDP] Found agent: ${known.agentType} (${target.targetId})`);
803
+ if (!this._lastDiscoveredTargets?.has(target.targetId)) {
804
+ this.log(`[CDP] Found agent: ${known.agentType} (${target.targetId})`);
805
+ }
803
806
  break;
804
807
  }
805
808
  }
806
809
  }
810
+
811
+ this._lastDiscoveredTargets = new Set(agents.map(a => a.targetId));
807
812
  return agents;
808
813
  } catch (e) {
809
814
  this.log(`[CDP] discoverAgentWebviews error: ${(e as Error).message}`);
@@ -110,6 +110,7 @@ export class DevServer {
110
110
  { method: 'GET', pattern: /^\/api\/providers\/([^/]+)\/source$/, handler: (q, s, p) => this.handleSource(p![0], q, s) },
111
111
  { method: 'POST', pattern: /^\/api\/providers\/([^/]+)\/save$/, handler: (q, s, p) => this.handleSave(p![0], q, s) },
112
112
  { method: 'POST', pattern: /^\/api\/providers\/([^/]+)\/typeAndSend$/, handler: (q, s, p) => this.handleTypeAndSend(p![0], q, s) },
113
+ { method: 'POST', pattern: /^\/api\/providers\/([^/]+)\/typeAndSendAt$/, handler: (q, s, p) => this.handleTypeAndSendAt(p![0], q, s) },
113
114
  { method: 'GET', pattern: /^\/api\/providers\/([^/]+)\/config$/, handler: (q, s, p) => this.handleProviderConfig(p![0], q, s) },
114
115
  { method: 'POST', pattern: /^\/api\/providers\/([^/]+)\/dom-context$/, handler: (q, s, p) => this.handleDomContext(p![0], q, s) },
115
116
  { method: 'POST', pattern: /^\/api\/providers\/([^/]+)\/auto-implement$/, handler: (q, s, p) => this.handleAutoImplement(p![0], q, s) },
@@ -891,6 +892,24 @@ export class DevServer {
891
892
  }
892
893
  }
893
894
 
895
+ private async handleTypeAndSendAt(type: string, req: http.IncomingMessage, res: http.ServerResponse): Promise<void> {
896
+ const body = await this.readBody(req);
897
+ const { x, y, text } = body;
898
+ if (typeof x !== 'number' || typeof y !== 'number' || !text || typeof text !== 'string') {
899
+ this.json(res, 400, { error: 'x, y numbers and text string required' }); return;
900
+ }
901
+ const cdp = this.getCdp(type);
902
+ if (!cdp) {
903
+ this.json(res, 503, { error: `CDP not connected for '${type}'` }); return;
904
+ }
905
+ try {
906
+ const sent = await cdp.typeAndSendAt(x, y, text);
907
+ this.json(res, 200, { sent });
908
+ } catch (e: any) {
909
+ this.json(res, 500, { error: e.message });
910
+ }
911
+ }
912
+
894
913
  private async handleScriptHints(type: string, _req: http.IncomingMessage, res: http.ServerResponse): Promise<void> {
895
914
  const dir = this.findProviderDir(type);
896
915
  if (!dir) { this.json(res, 404, { error: `Provider not found: ${type}` }); return; }
@@ -459,6 +459,7 @@ export interface ProviderScripts {
459
459
  // ─── Modal/Approval ───
460
460
  /** params: { action: 'approve'|'reject'|'custom', button?: string } */
461
461
  resolveAction?: (params?: Record<string, any>) => string;
462
+ webviewResolveAction?: (params?: Record<string, any>) => string;
462
463
 
463
464
  // ─── Notifications ───
464
465
  listNotifications?: (params?: Record<string, any>) => string;
@@ -930,15 +930,24 @@ export class ProviderLoader {
930
930
  } else {
931
931
  v = JSON.stringify(v);
932
932
  }
933
- content = content.replace(new RegExp(`\\$\\{${key}\\}`, 'g'), String(v));
933
+ const re = new RegExp(`\\$\\{\\s*${key}\\s*\\}`, 'g');
934
+ content = content.replace(re, String(v));
934
935
  }
936
+ } else if (typeof args[0] === 'string') {
937
+ // Fallback for single-string arg passed as firstVal
938
+ const re = new RegExp(`\\$\\{\\s*MESSAGE\\s*\\}`, 'g');
939
+ let v = args[0];
940
+ if (!v.startsWith('"') && !v.startsWith("'") && !v.startsWith('`')) {
941
+ v = JSON.stringify(v);
942
+ }
943
+ content = content.replace(re, String(v));
935
944
  } else if (args[0] !== undefined) {
936
945
  // legacy fallback for single argument usually MESSAGE
937
946
  let v = String(args[0]);
938
947
  if (!v.startsWith('"') && !v.startsWith("'") && !v.startsWith('`')) {
939
948
  v = JSON.stringify(v);
940
949
  }
941
- content = content.replace(/\$\{MESSAGE\}/g, v);
950
+ content = content.replace(new RegExp(`\\$\\{\\s*MESSAGE\\s*\\}`, 'g'), v);
942
951
  }
943
952
  return content;
944
953
  } catch { return ''; }
@@ -145,15 +145,15 @@ export class DaemonStatusReporter {
145
145
 
146
146
  // P2P-only = 5s heartbeat → DEBUG, P2P+Server = 30s interval → INFO
147
147
  const logLevel = opts?.p2pOnly ? 'debug' : 'info';
148
- const summary = `→${target} IDE: ${ideStates.length} [${ideSummary}] CLI: ${cliStates.length} [${cliSummary}] ACP: ${acpStates.length} [${acpSummary}]`;
148
+ const baseSummary = `IDE: ${ideStates.length} [${ideSummary}] CLI: ${cliStates.length} [${cliSummary}] ACP: ${acpStates.length} [${acpSummary}]`;
149
149
  // Skip identical repeats at any level to reduce log noise
150
- const summaryChanged = summary !== this.lastStatusSummary;
150
+ const summaryChanged = baseSummary !== this.lastStatusSummary;
151
151
  if (summaryChanged) {
152
- this.lastStatusSummary = summary;
152
+ this.lastStatusSummary = baseSummary;
153
153
  if (logLevel === 'debug') {
154
- LOG.debug('StatusReport', summary);
154
+ LOG.debug('StatusReport', `→${target} ${baseSummary}`);
155
155
  } else {
156
- LOG.info('StatusReport', summary);
156
+ LOG.info('StatusReport', `→${target} ${baseSummary}`);
157
157
  }
158
158
  }
159
159