@adhdev/daemon-core 0.9.76-rc.55 → 0.9.76-rc.57
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/index.js +39 -22
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +39 -22
- package/dist/index.mjs.map +1 -1
- package/dist/types.d.ts +9 -0
- package/package.json +1 -1
- package/src/commands/chat-commands.ts +12 -8
- package/src/mesh/coordinator-prompt.ts +3 -3
- package/src/providers/chat-message-normalization.ts +45 -19
- package/src/providers/cli-provider-instance.ts +6 -9
- package/src/providers/read-chat-contract.ts +8 -0
- package/src/types.ts +9 -0
package/dist/types.d.ts
CHANGED
|
@@ -42,6 +42,15 @@ export interface ChatMessage {
|
|
|
42
42
|
/** Optional: fiber metadata */
|
|
43
43
|
_type?: string;
|
|
44
44
|
_sub?: string;
|
|
45
|
+
/** Transcript visibility/audience contract for separating chat-visible content from internal/debug runtime rows. */
|
|
46
|
+
visibility?: 'visible' | 'user' | 'chat' | 'hidden' | 'debug' | 'internal' | (string & {});
|
|
47
|
+
transcriptVisibility?: 'visible' | 'user' | 'chat' | 'hidden' | 'debug' | 'internal' | (string & {});
|
|
48
|
+
audience?: 'chat' | 'debug' | 'trace' | 'internal' | (string & {});
|
|
49
|
+
source?: 'assistant_text' | 'tool_call' | 'terminal_command' | 'runtime_activity' | 'runtime_status' | 'provider_chrome' | 'control' | (string & {});
|
|
50
|
+
userFacing?: boolean;
|
|
51
|
+
internal?: boolean;
|
|
52
|
+
isInternal?: boolean;
|
|
53
|
+
debug?: boolean;
|
|
45
54
|
/** Meta information for thought/terminal logs etc */
|
|
46
55
|
meta?: {
|
|
47
56
|
label?: string;
|
package/package.json
CHANGED
|
@@ -320,19 +320,23 @@ function buildReadChatCommandResult(payload: Record<string, any>, args: any): Co
|
|
|
320
320
|
const visibleMessages = filterUserFacingChatMessages(messages);
|
|
321
321
|
const sync = buildFullTail(visibleMessages, normalizeReadChatTailLimit(args));
|
|
322
322
|
const hiddenMsgCount = Math.max(0, messages.length - visibleMessages.length);
|
|
323
|
-
const
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
323
|
+
const returnedDebugReadChat = debugReadChat
|
|
324
|
+
? {
|
|
325
|
+
...debugReadChat,
|
|
326
|
+
fullMsgCount: typeof debugReadChat.fullMsgCount === 'number'
|
|
327
|
+
? debugReadChat.fullMsgCount
|
|
328
|
+
: messages.length,
|
|
329
|
+
visibleMsgCount: visibleMessages.length,
|
|
330
|
+
hiddenMsgCount,
|
|
331
|
+
returnedMsgCount: sync.messages.length,
|
|
332
|
+
}
|
|
333
|
+
: undefined;
|
|
330
334
|
return {
|
|
331
335
|
success: true,
|
|
332
336
|
...validatedPayload,
|
|
333
337
|
messages: sync.messages,
|
|
334
338
|
totalMessages: sync.totalMessages,
|
|
335
|
-
debugReadChat:
|
|
339
|
+
...(returnedDebugReadChat ? { debugReadChat: returnedDebugReadChat } : {}),
|
|
336
340
|
};
|
|
337
341
|
}
|
|
338
342
|
|
|
@@ -145,8 +145,8 @@ const WORKFLOW_SECTION = `## Orchestration Workflow
|
|
|
145
145
|
b. If you need branch isolation for parallel work, call \`mesh_clone_node\` to create a worktree node first.
|
|
146
146
|
c. If no session exists, call \`mesh_launch_session\` to start one.
|
|
147
147
|
d. Call \`mesh_send_task\` with a **complete, self-contained** instruction that includes all context the agent needs (file paths, line numbers, what to change, why). Do not send partial instructions expecting future follow-up.
|
|
148
|
-
4. **Monitor** —
|
|
149
|
-
5. **Verify** — When a task reports completion, call \`mesh_git_status\` to verify changes were made.
|
|
148
|
+
4. **Monitor** — Prefer event-driven completion/status notifications. Do **not** poll \`mesh_read_chat\` repeatedly just because the delegated session has not produced a final assistant message yet; tool/terminal activity means work may still be in progress. Use at most one compact \`mesh_read_chat\` check after a completion/approval signal, an explicit user status request, or a real timeout/stall. Handle approvals via \`mesh_approve\`.
|
|
149
|
+
5. **Verify** — When a task reports completion or git work is visible, call \`mesh_git_status\` to verify changes were made.
|
|
150
150
|
6. **Checkpoint** — Call \`mesh_checkpoint\` to save the work.
|
|
151
151
|
7. **Clean up** — Remove worktree nodes via \`mesh_remove_node\` after their work is merged or no longer needed.
|
|
152
152
|
8. **Report** — Summarize what was done, what changed, and any issues.`;
|
|
@@ -163,7 +163,7 @@ function buildRulesSection(coordinatorCliType?: string): string {
|
|
|
163
163
|
- **Respect explicit provider requests.** If the user names an agent/provider, pass the matching provider type to \`mesh_launch_session\`: Hermes → \`hermes-cli\`, Claude Code/Claude → \`claude-cli\`, Codex → \`codex-cli\`, Gemini → \`gemini-cli\`. Never substitute \`claude-cli\` just because the coordinator itself is Claude Code.
|
|
164
164
|
- **Front-load the task message.** When calling \`mesh_send_task\`, include everything the agent needs: what files to touch, what the problem is, what the fix should look like. The agent won't ask follow-up questions.
|
|
165
165
|
- **Don't inspect code.** Trust the agent's output. Verify via \`mesh_git_status\`, not by reading source files.
|
|
166
|
-
- **Don't over-parallelize.** Start with 1-2 concurrent tasks. Scale up if they succeed.
|
|
166
|
+
- **Don't over-parallelize.** Start with 1-2 concurrent tasks. Scale up if they succeed. Never launch a duplicate session or second worker solely because \`mesh_read_chat\` has no final assistant message while the delegated session is still showing tool/terminal activity.
|
|
167
167
|
- **Handle failures gracefully.** If a task fails, read the chat to understand why, then retry or reassign.
|
|
168
168
|
- **Keep the user informed.** Report progress after each delegation round — one or two sentences, not a narration.
|
|
169
169
|
- **Respect node capabilities.** Don't send build tasks to read-only nodes. Don't push from nodes that aren't allowed to.
|
|
@@ -179,25 +179,51 @@ function readMessageMeta(message: ChatMessage): Record<string, unknown> | null {
|
|
|
179
179
|
: null;
|
|
180
180
|
}
|
|
181
181
|
|
|
182
|
-
function
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|| meta.internal === true
|
|
190
|
-
|| meta.debug === true
|
|
191
|
-
|| meta.statusOnly === true
|
|
192
|
-
|| meta.controlOnly === true;
|
|
182
|
+
function readStringField(value: unknown): string {
|
|
183
|
+
return typeof value === 'string' ? value.trim().toLowerCase() : '';
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
function readVisibilityField(message: ChatMessage, meta: Record<string, unknown> | null): string {
|
|
187
|
+
const record = message as ChatMessage & Record<string, unknown>;
|
|
188
|
+
return readStringField(record.visibility ?? record.transcriptVisibility ?? meta?.visibility ?? meta?.transcriptVisibility);
|
|
193
189
|
}
|
|
194
190
|
|
|
195
|
-
function
|
|
196
|
-
|
|
197
|
-
const visibility =
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
191
|
+
function isExplicitlyHiddenFromTranscript(message: ChatMessage, meta: Record<string, unknown> | null): boolean {
|
|
192
|
+
const record = message as ChatMessage & Record<string, unknown>;
|
|
193
|
+
const visibility = readVisibilityField(message, meta);
|
|
194
|
+
const audience = readStringField(record.audience ?? meta?.audience);
|
|
195
|
+
const source = readStringField(record.source ?? meta?.source);
|
|
196
|
+
|
|
197
|
+
return visibility === 'hidden'
|
|
198
|
+
|| visibility === 'debug'
|
|
199
|
+
|| visibility === 'internal'
|
|
200
|
+
|| audience === 'debug'
|
|
201
|
+
|| audience === 'trace'
|
|
202
|
+
|| audience === 'internal'
|
|
203
|
+
|| source === 'runtime_status'
|
|
204
|
+
|| source === 'runtime_activity'
|
|
205
|
+
|| source === 'provider_chrome'
|
|
206
|
+
|| source === 'control'
|
|
207
|
+
|| record.internal === true
|
|
208
|
+
|| record.isInternal === true
|
|
209
|
+
|| record.debug === true
|
|
210
|
+
|| meta?.internal === true
|
|
211
|
+
|| meta?.isInternal === true
|
|
212
|
+
|| meta?.debug === true
|
|
213
|
+
|| meta?.statusOnly === true
|
|
214
|
+
|| meta?.controlOnly === true;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function isExplicitlyVisibleInTranscript(message: ChatMessage, meta: Record<string, unknown> | null): boolean {
|
|
218
|
+
const record = message as ChatMessage & Record<string, unknown>;
|
|
219
|
+
const visibility = readVisibilityField(message, meta);
|
|
220
|
+
const audience = readStringField(record.audience ?? meta?.audience);
|
|
221
|
+
return visibility === 'visible'
|
|
222
|
+
|| visibility === 'user'
|
|
223
|
+
|| visibility === 'chat'
|
|
224
|
+
|| audience === 'chat'
|
|
225
|
+
|| record.userFacing === true
|
|
226
|
+
|| meta?.userFacing === true;
|
|
201
227
|
}
|
|
202
228
|
|
|
203
229
|
/**
|
|
@@ -212,8 +238,8 @@ function isExplicitlyVisibleInTranscript(meta: Record<string, unknown> | null):
|
|
|
212
238
|
export function isUserFacingChatMessage(message: ChatMessage | null | undefined): boolean {
|
|
213
239
|
if (!message) return false;
|
|
214
240
|
const meta = readMessageMeta(message);
|
|
215
|
-
if (isExplicitlyHiddenFromTranscript(meta)) return false;
|
|
216
|
-
if (isExplicitlyVisibleInTranscript(meta)) return true;
|
|
241
|
+
if (isExplicitlyHiddenFromTranscript(message, meta)) return false;
|
|
242
|
+
if (isExplicitlyVisibleInTranscript(message, meta)) return true;
|
|
217
243
|
|
|
218
244
|
const role = typeof message.role === 'string' ? message.role.trim().toLowerCase() : '';
|
|
219
245
|
const kind = resolveChatMessageKind(message);
|
|
@@ -25,7 +25,7 @@ import { formatAutoApprovalMessage, pickApprovalButton } from './approval-utils.
|
|
|
25
25
|
import { getCliScriptCommand, parseCliScriptResult } from './cli-script-results.js';
|
|
26
26
|
import { mergeProviderPatchState, resolveProviderStateSurface } from './provider-patch-state.js';
|
|
27
27
|
import { normalizeProviderSessionId } from './provider-session-id.js';
|
|
28
|
-
import { buildChatMessage, buildRuntimeSystemChatMessage, normalizeChatMessages, resolveChatMessageKind } from './chat-message-normalization.js';
|
|
28
|
+
import { buildChatMessage, buildRuntimeSystemChatMessage, isUserFacingChatMessage, normalizeChatMessages, resolveChatMessageKind } from './chat-message-normalization.js';
|
|
29
29
|
|
|
30
30
|
type PersistableCliHistoryMessage = {
|
|
31
31
|
role: string;
|
|
@@ -1031,14 +1031,11 @@ export class CliProviderInstance implements ProviderInstance {
|
|
|
1031
1031
|
const getRole = (message: ChatMessage): string => typeof message.role === 'string'
|
|
1032
1032
|
? message.role.trim().toLowerCase()
|
|
1033
1033
|
: '';
|
|
1034
|
-
const
|
|
1034
|
+
const isRuntimeOverlay = (entry: MergeEntry): boolean => {
|
|
1035
1035
|
if (entry.source !== 'runtime') return false;
|
|
1036
1036
|
const key = typeof entry.runtimeKey === 'string' ? entry.runtimeKey.trim().toLowerCase() : '';
|
|
1037
1037
|
if (key.startsWith('auto_approval:')) return true;
|
|
1038
|
-
|
|
1039
|
-
? entry.message.content.trim().toLowerCase()
|
|
1040
|
-
: flattenContent(entry.message.content).trim().toLowerCase();
|
|
1041
|
-
return content.startsWith('auto-approved:');
|
|
1038
|
+
return !isUserFacingChatMessage(entry.message);
|
|
1042
1039
|
};
|
|
1043
1040
|
const shouldKeepParsedBeforeUntimedRuntime = (message: ChatMessage): boolean => {
|
|
1044
1041
|
const role = getRole(message);
|
|
@@ -1059,7 +1056,7 @@ export class CliProviderInstance implements ProviderInstance {
|
|
|
1059
1056
|
if (a.source !== b.source && aTime !== bTime) {
|
|
1060
1057
|
const parsedEntry = a.source === 'parsed' ? a : b.source === 'parsed' ? b : null;
|
|
1061
1058
|
const runtimeEntry = a.source === 'runtime' ? a : b.source === 'runtime' ? b : null;
|
|
1062
|
-
if (parsedEntry && runtimeEntry &&
|
|
1059
|
+
if (parsedEntry && runtimeEntry && isRuntimeOverlay(runtimeEntry) && getTime(parsedEntry.message) === 0 && getTime(runtimeEntry.message) > 0) {
|
|
1063
1060
|
if (shouldKeepParsedBeforeUntimedRuntime(parsedEntry.message)) {
|
|
1064
1061
|
return a.source === 'parsed' ? -1 : 1;
|
|
1065
1062
|
}
|
|
@@ -1072,8 +1069,8 @@ export class CliProviderInstance implements ProviderInstance {
|
|
|
1072
1069
|
// do not carry timestamps on parsed messages. In that case there is no safe
|
|
1073
1070
|
// clock basis for interleaving timestamped runtime/system messages into the
|
|
1074
1071
|
// provider transcript. Keep user prompts before runtime overlays, but do not
|
|
1075
|
-
// let timed runtime/system overlays become the final chat turns
|
|
1076
|
-
// untimed parsed assistant transcript.
|
|
1072
|
+
// let timed runtime/system/tool/internal overlays become the final chat turns
|
|
1073
|
+
// after an untimed parsed assistant transcript.
|
|
1077
1074
|
return a.index - b.index;
|
|
1078
1075
|
})
|
|
1079
1076
|
.map((entry) => entry.message));
|
|
@@ -77,6 +77,14 @@ function validateMessage(message: unknown, source: string, index: number): ChatM
|
|
|
77
77
|
if (typeof message.senderName === 'string') normalized.senderName = message.senderName
|
|
78
78
|
if (typeof (message as any)._type === 'string') normalized._type = (message as any)._type
|
|
79
79
|
if (typeof (message as any)._sub === 'string') normalized._sub = (message as any)._sub
|
|
80
|
+
if (typeof (message as any).visibility === 'string') normalized.visibility = (message as any).visibility
|
|
81
|
+
if (typeof (message as any).transcriptVisibility === 'string') normalized.transcriptVisibility = (message as any).transcriptVisibility
|
|
82
|
+
if (typeof (message as any).audience === 'string') normalized.audience = (message as any).audience
|
|
83
|
+
if (typeof (message as any).source === 'string') normalized.source = (message as any).source
|
|
84
|
+
if (typeof (message as any).userFacing === 'boolean') normalized.userFacing = (message as any).userFacing
|
|
85
|
+
if (typeof (message as any).internal === 'boolean') normalized.internal = (message as any).internal
|
|
86
|
+
if (typeof (message as any).isInternal === 'boolean') normalized.isInternal = (message as any).isInternal
|
|
87
|
+
if (typeof (message as any).debug === 'boolean') normalized.debug = (message as any).debug
|
|
80
88
|
|
|
81
89
|
return normalized
|
|
82
90
|
}
|
package/src/types.ts
CHANGED
|
@@ -49,6 +49,15 @@ export interface ChatMessage {
|
|
|
49
49
|
/** Optional: fiber metadata */
|
|
50
50
|
_type?: string;
|
|
51
51
|
_sub?: string;
|
|
52
|
+
/** Transcript visibility/audience contract for separating chat-visible content from internal/debug runtime rows. */
|
|
53
|
+
visibility?: 'visible' | 'user' | 'chat' | 'hidden' | 'debug' | 'internal' | (string & {});
|
|
54
|
+
transcriptVisibility?: 'visible' | 'user' | 'chat' | 'hidden' | 'debug' | 'internal' | (string & {});
|
|
55
|
+
audience?: 'chat' | 'debug' | 'trace' | 'internal' | (string & {});
|
|
56
|
+
source?: 'assistant_text' | 'tool_call' | 'terminal_command' | 'runtime_activity' | 'runtime_status' | 'provider_chrome' | 'control' | (string & {});
|
|
57
|
+
userFacing?: boolean;
|
|
58
|
+
internal?: boolean;
|
|
59
|
+
isInternal?: boolean;
|
|
60
|
+
debug?: boolean;
|
|
52
61
|
/** Meta information for thought/terminal logs etc */
|
|
53
62
|
meta?: { label?: string; isRunning?: boolean } | Record<string, any>;
|
|
54
63
|
/** Sender name for shared sessions */
|