@adhdev/daemon-core 0.9.82-rc.425 → 0.9.82-rc.427

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adhdev/daemon-core",
3
- "version": "0.9.82-rc.425",
3
+ "version": "0.9.82-rc.427",
4
4
  "description": "ADHDev daemon core — CDP, IDE detection, providers, command execution",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -46,7 +46,7 @@
46
46
  "author": "vilmire",
47
47
  "license": "AGPL-3.0-or-later",
48
48
  "dependencies": {
49
- "@adhdev/mesh-shared": "0.9.82-rc.425",
49
+ "@adhdev/mesh-shared": "0.9.82-rc.427",
50
50
  "@adhdev/session-host-core": "*",
51
51
  "@agentclientprotocol/sdk": "^0.16.1",
52
52
  "ajv": "^8.20.0",
@@ -222,6 +222,64 @@ export const meshCrudHandlers: Record<string, MedFamilyHandler> = {
222
222
  }
223
223
  },
224
224
 
225
+ // ─── MAGI panels (machine-local config, sibling to meshes) ───────────────
226
+ // Panels live in ~/.adhdev/meshes.json `magiPanels` and are pure local config
227
+ // (no mesh ownership). These three handlers mirror list_meshes/create_mesh/
228
+ // update_mesh: dynamic-import the already-exported mesh-config accessors and
229
+ // surface normalizeMagiPanel's structured error codes (invalid_magi_panel,
230
+ // magi_panel_exists) verbatim so the dashboard can render them.
231
+ //
232
+ // Permission: magi_panel_set / magi_panel_remove are WRITE commands. They are
233
+ // intentionally NOT listed in canPeerUsePrivilegedShareCommand (daemon-cloud
234
+ // data-channel-router), so a peer holding ANY share permission hits its
235
+ // `default → false` branch — identical owner-only gating to create_mesh /
236
+ // update_mesh / list_meshes (none of which are listed there either). A trusted
237
+ // peer (no permission = the owner) passes the top `!permission → true` guard.
238
+ // Mirror, don't invent: do not add a new policy tier here.
239
+ //
240
+ // Resolvability (coupling / stale / available) is deliberately NOT computed
241
+ // here: buildMagiFanoutPlan lives in mcp-server, unreachable from daemon-core.
242
+ // magi_panel_list returns the raw definitions only; the dashboard derives
243
+ // member resolvability client-side (web-core MagiPanelManager, reusing the
244
+ // MagiGroupRow coupling logic) against live mesh_status.
245
+ magi_panel_list: async (_ctx: MedFamilyContext, _args: any) => {
246
+ try {
247
+ const { listMagiPanels } = await import('../../config/mesh-config.js');
248
+ return { success: true, panels: listMagiPanels() };
249
+ } catch (e: any) {
250
+ return { success: false, error: e.message };
251
+ }
252
+ },
253
+
254
+ magi_panel_set: async (_ctx: MedFamilyContext, args: any) => {
255
+ const name = typeof args?.name === 'string' ? args.name.trim() : '';
256
+ if (!name) return { success: false, error: 'invalid_magi_panel: panel name is required' };
257
+ try {
258
+ const { upsertMagiPanel } = await import('../../config/mesh-config.js');
259
+ // normalizeMagiPanel (invoked inside upsertMagiPanel) validates members,
260
+ // enforces MAX_MAGI_PANEL_MEMBERS, and clamps replica counts. Its
261
+ // invalid_magi_panel / magi_panel_exists messages flow back as `error`.
262
+ const panel = upsertMagiPanel(name, args?.panel, { overwrite: args?.overwrite === true });
263
+ return { success: true, name, panel };
264
+ } catch (e: any) {
265
+ // Surface the structured code (invalid_magi_panel: … / magi_panel_exists: …)
266
+ // verbatim so the editor can map it to a field-level message.
267
+ return { success: false, error: e.message };
268
+ }
269
+ },
270
+
271
+ magi_panel_remove: async (_ctx: MedFamilyContext, args: any) => {
272
+ const name = typeof args?.name === 'string' ? args.name.trim() : '';
273
+ if (!name) return { success: false, error: 'invalid_magi_panel: panel name is required' };
274
+ try {
275
+ const { removeMagiPanel } = await import('../../config/mesh-config.js');
276
+ const removed = removeMagiPanel(name);
277
+ return { success: true, removed };
278
+ } catch (e: any) {
279
+ return { success: false, error: e.message };
280
+ }
281
+ },
282
+
225
283
  add_mesh_node: async (ctx: MedFamilyContext, args: any) => {
226
284
  const meshId = typeof args?.meshId === 'string' ? args.meshId.trim() : '';
227
285
  const workspace = typeof args?.workspace === 'string' ? args.workspace.trim() : '';