@adhdev/daemon-core 0.9.82-rc.364 → 0.9.82-rc.365

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.
@@ -0,0 +1,2 @@
1
+ import type { MedFamilyHandler } from './types.js';
2
+ export declare const cliAgentHandlers: Record<string, MedFamilyHandler>;
@@ -0,0 +1,2 @@
1
+ import type { MedFamilyHandler } from './types.js';
2
+ export declare const fastForwardHandlers: Record<string, MedFamilyHandler>;
@@ -0,0 +1,10 @@
1
+ import type { CommandRouterResult } from '../router.js';
2
+ import type { MedFamilyContext, MedFamilyHandler } from './types.js';
3
+ /**
4
+ * IDE launch + CDP connect. Lifted verbatim from the original `launch_ide` switch
5
+ * case so restart_session / restart_ide can call it directly instead of recursing
6
+ * through executeDaemonCommand. Reads the router's CDP managers and detection
7
+ * caches via ctx.deps.
8
+ */
9
+ export declare function launchIde(ctx: MedFamilyContext, args: any): Promise<CommandRouterResult>;
10
+ export declare const ideHandlers: Record<string, MedFamilyHandler>;
@@ -0,0 +1,3 @@
1
+ import type { MedFamilyRegistry } from './types.js';
2
+ export type { MedFamilyContext, MedFamilyHandler, MedFamilyRegistry } from './types.js';
3
+ export declare const medFamilyRegistry: MedFamilyRegistry;
@@ -0,0 +1,2 @@
1
+ import type { MedFamilyHandler } from './types.js';
2
+ export declare const meshCrudHandlers: Record<string, MedFamilyHandler>;
@@ -0,0 +1,2 @@
1
+ import type { MedFamilyHandler } from './types.js';
2
+ export declare const meshHostPairingHandlers: Record<string, MedFamilyHandler>;
@@ -0,0 +1,2 @@
1
+ import type { MedFamilyHandler } from './types.js';
2
+ export declare const meshQueueHandlers: Record<string, MedFamilyHandler>;
@@ -0,0 +1,116 @@
1
+ /**
2
+ * RF-ROUTER MED family — shared types for the extracted medium-coupling command
3
+ * handlers. Like the LOW family, each handler is a function of (context, args)
4
+ * that returns the exact CommandRouterResult the original `executeDaemonCommand`
5
+ * switch case returned, so the router facade is unchanged.
6
+ *
7
+ * Unlike the LOW family, MED handlers need a handful of router-private
8
+ * collaborators (mesh resolution, owner gating, inline-cache mutation, worktree /
9
+ * session cleanup, refine job starters, IDE launch). The router binds these onto
10
+ * MedFamilyContext at dispatch; they are NOT reachable from `deps`. The IDE family
11
+ * also needs `launchIde` to break the original `launch_ide`/`restart_*`
12
+ * self-recursion through executeDaemonCommand.
13
+ *
14
+ * Registry dispatch: DaemonCommandRouter.executeDaemonCommand looks up the cmd in
15
+ * medFamilyRegistry BEFORE its switch; a hit returns the handler result, a miss
16
+ * falls through to the remaining switch (and ultimately CommandHandler delegation).
17
+ */
18
+ import type { CommandRouterDeps, CommandRouterResult, MeshGitProbeCache } from '../router.js';
19
+ import type { RepoMeshSessionCleanupMode } from '../../repo-mesh-types.js';
20
+ import type { WorktreeBootstrapState } from '../../mesh/worktree-bootstrap-config.js';
21
+ /** Mesh record resolved from the router's inline-mesh cache + local config. */
22
+ export type ResolvedMeshForCommand = {
23
+ mesh: any;
24
+ inline: boolean;
25
+ source: 'inline_cache' | 'inline_bootstrap' | 'local_config';
26
+ } | null;
27
+ /** Result of the router's local worktree-node cleanup. */
28
+ export type CleanupLocalWorktreeNodeResult = {
29
+ success: true;
30
+ skipped?: boolean;
31
+ removedPath?: string;
32
+ repoRoot?: string;
33
+ reason?: string;
34
+ fallback?: string;
35
+ forced?: boolean;
36
+ convergence?: Record<string, unknown>;
37
+ recovered?: boolean;
38
+ residue?: boolean;
39
+ residueWarning?: string;
40
+ residueError?: string;
41
+ } | {
42
+ success: false;
43
+ code: string;
44
+ error: string;
45
+ recoveryHint: string;
46
+ convergence?: Record<string, unknown>;
47
+ };
48
+ /**
49
+ * Router-private collaborators injected at dispatch. Each is a bound method or
50
+ * field of DaemonCommandRouter; handlers that don't need a given collaborator
51
+ * simply ignore it. The router owns this instance state (inline-mesh cache,
52
+ * aggregate-status cache, session/worktree cleanup, refine jobs), so it cannot be
53
+ * read from `deps` — the registry receives bound references instead.
54
+ */
55
+ export interface MedFamilyContext {
56
+ deps: CommandRouterDeps;
57
+ /** Bound `DaemonCommandRouter.getMeshForCommand`. */
58
+ getMeshForCommand: (meshId: string, inlineMesh?: unknown, options?: {
59
+ preferInline?: boolean;
60
+ }) => Promise<ResolvedMeshForCommand>;
61
+ /** Bound `DaemonCommandRouter.getCachedInlineMesh`. */
62
+ getCachedInlineMesh: (meshId: string, inlineMesh?: unknown) => any | undefined;
63
+ /** Bound `DaemonCommandRouter.requireMeshHostMutationOwner` (owner gate). */
64
+ requireMeshHostMutationOwner: (meshId: string, inlineMesh: unknown, operation: string) => Promise<CommandRouterResult | null>;
65
+ /** Bound `DaemonCommandRouter.invalidateAggregateMeshStatus`. */
66
+ invalidateAggregateMeshStatus: (meshId: string) => void;
67
+ /** Bound `DaemonCommandRouter.updateInlineMeshNode`. */
68
+ updateInlineMeshNode: (meshId: string, mesh: any, node: any) => void;
69
+ /** Bound `DaemonCommandRouter.removeInlineMeshNode`. */
70
+ removeInlineMeshNode: (meshId: string, mesh: any, nodeId: string) => boolean;
71
+ /** Bound `DaemonCommandRouter.normalizeMeshSessionCleanupMode`. */
72
+ normalizeMeshSessionCleanupMode: (value: unknown) => RepoMeshSessionCleanupMode;
73
+ /** Bound `DaemonCommandRouter.cleanupMeshSessions`. */
74
+ cleanupMeshSessions: (args: {
75
+ meshId: string;
76
+ nodeId: string;
77
+ node: any;
78
+ mode: RepoMeshSessionCleanupMode;
79
+ sessionIds?: string[];
80
+ dryRun?: boolean;
81
+ source?: 'mesh_cleanup_sessions' | 'mesh_remove_node';
82
+ }) => Promise<{
83
+ success: boolean;
84
+ [key: string]: unknown;
85
+ }>;
86
+ /** Bound `DaemonCommandRouter.cleanupLocalWorktreeNode`. */
87
+ cleanupLocalWorktreeNode: (args: {
88
+ mesh: any;
89
+ node: any;
90
+ nodeId: string;
91
+ force?: boolean;
92
+ }) => Promise<CleanupLocalWorktreeNodeResult>;
93
+ /** Bound `DaemonCommandRouter.startMeshRefineJob` (async execute path). */
94
+ startMeshRefineJob: (meshId: string, nodeId: string, args: any) => Promise<CommandRouterResult>;
95
+ /** Bound `DaemonCommandRouter.batchRefineMeshNodes` (dry-run batch plan). */
96
+ batchRefineMeshNodes: (meshId: string, requestedNodeIds: string[] | undefined, args: any) => Promise<CommandRouterResult>;
97
+ /** Bound `DaemonCommandRouter.startMeshRefineBatchJob` (async batch execute). */
98
+ startMeshRefineBatchJob: (meshId: string, requestedNodeIds: string[] | undefined, args: any) => Promise<CommandRouterResult>;
99
+ /** Bound `DaemonCommandRouter.stopIde` (CDP disconnect + cleanup + optional kill). */
100
+ stopIde: (ideType: string, killProcess?: boolean) => Promise<void>;
101
+ /**
102
+ * Module-level `launchIde` helper bound to this context. The original
103
+ * `launch_ide` case body, lifted into a free function so `restart_session` /
104
+ * `restart_ide` can invoke the IDE launch directly instead of recursing
105
+ * through `executeDaemonCommand('launch_ide')` (which would re-enter the
106
+ * registry). Byte-identical to the original case body.
107
+ */
108
+ launchIde: (args: any) => Promise<CommandRouterResult>;
109
+ /** Router's inline-mesh cache (read/write of resolved mesh records). */
110
+ inlineMeshCache: Map<string, any>;
111
+ /** Router's mesh git-probe cache (reused direct-truth probes for get_mesh). */
112
+ meshGitProbeCache: MeshGitProbeCache;
113
+ }
114
+ export type MedFamilyHandler = (ctx: MedFamilyContext, args: any) => Promise<CommandRouterResult | null>;
115
+ export type MedFamilyRegistry = Map<string, MedFamilyHandler>;
116
+ export type { WorktreeBootstrapState };
@@ -14,7 +14,22 @@ import { DaemonCliManager } from './cli-manager.js';
14
14
  import type { ProviderLoader } from '../providers/provider-loader.js';
