@adhdev/daemon-core 0.5.37 → 0.5.40

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.5.37",
3
+ "version": "0.5.40",
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",
@@ -62,6 +62,7 @@ export class ProviderStreamAdapter implements IAgentStreamAdapter {
62
62
  messages: data.messages || [],
63
63
  inputContent: data.inputContent || '',
64
64
  model: data.model,
65
+ mode: data.mode,
65
66
  activeModal: data.activeModal,
66
67
  };
67
68
  if (state.messages.length > 0) {
@@ -30,6 +30,7 @@ export interface AgentStreamState {
30
30
  messages: AgentChatMessage[];
31
31
  inputContent: string;
32
32
  model?: string;
33
+ mode?: string;
33
34
  activeModal?: { message: string; buttons: string[] };
34
35
  }
35
36
 
@@ -229,7 +229,15 @@ export async function handleExtensionScript(h: CommandHelpers, args: any, script
229
229
  }
230
230
 
231
231
  const scriptFn = provider.scripts[actualScriptName as keyof typeof provider.scripts] as Function;
232
- const scriptCode = scriptFn(args);
232
+ // Normalize args: script placeholders use UPPERCASE (${MODE}, ${MODEL}, ${MESSAGE})
233
+ // but WebSocket args typically use lowercase. Add uppercase versions of common keys.
234
+ const normalizedArgs = { ...args };
235
+ for (const key of ['mode', 'model', 'message', 'action', 'button', 'text', 'sessionId']) {
236
+ if (key in normalizedArgs && !(key.toUpperCase() in normalizedArgs)) {
237
+ normalizedArgs[key.toUpperCase()] = normalizedArgs[key];
238
+ }
239
+ }
240
+ const scriptCode = scriptFn(normalizedArgs);
233
241
  if (!scriptCode) return { success: false, error: `Script '${actualScriptName}' returned null` };
234
242
 
235
243
  const cdpKey = provider.category === 'ide' ? (h.currentIdeType || agentType) : (h.currentIdeType || ideType);
@@ -249,10 +257,35 @@ export async function handleExtensionScript(h: CommandHelpers, args: any, script
249
257
  break;
250
258
  }
251
259
  }
