Extract Claude MCP action seam
This commit is contained in:
parent
116d312cca
commit
b913978a3c
6 changed files with 204 additions and 153 deletions
181
apps/desktop/src/agent-setup-actions-claude-mcp.ts
Normal file
181
apps/desktop/src/agent-setup-actions-claude-mcp.ts
Normal file
|
|
@ -0,0 +1,181 @@
|
|||
import { app } from "electron";
|
||||
import type { ClaudeCommandSpec, ClaudeMcpPreview, FamiliarOSCommandMode } from "@familiaros/claude";
|
||||
|
||||
import {
|
||||
safeInstallClaudeMemory,
|
||||
safeUninstallClaudeMemory,
|
||||
summarizeMemoryMessages,
|
||||
writeActionJournal,
|
||||
type AgentSetupJournalEntry,
|
||||
type JournalAction,
|
||||
} from "./agent-setup-support.js";
|
||||
import { getPreferredClaudeCommand } from "./agent-setup-command-context.js";
|
||||
import type { AgentSetupCommandResult } from "./agent-setup-command-runner.js";
|
||||
import type {
|
||||
AgentSetupAction,
|
||||
AgentSetupActionResult,
|
||||
ClaudeCodeStatus,
|
||||
} from "./agent-setup.js";
|
||||
|
||||
type CommandResult = AgentSetupCommandResult;
|
||||
|
||||
type AgentSetupClaudeMcpActionHelpers = {
|
||||
readonly selectedPetId: string | undefined;
|
||||
readonly commandMode: FamiliarOSCommandMode;
|
||||
readonly detectClaudeCodeStatus: (selectedPetId: string | undefined, commandMode: FamiliarOSCommandMode) => Promise<ClaudeCodeStatus>;
|
||||
readonly formatUserPath: (path: string | undefined) => string | undefined;
|
||||
readonly sanitizeOutput: (value: string) => string;
|
||||
readonly summarizeCommandResult: (result: CommandResult) => string;
|
||||
readonly runClaudeCommand: (spec: ClaudeCommandSpec) => Promise<CommandResult>;
|
||||
readonly appendAgentSetupJournal: (entry: Omit<AgentSetupJournalEntry, "timestamp"> & { readonly timestamp?: string }) => void;
|
||||
readonly journalActionFor: (action: AgentSetupAction) => JournalAction;
|
||||
};
|
||||
|
||||
export async function runRemoveOnlyClaudeMcpAction(
|
||||
action: AgentSetupAction,
|
||||
commandMode: FamiliarOSCommandMode,
|
||||
helpers: AgentSetupClaudeMcpActionHelpers,
|
||||
): Promise<AgentSetupActionResult> {
|
||||
return runRemove(createRemoveOnlyPreview(commandMode), "Unknown", action, helpers);
|
||||
}
|
||||
|
||||
export async function runClaudeMcpAction(
|
||||
action: AgentSetupAction,
|
||||
preview: ClaudeMcpPreview,
|
||||
helpers: AgentSetupClaudeMcpActionHelpers,
|
||||
): Promise<AgentSetupActionResult> {
|
||||
const detection = await helpers.detectClaudeCodeStatus(helpers.selectedPetId, helpers.commandMode);
|
||||
const previousStatus = detection.label;
|
||||
if (detection.state === "not_detected") {
|
||||
const result = {
|
||||
ok: false,
|
||||
action,
|
||||
message: "Claude Code was not found. Install Claude Code or use Copy command to configure manually.",
|
||||
changed: false,
|
||||
} satisfies AgentSetupActionResult;
|
||||
helpers.appendAgentSetupJournal({
|
||||
action: helpers.journalActionFor(action),
|
||||
selectedPetId: helpers.selectedPetId,
|
||||
command: [preview.add.command, ...preview.add.args],
|
||||
previousStatus,
|
||||
success: false,
|
||||
message: result.message,
|
||||
});
|
||||
return result;
|
||||
}
|
||||
if (action === "configure") {
|
||||
return runConfigureClaudeMcpAction(detection, preview, previousStatus, helpers);
|
||||
}
|
||||
if (!detection.openPetsEntry.present) {
|
||||
return runAdd(preview, previousStatus, action, helpers);
|
||||
}
|
||||
const removed = await runRemove(preview, previousStatus, action, helpers);
|
||||
if (!removed.ok) return removed;
|
||||
const added = await runAdd(preview, previousStatus, action, helpers);
|
||||
if (!added.ok) {
|
||||
return {
|
||||
ok: false,
|
||||
action,
|
||||
message: `${added.message} The previous familiaros entry was removed; use this command to restore the intended entry: ${preview.displayCommand}`,
|
||||
changed: true,
|
||||
};
|
||||
}
|
||||
return {
|
||||
ok: true,
|
||||
action,
|
||||
message: `Replaced Claude Code FamiliarOS MCP entry.${summarizeMemoryMessages(removed.message, added.message)}`,
|
||||
changed: true,
|
||||
};
|
||||
}
|
||||
|
||||
function runConfigureClaudeMcpAction(
|
||||
detection: ClaudeCodeStatus,
|
||||
preview: ClaudeMcpPreview,
|
||||
previousStatus: string,
|
||||
helpers: AgentSetupClaudeMcpActionHelpers,
|
||||
): Promise<AgentSetupActionResult> | AgentSetupActionResult {
|
||||
if (detection.openPetsEntry.present && detection.openPetsEntry.verified && detection.openPetsEntry.matchesExpected) {
|
||||
const memoryResult = safeInstallClaudeMemory(app.getPath("home"));
|
||||
const message = `FamiliarOS MCP is already configured for Claude Code.${memoryResult.ok ? ` ${memoryResult.message}` : ` Claude instructions were not updated: ${memoryResult.message}`}`;
|
||||
return {
|
||||
ok: true,
|
||||
action: "configure",
|
||||
message,
|
||||
changed: memoryResult.ok && memoryResult.message.startsWith("Added"),
|
||||
};
|
||||
}
|
||||
if (detection.openPetsEntry.present) {
|
||||
return {
|
||||
ok: false,
|
||||
action: "configure",
|
||||
message: "Claude already has an familiaros MCP entry. FamiliarOS will keep it as installed; use Replace only if you want to recreate it with the recommended command.",
|
||||
changed: false,
|
||||
};
|
||||
}
|
||||
return runAdd(preview, previousStatus, "configure", helpers);
|
||||
}
|
||||
|
||||
async function runAdd(
|
||||
preview: ClaudeMcpPreview,
|
||||
previousStatus: string,
|
||||
action: AgentSetupAction,
|
||||
helpers: AgentSetupClaudeMcpActionHelpers,
|
||||
): Promise<AgentSetupActionResult> {
|
||||
const result = await helpers.runClaudeCommand(preview.add);
|
||||
const memoryResult = result.ok ? safeInstallClaudeMemory(app.getPath("home")) : { ok: false as const, message: "" };
|
||||
const message = result.ok
|
||||
? `Configured Claude Code FamiliarOS MCP entry.${memoryResult.ok ? ` ${memoryResult.message}` : ` Claude instructions were not updated: ${memoryResult.message}`}`
|
||||
: `Claude MCP add failed: ${helpers.summarizeCommandResult(result)}`;
|
||||
writeActionJournal({
|
||||
entry: {
|
||||
action: helpers.journalActionFor(action),
|
||||
selectedPetId: helpers.selectedPetId,
|
||||
command: [preview.add.command, ...preview.add.args],
|
||||
previousStatus,
|
||||
success: result.ok,
|
||||
message,
|
||||
},
|
||||
userDataPath: app.getPath("userData"),
|
||||
formatUserPath: helpers.formatUserPath,
|
||||
sanitizeOutput: helpers.sanitizeOutput,
|
||||
});
|
||||
return { ok: result.ok, action, message, changed: result.ok };
|
||||
}
|
||||
|
||||
async function runRemove(
|
||||
preview: ClaudeMcpPreview,
|
||||
previousStatus: string,
|
||||
action: AgentSetupAction,
|
||||
helpers: AgentSetupClaudeMcpActionHelpers,
|
||||
): Promise<AgentSetupActionResult> {
|
||||
const result = await helpers.runClaudeCommand(preview.remove);
|
||||
const memoryResult = result.ok ? safeUninstallClaudeMemory(app.getPath("home")) : { ok: false as const, message: "" };
|
||||
const message = result.ok
|
||||
? `Removed Claude Code FamiliarOS MCP entry.${memoryResult.ok ? ` ${memoryResult.message}` : ` Claude instructions were not updated: ${memoryResult.message}`}`
|
||||
: `Claude MCP remove failed: ${helpers.summarizeCommandResult(result)}`;
|
||||
writeActionJournal({
|
||||
entry: {
|
||||
action: helpers.journalActionFor(action),
|
||||
selectedPetId: helpers.selectedPetId,
|
||||
command: [preview.remove.command, ...preview.remove.args],
|
||||
previousStatus,
|
||||
success: result.ok,
|
||||
message,
|
||||
},
|
||||
userDataPath: app.getPath("userData"),
|
||||
formatUserPath: helpers.formatUserPath,
|
||||
sanitizeOutput: helpers.sanitizeOutput,
|
||||
});
|
||||
return { ok: result.ok, action, message, changed: result.ok };
|
||||
}
|
||||
|
||||
function createRemoveOnlyPreview(commandMode: FamiliarOSCommandMode): ClaudeMcpPreview {
|
||||
const claude = getPreferredClaudeCommand();
|
||||
return {
|
||||
commandMode,
|
||||
add: { command: claude, args: [] },
|
||||
remove: { command: claude, args: ["mcp", "remove", "--scope", "user", "familiaros"] },
|
||||
mcpJson: { mcpServers: { familiaros: { type: "stdio", command: "node", args: [] } } },
|
||||
displayCommand: "",
|
||||
};
|
||||
}
|
||||
|
|
@ -20,17 +20,17 @@ export {
|
|||
getOpenCodeSetup,
|
||||
runAgentSetupMcpServerHealthCheck,
|
||||
} from "./agent-setup-actions-tooling.js";
|
||||
import {
|
||||
runClaudeMcpAction,
|
||||
runRemoveOnlyClaudeMcpAction,
|
||||
} from "./agent-setup-actions-claude-mcp.js";
|
||||
import {
|
||||
createHookJournalCommand,
|
||||
safeInstallClaudeMemory,
|
||||
safeUninstallClaudeMemory,
|
||||
summarizeMemoryMessages,
|
||||
writeActionJournal,
|
||||
type AgentSetupJournalEntry,
|
||||
type JournalAction,
|
||||
} from "./agent-setup-support.js";
|
||||
import {
|
||||
getPreferredClaudeCommand,
|
||||
getPreferredNodeCommand,
|
||||
} from "./agent-setup-command-context.js";
|
||||
import type { AgentSetupCommandResult } from "./agent-setup-command-runner.js";
|
||||
|
|
@ -114,9 +114,7 @@ async function runImmediateAction(
|
|||
changed: result.ok && result.message.startsWith("Added"),
|
||||
};
|
||||
}
|
||||
if (action === "remove") {
|
||||
return runRemove(createRemoveOnlyPreview(helpers.commandMode), "Unknown", action, helpers);
|
||||
}
|
||||
if (action === "remove") return runRemoveOnlyClaudeMcpAction(action, helpers.commandMode, helpers);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
|
|
@ -180,144 +178,3 @@ function runInstallHooksAction(
|
|||
});
|
||||
return { ok: result.status !== "error", action, message, changed: result.changed };
|
||||
}
|
||||
|
||||
async function runClaudeMcpAction(
|
||||
action: AgentSetupAction,
|
||||
preview: ClaudeMcpPreview,
|
||||
helpers: AgentSetupActionHelpers,
|
||||
): Promise<AgentSetupActionResult> {
|
||||
const detection = await helpers.detectClaudeCodeStatus(helpers.selectedPetId, helpers.commandMode);
|
||||
const previousStatus = detection.label;
|
||||
if (detection.state === "not_detected") {
|
||||
const result = {
|
||||
ok: false,
|
||||
action,
|
||||
message: "Claude Code was not found. Install Claude Code or use Copy command to configure manually.",
|
||||
changed: false,
|
||||
} satisfies AgentSetupActionResult;
|
||||
helpers.appendAgentSetupJournal({
|
||||
action: helpers.journalActionFor(action),
|
||||
selectedPetId: helpers.selectedPetId,
|
||||
command: [preview.add.command, ...preview.add.args],
|
||||
previousStatus,
|
||||
success: false,
|
||||
message: result.message,
|
||||
});
|
||||
return result;
|
||||
}
|
||||
if (action === "configure") {
|
||||
return runConfigureClaudeMcpAction(detection, preview, previousStatus, helpers);
|
||||
}
|
||||
if (!detection.openPetsEntry.present) {
|
||||
return runAdd(preview, previousStatus, action, helpers);
|
||||
}
|
||||
const removed = await runRemove(preview, previousStatus, action, helpers);
|
||||
if (!removed.ok) return removed;
|
||||
const added = await runAdd(preview, previousStatus, action, helpers);
|
||||
if (!added.ok) {
|
||||
return {
|
||||
ok: false,
|
||||
action,
|
||||
message: `${added.message} The previous familiaros entry was removed; use this command to restore the intended entry: ${preview.displayCommand}`,
|
||||
changed: true,
|
||||
};
|
||||
}
|
||||
return {
|
||||
ok: true,
|
||||
action,
|
||||
message: `Replaced Claude Code FamiliarOS MCP entry.${summarizeMemoryMessages(removed.message, added.message)}`,
|
||||
changed: true,
|
||||
};
|
||||
}
|
||||
|
||||
function runConfigureClaudeMcpAction(
|
||||
detection: ClaudeCodeStatus,
|
||||
preview: ClaudeMcpPreview,
|
||||
previousStatus: string,
|
||||
helpers: AgentSetupActionHelpers,
|
||||
): Promise<AgentSetupActionResult> | AgentSetupActionResult {
|
||||
if (detection.openPetsEntry.present && detection.openPetsEntry.verified && detection.openPetsEntry.matchesExpected) {
|
||||
const memoryResult = safeInstallClaudeMemory(app.getPath("home"));
|
||||
const message = `FamiliarOS MCP is already configured for Claude Code.${memoryResult.ok ? ` ${memoryResult.message}` : ` Claude instructions were not updated: ${memoryResult.message}`}`;
|
||||
return {
|
||||
ok: true,
|
||||
action: "configure",
|
||||
message,
|
||||
changed: memoryResult.ok && memoryResult.message.startsWith("Added"),
|
||||
};
|
||||
}
|
||||
if (detection.openPetsEntry.present) {
|
||||
return {
|
||||
ok: false,
|
||||
action: "configure",
|
||||
message: "Claude already has an familiaros MCP entry. FamiliarOS will keep it as installed; use Replace only if you want to recreate it with the recommended command.",
|
||||
changed: false,
|
||||
};
|
||||
}
|
||||
return runAdd(preview, previousStatus, "configure", helpers);
|
||||
}
|
||||
|
||||
async function runAdd(
|
||||
preview: ClaudeMcpPreview,
|
||||
previousStatus: string,
|
||||
action: AgentSetupAction,
|
||||
helpers: AgentSetupActionHelpers,
|
||||
): Promise<AgentSetupActionResult> {
|
||||
const result = await helpers.runClaudeCommand(preview.add);
|
||||
const memoryResult = result.ok ? safeInstallClaudeMemory(app.getPath("home")) : { ok: false as const, message: "" };
|
||||
const message = result.ok
|
||||
? `Configured Claude Code FamiliarOS MCP entry.${memoryResult.ok ? ` ${memoryResult.message}` : ` Claude instructions were not updated: ${memoryResult.message}`}`
|
||||
: `Claude MCP add failed: ${helpers.summarizeCommandResult(result)}`;
|
||||
writeActionJournal({
|
||||
entry: {
|
||||
action: helpers.journalActionFor(action),
|
||||
selectedPetId: helpers.selectedPetId,
|
||||
command: [preview.add.command, ...preview.add.args],
|
||||
previousStatus,
|
||||
success: result.ok,
|
||||
message,
|
||||
},
|
||||
userDataPath: app.getPath("userData"),
|
||||
formatUserPath: helpers.formatUserPath,
|
||||
sanitizeOutput: helpers.sanitizeOutput,
|
||||
});
|
||||
return { ok: result.ok, action, message, changed: result.ok };
|
||||
}
|
||||
|
||||
async function runRemove(
|
||||
preview: ClaudeMcpPreview,
|
||||
previousStatus: string,
|
||||
action: AgentSetupAction,
|
||||
helpers: AgentSetupActionHelpers,
|
||||
): Promise<AgentSetupActionResult> {
|
||||
const result = await helpers.runClaudeCommand(preview.remove);
|
||||
const memoryResult = result.ok ? safeUninstallClaudeMemory(app.getPath("home")) : { ok: false as const, message: "" };
|
||||
const message = result.ok
|
||||
? `Removed Claude Code FamiliarOS MCP entry.${memoryResult.ok ? ` ${memoryResult.message}` : ` Claude instructions were not updated: ${memoryResult.message}`}`
|
||||
: `Claude MCP remove failed: ${helpers.summarizeCommandResult(result)}`;
|
||||
writeActionJournal({
|
||||
entry: {
|
||||
action: helpers.journalActionFor(action),
|
||||
selectedPetId: helpers.selectedPetId,
|
||||
command: [preview.remove.command, ...preview.remove.args],
|
||||
previousStatus,
|
||||
success: result.ok,
|
||||
message,
|
||||
},
|
||||
userDataPath: app.getPath("userData"),
|
||||
formatUserPath: helpers.formatUserPath,
|
||||
sanitizeOutput: helpers.sanitizeOutput,
|
||||
});
|
||||
return { ok: result.ok, action, message, changed: result.ok };
|
||||
}
|
||||
|
||||
function createRemoveOnlyPreview(commandMode: FamiliarOSCommandMode): ClaudeMcpPreview {
|
||||
const claude = getPreferredClaudeCommand();
|
||||
return {
|
||||
commandMode,
|
||||
add: { command: claude, args: [] },
|
||||
remove: { command: claude, args: ["mcp", "remove", "--scope", "user", "familiaros"] },
|
||||
mcpJson: { mcpServers: { familiaros: { type: "stdio", command: "node", args: [] } } },
|
||||
displayCommand: "",
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -199,6 +199,7 @@ const appStateStorageSource = readFileSync(join(appDir, "src", "app-state-storag
|
|||
const agentSetupSource = readFileSync(join(appDir, "src", "agent-setup.ts"), "utf8");
|
||||
const agentSetupClaudeStatusSource = readFileSync(join(appDir, "src", "agent-setup-claude-status.ts"), "utf8");
|
||||
const agentSetupActionsSource = readFileSync(join(appDir, "src", "agent-setup-actions.ts"), "utf8");
|
||||
const agentSetupActionsClaudeMcpSource = readFileSync(join(appDir, "src", "agent-setup-actions-claude-mcp.ts"), "utf8");
|
||||
const agentSetupActionsToolingSource = readFileSync(join(appDir, "src", "agent-setup-actions-tooling.ts"), "utf8");
|
||||
const agentSetupCommandRunnerSource = readFileSync(join(appDir, "src", "agent-setup-command-runner.ts"), "utf8");
|
||||
const agentSetupCommandContextSource = readFileSync(join(appDir, "src", "agent-setup-command-context.ts"), "utf8");
|
||||
|
|
@ -580,6 +581,9 @@ assert.match(agentSetupCommandRunnerSource, /export function createAgentSetupCom
|
|||
assert.match(agentSetupCommandRunnerSource, /export function summarizeAgentSetupCommandResult/, "agent-setup command-runner seam must export command result summarization.");
|
||||
assert.match(agentSetupActionsSource, /export async function executeAgentSetupResolvedAction/, "agent-setup action seam must export action execution.");
|
||||
assert.match(agentSetupActionsSource, /from "\.\/agent-setup-actions-tooling(?:\.js)?"/, "agent-setup action seam must import the extracted tooling seam.");
|
||||
assert.match(agentSetupActionsSource, /from "\.\/agent-setup-actions-claude-mcp(?:\.js)?"/, "agent-setup action seam must import the extracted Claude MCP action seam.");
|
||||
assert.match(agentSetupActionsClaudeMcpSource, /export async function runClaudeMcpAction/, "agent-setup Claude MCP seam must export add/configure/replace orchestration.");
|
||||
assert.match(agentSetupActionsClaudeMcpSource, /export async function runRemoveOnlyClaudeMcpAction/, "agent-setup Claude MCP seam must export the remove-only orchestration.");
|
||||
assert.match(agentSetupClaudeStatusSource, /export function sanitizeAgentSetupOutput/, "agent-setup Claude status seam must export output sanitization.");
|
||||
assert.match(agentSetupClaudeStatusSource, /export function safeBuildClaudeMcpPreview/, "agent-setup Claude status seam must export preview shaping.");
|
||||
assert.match(agentSetupClaudeStatusSource, /export function safeDoctorClaudeHooks/, "agent-setup Claude status seam must export hook doctor wrappers.");
|
||||
|
|
@ -850,7 +854,7 @@ assert.match(agentSetupActionsToolingSource, /from "\.\/agent-setup-editor-tools
|
|||
assert.match(agentSetupSource, /agent-setup-support\.js/, "Agent setup must import and re-export the extracted support helper seam.");
|
||||
assert.match(agentSetupActionsToolingSource, /getCliPackageVersion/, "Agent setup tooling seam must compose package version metadata through the command context helper.");
|
||||
assert.match(agentSetupActionsToolingSource, /buildOpenCodeSetupSnapshot/, "Agent setup tooling seam must delegate OpenCode previews through the editor setup helper.");
|
||||
assert.match(agentSetupActionsSource, /writeActionJournal/, "Agent setup action seam must delegate journal writes through the support helper.");
|
||||
assert.match(agentSetupActionsClaudeMcpSource, /writeActionJournal/, "Agent setup Claude MCP seam must delegate journal writes through the support helper.");
|
||||
assert.match(petWindowRenderSource, /from "\.\/familiar-window-render-bubbles(?:\.js)?"/, "familiar-window-render must compose the extracted bubble helper seam.");
|
||||
assert.match(petWindowRenderBubblesSource, /export function createBubbleMarkup/, "familiar-window render bubble seam must export the shared bubble markup builder.");
|
||||
assert.match(petWindowRenderBubblesSource, /export function getBubbleClassName/, "familiar-window render bubble seam must export bubble length classification.");
|
||||
|
|
|
|||
|
|
@ -74,7 +74,8 @@ windows.ts (IPC handlers)
|
|||
│ ├── Claude MCP preview/status detection and packaged-resource fallback shaping
|
||||
│ └── Claude/OpenCode command wrappers, output sanitization, and user-path formatting
|
||||
├── agent-setup-actions.ts
|
||||
│ ├── runAgentSetupResolvedAction() (configure/replace/remove, install-memory, hook actions)
|
||||
│ ├── runAgentSetupResolvedAction() shell and immediate action routing
|
||||
│ ├── agent-setup-actions-claude-mcp.ts (Claude MCP add/remove/configure/replace orchestration)
|
||||
│ └── agent-setup-actions-tooling.ts (OpenCode/Cursor setup snapshots, global config actions, and FamiliarOS MCP server health)
|
||||
├── agent-setup-command-context.ts
|
||||
│ ├── persisted command path preferences
|
||||
|
|
@ -218,6 +219,7 @@ plugin-service-local-support.ts → plugin-local-loader.ts validates selected fo
|
|||
- `control-center-ipc-pets.ts`: Familiar/catalog/Codex import and default familiar IPC routes for the Control Center
|
||||
- `control-center-ipc-agent.ts`: Agent setup, toolkit, and FamiliarOS MCP preview/test IPC routes for the Control Center
|
||||
- `agent-setup-actions.ts`: Extracted action execution shell for hook handling plus Claude MCP add/remove orchestration
|
||||
- `agent-setup-actions-claude-mcp.ts`: Extracted Claude MCP add/remove/configure/replace orchestration plus memory-aware journaling
|
||||
- `agent-setup-actions-tooling.ts`: Extracted OpenCode/Cursor setup loading, global config actions, and FamiliarOS MCP server health checks
|
||||
- `agent-setup-editor-tools-opencode.ts`: Extracted OpenCode global setup status, previews, and config write helpers
|
||||
- `agent-setup-editor-tools-cursor.ts`: Extracted Cursor global setup status, previews, and MCP config write helpers
|
||||
|
|
@ -350,7 +352,8 @@ plugin-service-local-support.ts → plugin-local-loader.ts validates selected fo
|
|||
|
||||
**Agent Integration**:
|
||||
- `agent-setup.ts`: Agent-setup public entry points, snapshot assembly, selected-pet validation, and action journal coordination
|
||||
- `agent-setup-actions.ts`: Extracted action execution shell plus Claude MCP add/remove orchestration
|
||||
- `agent-setup-actions.ts`: Extracted action execution shell plus immediate editor, hook, and memory action routing
|
||||
- `agent-setup-actions-claude-mcp.ts`: Extracted Claude MCP add/remove/configure/replace orchestration plus memory-aware journaling
|
||||
- `agent-setup-actions-tooling.ts`: Extracted editor setup loading, global config actions, and FamiliarOS MCP server health checks
|
||||
- `agent-setup-claude-status.ts`: Extracted Claude MCP preview/status detection, command wrappers, output sanitization, and packaged-resource error shaping
|
||||
- `agent-setup-command-context.ts`: Agent setup command path persistence, preferred command resolution, and workspace package metadata helpers
|
||||
|
|
|
|||
|
|
@ -6,15 +6,19 @@ import { fileURLToPath } from "node:url";
|
|||
const desktopRoot = process.env.FAMILIAROS_DESKTOP_ROOT ?? resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
||||
const agentSetupSource = readFileSync(resolve(desktopRoot, "src/agent-setup.ts"), "utf8");
|
||||
const agentSetupActionsSource = readFileSync(resolve(desktopRoot, "src/agent-setup-actions.ts"), "utf8");
|
||||
const agentSetupActionsClaudeMcpSource = readFileSync(resolve(desktopRoot, "src/agent-setup-actions-claude-mcp.ts"), "utf8");
|
||||
const agentSetupActionsToolingSource = readFileSync(resolve(desktopRoot, "src/agent-setup-actions-tooling.ts"), "utf8");
|
||||
|
||||
assert.match(agentSetupSource, /from "\.\/agent-setup-actions\.js"/, "Agent setup must import the extracted action seam.");
|
||||
assert.match(agentSetupActionsSource, /export async function executeAgentSetupResolvedAction/, "Agent setup action seam must export the action executor.");
|
||||
assert.match(agentSetupActionsSource, /from "\.\/agent-setup-actions-tooling(?:\.js)?"/, "Agent setup action seam must compose the extracted tooling seam.");
|
||||
assert.match(agentSetupActionsSource, /from "\.\/agent-setup-actions-claude-mcp(?:\.js)?"/, "Agent setup action seam must compose the extracted Claude MCP action seam.");
|
||||
assert.match(agentSetupActionsToolingSource, /export async function getOpenCodeSetup/, "Agent setup tooling seam must export OpenCode setup loading.");
|
||||
assert.match(agentSetupActionsToolingSource, /export async function getCursorSetup/, "Agent setup tooling seam must export Cursor setup loading.");
|
||||
assert.match(agentSetupActionsToolingSource, /export async function runAgentSetupMcpServerHealthCheck/, "Agent setup tooling seam must export MCP server health checks.");
|
||||
assert.match(agentSetupActionsSource, /from "\.\/agent-setup-support\.js"/, "Agent setup action seam must compose the extracted support helper seam.");
|
||||
assert.match(agentSetupActionsSource, /from "\.\/agent-setup-command-context\.js"/, "Agent setup action seam must compose the extracted command context seam.");
|
||||
assert.match(agentSetupActionsClaudeMcpSource, /export async function runClaudeMcpAction/, "Agent setup Claude MCP seam must export Claude MCP action orchestration.");
|
||||
assert.match(agentSetupActionsClaudeMcpSource, /export async function runRemoveOnlyClaudeMcpAction/, "Agent setup Claude MCP seam must export the remove-only action helper.");
|
||||
|
||||
console.error("Agent setup action seam validation passed.");
|
||||
|
|
|
|||
|
|
@ -6,12 +6,14 @@ import { fileURLToPath } from "node:url";
|
|||
const desktopRoot = process.env.FAMILIAROS_DESKTOP_ROOT ?? resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
||||
const agentSetupSource = readFileSync(resolve(desktopRoot, "src/agent-setup.ts"), "utf8");
|
||||
const agentSetupActionsSource = readFileSync(resolve(desktopRoot, "src/agent-setup-actions.ts"), "utf8");
|
||||
const agentSetupActionsClaudeMcpSource = readFileSync(resolve(desktopRoot, "src/agent-setup-actions-claude-mcp.ts"), "utf8");
|
||||
const agentSetupActionsToolingSource = readFileSync(resolve(desktopRoot, "src/agent-setup-actions-tooling.ts"), "utf8");
|
||||
const agentSetupSupportSource = readFileSync(resolve(desktopRoot, "src/agent-setup-support.ts"), "utf8");
|
||||
|
||||
assert.match(agentSetupSource, /from "\.\/agent-setup-support\.js"/, "Agent setup must import the extracted support helper seam.");
|
||||
assert.match(agentSetupActionsSource, /safeInstallClaudeMemory\(app\.getPath\("home"\)\)/, "Agent setup action seam must delegate Claude memory installs through the extracted support helper.");
|
||||
assert.match(agentSetupActionsSource, /writeActionJournal\(\{\s*entry:/, "Agent setup action seam must delegate action journaling through the extracted support helper.");
|
||||
assert.match(agentSetupActionsSource, /from "\.\/agent-setup-actions-claude-mcp(?:\.js)?"/, "Agent setup action shell must compose the extracted Claude MCP helper seam.");
|
||||
assert.match(agentSetupActionsSource, /safeInstallClaudeMemory\(app\.getPath\("home"\)\)/, "Agent setup action shell must keep memory installs routed through the support helper.");
|
||||
assert.match(agentSetupActionsClaudeMcpSource, /writeActionJournal\(\{\s*entry:/, "Agent setup Claude MCP seam must delegate action journaling through the extracted support helper.");
|
||||
assert.match(agentSetupActionsToolingSource, /buildFamiliarOSMcpServerPreview/, "Agent setup tooling seam must delegate MCP server preview shaping through the extracted support helper.");
|
||||
|
||||
assert.match(agentSetupSupportSource, /export function buildFamiliarOSMcpServerPreview/, "Agent setup support helper must own FamiliarOS MCP preview shaping.");
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue