@adhdev/daemon-core 0.9.82-rc.485 → 0.9.82-rc.486
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.d.ts +1 -1
- package/dist/index.js +249 -30
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +248 -30
- package/dist/index.mjs.map +1 -1
- package/dist/mesh/mesh-queue-assignment.d.ts +4 -0
- package/dist/mesh/mesh-work-queue.d.ts +9 -0
- package/dist/repo-mesh-types.d.ts +18 -2
- package/dist/shared-types.d.ts +8 -0
- package/dist/status/snapshot.d.ts +1 -0
- package/package.json +3 -3
- package/src/commands/handler.ts +21 -1
- package/src/commands/high-family/mesh-coordinator-launch.ts +17 -1
- package/src/commands/high-family/mesh-status.ts +8 -0
- package/src/commands/med-family/cli-agent.ts +29 -0
- package/src/index.ts +1 -1
- package/src/mesh/coordinator-prompt.ts +4 -1
- package/src/mesh/mesh-queue-assignment.ts +164 -27
- package/src/mesh/mesh-work-queue.ts +14 -0
- package/src/repo-mesh-types.ts +28 -3
- package/src/shared-types.ts +8 -0
- package/src/status/builders.ts +45 -2
- package/src/status/snapshot.ts +1 -1
|
@@ -591,6 +591,15 @@ export interface MeshWorkQueueEntry {
|
|
|
591
591
|
* setConfigOption('thought_level')). Rides in payload JSON. Best-effort like model.
|
|
592
592
|
*/
|
|
593
593
|
thinkingLevel?: string;
|
|
594
|
+
/**
|
|
595
|
+
* SLOT-ROUTING (ORCHESTRATION_NODE_SLOTS.md): the coordinator's difficulty
|
|
596
|
+
* classification for this task ('easy'|'medium'|'difficult'|'freeform'),
|
|
597
|
+
* PERSISTED on the entry so the scheduler can match it against node capability
|
|
598
|
+
* slots at assignment time. Previously an enqueue-only option consumed to
|
|
599
|
+
* resolve model/thinkingLevel and then discarded; keeping it lets task→node
|
|
600
|
+
* fitness matching run. Absent on tasks enqueued without a difficulty.
|
|
601
|
+
*/
|
|
602
|
+
difficulty?: string;
|
|
594
603
|
/**
|
|
595
604
|
* M1: why this task is held back (e.g. "dependency_failed:<taskId>").
|
|
596
605
|
* Only set by the system on dependency failure under the 'block' policy;
|
|
@@ -904,6 +913,10 @@ export function enqueueTask(
|
|
|
904
913
|
// an unconfigured preset just leaves the explicit values (or none) in place.
|
|
905
914
|
let effectiveModel = typeof opts?.model === 'string' && opts.model.trim() ? opts.model.trim() : undefined;
|
|
906
915
|
let effectiveThinkingLevel = typeof opts?.thinkingLevel === 'string' && opts.thinkingLevel.trim() ? opts.thinkingLevel.trim() : undefined;
|
|
916
|
+
// SLOT-ROUTING: persist the difficulty class on the entry so the scheduler can
|
|
917
|
+
// match it against node capability slots at assignment time (not just resolve
|
|
918
|
+
// model/thinking here). Absent/invalid → undefined (task carries no difficulty).
|
|
919
|
+
const taskDifficulty = isMeshTaskDifficulty(opts?.difficulty) ? (opts!.difficulty as MeshTaskDifficulty) : undefined;
|
|
907
920
|
if (isMeshTaskDifficulty(opts?.difficulty)) {
|
|
908
921
|
try {
|
|
909
922
|
const preset = getDifficultyBrains()[opts!.difficulty as MeshTaskDifficulty];
|
|
@@ -951,6 +964,7 @@ export function enqueueTask(
|
|
|
951
964
|
...(typeof opts?.consensusGroupId === 'string' && opts.consensusGroupId.trim() ? { consensusGroupId: opts.consensusGroupId.trim() } : {}),
|
|
952
965
|
...(effectiveModel ? { model: effectiveModel } : {}),
|
|
953
966
|
...(effectiveThinkingLevel ? { thinkingLevel: effectiveThinkingLevel } : {}),
|
|
967
|
+
...(taskDifficulty ? { difficulty: taskDifficulty } : {}),
|
|
954
968
|
...(typeof opts?.sourceCoordinatorSessionId === 'string' && opts.sourceCoordinatorSessionId.trim()
|
|
955
969
|
? { sourceCoordinatorSessionId: opts.sourceCoordinatorSessionId.trim() }
|
|
956
970
|
: {}),
|
package/src/repo-mesh-types.ts
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
import type { GitRepoStatus, GitCompactSummary } from './git/git-types.js';
|
|
15
15
|
import type { MeshMissionSummary, MeshMissionSlimSummary } from './mesh/mesh-missions.js';
|
|
16
16
|
import type { MeshMagiActivitySummary } from './mesh/mesh-magi-status.js';
|
|
17
|
-
import type { MagiKindPanelMap, DifficultyBrainMap } from '@adhdev/mesh-shared';
|
|
17
|
+
import type { MagiKindPanelMap, DifficultyBrainMap, NodeCapabilitySlot } from '@adhdev/mesh-shared';
|
|
18
18
|
|
|
19
19
|
// ─── Core Mesh Types ────────────────────────────
|
|
20
20
|
|
|
@@ -139,13 +139,18 @@ export type RepoMeshSchedulingStrategy =
|
|
|
139
139
|
| 'first_eligible'
|
|
140
140
|
| 'least_loaded'
|
|
141
141
|
| 'round_robin'
|
|
142
|
-
| 'priority_only'
|
|
142
|
+
| 'priority_only'
|
|
143
|
+
// ORCHESTRATION_NODE_SLOTS.md: rank nodes by task→capability-slot fitness
|
|
144
|
+
// (task difficulty/requiredTags vs the node's slots), then priority/load/order.
|
|
145
|
+
// Falls back to load ordering when no task is in scope (idle-session drain).
|
|
146
|
+
| 'fitness';
|
|
143
147
|
|
|
144
148
|
export const MESH_SCHEDULING_STRATEGIES: RepoMeshSchedulingStrategy[] = [
|
|
145
149
|
'first_eligible',
|
|
146
150
|
'least_loaded',
|
|
147
151
|
'round_robin',
|
|
148
152
|
'priority_only',
|
|
153
|
+
'fitness',
|
|
149
154
|
];
|
|
150
155
|
|
|
151
156
|
export const DEFAULT_MESH_SCHEDULING_STRATEGY: RepoMeshSchedulingStrategy = 'first_eligible';
|
|
@@ -403,8 +408,22 @@ export interface RepoMeshNodePolicy {
|
|
|
403
408
|
* enforced as an additional, stricter-wins constraint on top of the global
|
|
404
409
|
* maxParallelTasks/taskMode caps. Missing/empty: the node behaves exactly as
|
|
405
410
|
* before (global caps only). Routing is governed solely by required_tags.
|
|
411
|
+
*
|
|
412
|
+
* SUPERSEDED by `slots` (ORCHESTRATION_NODE_SLOTS.md). Kept for back-compat:
|
|
413
|
+
* when `slots` is absent, providerRoles + providerPriority + the machine-global
|
|
414
|
+
* difficultyBrains are auto-derived into slots via deriveSlotsFromLegacy.
|
|
406
415
|
*/
|
|
407
416
|
providerRoles?: RepoMeshProviderRole[];
|
|
417
|
+
/**
|
|
418
|
+
* Node capability slots (ORCHESTRATION_NODE_SLOTS.md) — the ordered "Preferred
|
|
419
|
+
* AI tools" profile that is the single source of truth for task routing, MAGI
|
|
420
|
+
* fan-out, and orchestrator-proposed edits. Each slot bundles provider + model
|
|
421
|
+
* + thinkingLevel + difficulty range + capability tags + per-slot maxParallel.
|
|
422
|
+
* Order = preference. When absent, the scheduler derives slots from the legacy
|
|
423
|
+
* providerPriority/providerRoles/difficultyBrains (deriveSlotsFromLegacy) so
|
|
424
|
+
* existing nodes keep working without reconfiguration.
|
|
425
|
+
*/
|
|
426
|
+
slots?: NodeCapabilitySlot[];
|
|
408
427
|
/**
|
|
409
428
|
* Per-node override for RepoMeshPolicy.delegatedWorkerAutoApprove. When set, takes
|
|
410
429
|
* precedence over the mesh-level policy for worker sessions launched onto this node.
|
|
@@ -440,7 +459,11 @@ export const DEFAULT_MESH_POLICY: RepoMeshPolicy = {
|
|
|
440
459
|
allowAutoPublishSubmoduleMainCommits: false,
|
|
441
460
|
requireApprovalForDestructiveGit: true,
|
|
442
461
|
dirtyWorkspaceBehavior: 'warn',
|
|
443
|
-
|
|
462
|
+
// Mesh-wide task cap is effectively unlimited by default: the real concurrency
|
|
463
|
+
// limits live per node / per capability slot (ORCHESTRATION_NODE_SLOTS.md), so a
|
|
464
|
+
// global ceiling is rarely meaningful. The UI hides this control; set it via the
|
|
465
|
+
// API only to impose a deliberate mesh-wide cap.
|
|
466
|
+
maxParallelTasks: 200,
|
|
444
467
|
// Coordinator-spawned worker sessions default to hidden so the dashboard is not
|
|
445
468
|
// flooded with mesh noise tabs/notifications. Users can still surface or unmute
|
|
446
469
|
// any specific session manually; that override is preserved per-device.
|
|
@@ -1143,6 +1166,8 @@ export interface RepoMeshNodeStatus {
|
|
|
1143
1166
|
activeSessions: string[];
|
|
1144
1167
|
activeSessionDetails?: RepoMeshSessionStatus[];
|
|
1145
1168
|
providerPriority?: string[];
|
|
1169
|
+
/** Explicitly-configured node capability slots (ORCHESTRATION_NODE_SLOTS.md). */
|
|
1170
|
+
slots?: NodeCapabilitySlot[];
|
|
1146
1171
|
launchReady?: boolean;
|
|
1147
1172
|
/** True when the node is clean, ahead=0, behind>0, and safe for fast-forward consideration. */
|
|
1148
1173
|
autoFastForwardEligible?: boolean;
|
package/src/shared-types.ts
CHANGED
|
@@ -416,6 +416,13 @@ export interface SessionEntry {
|
|
|
416
416
|
completionMarker?: string;
|
|
417
417
|
seenCompletionMarker?: string;
|
|
418
418
|
surfaceHidden?: boolean;
|
|
419
|
+
/**
|
|
420
|
+
* User (or coordinator-policy) muted: suppress attention side-effects
|
|
421
|
+
* (notifications, toasts, completion audio) for this session WITHOUT removing
|
|
422
|
+
* it from the inbox list. Distinct from surfaceHidden (which collapses it from
|
|
423
|
+
* the list). Daemon-owned, in-memory; rides the status snapshot.
|
|
424
|
+
*/
|
|
425
|
+
muted?: boolean;
|
|
419
426
|
settings?: Record<string, any>;
|
|
420
427
|
/**
|
|
421
428
|
* True owning-daemon id for a session a coordinator synthesises into its own
|
|
@@ -488,6 +495,7 @@ export interface CompactSessionEntry {
|
|
|
488
495
|
completionMarker?: string;
|
|
489
496
|
seenCompletionMarker?: string;
|
|
490
497
|
surfaceHidden?: boolean;
|
|
498
|
+
muted?: boolean;
|
|
491
499
|
controlValues?: Record<string, string | number | boolean>;
|
|
492
500
|
providerControls?: ProviderControlSchema[];
|
|
493
501
|
summaryMetadata?: ProviderSummaryMetadata;
|
package/src/status/builders.ts
CHANGED
|
@@ -34,6 +34,47 @@ import {
|
|
|
34
34
|
} from '../providers/open-panel-support.js';
|
|
35
35
|
import { TEXT_ONLY_MESSAGE_INPUT_SUPPORT } from '../providers/provider-input-support.js';
|
|
36
36
|
|
|
37
|
+
/**
|
|
38
|
+
* A coordinator-spawned worker session that mesh policy launched hidden. This is
|
|
39
|
+
* the daemon-side equivalent of the web `shouldAutoHideMeshConversation` predicate:
|
|
40
|
+
* these sessions should default to muted+hidden in the user dashboard (the user
|
|
41
|
+
* interacts through the ONE coordinator session, not each worker), while the
|
|
42
|
+
* coordinator↔worker mesh data/completion path (mesh-event-forwarding) is
|
|
43
|
+
* unaffected.
|
|
44
|
+
*/
|
|
45
|
+
function isCoordinatorSpawnedHiddenWorker(settings: Record<string, any> | undefined): boolean {
|
|
46
|
+
if (!settings) return false;
|
|
47
|
+
return settings.launchedByCoordinator === true
|
|
48
|
+
&& typeof settings.meshNodeFor === 'string'
|
|
49
|
+
&& settings.meshNodeFor.trim().length > 0
|
|
50
|
+
&& settings.spawnedSessionVisibility === 'hidden';
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* A session is surface-hidden (collapsed from the user's inbox/notifications) when
|
|
55
|
+
* mesh policy spawned it hidden, OR when a coordinator-spawned worker defaults
|
|
56
|
+
* hidden, OR when the user manually hid it (userHidden). userHidden === false is an
|
|
57
|
+
* explicit un-hide that overrides the policy/worker default until daemon restart.
|
|
58
|
+
*/
|
|
59
|
+
function resolveSurfaceHidden(settings: Record<string, any> | undefined): boolean {
|
|
60
|
+
if (!settings) return false;
|
|
61
|
+
if (settings.userHidden === true) return true;
|
|
62
|
+
if (settings.userHidden === false) return false;
|
|
63
|
+
return settings.spawnedSessionVisibility === 'hidden' || isCoordinatorSpawnedHiddenWorker(settings);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* A session is muted (attention side-effects suppressed, but still shown in the
|
|
68
|
+
* list) when the user muted it, OR a coordinator-spawned worker defaults muted.
|
|
69
|
+
* userMuted === false is an explicit un-mute overriding the worker default.
|
|
70
|
+
*/
|
|
71
|
+
function resolveMuted(settings: Record<string, any> | undefined): boolean {
|
|
72
|
+
if (!settings) return false;
|
|
73
|
+
if (settings.userMuted === true) return true;
|
|
74
|
+
if (settings.userMuted === false) return false;
|
|
75
|
+
return isCoordinatorSpawnedHiddenWorker(settings);
|
|
76
|
+
}
|
|
77
|
+
|
|
37
78
|
export type SessionEntryProfile = 'full' | 'live' | 'metadata';
|
|
38
79
|
|
|
39
80
|
export interface SessionEntryBuildOptions {
|
|
@@ -342,7 +383,8 @@ function buildCliSession(state: CliProviderState, options: SessionEntryBuildOpti
|
|
|
342
383
|
settings: state.settings,
|
|
343
384
|
...(coordinator && { coordinator }),
|
|
344
385
|
...(meshQueueStats && { meshQueueStats }),
|
|
345
|
-
...(state.settings
|
|
386
|
+
...(resolveSurfaceHidden(state.settings) && { surfaceHidden: true }),
|
|
387
|
+
...(resolveMuted(state.settings) && { muted: true }),
|
|
346
388
|
};
|
|
347
389
|
}
|
|
348
390
|
|
|
@@ -384,7 +426,8 @@ function buildAcpSession(state: AcpProviderState, options: SessionEntryBuildOpti
|
|
|
384
426
|
settings: state.settings,
|
|
385
427
|
...(coordinator && { coordinator }),
|
|
386
428
|
...(meshQueueStats && { meshQueueStats }),
|
|
387
|
-
...(state.settings
|
|
429
|
+
...(resolveSurfaceHidden(state.settings) && { surfaceHidden: true }),
|
|
430
|
+
...(resolveMuted(state.settings) && { muted: true }),
|
|
388
431
|
};
|
|
389
432
|
}
|
|
390
433
|
|
package/src/status/snapshot.ts
CHANGED
|
@@ -130,7 +130,7 @@ function buildDetectedIdeInfos(
|
|
|
130
130
|
}));
|
|
131
131
|
}
|
|
132
132
|
|
|
133
|
-
function buildAvailableProviders(
|
|
133
|
+
export function buildAvailableProviders(
|
|
134
134
|
providerLoader: StatusSnapshotOptions['providerLoader'],
|
|
135
135
|
): AvailableProviderInfo[] {
|
|
136
136
|
const providers: Array<{
|