@adhdev/daemon-core 0.9.77-rc.10 → 0.9.77-rc.12
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 +8 -0
- package/dist/index.js +108 -8
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +108 -8
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/commands/mesh-coordinator.ts +28 -6
- package/src/commands/router.ts +99 -0
- package/src/commands/stream-commands.ts +8 -1
- package/src/mesh/mesh-events.ts +1 -1
package/package.json
CHANGED
|
@@ -28,6 +28,15 @@ export type MeshCoordinatorSetup =
|
|
|
28
28
|
instructions: string
|
|
29
29
|
template: string
|
|
30
30
|
}
|
|
31
|
+
| {
|
|
32
|
+
/** Provider registers MCP via its own CLI command (e.g. `codex mcp add` / `gemini mcp add`). */
|
|
33
|
+
kind: 'cli_command'
|
|
34
|
+
serverName: string
|
|
35
|
+
/** The rendered shell command to execute before launching the coordinator session. */
|
|
36
|
+
command: string
|
|
37
|
+
requiresRestart: boolean
|
|
38
|
+
instructions: string
|
|
39
|
+
}
|
|
31
40
|
| {
|
|
32
41
|
kind: 'unsupported'
|
|
33
42
|
reason: string
|
|
@@ -152,6 +161,24 @@ export function resolveMeshCoordinatorSetup(options: ResolveMeshCoordinatorSetup
|
|
|
152
161
|
if (!instructions || !template?.trim()) {
|
|
153
162
|
return { kind: 'unsupported', reason: 'Provider manual MCP setup is missing instructions or template' }
|
|
154
163
|
}
|
|
164
|
+
const renderedTemplate = renderMeshCoordinatorTemplate(template, {
|
|
165
|
+
meshId,
|
|
166
|
+
workspace,
|
|
167
|
+
serverName,
|
|
168
|
+
adhdevMcpCommand: options.adhdevMcpCommand || DEFAULT_ADHDEV_MCP_COMMAND,
|
|
169
|
+
})
|
|
170
|
+
// Detect if the template is a runnable CLI command (single line, no YAML/JSON structure).
|
|
171
|
+
// If so, use cli_command kind so the daemon can execute it automatically.
|
|
172
|
+
const isCliCommand = !renderedTemplate.trim().includes('\n') && !renderedTemplate.trim().startsWith('{')
|
|
173
|
+
if (isCliCommand) {
|
|
174
|
+
return {
|
|
175
|
+
kind: 'cli_command',
|
|
176
|
+
serverName,
|
|
177
|
+
command: renderedTemplate.trim(),
|
|
178
|
+
requiresRestart: mcpConfig.requiresRestart === true,
|
|
179
|
+
instructions: instructions,
|
|
180
|
+
}
|
|
181
|
+
}
|
|
155
182
|
return {
|
|
156
183
|
kind: 'manual',
|
|
157
184
|
serverName,
|
|
@@ -159,12 +186,7 @@ export function resolveMeshCoordinatorSetup(options: ResolveMeshCoordinatorSetup
|
|
|
159
186
|
configPathCommand: mcpConfig.configPathCommand,
|
|
160
187
|
requiresRestart: mcpConfig.requiresRestart === true,
|
|
161
188
|
instructions,
|
|
162
|
-
template:
|
|
163
|
-
meshId,
|
|
164
|
-
workspace,
|
|
165
|
-
serverName,
|
|
166
|
-
adhdevMcpCommand: options.adhdevMcpCommand || DEFAULT_ADHDEV_MCP_COMMAND,
|
|
167
|
-
}),
|
|
189
|
+
template: renderedTemplate,
|
|
168
190
|
}
|
|
169
191
|
}
|
|
170
192
|
|
package/src/commands/router.ts
CHANGED
|
@@ -1711,6 +1711,105 @@ export class DaemonCommandRouter {
|
|
|
1711
1711
|
};
|
|
1712
1712
|
}
|
|
1713
1713
|
|
|
1714
|
+
// ─── CLI-command MCP registration (Codex, Gemini CLI) ───────────
|
|
1715
|
+
if (coordinatorSetup.kind === 'cli_command') {
|
|
1716
|
+
// Build coordinator prompt first — fail closed on errors.
|
|
1717
|
+
let cliCmdSystemPrompt = '';
|
|
1718
|
+
try {
|
|
1719
|
+
cliCmdSystemPrompt = buildCoordinatorSystemPrompt({ mesh, coordinatorCliType: cliType });
|
|
1720
|
+
} catch (error: any) {
|
|
1721
|
+
const message = error?.message || String(error);
|
|
1722
|
+
LOG.error('MeshCoordinator', `Failed to build coordinator prompt: ${message}`);
|
|
1723
|
+
return {
|
|
1724
|
+
success: false,
|
|
1725
|
+
code: 'mesh_coordinator_prompt_failed',
|
|
1726
|
+
error: `Failed to build Repo Mesh coordinator prompt: ${message}`,
|
|
1727
|
+
meshId, cliType, workspace,
|
|
1728
|
+
};
|
|
1729
|
+
}
|
|
1730
|
+
|
|
1731
|
+
// Run the provider's MCP registration command.
|
|
1732
|
+
try {
|
|
1733
|
+
const { execFileSync: execCmdSync } = await import('node:child_process');
|
|
1734
|
+
const cmdParts = coordinatorSetup.command.trim().split(/\s+/);
|
|
1735
|
+
const [regCmd, ...regArgs] = cmdParts;
|
|
1736
|
+
LOG.info('MeshCoordinator', `Running MCP registration: ${coordinatorSetup.command}`);
|
|
1737
|
+
execCmdSync(regCmd, regArgs, { stdio: 'pipe', timeout: 15_000 });
|
|
1738
|
+
} catch (error: any) {
|
|
1739
|
+
// Non-fatal — server may already be registered (providers return exit 1 on duplicate).
|
|
1740
|
+
LOG.warn('MeshCoordinator', `MCP registration command failed (may be pre-registered): ${error?.message || error}`);
|
|
1741
|
+
}
|
|
1742
|
+
|
|
1743
|
+
// Inject system prompt using provider-native methods.
|
|
1744
|
+
// Codex: -c 'instructions="..."' CLI config override
|
|
1745
|
+
// Gemini: write GEMINI.md to workspace (auto-loaded as context)
|
|
1746
|
+
const cliCmdArgs: string[] = [];
|
|
1747
|
+
const cliCmdEnv: Record<string, string> = {};
|
|
1748
|
+
if (cliCmdSystemPrompt) {
|
|
1749
|
+
if (cliType === 'codex-cli') {
|
|
1750
|
+
// Codex reads `developer_instructions` from config.toml as system instructions.
|
|
1751
|
+
// The -c flag overrides a config key for this session only.
|
|
1752
|
+
cliCmdArgs.push('-c', `developer_instructions=${JSON.stringify(cliCmdSystemPrompt)}`);
|
|
1753
|
+
} else if (cliType === 'gemini-cli') {
|
|
1754
|
+
// Gemini CLI auto-loads GEMINI.md from CWD as project context.
|
|
1755
|
+
// Write a temporary GEMINI.md to the workspace before launch.
|
|
1756
|
+
try {
|
|
1757
|
+
const { writeFileSync: wfs, existsSync: efs, readFileSync: rfs } = await import('node:fs');
|
|
1758
|
+
const geminiMdPath = `${workspace}/GEMINI.md`;
|
|
1759
|
+
const marker = '<!-- adhdev-mesh-coordinator-prompt -->';
|
|
1760
|
+
const markerEnd = '<!-- /adhdev-mesh-coordinator-prompt -->';
|
|
1761
|
+
const block = `${marker}\n${cliCmdSystemPrompt}\n${markerEnd}`;
|
|
1762
|
+
if (efs(geminiMdPath)) {
|
|
1763
|
+
const existing = rfs(geminiMdPath, 'utf-8');
|
|
1764
|
+
// Replace existing block or append
|
|
1765
|
+
const replaced = existing.replace(
|
|
1766
|
+
new RegExp(`${marker}[\\s\\S]*?${markerEnd}`, 'g'),
|
|
1767
|
+
block,
|
|
1768
|
+
);
|
|
1769
|
+
wfs(geminiMdPath, replaced.includes(marker) ? replaced : `${existing}\n\n${block}`);
|
|
1770
|
+
} else {
|
|
1771
|
+
wfs(geminiMdPath, block);
|
|
1772
|
+
}
|
|
1773
|
+
LOG.info('MeshCoordinator', `Wrote coordinator prompt to ${workspace}/GEMINI.md`);
|
|
1774
|
+
} catch (e: any) {
|
|
1775
|
+
LOG.warn('MeshCoordinator', `Could not write GEMINI.md: ${e?.message || e}`);
|
|
1776
|
+
}
|
|
1777
|
+
}
|
|
1778
|
+
}
|
|
1779
|
+
|
|
1780
|
+
const cliCmdLaunch: any = await this.deps.cliManager.handleCliCommand('launch_cli', {
|
|
1781
|
+
cliType,
|
|
1782
|
+
dir: workspace,
|
|
1783
|
+
cliArgs: cliCmdArgs.length > 0 ? cliCmdArgs : undefined,
|
|
1784
|
+
env: Object.keys(cliCmdEnv).length > 0 ? cliCmdEnv : undefined,
|
|
1785
|
+
settings: { meshCoordinatorFor: meshId },
|
|
1786
|
+
});
|
|
1787
|
+
|
|
1788
|
+
if (!cliCmdLaunch?.success) {
|
|
1789
|
+
return { success: false, error: cliCmdLaunch?.error || 'Failed to launch CLI session' };
|
|
1790
|
+
}
|
|
1791
|
+
|
|
1792
|
+
LOG.info('MeshCoordinator', `Launched ${cliType} coordinator (cli_command) for mesh ${meshId}`);
|
|
1793
|
+
try {
|
|
1794
|
+
const { appendLedgerEntry } = await import('../mesh/mesh-ledger.js');
|
|
1795
|
+
appendLedgerEntry(meshId, {
|
|
1796
|
+
kind: 'coordinator_started',
|
|
1797
|
+
sessionId: cliCmdLaunch.sessionId || cliCmdLaunch.id,
|
|
1798
|
+
providerType: cliType,
|
|
1799
|
+
payload: { workspace },
|
|
1800
|
+
});
|
|
1801
|
+
} catch { /* best-effort */ }
|
|
1802
|
+
|
|
1803
|
+
return {
|
|
1804
|
+
success: true,
|
|
1805
|
+
meshId,
|
|
1806
|
+
cliType,
|
|
1807
|
+
workspace,
|
|
1808
|
+
sessionId: cliCmdLaunch.sessionId || cliCmdLaunch.id,
|
|
1809
|
+
mcpRegistered: true,
|
|
1810
|
+
};
|
|
1811
|
+
}
|
|
1812
|
+
|
|
1714
1813
|
const configFormat = coordinatorSetup.configFormat as MeshCoordinatorConfigFormat;
|
|
1715
1814
|
if (configFormat !== 'claude_mcp_json' && configFormat !== 'hermes_config_yaml') {
|
|
1716
1815
|
return {
|
|
@@ -113,11 +113,18 @@ export async function handleOpenPanel(h: CommandHelpers, args: any): Promise<Com
|
|
|
113
113
|
export async function handlePtyInput(h: CommandHelpers, args: any): Promise<CommandResult> {
|
|
114
114
|
const { cliType, data, targetSessionId } = args || {};
|
|
115
115
|
if (!data) return { success: false, error: 'data required' };
|
|
116
|
+
|
|
117
|
+
// Filter out VT100/VT420 Device Attributes responses (e.g. \x1b[?1;2c)
|
|
118
|
+
// These are echoed by xterm.js in the dashboard in response to \x1b[c queries
|
|
119
|
+
// and pollute the CLI input buffer.
|
|
120
|
+
const cleanData = typeof data === 'string' ? data.replace(/\x1b\[\?[0-9;]*c/g, '') : data;
|
|
121
|
+
if (!cleanData) return { success: true };
|
|
122
|
+
|
|
116
123
|
const adapter = h.getCliAdapter(targetSessionId || cliType);
|
|
117
124
|
if (!adapter || typeof adapter.writeRaw !== 'function') {
|
|
118
125
|
return { success: false, error: `CLI adapter not found: ${targetSessionId || cliType || 'unknown'}` };
|
|
119
126
|
}
|
|
120
|
-
await adapter.writeRaw(
|
|
127
|
+
await adapter.writeRaw(cleanData);
|
|
121
128
|
return { success: true };
|
|
122
129
|
}
|
|
123
130
|
|
package/src/mesh/mesh-events.ts
CHANGED
|
@@ -76,7 +76,7 @@ export function tryAssignQueueTask(
|
|
|
76
76
|
targetSessionId: sessionId,
|
|
77
77
|
cliType: providerType,
|
|
78
78
|
action: 'send_chat',
|
|
79
|
-
|
|
79
|
+
message: task.message,
|
|
80
80
|
}).catch((e: any) => {
|
|
81
81
|
LOG.error('MeshQueue', `Failed to dispatch task to node ${nodeId}: ${e?.message}`);
|
|
82
82
|
});
|