@agimon-ai/doompi-mcp 0.0.1-alpha.89 → 0.0.1-alpha.90
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/extensions/pi.cjs +10 -6
- package/dist/extensions/pi.cjs.map +1 -1
- package/dist/extensions/pi.mjs +8 -5
- package/dist/extensions/pi.mjs.map +1 -1
- package/dist/extensions/server.cjs +57 -14
- package/dist/extensions/server.cjs.map +1 -1
- package/dist/extensions/server.mjs +52 -10
- package/dist/extensions/server.mjs.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/{keyringTokenStore-BwvTXKvD.cjs → keyringTokenStore-LBsDb_eC.cjs} +3 -3
- package/dist/{keyringTokenStore-BwvTXKvD.cjs.map → keyringTokenStore-LBsDb_eC.cjs.map} +1 -1
- package/dist/{mcpCatalog-nbZdP5rF.cjs → mcpCatalog-Bnkul3t_.cjs} +10 -49
- package/dist/mcpCatalog-Bnkul3t_.cjs.map +1 -0
- package/dist/{mcpCatalog-zoD27CZd.mjs → mcpCatalog-laXfwecc.mjs} +4 -1
- package/dist/mcpCatalog-laXfwecc.mjs.map +1 -0
- package/dist/{mcpCommand-btmh62JV.cjs → mcpCommand-BARs6Y1N.cjs} +14 -5
- package/dist/mcpCommand-BARs6Y1N.cjs.map +1 -0
- package/dist/{mcpCommand-CIkm3j9w.mjs → mcpCommand-BaJXXphd.mjs} +14 -5
- package/dist/mcpCommand-BaJXXphd.mjs.map +1 -0
- package/dist/projection-gyAA2jRB.mjs +43 -0
- package/dist/projection-gyAA2jRB.mjs.map +1 -0
- package/dist/projection-w3XxXmVi.cjs +51 -0
- package/dist/projection-w3XxXmVi.cjs.map +1 -0
- package/dist/projection.cjs +1 -1
- package/dist/projection.d.mts +3 -5
- package/dist/projection.d.mts.map +1 -1
- package/dist/projection.mjs +1 -1
- package/dist/rolldown-runtime-C0BPl7ul.cjs +43 -0
- package/package.json +8 -8
- package/dist/mcpCatalog-nbZdP5rF.cjs.map +0 -1
- package/dist/mcpCatalog-zoD27CZd.mjs.map +0 -1
- package/dist/mcpCommand-CIkm3j9w.mjs.map +0 -1
- package/dist/mcpCommand-btmh62JV.cjs.map +0 -1
- package/dist/projection-BJEX-pTt.mjs +0 -24
- package/dist/projection-BJEX-pTt.mjs.map +0 -1
- package/dist/projection-ZDNTQ3iE.cjs +0 -29
- package/dist/projection-ZDNTQ3iE.cjs.map +0 -1
package/dist/extensions/pi.cjs
CHANGED
|
@@ -2,11 +2,12 @@ Object.defineProperties(exports, {
|
|
|
2
2
|
__esModule: { value: true },
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
const
|
|
5
|
+
const require_rolldown_runtime = require("../rolldown-runtime-C0BPl7ul.cjs");
|
|
6
|
+
const require_mcpCatalog = require("../mcpCatalog-Bnkul3t_.cjs");
|
|
7
|
+
const require_projection = require("../projection-w3XxXmVi.cjs");
|
|
8
|
+
const require_mcpCommand = require("../mcpCommand-BARs6Y1N.cjs");
|
|
8
9
|
let node_path = require("node:path");
|
|
9
|
-
node_path =
|
|
10
|
+
node_path = require_rolldown_runtime.__toESM(node_path, 1);
|
|
10
11
|
let _agimon_ai_doompi_core_mcpProjection = require("@agimon-ai/doompi-core/mcpProjection");
|
|
11
12
|
let _agimon_ai_doompi_core_piExtension = require("@agimon-ai/doompi-core/piExtension");
|
|
12
13
|
let _agimon_ai_doompi_core_extensionFile = require("@agimon-ai/doompi-core/extensionFile");
|
|
@@ -83,7 +84,7 @@ function createMcpPiRuntime(runtime) {
|
|
|
83
84
|
};
|
|
84
85
|
const stopPublishing = session.onChange(publishServerStatus);
|
|
85
86
|
publishServerStatus();
|
|
86
|
-
if (mode === "standalone") await session.reconfigure(require_mcpCatalog.readSessionConfig(process.env, context.cwd));
|
|
87
|
+
if (mode === "standalone") await session.reconfigure(require_mcpCatalog.readSessionConfig(process.env, context.cwd), context.cwd);
|
|
87
88
|
else {
|
|
88
89
|
await session.reconfigure(failClosedSessionConfig(context.cwd));
|
|
89
90
|
sessionContext.inject([_agimon_ai_doompi_core_mcpProjection.DOOM_MCP_PROJECTION_SERVICE], async (projectionContext) => {
|
|
@@ -91,7 +92,10 @@ function createMcpPiRuntime(runtime) {
|
|
|
91
92
|
if (!projection || projection.sessionId !== expectedSessionId) {
|
|
92
93
|
await session.reconfigure(failClosedSessionConfig(context.cwd));
|
|
93
94
|
if (projection && sessionActive && !disposed) context.ui?.notify(`The Doom MCP projection belongs to session "${projection.sessionId}", not "${expectedSessionId}"; MCP is disabled.`, WARNING);
|
|
94
|
-
} else
|
|
95
|
+
} else {
|
|
96
|
+
const snapshot = projection.getSnapshot();
|
|
97
|
+
await session.reconfigure(require_projection.mcpSessionConfigFromProjection(snapshot, context.cwd), context.cwd, snapshot.repoRoot);
|
|
98
|
+
}
|
|
95
99
|
return async () => {
|
|
96
100
|
if (sessionActive && !disposed) await session.reconfigure(failClosedSessionConfig(context.cwd));
|
|
97
101
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pi.cjs","names":["PACKAGE_SOURCE","LEADER_BINDING_PREFIX","LEADER_GROUP","LEADER_DETAIL","path","McpSession","DOOM_UI_HUB_SERVICE","requireDoomUiHub","DOOM_TOOL_SURFACE_SERVICE","requireDoomToolSurface","DOOM_CORDIS_SESSION_SERVICE","MCP_STATUS_KEY","MCP_SESSION_AUTH_STATUS_KEY","formatMcpSessionAuthStatus","readSessionConfig","DOOM_MCP_PROJECTION_SERVICE","readDoomMcpProjectionService","mcpSessionConfigFromProjection","createMcpSessionToolsService","createMcpChildTool","DOOM_MCP_STATUS_SERVICE","DOOM_MCP_TOOL_RESOLVER_SERVICE","MCP_SESSION_TOOLS_SERVICE","DOOM_CHILD_SESSION_MCP_TOOL_SERVICE","defineRoot","defineRoutedContribution","createMcpCommand","defineResource","createMcpTool","wrapTextWithAnsi","truncateToWidth","renderToolHeading","DoomToolCall","defineRoutedContribution","definePiExtension","rootSession","composeRootHooks","commandMcp","resourceDoompiUseMcp","piToolContributions","toolMcp"],"sources":["../../src/services/leader/index.ts","../../src/services/piRuntime/index.ts","../../src/extensions/workspaces/sessions/(backend)/_lib/piRoot.ts","../../src/extensions/workspaces/sessions/(backend)/root.cli.ts","../../src/extensions/workspaces/sessions/(backend)/command/mcp.cli.ts","../../src/extensions/workspaces/sessions/(backend)/resource/doompi-use-mcp.cli.ts","../../src/services/mcpToolCollection/index.ts","../../src/tui/mcpToolRender.ts","../../src/extensions/workspaces/sessions/(backend)/tool/mcp.cli.ts","../../generated/pi.ts"],"sourcesContent":["import type { DoomUiHubService } from '@agimon-ai/doompi-core/uiHub';\n\nimport { COMMAND_NAME } from '../../constants/mcp';\nimport {\n LEADER_BINDING_PREFIX,\n LEADER_DETAIL,\n LEADER_GROUP,\n LEADER_KEY,\n LEADER_LABEL,\n PACKAGE_SOURCE,\n} from '../../constants/piMcp';\n\nexport function registerLeaderContribution(hub: DoomUiHubService): () => void {\n const contribution = hub.registerLeader({\n source: PACKAGE_SOURCE,\n bindings: [\n {\n id: `${LEADER_BINDING_PREFIX}.open`,\n path: [LEADER_GROUP, { key: LEADER_KEY, label: LEADER_LABEL, detail: LEADER_DETAIL }],\n command: { name: COMMAND_NAME },\n },\n ],\n });\n return () => contribution.dispose();\n}\n","import path from 'node:path';\n\nimport { DOOM_CHILD_SESSION_MCP_TOOL_SERVICE } from '@agimon-ai/doompi-core/childSession';\nimport type { DoomCordisRuntimeService } from '@agimon-ai/doompi-core/cordisHost';\nimport { DOOM_CORDIS_SESSION_SERVICE, type DoomCordisSessionService } from '@agimon-ai/doompi-core/cordisHost';\nimport { DOOM_MCP_PROJECTION_SERVICE, readDoomMcpProjectionService } from '@agimon-ai/doompi-core/mcpProjection';\nimport { DOOM_MCP_STATUS_SERVICE, type DoomMcpStatusService } from '@agimon-ai/doompi-core/mcpStatus';\nimport {\n DOOM_MCP_TOOL_RESOLVER_SERVICE,\n type DoomMcpToolResolverService,\n} from '@agimon-ai/doompi-core/mcpToolResolver';\nimport { DOOM_TOOL_SURFACE_SERVICE, requireDoomToolSurface } from '@agimon-ai/doompi-core/toolSurface';\nimport { DOOM_UI_HUB_SERVICE, requireDoomUiHub } from '@agimon-ai/doompi-core/uiHub';\nimport type { Context } from '@deepseek-ai/cordis';\nimport type { ExtensionContext } from '@earendil-works/pi-coding-agent';\n\nimport { MCP_STATUS_KEY } from '../../constants/piMcp';\nimport { McpSession } from '../../services/mcpSession';\nimport { mcpSessionConfigFromProjection } from '../../services/projection';\nimport { readSessionConfig } from '../../services/sessionConfig';\nimport type { McpSessionConfig } from '../../types/mcpConfig';\nimport { formatMcpSessionAuthStatus, MCP_SESSION_AUTH_STATUS_KEY } from '../../types/webMcp';\nimport { registerLeaderContribution } from '../leader';\nimport { createMcpChildTool, createMcpSessionToolsService, MCP_SESSION_TOOLS_SERVICE } from '../mcpSessionTools';\n\nconst INFO = 'info';\nconst WARNING = 'warning';\n\nfunction failClosedSessionConfig(cwd: string): McpSessionConfig {\n return {\n enabled: false,\n repoRoot: cwd,\n stagingDirectory: path.join(cwd, '.doom', 'mcp-disabled'),\n sources: [],\n };\n}\n\nexport function createMcpPiRuntime(runtime: DoomCordisRuntimeService) {\n const mode = runtime.mode;\n let activeContext: ExtensionContext | undefined;\n let disposed = false;\n const session = new McpSession({\n onAuthorizationUrl: async (url, serverName, { openBrowser }) => {\n const context = activeContext;\n if (context?.mode === 'tui') {\n if (!openBrowser) return;\n try {\n const { default: open } = await import('open');\n await open(url.toString());\n } catch (error) {\n context.ui.notify(\n `Could not open the authorization page for ${serverName}: ${error instanceof Error ? error.message : String(error)}. Press a in the MCP overlay to retry.`,\n WARNING,\n );\n throw error;\n }\n return;\n }\n context?.ui?.notify(`Authorize ${serverName} by opening:\\n${url.toString()}`, INFO);\n },\n });\n\n return {\n session,\n services: [\n (cordis: Context) => {\n cordis.inject([DOOM_UI_HUB_SERVICE], (uiContext) => registerLeaderContribution(requireDoomUiHub(uiContext)));\n // The surface lives on the session fiber, so this resolves after install has\n // already registered the cached wrappers: binding is what first hides the ones\n // no server has confirmed.\n cordis.inject([DOOM_TOOL_SURFACE_SERVICE], (surfaceContext) =>\n session.bindToolSurface(requireDoomToolSurface(surfaceContext)),\n );\n cordis.inject([DOOM_CORDIS_SESSION_SERVICE], async (sessionContext) => {\n const hostSession = sessionContext.get(DOOM_CORDIS_SESSION_SERVICE) as DoomCordisSessionService;\n const context = hostSession.context;\n const expectedSessionId = hostSession.sessionId;\n let sessionActive = true;\n activeContext = context;\n // The legacy server-name status remains available to every UI. The compact\n // authorization status is browser-only so the TUI footer stays unchanged.\n const publishServerStatus = (): void => {\n const servers = session.getSnapshot().servers;\n const names = servers.map((server) => server.name).join(',');\n context.ui?.setStatus(MCP_STATUS_KEY, names);\n if (context.mode !== 'tui') {\n context.ui?.setStatus(MCP_SESSION_AUTH_STATUS_KEY, formatMcpSessionAuthStatus(session.getServers()));\n }\n };\n const stopPublishing = session.onChange(publishServerStatus);\n publishServerStatus();\n\n if (mode === 'standalone') {\n await session.reconfigure(readSessionConfig(process.env, context.cwd));\n } else {\n await session.reconfigure(failClosedSessionConfig(context.cwd));\n sessionContext.inject([DOOM_MCP_PROJECTION_SERVICE], async (projectionContext) => {\n const projection = readDoomMcpProjectionService(projectionContext);\n if (!projection || projection.sessionId !== expectedSessionId) {\n await session.reconfigure(failClosedSessionConfig(context.cwd));\n if (projection && sessionActive && !disposed) {\n context.ui?.notify(\n `The Doom MCP projection belongs to session \"${projection.sessionId}\", not \"${expectedSessionId}\"; MCP is disabled.`,\n WARNING,\n );\n }\n } else {\n await session.reconfigure(mcpSessionConfigFromProjection(projection.getSnapshot()));\n }\n return async () => {\n if (sessionActive && !disposed) await session.reconfigure(failClosedSessionConfig(context.cwd));\n };\n });\n }\n\n const status: DoomMcpStatusService = Object.freeze({\n generation: `${hostSession.generation}:mcp-status`,\n getSnapshot: () => session.getSnapshot(),\n onChange: (listener: () => void) => session.onChange(listener),\n });\n const toolResolver: DoomMcpToolResolverService = Object.freeze({\n generation: `${hostSession.generation}:mcp-tool-resolver`,\n resolve: (selectors: readonly string[]) => session.resolveToolSelectors(selectors),\n });\n const sessionTools = createMcpSessionToolsService(session, `${hostSession.generation}:mcp-tools`);\n const childTool = createMcpChildTool(async (parameters, signal) => {\n if (!sessionActive || disposed) throw new Error('The parent MCP session is no longer available.');\n const tool = sessionTools\n .snapshot()\n .find(\n (candidate) => candidate.serverName === parameters.server && candidate.toolName === parameters.tool,\n );\n if (!tool)\n throw new Error(\n `MCP tool ${parameters.server}/${parameters.tool} is not available in the current session configuration.`,\n );\n return sessionTools.invoke(tool.piName, parameters.arguments ?? {}, signal);\n });\n sessionContext.plugin((providerContext) => {\n providerContext.provide(DOOM_MCP_STATUS_SERVICE, status);\n providerContext.provide(DOOM_MCP_TOOL_RESOLVER_SERVICE, toolResolver);\n providerContext.provide(MCP_SESSION_TOOLS_SERVICE, sessionTools);\n providerContext.provide(DOOM_CHILD_SESSION_MCP_TOOL_SERVICE, childTool);\n });\n for (const diagnostic of session.getDiagnostics()) context.ui?.notify(diagnostic, WARNING);\n return async () => {\n sessionActive = false;\n stopPublishing();\n context.ui?.setStatus(MCP_STATUS_KEY, undefined);\n if (context.mode !== 'tui') context.ui?.setStatus(MCP_SESSION_AUTH_STATUS_KEY, undefined);\n if (activeContext === context) activeContext = undefined;\n if (!disposed) await session.reconfigure(failClosedSessionConfig(context.cwd));\n };\n });\n },\n ],\n async onDispose() {\n disposed = true;\n activeContext = undefined;\n await session.dispose();\n },\n };\n}\n","import type { PiPluginContext } from '@agimon-ai/doompi-core/piExtension';\n\nimport { createMcpPiRuntime } from '../../../../../services/piRuntime';\nexport const createMcpPiRoot = ({ runtime }: PiPluginContext) => {\n if (!runtime) throw new Error('MCP requires the Cordis runtime mode.');\n const state = createMcpPiRuntime(runtime);\n return { value: state, services: state.services, onDispose: () => state.onDispose() };\n};\nexport type McpPiScope = Awaited<ReturnType<typeof createMcpPiRoot>>['value'];\n","import { defineRoot } from '@agimon-ai/doompi-core/extensionFile';\n\nimport { createMcpPiRoot } from './_lib/piRoot';\n\nexport default defineRoot(createMcpPiRoot);\n","import { defineRoutedContribution, type WithRoot } from '@agimon-ai/doompi-core/extensionFile';\nimport type { PiPluginContext } from '@agimon-ai/doompi-core/piExtension';\n\nimport { createMcpCommand } from '../../../../../services/mcpCommand';\nimport type { McpPiScope } from '../_lib/piRoot';\nexport default defineRoutedContribution(\n (context: WithRoot<PiPluginContext<unknown>, McpPiScope>) =>\n [\n createMcpCommand(context.root.session, {\n openOverlay: async (ctx) => {\n const { openMcpOverlay } = await import('../../../../../tui/mcpOverlay');\n return openMcpOverlay(ctx, context.root.session);\n },\n }),\n ] as const,\n { cardinality: 'many' },\n);\n","import { defineResource } from '@agimon-ai/doompi-core/extensionFile';\n\nexport default defineResource({\n source: '@agimon-ai/doompi-mcp',\n moduleUrl: import.meta.url,\n skills: [\n {\n name: 'doompi-use-mcp',\n description:\n 'Use Doom Pi MCP to inspect domain-scoped servers, authenticate, reload configuration, and troubleshoot tool availability.',\n },\n ],\n});\n","import type { PiToolCollection, PiToolDeclaration } from '@agimon-ai/doompi-core/piExtension';\n\nimport type { CatalogTool } from '../../services/mcpCatalog';\nimport type { McpSession } from '../../services/mcpSession';\nimport { createMcpTool, type McpToolRenderers } from '../mcpTools';\nexport function createMcpToolCollection(\n session: McpSession,\n renderers: (tool: CatalogTool) => McpToolRenderers = () => ({}),\n): PiToolCollection {\n const declarations = new Map<CatalogTool, PiToolDeclaration>();\n return {\n snapshot: (): readonly PiToolDeclaration[] =>\n session.toolDefinitions().map((tool) => {\n let declaration = declarations.get(tool);\n if (!declaration) {\n declaration = createMcpTool(\n session.getClientManager,\n tool,\n (candidate) => session.isToolAvailable(candidate),\n renderers(tool),\n );\n declarations.set(tool, declaration);\n }\n return declaration;\n }),\n subscribe: (listener: () => void) => session.onChange(listener),\n };\n}\n","import { DoomToolCall, renderToolHeading } from '@agimon-ai/doompi-ui/toolChrome';\nimport type { Theme } from '@earendil-works/pi-coding-agent';\nimport { type Component, truncateToWidth, wrapTextWithAnsi } from '@earendil-works/pi-tui';\n\nconst COLLAPSED_RESULT_LINES = 12;\nconst MAX_ARGUMENTS = 3;\nconst ELLIPSIS = '…';\n\ninterface McpToolTextLayout {\n wrap: boolean;\n separator: boolean;\n trailingBlank: boolean;\n}\n\n/** Bash-compatible width budget, horizontal inset, and structural result divider. */\nclass McpToolText implements Component {\n constructor(\n private readonly lines: readonly string[],\n private readonly layout: McpToolTextLayout,\n private readonly theme: Theme,\n ) {}\n\n render(width: number): string[] {\n if (width <= 0) return [];\n const contentWidth = Math.max(1, width - 2);\n const rendered = this.layout.wrap\n ? this.lines.flatMap((line) => wrapTextWithAnsi(line, contentWidth))\n : this.lines.map((line) => truncateToWidth(line, contentWidth, ELLIPSIS));\n if (this.layout.separator) {\n rendered.unshift(this.theme.fg('borderMuted', '─'.repeat(contentWidth)));\n }\n const padded = rendered.map((line) => ` ${line}`);\n if (this.layout.trailingBlank) padded.push('');\n return padded;\n }\n\n invalidate(): void {\n // Content is immutable and reflows from the current width on every render.\n }\n}\n\nfunction argumentValue(value: unknown): string {\n if (typeof value === 'string') return value;\n if (typeof value === 'number' || typeof value === 'boolean') return String(value);\n if (value === null) return 'null';\n if (Array.isArray(value)) return `[${value.length}]`;\n return '{…}';\n}\n\nfunction argumentSummary(params: Record<string, unknown>): string {\n const entries = Object.entries(params);\n const shown = entries.slice(0, MAX_ARGUMENTS).map(([key, value]) => `${key}=${argumentValue(value)}`);\n if (entries.length > shown.length) shown.push(`+${entries.length - shown.length}`);\n return shown.join(' · ');\n}\n\nexport interface McpToolIdentity {\n serverName: string;\n toolName: string;\n}\n\nexport function renderMcpCall(tool: McpToolIdentity, params: Record<string, unknown>, theme: Theme): Component {\n const heading = renderToolHeading('mcp', tool.serverName, theme, 'muted');\n const toolName = theme.fg('accent', tool.toolName);\n const argumentsText = argumentSummary(params);\n const text = `${heading}${theme.fg('muted', ' / ')}${toolName}${\n argumentsText ? ` ${theme.fg('muted', `· ${argumentsText}`)}` : ''\n }`;\n return new DoomToolCall(text);\n}\n\nexport interface McpToolResultLike {\n content?: Array<{ type: string; text?: string }>;\n}\n\nexport interface McpToolResultOptions {\n expanded: boolean;\n isPartial: boolean;\n isError: boolean;\n}\n\nfunction resultLines(result: McpToolResultLike): string[] {\n const text = (result.content ?? []).map((block) => block.text ?? '').join('');\n const lines = text.split('\\n');\n while (lines.length > 0 && lines.at(-1)?.trim() === '') lines.pop();\n return lines;\n}\n\nexport function renderMcpResult(result: McpToolResultLike, options: McpToolResultOptions, theme: Theme): Component {\n const all = resultLines(result);\n const shown = options.expanded ? all : all.slice(0, COLLAPSED_RESULT_LINES);\n const body = shown.map((line) => theme.fg('toolOutput', line));\n\n if (options.isPartial) {\n body.push(theme.fg('warning', '◐') + theme.fg('dim', ' running'));\n } else if (options.isError) {\n body.push(theme.fg('error', '✗') + theme.fg('dim', ' failed'));\n } else if (!options.expanded && all.length > shown.length) {\n body.push(theme.fg('dim', '… ctrl+o'));\n } else if (body.length === 0) {\n body.push(theme.fg('success', '✓') + theme.fg('dim', ' done'));\n }\n\n return new McpToolText(body, { wrap: options.expanded, separator: true, trailingBlank: true }, theme);\n}\n","import { defineRoutedContribution, type WithRoot } from '@agimon-ai/doompi-core/extensionFile';\nimport type { PiPluginContext, PiToolCollection } from '@agimon-ai/doompi-core/piExtension';\n\nimport { createMcpToolCollection } from '../../../../../services/mcpToolCollection';\nimport { renderMcpCall, renderMcpResult } from '../../../../../tui/mcpToolRender';\nimport type { McpPiScope } from '../_lib/piRoot';\n\nexport default defineRoutedContribution(\n (context: WithRoot<PiPluginContext<unknown>, McpPiScope>): PiToolCollection =>\n createMcpToolCollection(context.root.session, (tool) => ({\n renderCall: (params, theme) => renderMcpCall(tool, params as Record<string, unknown>, theme),\n renderResult: (result, options, theme, execution) =>\n renderMcpResult(result, { ...options, isError: execution.isError }, theme),\n })),\n { cardinality: 'collection' },\n);\n","// Generated by @agimon-ai/doompi-build. Do not edit by hand.\nimport { definePiExtension, piToolContributions, type PiPluginContext, type PiPluginContributions } from '@agimon-ai/doompi-core/piExtension';\nimport { composeRootHooks } from '@agimon-ai/doompi-core/extensionFile';\n\nimport rootSession from '../src/extensions/workspaces/sessions/(backend)/root.cli';\nimport commandMcp from '../src/extensions/workspaces/sessions/(backend)/command/mcp.cli';\nimport resourceDoompiUseMcp from '../src/extensions/workspaces/sessions/(backend)/resource/doompi-use-mcp.cli';\nimport toolMcp from '../src/extensions/workspaces/sessions/(backend)/tool/mcp.cli';\n\ntype OptionsOf<T> = T extends (context: PiPluginContext<infer Options>) => unknown ? Options : never;\ntype InferredOptions = Exclude<OptionsOf<typeof rootSession> | OptionsOf<typeof commandMcp> | OptionsOf<typeof resourceDoompiUseMcp> | OptionsOf<typeof toolMcp>, undefined>;\ntype Intersect<Union> =\n (Union extends unknown ? (value: Union) => void : never) extends (value: infer Value) => void ? Value : never;\ntype ExtensionOptions = [InferredOptions] extends [never] ? undefined : Intersect<InferredOptions>;\n\ntype Factory<T, C> = (context: C) => T;\nconst at = <T, C>(value: T | Factory<T, C>, context: C): T =>\n typeof value === 'function' ? (value as Factory<T, C>)(context) : value;\ntype ManyFactory<T, C> = (context: C) => T | readonly T[];\nconst many = <T, C>(value: T | readonly T[] | ManyFactory<T, C>, context: C): readonly T[] => {\n const resolved = typeof value === 'function' ? (value as ManyFactory<T, C>)(context) : value;\n return Array.isArray(resolved) ? resolved : [resolved as T];\n};\n\nexport const extension = definePiExtension<ExtensionOptions>('@agimon-ai/doompi-mcp', async (context) => {\n const scopeSession = await rootSession(context);\n const contextSession = { ...context, root: scopeSession.value };\n return {\n ...composeRootHooks(scopeSession),\n get commands(): PiPluginContributions['commands'] { return [...many(commandMcp, contextSession)]; },\n get resources(): PiPluginContributions['resources'] { return [at(resourceDoompiUseMcp, contextSession)]; },\n ...piToolContributions('@agimon-ai/doompi-mcp', at(toolMcp, contextSession)),\n services: [...(scopeSession.services ?? [])],\n };\n});\n\nexport default extension;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"pi.cjs","names":["PACKAGE_SOURCE","LEADER_BINDING_PREFIX","LEADER_GROUP","LEADER_DETAIL","path","McpSession","DOOM_UI_HUB_SERVICE","requireDoomUiHub","DOOM_TOOL_SURFACE_SERVICE","requireDoomToolSurface","DOOM_CORDIS_SESSION_SERVICE","MCP_STATUS_KEY","MCP_SESSION_AUTH_STATUS_KEY","formatMcpSessionAuthStatus","readSessionConfig","DOOM_MCP_PROJECTION_SERVICE","readDoomMcpProjectionService","mcpSessionConfigFromProjection","createMcpSessionToolsService","createMcpChildTool","DOOM_MCP_STATUS_SERVICE","DOOM_MCP_TOOL_RESOLVER_SERVICE","MCP_SESSION_TOOLS_SERVICE","DOOM_CHILD_SESSION_MCP_TOOL_SERVICE","defineRoot","defineRoutedContribution","createMcpCommand","defineResource","createMcpTool","wrapTextWithAnsi","truncateToWidth","renderToolHeading","DoomToolCall","defineRoutedContribution","definePiExtension","rootSession","composeRootHooks","commandMcp","resourceDoompiUseMcp","piToolContributions","toolMcp"],"sources":["../../src/services/leader/index.ts","../../src/services/piRuntime/index.ts","../../src/extensions/workspaces/sessions/(backend)/_lib/piRoot.ts","../../src/extensions/workspaces/sessions/(backend)/root.cli.ts","../../src/extensions/workspaces/sessions/(backend)/command/mcp.cli.ts","../../src/extensions/workspaces/sessions/(backend)/resource/doompi-use-mcp.cli.ts","../../src/services/mcpToolCollection/index.ts","../../src/tui/mcpToolRender.ts","../../src/extensions/workspaces/sessions/(backend)/tool/mcp.cli.ts","../../generated/pi.ts"],"sourcesContent":["import type { DoomUiHubService } from '@agimon-ai/doompi-core/uiHub';\n\nimport { COMMAND_NAME } from '../../constants/mcp';\nimport {\n LEADER_BINDING_PREFIX,\n LEADER_DETAIL,\n LEADER_GROUP,\n LEADER_KEY,\n LEADER_LABEL,\n PACKAGE_SOURCE,\n} from '../../constants/piMcp';\n\nexport function registerLeaderContribution(hub: DoomUiHubService): () => void {\n const contribution = hub.registerLeader({\n source: PACKAGE_SOURCE,\n bindings: [\n {\n id: `${LEADER_BINDING_PREFIX}.open`,\n path: [LEADER_GROUP, { key: LEADER_KEY, label: LEADER_LABEL, detail: LEADER_DETAIL }],\n command: { name: COMMAND_NAME },\n },\n ],\n });\n return () => contribution.dispose();\n}\n","import path from 'node:path';\n\nimport { DOOM_CHILD_SESSION_MCP_TOOL_SERVICE } from '@agimon-ai/doompi-core/childSession';\nimport type { DoomCordisRuntimeService } from '@agimon-ai/doompi-core/cordisHost';\nimport { DOOM_CORDIS_SESSION_SERVICE, type DoomCordisSessionService } from '@agimon-ai/doompi-core/cordisHost';\nimport { DOOM_MCP_PROJECTION_SERVICE, readDoomMcpProjectionService } from '@agimon-ai/doompi-core/mcpProjection';\nimport { DOOM_MCP_STATUS_SERVICE, type DoomMcpStatusService } from '@agimon-ai/doompi-core/mcpStatus';\nimport {\n DOOM_MCP_TOOL_RESOLVER_SERVICE,\n type DoomMcpToolResolverService,\n} from '@agimon-ai/doompi-core/mcpToolResolver';\nimport { DOOM_TOOL_SURFACE_SERVICE, requireDoomToolSurface } from '@agimon-ai/doompi-core/toolSurface';\nimport { DOOM_UI_HUB_SERVICE, requireDoomUiHub } from '@agimon-ai/doompi-core/uiHub';\nimport type { Context } from '@deepseek-ai/cordis';\nimport type { ExtensionContext } from '@earendil-works/pi-coding-agent';\n\nimport { MCP_STATUS_KEY } from '../../constants/piMcp';\nimport { McpSession } from '../../services/mcpSession';\nimport { mcpSessionConfigFromProjection } from '../../services/projection';\nimport { readSessionConfig } from '../../services/sessionConfig';\nimport type { McpSessionConfig } from '../../types/mcpConfig';\nimport { formatMcpSessionAuthStatus, MCP_SESSION_AUTH_STATUS_KEY } from '../../types/webMcp';\nimport { registerLeaderContribution } from '../leader';\nimport { createMcpChildTool, createMcpSessionToolsService, MCP_SESSION_TOOLS_SERVICE } from '../mcpSessionTools';\n\nconst INFO = 'info';\nconst WARNING = 'warning';\n\nfunction failClosedSessionConfig(cwd: string): McpSessionConfig {\n return {\n enabled: false,\n repoRoot: cwd,\n stagingDirectory: path.join(cwd, '.doom', 'mcp-disabled'),\n sources: [],\n };\n}\n\nexport function createMcpPiRuntime(runtime: DoomCordisRuntimeService) {\n const mode = runtime.mode;\n let activeContext: ExtensionContext | undefined;\n let disposed = false;\n const session = new McpSession({\n onAuthorizationUrl: async (url, serverName, { openBrowser }) => {\n const context = activeContext;\n if (context?.mode === 'tui') {\n if (!openBrowser) return;\n try {\n const { default: open } = await import('open');\n await open(url.toString());\n } catch (error) {\n context.ui.notify(\n `Could not open the authorization page for ${serverName}: ${error instanceof Error ? error.message : String(error)}. Press a in the MCP overlay to retry.`,\n WARNING,\n );\n throw error;\n }\n return;\n }\n context?.ui?.notify(`Authorize ${serverName} by opening:\\n${url.toString()}`, INFO);\n },\n });\n\n return {\n session,\n services: [\n (cordis: Context) => {\n cordis.inject([DOOM_UI_HUB_SERVICE], (uiContext) => registerLeaderContribution(requireDoomUiHub(uiContext)));\n // The surface lives on the session fiber, so this resolves after install has\n // already registered the cached wrappers: binding is what first hides the ones\n // no server has confirmed.\n cordis.inject([DOOM_TOOL_SURFACE_SERVICE], (surfaceContext) =>\n session.bindToolSurface(requireDoomToolSurface(surfaceContext)),\n );\n cordis.inject([DOOM_CORDIS_SESSION_SERVICE], async (sessionContext) => {\n const hostSession = sessionContext.get(DOOM_CORDIS_SESSION_SERVICE) as DoomCordisSessionService;\n const context = hostSession.context;\n const expectedSessionId = hostSession.sessionId;\n let sessionActive = true;\n activeContext = context;\n // The legacy server-name status remains available to every UI. The compact\n // authorization status is browser-only so the TUI footer stays unchanged.\n const publishServerStatus = (): void => {\n const servers = session.getSnapshot().servers;\n const names = servers.map((server) => server.name).join(',');\n context.ui?.setStatus(MCP_STATUS_KEY, names);\n if (context.mode !== 'tui') {\n context.ui?.setStatus(MCP_SESSION_AUTH_STATUS_KEY, formatMcpSessionAuthStatus(session.getServers()));\n }\n };\n const stopPublishing = session.onChange(publishServerStatus);\n publishServerStatus();\n\n if (mode === 'standalone') {\n await session.reconfigure(readSessionConfig(process.env, context.cwd), context.cwd);\n } else {\n await session.reconfigure(failClosedSessionConfig(context.cwd));\n sessionContext.inject([DOOM_MCP_PROJECTION_SERVICE], async (projectionContext) => {\n const projection = readDoomMcpProjectionService(projectionContext);\n if (!projection || projection.sessionId !== expectedSessionId) {\n await session.reconfigure(failClosedSessionConfig(context.cwd));\n if (projection && sessionActive && !disposed) {\n context.ui?.notify(\n `The Doom MCP projection belongs to session \"${projection.sessionId}\", not \"${expectedSessionId}\"; MCP is disabled.`,\n WARNING,\n );\n }\n } else {\n const snapshot = projection.getSnapshot();\n await session.reconfigure(\n mcpSessionConfigFromProjection(snapshot, context.cwd),\n context.cwd,\n snapshot.repoRoot,\n );\n }\n return async () => {\n if (sessionActive && !disposed) await session.reconfigure(failClosedSessionConfig(context.cwd));\n };\n });\n }\n\n const status: DoomMcpStatusService = Object.freeze({\n generation: `${hostSession.generation}:mcp-status`,\n getSnapshot: () => session.getSnapshot(),\n onChange: (listener: () => void) => session.onChange(listener),\n });\n const toolResolver: DoomMcpToolResolverService = Object.freeze({\n generation: `${hostSession.generation}:mcp-tool-resolver`,\n resolve: (selectors: readonly string[]) => session.resolveToolSelectors(selectors),\n });\n const sessionTools = createMcpSessionToolsService(session, `${hostSession.generation}:mcp-tools`);\n const childTool = createMcpChildTool(async (parameters, signal) => {\n if (!sessionActive || disposed) throw new Error('The parent MCP session is no longer available.');\n const tool = sessionTools\n .snapshot()\n .find(\n (candidate) => candidate.serverName === parameters.server && candidate.toolName === parameters.tool,\n );\n if (!tool)\n throw new Error(\n `MCP tool ${parameters.server}/${parameters.tool} is not available in the current session configuration.`,\n );\n return sessionTools.invoke(tool.piName, parameters.arguments ?? {}, signal);\n });\n sessionContext.plugin((providerContext) => {\n providerContext.provide(DOOM_MCP_STATUS_SERVICE, status);\n providerContext.provide(DOOM_MCP_TOOL_RESOLVER_SERVICE, toolResolver);\n providerContext.provide(MCP_SESSION_TOOLS_SERVICE, sessionTools);\n providerContext.provide(DOOM_CHILD_SESSION_MCP_TOOL_SERVICE, childTool);\n });\n for (const diagnostic of session.getDiagnostics()) context.ui?.notify(diagnostic, WARNING);\n return async () => {\n sessionActive = false;\n stopPublishing();\n context.ui?.setStatus(MCP_STATUS_KEY, undefined);\n if (context.mode !== 'tui') context.ui?.setStatus(MCP_SESSION_AUTH_STATUS_KEY, undefined);\n if (activeContext === context) activeContext = undefined;\n if (!disposed) await session.reconfigure(failClosedSessionConfig(context.cwd));\n };\n });\n },\n ],\n async onDispose() {\n disposed = true;\n activeContext = undefined;\n await session.dispose();\n },\n };\n}\n","import type { PiPluginContext } from '@agimon-ai/doompi-core/piExtension';\n\nimport { createMcpPiRuntime } from '../../../../../services/piRuntime';\nexport const createMcpPiRoot = ({ runtime }: PiPluginContext) => {\n if (!runtime) throw new Error('MCP requires the Cordis runtime mode.');\n const state = createMcpPiRuntime(runtime);\n return { value: state, services: state.services, onDispose: () => state.onDispose() };\n};\nexport type McpPiScope = Awaited<ReturnType<typeof createMcpPiRoot>>['value'];\n","import { defineRoot } from '@agimon-ai/doompi-core/extensionFile';\n\nimport { createMcpPiRoot } from './_lib/piRoot';\n\nexport default defineRoot(createMcpPiRoot);\n","import { defineRoutedContribution, type WithRoot } from '@agimon-ai/doompi-core/extensionFile';\nimport type { PiPluginContext } from '@agimon-ai/doompi-core/piExtension';\n\nimport { createMcpCommand } from '../../../../../services/mcpCommand';\nimport type { McpPiScope } from '../_lib/piRoot';\nexport default defineRoutedContribution(\n (context: WithRoot<PiPluginContext<unknown>, McpPiScope>) =>\n [\n createMcpCommand(context.root.session, {\n openOverlay: async (ctx) => {\n const { openMcpOverlay } = await import('../../../../../tui/mcpOverlay');\n return openMcpOverlay(ctx, context.root.session);\n },\n }),\n ] as const,\n { cardinality: 'many' },\n);\n","import { defineResource } from '@agimon-ai/doompi-core/extensionFile';\n\nexport default defineResource({\n source: '@agimon-ai/doompi-mcp',\n moduleUrl: import.meta.url,\n skills: [\n {\n name: 'doompi-use-mcp',\n description:\n 'Use Doom Pi MCP to inspect domain-scoped servers, authenticate, reload configuration, and troubleshoot tool availability.',\n },\n ],\n});\n","import type { PiToolCollection, PiToolDeclaration } from '@agimon-ai/doompi-core/piExtension';\n\nimport type { CatalogTool } from '../../services/mcpCatalog';\nimport type { McpSession } from '../../services/mcpSession';\nimport { createMcpTool, type McpToolRenderers } from '../mcpTools';\nexport function createMcpToolCollection(\n session: McpSession,\n renderers: (tool: CatalogTool) => McpToolRenderers = () => ({}),\n): PiToolCollection {\n const declarations = new Map<CatalogTool, PiToolDeclaration>();\n return {\n snapshot: (): readonly PiToolDeclaration[] =>\n session.toolDefinitions().map((tool) => {\n let declaration = declarations.get(tool);\n if (!declaration) {\n declaration = createMcpTool(\n session.getClientManager,\n tool,\n (candidate) => session.isToolAvailable(candidate),\n renderers(tool),\n );\n declarations.set(tool, declaration);\n }\n return declaration;\n }),\n subscribe: (listener: () => void) => session.onChange(listener),\n };\n}\n","import { DoomToolCall, renderToolHeading } from '@agimon-ai/doompi-ui/toolChrome';\nimport type { Theme } from '@earendil-works/pi-coding-agent';\nimport { type Component, truncateToWidth, wrapTextWithAnsi } from '@earendil-works/pi-tui';\n\nconst COLLAPSED_RESULT_LINES = 12;\nconst MAX_ARGUMENTS = 3;\nconst ELLIPSIS = '…';\n\ninterface McpToolTextLayout {\n wrap: boolean;\n separator: boolean;\n trailingBlank: boolean;\n}\n\n/** Bash-compatible width budget, horizontal inset, and structural result divider. */\nclass McpToolText implements Component {\n constructor(\n private readonly lines: readonly string[],\n private readonly layout: McpToolTextLayout,\n private readonly theme: Theme,\n ) {}\n\n render(width: number): string[] {\n if (width <= 0) return [];\n const contentWidth = Math.max(1, width - 2);\n const rendered = this.layout.wrap\n ? this.lines.flatMap((line) => wrapTextWithAnsi(line, contentWidth))\n : this.lines.map((line) => truncateToWidth(line, contentWidth, ELLIPSIS));\n if (this.layout.separator) {\n rendered.unshift(this.theme.fg('borderMuted', '─'.repeat(contentWidth)));\n }\n const padded = rendered.map((line) => ` ${line}`);\n if (this.layout.trailingBlank) padded.push('');\n return padded;\n }\n\n invalidate(): void {\n // Content is immutable and reflows from the current width on every render.\n }\n}\n\nfunction argumentValue(value: unknown): string {\n if (typeof value === 'string') return value;\n if (typeof value === 'number' || typeof value === 'boolean') return String(value);\n if (value === null) return 'null';\n if (Array.isArray(value)) return `[${value.length}]`;\n return '{…}';\n}\n\nfunction argumentSummary(params: Record<string, unknown>): string {\n const entries = Object.entries(params);\n const shown = entries.slice(0, MAX_ARGUMENTS).map(([key, value]) => `${key}=${argumentValue(value)}`);\n if (entries.length > shown.length) shown.push(`+${entries.length - shown.length}`);\n return shown.join(' · ');\n}\n\nexport interface McpToolIdentity {\n serverName: string;\n toolName: string;\n}\n\nexport function renderMcpCall(tool: McpToolIdentity, params: Record<string, unknown>, theme: Theme): Component {\n const heading = renderToolHeading('mcp', tool.serverName, theme, 'muted');\n const toolName = theme.fg('accent', tool.toolName);\n const argumentsText = argumentSummary(params);\n const text = `${heading}${theme.fg('muted', ' / ')}${toolName}${\n argumentsText ? ` ${theme.fg('muted', `· ${argumentsText}`)}` : ''\n }`;\n return new DoomToolCall(text);\n}\n\nexport interface McpToolResultLike {\n content?: Array<{ type: string; text?: string }>;\n}\n\nexport interface McpToolResultOptions {\n expanded: boolean;\n isPartial: boolean;\n isError: boolean;\n}\n\nfunction resultLines(result: McpToolResultLike): string[] {\n const text = (result.content ?? []).map((block) => block.text ?? '').join('');\n const lines = text.split('\\n');\n while (lines.length > 0 && lines.at(-1)?.trim() === '') lines.pop();\n return lines;\n}\n\nexport function renderMcpResult(result: McpToolResultLike, options: McpToolResultOptions, theme: Theme): Component {\n const all = resultLines(result);\n const shown = options.expanded ? all : all.slice(0, COLLAPSED_RESULT_LINES);\n const body = shown.map((line) => theme.fg('toolOutput', line));\n\n if (options.isPartial) {\n body.push(theme.fg('warning', '◐') + theme.fg('dim', ' running'));\n } else if (options.isError) {\n body.push(theme.fg('error', '✗') + theme.fg('dim', ' failed'));\n } else if (!options.expanded && all.length > shown.length) {\n body.push(theme.fg('dim', '… ctrl+o'));\n } else if (body.length === 0) {\n body.push(theme.fg('success', '✓') + theme.fg('dim', ' done'));\n }\n\n return new McpToolText(body, { wrap: options.expanded, separator: true, trailingBlank: true }, theme);\n}\n","import { defineRoutedContribution, type WithRoot } from '@agimon-ai/doompi-core/extensionFile';\nimport type { PiPluginContext, PiToolCollection } from '@agimon-ai/doompi-core/piExtension';\n\nimport { createMcpToolCollection } from '../../../../../services/mcpToolCollection';\nimport { renderMcpCall, renderMcpResult } from '../../../../../tui/mcpToolRender';\nimport type { McpPiScope } from '../_lib/piRoot';\n\nexport default defineRoutedContribution(\n (context: WithRoot<PiPluginContext<unknown>, McpPiScope>): PiToolCollection =>\n createMcpToolCollection(context.root.session, (tool) => ({\n renderCall: (params, theme) => renderMcpCall(tool, params as Record<string, unknown>, theme),\n renderResult: (result, options, theme, execution) =>\n renderMcpResult(result, { ...options, isError: execution.isError }, theme),\n })),\n { cardinality: 'collection' },\n);\n","// Generated by @agimon-ai/doompi-build. Do not edit by hand.\nimport { definePiExtension, piToolContributions, type PiPluginContext, type PiPluginContributions } from '@agimon-ai/doompi-core/piExtension';\nimport { composeRootHooks } from '@agimon-ai/doompi-core/extensionFile';\n\nimport rootSession from '../src/extensions/workspaces/sessions/(backend)/root.cli';\nimport commandMcp from '../src/extensions/workspaces/sessions/(backend)/command/mcp.cli';\nimport resourceDoompiUseMcp from '../src/extensions/workspaces/sessions/(backend)/resource/doompi-use-mcp.cli';\nimport toolMcp from '../src/extensions/workspaces/sessions/(backend)/tool/mcp.cli';\n\ntype OptionsOf<T> = T extends (context: PiPluginContext<infer Options>) => unknown ? Options : never;\ntype InferredOptions = Exclude<OptionsOf<typeof rootSession> | OptionsOf<typeof commandMcp> | OptionsOf<typeof resourceDoompiUseMcp> | OptionsOf<typeof toolMcp>, undefined>;\ntype Intersect<Union> =\n (Union extends unknown ? (value: Union) => void : never) extends (value: infer Value) => void ? Value : never;\ntype ExtensionOptions = [InferredOptions] extends [never] ? undefined : Intersect<InferredOptions>;\n\ntype Factory<T, C> = (context: C) => T;\nconst at = <T, C>(value: T | Factory<T, C>, context: C): T =>\n typeof value === 'function' ? (value as Factory<T, C>)(context) : value;\ntype ManyFactory<T, C> = (context: C) => T | readonly T[];\nconst many = <T, C>(value: T | readonly T[] | ManyFactory<T, C>, context: C): readonly T[] => {\n const resolved = typeof value === 'function' ? (value as ManyFactory<T, C>)(context) : value;\n return Array.isArray(resolved) ? resolved : [resolved as T];\n};\n\nexport const extension = definePiExtension<ExtensionOptions>('@agimon-ai/doompi-mcp', async (context) => {\n const scopeSession = await rootSession(context);\n const contextSession = { ...context, root: scopeSession.value };\n return {\n ...composeRootHooks(scopeSession),\n get commands(): PiPluginContributions['commands'] { return [...many(commandMcp, contextSession)]; },\n get resources(): PiPluginContributions['resources'] { return [at(resourceDoompiUseMcp, contextSession)]; },\n ...piToolContributions('@agimon-ai/doompi-mcp', at(toolMcp, contextSession)),\n services: [...(scopeSession.services ?? [])],\n };\n});\n\nexport default extension;\n"],"mappings":"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"}
|
package/dist/extensions/pi.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { a as readSessionConfig } from "../mcpCatalog-
|
|
2
|
-
import { t as mcpSessionConfigFromProjection } from "../projection-
|
|
3
|
-
import { _ as LEADER_BINDING_PREFIX, a as createMcpSessionToolsService, b as MCP_STATUS_KEY, g as createMcpTool, h as McpSession, i as createMcpChildTool, m as formatMcpSessionAuthStatus, p as MCP_SESSION_AUTH_STATUS_KEY, r as MCP_SESSION_TOOLS_SERVICE, t as createMcpCommand, v as LEADER_DETAIL, x as PACKAGE_SOURCE, y as LEADER_GROUP } from "../mcpCommand-
|
|
1
|
+
import { a as readSessionConfig } from "../mcpCatalog-laXfwecc.mjs";
|
|
2
|
+
import { t as mcpSessionConfigFromProjection } from "../projection-gyAA2jRB.mjs";
|
|
3
|
+
import { _ as LEADER_BINDING_PREFIX, a as createMcpSessionToolsService, b as MCP_STATUS_KEY, g as createMcpTool, h as McpSession, i as createMcpChildTool, m as formatMcpSessionAuthStatus, p as MCP_SESSION_AUTH_STATUS_KEY, r as MCP_SESSION_TOOLS_SERVICE, t as createMcpCommand, v as LEADER_DETAIL, x as PACKAGE_SOURCE, y as LEADER_GROUP } from "../mcpCommand-BaJXXphd.mjs";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import { DOOM_MCP_PROJECTION_SERVICE, readDoomMcpProjectionService } from "@agimon-ai/doompi-core/mcpProjection";
|
|
6
6
|
import { definePiExtension, piToolContributions } from "@agimon-ai/doompi-core/piExtension";
|
|
@@ -78,7 +78,7 @@ function createMcpPiRuntime(runtime) {
|
|
|
78
78
|
};
|
|
79
79
|
const stopPublishing = session.onChange(publishServerStatus);
|
|
80
80
|
publishServerStatus();
|
|
81
|
-
if (mode === "standalone") await session.reconfigure(readSessionConfig(process.env, context.cwd));
|
|
81
|
+
if (mode === "standalone") await session.reconfigure(readSessionConfig(process.env, context.cwd), context.cwd);
|
|
82
82
|
else {
|
|
83
83
|
await session.reconfigure(failClosedSessionConfig(context.cwd));
|
|
84
84
|
sessionContext.inject([DOOM_MCP_PROJECTION_SERVICE], async (projectionContext) => {
|
|
@@ -86,7 +86,10 @@ function createMcpPiRuntime(runtime) {
|
|
|
86
86
|
if (!projection || projection.sessionId !== expectedSessionId) {
|
|
87
87
|
await session.reconfigure(failClosedSessionConfig(context.cwd));
|
|
88
88
|
if (projection && sessionActive && !disposed) context.ui?.notify(`The Doom MCP projection belongs to session "${projection.sessionId}", not "${expectedSessionId}"; MCP is disabled.`, WARNING);
|
|
89
|
-
} else
|
|
89
|
+
} else {
|
|
90
|
+
const snapshot = projection.getSnapshot();
|
|
91
|
+
await session.reconfigure(mcpSessionConfigFromProjection(snapshot, context.cwd), context.cwd, snapshot.repoRoot);
|
|
92
|
+
}
|
|
90
93
|
return async () => {
|
|
91
94
|
if (sessionActive && !disposed) await session.reconfigure(failClosedSessionConfig(context.cwd));
|
|
92
95
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pi.mjs","names":["rootSession","commandMcp","resourceDoompiUseMcp","toolMcp"],"sources":["../../src/services/leader/index.ts","../../src/services/piRuntime/index.ts","../../src/extensions/workspaces/sessions/(backend)/_lib/piRoot.ts","../../src/extensions/workspaces/sessions/(backend)/root.cli.ts","../../src/extensions/workspaces/sessions/(backend)/command/mcp.cli.ts","../../src/extensions/workspaces/sessions/(backend)/resource/doompi-use-mcp.cli.ts","../../src/services/mcpToolCollection/index.ts","../../src/tui/mcpToolRender.ts","../../src/extensions/workspaces/sessions/(backend)/tool/mcp.cli.ts","../../generated/pi.ts"],"sourcesContent":["import type { DoomUiHubService } from '@agimon-ai/doompi-core/uiHub';\n\nimport { COMMAND_NAME } from '../../constants/mcp';\nimport {\n LEADER_BINDING_PREFIX,\n LEADER_DETAIL,\n LEADER_GROUP,\n LEADER_KEY,\n LEADER_LABEL,\n PACKAGE_SOURCE,\n} from '../../constants/piMcp';\n\nexport function registerLeaderContribution(hub: DoomUiHubService): () => void {\n const contribution = hub.registerLeader({\n source: PACKAGE_SOURCE,\n bindings: [\n {\n id: `${LEADER_BINDING_PREFIX}.open`,\n path: [LEADER_GROUP, { key: LEADER_KEY, label: LEADER_LABEL, detail: LEADER_DETAIL }],\n command: { name: COMMAND_NAME },\n },\n ],\n });\n return () => contribution.dispose();\n}\n","import path from 'node:path';\n\nimport { DOOM_CHILD_SESSION_MCP_TOOL_SERVICE } from '@agimon-ai/doompi-core/childSession';\nimport type { DoomCordisRuntimeService } from '@agimon-ai/doompi-core/cordisHost';\nimport { DOOM_CORDIS_SESSION_SERVICE, type DoomCordisSessionService } from '@agimon-ai/doompi-core/cordisHost';\nimport { DOOM_MCP_PROJECTION_SERVICE, readDoomMcpProjectionService } from '@agimon-ai/doompi-core/mcpProjection';\nimport { DOOM_MCP_STATUS_SERVICE, type DoomMcpStatusService } from '@agimon-ai/doompi-core/mcpStatus';\nimport {\n DOOM_MCP_TOOL_RESOLVER_SERVICE,\n type DoomMcpToolResolverService,\n} from '@agimon-ai/doompi-core/mcpToolResolver';\nimport { DOOM_TOOL_SURFACE_SERVICE, requireDoomToolSurface } from '@agimon-ai/doompi-core/toolSurface';\nimport { DOOM_UI_HUB_SERVICE, requireDoomUiHub } from '@agimon-ai/doompi-core/uiHub';\nimport type { Context } from '@deepseek-ai/cordis';\nimport type { ExtensionContext } from '@earendil-works/pi-coding-agent';\n\nimport { MCP_STATUS_KEY } from '../../constants/piMcp';\nimport { McpSession } from '../../services/mcpSession';\nimport { mcpSessionConfigFromProjection } from '../../services/projection';\nimport { readSessionConfig } from '../../services/sessionConfig';\nimport type { McpSessionConfig } from '../../types/mcpConfig';\nimport { formatMcpSessionAuthStatus, MCP_SESSION_AUTH_STATUS_KEY } from '../../types/webMcp';\nimport { registerLeaderContribution } from '../leader';\nimport { createMcpChildTool, createMcpSessionToolsService, MCP_SESSION_TOOLS_SERVICE } from '../mcpSessionTools';\n\nconst INFO = 'info';\nconst WARNING = 'warning';\n\nfunction failClosedSessionConfig(cwd: string): McpSessionConfig {\n return {\n enabled: false,\n repoRoot: cwd,\n stagingDirectory: path.join(cwd, '.doom', 'mcp-disabled'),\n sources: [],\n };\n}\n\nexport function createMcpPiRuntime(runtime: DoomCordisRuntimeService) {\n const mode = runtime.mode;\n let activeContext: ExtensionContext | undefined;\n let disposed = false;\n const session = new McpSession({\n onAuthorizationUrl: async (url, serverName, { openBrowser }) => {\n const context = activeContext;\n if (context?.mode === 'tui') {\n if (!openBrowser) return;\n try {\n const { default: open } = await import('open');\n await open(url.toString());\n } catch (error) {\n context.ui.notify(\n `Could not open the authorization page for ${serverName}: ${error instanceof Error ? error.message : String(error)}. Press a in the MCP overlay to retry.`,\n WARNING,\n );\n throw error;\n }\n return;\n }\n context?.ui?.notify(`Authorize ${serverName} by opening:\\n${url.toString()}`, INFO);\n },\n });\n\n return {\n session,\n services: [\n (cordis: Context) => {\n cordis.inject([DOOM_UI_HUB_SERVICE], (uiContext) => registerLeaderContribution(requireDoomUiHub(uiContext)));\n // The surface lives on the session fiber, so this resolves after install has\n // already registered the cached wrappers: binding is what first hides the ones\n // no server has confirmed.\n cordis.inject([DOOM_TOOL_SURFACE_SERVICE], (surfaceContext) =>\n session.bindToolSurface(requireDoomToolSurface(surfaceContext)),\n );\n cordis.inject([DOOM_CORDIS_SESSION_SERVICE], async (sessionContext) => {\n const hostSession = sessionContext.get(DOOM_CORDIS_SESSION_SERVICE) as DoomCordisSessionService;\n const context = hostSession.context;\n const expectedSessionId = hostSession.sessionId;\n let sessionActive = true;\n activeContext = context;\n // The legacy server-name status remains available to every UI. The compact\n // authorization status is browser-only so the TUI footer stays unchanged.\n const publishServerStatus = (): void => {\n const servers = session.getSnapshot().servers;\n const names = servers.map((server) => server.name).join(',');\n context.ui?.setStatus(MCP_STATUS_KEY, names);\n if (context.mode !== 'tui') {\n context.ui?.setStatus(MCP_SESSION_AUTH_STATUS_KEY, formatMcpSessionAuthStatus(session.getServers()));\n }\n };\n const stopPublishing = session.onChange(publishServerStatus);\n publishServerStatus();\n\n if (mode === 'standalone') {\n await session.reconfigure(readSessionConfig(process.env, context.cwd));\n } else {\n await session.reconfigure(failClosedSessionConfig(context.cwd));\n sessionContext.inject([DOOM_MCP_PROJECTION_SERVICE], async (projectionContext) => {\n const projection = readDoomMcpProjectionService(projectionContext);\n if (!projection || projection.sessionId !== expectedSessionId) {\n await session.reconfigure(failClosedSessionConfig(context.cwd));\n if (projection && sessionActive && !disposed) {\n context.ui?.notify(\n `The Doom MCP projection belongs to session \"${projection.sessionId}\", not \"${expectedSessionId}\"; MCP is disabled.`,\n WARNING,\n );\n }\n } else {\n await session.reconfigure(mcpSessionConfigFromProjection(projection.getSnapshot()));\n }\n return async () => {\n if (sessionActive && !disposed) await session.reconfigure(failClosedSessionConfig(context.cwd));\n };\n });\n }\n\n const status: DoomMcpStatusService = Object.freeze({\n generation: `${hostSession.generation}:mcp-status`,\n getSnapshot: () => session.getSnapshot(),\n onChange: (listener: () => void) => session.onChange(listener),\n });\n const toolResolver: DoomMcpToolResolverService = Object.freeze({\n generation: `${hostSession.generation}:mcp-tool-resolver`,\n resolve: (selectors: readonly string[]) => session.resolveToolSelectors(selectors),\n });\n const sessionTools = createMcpSessionToolsService(session, `${hostSession.generation}:mcp-tools`);\n const childTool = createMcpChildTool(async (parameters, signal) => {\n if (!sessionActive || disposed) throw new Error('The parent MCP session is no longer available.');\n const tool = sessionTools\n .snapshot()\n .find(\n (candidate) => candidate.serverName === parameters.server && candidate.toolName === parameters.tool,\n );\n if (!tool)\n throw new Error(\n `MCP tool ${parameters.server}/${parameters.tool} is not available in the current session configuration.`,\n );\n return sessionTools.invoke(tool.piName, parameters.arguments ?? {}, signal);\n });\n sessionContext.plugin((providerContext) => {\n providerContext.provide(DOOM_MCP_STATUS_SERVICE, status);\n providerContext.provide(DOOM_MCP_TOOL_RESOLVER_SERVICE, toolResolver);\n providerContext.provide(MCP_SESSION_TOOLS_SERVICE, sessionTools);\n providerContext.provide(DOOM_CHILD_SESSION_MCP_TOOL_SERVICE, childTool);\n });\n for (const diagnostic of session.getDiagnostics()) context.ui?.notify(diagnostic, WARNING);\n return async () => {\n sessionActive = false;\n stopPublishing();\n context.ui?.setStatus(MCP_STATUS_KEY, undefined);\n if (context.mode !== 'tui') context.ui?.setStatus(MCP_SESSION_AUTH_STATUS_KEY, undefined);\n if (activeContext === context) activeContext = undefined;\n if (!disposed) await session.reconfigure(failClosedSessionConfig(context.cwd));\n };\n });\n },\n ],\n async onDispose() {\n disposed = true;\n activeContext = undefined;\n await session.dispose();\n },\n };\n}\n","import type { PiPluginContext } from '@agimon-ai/doompi-core/piExtension';\n\nimport { createMcpPiRuntime } from '../../../../../services/piRuntime';\nexport const createMcpPiRoot = ({ runtime }: PiPluginContext) => {\n if (!runtime) throw new Error('MCP requires the Cordis runtime mode.');\n const state = createMcpPiRuntime(runtime);\n return { value: state, services: state.services, onDispose: () => state.onDispose() };\n};\nexport type McpPiScope = Awaited<ReturnType<typeof createMcpPiRoot>>['value'];\n","import { defineRoot } from '@agimon-ai/doompi-core/extensionFile';\n\nimport { createMcpPiRoot } from './_lib/piRoot';\n\nexport default defineRoot(createMcpPiRoot);\n","import { defineRoutedContribution, type WithRoot } from '@agimon-ai/doompi-core/extensionFile';\nimport type { PiPluginContext } from '@agimon-ai/doompi-core/piExtension';\n\nimport { createMcpCommand } from '../../../../../services/mcpCommand';\nimport type { McpPiScope } from '../_lib/piRoot';\nexport default defineRoutedContribution(\n (context: WithRoot<PiPluginContext<unknown>, McpPiScope>) =>\n [\n createMcpCommand(context.root.session, {\n openOverlay: async (ctx) => {\n const { openMcpOverlay } = await import('../../../../../tui/mcpOverlay');\n return openMcpOverlay(ctx, context.root.session);\n },\n }),\n ] as const,\n { cardinality: 'many' },\n);\n","import { defineResource } from '@agimon-ai/doompi-core/extensionFile';\n\nexport default defineResource({\n source: '@agimon-ai/doompi-mcp',\n moduleUrl: import.meta.url,\n skills: [\n {\n name: 'doompi-use-mcp',\n description:\n 'Use Doom Pi MCP to inspect domain-scoped servers, authenticate, reload configuration, and troubleshoot tool availability.',\n },\n ],\n});\n","import type { PiToolCollection, PiToolDeclaration } from '@agimon-ai/doompi-core/piExtension';\n\nimport type { CatalogTool } from '../../services/mcpCatalog';\nimport type { McpSession } from '../../services/mcpSession';\nimport { createMcpTool, type McpToolRenderers } from '../mcpTools';\nexport function createMcpToolCollection(\n session: McpSession,\n renderers: (tool: CatalogTool) => McpToolRenderers = () => ({}),\n): PiToolCollection {\n const declarations = new Map<CatalogTool, PiToolDeclaration>();\n return {\n snapshot: (): readonly PiToolDeclaration[] =>\n session.toolDefinitions().map((tool) => {\n let declaration = declarations.get(tool);\n if (!declaration) {\n declaration = createMcpTool(\n session.getClientManager,\n tool,\n (candidate) => session.isToolAvailable(candidate),\n renderers(tool),\n );\n declarations.set(tool, declaration);\n }\n return declaration;\n }),\n subscribe: (listener: () => void) => session.onChange(listener),\n };\n}\n","import { DoomToolCall, renderToolHeading } from '@agimon-ai/doompi-ui/toolChrome';\nimport type { Theme } from '@earendil-works/pi-coding-agent';\nimport { type Component, truncateToWidth, wrapTextWithAnsi } from '@earendil-works/pi-tui';\n\nconst COLLAPSED_RESULT_LINES = 12;\nconst MAX_ARGUMENTS = 3;\nconst ELLIPSIS = '…';\n\ninterface McpToolTextLayout {\n wrap: boolean;\n separator: boolean;\n trailingBlank: boolean;\n}\n\n/** Bash-compatible width budget, horizontal inset, and structural result divider. */\nclass McpToolText implements Component {\n constructor(\n private readonly lines: readonly string[],\n private readonly layout: McpToolTextLayout,\n private readonly theme: Theme,\n ) {}\n\n render(width: number): string[] {\n if (width <= 0) return [];\n const contentWidth = Math.max(1, width - 2);\n const rendered = this.layout.wrap\n ? this.lines.flatMap((line) => wrapTextWithAnsi(line, contentWidth))\n : this.lines.map((line) => truncateToWidth(line, contentWidth, ELLIPSIS));\n if (this.layout.separator) {\n rendered.unshift(this.theme.fg('borderMuted', '─'.repeat(contentWidth)));\n }\n const padded = rendered.map((line) => ` ${line}`);\n if (this.layout.trailingBlank) padded.push('');\n return padded;\n }\n\n invalidate(): void {\n // Content is immutable and reflows from the current width on every render.\n }\n}\n\nfunction argumentValue(value: unknown): string {\n if (typeof value === 'string') return value;\n if (typeof value === 'number' || typeof value === 'boolean') return String(value);\n if (value === null) return 'null';\n if (Array.isArray(value)) return `[${value.length}]`;\n return '{…}';\n}\n\nfunction argumentSummary(params: Record<string, unknown>): string {\n const entries = Object.entries(params);\n const shown = entries.slice(0, MAX_ARGUMENTS).map(([key, value]) => `${key}=${argumentValue(value)}`);\n if (entries.length > shown.length) shown.push(`+${entries.length - shown.length}`);\n return shown.join(' · ');\n}\n\nexport interface McpToolIdentity {\n serverName: string;\n toolName: string;\n}\n\nexport function renderMcpCall(tool: McpToolIdentity, params: Record<string, unknown>, theme: Theme): Component {\n const heading = renderToolHeading('mcp', tool.serverName, theme, 'muted');\n const toolName = theme.fg('accent', tool.toolName);\n const argumentsText = argumentSummary(params);\n const text = `${heading}${theme.fg('muted', ' / ')}${toolName}${\n argumentsText ? ` ${theme.fg('muted', `· ${argumentsText}`)}` : ''\n }`;\n return new DoomToolCall(text);\n}\n\nexport interface McpToolResultLike {\n content?: Array<{ type: string; text?: string }>;\n}\n\nexport interface McpToolResultOptions {\n expanded: boolean;\n isPartial: boolean;\n isError: boolean;\n}\n\nfunction resultLines(result: McpToolResultLike): string[] {\n const text = (result.content ?? []).map((block) => block.text ?? '').join('');\n const lines = text.split('\\n');\n while (lines.length > 0 && lines.at(-1)?.trim() === '') lines.pop();\n return lines;\n}\n\nexport function renderMcpResult(result: McpToolResultLike, options: McpToolResultOptions, theme: Theme): Component {\n const all = resultLines(result);\n const shown = options.expanded ? all : all.slice(0, COLLAPSED_RESULT_LINES);\n const body = shown.map((line) => theme.fg('toolOutput', line));\n\n if (options.isPartial) {\n body.push(theme.fg('warning', '◐') + theme.fg('dim', ' running'));\n } else if (options.isError) {\n body.push(theme.fg('error', '✗') + theme.fg('dim', ' failed'));\n } else if (!options.expanded && all.length > shown.length) {\n body.push(theme.fg('dim', '… ctrl+o'));\n } else if (body.length === 0) {\n body.push(theme.fg('success', '✓') + theme.fg('dim', ' done'));\n }\n\n return new McpToolText(body, { wrap: options.expanded, separator: true, trailingBlank: true }, theme);\n}\n","import { defineRoutedContribution, type WithRoot } from '@agimon-ai/doompi-core/extensionFile';\nimport type { PiPluginContext, PiToolCollection } from '@agimon-ai/doompi-core/piExtension';\n\nimport { createMcpToolCollection } from '../../../../../services/mcpToolCollection';\nimport { renderMcpCall, renderMcpResult } from '../../../../../tui/mcpToolRender';\nimport type { McpPiScope } from '../_lib/piRoot';\n\nexport default defineRoutedContribution(\n (context: WithRoot<PiPluginContext<unknown>, McpPiScope>): PiToolCollection =>\n createMcpToolCollection(context.root.session, (tool) => ({\n renderCall: (params, theme) => renderMcpCall(tool, params as Record<string, unknown>, theme),\n renderResult: (result, options, theme, execution) =>\n renderMcpResult(result, { ...options, isError: execution.isError }, theme),\n })),\n { cardinality: 'collection' },\n);\n","// Generated by @agimon-ai/doompi-build. Do not edit by hand.\nimport { definePiExtension, piToolContributions, type PiPluginContext, type PiPluginContributions } from '@agimon-ai/doompi-core/piExtension';\nimport { composeRootHooks } from '@agimon-ai/doompi-core/extensionFile';\n\nimport rootSession from '../src/extensions/workspaces/sessions/(backend)/root.cli';\nimport commandMcp from '../src/extensions/workspaces/sessions/(backend)/command/mcp.cli';\nimport resourceDoompiUseMcp from '../src/extensions/workspaces/sessions/(backend)/resource/doompi-use-mcp.cli';\nimport toolMcp from '../src/extensions/workspaces/sessions/(backend)/tool/mcp.cli';\n\ntype OptionsOf<T> = T extends (context: PiPluginContext<infer Options>) => unknown ? Options : never;\ntype InferredOptions = Exclude<OptionsOf<typeof rootSession> | OptionsOf<typeof commandMcp> | OptionsOf<typeof resourceDoompiUseMcp> | OptionsOf<typeof toolMcp>, undefined>;\ntype Intersect<Union> =\n (Union extends unknown ? (value: Union) => void : never) extends (value: infer Value) => void ? Value : never;\ntype ExtensionOptions = [InferredOptions] extends [never] ? undefined : Intersect<InferredOptions>;\n\ntype Factory<T, C> = (context: C) => T;\nconst at = <T, C>(value: T | Factory<T, C>, context: C): T =>\n typeof value === 'function' ? (value as Factory<T, C>)(context) : value;\ntype ManyFactory<T, C> = (context: C) => T | readonly T[];\nconst many = <T, C>(value: T | readonly T[] | ManyFactory<T, C>, context: C): readonly T[] => {\n const resolved = typeof value === 'function' ? (value as ManyFactory<T, C>)(context) : value;\n return Array.isArray(resolved) ? resolved : [resolved as T];\n};\n\nexport const extension = definePiExtension<ExtensionOptions>('@agimon-ai/doompi-mcp', async (context) => {\n const scopeSession = await rootSession(context);\n const contextSession = { ...context, root: scopeSession.value };\n return {\n ...composeRootHooks(scopeSession),\n get commands(): PiPluginContributions['commands'] { return [...many(commandMcp, contextSession)]; },\n get resources(): PiPluginContributions['resources'] { return [at(resourceDoompiUseMcp, contextSession)]; },\n ...piToolContributions('@agimon-ai/doompi-mcp', at(toolMcp, contextSession)),\n services: [...(scopeSession.services ?? [])],\n };\n});\n\nexport default extension;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"pi.mjs","names":["rootSession","commandMcp","resourceDoompiUseMcp","toolMcp"],"sources":["../../src/services/leader/index.ts","../../src/services/piRuntime/index.ts","../../src/extensions/workspaces/sessions/(backend)/_lib/piRoot.ts","../../src/extensions/workspaces/sessions/(backend)/root.cli.ts","../../src/extensions/workspaces/sessions/(backend)/command/mcp.cli.ts","../../src/extensions/workspaces/sessions/(backend)/resource/doompi-use-mcp.cli.ts","../../src/services/mcpToolCollection/index.ts","../../src/tui/mcpToolRender.ts","../../src/extensions/workspaces/sessions/(backend)/tool/mcp.cli.ts","../../generated/pi.ts"],"sourcesContent":["import type { DoomUiHubService } from '@agimon-ai/doompi-core/uiHub';\n\nimport { COMMAND_NAME } from '../../constants/mcp';\nimport {\n LEADER_BINDING_PREFIX,\n LEADER_DETAIL,\n LEADER_GROUP,\n LEADER_KEY,\n LEADER_LABEL,\n PACKAGE_SOURCE,\n} from '../../constants/piMcp';\n\nexport function registerLeaderContribution(hub: DoomUiHubService): () => void {\n const contribution = hub.registerLeader({\n source: PACKAGE_SOURCE,\n bindings: [\n {\n id: `${LEADER_BINDING_PREFIX}.open`,\n path: [LEADER_GROUP, { key: LEADER_KEY, label: LEADER_LABEL, detail: LEADER_DETAIL }],\n command: { name: COMMAND_NAME },\n },\n ],\n });\n return () => contribution.dispose();\n}\n","import path from 'node:path';\n\nimport { DOOM_CHILD_SESSION_MCP_TOOL_SERVICE } from '@agimon-ai/doompi-core/childSession';\nimport type { DoomCordisRuntimeService } from '@agimon-ai/doompi-core/cordisHost';\nimport { DOOM_CORDIS_SESSION_SERVICE, type DoomCordisSessionService } from '@agimon-ai/doompi-core/cordisHost';\nimport { DOOM_MCP_PROJECTION_SERVICE, readDoomMcpProjectionService } from '@agimon-ai/doompi-core/mcpProjection';\nimport { DOOM_MCP_STATUS_SERVICE, type DoomMcpStatusService } from '@agimon-ai/doompi-core/mcpStatus';\nimport {\n DOOM_MCP_TOOL_RESOLVER_SERVICE,\n type DoomMcpToolResolverService,\n} from '@agimon-ai/doompi-core/mcpToolResolver';\nimport { DOOM_TOOL_SURFACE_SERVICE, requireDoomToolSurface } from '@agimon-ai/doompi-core/toolSurface';\nimport { DOOM_UI_HUB_SERVICE, requireDoomUiHub } from '@agimon-ai/doompi-core/uiHub';\nimport type { Context } from '@deepseek-ai/cordis';\nimport type { ExtensionContext } from '@earendil-works/pi-coding-agent';\n\nimport { MCP_STATUS_KEY } from '../../constants/piMcp';\nimport { McpSession } from '../../services/mcpSession';\nimport { mcpSessionConfigFromProjection } from '../../services/projection';\nimport { readSessionConfig } from '../../services/sessionConfig';\nimport type { McpSessionConfig } from '../../types/mcpConfig';\nimport { formatMcpSessionAuthStatus, MCP_SESSION_AUTH_STATUS_KEY } from '../../types/webMcp';\nimport { registerLeaderContribution } from '../leader';\nimport { createMcpChildTool, createMcpSessionToolsService, MCP_SESSION_TOOLS_SERVICE } from '../mcpSessionTools';\n\nconst INFO = 'info';\nconst WARNING = 'warning';\n\nfunction failClosedSessionConfig(cwd: string): McpSessionConfig {\n return {\n enabled: false,\n repoRoot: cwd,\n stagingDirectory: path.join(cwd, '.doom', 'mcp-disabled'),\n sources: [],\n };\n}\n\nexport function createMcpPiRuntime(runtime: DoomCordisRuntimeService) {\n const mode = runtime.mode;\n let activeContext: ExtensionContext | undefined;\n let disposed = false;\n const session = new McpSession({\n onAuthorizationUrl: async (url, serverName, { openBrowser }) => {\n const context = activeContext;\n if (context?.mode === 'tui') {\n if (!openBrowser) return;\n try {\n const { default: open } = await import('open');\n await open(url.toString());\n } catch (error) {\n context.ui.notify(\n `Could not open the authorization page for ${serverName}: ${error instanceof Error ? error.message : String(error)}. Press a in the MCP overlay to retry.`,\n WARNING,\n );\n throw error;\n }\n return;\n }\n context?.ui?.notify(`Authorize ${serverName} by opening:\\n${url.toString()}`, INFO);\n },\n });\n\n return {\n session,\n services: [\n (cordis: Context) => {\n cordis.inject([DOOM_UI_HUB_SERVICE], (uiContext) => registerLeaderContribution(requireDoomUiHub(uiContext)));\n // The surface lives on the session fiber, so this resolves after install has\n // already registered the cached wrappers: binding is what first hides the ones\n // no server has confirmed.\n cordis.inject([DOOM_TOOL_SURFACE_SERVICE], (surfaceContext) =>\n session.bindToolSurface(requireDoomToolSurface(surfaceContext)),\n );\n cordis.inject([DOOM_CORDIS_SESSION_SERVICE], async (sessionContext) => {\n const hostSession = sessionContext.get(DOOM_CORDIS_SESSION_SERVICE) as DoomCordisSessionService;\n const context = hostSession.context;\n const expectedSessionId = hostSession.sessionId;\n let sessionActive = true;\n activeContext = context;\n // The legacy server-name status remains available to every UI. The compact\n // authorization status is browser-only so the TUI footer stays unchanged.\n const publishServerStatus = (): void => {\n const servers = session.getSnapshot().servers;\n const names = servers.map((server) => server.name).join(',');\n context.ui?.setStatus(MCP_STATUS_KEY, names);\n if (context.mode !== 'tui') {\n context.ui?.setStatus(MCP_SESSION_AUTH_STATUS_KEY, formatMcpSessionAuthStatus(session.getServers()));\n }\n };\n const stopPublishing = session.onChange(publishServerStatus);\n publishServerStatus();\n\n if (mode === 'standalone') {\n await session.reconfigure(readSessionConfig(process.env, context.cwd), context.cwd);\n } else {\n await session.reconfigure(failClosedSessionConfig(context.cwd));\n sessionContext.inject([DOOM_MCP_PROJECTION_SERVICE], async (projectionContext) => {\n const projection = readDoomMcpProjectionService(projectionContext);\n if (!projection || projection.sessionId !== expectedSessionId) {\n await session.reconfigure(failClosedSessionConfig(context.cwd));\n if (projection && sessionActive && !disposed) {\n context.ui?.notify(\n `The Doom MCP projection belongs to session \"${projection.sessionId}\", not \"${expectedSessionId}\"; MCP is disabled.`,\n WARNING,\n );\n }\n } else {\n const snapshot = projection.getSnapshot();\n await session.reconfigure(\n mcpSessionConfigFromProjection(snapshot, context.cwd),\n context.cwd,\n snapshot.repoRoot,\n );\n }\n return async () => {\n if (sessionActive && !disposed) await session.reconfigure(failClosedSessionConfig(context.cwd));\n };\n });\n }\n\n const status: DoomMcpStatusService = Object.freeze({\n generation: `${hostSession.generation}:mcp-status`,\n getSnapshot: () => session.getSnapshot(),\n onChange: (listener: () => void) => session.onChange(listener),\n });\n const toolResolver: DoomMcpToolResolverService = Object.freeze({\n generation: `${hostSession.generation}:mcp-tool-resolver`,\n resolve: (selectors: readonly string[]) => session.resolveToolSelectors(selectors),\n });\n const sessionTools = createMcpSessionToolsService(session, `${hostSession.generation}:mcp-tools`);\n const childTool = createMcpChildTool(async (parameters, signal) => {\n if (!sessionActive || disposed) throw new Error('The parent MCP session is no longer available.');\n const tool = sessionTools\n .snapshot()\n .find(\n (candidate) => candidate.serverName === parameters.server && candidate.toolName === parameters.tool,\n );\n if (!tool)\n throw new Error(\n `MCP tool ${parameters.server}/${parameters.tool} is not available in the current session configuration.`,\n );\n return sessionTools.invoke(tool.piName, parameters.arguments ?? {}, signal);\n });\n sessionContext.plugin((providerContext) => {\n providerContext.provide(DOOM_MCP_STATUS_SERVICE, status);\n providerContext.provide(DOOM_MCP_TOOL_RESOLVER_SERVICE, toolResolver);\n providerContext.provide(MCP_SESSION_TOOLS_SERVICE, sessionTools);\n providerContext.provide(DOOM_CHILD_SESSION_MCP_TOOL_SERVICE, childTool);\n });\n for (const diagnostic of session.getDiagnostics()) context.ui?.notify(diagnostic, WARNING);\n return async () => {\n sessionActive = false;\n stopPublishing();\n context.ui?.setStatus(MCP_STATUS_KEY, undefined);\n if (context.mode !== 'tui') context.ui?.setStatus(MCP_SESSION_AUTH_STATUS_KEY, undefined);\n if (activeContext === context) activeContext = undefined;\n if (!disposed) await session.reconfigure(failClosedSessionConfig(context.cwd));\n };\n });\n },\n ],\n async onDispose() {\n disposed = true;\n activeContext = undefined;\n await session.dispose();\n },\n };\n}\n","import type { PiPluginContext } from '@agimon-ai/doompi-core/piExtension';\n\nimport { createMcpPiRuntime } from '../../../../../services/piRuntime';\nexport const createMcpPiRoot = ({ runtime }: PiPluginContext) => {\n if (!runtime) throw new Error('MCP requires the Cordis runtime mode.');\n const state = createMcpPiRuntime(runtime);\n return { value: state, services: state.services, onDispose: () => state.onDispose() };\n};\nexport type McpPiScope = Awaited<ReturnType<typeof createMcpPiRoot>>['value'];\n","import { defineRoot } from '@agimon-ai/doompi-core/extensionFile';\n\nimport { createMcpPiRoot } from './_lib/piRoot';\n\nexport default defineRoot(createMcpPiRoot);\n","import { defineRoutedContribution, type WithRoot } from '@agimon-ai/doompi-core/extensionFile';\nimport type { PiPluginContext } from '@agimon-ai/doompi-core/piExtension';\n\nimport { createMcpCommand } from '../../../../../services/mcpCommand';\nimport type { McpPiScope } from '../_lib/piRoot';\nexport default defineRoutedContribution(\n (context: WithRoot<PiPluginContext<unknown>, McpPiScope>) =>\n [\n createMcpCommand(context.root.session, {\n openOverlay: async (ctx) => {\n const { openMcpOverlay } = await import('../../../../../tui/mcpOverlay');\n return openMcpOverlay(ctx, context.root.session);\n },\n }),\n ] as const,\n { cardinality: 'many' },\n);\n","import { defineResource } from '@agimon-ai/doompi-core/extensionFile';\n\nexport default defineResource({\n source: '@agimon-ai/doompi-mcp',\n moduleUrl: import.meta.url,\n skills: [\n {\n name: 'doompi-use-mcp',\n description:\n 'Use Doom Pi MCP to inspect domain-scoped servers, authenticate, reload configuration, and troubleshoot tool availability.',\n },\n ],\n});\n","import type { PiToolCollection, PiToolDeclaration } from '@agimon-ai/doompi-core/piExtension';\n\nimport type { CatalogTool } from '../../services/mcpCatalog';\nimport type { McpSession } from '../../services/mcpSession';\nimport { createMcpTool, type McpToolRenderers } from '../mcpTools';\nexport function createMcpToolCollection(\n session: McpSession,\n renderers: (tool: CatalogTool) => McpToolRenderers = () => ({}),\n): PiToolCollection {\n const declarations = new Map<CatalogTool, PiToolDeclaration>();\n return {\n snapshot: (): readonly PiToolDeclaration[] =>\n session.toolDefinitions().map((tool) => {\n let declaration = declarations.get(tool);\n if (!declaration) {\n declaration = createMcpTool(\n session.getClientManager,\n tool,\n (candidate) => session.isToolAvailable(candidate),\n renderers(tool),\n );\n declarations.set(tool, declaration);\n }\n return declaration;\n }),\n subscribe: (listener: () => void) => session.onChange(listener),\n };\n}\n","import { DoomToolCall, renderToolHeading } from '@agimon-ai/doompi-ui/toolChrome';\nimport type { Theme } from '@earendil-works/pi-coding-agent';\nimport { type Component, truncateToWidth, wrapTextWithAnsi } from '@earendil-works/pi-tui';\n\nconst COLLAPSED_RESULT_LINES = 12;\nconst MAX_ARGUMENTS = 3;\nconst ELLIPSIS = '…';\n\ninterface McpToolTextLayout {\n wrap: boolean;\n separator: boolean;\n trailingBlank: boolean;\n}\n\n/** Bash-compatible width budget, horizontal inset, and structural result divider. */\nclass McpToolText implements Component {\n constructor(\n private readonly lines: readonly string[],\n private readonly layout: McpToolTextLayout,\n private readonly theme: Theme,\n ) {}\n\n render(width: number): string[] {\n if (width <= 0) return [];\n const contentWidth = Math.max(1, width - 2);\n const rendered = this.layout.wrap\n ? this.lines.flatMap((line) => wrapTextWithAnsi(line, contentWidth))\n : this.lines.map((line) => truncateToWidth(line, contentWidth, ELLIPSIS));\n if (this.layout.separator) {\n rendered.unshift(this.theme.fg('borderMuted', '─'.repeat(contentWidth)));\n }\n const padded = rendered.map((line) => ` ${line}`);\n if (this.layout.trailingBlank) padded.push('');\n return padded;\n }\n\n invalidate(): void {\n // Content is immutable and reflows from the current width on every render.\n }\n}\n\nfunction argumentValue(value: unknown): string {\n if (typeof value === 'string') return value;\n if (typeof value === 'number' || typeof value === 'boolean') return String(value);\n if (value === null) return 'null';\n if (Array.isArray(value)) return `[${value.length}]`;\n return '{…}';\n}\n\nfunction argumentSummary(params: Record<string, unknown>): string {\n const entries = Object.entries(params);\n const shown = entries.slice(0, MAX_ARGUMENTS).map(([key, value]) => `${key}=${argumentValue(value)}`);\n if (entries.length > shown.length) shown.push(`+${entries.length - shown.length}`);\n return shown.join(' · ');\n}\n\nexport interface McpToolIdentity {\n serverName: string;\n toolName: string;\n}\n\nexport function renderMcpCall(tool: McpToolIdentity, params: Record<string, unknown>, theme: Theme): Component {\n const heading = renderToolHeading('mcp', tool.serverName, theme, 'muted');\n const toolName = theme.fg('accent', tool.toolName);\n const argumentsText = argumentSummary(params);\n const text = `${heading}${theme.fg('muted', ' / ')}${toolName}${\n argumentsText ? ` ${theme.fg('muted', `· ${argumentsText}`)}` : ''\n }`;\n return new DoomToolCall(text);\n}\n\nexport interface McpToolResultLike {\n content?: Array<{ type: string; text?: string }>;\n}\n\nexport interface McpToolResultOptions {\n expanded: boolean;\n isPartial: boolean;\n isError: boolean;\n}\n\nfunction resultLines(result: McpToolResultLike): string[] {\n const text = (result.content ?? []).map((block) => block.text ?? '').join('');\n const lines = text.split('\\n');\n while (lines.length > 0 && lines.at(-1)?.trim() === '') lines.pop();\n return lines;\n}\n\nexport function renderMcpResult(result: McpToolResultLike, options: McpToolResultOptions, theme: Theme): Component {\n const all = resultLines(result);\n const shown = options.expanded ? all : all.slice(0, COLLAPSED_RESULT_LINES);\n const body = shown.map((line) => theme.fg('toolOutput', line));\n\n if (options.isPartial) {\n body.push(theme.fg('warning', '◐') + theme.fg('dim', ' running'));\n } else if (options.isError) {\n body.push(theme.fg('error', '✗') + theme.fg('dim', ' failed'));\n } else if (!options.expanded && all.length > shown.length) {\n body.push(theme.fg('dim', '… ctrl+o'));\n } else if (body.length === 0) {\n body.push(theme.fg('success', '✓') + theme.fg('dim', ' done'));\n }\n\n return new McpToolText(body, { wrap: options.expanded, separator: true, trailingBlank: true }, theme);\n}\n","import { defineRoutedContribution, type WithRoot } from '@agimon-ai/doompi-core/extensionFile';\nimport type { PiPluginContext, PiToolCollection } from '@agimon-ai/doompi-core/piExtension';\n\nimport { createMcpToolCollection } from '../../../../../services/mcpToolCollection';\nimport { renderMcpCall, renderMcpResult } from '../../../../../tui/mcpToolRender';\nimport type { McpPiScope } from '../_lib/piRoot';\n\nexport default defineRoutedContribution(\n (context: WithRoot<PiPluginContext<unknown>, McpPiScope>): PiToolCollection =>\n createMcpToolCollection(context.root.session, (tool) => ({\n renderCall: (params, theme) => renderMcpCall(tool, params as Record<string, unknown>, theme),\n renderResult: (result, options, theme, execution) =>\n renderMcpResult(result, { ...options, isError: execution.isError }, theme),\n })),\n { cardinality: 'collection' },\n);\n","// Generated by @agimon-ai/doompi-build. Do not edit by hand.\nimport { definePiExtension, piToolContributions, type PiPluginContext, type PiPluginContributions } from '@agimon-ai/doompi-core/piExtension';\nimport { composeRootHooks } from '@agimon-ai/doompi-core/extensionFile';\n\nimport rootSession from '../src/extensions/workspaces/sessions/(backend)/root.cli';\nimport commandMcp from '../src/extensions/workspaces/sessions/(backend)/command/mcp.cli';\nimport resourceDoompiUseMcp from '../src/extensions/workspaces/sessions/(backend)/resource/doompi-use-mcp.cli';\nimport toolMcp from '../src/extensions/workspaces/sessions/(backend)/tool/mcp.cli';\n\ntype OptionsOf<T> = T extends (context: PiPluginContext<infer Options>) => unknown ? Options : never;\ntype InferredOptions = Exclude<OptionsOf<typeof rootSession> | OptionsOf<typeof commandMcp> | OptionsOf<typeof resourceDoompiUseMcp> | OptionsOf<typeof toolMcp>, undefined>;\ntype Intersect<Union> =\n (Union extends unknown ? (value: Union) => void : never) extends (value: infer Value) => void ? Value : never;\ntype ExtensionOptions = [InferredOptions] extends [never] ? undefined : Intersect<InferredOptions>;\n\ntype Factory<T, C> = (context: C) => T;\nconst at = <T, C>(value: T | Factory<T, C>, context: C): T =>\n typeof value === 'function' ? (value as Factory<T, C>)(context) : value;\ntype ManyFactory<T, C> = (context: C) => T | readonly T[];\nconst many = <T, C>(value: T | readonly T[] | ManyFactory<T, C>, context: C): readonly T[] => {\n const resolved = typeof value === 'function' ? (value as ManyFactory<T, C>)(context) : value;\n return Array.isArray(resolved) ? resolved : [resolved as T];\n};\n\nexport const extension = definePiExtension<ExtensionOptions>('@agimon-ai/doompi-mcp', async (context) => {\n const scopeSession = await rootSession(context);\n const contextSession = { ...context, root: scopeSession.value };\n return {\n ...composeRootHooks(scopeSession),\n get commands(): PiPluginContributions['commands'] { return [...many(commandMcp, contextSession)]; },\n get resources(): PiPluginContributions['resources'] { return [at(resourceDoompiUseMcp, contextSession)]; },\n ...piToolContributions('@agimon-ai/doompi-mcp', at(toolMcp, contextSession)),\n services: [...(scopeSession.services ?? [])],\n };\n});\n\nexport default extension;\n"],"mappings":"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"}
|
|
@@ -2,22 +2,26 @@ Object.defineProperties(exports, {
|
|
|
2
2
|
__esModule: { value: true },
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
const
|
|
5
|
+
const require_rolldown_runtime = require("../rolldown-runtime-C0BPl7ul.cjs");
|
|
6
|
+
const require_mcpCatalog = require("../mcpCatalog-Bnkul3t_.cjs");
|
|
7
|
+
const require_projection = require("../projection-w3XxXmVi.cjs");
|
|
8
|
+
const require_mcpCommand = require("../mcpCommand-BARs6Y1N.cjs");
|
|
9
|
+
const require_keyringTokenStore = require("../keyringTokenStore-LBsDb_eC.cjs");
|
|
9
10
|
let node_crypto = require("node:crypto");
|
|
10
11
|
let node_fs = require("node:fs");
|
|
11
|
-
node_fs =
|
|
12
|
+
node_fs = require_rolldown_runtime.__toESM(node_fs, 1);
|
|
12
13
|
let node_path = require("node:path");
|
|
13
|
-
node_path =
|
|
14
|
+
node_path = require_rolldown_runtime.__toESM(node_path, 1);
|
|
14
15
|
let node_os = require("node:os");
|
|
15
|
-
node_os =
|
|
16
|
+
node_os = require_rolldown_runtime.__toESM(node_os, 1);
|
|
17
|
+
let _agimon_ai_doompi_core_mcpProjection = require("@agimon-ai/doompi-core/mcpProjection");
|
|
16
18
|
let _agimon_ai_doompi_core_extensionFile = require("@agimon-ai/doompi-core/extensionFile");
|
|
17
19
|
let _agimon_ai_doompi_core_childSession = require("@agimon-ai/doompi-core/childSession");
|
|
18
20
|
let _agimon_ai_doompi_core_mcpStatus = require("@agimon-ai/doompi-core/mcpStatus");
|
|
19
21
|
let _agimon_ai_doompi_core_mcpToolResolver = require("@agimon-ai/doompi-core/mcpToolResolver");
|
|
20
22
|
let _agimon_ai_doompi_core_serverFacet = require("@agimon-ai/doompi-core/serverFacet");
|
|
23
|
+
let _agimon_ai_doompi_core_headless = require("@agimon-ai/doompi-core/headless");
|
|
24
|
+
let _agimon_ai_doompi_config_harnessStore = require("@agimon-ai/doompi-config/harnessStore");
|
|
21
25
|
let _agimon_ai_doompi_core_web = require("@agimon-ai/doompi-core/web");
|
|
22
26
|
//#region src/services/mcpHeadlessTools/index.ts
|
|
23
27
|
const MCP_HEADLESS_TOOLS_SERVICE = "doom/mcp-headless-tools";
|
|
@@ -30,8 +34,23 @@ function mountMcpHeadlessTools(tools) {
|
|
|
30
34
|
}
|
|
31
35
|
//#endregion
|
|
32
36
|
//#region src/services/serverRuntime/index.ts
|
|
33
|
-
function
|
|
37
|
+
function sessionConfiguration(execution, workspaceRoot) {
|
|
38
|
+
if (workspaceRoot !== void 0) {
|
|
39
|
+
const loaded = (0, _agimon_ai_doompi_config_harnessStore.loadHarnessState)({ ...execution.environment });
|
|
40
|
+
const projection = loaded.state.mcpProjection;
|
|
41
|
+
if (loaded.filePath && loaded.state.root === workspaceRoot && execution.repoRoot === workspaceRoot && loaded.state.mcp && loaded.state.majorMode === execution.selection.majorMode && JSON.stringify(loaded.state.domains) === JSON.stringify(execution.selection.domains) && JSON.stringify(loaded.state.layers) === JSON.stringify(execution.selection.activeLayers) && (0, _agimon_ai_doompi_core_mcpProjection.isDoomMcpProjection)(projection) && projection.repoRoot === workspaceRoot) return require_projection.mcpSessionConfigFromProjection(projection, execution.cwd);
|
|
42
|
+
return {
|
|
43
|
+
enabled: false,
|
|
44
|
+
repoRoot: execution.cwd,
|
|
45
|
+
stagingDirectory: node_path.default.join(execution.cwd, ".doom", "mcp-disabled"),
|
|
46
|
+
sources: []
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
return require_mcpCatalog.readSessionConfig(execution.environment, execution.cwd);
|
|
50
|
+
}
|
|
51
|
+
function createMcpServerRuntime(environment = {}, workspaceRoot) {
|
|
34
52
|
let active;
|
|
53
|
+
let staleSelection = false;
|
|
35
54
|
const authorizing = /* @__PURE__ */ new Map();
|
|
36
55
|
const session = new require_mcpCommand.McpSession({
|
|
37
56
|
environment: { ...environment },
|
|
@@ -47,6 +66,7 @@ function createMcpServerRuntime(environment = {}) {
|
|
|
47
66
|
name: "doompi-mcp-runtime",
|
|
48
67
|
async start(execution) {
|
|
49
68
|
active = execution;
|
|
69
|
+
staleSelection = false;
|
|
50
70
|
const reported = /* @__PURE__ */ new Set();
|
|
51
71
|
const publish = () => {
|
|
52
72
|
execution.client.setStatus(require_mcpCommand.MCP_STATUS_KEY, session.getServers().map((server) => server.name).join(","));
|
|
@@ -63,7 +83,7 @@ function createMcpServerRuntime(environment = {}) {
|
|
|
63
83
|
};
|
|
64
84
|
const stopPublishing = session.onChange(publish);
|
|
65
85
|
try {
|
|
66
|
-
await session.reconfigure(
|
|
86
|
+
await session.reconfigure(sessionConfiguration(execution, workspaceRoot), execution.cwd, execution.repoRoot);
|
|
67
87
|
publish();
|
|
68
88
|
} catch (error) {
|
|
69
89
|
await execution.client.notify({
|
|
@@ -76,6 +96,7 @@ function createMcpServerRuntime(environment = {}) {
|
|
|
76
96
|
stopPublishing();
|
|
77
97
|
if (active !== execution) return;
|
|
78
98
|
active = void 0;
|
|
99
|
+
staleSelection = false;
|
|
79
100
|
authorizing.clear();
|
|
80
101
|
try {
|
|
81
102
|
await session.dispose();
|
|
@@ -93,6 +114,7 @@ function createMcpServerRuntime(environment = {}) {
|
|
|
93
114
|
};
|
|
94
115
|
const invoke = async (parameters, signal) => {
|
|
95
116
|
if (!active) throw new Error("The MCP runtime has not started yet.");
|
|
117
|
+
if (staleSelection) throw new Error("The MCP projection is stale for the current selection.");
|
|
96
118
|
const selected = session.activeToolDefinitions().find((candidate) => candidate.serverName === parameters.server && candidate.toolName === parameters.tool);
|
|
97
119
|
if (!selected) throw new Error(`MCP tool ${parameters.server}/${parameters.tool} is not available in this session.`);
|
|
98
120
|
return session.invokeTool(selected.piName, parameters.arguments ?? {}, signal);
|
|
@@ -118,6 +140,7 @@ function createMcpServerRuntime(environment = {}) {
|
|
|
118
140
|
return;
|
|
119
141
|
}
|
|
120
142
|
if (!active) throw new Error("The MCP runtime has not started yet.");
|
|
143
|
+
if (staleSelection) throw new Error("The MCP projection is stale for the current selection.");
|
|
121
144
|
if (subcommand === "auth" || subcommand === "disconnect") {
|
|
122
145
|
if (!serverName) throw new Error(`Name the server, for example /mcp ${subcommand} <server>.`);
|
|
123
146
|
const server = session.getServers().find((candidate) => candidate.name === serverName);
|
|
@@ -158,7 +181,7 @@ function createMcpServerRuntime(environment = {}) {
|
|
|
158
181
|
stagingDirectory: execution.cwd
|
|
159
182
|
});
|
|
160
183
|
}
|
|
161
|
-
await session.reconfigure(
|
|
184
|
+
await session.reconfigure(sessionConfiguration(execution, workspaceRoot), execution.cwd, execution.repoRoot);
|
|
162
185
|
await notify("Reconnecting MCP servers.");
|
|
163
186
|
return;
|
|
164
187
|
}
|
|
@@ -188,16 +211,32 @@ function createMcpServerRuntime(environment = {}) {
|
|
|
188
211
|
}
|
|
189
212
|
}
|
|
190
213
|
}],
|
|
191
|
-
childTool
|
|
214
|
+
childTool,
|
|
215
|
+
async onSelectionChange(selection) {
|
|
216
|
+
if (!active || workspaceRoot === void 0) return;
|
|
217
|
+
const initial = active.selection;
|
|
218
|
+
if (!initial || JSON.stringify(initial.domains) === JSON.stringify(selection.domains)) return;
|
|
219
|
+
staleSelection = true;
|
|
220
|
+
authorizing.clear();
|
|
221
|
+
await session.reconfigure({
|
|
222
|
+
enabled: false,
|
|
223
|
+
repoRoot: active.cwd,
|
|
224
|
+
stagingDirectory: node_path.default.join(active.cwd, ".doom", "mcp-disabled"),
|
|
225
|
+
sources: []
|
|
226
|
+
});
|
|
227
|
+
}
|
|
192
228
|
};
|
|
193
229
|
}
|
|
194
230
|
//#endregion
|
|
195
231
|
//#region src/extensions/workspaces/sessions/(backend)/_lib/serverRoot.ts
|
|
196
232
|
const createMcpServerRoot = (context) => {
|
|
197
|
-
const runtime = createMcpServerRuntime(context?.agent?.context?.environment);
|
|
233
|
+
const runtime = createMcpServerRuntime(context?.agent?.context?.environment, context?.host.context.workspaceRoot);
|
|
198
234
|
const generation = `${context?.agent?.context?.sessionId ?? crypto.randomUUID()}:mcp-server`;
|
|
199
235
|
const { session } = runtime;
|
|
200
236
|
const mountSession = (cordis) => {
|
|
237
|
+
cordis.inject([_agimon_ai_doompi_core_headless.DOOM_HEADLESS_HOST_SERVICE], (hostContext) => {
|
|
238
|
+
return hostContext.get(_agimon_ai_doompi_core_headless.DOOM_HEADLESS_HOST_SERVICE).subscribeSelection((selection) => runtime.onSelectionChange(selection));
|
|
239
|
+
});
|
|
201
240
|
cordis.plugin((provider) => {
|
|
202
241
|
provider.provide(_agimon_ai_doompi_core_mcpStatus.DOOM_MCP_STATUS_SERVICE, {
|
|
203
242
|
generation,
|
|
@@ -418,6 +457,8 @@ var McpSettingsManager = class {
|
|
|
418
457
|
try {
|
|
419
458
|
const handle = await owner.start({
|
|
420
459
|
configSources: prepared.configSources,
|
|
460
|
+
workspaceRoot: repositoryRoot,
|
|
461
|
+
executionCwd: repositoryRoot,
|
|
421
462
|
tokenStore: await this.tokenStore(),
|
|
422
463
|
onAuthorizationUrl: (_url, serverName) => {
|
|
423
464
|
liveStates.set(serverName, {
|
|
@@ -479,7 +520,7 @@ var McpSettingsManager = class {
|
|
|
479
520
|
};
|
|
480
521
|
this.flows.set(flow.id, flow);
|
|
481
522
|
this.busyRepositories.add(repositoryId);
|
|
482
|
-
this.runAuthorization(flow, prepared.configSources, redirect);
|
|
523
|
+
this.runAuthorization(flow, prepared.configSources, repositoryRoot, redirect);
|
|
483
524
|
return publicFlow(flow);
|
|
484
525
|
}
|
|
485
526
|
getAuthorization(flowId, repositoryId) {
|
|
@@ -496,7 +537,7 @@ var McpSettingsManager = class {
|
|
|
496
537
|
}
|
|
497
538
|
return publicFlow(flow);
|
|
498
539
|
}
|
|
499
|
-
async runAuthorization(flow, sources, redirect) {
|
|
540
|
+
async runAuthorization(flow, sources, repositoryRoot, redirect) {
|
|
500
541
|
const owner = new require_mcpCatalog.McpRuntimeOwner();
|
|
501
542
|
flow.owner = owner;
|
|
502
543
|
flow.timeout = setTimeout(() => {
|
|
@@ -508,6 +549,8 @@ var McpSettingsManager = class {
|
|
|
508
549
|
try {
|
|
509
550
|
const handle = await owner.start({
|
|
510
551
|
configSources: sources,
|
|
552
|
+
workspaceRoot: repositoryRoot,
|
|
553
|
+
executionCwd: repositoryRoot,
|
|
511
554
|
tokenStore: await this.tokenStore(),
|
|
512
555
|
...redirect ? { callbackServer: require_mcpCatalog.hubCallbackSink(redirect) } : {},
|
|
513
556
|
onAuthorizationUrl: (url, serverName) => {
|