15
15
  import type { ProviderInstanceManager } from '../providers/provider-instance-manager.js';
16
16
  import { SessionRegistry } from '../sessions/registry.js';
17
+ /**
18
+ * Normalize a providerRoles array (RepoMeshNodePolicy.providerRoles) from raw
19
+ * tool args. Each entry binds a providerType to an optional `maxParallel` cap.
20
+ * Entries without a usable providerType are dropped; the last entry wins on
21
+ * duplicate providerType. Returns [] when no valid entries — callers then omit
22
+ * the field entirely (full backward compat). Routing is governed by required_tags;
23
+ * any legacy `role` field on the input is ignored.
24
+ */
25
+ export declare function normalizeProviderRoles(value: unknown): Array<{
26
+ providerType: string;
27
+ maxParallel?: number;
28
+ }>;
29
+ export declare function readObjectRecord(value: unknown): Record<string, any>;
30
+ export declare function readStringValue(...values: unknown[]): string | undefined;
17
31
  export declare function buildMeshNodeDisplayLabel(node: Record<string, unknown>, nodeId: string, providerPriority: string[]): string;
32
+ export declare function readMeshNodeMachineId(node: Record<string, unknown>): string | undefined;
18
33
  /**
19
34
  * Resolve the owning-node attribution for a mesh node record so a coordinator can
20
35
  * stamp the TRUE owner onto a synthetic session entry instead of letting the
@@ -28,6 +43,54 @@ export declare function resolveMeshNodeAttribution(node: unknown): {
28
43
  machineName?: string;
29
44
  };
30
45
  export declare function readCachedInlineMeshActiveSessionDetails(node: any): Array<Record<string, unknown>>;
46
+ /**
47
+ * De-duplicates and rate-limits per-peer git_status probes so a single mesh
48
+ * refresh — or a burst of refreshes from the dashboard auto-retry loop — cannot
49
+ * launch a storm of concurrent/back-to-back `refreshUpstream:true` commands to
50
+ * the same slow peer.
51
+ *
52
+ * Two gates, both keyed by `daemonId::workspace`:
53
+ * - In-flight dedup: a second probe for a key with a probe already running
54
+ * shares (awaits) the in-flight promise instead of issuing a second command.
55
+ * - Recently-probed reuse: a successful probe younger than `reuseMs` is reused
56
+ * verbatim instead of issuing a fresh probe. Failures are NOT cached (so a
57
+ * transient timeout doesn't pin a peer to "no truth" for the whole window).
58
+ *
59
+ * Lives on the router instance so the gate spans separate mesh_status calls,
60
+ * which is exactly where the refresh storm happens.
61
+ */
62
+ export declare class MeshGitProbeCache {
63
+ private readonly reuseMs;
64
+ private readonly now;
65
+ private inflight;
66
+ private recent;
67
+ constructor(reuseMs: number, now?: () => number);
68
+ private key;
69
+ /**
70
+ * Run `probe` for this peer, but reuse a fresh recent result or an in-flight
71
+ * probe for the same key when one is available. `probe` is only invoked when
72
+ * neither gate is satisfied.
73
+ */
74
+ probe(daemonId: string, workspace: string, probe: () => Promise<Record<string, unknown> | null>): Promise<Record<string, unknown> | null>;
75
+ }
76
+ export declare function hydrateInlineMeshDirectTruth(args: {
77
+ mesh: any;
78
+ meshSource: 'inline_cache' | 'inline_bootstrap' | 'local_config';
79
+ dispatchMeshCommand?: (daemonId: string, cmd: string, args: Record<string, unknown>) => Promise<unknown>;
80
+ getMeshPeerConnectionStatus?: (daemonId: string) => Record<string, unknown> | null;
81
+ statusInstanceId?: string;
82
+ localMachineId?: string;
83
+ probeRemotePeers: boolean;
84
+ probeCache?: MeshGitProbeCache;
85
+ }): Promise<{
86
+ directEvidenceCount: number;
87
+ localConfirmedCount: number;
88
+ peerAttemptedCount: number;
89
+ peerConfirmedCount: number;
90
+ standingEvidenceCount: number;
91
+ unavailableNodeIds: string[];
92
+ deadNodeIds: string[];
93
+ }>;
31
94
  type MeshRefineStageStatus = 'passed' | 'failed' | 'skipped';