252
- if (!targetSessionId) {
253
- return { success: false, error: `No active session found for ${agentType}` };
260
+
261
+ // IDE-level scripts (model/mode) try session frame first, fallback to main page
262
+ const IDE_LEVEL_SCRIPTS = ['listModes', 'setMode', 'listModels', 'setModel'];
263
+ if (IDE_LEVEL_SCRIPTS.includes(scriptName)) {
264
+ // Try session frame first (some extensions embed mode selector in their webview)
265
+ if (targetSessionId) {
266
+ try {
267
+ result = await cdp.evaluateInSessionFrame(targetSessionId, scriptCode);
268
+ // Check if result indicates "not found" — fallback to main page
269
+ const parsed = typeof result === 'string' ? JSON.parse(result) : result;
270
+ const notFound = parsed?.error?.includes('not found') || parsed?.error?.includes('no root');
271
+ if (notFound) {
272
+ LOG.info('Command', `[ExtScript] ${scriptName} not found in session frame → trying IDE main page`);
273
+ result = await cdp.evaluate(scriptCode, 30000);
274
+ }
275
+ } catch {
276
+ LOG.info('Command', `[ExtScript] ${scriptName} session frame failed → trying IDE main page`);
277
+ result = await cdp.evaluate(scriptCode, 30000);
278
+ }
279
+ } else {
280
+ LOG.info('Command', `[ExtScript] ${scriptName} no session → trying IDE main page`);
281
+ result = await cdp.evaluate(scriptCode, 30000);
282
+ }
283
+ } else {
284
+ if (!targetSessionId) {
285
+ return { success: false, error: `No active session found for ${agentType}` };
286
+ }
287
+ result = await cdp.evaluateInSessionFrame(targetSessionId, scriptCode);
254
288
  }
255
- result = await cdp.evaluateInSessionFrame(targetSessionId, scriptCode);
256
289
  } else if (hasWebviewScript && cdp.evaluateInWebviewFrame) {
257
290
  const matchText = provider.webviewMatchText;
258
291
  const matchFn = matchText ? (body: string) => body.includes(matchText) : undefined;
@@ -339,15 +339,29 @@ export class DevServer {
339
339
  }
340
340
  this.log(`Exec script length: ${scriptCode.length}, first 50 chars: ${scriptCode.slice(0, 50)}...`);
341
341
 
342
- // Execute webview script via evaluateInWebviewFrame
343
- const isWebviewScript = provider.category === 'extension' || scriptName.toLowerCase().includes('webview');
342
+ // Execute based on provider category
343
+ const isWebviewScript = scriptName.toLowerCase().includes('webview');
344
344
  let raw: any;
345
- if (isWebviewScript) {
345
+ if (provider.category === 'extension' && !isWebviewScript) {
346
+ // Extension scripts: prefer session frame (agent webview) — matching agent-stream poller behavior
347
+ const sessions = cdp.getAgentSessions();
348
+ let sessionId: string | null = null;
349
+ for (const [sid, target] of sessions) {
350
+ if (target.agentType === type) { sessionId = sid; break; }
351
+ }
352
+ if (sessionId) {
353
+ raw = await cdp.evaluateInSessionFrame(sessionId, scriptCode);
354
+ } else if (cdp.evaluateInWebviewFrame) {
355
+ // Fallback: try evaluateInWebviewFrame
356
+ const matchText = provider.webviewMatchText;
357
+ const matchFn = matchText ? (body: string) => body.includes(matchText) : undefined;
358
+ raw = await cdp.evaluateInWebviewFrame(scriptCode, matchFn);
359
+ } else {
360
+ raw = await cdp.evaluate(scriptCode, 30000);
361
+ }
362
+ } else if (isWebviewScript && cdp.evaluateInWebviewFrame) {
346
363
  const matchText = provider.webviewMatchText;
347
364
  const matchFn = matchText ? (body: string) => body.includes(matchText) : undefined;
348
- if (!cdp.evaluateInWebviewFrame) {
349
- throw new Error(`CDP manager does not support evaluateInWebviewFrame`);
350
- }
351
365
  raw = await cdp.evaluateInWebviewFrame(scriptCode, matchFn);
352
366
  } else {
353
367
  raw = await cdp.evaluate(scriptCode, 30000);
@@ -23,6 +23,8 @@ export class ExtensionProviderInstance implements ProviderInstance {
23
23
  private agentStreams: any[] = [];
24
24
  private messages: any[] = [];
25
25
  private activeModal: any = null;
26
+ private currentModel: string = '';
27
+ private currentMode: string = '';
26
28
  private lastAgentStatus: string = 'idle';
27
29
  private generatingStartedAt: number = 0;
28
30
  private monitor: StatusMonitor;
@@ -74,6 +76,8 @@ export class ExtensionProviderInstance implements ProviderInstance {
74
76
  activeModal: this.activeModal,
75
77
  inputContent: '',
76
78
  } : null,
79
+ currentModel: this.currentModel || undefined,
80
+ currentPlan: this.currentMode || undefined,
77
81
  agentStreams: this.agentStreams,
78
82
  instanceId: this.instanceId,
79
83
  lastUpdated: Date.now(),
@@ -88,6 +92,8 @@ export class ExtensionProviderInstance implements ProviderInstance {
88
92
  if (data?.streams) this.agentStreams = data.streams;
89
93
  if (data?.messages) this.messages = data.messages;
90
94
  if (data?.activeModal !== undefined) this.activeModal = data.activeModal;
95
+ if (data?.model) this.currentModel = data.model;
96
+ if (data?.mode) this.currentMode = data.mode;
91
97
  if (data?.status) {
92
98
  const newStatus = data.status;
93
99
  this.detectTransition(newStatus, data);
@@ -221,7 +221,7 @@ export class DaemonStatusReporter {
221
221
  LOG.debug('P2P', `sent (${JSON.stringify(payload).length} bytes)`);
222
222
  }
223
223
 
224
- // ═══ Server transmit (minimal routing meta only — sanitizeForRelay removes everything else) ═══
224
+ // ═══ Server transmit (minimal routing meta only) ═══
225
225
  if (opts?.p2pOnly) return;
226
226
  const wsPayload = {
227
227
  daemonMode: true,