@adhdev/daemon-core 0.9.68 → 0.9.70
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/commands/mesh-coordinator.d.ts +25 -0
- package/dist/index.js +163 -5
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +163 -5
- package/dist/index.mjs.map +1 -1
- package/dist/providers/contracts.d.ts +34 -0
- package/dist/shared-types.d.ts +3 -1
- package/node_modules/@adhdev/session-host-core/package.json +1 -1
- package/package.json +1 -1
- package/src/commands/mesh-coordinator.ts +97 -0
- package/src/commands/router.ts +47 -7
- package/src/providers/contracts.ts +37 -0
- package/src/providers/provider-schema.ts +67 -0
- package/src/shared-types.ts +3 -1
- package/src/status/snapshot.ts +2 -0
|
@@ -260,6 +260,31 @@ export interface CdpTargetFilter {
|
|
|
260
260
|
titleExcludes?: string;
|
|
261
261
|
}
|
|
262
262
|
export type ProviderVersionCommand = string | Partial<Record<string, string>>;
|
|
263
|
+
export type MeshCoordinatorMcpConfigMode = 'auto_import' | 'manual' | 'none';
|
|
264
|
+
export type MeshCoordinatorMcpConfigFormat = 'claude_mcp_json' | 'hermes_config_yaml';
|
|
265
|
+
export interface ProviderMeshCoordinatorConfig {
|
|
266
|
+
/** Whether ADHDev may select this provider for Repo Mesh coordinator sessions. */
|
|
267
|
+
supported: boolean;
|
|
268
|
+
/** Human-readable reason shown when unsupported or blocked. */
|
|
269
|
+
reason?: string;
|
|
270
|
+
/** How ADHDev mesh MCP tools become visible to the launched CLI. */
|
|
271
|
+
mcpConfig?: {
|
|
272
|
+
mode: MeshCoordinatorMcpConfigMode;
|
|
273
|
+
format?: MeshCoordinatorMcpConfigFormat;
|
|
274
|
+
/** Provider-relative/project-relative config path for auto-import modes, e.g. '.mcp.json'. */
|
|
275
|
+
path?: string;
|
|
276
|
+
/** MCP server name to materialize or display. Defaults to 'adhdev-mesh'. */
|
|
277
|
+
serverName?: string;
|
|
278
|
+
/** Manual setup target path/help command, e.g. 'hermes config path'. */
|
|
279
|
+
configPathCommand?: string;
|
|
280
|
+
/** Whether users need a fresh CLI session after config changes. */
|
|
281
|
+
requiresRestart?: boolean;
|
|
282
|
+
/** User-facing setup explanation for manual modes. */
|
|
283
|
+
instructions?: string;
|
|
284
|
+
/** Copyable setup template. Supports {{meshId}}, {{adhdevMcpCommand}}, {{workspace}}, {{serverName}}. */
|
|
285
|
+
template?: string;
|
|
286
|
+
};
|
|
287
|
+
}
|
|
263
288
|
export interface ProviderCompatibilityEntry {
|
|
264
289
|
ideVersion: string;
|
|
265
290
|
scriptDir: string;
|
|
@@ -271,6 +296,10 @@ export interface ProviderModule {
|
|
|
271
296
|
name: string;
|
|
272
297
|
/** Category: determines execution method */
|
|
273
298
|
category: ProviderCategory;
|
|
299
|
+
/** When provider-owned, daemon treats provider parser output as canonical transcript authority. */
|
|
300
|
+
transcriptAuthority?: 'provider' | 'daemon';
|
|
301
|
+
/** Full context lets provider-owned parsers canonicalize retained history instead of daemon prefix stitching. */
|
|
302
|
+
transcriptContext?: 'full' | 'tail';
|
|
274
303
|
/** Alias list — allows users to invoke by alternate names (e.g. ['claude', 'claude-code']) */
|
|
275
304
|
aliases?: string[];
|
|
276
305
|
/** CDP ports [primary, secondary] (IDE category only) */
|
|
@@ -448,6 +477,11 @@ export interface ProviderModule {
|
|
|
448
477
|
spawnArgBuilder?: (config: Record<string, string>) => string[];
|
|
449
478
|
/** ACP agent auth methods (multiple supported — in priority order) */
|
|
450
479
|
auth?: AcpAuthMethod[];
|
|
480
|
+
/**
|
|
481
|
+
* Repo Mesh coordinator capability and MCP ingestion behavior.
|
|
482
|
+
* Providers must declare this rather than relying on daemon hardcoded CLI quirks.
|
|
483
|
+
*/
|
|
484
|
+
meshCoordinator?: ProviderMeshCoordinatorConfig;
|
|
451
485
|
contractVersion?: number;
|
|
452
486
|
capabilities?: {
|
|
453
487
|
input?: {
|
package/dist/shared-types.d.ts
CHANGED
|
@@ -12,7 +12,7 @@ export type { ProviderState, ProviderStatus, ActiveChatData, IdeProviderState, C
|
|
|
12
12
|
export type { ProviderErrorReason } from './providers/provider-instance.js';
|
|
13
13
|
import type { ActiveChatData as _ActiveChatData, ProviderErrorReason as _ProviderErrorReason } from './providers/provider-instance.js';
|
|
14
14
|
import type { WorkspaceEntry } from './config/workspaces.js';
|
|
15
|
-
import type { ProviderResumeCapability } from './providers/contracts.js';
|
|
15
|
+
import type { ProviderMeshCoordinatorConfig, ProviderResumeCapability } from './providers/contracts.js';
|
|
16
16
|
import type { GitCompactSummary, GitWorkspaceUpdate, WorkspaceGitSubscriptionParams } from './git/git-types.js';
|
|
17
17
|
export type { GitCommandName, GitCompactSummary, GitDiffSummary, GitFailureReason, GitFileChange, GitFileChangeStatus, GitRepoIdentity, GitRepoStatus, GitSnapshot, GitSnapshotCompareSummary, GitSnapshotReason, GitWorkspaceUpdate, WorkspaceGitSubscriptionParams, } from './git/git-types.js';
|
|
18
18
|
export interface SessionActiveChatData extends Omit<_ActiveChatData, 'messages'> {
|
|
@@ -343,6 +343,8 @@ export interface AvailableProviderInfo {
|
|
|
343
343
|
lastDetection?: MachineProviderCheckResult;
|
|
344
344
|
/** Last end-to-end ADHDev verification result, when available. */
|
|
345
345
|
lastVerification?: MachineProviderCheckResult;
|
|
346
|
+
/** Provider-declared Repo Mesh coordinator/MCP behavior. */
|
|
347
|
+
meshCoordinator?: ProviderMeshCoordinatorConfig;
|
|
346
348
|
}
|
|
347
349
|
export interface MachineProviderCheckResult {
|
|
348
350
|
ok: boolean;
|
package/package.json
CHANGED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { join } from 'path'
|
|
2
|
+
import type { ProviderModule, MeshCoordinatorMcpConfigFormat } from '../providers/contracts.js'
|
|
3
|
+
|
|
4
|
+
export type MeshCoordinatorSetup =
|
|
5
|
+
| {
|
|
6
|
+
kind: 'auto_import'
|
|
7
|
+
serverName: string
|
|
8
|
+
configPath: string
|
|
9
|
+
configFormat?: MeshCoordinatorMcpConfigFormat
|
|
10
|
+
}
|
|
11
|
+
| {
|
|
12
|
+
kind: 'manual'
|
|
13
|
+
serverName: string
|
|
14
|
+
configFormat?: MeshCoordinatorMcpConfigFormat
|
|
15
|
+
configPathCommand?: string
|
|
16
|
+
requiresRestart: boolean
|
|
17
|
+
instructions: string
|
|
18
|
+
template: string
|
|
19
|
+
}
|
|
20
|
+
| {
|
|
21
|
+
kind: 'unsupported'
|
|
22
|
+
reason: string
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface ResolveMeshCoordinatorSetupOptions {
|
|
26
|
+
provider?: ProviderModule | null
|
|
27
|
+
meshId: string
|
|
28
|
+
workspace: string
|
|
29
|
+
adhdevMcpCommand?: string
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const DEFAULT_SERVER_NAME = 'adhdev-mesh'
|
|
33
|
+
const DEFAULT_ADHDEV_MCP_COMMAND = 'adhdev-mcp'
|
|
34
|
+
|
|
35
|
+
export function resolveMeshCoordinatorSetup(options: ResolveMeshCoordinatorSetupOptions): MeshCoordinatorSetup {
|
|
36
|
+
const { provider, meshId, workspace } = options
|
|
37
|
+
const config = provider?.meshCoordinator
|
|
38
|
+
if (!config?.supported) {
|
|
39
|
+
return {
|
|
40
|
+
kind: 'unsupported',
|
|
41
|
+
reason: config?.reason || 'Provider does not declare Repo Mesh coordinator support',
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const mcpConfig = config.mcpConfig
|
|
46
|
+
if (!mcpConfig || mcpConfig.mode === 'none') {
|
|
47
|
+
return {
|
|
48
|
+
kind: 'unsupported',
|
|
49
|
+
reason: config.reason || 'Provider does not declare a usable Repo Mesh MCP configuration mode',
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const serverName = mcpConfig.serverName?.trim() || DEFAULT_SERVER_NAME
|
|
54
|
+
if (mcpConfig.mode === 'auto_import') {
|
|
55
|
+
const path = mcpConfig.path?.trim()
|
|
56
|
+
if (!path) {
|
|
57
|
+
return { kind: 'unsupported', reason: 'Provider auto-import MCP config is missing a config path' }
|
|
58
|
+
}
|
|
59
|
+
return {
|
|
60
|
+
kind: 'auto_import',
|
|
61
|
+
serverName,
|
|
62
|
+
configPath: join(workspace, path),
|
|
63
|
+
configFormat: mcpConfig.format,
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (mcpConfig.mode === 'manual') {
|
|
68
|
+
const instructions = mcpConfig.instructions?.trim()
|
|
69
|
+
const template = mcpConfig.template
|
|
70
|
+
if (!instructions || !template?.trim()) {
|
|
71
|
+
return { kind: 'unsupported', reason: 'Provider manual MCP setup is missing instructions or template' }
|
|
72
|
+
}
|
|
73
|
+
return {
|
|
74
|
+
kind: 'manual',
|
|
75
|
+
serverName,
|
|
76
|
+
configFormat: mcpConfig.format,
|
|
77
|
+
configPathCommand: mcpConfig.configPathCommand,
|
|
78
|
+
requiresRestart: mcpConfig.requiresRestart === true,
|
|
79
|
+
instructions,
|
|
80
|
+
template: renderMeshCoordinatorTemplate(template, {
|
|
81
|
+
meshId,
|
|
82
|
+
workspace,
|
|
83
|
+
serverName,
|
|
84
|
+
adhdevMcpCommand: options.adhdevMcpCommand || DEFAULT_ADHDEV_MCP_COMMAND,
|
|
85
|
+
}),
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return {
|
|
90
|
+
kind: 'unsupported',
|
|
91
|
+
reason: `Unsupported Repo Mesh MCP configuration mode: ${String(mcpConfig.mode)}`,
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function renderMeshCoordinatorTemplate(template: string, values: Record<string, string>): string {
|
|
96
|
+
return template.replace(/\{\{\s*(meshId|workspace|serverName|adhdevMcpCommand)\s*\}\}/g, (_, key: string) => values[key] || '')
|
|
97
|
+
}
|
package/src/commands/router.ts
CHANGED
|
@@ -33,6 +33,7 @@ import type { CommandLogEntry } from '../logging/command-log.js';
|
|
|
33
33
|
import { getRecentLogs, LOG_PATH } from '../logging/logger.js';
|
|
34
34
|
import { createInteractionId, getRecentDebugTrace, recordDebugTrace } from '../logging/debug-trace.js';
|
|
35
35
|
import { getSessionHostSurfaceKind, partitionSessionHostRecords } from '../session-host/runtime-surface.js';
|
|
36
|
+
import { resolveMeshCoordinatorSetup } from './mesh-coordinator.js';
|
|
36
37
|
import { buildSessionEntries } from '../status/builders.js';
|
|
37
38
|
import { buildMachineInfo, buildStatusSnapshot } from '../status/snapshot.js';
|
|
38
39
|
import { getSessionCompletionMarker } from '../status/snapshot.js';
|
|
@@ -1012,13 +1013,52 @@ export class DaemonCommandRouter {
|
|
|
1012
1013
|
if (mesh.nodes.length === 0) return { success: false, error: 'No nodes in mesh' };
|
|
1013
1014
|
|
|
1014
1015
|
const workspace = mesh.nodes[0].workspace;
|
|
1016
|
+
const providerMeta = this.deps.providerLoader.resolve?.(cliType) || this.deps.providerLoader.getMeta(cliType);
|
|
1017
|
+
const coordinatorSetup = resolveMeshCoordinatorSetup({
|
|
1018
|
+
provider: providerMeta,
|
|
1019
|
+
meshId,
|
|
1020
|
+
workspace,
|
|
1021
|
+
});
|
|
1022
|
+
|
|
1023
|
+
if (coordinatorSetup.kind === 'unsupported') {
|
|
1024
|
+
return {
|
|
1025
|
+
success: false,
|
|
1026
|
+
code: 'mesh_coordinator_unsupported',
|
|
1027
|
+
error: coordinatorSetup.reason,
|
|
1028
|
+
meshId,
|
|
1029
|
+
cliType,
|
|
1030
|
+
workspace,
|
|
1031
|
+
};
|
|
1032
|
+
}
|
|
1033
|
+
|
|
1034
|
+
if (coordinatorSetup.kind === 'manual') {
|
|
1035
|
+
return {
|
|
1036
|
+
success: false,
|
|
1037
|
+
code: 'mesh_coordinator_manual_mcp_setup_required',
|
|
1038
|
+
error: coordinatorSetup.instructions,
|
|
1039
|
+
meshId,
|
|
1040
|
+
cliType,
|
|
1041
|
+
workspace,
|
|
1042
|
+
meshCoordinatorSetup: coordinatorSetup,
|
|
1043
|
+
};
|
|
1044
|
+
}
|
|
1045
|
+
|
|
1046
|
+
if (coordinatorSetup.configFormat !== 'claude_mcp_json') {
|
|
1047
|
+
return {
|
|
1048
|
+
success: false,
|
|
1049
|
+
code: 'mesh_coordinator_unsupported',
|
|
1050
|
+
error: `Unsupported auto-import MCP config format: ${String(coordinatorSetup.configFormat)}`,
|
|
1051
|
+
meshId,
|
|
1052
|
+
cliType,
|
|
1053
|
+
workspace,
|
|
1054
|
+
};
|
|
1055
|
+
}
|
|
1015
1056
|
|
|
1016
|
-
// 1. Write
|
|
1057
|
+
// 1. Write provider-declared MCP config to workspace for CLIs that auto-import it.
|
|
1017
1058
|
const { existsSync, readFileSync, writeFileSync, copyFileSync } = await import('fs');
|
|
1018
|
-
const
|
|
1019
|
-
const mcpConfigPath = join(workspace, '.mcp.json');
|
|
1059
|
+
const mcpConfigPath = coordinatorSetup.configPath;
|
|
1020
1060
|
|
|
1021
|
-
// Backup existing
|
|
1061
|
+
// Backup existing MCP config if present.
|
|
1022
1062
|
const hadExistingMcpConfig = existsSync(mcpConfigPath);
|
|
1023
1063
|
let existingMcpConfig: any = {};
|
|
1024
1064
|
if (hadExistingMcpConfig) {
|
|
@@ -1028,19 +1068,19 @@ export class DaemonCommandRouter {
|
|
|
1028
1068
|
} catch { /* empty */ }
|
|
1029
1069
|
}
|
|
1030
1070
|
|
|
1031
|
-
// Merge
|
|
1071
|
+
// Merge ADHDev mesh server into existing config.
|
|
1032
1072
|
const mcpConfig = {
|
|
1033
1073
|
...existingMcpConfig,
|
|
1034
1074
|
mcpServers: {
|
|
1035
1075
|
...(existingMcpConfig.mcpServers || {}),
|
|
1036
|
-
|
|
1076
|
+
[coordinatorSetup.serverName]: {
|
|
1037
1077
|
command: 'adhdev-mcp',
|
|
1038
1078
|
args: ['--repo-mesh', meshId],
|
|
1039
1079
|
},
|
|
1040
1080
|
},
|
|
1041
1081
|
};
|
|
1042
1082
|
writeFileSync(mcpConfigPath, JSON.stringify(mcpConfig, null, 2), 'utf-8');
|
|
1043
|
-
LOG.info('MeshCoordinator', `Wrote
|
|
1083
|
+
LOG.info('MeshCoordinator', `Wrote ${mcpConfigPath} with ${coordinatorSetup.serverName} server`);
|
|
1044
1084
|
|
|
1045
1085
|
// 2. Build coordinator system prompt
|
|
1046
1086
|
let systemPrompt = '';
|
|
@@ -345,6 +345,33 @@ export interface CdpTargetFilter {
|
|
|
345
345
|
|
|
346
346
|
export type ProviderVersionCommand = string | Partial<Record<string, string>>;
|
|
347
347
|
|
|
348
|
+
export type MeshCoordinatorMcpConfigMode = 'auto_import' | 'manual' | 'none';
|
|
349
|
+
export type MeshCoordinatorMcpConfigFormat = 'claude_mcp_json' | 'hermes_config_yaml';
|
|
350
|
+
|
|
351
|
+
export interface ProviderMeshCoordinatorConfig {
|
|
352
|
+
/** Whether ADHDev may select this provider for Repo Mesh coordinator sessions. */
|
|
353
|
+
supported: boolean;
|
|
354
|
+
/** Human-readable reason shown when unsupported or blocked. */
|
|
355
|
+
reason?: string;
|
|
356
|
+
/** How ADHDev mesh MCP tools become visible to the launched CLI. */
|
|
357
|
+
mcpConfig?: {
|
|
358
|
+
mode: MeshCoordinatorMcpConfigMode;
|
|
359
|
+
format?: MeshCoordinatorMcpConfigFormat;
|
|
360
|
+
/** Provider-relative/project-relative config path for auto-import modes, e.g. '.mcp.json'. */
|
|
361
|
+
path?: string;
|
|
362
|
+
/** MCP server name to materialize or display. Defaults to 'adhdev-mesh'. */
|
|
363
|
+
serverName?: string;
|
|
364
|
+
/** Manual setup target path/help command, e.g. 'hermes config path'. */
|
|
365
|
+
configPathCommand?: string;
|
|
366
|
+
/** Whether users need a fresh CLI session after config changes. */
|
|
367
|
+
requiresRestart?: boolean;
|
|
368
|
+
/** User-facing setup explanation for manual modes. */
|
|
369
|
+
instructions?: string;
|
|
370
|
+
/** Copyable setup template. Supports {{meshId}}, {{adhdevMcpCommand}}, {{workspace}}, {{serverName}}. */
|
|
371
|
+
template?: string;
|
|
372
|
+
};
|
|
373
|
+
}
|
|
374
|
+
|
|
348
375
|
export interface ProviderCompatibilityEntry {
|
|
349
376
|
ideVersion: string;
|
|
350
377
|
scriptDir: string;
|
|
@@ -357,6 +384,10 @@ export interface ProviderModule {
|
|
|
357
384
|
name: string;
|
|
358
385
|
/** Category: determines execution method */
|
|
359
386
|
category: ProviderCategory;
|
|
387
|
+
/** When provider-owned, daemon treats provider parser output as canonical transcript authority. */
|
|
388
|
+
transcriptAuthority?: 'provider' | 'daemon';
|
|
389
|
+
/** Full context lets provider-owned parsers canonicalize retained history instead of daemon prefix stitching. */
|
|
390
|
+
transcriptContext?: 'full' | 'tail';
|
|
360
391
|
/** Alias list — allows users to invoke by alternate names (e.g. ['claude', 'claude-code']) */
|
|
361
392
|
aliases?: string[];
|
|
362
393
|
|
|
@@ -555,6 +586,12 @@ export interface ProviderModule {
|
|
|
555
586
|
/** ACP agent auth methods (multiple supported — in priority order) */
|
|
556
587
|
auth?: AcpAuthMethod[];
|
|
557
588
|
|
|
589
|
+
/**
|
|
590
|
+
* Repo Mesh coordinator capability and MCP ingestion behavior.
|
|
591
|
+
* Providers must declare this rather than relying on daemon hardcoded CLI quirks.
|
|
592
|
+
*/
|
|
593
|
+
meshCoordinator?: ProviderMeshCoordinatorConfig;
|
|
594
|
+
|
|
558
595
|
// ─── Contract version / capability declaration ───
|
|
559
596
|
contractVersion?: number;
|
|
560
597
|
capabilities?: {
|
|
@@ -7,6 +7,8 @@ const KNOWN_PROVIDER_FIELDS = new Set<string>([
|
|
|
7
7
|
'type',
|
|
8
8
|
'name',
|
|
9
9
|
'category',
|
|
10
|
+
'transcriptAuthority',
|
|
11
|
+
'transcriptContext',
|
|
10
12
|
'aliases',
|
|
11
13
|
'cdpPorts',
|
|
12
14
|
'targetFilter',
|
|
@@ -51,6 +53,7 @@ const KNOWN_PROVIDER_FIELDS = new Set<string>([
|
|
|
51
53
|
'staticConfigOptions',
|
|
52
54
|
'spawnArgBuilder',
|
|
53
55
|
'auth',
|
|
56
|
+
'meshCoordinator',
|
|
54
57
|
'contractVersion',
|
|
55
58
|
'capabilities',
|
|
56
59
|
'providerVersion',
|
|
@@ -125,6 +128,7 @@ export function validateProviderDefinition(raw: unknown): ProviderValidationResu
|
|
|
125
128
|
|
|
126
129
|
validateCapabilities(provider as unknown as ProviderModule, controls, errors)
|
|
127
130
|
validateCanonicalHistory(provider.canonicalHistory, errors)
|
|
131
|
+
validateMeshCoordinator(provider.meshCoordinator, errors)
|
|
128
132
|
|
|
129
133
|
for (const control of controls) {
|
|
130
134
|
validateControl(control as ProviderControlDef, errors)
|
|
@@ -233,6 +237,69 @@ function validateCanonicalHistory(raw: unknown, errors: string[]): void {
|
|
|
233
237
|
}
|
|
234
238
|
}
|
|
235
239
|
|
|
240
|
+
function validateMeshCoordinator(raw: unknown, errors: string[]): void {
|
|
241
|
+
if (raw === undefined) return
|
|
242
|
+
if (!raw || typeof raw !== 'object' || Array.isArray(raw)) {
|
|
243
|
+
errors.push('meshCoordinator must be an object')
|
|
244
|
+
return
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
const meshCoordinator = raw as Record<string, unknown>
|
|
248
|
+
if (typeof meshCoordinator.supported !== 'boolean') {
|
|
249
|
+
errors.push('meshCoordinator.supported must be boolean')
|
|
250
|
+
}
|
|
251
|
+
if (meshCoordinator.reason !== undefined && (typeof meshCoordinator.reason !== 'string' || !meshCoordinator.reason.trim())) {
|
|
252
|
+
errors.push('meshCoordinator.reason must be a non-empty string when provided')
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
const mcpConfig = meshCoordinator.mcpConfig
|
|
256
|
+
if (mcpConfig === undefined) return
|
|
257
|
+
if (!mcpConfig || typeof mcpConfig !== 'object' || Array.isArray(mcpConfig)) {
|
|
258
|
+
errors.push('meshCoordinator.mcpConfig must be an object')
|
|
259
|
+
return
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
const config = mcpConfig as Record<string, unknown>
|
|
263
|
+
const mode = config.mode
|
|
264
|
+
if (!['auto_import', 'manual', 'none'].includes(String(mode))) {
|
|
265
|
+
errors.push('meshCoordinator.mcpConfig.mode must be one of: auto_import, manual, none')
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
const format = config.format
|
|
269
|
+
if (format !== undefined && !['claude_mcp_json', 'hermes_config_yaml'].includes(String(format))) {
|
|
270
|
+
errors.push('meshCoordinator.mcpConfig.format must be one of: claude_mcp_json, hermes_config_yaml')
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
for (const key of ['path', 'serverName', 'configPathCommand', 'instructions', 'template']) {
|
|
274
|
+
const value = config[key]
|
|
275
|
+
if (value !== undefined && (typeof value !== 'string' || !value.trim())) {
|
|
276
|
+
errors.push(`meshCoordinator.mcpConfig.${key} must be a non-empty string when provided`)
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
if (config.requiresRestart !== undefined && typeof config.requiresRestart !== 'boolean') {
|
|
281
|
+
errors.push('meshCoordinator.mcpConfig.requiresRestart must be boolean when provided')
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
if (mode === 'auto_import') {
|
|
285
|
+
if (format === undefined) {
|
|
286
|
+
errors.push('meshCoordinator.mcpConfig.format is required for auto_import MCP setup')
|
|
287
|
+
}
|
|
288
|
+
if (typeof config.path !== 'string' || !config.path.trim()) {
|
|
289
|
+
errors.push('meshCoordinator.mcpConfig.path is required for auto_import MCP setup')
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
if (mode === 'manual') {
|
|
294
|
+
if (typeof config.instructions !== 'string' || !config.instructions.trim()) {
|
|
295
|
+
errors.push('meshCoordinator.mcpConfig.instructions is required for manual MCP setup')
|
|
296
|
+
}
|
|
297
|
+
if (typeof config.template !== 'string' || !config.template.trim()) {
|
|
298
|
+
errors.push('meshCoordinator.mcpConfig.template is required for manual MCP setup')
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
236
303
|
function validateControl(control: ProviderControlDef, errors: string[]): void {
|
|
237
304
|
if (!control || typeof control !== 'object') {
|
|
238
305
|
errors.push('controls: each control must be an object')
|
package/src/shared-types.ts
CHANGED
|
@@ -43,7 +43,7 @@ export type { ProviderErrorReason } from './providers/provider-instance.js';
|
|
|
43
43
|
// Local import for use in Managed*Entry types below
|
|
44
44
|
import type { ActiveChatData as _ActiveChatData, ProviderErrorReason as _ProviderErrorReason } from './providers/provider-instance.js';
|
|
45
45
|
import type { WorkspaceEntry } from './config/workspaces.js';
|
|
46
|
-
import type { ProviderResumeCapability } from './providers/contracts.js';
|
|
46
|
+
import type { ProviderMeshCoordinatorConfig, ProviderResumeCapability } from './providers/contracts.js';
|
|
47
47
|
import type {
|
|
48
48
|
GitCompactSummary,
|
|
49
49
|
GitDiffSummary,
|
|
@@ -447,6 +447,8 @@ export interface AvailableProviderInfo {
|
|
|
447
447
|
lastDetection?: MachineProviderCheckResult;
|
|
448
448
|
/** Last end-to-end ADHDev verification result, when available. */
|
|
449
449
|
lastVerification?: MachineProviderCheckResult;
|
|
450
|
+
/** Provider-declared Repo Mesh coordinator/MCP behavior. */
|
|
451
|
+
meshCoordinator?: ProviderMeshCoordinatorConfig;
|
|
450
452
|
}
|
|
451
453
|
|
|
452
454
|
export interface MachineProviderCheckResult {
|
package/src/status/snapshot.ts
CHANGED
|
@@ -144,6 +144,7 @@ function buildAvailableProviders(
|
|
|
144
144
|
machineStatus?: 'disabled' | 'enabled_unchecked' | 'not_detected' | 'detected';
|
|
145
145
|
lastDetection?: AvailableProviderInfo['lastDetection'];
|
|
146
146
|
lastVerification?: AvailableProviderInfo['lastVerification'];
|
|
147
|
+
meshCoordinator?: AvailableProviderInfo['meshCoordinator'];
|
|
147
148
|
}> = providerLoader.getAvailableProviderInfos?.() || providerLoader.getAll();
|
|
148
149
|
return providers.map((provider) => ({
|
|
149
150
|
type: provider.type,
|
|
@@ -157,6 +158,7 @@ function buildAvailableProviders(
|
|
|
157
158
|
...(provider.machineStatus !== undefined ? { machineStatus: provider.machineStatus } : {}),
|
|
158
159
|
...(provider.lastDetection !== undefined ? { lastDetection: provider.lastDetection } : {}),
|
|
159
160
|
...(provider.lastVerification !== undefined ? { lastVerification: provider.lastVerification } : {}),
|
|
161
|
+
...(provider.meshCoordinator !== undefined ? { meshCoordinator: provider.meshCoordinator } : {}),
|
|
160
162
|
}));
|
|
161
163
|
}
|
|
162
164
|
|