32
95
  type MeshRefinePatchEquivalenceSummary = {
33
96
  status: MeshRefineStageStatus;
@@ -206,6 +269,7 @@ export declare function collectFastForwardGitlinkPaths(repoRoot: string, baseHea
206
269
  * passes a regular-file conflict or a diverged (non-ff) gitlink.
207
270
  */
208
271
  export declare function evaluateGitlinkTrivialFastForward(repoRoot: string, baseHead: string, branchHead: string): GitlinkTrivialFastForwardEvaluation;
272
+ export declare function buildMeshRefineValidationPlan(mesh: any, workspace: string): Record<string, unknown>;
209
273
  export interface SessionHostControlPlane {
210
274
  getDiagnostics(payload?: {
211
275
  includeSessions?: boolean;
@@ -275,6 +339,15 @@ export interface CommandRouterResult {
275
339
  success: boolean;
276
340
  [key: string]: unknown;
277
341
  }
342
+ /**
343
+ * Confine a spec path to ~/.adhdev/providers, defeating both prefix-bypass
344
+ * (e.g. ".../providers-evil") and symlink escape. Resolves the real path of
345
+ * the *parent* directory (the file may not exist yet for writes), requires the
346
+ * basename to be a literal `*.json`, and re-joins under the verified parent so
347
+ * the returned path can't point outside the tree. Used by get/write_spec_source.
348
+ */
349
+ export declare function normalizeStandaloneHostCommandUrl(hostAddress: string): string;
350
+ export declare function buildMemberJoinNode(mesh: any, args: any, fallbackDaemonId?: string): Record<string, unknown> | null;
278
351
  export declare class DaemonCommandRouter {
279
352
  private deps;
280
353
  /** In-memory cache for cloud-originating meshes passed via inlineMesh.
@@ -349,6 +422,16 @@ export declare class DaemonCommandRouter {
349
422
  private warmInlineMeshCache;
350
423
  private getMeshForCommand;
351
424
  private invalidateAggregateMeshStatus;
425
+ /**
426
+ * Build the MedFamilyContext handed to RF-ROUTER MED family handlers. Binds the
427
+ * router-private collaborators those handlers need (mesh resolution, owner
428
+ * gating, inline-cache mutation, worktree / session cleanup, refine job
429
+ * starters, IDE stop/launch) plus the inline-mesh and git-probe caches. The
430
+ * `launchIde` field closes over the freshly-built context so restart_session /
431
+ * restart_ide invoke the IDE launch directly instead of recursing through
432
+ * executeDaemonCommand('launch_ide').
433
+ */
434
+ private buildMedFamilyContext;
352
435
  private requireMeshHostMutationOwner;
353
436
  private updateInlineMeshNode;
354
437
  private removeInlineMeshNode;