@adhdev/daemon-core 0.8.60 → 0.8.62
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-adapters/provider-cli-adapter.d.ts +1 -0
- package/dist/cli-adapters/provider-cli-parse.d.ts +1 -0
- package/dist/cli-adapters/provider-cli-shared.d.ts +5 -2
- package/dist/index.d.ts +2 -0
- package/dist/index.js +521 -343
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +511 -343
- package/dist/index.mjs.map +1 -1
- package/dist/providers/chat-message-normalization.d.ts +43 -0
- package/dist/providers/cli-provider-instance.d.ts +1 -0
- package/dist/providers/contracts.d.ts +5 -1
- package/dist/providers/control-effects.d.ts +2 -0
- package/dist/providers/extension-provider-instance.d.ts +2 -1
- package/dist/providers/ide-provider-instance.d.ts +2 -1
- package/dist/types.d.ts +2 -1
- package/node_modules/@adhdev/session-host-core/package.json +2 -2
- package/package.json +2 -2
- package/src/agent-stream/poller.ts +3 -5
- package/src/cli-adapters/provider-cli-adapter.ts +32 -10
- package/src/cli-adapters/provider-cli-parse.d.ts +1 -0
- package/src/cli-adapters/provider-cli-parse.ts +3 -0
- package/src/cli-adapters/provider-cli-shared.d.ts +2 -0
- package/src/cli-adapters/provider-cli-shared.ts +5 -2
- package/src/commands/chat-commands.ts +2 -1
- package/src/config/chat-history.ts +6 -5
- package/src/index.ts +13 -0
- package/src/providers/acp-provider-instance.ts +19 -24
- package/src/providers/chat-message-normalization.ts +68 -0
- package/src/providers/cli-provider-instance.ts +42 -29
- package/src/providers/contracts.ts +5 -1
- package/src/providers/control-effects.ts +72 -0
- package/src/providers/extension-provider-instance.ts +43 -31
- package/src/providers/ide-provider-instance.ts +42 -30
- package/src/types.ts +2 -1
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { ChatMessage } from '../types.js';
|
|
2
|
+
export declare const BUILTIN_CHAT_MESSAGE_KINDS: readonly ["standard", "thought", "tool", "terminal", "system"];
|
|
3
|
+
export type BuiltinChatMessageKind = typeof BUILTIN_CHAT_MESSAGE_KINDS[number];
|
|
4
|
+
export type ChatMessageKind = BuiltinChatMessageKind | (string & {});
|
|
5
|
+
export declare function isBuiltinChatMessageKind(kind: unknown): kind is BuiltinChatMessageKind;
|
|
6
|
+
export declare function normalizeChatMessageKind(kind: unknown, role: unknown): ChatMessageKind;
|
|
7
|
+
export declare function buildChatMessage<T extends Omit<ChatMessage, 'kind'> & {
|
|
8
|
+
kind?: ChatMessageKind;
|
|
9
|
+
}>(message: T): T & {
|
|
10
|
+
kind: ChatMessageKind;
|
|
11
|
+
};
|
|
12
|
+
export declare function buildSystemChatMessage<T extends Omit<ChatMessage, 'role' | 'kind'> & {
|
|
13
|
+
role?: 'system';
|
|
14
|
+
kind?: ChatMessageKind;
|
|
15
|
+
}>(message: T): (T & {
|
|
16
|
+
role: 'system';
|
|
17
|
+
kind: ChatMessageKind;
|
|
18
|
+
});
|
|
19
|
+
export declare function buildRuntimeSystemChatMessage<T extends Omit<ChatMessage, 'role' | 'kind' | 'senderName'> & {
|
|
20
|
+
role?: 'system';
|
|
21
|
+
kind?: ChatMessageKind;
|
|
22
|
+
senderName?: string;
|
|
23
|
+
}>(message: T): (T & {
|
|
24
|
+
role: 'system';
|
|
25
|
+
kind: ChatMessageKind;
|
|
26
|
+
senderName: string;
|
|
27
|
+
});
|
|
28
|
+
export declare function buildAssistantChatMessage<T extends Omit<ChatMessage, 'role' | 'kind'> & {
|
|
29
|
+
role?: 'assistant';
|
|
30
|
+
kind?: ChatMessageKind;
|
|
31
|
+
}>(message: T): (T & {
|
|
32
|
+
role: 'assistant';
|
|
33
|
+
kind: ChatMessageKind;
|
|
34
|
+
});
|
|
35
|
+
export declare function buildUserChatMessage<T extends Omit<ChatMessage, 'role' | 'kind'> & {
|
|
36
|
+
role?: 'user';
|
|
37
|
+
kind?: ChatMessageKind;
|
|
38
|
+
}>(message: T): (T & {
|
|
39
|
+
role: 'user';
|
|
40
|
+
kind: ChatMessageKind;
|
|
41
|
+
});
|
|
42
|
+
export declare function normalizeChatMessage<T extends ChatMessage>(message: T): T;
|
|
43
|
+
export declare function normalizeChatMessages<T extends ChatMessage>(messages: T[] | null | undefined): T[];
|
|
@@ -89,6 +89,7 @@ export declare class CliProviderInstance implements ProviderInstance {
|
|
|
89
89
|
private formatMarkerTimestamp;
|
|
90
90
|
private maybeAppendRuntimeRecoveryMessage;
|
|
91
91
|
private appendRuntimeSystemMessage;
|
|
92
|
+
private appendRuntimeMessage;
|
|
92
93
|
private mergeConversationMessages;
|
|
93
94
|
private formatApprovalRequestMessage;
|
|
94
95
|
private promoteProviderSessionId;
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* - User custom providers use the same contracts
|
|
8
8
|
*/
|
|
9
9
|
import type { ProviderSummaryMetadata } from '../shared-types.js';
|
|
10
|
+
import type { ChatMessageKind } from './chat-message-normalization.js';
|
|
10
11
|
export interface ReadChatResult {
|
|
11
12
|
messages: ChatMessage[];
|
|
12
13
|
status: AgentStatus;
|
|
@@ -43,7 +44,7 @@ export interface ModalInfo {
|
|
|
43
44
|
export interface ProviderEffectMessage {
|
|
44
45
|
role?: 'system' | 'assistant' | 'user';
|
|
45
46
|
content: string | MessagePart[];
|
|
46
|
-
kind?:
|
|
47
|
+
kind?: ChatMessageKind;
|
|
47
48
|
senderName?: string;
|
|
48
49
|
}
|
|
49
50
|
export interface ProviderEffectToast {
|
|
@@ -59,6 +60,9 @@ export interface ProviderEffectNotification {
|
|
|
59
60
|
channels?: ProviderNotificationChannel[];
|
|
60
61
|
preferenceKey?: ProviderNotificationPreferenceKey;
|
|
61
62
|
bubbleContent?: string | MessagePart[];
|
|
63
|
+
bubbleKind?: ChatMessageKind;
|
|
64
|
+
bubbleRole?: 'system' | 'assistant' | 'user';
|
|
65
|
+
bubbleSenderName?: string;
|
|
62
66
|
}
|
|
63
67
|
export interface ProviderEffect {
|
|
64
68
|
type: 'message' | 'toast' | 'notification';
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import type { ControlInvokeResult, ControlListResult, ControlSetResult, ProviderControlDef, ProviderEffect } from './contracts.js';
|
|
2
|
+
import type { ChatMessage } from '../types.js';
|
|
2
3
|
export type ProviderControlValue = string | number | boolean;
|
|
3
4
|
export declare function extractProviderControlValues(controls: ProviderControlDef[] | undefined, data: any): Record<string, ProviderControlValue> | undefined;
|
|
4
5
|
export declare function normalizeProviderEffects(data: any): ProviderEffect[];
|
|
6
|
+
export declare function buildPersistedProviderEffectMessage(effect: ProviderEffect | null | undefined): ChatMessage | null;
|
|
5
7
|
export declare function normalizeControlListResult(data: any): ControlListResult;
|
|
6
8
|
export declare function normalizeControlSetResult(data: any): ControlSetResult;
|
|
7
9
|
export declare function normalizeControlInvokeResult(data: any): ControlInvokeResult;
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Manages IDE extensions (Cline, Roo Code, etc).
|
|
5
5
|
* CDP webview discovery + agent stream collection moved here.
|
|
6
6
|
*/
|
|
7
|
-
import type
|
|
7
|
+
import { type ProviderModule } from './contracts.js';
|
|
8
8
|
import type { ProviderInstance, ProviderState, InstanceContext } from './provider-instance.js';
|
|
9
9
|
export declare class ExtensionProviderInstance implements ProviderInstance {
|
|
10
10
|
readonly type: string;
|
|
@@ -45,6 +45,7 @@ export declare class ExtensionProviderInstance implements ProviderInstance {
|
|
|
45
45
|
private pushEvent;
|
|
46
46
|
private applyProviderResponse;
|
|
47
47
|
private appendRuntimeSystemMessage;
|
|
48
|
+
private appendRuntimeMessage;
|
|
48
49
|
/**
|
|
49
50
|
* Assign stable receivedAt to extension messages.
|
|
50
51
|
* Same pattern as IdeProviderInstance.readChat() prevByHash —
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* IDE Instance manages child Extension Instances.
|
|
9
9
|
* Daemon collects all via a single IDE Instance.getState() call.
|
|
10
10
|
*/
|
|
11
|
-
import type
|
|
11
|
+
import { type ProviderModule } from './contracts.js';
|
|
12
12
|
import type { ProviderInstance, ProviderState, InstanceContext } from './provider-instance.js';
|
|
13
13
|
import { ExtensionProviderInstance } from './extension-provider-instance.js';
|
|
14
14
|
export declare class IdeProviderInstance implements ProviderInstance {
|
|
@@ -60,6 +60,7 @@ export declare class IdeProviderInstance implements ProviderInstance {
|
|
|
60
60
|
private pushEvent;
|
|
61
61
|
private applyProviderResponse;
|
|
62
62
|
private appendRuntimeSystemMessage;
|
|
63
|
+
private appendRuntimeMessage;
|
|
63
64
|
private mergeConversationMessages;
|
|
64
65
|
private getPersistedEffectContent;
|
|
65
66
|
private getEffectDedupKey;
|
package/dist/types.d.ts
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* When modifying this file, also update interface contracts in AGENT_PROTOCOL.md.
|
|
6
6
|
*/
|
|
7
7
|
import type { StatusReportPayload, AvailableProviderInfo } from './shared-types.js';
|
|
8
|
+
import type { ChatMessageKind } from './providers/chat-message-normalization.js';
|
|
8
9
|
/** Full status response from /api/v1/status and WS events */
|
|
9
10
|
export interface StatusResponse extends StatusReportPayload {
|
|
10
11
|
/** For standalone API compat */
|
|
@@ -23,7 +24,7 @@ export interface ChatMessage {
|
|
|
23
24
|
role: string;
|
|
24
25
|
/** Plain text (legacy) or canonical message parts */
|
|
25
26
|
content: string | MessagePart[];
|
|
26
|
-
kind?:
|
|
27
|
+
kind?: ChatMessageKind;
|
|
27
28
|
id?: string;
|
|
28
29
|
index?: number;
|
|
29
30
|
timestamp?: number;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adhdev/session-host-core",
|
|
3
|
-
"version": "0.8.
|
|
4
|
-
"description": "ADHDev local session host core
|
|
3
|
+
"version": "0.8.62",
|
|
4
|
+
"description": "ADHDev local session host core \u2014 session registry, protocol, buffers",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"exports": {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adhdev/daemon-core",
|
|
3
|
-
"version": "0.8.
|
|
4
|
-
"description": "ADHDev daemon core
|
|
3
|
+
"version": "0.8.62",
|
|
4
|
+
"description": "ADHDev daemon core \u2014 CDP, IDE detection, providers, command execution",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"exports": {
|
|
@@ -21,6 +21,7 @@ import { LOG } from '../logging/logger.js';
|
|
|
21
21
|
import type { AgentStreamState } from './types.js';
|
|
22
22
|
import { formatAutoApprovalMessage, pickApprovalButton } from '../providers/approval-utils.js';
|
|
23
23
|
import type { ProviderModule } from '../providers/contracts.js';
|
|
24
|
+
import { buildRuntimeSystemChatMessage } from '../providers/chat-message-normalization.js';
|
|
24
25
|
|
|
25
26
|
interface ExtensionInstanceLike {
|
|
26
27
|
type?: string;
|
|
@@ -229,12 +230,9 @@ export class AgentStreamPoller {
|
|
|
229
230
|
type: 'message',
|
|
230
231
|
id: effectId,
|
|
231
232
|
persist: true,
|
|
232
|
-
message: {
|
|
233
|
-
role: 'system',
|
|
234
|
-
senderName: 'System',
|
|
235
|
-
kind: 'system',
|
|
233
|
+
message: buildRuntimeSystemChatMessage({
|
|
236
234
|
content: formatAutoApprovalMessage(stream.activeModal?.message, buttonLabel),
|
|
237
|
-
},
|
|
235
|
+
}),
|
|
238
236
|
},
|
|
239
237
|
],
|
|
240
238
|
};
|
|
@@ -44,6 +44,7 @@ import {
|
|
|
44
44
|
type CliSessionStatus,
|
|
45
45
|
type CliTraceEntry,
|
|
46
46
|
} from './provider-cli-shared.js';
|
|
47
|
+
import { buildChatMessage } from '../providers/chat-message-normalization.js';
|
|
47
48
|
import {
|
|
48
49
|
buildCliParseInput,
|
|
49
50
|
buildCliTraceParseSnapshot,
|
|
@@ -738,6 +739,19 @@ export class ProviderCliAdapter implements CliAdapter {
|
|
|
738
739
|
|| screenStableMs < holdMs;
|
|
739
740
|
}
|
|
740
741
|
|
|
742
|
+
private shouldDeferIdleTimeoutFinish(): boolean {
|
|
743
|
+
if (!this.isWaitingForResponse || this.currentStatus === 'waiting_approval') {
|
|
744
|
+
return false;
|
|
745
|
+
}
|
|
746
|
+
const latestStatus = this.runDetectStatus(this.recentOutputBuffer) || this.currentStatus;
|
|
747
|
+
if (latestStatus === 'generating') {
|
|
748
|
+
this.settledBuffer = this.recentOutputBuffer;
|
|
749
|
+
this.evaluateSettled();
|
|
750
|
+
return true;
|
|
751
|
+
}
|
|
752
|
+
return false;
|
|
753
|
+
}
|
|
754
|
+
|
|
741
755
|
private getStartupConfirmationModal(screenText: string): { message: string; buttons: string[] } | null {
|
|
742
756
|
const text = sanitizeTerminalText(String(screenText || ''));
|
|
743
757
|
if (!text.trim()) return null;
|
|
@@ -929,6 +943,7 @@ export class ProviderCliAdapter implements CliAdapter {
|
|
|
929
943
|
if (this.idleTimeout) clearTimeout(this.idleTimeout);
|
|
930
944
|
this.idleTimeout = setTimeout(() => {
|
|
931
945
|
if (this.isWaitingForResponse && this.currentStatus !== 'waiting_approval') {
|
|
946
|
+
if (this.shouldDeferIdleTimeoutFinish()) return;
|
|
932
947
|
this.finishResponse();
|
|
933
948
|
}
|
|
934
949
|
}, this.timeouts.generatingIdle);
|
|
@@ -962,6 +977,7 @@ export class ProviderCliAdapter implements CliAdapter {
|
|
|
962
977
|
if (this.idleTimeout) clearTimeout(this.idleTimeout);
|
|
963
978
|
this.idleTimeout = setTimeout(() => {
|
|
964
979
|
if (this.isWaitingForResponse && this.currentStatus !== 'waiting_approval') {
|
|
980
|
+
if (this.shouldDeferIdleTimeoutFinish()) return;
|
|
965
981
|
this.finishResponse();
|
|
966
982
|
}
|
|
967
983
|
}, this.timeouts.generatingIdle);
|
|
@@ -1011,7 +1027,10 @@ export class ProviderCliAdapter implements CliAdapter {
|
|
|
1011
1027
|
// Reset idle timeout
|
|
1012
1028
|
if (this.idleTimeout) clearTimeout(this.idleTimeout);
|
|
1013
1029
|
this.idleTimeout = setTimeout(() => {
|
|
1014
|
-
if (this.isWaitingForResponse)
|
|
1030
|
+
if (this.isWaitingForResponse) {
|
|
1031
|
+
if (this.shouldDeferIdleTimeoutFinish()) return;
|
|
1032
|
+
this.finishResponse();
|
|
1033
|
+
}
|
|
1015
1034
|
}, this.timeouts.generatingIdle);
|
|
1016
1035
|
this.onStatusChange?.();
|
|
1017
1036
|
return;
|
|
@@ -1090,6 +1109,7 @@ export class ProviderCliAdapter implements CliAdapter {
|
|
|
1090
1109
|
if (this.idleTimeout) clearTimeout(this.idleTimeout);
|
|
1091
1110
|
this.idleTimeout = setTimeout(() => {
|
|
1092
1111
|
if (this.isWaitingForResponse && this.currentStatus !== 'waiting_approval') {
|
|
1112
|
+
if (this.shouldDeferIdleTimeoutFinish()) return;
|
|
1093
1113
|
this.clearIdleFinishCandidate('idle_timeout_finish');
|
|
1094
1114
|
this.finishResponse();
|
|
1095
1115
|
}
|
|
@@ -1218,6 +1238,7 @@ export class ProviderCliAdapter implements CliAdapter {
|
|
|
1218
1238
|
tail: text.slice(-500),
|
|
1219
1239
|
screenText,
|
|
1220
1240
|
rawBuffer: this.accumulatedRawBuffer,
|
|
1241
|
+
isWaitingForResponse: this.isWaitingForResponse,
|
|
1221
1242
|
screen: buildCliScreenSnapshot(screenText),
|
|
1222
1243
|
tailScreen: buildCliScreenSnapshot(text.slice(-500)),
|
|
1223
1244
|
});
|
|
@@ -1297,11 +1318,10 @@ export class ProviderCliAdapter implements CliAdapter {
|
|
|
1297
1318
|
&& !this.activeModal;
|
|
1298
1319
|
if (parsed && Array.isArray(parsed.messages)) {
|
|
1299
1320
|
const hydratedMessages = shouldPreferCommittedMessages
|
|
1300
|
-
? this.committedMessages.map((message, index) => ({
|
|
1321
|
+
? this.committedMessages.map((message, index) => buildChatMessage({
|
|
1301
1322
|
...message,
|
|
1302
1323
|
id: message.id || `msg_${index}`,
|
|
1303
1324
|
index: typeof message.index === 'number' ? message.index : index,
|
|
1304
|
-
kind: message.kind || 'standard',
|
|
1305
1325
|
receivedAt: typeof message.receivedAt === 'number'
|
|
1306
1326
|
? message.receivedAt
|
|
1307
1327
|
: message.timestamp,
|
|
@@ -1326,13 +1346,13 @@ export class ProviderCliAdapter implements CliAdapter {
|
|
|
1326
1346
|
id: 'cli_session',
|
|
1327
1347
|
status: this.currentStatus,
|
|
1328
1348
|
title: this.cliName,
|
|
1329
|
-
messages: messages.slice(-50).map((message, index) => ({
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1349
|
+
messages: messages.slice(-50).map((message, index) => buildChatMessage({
|
|
1350
|
+
...message,
|
|
1351
|
+
id: message.id || `msg_${index}`,
|
|
1352
|
+
index: typeof message.index === 'number' ? message.index : index,
|
|
1353
|
+
receivedAt: typeof message.receivedAt === 'number'
|
|
1354
|
+
? message.receivedAt
|
|
1355
|
+
: message.timestamp,
|
|
1336
1356
|
})),
|
|
1337
1357
|
activeModal: this.activeModal,
|
|
1338
1358
|
};
|
|
@@ -1350,6 +1370,7 @@ export class ProviderCliAdapter implements CliAdapter {
|
|
|
1350
1370
|
terminalScreenText: this.terminalScreen.getText(),
|
|
1351
1371
|
baseMessages: this.committedMessages,
|
|
1352
1372
|
partialResponse: this.responseBuffer,
|
|
1373
|
+
isWaitingForResponse: this.isWaitingForResponse,
|
|
1353
1374
|
scope: this.currentTurnScope,
|
|
1354
1375
|
runtimeSettings: this.runtimeSettings,
|
|
1355
1376
|
});
|
|
@@ -1369,6 +1390,7 @@ export class ProviderCliAdapter implements CliAdapter {
|
|
|
1369
1390
|
terminalScreenText: this.terminalScreen.getText(),
|
|
1370
1391
|
baseMessages,
|
|
1371
1392
|
partialResponse,
|
|
1393
|
+
isWaitingForResponse: this.isWaitingForResponse,
|
|
1372
1394
|
scope,
|
|
1373
1395
|
runtimeSettings: this.runtimeSettings,
|
|
1374
1396
|
});
|
|
@@ -24,6 +24,7 @@ export declare function buildCliParseInput(options: {
|
|
|
24
24
|
terminalScreenText: string;
|
|
25
25
|
baseMessages: CliChatMessage[];
|
|
26
26
|
partialResponse: string;
|
|
27
|
+
isWaitingForResponse?: boolean;
|
|
27
28
|
scope?: TurnParseScope | null;
|
|
28
29
|
runtimeSettings: Record<string, any>;
|
|
29
30
|
}): CliScriptInput;
|
|
@@ -123,6 +123,7 @@ export function buildCliParseInput(options: {
|
|
|
123
123
|
terminalScreenText: string;
|
|
124
124
|
baseMessages: CliChatMessage[];
|
|
125
125
|
partialResponse: string;
|
|
126
|
+
isWaitingForResponse?: boolean;
|
|
126
127
|
scope?: TurnParseScope | null;
|
|
127
128
|
runtimeSettings: Record<string, any>;
|
|
128
129
|
}): CliScriptInput {
|
|
@@ -133,6 +134,7 @@ export function buildCliParseInput(options: {
|
|
|
133
134
|
terminalScreenText,
|
|
134
135
|
baseMessages,
|
|
135
136
|
partialResponse,
|
|
137
|
+
isWaitingForResponse,
|
|
136
138
|
scope,
|
|
137
139
|
runtimeSettings,
|
|
138
140
|
} = options;
|
|
@@ -155,6 +157,7 @@ export function buildCliParseInput(options: {
|
|
|
155
157
|
recentScreen: buildCliScreenSnapshot(recentBuffer),
|
|
156
158
|
messages: [...baseMessages],
|
|
157
159
|
partialResponse,
|
|
160
|
+
isWaitingForResponse,
|
|
158
161
|
promptText: scope?.prompt || '',
|
|
159
162
|
settings: { ...runtimeSettings },
|
|
160
163
|
};
|
|
@@ -62,6 +62,7 @@ export interface CliScriptInput {
|
|
|
62
62
|
recentScreen: CliScreenSnapshot;
|
|
63
63
|
messages: CliChatMessage[];
|
|
64
64
|
partialResponse: string;
|
|
65
|
+
isWaitingForResponse?: boolean;
|
|
65
66
|
promptText?: string;
|
|
66
67
|
settings?: Record<string, any>;
|
|
67
68
|
args?: Record<string, any>;
|
|
@@ -70,6 +71,7 @@ export interface CliStatusInput {
|
|
|
70
71
|
tail: string;
|
|
71
72
|
screenText?: string;
|
|
72
73
|
rawBuffer?: string;
|
|
74
|
+
isWaitingForResponse?: boolean;
|
|
73
75
|
screen: CliScreenSnapshot;
|
|
74
76
|
tailScreen: CliScreenSnapshot;
|
|
75
77
|
}
|
|
@@ -2,6 +2,7 @@ import * as os from 'os';
|
|
|
2
2
|
import * as path from 'path';
|
|
3
3
|
import { execSync } from 'child_process';
|
|
4
4
|
import type { ProviderResumeCapability } from '../providers/contracts.js';
|
|
5
|
+
import type { ChatMessageKind } from '../providers/chat-message-normalization.js';
|
|
5
6
|
import { sanitizeSpawnEnv } from './spawn-env.js';
|
|
6
7
|
|
|
7
8
|
export interface CliChatMessage {
|
|
@@ -9,10 +10,10 @@ export interface CliChatMessage {
|
|
|
9
10
|
content: string;
|
|
10
11
|
timestamp?: number;
|
|
11
12
|
receivedAt?: number;
|
|
12
|
-
kind?:
|
|
13
|
+
kind?: ChatMessageKind;
|
|
13
14
|
id?: string;
|
|
14
15
|
index?: number;
|
|
15
|
-
meta?: Record<string,
|
|
16
|
+
meta?: Record<string, unknown>;
|
|
16
17
|
senderName?: string;
|
|
17
18
|
}
|
|
18
19
|
|
|
@@ -65,6 +66,7 @@ export interface CliScriptInput {
|
|
|
65
66
|
recentScreen: CliScreenSnapshot;
|
|
66
67
|
messages: CliChatMessage[];
|
|
67
68
|
partialResponse: string;
|
|
69
|
+
isWaitingForResponse?: boolean;
|
|
68
70
|
promptText?: string;
|
|
69
71
|
settings?: Record<string, any>;
|
|
70
72
|
args?: Record<string, any>;
|
|
@@ -74,6 +76,7 @@ export interface CliStatusInput {
|
|
|
74
76
|
tail: string;
|
|
75
77
|
screenText?: string;
|
|
76
78
|
rawBuffer?: string;
|
|
79
|
+
isWaitingForResponse?: boolean;
|
|
77
80
|
screen: CliScreenSnapshot;
|
|
78
81
|
tailScreen: CliScreenSnapshot;
|
|
79
82
|
}
|
|
@@ -12,6 +12,7 @@ import { LOG } from '../logging/logger.js';
|
|
|
12
12
|
import { recordDebugTrace } from '../logging/debug-trace.js';
|
|
13
13
|
import type { ChatMessage } from '../types.js';
|
|
14
14
|
import type { ReadChatCursor, ReadChatSyncMode, SessionTransport } from '../shared-types.js';
|
|
15
|
+
import { normalizeChatMessages } from '../providers/chat-message-normalization.js';
|
|
15
16
|
|
|
16
17
|
const RECENT_SEND_WINDOW_MS = 1200;
|
|
17
18
|
const recentSendByTarget = new Map<string, number>();
|
|
@@ -189,7 +190,7 @@ function normalizeReadChatCursor(args: any): Required<ReadChatCursor> {
|
|
|
189
190
|
|
|
190
191
|
function normalizeReadChatMessages(payload: Record<string, any>): ChatMessage[] {
|
|
191
192
|
const messages = Array.isArray(payload.messages) ? payload.messages as ChatMessage[] : [];
|
|
192
|
-
return messages;
|
|
193
|
+
return normalizeChatMessages(messages);
|
|
193
194
|
}
|
|
194
195
|
|
|
195
196
|
function deriveHistoryDedupKey(message: ChatMessage & { _unitKey?: string; _turnKey?: string }): string | undefined {
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
import * as fs from 'fs';
|
|
13
13
|
import * as path from 'path';
|
|
14
14
|
import * as os from 'os';
|
|
15
|
+
import { buildRuntimeSystemChatMessage } from '../providers/chat-message-normalization.js';
|
|
15
16
|
|
|
16
17
|
const HISTORY_DIR = path.join(os.homedir(), '.adhdev', 'history');
|
|
17
18
|
const RETAIN_DAYS = 30;
|
|
@@ -314,11 +315,11 @@ export class ChatHistoryWriter {
|
|
|
314
315
|
this.appendNewMessages(
|
|
315
316
|
agentType,
|
|
316
317
|
[{
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
318
|
+
...buildRuntimeSystemChatMessage({
|
|
319
|
+
content,
|
|
320
|
+
receivedAt: options.receivedAt,
|
|
321
|
+
senderName: options.senderName,
|
|
322
|
+
}),
|
|
322
323
|
historyDedupKey: options.dedupKey,
|
|
323
324
|
}],
|
|
324
325
|
options.sessionTitle,
|
package/src/index.ts
CHANGED
|
@@ -200,6 +200,19 @@ export type { ProviderModule, CdpTargetFilter, ProviderResumeCapability, InputEn
|
|
|
200
200
|
export type { ProviderSourceConfigSnapshot, ProviderSourceConfigUpdate } from './config/provider-source-config.js';
|
|
201
201
|
export { parseProviderSourceConfigUpdate } from './config/provider-source-config.js';
|
|
202
202
|
export { normalizeInputEnvelope, normalizeMessageParts, flattenMessageParts } from './providers/io-contracts.js';
|
|
203
|
+
export {
|
|
204
|
+
BUILTIN_CHAT_MESSAGE_KINDS,
|
|
205
|
+
isBuiltinChatMessageKind,
|
|
206
|
+
normalizeChatMessageKind,
|
|
207
|
+
buildChatMessage,
|
|
208
|
+
buildSystemChatMessage,
|
|
209
|
+
buildRuntimeSystemChatMessage,
|
|
210
|
+
buildAssistantChatMessage,
|
|
211
|
+
buildUserChatMessage,
|
|
212
|
+
normalizeChatMessage,
|
|
213
|
+
normalizeChatMessages,
|
|
214
|
+
} from './providers/chat-message-normalization.js';
|
|
215
|
+
export type { BuiltinChatMessageKind, ChatMessageKind } from './providers/chat-message-normalization.js';
|
|
203
216
|
export { VersionArchive, detectAllVersions } from './providers/version-archive.js';
|
|
204
217
|
export type { ProviderVersionInfo, VersionHistory } from './providers/version-archive.js';
|
|
205
218
|
|
|
@@ -51,15 +51,16 @@ import { normalizeContent, flattenContent, normalizeInputEnvelope } from './cont
|
|
|
51
51
|
import type { ProviderInstance, ProviderState, AcpProviderState, ProviderErrorReason, ProviderEvent, InstanceContext } from './provider-instance.js';
|
|
52
52
|
import { StatusMonitor } from './status-monitor.js';
|
|
53
53
|
import { buildLegacyModelModeSummaryMetadata } from './summary-metadata.js';
|
|
54
|
+
import { buildAssistantChatMessage, buildChatMessage, buildRuntimeSystemChatMessage, buildUserChatMessage, normalizeChatMessages } from './chat-message-normalization.js';
|
|
54
55
|
import { LOG } from '../logging/logger.js';
|
|
56
|
+
import type { ChatMessage } from '../types.js';
|
|
55
57
|
|
|
56
58
|
// ─── Internal Display Types (for dashboard) ────────────────────────────
|
|
57
59
|
|
|
58
|
-
|
|
60
|
+
type AcpMessage = ChatMessage & {
|
|
59
61
|
role: 'user' | 'assistant' | 'system';
|
|
60
62
|
/** Rich content blocks (ACP standard) or plain text (legacy) */
|
|
61
63
|
content: string | ContentBlock[];
|
|
62
|
-
timestamp?: number;
|
|
63
64
|
/** Tool calls associated with this message */
|
|
64
65
|
toolCalls?: ToolCallInfo[];
|
|
65
66
|
}
|
|
@@ -293,26 +294,23 @@ export class AcpProviderInstance implements ProviderInstance {
|
|
|
293
294
|
const dirName = this.workingDir.split('/').filter(Boolean).pop() || 'session';
|
|
294
295
|
|
|
295
296
|
// Recent 50 messages
|
|
296
|
-
const recentMessages = this.messages.slice(-50).map(m => {
|
|
297
|
+
const recentMessages = normalizeChatMessages(this.messages.slice(-50).map(m => {
|
|
297
298
|
const content = this.truncateContent(m.content);
|
|
298
|
-
return {
|
|
299
|
-
|
|
299
|
+
return buildChatMessage({
|
|
300
|
+
...m,
|
|
300
301
|
content,
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
};
|
|
304
|
-
});
|
|
302
|
+
});
|
|
303
|
+
}));
|
|
305
304
|
|
|
306
305
|
// generating during partial response add
|
|
307
306
|
if (this.currentStatus === 'generating' && (this.partialContent || this.partialBlocks.length > 0)) {
|
|
308
307
|
const blocks = this.buildPartialBlocks();
|
|
309
308
|
if (blocks.length > 0) {
|
|
310
|
-
recentMessages.push({
|
|
311
|
-
role: 'assistant',
|
|
309
|
+
recentMessages.push(buildAssistantChatMessage({
|
|
312
310
|
content: blocks,
|
|
313
311
|
timestamp: Date.now(),
|
|
314
312
|
toolCalls: this.turnToolCalls.length > 0 ? [...this.turnToolCalls] : undefined,
|
|
315
|
-
});
|
|
313
|
+
}));
|
|
316
314
|
}
|
|
317
315
|
}
|
|
318
316
|
|
|
@@ -326,7 +324,7 @@ export class AcpProviderInstance implements ProviderInstance {
|
|
|
326
324
|
id: this.sessionId || `${this.type}_${this.workingDir}`,
|
|
327
325
|
title: `${this.provider.name} · ${dirName}`,
|
|
328
326
|
status: this.currentStatus,
|
|
329
|
-
messages: recentMessages,
|
|
327
|
+
messages: normalizeChatMessages(recentMessages as any),
|
|
330
328
|
activeModal: this.currentStatus === 'waiting_approval' ? {
|
|
331
329
|
message: this.activeToolCalls.find(t => t.status === 'running')?.name || 'Permission requested',
|
|
332
330
|
buttons: ['Approve', 'Reject'],
|
|
@@ -975,11 +973,10 @@ export class AcpProviderInstance implements ProviderInstance {
|
|
|
975
973
|
: [{ type: 'text', text }];
|
|
976
974
|
|
|
977
975
|
// Add user message locally (store as ContentBlock[])
|
|
978
|
-
this.messages.push({
|
|
979
|
-
role: 'user',
|
|
976
|
+
this.messages.push(buildUserChatMessage({
|
|
980
977
|
content: contentBlocks && contentBlocks.length > 0 ? contentBlocks : text,
|
|
981
978
|
timestamp: Date.now(),
|
|
982
|
-
});
|
|
979
|
+
}));
|
|
983
980
|
|
|
984
981
|
this.currentStatus = 'generating';
|
|
985
982
|
this.partialContent = '';
|
|
@@ -1181,11 +1178,11 @@ export class AcpProviderInstance implements ProviderInstance {
|
|
|
1181
1178
|
}
|
|
1182
1179
|
|
|
1183
1180
|
if (content.trim()) {
|
|
1184
|
-
this.messages.push({
|
|
1181
|
+
this.messages.push(buildChatMessage({
|
|
1185
1182
|
role: m.role || 'assistant',
|
|
1186
1183
|
content: content.trim(),
|
|
1187
1184
|
timestamp: Date.now(),
|
|
1188
|
-
});
|
|
1185
|
+
}));
|
|
1189
1186
|
this.partialContent = '';
|
|
1190
1187
|
}
|
|
1191
1188
|
}
|
|
@@ -1271,14 +1268,13 @@ export class AcpProviderInstance implements ProviderInstance {
|
|
|
1271
1268
|
}).filter(b => b.type !== 'text' || (b.type === 'text' && b.text.trim()));
|
|
1272
1269
|
|
|
1273
1270
|
if (finalBlocks.length > 0) {
|
|
1274
|
-
this.messages.push({
|
|
1275
|
-
role: 'assistant',
|
|
1271
|
+
this.messages.push(buildAssistantChatMessage({
|
|
1276
1272
|
content: finalBlocks.length === 1 && finalBlocks[0].type === 'text'
|
|
1277
1273
|
? (finalBlocks[0] as {type: 'text', text: string}).text // single text → string (backward compat)
|
|
1278
1274
|
: finalBlocks,
|
|
1279
1275
|
timestamp: Date.now(),
|
|
1280
1276
|
toolCalls: this.turnToolCalls.length > 0 ? [...this.turnToolCalls] : undefined,
|
|
1281
|
-
});
|
|
1277
|
+
}));
|
|
1282
1278
|
}
|
|
1283
1279
|
this.partialContent = '';
|
|
1284
1280
|
this.partialBlocks = [];
|
|
@@ -1347,11 +1343,10 @@ export class AcpProviderInstance implements ProviderInstance {
|
|
|
1347
1343
|
private appendSystemMessage(content: string, timestamp = Date.now()): void {
|
|
1348
1344
|
const normalizedContent = String(content || '').trim();
|
|
1349
1345
|
if (!normalizedContent) return;
|
|
1350
|
-
this.messages.push({
|
|
1351
|
-
role: 'system',
|
|
1346
|
+
this.messages.push(buildRuntimeSystemChatMessage({
|
|
1352
1347
|
content: normalizedContent,
|
|
1353
1348
|
timestamp,
|
|
1354
|
-
});
|
|
1349
|
+
}));
|
|
1355
1350
|
if (this.messages.length > 200) {
|
|
1356
1351
|
this.messages = this.messages.slice(-100);
|
|
1357
1352
|
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import type { ChatMessage } from '../types.js';
|
|
2
|
+
|
|
3
|
+
export const BUILTIN_CHAT_MESSAGE_KINDS = ['standard', 'thought', 'tool', 'terminal', 'system'] as const;
|
|
4
|
+
|
|
5
|
+
export type BuiltinChatMessageKind = typeof BUILTIN_CHAT_MESSAGE_KINDS[number];
|
|
6
|
+
export type ChatMessageKind = BuiltinChatMessageKind | (string & {});
|
|
7
|
+
|
|
8
|
+
const KNOWN_CHAT_MESSAGE_KINDS = new Set<string>(BUILTIN_CHAT_MESSAGE_KINDS);
|
|
9
|
+
|
|
10
|
+
export function isBuiltinChatMessageKind(kind: unknown): kind is BuiltinChatMessageKind {
|
|
11
|
+
return typeof kind === 'string' && KNOWN_CHAT_MESSAGE_KINDS.has(kind.trim().toLowerCase());
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function normalizeChatMessageKind(kind: unknown, role: unknown): ChatMessageKind {
|
|
15
|
+
const normalizedKind = typeof kind === 'string' ? kind.trim().toLowerCase() : '';
|
|
16
|
+
if (normalizedKind && KNOWN_CHAT_MESSAGE_KINDS.has(normalizedKind)) return normalizedKind as BuiltinChatMessageKind;
|
|
17
|
+
|
|
18
|
+
const normalizedRole = typeof role === 'string' ? role.trim().toLowerCase() : '';
|
|
19
|
+
return normalizedRole === 'system' ? 'system' : 'standard';
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function buildChatMessage<T extends Omit<ChatMessage, 'kind'> & { kind?: ChatMessageKind }>(message: T): T & { kind: ChatMessageKind } {
|
|
23
|
+
return {
|
|
24
|
+
...message,
|
|
25
|
+
kind: normalizeChatMessageKind(message?.kind, message?.role),
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function buildSystemChatMessage<T extends Omit<ChatMessage, 'role' | 'kind'> & { role?: 'system'; kind?: ChatMessageKind }>(message: T): (T & { role: 'system'; kind: ChatMessageKind }) {
|
|
30
|
+
return buildChatMessage({
|
|
31
|
+
...message,
|
|
32
|
+
role: 'system',
|
|
33
|
+
kind: message?.kind || 'system',
|
|
34
|
+
} as T & { role: 'system'; kind?: ChatMessageKind }) as T & { role: 'system'; kind: ChatMessageKind };
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function buildRuntimeSystemChatMessage<T extends Omit<ChatMessage, 'role' | 'kind' | 'senderName'> & { role?: 'system'; kind?: ChatMessageKind; senderName?: string }>(message: T): (T & { role: 'system'; kind: ChatMessageKind; senderName: string }) {
|
|
38
|
+
return buildSystemChatMessage({
|
|
39
|
+
...message,
|
|
40
|
+
senderName: typeof message?.senderName === 'string' && message.senderName.trim()
|
|
41
|
+
? message.senderName
|
|
42
|
+
: 'System',
|
|
43
|
+
} as T & { role?: 'system'; kind?: ChatMessageKind; senderName?: string }) as T & { role: 'system'; kind: ChatMessageKind; senderName: string };
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function buildAssistantChatMessage<T extends Omit<ChatMessage, 'role' | 'kind'> & { role?: 'assistant'; kind?: ChatMessageKind }>(message: T): (T & { role: 'assistant'; kind: ChatMessageKind }) {
|
|
47
|
+
return buildChatMessage({
|
|
48
|
+
...message,
|
|
49
|
+
role: 'assistant',
|
|
50
|
+
kind: message?.kind || 'standard',
|
|
51
|
+
} as T & { role: 'assistant'; kind?: ChatMessageKind }) as T & { role: 'assistant'; kind: ChatMessageKind };
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function buildUserChatMessage<T extends Omit<ChatMessage, 'role' | 'kind'> & { role?: 'user'; kind?: ChatMessageKind }>(message: T): (T & { role: 'user'; kind: ChatMessageKind }) {
|
|
55
|
+
return buildChatMessage({
|
|
56
|
+
...message,
|
|
57
|
+
role: 'user',
|
|
58
|
+
kind: message?.kind || 'standard',
|
|
59
|
+
} as T & { role: 'user'; kind?: ChatMessageKind }) as T & { role: 'user'; kind: ChatMessageKind };
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function normalizeChatMessage<T extends ChatMessage>(message: T): T {
|
|
63
|
+
return buildChatMessage(message) as T;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export function normalizeChatMessages<T extends ChatMessage>(messages: T[] | null | undefined): T[] {
|
|
67
|
+
return (Array.isArray(messages) ? messages : []).map((message) => normalizeChatMessage(message));
|
|
68
|
+
}
|