@adhdev/daemon-core 0.9.34 → 0.9.36
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/cli-adapter-types.d.ts +1 -0
- package/dist/cli-adapters/provider-cli-adapter.d.ts +11 -0
- package/dist/index.js +152 -37
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +152 -37
- package/dist/index.mjs.map +1 -1
- package/dist/providers/cli-provider-instance.d.ts +1 -0
- package/dist/providers/provider-instance-manager.d.ts +1 -0
- package/dist/providers/provider-instance.d.ts +3 -1
- package/node_modules/@adhdev/session-host-core/package.json +1 -1
- package/package.json +1 -1
- package/src/cli-adapter-types.ts +1 -0
- package/src/cli-adapters/provider-cli-adapter.ts +146 -32
- package/src/commands/handler.ts +10 -1
- package/src/daemon/dev-server.ts +3 -14
- package/src/providers/cli-provider-instance.ts +10 -0
- package/src/providers/provider-instance-manager.ts +15 -0
- package/src/providers/provider-instance.ts +3 -0
|
@@ -79,6 +79,7 @@ export declare class CliProviderInstance implements ProviderInstance {
|
|
|
79
79
|
previousProviderSessionId?: string;
|
|
80
80
|
}) => void;
|
|
81
81
|
});
|
|
82
|
+
refreshProviderDefinition(provider: ProviderModule): void;
|
|
82
83
|
init(context: InstanceContext): Promise<void>;
|
|
83
84
|
onTick(): Promise<void>;
|
|
84
85
|
/**
|
|
@@ -78,6 +78,7 @@ export declare class ProviderInstanceManager {
|
|
|
78
78
|
* Called when user changes settings from dashboard.
|
|
79
79
|
*/
|
|
80
80
|
updateInstanceSettings(providerType: string, settings: Record<string, any>): number;
|
|
81
|
+
refreshProviderDefinitions(resolveProvider: (providerType: string) => unknown): number;
|
|
81
82
|
/**
|
|
82
83
|
* All terminate
|
|
83
84
|
*/
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* Daemon only collects via ProviderInstance.getState(),
|
|
8
8
|
* Each Instance manages its own status.
|
|
9
9
|
*/
|
|
10
|
-
import type { ProviderResumeCapability } from './contracts.js';
|
|
10
|
+
import type { ProviderModule, ProviderResumeCapability } from './contracts.js';
|
|
11
11
|
import type { AcpConfigOption, AcpMode, ProviderControlSchema, ProviderSummaryMetadata, SessionCapability } from '../shared-types.js';
|
|
12
12
|
import type { ChatMessage } from '../types.js';
|
|
13
13
|
export type ProviderStatus = 'idle' | 'generating' | 'waiting_approval' | 'error' | 'stopped' | 'starting';
|
|
@@ -163,6 +163,8 @@ export interface ProviderInstance {
|
|
|
163
163
|
onEvent(event: string, data?: any): void;
|
|
164
164
|
/** Update settings at runtime (called when user changes settings from dashboard) */
|
|
165
165
|
updateSettings?(newSettings: Record<string, any>): void;
|
|
166
|
+
/** Refresh static provider definition/scripts without restarting the live runtime. */
|
|
167
|
+
refreshProviderDefinition?(provider: ProviderModule): void;
|
|
166
168
|
/** cleanup */
|
|
167
169
|
dispose(): void;
|
|
168
170
|
}
|
package/package.json
CHANGED
package/src/cli-adapter-types.ts
CHANGED
|
@@ -51,6 +51,7 @@ export interface CliAdapter {
|
|
|
51
51
|
isReady(): boolean;
|
|
52
52
|
setOnStatusChange(callback: () => void): void;
|
|
53
53
|
updateRuntimeSettings?(settings: Record<string, unknown>): void;
|
|
54
|
+
setCliScripts?(scripts: Record<string, unknown>): void;
|
|
54
55
|
setServerConn?(serverConn: unknown): void;
|
|
55
56
|
clearHistory?(): void;
|
|
56
57
|
resolveAction?(data: unknown): Promise<void>;
|
|
@@ -32,6 +32,7 @@ import {
|
|
|
32
32
|
extractPromptRetrySnippet,
|
|
33
33
|
getLastUserPromptText,
|
|
34
34
|
listCliScriptNames,
|
|
35
|
+
normalizeComparableMessageContent,
|
|
35
36
|
normalizePromptText,
|
|
36
37
|
normalizeScreenSnapshot,
|
|
37
38
|
promptLikelyVisible,
|
|
@@ -183,6 +184,8 @@ export class ProviderCliAdapter implements CliAdapter {
|
|
|
183
184
|
private messages: CliChatMessage[] = [];
|
|
184
185
|
private committedMessages: CliChatMessage[] = [];
|
|
185
186
|
private structuredMessages: CliChatMessage[] = [];
|
|
187
|
+
private committedMessagesActivitySignature = '';
|
|
188
|
+
private committedMessagesChangedAt = 0;
|
|
186
189
|
private currentStatus: CliSessionStatus['status'] = 'starting';
|
|
187
190
|
private onStatusChange: (() => void) | null = null;
|
|
188
191
|
|
|
@@ -288,11 +291,38 @@ export class ProviderCliAdapter implements CliAdapter {
|
|
|
288
291
|
private static readonly FINISH_RETRY_DELAY_MS = 300;
|
|
289
292
|
private static readonly MAX_FINISH_RETRIES = 2;
|
|
290
293
|
|
|
294
|
+
private buildCommittedMessagesActivitySignature(): string {
|
|
295
|
+
const last = this.committedMessages[this.committedMessages.length - 1];
|
|
296
|
+
return [
|
|
297
|
+
String(this.committedMessages.length),
|
|
298
|
+
String(last?.role || ''),
|
|
299
|
+
String(last?.kind || ''),
|
|
300
|
+
String(last?.senderName || ''),
|
|
301
|
+
String(last?.timestamp || ''),
|
|
302
|
+
String(last?.receivedAt || ''),
|
|
303
|
+
normalizeComparableMessageContent(last?.content || '').slice(-240),
|
|
304
|
+
].join('|');
|
|
305
|
+
}
|
|
306
|
+
|
|
291
307
|
private syncMessageViews(): void {
|
|
308
|
+
const signature = this.buildCommittedMessagesActivitySignature();
|
|
309
|
+
if (signature !== this.committedMessagesActivitySignature) {
|
|
310
|
+
this.committedMessagesActivitySignature = signature;
|
|
311
|
+
this.committedMessagesChangedAt = Date.now();
|
|
312
|
+
}
|
|
292
313
|
this.messages = [...this.committedMessages];
|
|
293
314
|
this.structuredMessages = [...this.committedMessages];
|
|
294
315
|
}
|
|
295
316
|
|
|
317
|
+
getLastCommittedMessageActivityAt(): number {
|
|
318
|
+
const last = this.committedMessages[this.committedMessages.length - 1];
|
|
319
|
+
const messageTime = Math.max(
|
|
320
|
+
typeof last?.receivedAt === 'number' && Number.isFinite(last.receivedAt) ? last.receivedAt : 0,
|
|
321
|
+
typeof last?.timestamp === 'number' && Number.isFinite(last.timestamp) ? last.timestamp : 0,
|
|
322
|
+
);
|
|
323
|
+
return Math.max(messageTime, this.committedMessagesChangedAt || 0);
|
|
324
|
+
}
|
|
325
|
+
|
|
296
326
|
private readTerminalScreenText(now = Date.now()): string {
|
|
297
327
|
const screenText = this.terminalScreen.getText() || '';
|
|
298
328
|
this.lastScreenText = screenText;
|
|
@@ -339,7 +369,17 @@ export class ProviderCliAdapter implements CliAdapter {
|
|
|
339
369
|
return baseMessages.slice(-ProviderCliAdapter.PARSE_MESSAGE_TAIL_LIMIT);
|
|
340
370
|
}
|
|
341
371
|
|
|
372
|
+
private messagesShareStableIdentity(left: any, right: any): boolean {
|
|
373
|
+
if (left === right) return true;
|
|
374
|
+
if (!left || !right) return false;
|
|
375
|
+
if ((left.role || '') !== (right.role || '')) return false;
|
|
376
|
+
if (left.id && right.id && String(left.id) === String(right.id)) return true;
|
|
377
|
+
if (typeof left.index === 'number' && typeof right.index === 'number' && left.index === right.index) return true;
|
|
378
|
+
return false;
|
|
379
|
+
}
|
|
380
|
+
|
|
342
381
|
private messagesComparable(left: any, right: any): boolean {
|
|
382
|
+
if (this.messagesShareStableIdentity(left, right)) return true;
|
|
343
383
|
if (!left || !right) return false;
|
|
344
384
|
if ((left.role || '') !== (right.role || '')) return false;
|
|
345
385
|
const leftText = normalizeComparableTranscriptText(left.content);
|
|
@@ -519,10 +559,18 @@ export class ProviderCliAdapter implements CliAdapter {
|
|
|
519
559
|
/** Inject CLI scripts after construction (e.g. when resolved by ProviderLoader) */
|
|
520
560
|
setCliScripts(scripts: CliScripts): void {
|
|
521
561
|
this.cliScripts = scripts;
|
|
562
|
+
this.parsedStatusCache = null;
|
|
563
|
+
this.parseErrorMessage = null;
|
|
522
564
|
const scriptNames = listCliScriptNames(scripts);
|
|
523
565
|
LOG.info('CLI', `[${this.cliType}] CLI scripts injected: [${scriptNames.join(', ')}]`);
|
|
524
566
|
}
|
|
525
567
|
|
|
568
|
+
/** Refresh provider scripts/config used by this adapter without restarting the PTY runtime. */
|
|
569
|
+
refreshProviderDefinition(provider: CliProviderModule): void {
|
|
570
|
+
this.provider = provider;
|
|
571
|
+
this.setCliScripts(provider.scripts || {});
|
|
572
|
+
}
|
|
573
|
+
|
|
526
574
|
updateRuntimeSettings(settings: Record<string, any>): void {
|
|
527
575
|
this.runtimeSettings = { ...settings };
|
|
528
576
|
}
|
|
@@ -1685,6 +1733,82 @@ export class ProviderCliAdapter implements CliAdapter {
|
|
|
1685
1733
|
this.syncMessageViews();
|
|
1686
1734
|
}
|
|
1687
1735
|
|
|
1736
|
+
private getSharedCommittedPrefixLength(parsedMessages: any[]): number {
|
|
1737
|
+
const committedMessages = this.committedMessages;
|
|
1738
|
+
const max = Math.min(parsedMessages.length, committedMessages.length);
|
|
1739
|
+
let index = 0;
|
|
1740
|
+
while (index < max && this.messagesShareStableIdentity(parsedMessages[index], committedMessages[index])) {
|
|
1741
|
+
index += 1;
|
|
1742
|
+
}
|
|
1743
|
+
return index;
|
|
1744
|
+
}
|
|
1745
|
+
|
|
1746
|
+
private hydrateCommittedPrefixForParsedStatus(parsedMessages: any[]): any[] | null {
|
|
1747
|
+
const sharedPrefixLength = this.getSharedCommittedPrefixLength(parsedMessages);
|
|
1748
|
+
if (sharedPrefixLength !== this.committedMessages.length) return null;
|
|
1749
|
+
|
|
1750
|
+
const committedHydratedMessages = this.committedMessages.map((message, index) => {
|
|
1751
|
+
const timestamp = typeof message.timestamp === 'number' && Number.isFinite(message.timestamp)
|
|
1752
|
+
? message.timestamp
|
|
1753
|
+
: (this.lastOutputAt || this.currentTurnScope?.startedAt || Date.now());
|
|
1754
|
+
const contentValue = message.content;
|
|
1755
|
+
return {
|
|
1756
|
+
role: message.role,
|
|
1757
|
+
content: typeof contentValue === 'string' ? contentValue : String(contentValue || ''),
|
|
1758
|
+
timestamp,
|
|
1759
|
+
receivedAt: typeof message.receivedAt === 'number' && Number.isFinite(message.receivedAt)
|
|
1760
|
+
? message.receivedAt
|
|
1761
|
+
: timestamp,
|
|
1762
|
+
kind: message.kind,
|
|
1763
|
+
id: message.id || `msg_${index}`,
|
|
1764
|
+
index: typeof message.index === 'number' ? message.index : index,
|
|
1765
|
+
meta: message.meta,
|
|
1766
|
+
senderName: message.senderName,
|
|
1767
|
+
};
|
|
1768
|
+
});
|
|
1769
|
+
const extraMessages = parsedMessages.slice(sharedPrefixLength);
|
|
1770
|
+
if (extraMessages.length === 0) return committedHydratedMessages;
|
|
1771
|
+
|
|
1772
|
+
const extraHydratedMessages = hydrateCliParsedMessages(extraMessages, {
|
|
1773
|
+
committedMessages: [],
|
|
1774
|
+
scope: this.currentTurnScope,
|
|
1775
|
+
lastOutputAt: this.lastOutputAt,
|
|
1776
|
+
}).map((message, offset) => ({
|
|
1777
|
+
...message,
|
|
1778
|
+
id: message.id || `msg_${sharedPrefixLength + offset}`,
|
|
1779
|
+
index: typeof message.index === 'number' ? message.index : sharedPrefixLength + offset,
|
|
1780
|
+
}));
|
|
1781
|
+
return [...committedHydratedMessages, ...extraHydratedMessages];
|
|
1782
|
+
}
|
|
1783
|
+
|
|
1784
|
+
private hydrateParsedMessagesForStatus(parsedMessages: any[]): any[] {
|
|
1785
|
+
return this.hydrateCommittedPrefixForParsedStatus(parsedMessages)
|
|
1786
|
+
|| hydrateCliParsedMessages(parsedMessages, {
|
|
1787
|
+
committedMessages: this.committedMessages,
|
|
1788
|
+
scope: this.currentTurnScope,
|
|
1789
|
+
lastOutputAt: this.lastOutputAt,
|
|
1790
|
+
});
|
|
1791
|
+
}
|
|
1792
|
+
|
|
1793
|
+
private buildCommittedChatMessages(): any[] {
|
|
1794
|
+
return this.committedMessages.map((message, index) => {
|
|
1795
|
+
const contentValue = message.content;
|
|
1796
|
+
return buildChatMessage({
|
|
1797
|
+
role: message.role,
|
|
1798
|
+
content: typeof contentValue === 'string' ? contentValue : String(contentValue || ''),
|
|
1799
|
+
timestamp: message.timestamp,
|
|
1800
|
+
kind: message.kind,
|
|
1801
|
+
meta: message.meta,
|
|
1802
|
+
senderName: message.senderName,
|
|
1803
|
+
id: message.id || `msg_${index}`,
|
|
1804
|
+
index: typeof message.index === 'number' ? message.index : index,
|
|
1805
|
+
receivedAt: typeof message.receivedAt === 'number'
|
|
1806
|
+
? message.receivedAt
|
|
1807
|
+
: message.timestamp,
|
|
1808
|
+
});
|
|
1809
|
+
});
|
|
1810
|
+
}
|
|
1811
|
+
|
|
1688
1812
|
/**
|
|
1689
1813
|
* Script-based full parse — returns ReadChatResult.
|
|
1690
1814
|
* Called by command handler / dashboard for rich content rendering.
|
|
@@ -1727,7 +1851,7 @@ export class ProviderCliAdapter implements CliAdapter {
|
|
|
1727
1851
|
this.onStatusChange?.();
|
|
1728
1852
|
}
|
|
1729
1853
|
}
|
|
1730
|
-
if (parsed && Array.isArray(parsed.messages)) {
|
|
1854
|
+
if (parsed && Array.isArray(parsed.messages) && this.provider.allowInputDuringGeneration === true) {
|
|
1731
1855
|
const hydratedForCommit = normalizeCliParsedMessages(parsed.messages, {
|
|
1732
1856
|
committedMessages: this.committedMessages,
|
|
1733
1857
|
scope: this.currentTurnScope,
|
|
@@ -1749,25 +1873,13 @@ export class ProviderCliAdapter implements CliAdapter {
|
|
|
1749
1873
|
&& this.currentStatus === 'idle';
|
|
1750
1874
|
let result: any;
|
|
1751
1875
|
if (parsed && Array.isArray(parsed.messages)) {
|
|
1752
|
-
const parsedHydratedMessages =
|
|
1753
|
-
committedMessages: this.committedMessages,
|
|
1754
|
-
scope: this.currentTurnScope,
|
|
1755
|
-
lastOutputAt: this.lastOutputAt,
|
|
1756
|
-
});
|
|
1757
|
-
const committedHydratedMessages = this.committedMessages.map((message, index) => buildChatMessage({
|
|
1758
|
-
...message,
|
|
1759
|
-
id: message.id || `msg_${index}`,
|
|
1760
|
-
index: typeof message.index === 'number' ? message.index : index,
|
|
1761
|
-
receivedAt: typeof message.receivedAt === 'number'
|
|
1762
|
-
? message.receivedAt
|
|
1763
|
-
: message.timestamp,
|
|
1764
|
-
}));
|
|
1876
|
+
const parsedHydratedMessages = this.hydrateParsedMessagesForStatus(parsed.messages);
|
|
1765
1877
|
const parsedLastAssistant = [...parsedHydratedMessages].reverse().find((message) => message.role === 'assistant' && typeof message.content === 'string' && message.content.trim());
|
|
1766
1878
|
const shouldAdoptParsedIdleReplay =
|
|
1767
1879
|
!this.currentTurnScope
|
|
1768
1880
|
&& !this.activeModal
|
|
1769
1881
|
&& !!parsedLastAssistant
|
|
1770
|
-
&& parsedTranscriptIsRicherThanCommitted(parsedHydratedMessages,
|
|
1882
|
+
&& parsedTranscriptIsRicherThanCommitted(parsedHydratedMessages, this.committedMessages)
|
|
1771
1883
|
&& (
|
|
1772
1884
|
this.currentStatus === 'idle'
|
|
1773
1885
|
|| (
|
|
@@ -1778,11 +1890,23 @@ export class ProviderCliAdapter implements CliAdapter {
|
|
|
1778
1890
|
)
|
|
1779
1891
|
);
|
|
1780
1892
|
if (shouldAdoptParsedIdleReplay) {
|
|
1781
|
-
this.committedMessages =
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1893
|
+
this.committedMessages = this.getSharedCommittedPrefixLength(parsed.messages) === this.committedMessages.length
|
|
1894
|
+
? parsedHydratedMessages.map((message) => ({
|
|
1895
|
+
role: message.role,
|
|
1896
|
+
content: typeof message.content === 'string' ? message.content : String(message.content || ''),
|
|
1897
|
+
timestamp: message.timestamp,
|
|
1898
|
+
receivedAt: message.receivedAt,
|
|
1899
|
+
kind: message.kind,
|
|
1900
|
+
id: message.id,
|
|
1901
|
+
index: message.index,
|
|
1902
|
+
meta: message.meta,
|
|
1903
|
+
senderName: message.senderName,
|
|
1904
|
+
}))
|
|
1905
|
+
: normalizeCliParsedMessages(parsed.messages, {
|
|
1906
|
+
committedMessages: this.committedMessages,
|
|
1907
|
+
scope: this.currentTurnScope,
|
|
1908
|
+
lastOutputAt: this.lastOutputAt,
|
|
1909
|
+
});
|
|
1786
1910
|
this.syncMessageViews();
|
|
1787
1911
|
if (this.currentStatus !== 'idle' || this.isWaitingForResponse) {
|
|
1788
1912
|
this.responseBuffer = '';
|
|
@@ -1797,25 +1921,15 @@ export class ProviderCliAdapter implements CliAdapter {
|
|
|
1797
1921
|
this.onStatusChange?.();
|
|
1798
1922
|
}
|
|
1799
1923
|
}
|
|
1800
|
-
const effectiveCommittedHydratedMessages = shouldAdoptParsedIdleReplay
|
|
1801
|
-
? this.committedMessages.map((message, index) => buildChatMessage({
|
|
1802
|
-
...message,
|
|
1803
|
-
id: message.id || `msg_${index}`,
|
|
1804
|
-
index: typeof message.index === 'number' ? message.index : index,
|
|
1805
|
-
receivedAt: typeof message.receivedAt === 'number'
|
|
1806
|
-
? message.receivedAt
|
|
1807
|
-
: message.timestamp,
|
|
1808
|
-
}))
|
|
1809
|
-
: committedHydratedMessages;
|
|
1810
1924
|
const shouldPreferCommittedHistoryReplay =
|
|
1811
1925
|
!this.currentTurnScope
|
|
1812
1926
|
&& !this.activeModal
|
|
1813
|
-
&&
|
|
1927
|
+
&& this.committedMessages.length > parsedHydratedMessages.length;
|
|
1814
1928
|
const shouldPreferCommittedIdleReplay =
|
|
1815
1929
|
shouldPreferCommittedMessages
|
|
1816
1930
|
&& !shouldAdoptParsedIdleReplay;
|
|
1817
1931
|
const hydratedMessages = (shouldPreferCommittedIdleReplay || shouldPreferCommittedHistoryReplay)
|
|
1818
|
-
?
|
|
1932
|
+
? this.buildCommittedChatMessages()
|
|
1819
1933
|
: parsedHydratedMessages;
|
|
1820
1934
|
result = {
|
|
1821
1935
|
id: parsed.id || 'cli_session',
|
package/src/commands/handler.ts
CHANGED
|
@@ -507,7 +507,16 @@ export class DaemonCommandHandler implements CommandHelpers {
|
|
|
507
507
|
if (this._ctx.providerLoader) {
|
|
508
508
|
await this._ctx.providerLoader.fetchLatest().catch(() => {});
|
|
509
509
|
this._ctx.providerLoader.reload();
|
|
510
|
-
|
|
510
|
+
this._ctx.providerLoader.registerToDetector();
|
|
511
|
+
const refreshedInstances = this._ctx.instanceManager
|
|
512
|
+
? this._ctx.instanceManager.refreshProviderDefinitions((providerType) => this._ctx.providerLoader!.resolve(providerType))
|
|
513
|
+
: 0;
|
|
514
|
+
const providers = this._ctx.providerLoader.getAll().map((provider) => ({
|
|
515
|
+
type: provider.type,
|
|
516
|
+
name: provider.name,
|
|
517
|
+
category: provider.category,
|
|
518
|
+
}));
|
|
519
|
+
return { success: true, refreshedInstances, providers };
|
|
511
520
|
}
|
|
512
521
|
return { success: false, error: 'ProviderLoader not initialized' };
|
|
513
522
|
}
|
package/src/daemon/dev-server.ts
CHANGED
|
@@ -507,20 +507,9 @@ export class DevServer implements DevServerContext {
|
|
|
507
507
|
private async handleReload(_req: http.IncomingMessage, res: http.ServerResponse): Promise<void> {
|
|
508
508
|
try {
|
|
509
509
|
this.providerLoader.reload();
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
const instance = this.instanceManager.getInstance(id) as any;
|
|
514
|
-
const providerType = typeof instance?.type === 'string' ? instance.type : '';
|
|
515
|
-
if (!providerType) continue;
|
|
516
|
-
const resolved = this.providerLoader.resolve(providerType);
|
|
517
|
-
if (!resolved) continue;
|
|
518
|
-
if (instance && typeof instance === 'object' && 'provider' in instance) {
|
|
519
|
-
instance.provider = resolved;
|
|
520
|
-
refreshedInstances += 1;
|
|
521
|
-
}
|
|
522
|
-
}
|
|
523
|
-
}
|
|
510
|
+
const refreshedInstances = this.instanceManager
|
|
511
|
+
? this.instanceManager.refreshProviderDefinitions((providerType) => this.providerLoader.resolve(providerType))
|
|
512
|
+
: 0;
|
|
524
513
|
const providers = this.providerLoader.getAll().map(p => ({
|
|
525
514
|
type: p.type, name: p.name, category: p.category,
|
|
526
515
|
}));
|
|
@@ -219,6 +219,12 @@ export class CliProviderInstance implements ProviderInstance {
|
|
|
219
219
|
this.historyWriter = new ChatHistoryWriter();
|
|
220
220
|
}
|
|
221
221
|
|
|
222
|
+
refreshProviderDefinition(provider: ProviderModule): void {
|
|
223
|
+
if (provider.type !== this.type || provider.category !== 'cli') return;
|
|
224
|
+
this.provider = provider;
|
|
225
|
+
this.adapter.refreshProviderDefinition(provider as CliProviderModule);
|
|
226
|
+
}
|
|
227
|
+
|
|
222
228
|
// ─── Lifecycle ─────────────────────────────────
|
|
223
229
|
|
|
224
230
|
async init(context: InstanceContext): Promise<void> {
|
|
@@ -492,9 +498,13 @@ export class CliProviderInstance implements ProviderInstance {
|
|
|
492
498
|
const autoApproveActive = adapterStatus.status === 'waiting_approval' && this.shouldAutoApprove();
|
|
493
499
|
const visibleStatus = autoApproveActive ? 'generating' : adapterStatus.status;
|
|
494
500
|
const runtime = this.adapter.getRuntimeMetadata();
|
|
501
|
+
const lastCommittedMessageActivityAt = typeof this.adapter.getLastCommittedMessageActivityAt === 'function'
|
|
502
|
+
? this.adapter.getLastCommittedMessageActivityAt()
|
|
503
|
+
: 0;
|
|
495
504
|
return {
|
|
496
505
|
id: this.instanceId,
|
|
497
506
|
status: visibleStatus,
|
|
507
|
+
lastMessageAt: lastCommittedMessageActivityAt || undefined,
|
|
498
508
|
runtimeLifecycle: runtime?.lifecycle ?? null,
|
|
499
509
|
runtimeSurfaceKind: runtime?.surfaceKind,
|
|
500
510
|
runtimeRestoredFromStorage: runtime?.restoredFromStorage === true,
|
|
@@ -15,6 +15,9 @@ function projectHotChatSessionStatesFromProviderState(state: ProviderState): Hot
|
|
|
15
15
|
const project = (item: ProviderState): HotChatSessionState => ({
|
|
16
16
|
id: item.instanceId,
|
|
17
17
|
status: item.activeChat?.status || item.status,
|
|
18
|
+
unread: (item as any).unread,
|
|
19
|
+
inboxBucket: (item as any).inboxBucket,
|
|
20
|
+
lastMessageAt: (item as any).lastMessageAt ?? (item.activeChat as any)?.lastMessageAt,
|
|
18
21
|
runtimeLifecycle: item.runtime?.lifecycle ?? null,
|
|
19
22
|
runtimeSurfaceKind: item.runtime?.surfaceKind,
|
|
20
23
|
runtimeRestoredFromStorage: item.runtime?.restoredFromStorage === true,
|
|
@@ -258,6 +261,18 @@ export class ProviderInstanceManager {
|
|
|
258
261
|
return updated;
|
|
259
262
|
}
|
|
260
263
|
|
|
264
|
+
refreshProviderDefinitions(resolveProvider: (providerType: string) => unknown): number {
|
|
265
|
+
let refreshed = 0;
|
|
266
|
+
for (const instance of this.instances.values()) {
|
|
267
|
+
if (typeof instance.refreshProviderDefinition !== 'function') continue;
|
|
268
|
+
const provider = resolveProvider(instance.type);
|
|
269
|
+
if (!provider || typeof provider !== 'object') continue;
|
|
270
|
+
instance.refreshProviderDefinition(provider as any);
|
|
271
|
+
refreshed += 1;
|
|
272
|
+
}
|
|
273
|
+
return refreshed;
|
|
274
|
+
}
|
|
275
|
+
|
|
261
276
|
// ─── cleanup ──────────────────────────────────────
|
|
262
277
|
|
|
263
278
|
/**
|
|
@@ -197,6 +197,9 @@ export interface ProviderInstance {
|
|
|
197
197
|
/** Update settings at runtime (called when user changes settings from dashboard) */
|
|
198
198
|
updateSettings?(newSettings: Record<string, any>): void;
|
|
199
199
|
|
|
200
|
+
/** Refresh static provider definition/scripts without restarting the live runtime. */
|
|
201
|
+
refreshProviderDefinition?(provider: ProviderModule): void;
|
|
202
|
+
|
|
200
203
|
/** cleanup */
|
|
201
204
|
dispose(): void;
|
|
202
205
|
}
|