@adhdev/daemon-core 0.9.67 → 0.9.68

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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adhdev/session-host-core",
3
- "version": "0.9.67",
3
+ "version": "0.9.68",
4
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",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adhdev/daemon-core",
3
- "version": "0.9.67",
3
+ "version": "0.9.68",
4
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",
@@ -920,6 +920,162 @@ export class DaemonCommandRouter {
920
920
  return { success: true };
921
921
  }
922
922
 
923
+ // ─── Mesh CRUD (local meshes.json) ───
924
+ case 'list_meshes': {
925
+ try {
926
+ const { listMeshes } = await import('../config/mesh-config.js');
927
+ return { success: true, meshes: listMeshes() };
928
+ } catch (e: any) {
929
+ return { success: false, error: e.message };
930
+ }
931
+ }
932
+
933
+ case 'get_mesh': {
934
+ const meshId = typeof args?.meshId === 'string' ? args.meshId.trim() : '';
935
+ if (!meshId) return { success: false, error: 'meshId required' };
936
+ try {
937
+ const { getMesh } = await import('../config/mesh-config.js');
938
+ const mesh = getMesh(meshId);
939
+ if (!mesh) return { success: false, error: 'Mesh not found' };
940
+ return { success: true, mesh };
941
+ } catch (e: any) {
942
+ return { success: false, error: e.message };
943
+ }
944
+ }
945
+
946
+ case 'create_mesh': {
947
+ const name = typeof args?.name === 'string' ? args.name.trim() : '';
948
+ const repoIdentity = typeof args?.repoIdentity === 'string' ? args.repoIdentity.trim() : '';
949
+ const repoRemoteUrl = typeof args?.repoRemoteUrl === 'string' ? args.repoRemoteUrl.trim() : undefined;
950
+ const defaultBranch = typeof args?.defaultBranch === 'string' ? args.defaultBranch.trim() : undefined;
951
+ if (!name) return { success: false, error: 'name required' };
952
+ try {
953
+ const { createMesh } = await import('../config/mesh-config.js');
954
+ const mesh = createMesh({ name, repoIdentity, repoRemoteUrl, defaultBranch });
955
+ return { success: true, mesh };
956
+ } catch (e: any) {
957
+ return { success: false, error: e.message };
958
+ }
959
+ }
960
+
961
+ case 'delete_mesh': {
962
+ const meshId = typeof args?.meshId === 'string' ? args.meshId.trim() : '';
963
+ if (!meshId) return { success: false, error: 'meshId required' };
964
+ try {
965
+ const { deleteMesh } = await import('../config/mesh-config.js');
966
+ const deleted = deleteMesh(meshId);
967
+ return { success: true, deleted };
968
+ } catch (e: any) {
969
+ return { success: false, error: e.message };
970
+ }
971
+ }
972
+
973
+ case 'add_mesh_node': {
974
+ const meshId = typeof args?.meshId === 'string' ? args.meshId.trim() : '';
975
+ const workspace = typeof args?.workspace === 'string' ? args.workspace.trim() : '';
976
+ if (!meshId) return { success: false, error: 'meshId required' };
977
+ if (!workspace) return { success: false, error: 'workspace required' };
978
+ try {
979
+ const { addNode } = await import('../config/mesh-config.js');
980
+ const node = addNode(meshId, { workspace });
981
+ if (!node) return { success: false, error: 'Mesh not found' };
982
+ return { success: true, node };
983
+ } catch (e: any) {
984
+ return { success: false, error: e.message };
985
+ }
986
+ }
987
+
988
+ case 'remove_mesh_node': {
989
+ const meshId = typeof args?.meshId === 'string' ? args.meshId.trim() : '';
990
+ const nodeId = typeof args?.nodeId === 'string' ? args.nodeId.trim() : '';
991
+ if (!meshId || !nodeId) return { success: false, error: 'meshId and nodeId required' };
992
+ try {
993
+ const { removeNode } = await import('../config/mesh-config.js');
994
+ const removed = removeNode(meshId, nodeId);
995
+ return { success: true, removed };
996
+ } catch (e: any) {
997
+ return { success: false, error: e.message };
998
+ }
999
+ }
1000
+
1001
+ // ─── Mesh Coordinator Launch ───
1002
+ case 'launch_mesh_coordinator': {
1003
+ const meshId = typeof args?.meshId === 'string' ? args.meshId.trim() : '';
1004
+ const cliType = typeof args?.cliType === 'string' ? args.cliType.trim() : 'claude-cli';
1005
+ if (!meshId) return { success: false, error: 'meshId required' };
1006
+
1007
+ try {
1008
+ const { getMesh } = await import('../config/mesh-config.js');
1009
+ const { buildCoordinatorSystemPrompt } = await import('../mesh/coordinator-prompt.js');
1010
+ const mesh = getMesh(meshId);
1011
+ if (!mesh) return { success: false, error: 'Mesh not found' };
1012
+ if (mesh.nodes.length === 0) return { success: false, error: 'No nodes in mesh' };
1013
+
1014
+ const workspace = mesh.nodes[0].workspace;
1015
+
1016
+ // 1. Write .mcp.json to workspace so Claude CLI auto-discovers mesh tools
1017
+ const { existsSync, readFileSync, writeFileSync, copyFileSync } = await import('fs');
1018
+ const { join } = await import('path');
1019
+ const mcpConfigPath = join(workspace, '.mcp.json');
1020
+
1021
+ // Backup existing .mcp.json if present
1022
+ const hadExistingMcpConfig = existsSync(mcpConfigPath);
1023
+ let existingMcpConfig: any = {};
1024
+ if (hadExistingMcpConfig) {
1025
+ try {
1026
+ existingMcpConfig = JSON.parse(readFileSync(mcpConfigPath, 'utf-8'));
1027
+ copyFileSync(mcpConfigPath, mcpConfigPath + '.backup');
1028
+ } catch { /* empty */ }
1029
+ }
1030
+
1031
+ // Merge adhdev-mesh server into existing config
1032
+ const mcpConfig = {
1033
+ ...existingMcpConfig,
1034
+ mcpServers: {
1035
+ ...(existingMcpConfig.mcpServers || {}),
1036
+ 'adhdev-mesh': {
1037
+ command: 'adhdev-mcp',
1038
+ args: ['--repo-mesh', meshId],
1039
+ },
1040
+ },
1041
+ };
1042
+ writeFileSync(mcpConfigPath, JSON.stringify(mcpConfig, null, 2), 'utf-8');
1043
+ LOG.info('MeshCoordinator', `Wrote .mcp.json to ${workspace} with adhdev-mesh server`);
1044
+
1045
+ // 2. Build coordinator system prompt
1046
+ let systemPrompt = '';
1047
+ try {
1048
+ systemPrompt = buildCoordinatorSystemPrompt({ mesh });
1049
+ } catch {
1050
+ systemPrompt = `You are a Repo Mesh Coordinator for "${mesh.name}". Use the adhdev-mesh MCP tools (mesh_status, mesh_list_nodes, mesh_send_task, mesh_read_chat, mesh_launch_session, etc.) to orchestrate work across ${mesh.nodes.length} node(s).`;
1051
+ }
1052
+
1053
+ // 3. Launch CLI session via existing cliManager
1054
+ const launchResult: any = await this.deps.cliManager.handleCliCommand('launch_cli', {
1055
+ cliType,
1056
+ dir: workspace,
1057
+ initialPrompt: systemPrompt,
1058
+ });
1059
+
1060
+ if (!launchResult?.success) {
1061
+ return { success: false, error: launchResult?.error || 'Failed to launch CLI session' };
1062
+ }
1063
+
1064
+ LOG.info('MeshCoordinator', `Launched ${cliType} coordinator for mesh ${meshId} in ${workspace}`);
1065
+ return {
1066
+ success: true,
1067
+ meshId,
1068
+ cliType,
1069
+ workspace,
1070
+ sessionId: launchResult.sessionId || launchResult.id,
1071
+ mcpConfigWritten: true,
1072
+ };
1073
+ } catch (e: any) {
1074
+ LOG.error('MeshCoordinator', `Failed: ${e.message}`);
1075
+ return { success: false, error: e.message };
1076
+ }
1077
+ }
1078
+
923
1079
  default:
924
1080
  break;
925
1081
  }