@adhdev/daemon-core 0.8.21 → 0.8.23
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/agent-stream/types.d.ts +3 -0
- package/dist/cli-adapter-types.d.ts +3 -0
- package/dist/cli-adapters/provider-cli-adapter.d.ts +71 -11
- package/dist/commands/stream-commands.d.ts +1 -0
- package/dist/config/config.d.ts +6 -0
- package/dist/index.js +1163 -314
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1163 -314
- package/dist/index.mjs.map +1 -1
- package/dist/providers/cli-provider-instance.d.ts +6 -0
- package/dist/providers/contracts.d.ts +59 -1
- package/dist/providers/control-effects.d.ts +4 -0
- package/dist/providers/extension-provider-instance.d.ts +9 -0
- package/dist/providers/ide-provider-instance.d.ts +8 -0
- package/dist/shared-types.d.ts +2 -1
- package/node_modules/@adhdev/session-host-core/package.json +1 -1
- package/package.json +3 -2
- package/src/agent-stream/forward.ts +2 -0
- package/src/agent-stream/provider-adapter.ts +5 -15
- package/src/agent-stream/types.ts +4 -0
- package/src/cli-adapter-types.ts +3 -0
- package/src/cli-adapters/provider-cli-adapter.ts +399 -49
- package/src/commands/chat-commands.ts +33 -12
- package/src/commands/handler.ts +1 -0
- package/src/commands/stream-commands.ts +99 -8
- package/src/config/config.d.ts +1 -0
- package/src/config/config.ts +9 -0
- package/src/launch.ts +57 -11
- package/src/providers/cli-provider-instance.ts +148 -2
- package/src/providers/contracts.ts +65 -2
- package/src/providers/control-effects.ts +114 -0
- package/src/providers/extension-provider-instance.ts +163 -3
- package/src/providers/ide-provider-instance.ts +181 -2
- package/src/shared-types.d.ts +1 -0
- package/src/shared-types.ts +2 -1
- package/src/status/snapshot.ts +1 -0
|
@@ -17,6 +17,8 @@ import { ExtensionProviderInstance } from './extension-provider-instance.js';
|
|
|
17
17
|
import { StatusMonitor } from './status-monitor.js';
|
|
18
18
|
import { ChatHistoryWriter } from '../config/chat-history.js';
|
|
19
19
|
import { LOG } from '../logging/logger.js';
|
|
20
|
+
import { extractProviderControlValues, normalizeProviderEffects } from './control-effects.js';
|
|
21
|
+
import type { ChatMessage } from '../types.js';
|
|
20
22
|
|
|
21
23
|
export class IdeProviderInstance implements ProviderInstance {
|
|
22
24
|
readonly type: string;
|
|
@@ -37,6 +39,8 @@ export class IdeProviderInstance implements ProviderInstance {
|
|
|
37
39
|
private monitor: StatusMonitor;
|
|
38
40
|
private historyWriter: ChatHistoryWriter;
|
|
39
41
|
private autoApproveBusy = false;
|
|
42
|
+
private appliedEffectKeys = new Set<string>();
|
|
43
|
+
private runtimeMessages: Array<{ key: string; message: ChatMessage }> = [];
|
|
40
44
|
|
|
41
45
|
// IDE meta
|
|
42
46
|
private ideVersion: string = '';
|
|
@@ -115,7 +119,7 @@ export class IdeProviderInstance implements ProviderInstance {
|
|
|
115
119
|
id: this.cachedChat.id || 'active_session',
|
|
116
120
|
title: this.cachedChat.title || this.type,
|
|
117
121
|
status: this.cachedChat.status || this.currentStatus,
|
|
118
|
-
messages: this.cachedChat.messages || [],
|
|
122
|
+
messages: this.mergeConversationMessages(this.cachedChat.messages || []),
|
|
119
123
|
activeModal: this.cachedChat.activeModal || null,
|
|
120
124
|
inputContent: this.cachedChat.inputContent || '',
|
|
121
125
|
} : null,
|
|
@@ -136,7 +140,7 @@ export class IdeProviderInstance implements ProviderInstance {
|
|
|
136
140
|
|
|
137
141
|
onEvent(event: string, data?: any): void {
|
|
138
142
|
if (event === 'cdp_connected') {
|
|
139
|
-
|
|
143
|
+
// CDP connection done
|
|
140
144
|
} else if (event === 'cdp_disconnected') {
|
|
141
145
|
this.cachedChat = null;
|
|
142
146
|
this.currentStatus = 'idle';
|
|
@@ -158,6 +162,13 @@ export class IdeProviderInstance implements ProviderInstance {
|
|
|
158
162
|
for (const ext of this.extensions.values()) {
|
|
159
163
|
ext.onEvent('stream_reset');
|
|
160
164
|
}
|
|
165
|
+
} else if (event === 'provider_state_patch' && data && typeof data === 'object') {
|
|
166
|
+
const extType = typeof data.extensionType === 'string' ? data.extensionType : '';
|
|
167
|
+
if (extType && this.extensions.has(extType)) {
|
|
168
|
+
this.extensions.get(extType)!.onEvent('provider_state_patch', data);
|
|
169
|
+
} else {
|
|
170
|
+
this.applyProviderResponse(data, { phase: 'immediate' });
|
|
171
|
+
}
|
|
161
172
|
}
|
|
162
173
|
}
|
|
163
174
|
|
|
@@ -166,6 +177,8 @@ export class IdeProviderInstance implements ProviderInstance {
|
|
|
166
177
|
this.lastAgentStatuses.clear();
|
|
167
178
|
this.generatingStartedAt.clear();
|
|
168
179
|
this.monitor.reset();
|
|
180
|
+
this.appliedEffectKeys.clear();
|
|
181
|
+
this.runtimeMessages = [];
|
|
169
182
|
// Child Extension cleanup
|
|
170
183
|
for (const ext of this.extensions.values()) {
|
|
171
184
|
ext.dispose();
|
|
@@ -173,6 +186,15 @@ export class IdeProviderInstance implements ProviderInstance {
|
|
|
173
186
|
this.extensions.clear();
|
|
174
187
|
}
|
|
175
188
|
|
|
189
|
+
updateSettings(newSettings: Record<string, any>): void {
|
|
190
|
+
this.settings = { ...newSettings };
|
|
191
|
+
this.monitor.updateConfig({
|
|
192
|
+
approvalAlert: this.settings.approvalAlert !== false,
|
|
193
|
+
longGeneratingAlert: this.settings.longGeneratingAlert !== false,
|
|
194
|
+
longGeneratingThresholdSec: this.settings.longGeneratingThresholdSec || 180,
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
|
|
176
198
|
// ─── Extension manage ─────────────────────────────
|
|
177
199
|
|
|
178
200
|
/** Extension Instance add */
|
|
@@ -298,6 +320,9 @@ export class IdeProviderInstance implements ProviderInstance {
|
|
|
298
320
|
}
|
|
299
321
|
}
|
|
300
322
|
|
|
323
|
+
const controlValues = extractProviderControlValues(this.provider.controls, raw);
|
|
324
|
+
if (controlValues) raw.controlValues = controlValues;
|
|
325
|
+
|
|
301
326
|
this.cachedChat = { ...raw, activeModal };
|
|
302
327
|
this.detectAgentTransitions(raw, now);
|
|
303
328
|
|
|
@@ -382,6 +407,12 @@ export class IdeProviderInstance implements ProviderInstance {
|
|
|
382
407
|
this.lastAgentStatuses.set(agentKey, agentStatus);
|
|
383
408
|
}
|
|
384
409
|
|
|
410
|
+
this.applyProviderResponse(chatData, {
|
|
411
|
+
phase: (agentStatus === 'idle' && (lastStatus === 'generating' || lastStatus === 'waiting_approval'))
|
|
412
|
+
? 'turn_completed'
|
|
413
|
+
: 'immediate',
|
|
414
|
+
});
|
|
415
|
+
|
|
385
416
|
// Auto-approve: when waiting_approval + settings.autoApprove → auto-click approve via CDP
|
|
386
417
|
if (agentStatus === 'waiting_approval' && this.settings.autoApprove && !this.autoApproveBusy) {
|
|
387
418
|
this.autoApproveViaScript(chatData);
|
|
@@ -399,6 +430,154 @@ export class IdeProviderInstance implements ProviderInstance {
|
|
|
399
430
|
if (this.events.length > 50) this.events = this.events.slice(-50);
|
|
400
431
|
}
|
|
401
432
|
|
|
433
|
+
private applyProviderResponse(data: any, options: { phase: 'immediate' | 'turn_completed' }): void {
|
|
434
|
+
if (!data || typeof data !== 'object') return;
|
|
435
|
+
|
|
436
|
+
const controlValues = extractProviderControlValues(this.provider.controls, data);
|
|
437
|
+
if (controlValues) {
|
|
438
|
+
this.cachedChat = {
|
|
439
|
+
...(this.cachedChat || {}),
|
|
440
|
+
...data,
|
|
441
|
+
controlValues: { ...(this.cachedChat?.controlValues || {}), ...controlValues },
|
|
442
|
+
};
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
const effects = normalizeProviderEffects(data);
|
|
446
|
+
for (const effect of effects) {
|
|
447
|
+
const effectWhen = effect.when || 'immediate';
|
|
448
|
+
if (effectWhen === 'turn_completed' && options.phase !== 'turn_completed') continue;
|
|
449
|
+
if (effectWhen === 'immediate' && options.phase === 'turn_completed') continue;
|
|
450
|
+
|
|
451
|
+
const effectKey = this.getEffectDedupKey(effect);
|
|
452
|
+
if (this.appliedEffectKeys.has(effectKey)) continue;
|
|
453
|
+
this.appliedEffectKeys.add(effectKey);
|
|
454
|
+
|
|
455
|
+
if (effect.persist !== false) {
|
|
456
|
+
const persisted = this.getPersistedEffectContent(effect);
|
|
457
|
+
if (persisted) this.appendRuntimeSystemMessage(persisted, effectKey);
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
if (effect.type === 'message' && effect.message) {
|
|
461
|
+
this.pushEvent({
|
|
462
|
+
event: 'provider:message',
|
|
463
|
+
timestamp: Date.now(),
|
|
464
|
+
content: typeof effect.message.content === 'string' ? effect.message.content : JSON.stringify(effect.message.content),
|
|
465
|
+
role: effect.message.role || 'system',
|
|
466
|
+
kind: effect.message.kind,
|
|
467
|
+
senderName: effect.message.senderName,
|
|
468
|
+
});
|
|
469
|
+
} else if (effect.type === 'toast' && effect.toast) {
|
|
470
|
+
this.pushEvent({
|
|
471
|
+
event: 'provider:toast',
|
|
472
|
+
effectId: effect.id || effectKey,
|
|
473
|
+
timestamp: Date.now(),
|
|
474
|
+
message: effect.toast.message,
|
|
475
|
+
level: effect.toast.level || 'info',
|
|
476
|
+
});
|
|
477
|
+
} else if (effect.type === 'notification' && effect.notification) {
|
|
478
|
+
this.pushEvent({
|
|
479
|
+
event: 'provider:notification',
|
|
480
|
+
effectId: effect.id || effectKey,
|
|
481
|
+
timestamp: Date.now(),
|
|
482
|
+
title: effect.notification.title,
|
|
483
|
+
message: effect.notification.body,
|
|
484
|
+
content: typeof effect.notification.bubbleContent === 'string'
|
|
485
|
+
? effect.notification.bubbleContent
|
|
486
|
+
: effect.notification.body,
|
|
487
|
+
level: effect.notification.level || 'info',
|
|
488
|
+
channels: effect.notification.channels || ['toast'],
|
|
489
|
+
preferenceKey: effect.notification.preferenceKey,
|
|
490
|
+
});
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
private appendRuntimeSystemMessage(content: string, dedupKey: string, receivedAt = Date.now()): void {
|
|
496
|
+
const normalizedContent = String(content || '').trim();
|
|
497
|
+
if (!normalizedContent) return;
|
|
498
|
+
if (this.runtimeMessages.some((entry) => entry.key === dedupKey)) return;
|
|
499
|
+
if (!this.cachedChat) {
|
|
500
|
+
this.cachedChat = {
|
|
501
|
+
id: 'active_session',
|
|
502
|
+
title: this.provider.name,
|
|
503
|
+
status: this.currentStatus,
|
|
504
|
+
messages: [],
|
|
505
|
+
activeModal: null,
|
|
506
|
+
inputContent: '',
|
|
507
|
+
};
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
this.runtimeMessages.push({
|
|
511
|
+
key: dedupKey,
|
|
512
|
+
message: {
|
|
513
|
+
role: 'system',
|
|
514
|
+
senderName: 'System',
|
|
515
|
+
content: normalizedContent,
|
|
516
|
+
receivedAt,
|
|
517
|
+
timestamp: receivedAt,
|
|
518
|
+
},
|
|
519
|
+
});
|
|
520
|
+
if (this.runtimeMessages.length > 50) this.runtimeMessages = this.runtimeMessages.slice(-50);
|
|
521
|
+
|
|
522
|
+
this.historyWriter.appendNewMessages(
|
|
523
|
+
this.type,
|
|
524
|
+
[{
|
|
525
|
+
role: 'system',
|
|
526
|
+
senderName: 'System',
|
|
527
|
+
content: normalizedContent,
|
|
528
|
+
kind: 'system',
|
|
529
|
+
receivedAt,
|
|
530
|
+
historyDedupKey: dedupKey,
|
|
531
|
+
}],
|
|
532
|
+
this.cachedChat?.title || this.provider.name,
|
|
533
|
+
this.instanceId,
|
|
534
|
+
this.cachedChat?.id || this.instanceId,
|
|
535
|
+
);
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
private mergeConversationMessages(messages: any[]): ChatMessage[] {
|
|
539
|
+
if (this.runtimeMessages.length === 0) return messages;
|
|
540
|
+
return [...messages, ...this.runtimeMessages.map((entry) => entry.message)]
|
|
541
|
+
.map((message, index) => ({ message, index }))
|
|
542
|
+
.sort((a, b) => {
|
|
543
|
+
const aTime = a.message.receivedAt || a.message.timestamp || 0;
|
|
544
|
+
const bTime = b.message.receivedAt || b.message.timestamp || 0;
|
|
545
|
+
if (aTime !== bTime) return aTime - bTime;
|
|
546
|
+
return a.index - b.index;
|
|
547
|
+
})
|
|
548
|
+
.map((entry) => entry.message);
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
private getPersistedEffectContent(effect: { type: string; message?: { content?: unknown }; toast?: { message?: string }; notification?: { title?: string; body?: string; bubbleContent?: unknown } }): string | null {
|
|
552
|
+
if (effect.type === 'message') {
|
|
553
|
+
return typeof effect.message?.content === 'string'
|
|
554
|
+
? effect.message.content
|
|
555
|
+
: JSON.stringify(effect.message?.content || '');
|
|
556
|
+
}
|
|
557
|
+
if (effect.type === 'toast') {
|
|
558
|
+
return effect.toast?.message || null;
|
|
559
|
+
}
|
|
560
|
+
if (effect.type === 'notification') {
|
|
561
|
+
if (typeof effect.notification?.bubbleContent === 'string') return effect.notification.bubbleContent;
|
|
562
|
+
if (typeof effect.notification?.title === 'string' && effect.notification.title.trim()) {
|
|
563
|
+
return `${effect.notification.title}\n${effect.notification.body || ''}`.trim();
|
|
564
|
+
}
|
|
565
|
+
return effect.notification?.body || null;
|
|
566
|
+
}
|
|
567
|
+
return null;
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
private getEffectDedupKey(effect: { id?: string; type: string; message?: { content?: unknown }; toast?: { message?: string }; notification?: { title?: string; body?: string } }): string {
|
|
571
|
+
if (effect.id) return `provider_effect:${effect.id}`;
|
|
572
|
+
if (effect.type === 'message') {
|
|
573
|
+
return `provider_effect:message:${typeof effect.message?.content === 'string' ? effect.message.content : JSON.stringify(effect.message?.content || '')}`;
|
|
574
|
+
}
|
|
575
|
+
if (effect.type === 'notification') {
|
|
576
|
+
return `provider_effect:notification:${effect.notification?.title || ''}:${effect.notification?.body || ''}`;
|
|
577
|
+
}
|
|
578
|
+
return `provider_effect:toast:${effect.toast?.message || ''}`;
|
|
579
|
+
}
|
|
580
|
+
|
|
402
581
|
private flushEvents(): ProviderEvent[] {
|
|
403
582
|
const events = [...this.events];
|
|
404
583
|
this.events = [];
|
package/src/shared-types.d.ts
CHANGED
|
@@ -187,6 +187,7 @@ export interface StatusReportPayload {
|
|
|
187
187
|
workspaces?: WorkspaceEntry[];
|
|
188
188
|
defaultWorkspaceId?: string | null;
|
|
189
189
|
defaultWorkspacePath?: string | null;
|
|
190
|
+
terminalSizingMode?: 'measured' | 'fit';
|
|
190
191
|
workspaceActivity?: WorkspaceActivity[];
|
|
191
192
|
recentLaunches?: RecentLaunchEntry[];
|
|
192
193
|
}
|
package/src/shared-types.ts
CHANGED
|
@@ -159,7 +159,7 @@ export interface AcpMode {
|
|
|
159
159
|
/** Provider control schema transmitted to frontend */
|
|
160
160
|
export interface ProviderControlSchema {
|
|
161
161
|
id: string;
|
|
162
|
-
type: 'select' | 'toggle' | 'cycle' | 'slider' | 'action';
|
|
162
|
+
type: 'select' | 'toggle' | 'cycle' | 'slider' | 'action' | 'display';
|
|
163
163
|
label: string;
|
|
164
164
|
icon?: string;
|
|
165
165
|
placement: 'bar' | 'header' | 'menu';
|
|
@@ -255,6 +255,7 @@ export interface StatusReportPayload {
|
|
|
255
255
|
workspaces?: WorkspaceEntry[];
|
|
256
256
|
defaultWorkspaceId?: string | null;
|
|
257
257
|
defaultWorkspacePath?: string | null;
|
|
258
|
+
terminalSizingMode?: 'measured' | 'fit';
|
|
258
259
|
recentLaunches?: RecentLaunchEntry[];
|
|
259
260
|
terminalBackend?: TerminalBackendStatus;
|
|
260
261
|
/** Available providers (present in StatusSnapshot, optional in raw payload) */
|
package/src/status/snapshot.ts
CHANGED
|
@@ -256,6 +256,7 @@ export function buildStatusSnapshot(options: StatusSnapshotOptions): StatusSnaps
|
|
|
256
256
|
workspaces: wsState.workspaces,
|
|
257
257
|
defaultWorkspaceId: wsState.defaultWorkspaceId,
|
|
258
258
|
defaultWorkspacePath: wsState.defaultWorkspacePath,
|
|
259
|
+
terminalSizingMode: cfg.terminalSizingMode || 'measured',
|
|
259
260
|
recentLaunches: buildRecentLaunches(recentActivity),
|
|
260
261
|
terminalBackend,
|
|
261
262
|
availableProviders: buildAvailableProviders(options.providerLoader),
|