@adhdev/daemon-core 0.9.76-rc.32 → 0.9.76-rc.34
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 +119 -58
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +119 -58
- package/dist/index.mjs.map +1 -1
- package/dist/mesh/mesh-events.d.ts +9 -0
- package/package.json +1 -1
- package/src/commands/chat-commands.ts +26 -0
- package/src/commands/router.ts +5 -0
- package/src/mesh/mesh-events.ts +76 -33
|
@@ -1,2 +1,11 @@
|
|
|
1
1
|
import type { DaemonComponents } from '../boot/daemon-lifecycle.js';
|
|
2
|
+
export declare function handleMeshForwardEvent(components: DaemonComponents, payload: Record<string, unknown>): {
|
|
3
|
+
success: boolean;
|
|
4
|
+
forwarded: number;
|
|
5
|
+
error?: undefined;
|
|
6
|
+
} | {
|
|
7
|
+
success: boolean;
|
|
8
|
+
error: string;
|
|
9
|
+
forwarded?: undefined;
|
|
10
|
+
};
|
|
2
11
|
export declare function setupMeshEventForwarding(components: DaemonComponents): void;
|
package/package.json
CHANGED
|
@@ -502,6 +502,18 @@ function buildChatDebugBundleSummary(bundle: Record<string, unknown>): Record<st
|
|
|
502
502
|
const readChat = bundle.readChat && typeof bundle.readChat === 'object' ? bundle.readChat as Record<string, unknown> : {};
|
|
503
503
|
const cli = bundle.cli && typeof bundle.cli === 'object' ? bundle.cli as Record<string, unknown> : null;
|
|
504
504
|
const frontend = bundle.frontend && typeof bundle.frontend === 'object' ? bundle.frontend as Record<string, unknown> : null;
|
|
505
|
+
const debugReadChat = readChat.debugReadChat && typeof readChat.debugReadChat === 'object'
|
|
506
|
+
? readChat.debugReadChat as Record<string, unknown>
|
|
507
|
+
: {};
|
|
508
|
+
const parsedStatus = cli?.parsedStatus && typeof cli.parsedStatus === 'object'
|
|
509
|
+
? cli.parsedStatus as Record<string, unknown>
|
|
510
|
+
: null;
|
|
511
|
+
const cliParsedMessageCount = Array.isArray(parsedStatus?.messages) ? parsedStatus.messages.length : undefined;
|
|
512
|
+
const readChatReturnedMessages = Array.isArray(readChat.messagesTail) ? readChat.messagesTail.length : undefined;
|
|
513
|
+
const cliPartialResponse = typeof cli?.partialResponse === 'string' ? cli.partialResponse : '';
|
|
514
|
+
const readChatStatus = typeof readChat.status === 'string' ? readChat.status : '';
|
|
515
|
+
const cliStatus = typeof cli?.status === 'string' ? cli.status : '';
|
|
516
|
+
const cliParsedStatus = typeof parsedStatus?.status === 'string' ? parsedStatus.status : '';
|
|
505
517
|
return {
|
|
506
518
|
createdAt: bundle.createdAt,
|
|
507
519
|
targetSessionId: target.targetSessionId,
|
|
@@ -510,8 +522,22 @@ function buildChatDebugBundleSummary(bundle: Record<string, unknown>): Record<st
|
|
|
510
522
|
readChatSuccess: readChat.success,
|
|
511
523
|
readChatStatus: readChat.status,
|
|
512
524
|
readChatTotalMessages: readChat.totalMessages,
|
|
525
|
+
readChatReturnedMessages,
|
|
513
526
|
cliStatus: cli?.status,
|
|
527
|
+
cliParsedStatus: cliParsedStatus || undefined,
|
|
514
528
|
cliMessageCount: cli?.messageCount,
|
|
529
|
+
cliParsedMessageCount,
|
|
530
|
+
cliPartialResponseChars: cliPartialResponse.length,
|
|
531
|
+
parserAdapterStatusMismatch: Boolean(cliStatus && cliParsedStatus && cliStatus !== cliParsedStatus),
|
|
532
|
+
parserReadChatStatusMismatch: Boolean(readChatStatus && cliParsedStatus && readChatStatus !== cliParsedStatus),
|
|
533
|
+
readChatDebug: Object.keys(debugReadChat).length ? {
|
|
534
|
+
adapterStatus: debugReadChat.adapterStatus,
|
|
535
|
+
parsedStatus: debugReadChat.parsedStatus,
|
|
536
|
+
returnedStatus: debugReadChat.returnedStatus,
|
|
537
|
+
parsedMsgCount: debugReadChat.parsedMsgCount,
|
|
538
|
+
returnedMsgCount: debugReadChat.returnedMsgCount,
|
|
539
|
+
shouldPreferAdapterMessages: debugReadChat.shouldPreferAdapterMessages,
|
|
540
|
+
} : undefined,
|
|
515
541
|
hasFrontendSnapshot: !!frontend,
|
|
516
542
|
};
|
|
517
543
|
}
|
package/src/commands/router.ts
CHANGED
|
@@ -36,6 +36,7 @@ import { createInteractionId, getRecentDebugTrace, recordDebugTrace } from '../l
|
|
|
36
36
|
import { getSessionHostSurfaceKind, partitionSessionHostRecords } from '../session-host/runtime-surface.js';
|
|
37
37
|
import { createHermesManualMeshCoordinatorSetup, resolveMeshCoordinatorSetup } from './mesh-coordinator.js';
|
|
38
38
|
import { buildSessionEntries } from '../status/builders.js';
|
|
39
|
+
import { handleMeshForwardEvent } from '../mesh/mesh-events.js';
|
|
39
40
|
import { buildMachineInfo, buildStatusSnapshot } from '../status/snapshot.js';
|
|
40
41
|
import { getSessionCompletionMarker } from '../status/snapshot.js';
|
|
41
42
|
import { execNpmCommandSync, resolveCurrentGlobalInstallSurface, spawnDetachedDaemonUpgradeHelper } from './upgrade-helper.js';
|
|
@@ -471,6 +472,10 @@ export class DaemonCommandRouter {
|
|
|
471
472
|
private async executeDaemonCommand(cmd: string, args: any): Promise<CommandRouterResult | null> {
|
|
472
473
|
switch (cmd) {
|
|
473
474
|
// ─── CLI / ACP commands ───
|
|
475
|
+
case 'mesh_forward_event': {
|
|
476
|
+
return handleMeshForwardEvent({ instanceManager: this.deps.instanceManager } as any, args as Record<string, unknown>);
|
|
477
|
+
}
|
|
478
|
+
|
|
474
479
|
case 'launch_cli':
|
|
475
480
|
case 'stop_cli':
|
|
476
481
|
case 'set_cli_view_mode':
|
package/src/mesh/mesh-events.ts
CHANGED
|
@@ -15,6 +15,75 @@ function formatCompletionMetadata(event: Record<string, unknown>): string {
|
|
|
15
15
|
return parts.length > 0 ? ` (${parts.join('; ')})` : '';
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
+
function buildMeshSystemMessage(args: {
|
|
19
|
+
event: string;
|
|
20
|
+
nodeLabel: string;
|
|
21
|
+
metadataEvent: Record<string, unknown>;
|
|
22
|
+
}): string {
|
|
23
|
+
const metadata = formatCompletionMetadata(args.metadataEvent);
|
|
24
|
+
if (args.event === 'agent:generating_completed') {
|
|
25
|
+
return `[System] ${args.nodeLabel} has completed its task and is now idle${metadata}. You may use mesh_read_chat to review its progress.`;
|
|
26
|
+
}
|
|
27
|
+
if (args.event === 'agent:waiting_approval') {
|
|
28
|
+
return `[System] ${args.nodeLabel} is waiting for approval to proceed${metadata}. You may use mesh_read_chat and mesh_approve to handle it.`;
|
|
29
|
+
}
|
|
30
|
+
return '';
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function injectMeshSystemMessage(components: DaemonComponents, args: {
|
|
34
|
+
meshId: string;
|
|
35
|
+
sourceInstanceId?: string;
|
|
36
|
+
nodeLabel: string;
|
|
37
|
+
event: string;
|
|
38
|
+
metadataEvent: Record<string, unknown>;
|
|
39
|
+
}) {
|
|
40
|
+
const coordinatorInstances = components.instanceManager.getByCategory('cli').filter((inst) => {
|
|
41
|
+
const instState = inst.getState();
|
|
42
|
+
if (instState.settings?.meshCoordinatorFor !== args.meshId) return false;
|
|
43
|
+
if (args.sourceInstanceId && instState.instanceId === args.sourceInstanceId) return false;
|
|
44
|
+
return true;
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
if (coordinatorInstances.length === 0) return { success: true, forwarded: 0 };
|
|
48
|
+
|
|
49
|
+
const messageText = buildMeshSystemMessage({
|
|
50
|
+
event: args.event,
|
|
51
|
+
nodeLabel: args.nodeLabel,
|
|
52
|
+
metadataEvent: args.metadataEvent,
|
|
53
|
+
});
|
|
54
|
+
if (!messageText) return { success: false, error: 'unsupported mesh event' };
|
|
55
|
+
|
|
56
|
+
for (const coord of coordinatorInstances) {
|
|
57
|
+
const coordState = coord.getState();
|
|
58
|
+
LOG.info('MeshEvents', `Forwarding mesh event to coordinator ${coordState.instanceId}`);
|
|
59
|
+
coord.onEvent('send_message', { input: { text: messageText, textFallback: messageText } });
|
|
60
|
+
}
|
|
61
|
+
return { success: true, forwarded: coordinatorInstances.length };
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function handleMeshForwardEvent(components: DaemonComponents, payload: Record<string, unknown>) {
|
|
65
|
+
const eventName = readNonEmptyString(payload.event);
|
|
66
|
+
if (eventName !== 'agent:generating_completed' && eventName !== 'agent:waiting_approval') {
|
|
67
|
+
return { success: false, error: 'unsupported mesh event' };
|
|
68
|
+
}
|
|
69
|
+
const meshId = readNonEmptyString(payload.meshId);
|
|
70
|
+
if (!meshId) return { success: false, error: 'meshId required' };
|
|
71
|
+
|
|
72
|
+
const nodeId = readNonEmptyString(payload.nodeId);
|
|
73
|
+
const workspace = readNonEmptyString(payload.workspace);
|
|
74
|
+
const nodeLabel = nodeId ? `Node '${nodeId}'` : workspace ? `Agent at ${workspace}` : 'Remote agent';
|
|
75
|
+
return injectMeshSystemMessage(components, {
|
|
76
|
+
meshId,
|
|
77
|
+
nodeLabel,
|
|
78
|
+
event: eventName,
|
|
79
|
+
metadataEvent: {
|
|
80
|
+
targetSessionId: readNonEmptyString(payload.targetSessionId) || readNonEmptyString(payload.sessionId),
|
|
81
|
+
providerType: readNonEmptyString(payload.providerType),
|
|
82
|
+
providerSessionId: readNonEmptyString(payload.providerSessionId),
|
|
83
|
+
},
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
|
|
18
87
|
export function setupMeshEventForwarding(components: DaemonComponents) {
|
|
19
88
|
components.instanceManager.onEvent((event) => {
|
|
20
89
|
// We only care about agent sub-session completion or waiting approval
|
|
@@ -38,22 +107,6 @@ export function setupMeshEventForwarding(components: DaemonComponents) {
|
|
|
38
107
|
const meshId = meshIdFromRuntime || readNonEmptyString(mesh?.id);
|
|
39
108
|
if (!meshId) return;
|
|
40
109
|
|
|
41
|
-
// Find the coordinator session(s)
|
|
42
|
-
const allInstances = components.instanceManager.getByCategory('cli');
|
|
43
|
-
const coordinatorInstances = allInstances.filter((inst) => {
|
|
44
|
-
const instState = inst.getState();
|
|
45
|
-
|
|
46
|
-
// The coordinator session was launched with meshCoordinatorFor setting
|
|
47
|
-
if (instState.settings?.meshCoordinatorFor !== meshId) return false;
|
|
48
|
-
|
|
49
|
-
// Exclude the source instance itself (just in case)
|
|
50
|
-
if (instState.instanceId === instanceId) return false;
|
|
51
|
-
|
|
52
|
-
return true;
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
if (coordinatorInstances.length === 0) return;
|
|
56
|
-
|
|
57
110
|
// Determine node label. Inline/cloud meshes may be unavailable here, so preserve runtime node id.
|
|
58
111
|
const targetNode = mesh?.nodes?.find((n: any) => n.workspace === workspace);
|
|
59
112
|
const runtimeNodeId = readNonEmptyString(settings.meshNodeId);
|
|
@@ -62,23 +115,13 @@ export function setupMeshEventForwarding(components: DaemonComponents) {
|
|
|
62
115
|
: runtimeNodeId
|
|
63
116
|
? `Node '${runtimeNodeId}'`
|
|
64
117
|
: `Agent at ${workspace}`;
|
|
65
|
-
const metadata = formatCompletionMetadata(event);
|
|
66
|
-
|
|
67
|
-
// Construct a system message in English
|
|
68
|
-
let messageText = '';
|
|
69
|
-
if (event.event === 'agent:generating_completed') {
|
|
70
|
-
messageText = `[System] ${nodeLabel} has completed its task and is now idle${metadata}. You may use mesh_read_chat to review its progress.`;
|
|
71
|
-
} else if (event.event === 'agent:waiting_approval') {
|
|
72
|
-
messageText = `[System] ${nodeLabel} is waiting for approval to proceed${metadata}. You may use mesh_read_chat and mesh_approve to handle it.`;
|
|
73
|
-
}
|
|
74
118
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
}
|
|
119
|
+
injectMeshSystemMessage(components, {
|
|
120
|
+
meshId,
|
|
121
|
+
sourceInstanceId: instanceId,
|
|
122
|
+
nodeLabel,
|
|
123
|
+
event: event.event,
|
|
124
|
+
metadataEvent: event,
|
|
125
|
+
});
|
|
83
126
|
});
|
|
84
127
|
}
|