@agimon-ai/doompi-core 0.0.1-alpha.79 → 0.0.1-alpha.80
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/mcp-facet.cjs +1 -0
- package/dist/mcp-facet.d.cts +2 -2
- package/dist/mcp-facet.d.mts +2 -2
- package/dist/mcp-facet.mjs +2 -2
- package/dist/schemas/headless.cjs.map +1 -1
- package/dist/schemas/headless.d.cts +17 -2
- package/dist/schemas/headless.d.cts.map +1 -1
- package/dist/schemas/headless.d.mts +17 -2
- package/dist/schemas/headless.d.mts.map +1 -1
- package/dist/schemas/headless.mjs.map +1 -1
- package/dist/schemas/mcpFacet.cjs +5 -0
- package/dist/schemas/mcpFacet.cjs.map +1 -1
- package/dist/schemas/mcpFacet.d.cts +24 -0
- package/dist/schemas/mcpFacet.d.cts.map +1 -1
- package/dist/schemas/mcpFacet.d.mts +24 -0
- package/dist/schemas/mcpFacet.d.mts.map +1 -1
- package/dist/schemas/mcpFacet.mjs +5 -1
- package/dist/schemas/mcpFacet.mjs.map +1 -1
- package/dist/server/sessionMcpHandler.cjs +33 -9
- package/dist/server/sessionMcpHandler.cjs.map +1 -1
- package/dist/server/sessionMcpHandler.d.cts.map +1 -1
- package/dist/server/sessionMcpHandler.d.mts.map +1 -1
- package/dist/server/sessionMcpHandler.mjs +33 -9
- package/dist/server/sessionMcpHandler.mjs.map +1 -1
- package/dist/session-mcp.d.cts +2 -2
- package/dist/session-mcp.d.mts +2 -2
- package/dist/systems/main/adapters/headlessHost.cjs +6 -3
- package/dist/systems/main/adapters/headlessHost.cjs.map +1 -1
- package/dist/systems/main/adapters/headlessHost.d.cts +2 -0
- package/dist/systems/main/adapters/headlessHost.d.cts.map +1 -1
- package/dist/systems/main/adapters/headlessHost.d.mts +2 -0
- package/dist/systems/main/adapters/headlessHost.d.mts.map +1 -1
- package/dist/systems/main/adapters/headlessHost.mjs +6 -3
- package/dist/systems/main/adapters/headlessHost.mjs.map +1 -1
- package/dist/systems/main/adapters/headlessSessionHost.cjs +49 -4
- package/dist/systems/main/adapters/headlessSessionHost.cjs.map +1 -1
- package/dist/systems/main/adapters/headlessSessionHost.d.cts.map +1 -1
- package/dist/systems/main/adapters/headlessSessionHost.d.mts.map +1 -1
- package/dist/systems/main/adapters/headlessSessionHost.mjs +49 -4
- package/dist/systems/main/adapters/headlessSessionHost.mjs.map +1 -1
- package/dist/types/server/sessionToolSurface.d.cts +5 -0
- package/dist/types/server/sessionToolSurface.d.cts.map +1 -1
- package/dist/types/server/sessionToolSurface.d.mts +5 -0
- package/dist/types/server/sessionToolSurface.d.mts.map +1 -1
- package/package.json +11 -11
package/dist/mcp-facet.cjs
CHANGED
|
@@ -7,5 +7,6 @@ exports.DOOM_MCP_BUNDLE_VERSION = require_mcpBundle.DOOM_MCP_BUNDLE_VERSION;
|
|
|
7
7
|
exports.defineMcpPlugin = require_mcpFacet.defineMcpPlugin;
|
|
8
8
|
exports.defineMcpSkill = require_mcpFacet.defineMcpSkill;
|
|
9
9
|
exports.defineMcpTool = require_mcpFacet.defineMcpTool;
|
|
10
|
+
exports.defineMcpUiResource = require_mcpFacet.defineMcpUiResource;
|
|
10
11
|
exports.loadMcpBundle = require_mcpBundleLoader.loadMcpBundle;
|
|
11
12
|
exports.parseDoomMcpBundle = require_mcpBundle.parseDoomMcpBundle;
|
package/dist/mcp-facet.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DoomMcpContextSnapshot, DoomMcpPluginContext, DoomMcpPluginDefinition, DoomMcpServiceScope, DoomMcpSessionPlugin, DoomMcpSkill, defineMcpPlugin, defineMcpSkill, defineMcpTool } from "./schemas/mcpFacet.cjs";
|
|
1
|
+
import { DoomMcpContextSnapshot, DoomMcpPluginContext, DoomMcpPluginDefinition, DoomMcpServiceScope, DoomMcpSessionPlugin, DoomMcpSkill, DoomMcpUiResource, defineMcpPlugin, defineMcpSkill, defineMcpTool, defineMcpUiResource } from "./schemas/mcpFacet.cjs";
|
|
2
2
|
import { DOOM_MCP_BUNDLE_FILE, DOOM_MCP_BUNDLE_VERSION, DoomMcpBundle, DoomMcpBundleEntry, parseDoomMcpBundle } from "./schemas/mcpBundle.cjs";
|
|
3
3
|
import { LoadMcpBundleOptions, LoadedMcpBundle, LoadedMcpPlugin, loadMcpBundle } from "./server/mcpBundleLoader.cjs";
|
|
4
|
-
export { DOOM_MCP_BUNDLE_FILE, DOOM_MCP_BUNDLE_VERSION, type DoomMcpBundle, type DoomMcpBundleEntry, type DoomMcpContextSnapshot, type DoomMcpPluginContext, type DoomMcpPluginDefinition, type DoomMcpServiceScope, type DoomMcpSessionPlugin, type DoomMcpSkill, type LoadMcpBundleOptions, type LoadedMcpBundle, type LoadedMcpPlugin, defineMcpPlugin, defineMcpSkill, defineMcpTool, loadMcpBundle, parseDoomMcpBundle };
|
|
4
|
+
export { DOOM_MCP_BUNDLE_FILE, DOOM_MCP_BUNDLE_VERSION, type DoomMcpBundle, type DoomMcpBundleEntry, type DoomMcpContextSnapshot, type DoomMcpPluginContext, type DoomMcpPluginDefinition, type DoomMcpServiceScope, type DoomMcpSessionPlugin, type DoomMcpSkill, type DoomMcpUiResource, type LoadMcpBundleOptions, type LoadedMcpBundle, type LoadedMcpPlugin, defineMcpPlugin, defineMcpSkill, defineMcpTool, defineMcpUiResource, loadMcpBundle, parseDoomMcpBundle };
|
package/dist/mcp-facet.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DoomMcpContextSnapshot, DoomMcpPluginContext, DoomMcpPluginDefinition, DoomMcpServiceScope, DoomMcpSessionPlugin, DoomMcpSkill, defineMcpPlugin, defineMcpSkill, defineMcpTool } from "./schemas/mcpFacet.mjs";
|
|
1
|
+
import { DoomMcpContextSnapshot, DoomMcpPluginContext, DoomMcpPluginDefinition, DoomMcpServiceScope, DoomMcpSessionPlugin, DoomMcpSkill, DoomMcpUiResource, defineMcpPlugin, defineMcpSkill, defineMcpTool, defineMcpUiResource } from "./schemas/mcpFacet.mjs";
|
|
2
2
|
import { DOOM_MCP_BUNDLE_FILE, DOOM_MCP_BUNDLE_VERSION, DoomMcpBundle, DoomMcpBundleEntry, parseDoomMcpBundle } from "./schemas/mcpBundle.mjs";
|
|
3
3
|
import { LoadMcpBundleOptions, LoadedMcpBundle, LoadedMcpPlugin, loadMcpBundle } from "./server/mcpBundleLoader.mjs";
|
|
4
|
-
export { DOOM_MCP_BUNDLE_FILE, DOOM_MCP_BUNDLE_VERSION, type DoomMcpBundle, type DoomMcpBundleEntry, type DoomMcpContextSnapshot, type DoomMcpPluginContext, type DoomMcpPluginDefinition, type DoomMcpServiceScope, type DoomMcpSessionPlugin, type DoomMcpSkill, type LoadMcpBundleOptions, type LoadedMcpBundle, type LoadedMcpPlugin, defineMcpPlugin, defineMcpSkill, defineMcpTool, loadMcpBundle, parseDoomMcpBundle };
|
|
4
|
+
export { DOOM_MCP_BUNDLE_FILE, DOOM_MCP_BUNDLE_VERSION, type DoomMcpBundle, type DoomMcpBundleEntry, type DoomMcpContextSnapshot, type DoomMcpPluginContext, type DoomMcpPluginDefinition, type DoomMcpServiceScope, type DoomMcpSessionPlugin, type DoomMcpSkill, type DoomMcpUiResource, type LoadMcpBundleOptions, type LoadedMcpBundle, type LoadedMcpPlugin, defineMcpPlugin, defineMcpSkill, defineMcpTool, defineMcpUiResource, loadMcpBundle, parseDoomMcpBundle };
|
package/dist/mcp-facet.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { defineMcpPlugin, defineMcpSkill, defineMcpTool } from "./schemas/mcpFacet.mjs";
|
|
1
|
+
import { defineMcpPlugin, defineMcpSkill, defineMcpTool, defineMcpUiResource } from "./schemas/mcpFacet.mjs";
|
|
2
2
|
import { DOOM_MCP_BUNDLE_FILE, DOOM_MCP_BUNDLE_VERSION, parseDoomMcpBundle } from "./schemas/mcpBundle.mjs";
|
|
3
3
|
import { loadMcpBundle } from "./server/mcpBundleLoader.mjs";
|
|
4
|
-
export { DOOM_MCP_BUNDLE_FILE, DOOM_MCP_BUNDLE_VERSION, defineMcpPlugin, defineMcpSkill, defineMcpTool, loadMcpBundle, parseDoomMcpBundle };
|
|
4
|
+
export { DOOM_MCP_BUNDLE_FILE, DOOM_MCP_BUNDLE_VERSION, defineMcpPlugin, defineMcpSkill, defineMcpTool, defineMcpUiResource, loadMcpBundle, parseDoomMcpBundle };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"headless.cjs","names":[],"sources":["../../src/schemas/headless.ts"],"sourcesContent":["import type { Context } from '@deepseek-ai/cordis';\nimport type { ThinkingLevel } from '@earendil-works/pi-agent-core';\nimport type { Tool } from '@modelcontextprotocol/sdk/types.js';\nimport type { Static, TSchema } from 'typebox';\n\nimport type { DoomNotificationRequest } from './notification';\nimport type { DoomServerBundleEntry } from './serverBundle';\n\n/** Session-only contributions. This is not a Pi ExtensionAPI or a TUI adapter. */\nexport const DOOM_HEADLESS_HOST_SERVICE = 'doom/headless-host';\nexport const DOOM_HEADLESS_OWNER = Symbol.for('doom/headless-owner');\n\nexport interface DoomHeadlessSelection {\n readonly majorMode: string;\n readonly activeLayers: readonly string[];\n readonly domains: readonly string[];\n readonly profile?: string;\n /** Feature-owned activation sets, keyed by the contributing capability. */\n readonly state?: Readonly<Record<string, readonly string[]>>;\n}\n\n/** One package-owned selection transition. Server facets change exactly one axis per operation. */\nexport type DoomHeadlessSelectionChange =\n | { readonly axis: 'majorMode'; readonly majorMode: string }\n | { readonly axis: 'domains'; readonly domains: readonly string[] }\n | { readonly axis: 'profile'; readonly profile?: string }\n | { readonly axis: 'state'; readonly key: string; readonly values: readonly string[] };\n\nexport function readDoomHeadlessOwner(context: Context): DoomServerBundleEntry | undefined {\n return (context as Context & { [DOOM_HEADLESS_OWNER]?: DoomServerBundleEntry })[DOOM_HEADLESS_OWNER];\n}\n\nexport interface DoomHeadlessRegistration {\n dispose(): void;\n}\n\nexport type DoomHeadlessContent = { type: 'text'; text: string } | { type: 'image'; data: string; mimeType: string };\n\nexport interface DoomHeadlessToolResult {\n content: DoomHeadlessContent[];\n /** Public MCP result data. Internal renderer details are not a remote result contract. */\n structuredContent?: Record<string, unknown>;\n details?: unknown;\n isError?: boolean;\n}\n\nexport interface DoomHeadlessClientRequest {\n kind: 'confirm' | 'select' | 'input';\n title: string;\n message?: string;\n options?: readonly { label: string; description?: string; value: string }[];\n initialValue?: string;\n multiline?: boolean;\n}\n\nexport interface DoomHeadlessClient {\n /**\n * Operator-facing surface only: the body is flattened to one line and capped at 4096 characters\n * by schemas/notification.ts:73-83, and the model never sees it. Use session.admitPrompt to\n * reach the model.\n */\n notify(request: DoomNotificationRequest): void | Promise<void>;\n request(request: DoomHeadlessClientRequest, signal?: AbortSignal): Promise<unknown>;\n setStatus(source: string, text: string | undefined): void;\n appendComposerText?(text: string): void;\n}\n\nexport interface DoomHeadlessModelSettings {\n model?: { provider: string; id: string };\n thinkingLevel: ThinkingLevel;\n}\n\nexport interface DoomHeadlessSession {\n readModelSettings?(): Promise<DoomHeadlessModelSettings>;\n setModelSettings?(settings: Partial<DoomHeadlessModelSettings>): Promise<void>;\n /** Query durable history on demand; hosts do not retain the entire transcript. */\n entries(query?: {\n type?: 'custom' | 'message';\n customType?: string;\n limit?: number;\n }): readonly Record<string, unknown>[] | Promise<readonly Record<string, unknown>[]>;\n appendCustomEntry(type: string, data: unknown): Promise<void>;\n /**\n * Delivers and awaits the turn. 'steer' and 'followUp' only enqueue into a running turn; they do\n * NOT wake an idle agent.\n */\n prompt(text: string, delivery?: 'prompt' | 'steer' | 'followUp'): Promise<void>;\n /**\n * Resolves when accepted by the session, before the agent turn settles. Here 'steer' describes\n * how to deliver IF a turn is already running; an idle agent is woken either way, matching Pi's\n * ExtensionAPI.sendMessage({ triggerTurn: true, deliverAs: 'steer' }).\n */\n admitPrompt?(text: string, delivery?: 'prompt' | 'steer' | 'followUp'): Promise<void>;\n abort(): Promise<void>;\n compact(instructions?: string): Promise<void>;\n activity(): Promise<{ hasPendingMessages: boolean; isIdle: boolean }>;\n /** Capture the current persisted branch for an in-process child fork. */\n forkSource?(): Promise<{ kind: 'v4-fork'; sessionFile: string; branch: string; entryId?: string }>;\n}\n\n/** A grant-filtered skill view available only during one remote MCP tool invocation. */\nexport interface DoomMcpSkillAccess {\n list(): Promise<readonly { name: string; description: string }[]>;\n read(name: string): Promise<string>;\n}\n\nexport interface DoomHeadlessExecutionContext {\n readonly cwd: string;\n /** Admitted configuration root, distinct from the tool execution directory. */\n readonly repoRoot: string;\n readonly sessionId: string;\n /** Immutable session configuration. Facets must not read or mutate process.env. */\n readonly environment: Readonly<Record<string, string | undefined>>;\n readonly client: DoomHeadlessClient;\n readonly session: DoomHeadlessSession;\n readonly model?: { provider: string; id: string };\n readonly textCompletion?: {\n available(reference: string): boolean;\n complete(\n reference: string,\n request: {\n systemPrompt: string;\n input: string;\n maxTokens: number;\n cacheRetention?: 'none' | 'short' | 'long';\n signal?: AbortSignal;\n },\n ): Promise<string>;\n };\n readonly selection: DoomHeadlessSelection;\n /** Present only while an authenticated remote MCP tool is running. */\n readonly mcpSkills?: DoomMcpSkillAccess;\n shutdown(): void;\n}\n\n/** Conditions narrow an eligible owner's contributions; they can never restore a disabled owner. */\nexport interface DoomHeadlessCondition {\n state?: Readonly<Record<string, string>>;\n attribution?: { kind: 'minor' | 'domain'; mode: string; label?: string };\n domain?: string;\n}\n\nexport interface DoomHeadlessToolRestriction {\n when?: DoomHeadlessCondition;\n allowedTools: readonly string[];\n}\n\nexport interface DoomHeadlessTool<TParameters extends TSchema = TSchema> {\n when?: DoomHeadlessCondition;\n name: string;\n label?: string;\n description: string;\n parameters: TParameters;\n annotations?: Tool['annotations'];\n outputSchema?: Tool['outputSchema'];\n promptSnippet?: string;\n promptGuidelines?: readonly string[];\n executionMode?: 'parallel' | 'serial';\n execute(\n toolCallId: string,\n parameters: Static<TParameters>,\n signal: AbortSignal | undefined,\n onUpdate: ((result: DoomHeadlessToolResult) => void) | undefined,\n context: DoomHeadlessExecutionContext,\n ): Promise<DoomHeadlessToolResult>;\n}\n\n/**\n * One package contribution to the session's resource surface.\n *\n * `kind` decides what the model is billed for, and the difference is large:\n * - `context` is EAGER. `read()` runs on every prompt build and the text is pasted\n * into the system prompt verbatim. Reserve it for small live session state that\n * exists nowhere on disk. Never use it for a file the package ships: a README\n * registered this way costs its full length on every single turn.\n * - `skill` is LAZY. Only `name`, `description` and `path` reach the prompt; the\n * agent reads the file itself when the description matches the task.\n * - `prompt` is inert until the user invokes it by name.\n *\n * The rule in one line: if it is a file the package ships, it is a `skill`.\n */\nexport interface DoomHeadlessResource {\n when?: DoomHeadlessCondition;\n name: string;\n /** Model-visible selection signal. A `skill` without one tells the agent nothing. */\n description?: string;\n /** Absolute path of the file `read()` returns, so an advertised skill is one the agent can open. */\n path?: string;\n kind: 'prompt' | 'skill' | 'context';\n read(context: DoomHeadlessExecutionContext): string | Promise<string>;\n}\n\nexport interface DoomHeadlessCommand {\n when?: DoomHeadlessCondition;\n name: string;\n description: string;\n execute(args: string, context: DoomHeadlessExecutionContext): void | Promise<void>;\n}\n\nexport type DoomHeadlessEventName =\n | 'session_start'\n | 'session_shutdown'\n | 'session_tree'\n | 'before_agent_start'\n | 'agent_start'\n | 'agent_settled'\n | 'turn_start'\n | 'turn_end'\n | 'context'\n | 'before_provider_request'\n | 'message_start'\n | 'message_update'\n | 'message_end'\n | 'tool_call'\n | 'tool_execution_start'\n | 'tool_execution_update'\n | 'tool_execution_end'\n | 'tool_result'\n | 'model_select'\n | 'session_before_compact'\n | 'session_compact';\n\nexport type DoomHeadlessHookEvent<E extends DoomHeadlessEventName> = E extends 'before_provider_request'\n ? { lane: string; runId: string; model: { provider: string; id: string }; payload: unknown }\n : E extends 'session_before_compact'\n ? { reason: string; preparation: unknown; instructions?: string; customInstructions?: string }\n : E extends 'model_select'\n ? { model: { provider: string; id: string } }\n : Readonly<Record<string, unknown>>;\n\nexport interface DoomHeadlessCompactionResult {\n summary: string;\n tokensBefore: number;\n retainedTail: Record<string, unknown>[];\n usage?: Record<string, unknown>;\n details?: unknown;\n}\n\nexport type DoomHeadlessHookResult<E extends DoomHeadlessEventName> = E extends 'before_provider_request'\n ? { payload: unknown } | void\n : E extends 'session_before_compact'\n ? { cancel?: boolean; decline?: boolean; compaction?: DoomHeadlessCompactionResult } | void\n : E extends 'context'\n ? { messages?: unknown[]; systemPrompt?: string } | void\n : E extends 'before_agent_start'\n ? { systemPrompt?: string } | void\n : E extends 'tool_call'\n ? { args?: Record<string, unknown>; block?: { reason: string; terminate?: boolean } } | void\n : E extends 'tool_result'\n ? {\n content?: DoomHeadlessContent[];\n details?: unknown;\n isError?: boolean;\n usage?: Record<string, unknown>;\n terminate?: boolean;\n } | void\n : unknown;\n\nexport type DoomHeadlessHook<E extends DoomHeadlessEventName = DoomHeadlessEventName> = E extends DoomHeadlessEventName\n ? {\n when?: DoomHeadlessCondition;\n event: E;\n handle(\n event: Readonly<DoomHeadlessHookEvent<E>>,\n context: DoomHeadlessExecutionContext,\n ): DoomHeadlessHookResult<E> | Promise<DoomHeadlessHookResult<E>>;\n }\n : never;\n\n/** A retained facet can register activity without starting disabled watchers or services. */\nexport interface DoomHeadlessActivity {\n when?: DoomHeadlessCondition;\n name: string;\n start(context: DoomHeadlessExecutionContext): (() => void | Promise<void>) | Promise<() => void | Promise<void>>;\n}\n\n/** Registrations inherit package ownership from the caller's Cordis facet. */\nexport interface DoomHeadlessHostService {\n readonly context: DoomHeadlessExecutionContext;\n changeSelection(change: DoomHeadlessSelectionChange): Promise<void>;\n assertActive(source?: string): void;\n subscribeSelection(listener: (selection: DoomHeadlessSelection) => void | Promise<void>): () => void;\n registerToolRestriction(restriction: DoomHeadlessToolRestriction): DoomHeadlessRegistration;\n registerTool<TParameters extends TSchema>(tool: DoomHeadlessTool<TParameters>): DoomHeadlessRegistration;\n registerResource(resource: DoomHeadlessResource): DoomHeadlessRegistration;\n registerCommand(command: DoomHeadlessCommand): DoomHeadlessRegistration;\n registerHook(hook: DoomHeadlessHook): DoomHeadlessRegistration;\n registerActivity(activity: DoomHeadlessActivity): DoomHeadlessRegistration;\n}\n\ndeclare module '@deepseek-ai/cordis' {\n interface Context {\n 'doom/headless-host': DoomHeadlessHostService;\n }\n}\n\nexport function readDoomHeadlessHost(context: Context): DoomHeadlessHostService | undefined {\n return context.get(DOOM_HEADLESS_HOST_SERVICE) as DoomHeadlessHostService | undefined;\n}\n\nexport function requireDoomHeadlessHost(context: Context): DoomHeadlessHostService {\n const host = readDoomHeadlessHost(context);\n if (!host) throw new Error('This contribution requires the Doom headless session host.');\n return host;\n}\n"],"mappings":";;AASA,MAAa,6BAA6B;AAC1C,MAAa,sBAAsB,OAAO,IAAI,qBAAqB;AAkBnE,SAAgB,sBAAsB,SAAqD;CACzF,OAAQ,QAAwE;AAClF;AA0QA,SAAgB,qBAAqB,SAAuD;CAC1F,OAAO,QAAQ,IAAI,0BAA0B;AAC/C;AAEA,SAAgB,wBAAwB,SAA2C;CACjF,MAAM,OAAO,qBAAqB,OAAO;CACzC,IAAI,CAAC,MAAM,MAAM,IAAI,MAAM,4DAA4D;CACvF,OAAO;AACT"}
|
|
1
|
+
{"version":3,"file":"headless.cjs","names":[],"sources":["../../src/schemas/headless.ts"],"sourcesContent":["import type { Context } from '@deepseek-ai/cordis';\nimport type { ThinkingLevel } from '@earendil-works/pi-agent-core';\nimport type { CallToolResult, Tool } from '@modelcontextprotocol/sdk/types.js';\nimport type { Static, TSchema } from 'typebox';\n\nimport type { DoomNotificationRequest } from './notification';\nimport type { DoomServerBundleEntry } from './serverBundle';\n\n/** Session-only contributions. This is not a Pi ExtensionAPI or a TUI adapter. */\nexport const DOOM_HEADLESS_HOST_SERVICE = 'doom/headless-host';\nexport const DOOM_HEADLESS_OWNER = Symbol.for('doom/headless-owner');\n\nexport interface DoomHeadlessSelection {\n readonly majorMode: string;\n readonly activeLayers: readonly string[];\n readonly domains: readonly string[];\n readonly profile?: string;\n /** Feature-owned activation sets, keyed by the contributing capability. */\n readonly state?: Readonly<Record<string, readonly string[]>>;\n}\n\n/** One package-owned selection transition. Server facets change exactly one axis per operation. */\nexport type DoomHeadlessSelectionChange =\n | { readonly axis: 'majorMode'; readonly majorMode: string }\n | { readonly axis: 'domains'; readonly domains: readonly string[] }\n | { readonly axis: 'profile'; readonly profile?: string }\n | { readonly axis: 'state'; readonly key: string; readonly values: readonly string[] };\n\nexport function readDoomHeadlessOwner(context: Context): DoomServerBundleEntry | undefined {\n return (context as Context & { [DOOM_HEADLESS_OWNER]?: DoomServerBundleEntry })[DOOM_HEADLESS_OWNER];\n}\n\nexport interface DoomHeadlessRegistration {\n dispose(): void;\n}\n\nexport type DoomHeadlessContent = { type: 'text'; text: string } | { type: 'image'; data: string; mimeType: string };\n\nexport interface DoomHeadlessToolResult {\n content: DoomHeadlessContent[];\n /** Public MCP result data. Internal renderer details are not a remote result contract. */\n structuredContent?: Record<string, unknown>;\n /** Component-only MCP metadata, never inferred from internal renderer details. */\n _meta?: CallToolResult['_meta'];\n details?: unknown;\n isError?: boolean;\n}\n\nexport interface DoomHeadlessClientRequest {\n kind: 'confirm' | 'select' | 'input';\n title: string;\n message?: string;\n options?: readonly { label: string; description?: string; value: string }[];\n initialValue?: string;\n multiline?: boolean;\n}\n\nexport interface DoomHeadlessClient {\n /**\n * Operator-facing surface only: the body is flattened to one line and capped at 4096 characters\n * by schemas/notification.ts:73-83, and the model never sees it. Use session.admitPrompt to\n * reach the model.\n */\n notify(request: DoomNotificationRequest): void | Promise<void>;\n request(request: DoomHeadlessClientRequest, signal?: AbortSignal): Promise<unknown>;\n setStatus(source: string, text: string | undefined): void;\n appendComposerText?(text: string): void;\n}\n\nexport interface DoomHeadlessModelSettings {\n model?: { provider: string; id: string };\n thinkingLevel: ThinkingLevel;\n}\n\nexport interface DoomHeadlessSession {\n readModelSettings?(): Promise<DoomHeadlessModelSettings>;\n setModelSettings?(settings: Partial<DoomHeadlessModelSettings>): Promise<void>;\n /** Query durable history on demand; hosts do not retain the entire transcript. */\n entries(query?: {\n type?: 'custom' | 'message';\n customType?: string;\n limit?: number;\n }): readonly Record<string, unknown>[] | Promise<readonly Record<string, unknown>[]>;\n appendCustomEntry(type: string, data: unknown): Promise<void>;\n /**\n * Delivers and awaits the turn. 'steer' and 'followUp' only enqueue into a running turn; they do\n * NOT wake an idle agent.\n */\n prompt(text: string, delivery?: 'prompt' | 'steer' | 'followUp'): Promise<void>;\n /**\n * Resolves when accepted by the session, before the agent turn settles. Here 'steer' describes\n * how to deliver IF a turn is already running; an idle agent is woken either way, matching Pi's\n * ExtensionAPI.sendMessage({ triggerTurn: true, deliverAs: 'steer' }).\n */\n admitPrompt?(text: string, delivery?: 'prompt' | 'steer' | 'followUp'): Promise<void>;\n abort(): Promise<void>;\n compact(instructions?: string): Promise<void>;\n activity(): Promise<{ hasPendingMessages: boolean; isIdle: boolean }>;\n /** Capture the current persisted branch for an in-process child fork. */\n forkSource?(): Promise<{ kind: 'v4-fork'; sessionFile: string; branch: string; entryId?: string }>;\n}\n\n/** A grant-filtered skill view available only during one remote MCP tool invocation. */\nexport interface DoomMcpSkillAccess {\n list(): Promise<readonly { name: string; description: string }[]>;\n read(name: string): Promise<string>;\n}\n\nexport interface DoomHeadlessExecutionContext {\n readonly cwd: string;\n /** Admitted configuration root, distinct from the tool execution directory. */\n readonly repoRoot: string;\n readonly sessionId: string;\n /** Immutable session configuration. Facets must not read or mutate process.env. */\n readonly environment: Readonly<Record<string, string | undefined>>;\n readonly client: DoomHeadlessClient;\n readonly session: DoomHeadlessSession;\n readonly model?: { provider: string; id: string };\n readonly textCompletion?: {\n available(reference: string): boolean;\n complete(\n reference: string,\n request: {\n systemPrompt: string;\n input: string;\n maxTokens: number;\n cacheRetention?: 'none' | 'short' | 'long';\n signal?: AbortSignal;\n },\n ): Promise<string>;\n };\n readonly selection: DoomHeadlessSelection;\n /** Present only while an authenticated remote MCP tool is running. */\n readonly mcpSkills?: DoomMcpSkillAccess;\n shutdown(): void;\n}\n\n/** Conditions narrow an eligible owner's contributions; they can never restore a disabled owner. */\nexport interface DoomHeadlessCondition {\n state?: Readonly<Record<string, string>>;\n attribution?: { kind: 'minor' | 'domain'; mode: string; label?: string };\n domain?: string;\n}\n\nexport interface DoomHeadlessToolRestriction {\n when?: DoomHeadlessCondition;\n /** Optional capability ceiling. An empty list disables every tool. */\n allowedTools?: readonly string[];\n /**\n * Narrow exclusions without disabling unrelated tools. Exclude a tool your package owns, or a\n * specific foreign tool the mode exists to withdraw. Never enumerate an allowlist here.\n */\n excludedTools?: readonly string[];\n}\n\nexport interface DoomHeadlessTool<TParameters extends TSchema = TSchema> {\n when?: DoomHeadlessCondition;\n name: string;\n label?: string;\n description: string;\n parameters: TParameters;\n annotations?: Tool['annotations'];\n outputSchema?: Tool['outputSchema'];\n /** Remote presentation only. Component tool access must be explicitly opted into. */\n _meta?: Tool['_meta'] & {\n ui?: {\n resourceUri?: string;\n visibility?: ('model' | 'app')[];\n };\n };\n promptSnippet?: string;\n promptGuidelines?: readonly string[];\n executionMode?: 'parallel' | 'serial';\n execute(\n toolCallId: string,\n parameters: Static<TParameters>,\n signal: AbortSignal | undefined,\n onUpdate: ((result: DoomHeadlessToolResult) => void) | undefined,\n context: DoomHeadlessExecutionContext,\n ): Promise<DoomHeadlessToolResult>;\n}\n\n/**\n * One package contribution to the session's resource surface.\n *\n * `kind` decides what the model is billed for, and the difference is large:\n * - `context` is EAGER. `read()` runs on every prompt build and the text is pasted\n * into the system prompt verbatim. Reserve it for small live session state that\n * exists nowhere on disk. Never use it for a file the package ships: a README\n * registered this way costs its full length on every single turn.\n * - `skill` is LAZY. Only `name`, `description` and `path` reach the prompt; the\n * agent reads the file itself when the description matches the task.\n * - `prompt` is inert until the user invokes it by name.\n *\n * The rule in one line: if it is a file the package ships, it is a `skill`.\n */\nexport interface DoomHeadlessResource {\n when?: DoomHeadlessCondition;\n name: string;\n /** Model-visible selection signal. A `skill` without one tells the agent nothing. */\n description?: string;\n /** Absolute path of the file `read()` returns, so an advertised skill is one the agent can open. */\n path?: string;\n kind: 'prompt' | 'skill' | 'context';\n read(context: DoomHeadlessExecutionContext): string | Promise<string>;\n}\n\nexport interface DoomHeadlessCommand {\n when?: DoomHeadlessCondition;\n name: string;\n description: string;\n execute(args: string, context: DoomHeadlessExecutionContext): void | Promise<void>;\n}\n\nexport type DoomHeadlessEventName =\n | 'session_start'\n | 'session_shutdown'\n | 'session_tree'\n | 'before_agent_start'\n | 'agent_start'\n | 'agent_settled'\n | 'turn_start'\n | 'turn_end'\n | 'context'\n | 'before_provider_request'\n | 'message_start'\n | 'message_update'\n | 'message_end'\n | 'tool_call'\n | 'tool_execution_start'\n | 'tool_execution_update'\n | 'tool_execution_end'\n | 'tool_result'\n | 'model_select'\n | 'session_before_compact'\n | 'session_compact';\n\nexport type DoomHeadlessHookEvent<E extends DoomHeadlessEventName> = E extends 'before_provider_request'\n ? { lane: string; runId: string; model: { provider: string; id: string }; payload: unknown }\n : E extends 'session_before_compact'\n ? { reason: string; preparation: unknown; instructions?: string; customInstructions?: string }\n : E extends 'model_select'\n ? { model: { provider: string; id: string } }\n : Readonly<Record<string, unknown>>;\n\nexport interface DoomHeadlessCompactionResult {\n summary: string;\n tokensBefore: number;\n retainedTail: Record<string, unknown>[];\n usage?: Record<string, unknown>;\n details?: unknown;\n}\n\nexport type DoomHeadlessHookResult<E extends DoomHeadlessEventName> = E extends 'before_provider_request'\n ? { payload: unknown } | void\n : E extends 'session_before_compact'\n ? { cancel?: boolean; decline?: boolean; compaction?: DoomHeadlessCompactionResult } | void\n : E extends 'context'\n ? { messages?: unknown[]; systemPrompt?: string } | void\n : E extends 'before_agent_start'\n ? { systemPrompt?: string } | void\n : E extends 'tool_call'\n ? { args?: Record<string, unknown>; block?: { reason: string; terminate?: boolean } } | void\n : E extends 'tool_result'\n ? {\n content?: DoomHeadlessContent[];\n details?: unknown;\n isError?: boolean;\n usage?: Record<string, unknown>;\n terminate?: boolean;\n } | void\n : unknown;\n\nexport type DoomHeadlessHook<E extends DoomHeadlessEventName = DoomHeadlessEventName> = E extends DoomHeadlessEventName\n ? {\n when?: DoomHeadlessCondition;\n event: E;\n handle(\n event: Readonly<DoomHeadlessHookEvent<E>>,\n context: DoomHeadlessExecutionContext,\n ): DoomHeadlessHookResult<E> | Promise<DoomHeadlessHookResult<E>>;\n }\n : never;\n\n/** A retained facet can register activity without starting disabled watchers or services. */\nexport interface DoomHeadlessActivity {\n when?: DoomHeadlessCondition;\n name: string;\n start(context: DoomHeadlessExecutionContext): (() => void | Promise<void>) | Promise<() => void | Promise<void>>;\n}\n\n/** Registrations inherit package ownership from the caller's Cordis facet. */\nexport interface DoomHeadlessHostService {\n readonly context: DoomHeadlessExecutionContext;\n changeSelection(change: DoomHeadlessSelectionChange): Promise<void>;\n assertActive(source?: string): void;\n subscribeSelection(listener: (selection: DoomHeadlessSelection) => void | Promise<void>): () => void;\n registerToolRestriction(restriction: DoomHeadlessToolRestriction): DoomHeadlessRegistration;\n registerTool<TParameters extends TSchema>(tool: DoomHeadlessTool<TParameters>): DoomHeadlessRegistration;\n registerResource(resource: DoomHeadlessResource): DoomHeadlessRegistration;\n registerCommand(command: DoomHeadlessCommand): DoomHeadlessRegistration;\n registerHook(hook: DoomHeadlessHook): DoomHeadlessRegistration;\n registerActivity(activity: DoomHeadlessActivity): DoomHeadlessRegistration;\n}\n\ndeclare module '@deepseek-ai/cordis' {\n interface Context {\n 'doom/headless-host': DoomHeadlessHostService;\n }\n}\n\nexport function readDoomHeadlessHost(context: Context): DoomHeadlessHostService | undefined {\n return context.get(DOOM_HEADLESS_HOST_SERVICE) as DoomHeadlessHostService | undefined;\n}\n\nexport function requireDoomHeadlessHost(context: Context): DoomHeadlessHostService {\n const host = readDoomHeadlessHost(context);\n if (!host) throw new Error('This contribution requires the Doom headless session host.');\n return host;\n}\n"],"mappings":";;AASA,MAAa,6BAA6B;AAC1C,MAAa,sBAAsB,OAAO,IAAI,qBAAqB;AAkBnE,SAAgB,sBAAsB,SAAqD;CACzF,OAAQ,QAAwE;AAClF;AAyRA,SAAgB,qBAAqB,SAAuD;CAC1F,OAAO,QAAQ,IAAI,0BAA0B;AAC/C;AAEA,SAAgB,wBAAwB,SAA2C;CACjF,MAAM,OAAO,qBAAqB,OAAO;CACzC,IAAI,CAAC,MAAM,MAAM,IAAI,MAAM,4DAA4D;CACvF,OAAO;AACT"}
|
|
@@ -3,7 +3,7 @@ import { DoomNotificationRequest } from "./notification.cjs";
|
|
|
3
3
|
import { Static, TSchema } from "typebox";
|
|
4
4
|
import { Context } from "@deepseek-ai/cordis";
|
|
5
5
|
import { ThinkingLevel } from "@earendil-works/pi-agent-core";
|
|
6
|
-
import { Tool } from "@modelcontextprotocol/sdk/types.js";
|
|
6
|
+
import { CallToolResult, Tool } from "@modelcontextprotocol/sdk/types.js";
|
|
7
7
|
//#region src/schemas/headless.d.ts
|
|
8
8
|
/** Session-only contributions. This is not a Pi ExtensionAPI or a TUI adapter. */
|
|
9
9
|
export declare const DOOM_HEADLESS_HOST_SERVICE = "doom/headless-host";
|
|
@@ -47,6 +47,8 @@ export interface DoomHeadlessToolResult {
|
|
|
47
47
|
content: DoomHeadlessContent[];
|
|
48
48
|
/** Public MCP result data. Internal renderer details are not a remote result contract. */
|
|
49
49
|
structuredContent?: Record<string, unknown>;
|
|
50
|
+
/** Component-only MCP metadata, never inferred from internal renderer details. */
|
|
51
|
+
_meta?: CallToolResult['_meta'];
|
|
50
52
|
details?: unknown;
|
|
51
53
|
isError?: boolean;
|
|
52
54
|
}
|
|
@@ -163,7 +165,13 @@ export interface DoomHeadlessCondition {
|
|
|
163
165
|
}
|
|
164
166
|
export interface DoomHeadlessToolRestriction {
|
|
165
167
|
when?: DoomHeadlessCondition;
|
|
166
|
-
|
|
168
|
+
/** Optional capability ceiling. An empty list disables every tool. */
|
|
169
|
+
allowedTools?: readonly string[];
|
|
170
|
+
/**
|
|
171
|
+
* Narrow exclusions without disabling unrelated tools. Exclude a tool your package owns, or a
|
|
172
|
+
* specific foreign tool the mode exists to withdraw. Never enumerate an allowlist here.
|
|
173
|
+
*/
|
|
174
|
+
excludedTools?: readonly string[];
|
|
167
175
|
}
|
|
168
176
|
export interface DoomHeadlessTool<TParameters extends TSchema = TSchema> {
|
|
169
177
|
when?: DoomHeadlessCondition;
|
|
@@ -173,6 +181,13 @@ export interface DoomHeadlessTool<TParameters extends TSchema = TSchema> {
|
|
|
173
181
|
parameters: TParameters;
|
|
174
182
|
annotations?: Tool['annotations'];
|
|
175
183
|
outputSchema?: Tool['outputSchema'];
|
|
184
|
+
/** Remote presentation only. Component tool access must be explicitly opted into. */
|
|
185
|
+
_meta?: Tool['_meta'] & {
|
|
186
|
+
ui?: {
|
|
187
|
+
resourceUri?: string;
|
|
188
|
+
visibility?: ('model' | 'app')[];
|
|
189
|
+
};
|
|
190
|
+
};
|
|
176
191
|
promptSnippet?: string;
|
|
177
192
|
promptGuidelines?: readonly string[];
|
|
178
193
|
executionMode?: 'parallel' | 'serial';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"headless.d.cts","names":[],"sources":["../../src/schemas/headless.ts"],"mappings":";;;;;;;;qBASa;qBACA;iBAEI;WACN;WACA;WACA;WACA;;WAEA,QAAQ,SAAS;;;YAIhB;WACG;WAA4B;;WAC5B;WAA0B;;WAC1B;WAA0B;;WAC1B;WAAwB;WAAsB;;wBAE7C,sBAAsB,SAAS,UAAU;iBAIxC;EACf;;YAGU;EAAwB;EAAc;;EAAmB;EAAe;EAAc;;iBAEjF;EACf,SAAS;;EAET,oBAAoB;
|
|
1
|
+
{"version":3,"file":"headless.d.cts","names":[],"sources":["../../src/schemas/headless.ts"],"mappings":";;;;;;;;qBASa;qBACA;iBAEI;WACN;WACA;WACA;WACA;;WAEA,QAAQ,SAAS;;;YAIhB;WACG;WAA4B;;WAC5B;WAA0B;;WAC1B;WAA0B;;WAC1B;WAAwB;WAAsB;;wBAE7C,sBAAsB,SAAS,UAAU;iBAIxC;EACf;;YAGU;EAAwB;EAAc;;EAAmB;EAAe;EAAc;;iBAEjF;EACf,SAAS;;EAET,oBAAoB;;EAEpB,QAAQ;EACR;EACA;;iBAGe;EACf;EACA;EACA;EACA;IAAqB;IAAe;IAAsB;;EAC1D;EACA;;iBAGe;;;;;;EAMf,OAAO,SAAS,iCAAiC;EACjD,QAAQ,SAAS,2BAA2B,SAAS,cAAc;EACnE,UAAU,gBAAgB;EAC1B,oBAAoB;;iBAGL;EACf;IAAU;IAAkB;;EAC5B,eAAe;;iBAGA;EACf,sBAAsB,QAAQ;EAC9B,kBAAkB,UAAU,QAAQ,6BAA6B;;EAEjE,QAAQ;IACN;IACA;IACA;eACW,4BAA4B,iBAAiB;EAC1D,kBAAkB,cAAc,gBAAgB;;;;;EAKhD,OAAO,cAAc,6CAA6C;;;;;;EAMlE,aAAa,cAAc,6CAA6C;EACxE,SAAS;EACT,QAAQ,wBAAwB;EAChC,YAAY;IAAU;IAA6B;;;EAEnD,eAAe;IAAU;IAAiB;IAAqB;IAAgB;;;;iBAIhE;EACf,QAAQ;IAAmB;IAAc;;EACzC,KAAK,eAAe;;iBAGL;WACN;;WAEA;WACA;;WAEA,aAAa,SAAS;WACtB,QAAQ;WACR,SAAS;WACT;IAAU;IAAkB;;WAC5B;IACP,UAAU;IACV,SACE,mBACA;MACE;MACA;MACA;MACA;MACA,SAAS;QAEV;;WAEI,WAAW;;WAEX,YAAY;EACrB;;;iBAIe;EACf,QAAQ,SAAS;EACjB;IAAgB;IAA0B;IAAc;;EACxD;;iBAGe;EACf,OAAO;;EAEP;;;;;EAKA;;iBAGe,iBAAiB,oBAAoB,UAAU;EAC9D,OAAO;EACP;EACA;EACA;EACA,YAAY;EACZ,cAAc;EACd,eAAe;;EAEf,QAAQ;IACN;MACE;MACA;;;EAGJ;EACA;EACA;EACA,QACE,oBACA,YAAY,OAAO,cACnB,QAAQ,yBACR,YAAY,QAAQ,8CACpB,SAAS,+BACR,QAAQ;;;;;;;;;;;;;;;;iBAiBI;EACf,OAAO;EACP;;EAEA;;EAEA;EACA;EACA,KAAK,SAAS,wCAAwC;;iBAGvC;EACf,OAAO;EACP;EACA;EACA,QAAQ,cAAc,SAAS,sCAAsC;;YAG3D;YAuBA,sBAAsB,UAAU,yBAAyB;EAC/D;EAAc;EAAe;IAAS;IAAkB;;EAAc;IACxE;EACI;EAAgB;EAAsB;EAAuB;IAC/D;EACI;IAAS;IAAkB;;IAC7B,SAAS;iBAEA;EACf;EACA;EACA,cAAc;EACd,QAAQ;EACR;;YAGU,uBAAuB,UAAU,yBAAyB;EAChE;WACF;EACI;EAAkB;EAAmB,aAAa;WACpD;EACI;EAAsB;WACxB;EACI;WACF;EACI,OAAO;EAAyB;IAAU;IAAgB;;WAC5D;EAEI,UAAU;EACV;EACA;EACA,QAAQ;EACR;;YAIJ,iBAAiB,UAAU,wBAAwB,yBAAyB,UAAU;EAE5F,OAAO;EACP,OAAO;EACP,OACE,OAAO,SAAS,sBAAsB,KACtC,SAAS,+BACR,uBAAuB,KAAK,QAAQ,uBAAuB;;;iBAKnD;EACf,OAAO;EACP;EACA,MAAM,SAAS,6CAA6C,iBAAiB,qBAAqB;;;iBAInF;WACN,SAAS;EAClB,gBAAgB,QAAQ,8BAA8B;EACtD,aAAa;EACb,mBAAmB,WAAW,WAAW,iCAAiC;EAC1E,wBAAwB,aAAa,8BAA8B;EACnE,aAAa,oBAAoB,SAAS,MAAM,iBAAiB,eAAe;EAChF,iBAAiB,UAAU,uBAAuB;EAClD,gBAAgB,SAAS,sBAAsB;EAC/C,aAAa,MAAM,mBAAmB;EACtC,iBAAiB,UAAU,uBAAuB;;;YAIxC;IACR,sBAAsB;;;wBAIV,qBAAqB,SAAS,UAAU;wBAIxC,wBAAwB,SAAS,UAAU"}
|
|
@@ -2,7 +2,7 @@ import { DoomServerBundleEntry } from "./serverBundle.mjs";
|
|
|
2
2
|
import { DoomNotificationRequest } from "./notification.mjs";
|
|
3
3
|
import { Static, TSchema } from "typebox";
|
|
4
4
|
import { Context } from "@deepseek-ai/cordis";
|
|
5
|
-
import { Tool } from "@modelcontextprotocol/sdk/types.js";
|
|
5
|
+
import { CallToolResult, Tool } from "@modelcontextprotocol/sdk/types.js";
|
|
6
6
|
import { ThinkingLevel } from "@earendil-works/pi-agent-core";
|
|
7
7
|
//#region src/schemas/headless.d.ts
|
|
8
8
|
/** Session-only contributions. This is not a Pi ExtensionAPI or a TUI adapter. */
|
|
@@ -47,6 +47,8 @@ export interface DoomHeadlessToolResult {
|
|
|
47
47
|
content: DoomHeadlessContent[];
|
|
48
48
|
/** Public MCP result data. Internal renderer details are not a remote result contract. */
|
|
49
49
|
structuredContent?: Record<string, unknown>;
|
|
50
|
+
/** Component-only MCP metadata, never inferred from internal renderer details. */
|
|
51
|
+
_meta?: CallToolResult['_meta'];
|
|
50
52
|
details?: unknown;
|
|
51
53
|
isError?: boolean;
|
|
52
54
|
}
|
|
@@ -163,7 +165,13 @@ export interface DoomHeadlessCondition {
|
|
|
163
165
|
}
|
|
164
166
|
export interface DoomHeadlessToolRestriction {
|
|
165
167
|
when?: DoomHeadlessCondition;
|
|
166
|
-
|
|
168
|
+
/** Optional capability ceiling. An empty list disables every tool. */
|
|
169
|
+
allowedTools?: readonly string[];
|
|
170
|
+
/**
|
|
171
|
+
* Narrow exclusions without disabling unrelated tools. Exclude a tool your package owns, or a
|
|
172
|
+
* specific foreign tool the mode exists to withdraw. Never enumerate an allowlist here.
|
|
173
|
+
*/
|
|
174
|
+
excludedTools?: readonly string[];
|
|
167
175
|
}
|
|
168
176
|
export interface DoomHeadlessTool<TParameters extends TSchema = TSchema> {
|
|
169
177
|
when?: DoomHeadlessCondition;
|
|
@@ -173,6 +181,13 @@ export interface DoomHeadlessTool<TParameters extends TSchema = TSchema> {
|
|
|
173
181
|
parameters: TParameters;
|
|
174
182
|
annotations?: Tool['annotations'];
|
|
175
183
|
outputSchema?: Tool['outputSchema'];
|
|
184
|
+
/** Remote presentation only. Component tool access must be explicitly opted into. */
|
|
185
|
+
_meta?: Tool['_meta'] & {
|
|
186
|
+
ui?: {
|
|
187
|
+
resourceUri?: string;
|
|
188
|
+
visibility?: ('model' | 'app')[];
|
|
189
|
+
};
|
|
190
|
+
};
|
|
176
191
|
promptSnippet?: string;
|
|
177
192
|
promptGuidelines?: readonly string[];
|
|
178
193
|
executionMode?: 'parallel' | 'serial';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"headless.d.mts","names":[],"sources":["../../src/schemas/headless.ts"],"mappings":";;;;;;;;qBASa;qBACA;iBAEI;WACN;WACA;WACA;WACA;;WAEA,QAAQ,SAAS;;;YAIhB;WACG;WAA4B;;WAC5B;WAA0B;;WAC1B;WAA0B;;WAC1B;WAAwB;WAAsB;;wBAE7C,sBAAsB,SAAS,UAAU;iBAIxC;EACf;;YAGU;EAAwB;EAAc;;EAAmB;EAAe;EAAc;;iBAEjF;EACf,SAAS;;EAET,oBAAoB;
|
|
1
|
+
{"version":3,"file":"headless.d.mts","names":[],"sources":["../../src/schemas/headless.ts"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"headless.mjs","names":[],"sources":["../../src/schemas/headless.ts"],"sourcesContent":["import type { Context } from '@deepseek-ai/cordis';\nimport type { ThinkingLevel } from '@earendil-works/pi-agent-core';\nimport type { Tool } from '@modelcontextprotocol/sdk/types.js';\nimport type { Static, TSchema } from 'typebox';\n\nimport type { DoomNotificationRequest } from './notification';\nimport type { DoomServerBundleEntry } from './serverBundle';\n\n/** Session-only contributions. This is not a Pi ExtensionAPI or a TUI adapter. */\nexport const DOOM_HEADLESS_HOST_SERVICE = 'doom/headless-host';\nexport const DOOM_HEADLESS_OWNER = Symbol.for('doom/headless-owner');\n\nexport interface DoomHeadlessSelection {\n readonly majorMode: string;\n readonly activeLayers: readonly string[];\n readonly domains: readonly string[];\n readonly profile?: string;\n /** Feature-owned activation sets, keyed by the contributing capability. */\n readonly state?: Readonly<Record<string, readonly string[]>>;\n}\n\n/** One package-owned selection transition. Server facets change exactly one axis per operation. */\nexport type DoomHeadlessSelectionChange =\n | { readonly axis: 'majorMode'; readonly majorMode: string }\n | { readonly axis: 'domains'; readonly domains: readonly string[] }\n | { readonly axis: 'profile'; readonly profile?: string }\n | { readonly axis: 'state'; readonly key: string; readonly values: readonly string[] };\n\nexport function readDoomHeadlessOwner(context: Context): DoomServerBundleEntry | undefined {\n return (context as Context & { [DOOM_HEADLESS_OWNER]?: DoomServerBundleEntry })[DOOM_HEADLESS_OWNER];\n}\n\nexport interface DoomHeadlessRegistration {\n dispose(): void;\n}\n\nexport type DoomHeadlessContent = { type: 'text'; text: string } | { type: 'image'; data: string; mimeType: string };\n\nexport interface DoomHeadlessToolResult {\n content: DoomHeadlessContent[];\n /** Public MCP result data. Internal renderer details are not a remote result contract. */\n structuredContent?: Record<string, unknown>;\n details?: unknown;\n isError?: boolean;\n}\n\nexport interface DoomHeadlessClientRequest {\n kind: 'confirm' | 'select' | 'input';\n title: string;\n message?: string;\n options?: readonly { label: string; description?: string; value: string }[];\n initialValue?: string;\n multiline?: boolean;\n}\n\nexport interface DoomHeadlessClient {\n /**\n * Operator-facing surface only: the body is flattened to one line and capped at 4096 characters\n * by schemas/notification.ts:73-83, and the model never sees it. Use session.admitPrompt to\n * reach the model.\n */\n notify(request: DoomNotificationRequest): void | Promise<void>;\n request(request: DoomHeadlessClientRequest, signal?: AbortSignal): Promise<unknown>;\n setStatus(source: string, text: string | undefined): void;\n appendComposerText?(text: string): void;\n}\n\nexport interface DoomHeadlessModelSettings {\n model?: { provider: string; id: string };\n thinkingLevel: ThinkingLevel;\n}\n\nexport interface DoomHeadlessSession {\n readModelSettings?(): Promise<DoomHeadlessModelSettings>;\n setModelSettings?(settings: Partial<DoomHeadlessModelSettings>): Promise<void>;\n /** Query durable history on demand; hosts do not retain the entire transcript. */\n entries(query?: {\n type?: 'custom' | 'message';\n customType?: string;\n limit?: number;\n }): readonly Record<string, unknown>[] | Promise<readonly Record<string, unknown>[]>;\n appendCustomEntry(type: string, data: unknown): Promise<void>;\n /**\n * Delivers and awaits the turn. 'steer' and 'followUp' only enqueue into a running turn; they do\n * NOT wake an idle agent.\n */\n prompt(text: string, delivery?: 'prompt' | 'steer' | 'followUp'): Promise<void>;\n /**\n * Resolves when accepted by the session, before the agent turn settles. Here 'steer' describes\n * how to deliver IF a turn is already running; an idle agent is woken either way, matching Pi's\n * ExtensionAPI.sendMessage({ triggerTurn: true, deliverAs: 'steer' }).\n */\n admitPrompt?(text: string, delivery?: 'prompt' | 'steer' | 'followUp'): Promise<void>;\n abort(): Promise<void>;\n compact(instructions?: string): Promise<void>;\n activity(): Promise<{ hasPendingMessages: boolean; isIdle: boolean }>;\n /** Capture the current persisted branch for an in-process child fork. */\n forkSource?(): Promise<{ kind: 'v4-fork'; sessionFile: string; branch: string; entryId?: string }>;\n}\n\n/** A grant-filtered skill view available only during one remote MCP tool invocation. */\nexport interface DoomMcpSkillAccess {\n list(): Promise<readonly { name: string; description: string }[]>;\n read(name: string): Promise<string>;\n}\n\nexport interface DoomHeadlessExecutionContext {\n readonly cwd: string;\n /** Admitted configuration root, distinct from the tool execution directory. */\n readonly repoRoot: string;\n readonly sessionId: string;\n /** Immutable session configuration. Facets must not read or mutate process.env. */\n readonly environment: Readonly<Record<string, string | undefined>>;\n readonly client: DoomHeadlessClient;\n readonly session: DoomHeadlessSession;\n readonly model?: { provider: string; id: string };\n readonly textCompletion?: {\n available(reference: string): boolean;\n complete(\n reference: string,\n request: {\n systemPrompt: string;\n input: string;\n maxTokens: number;\n cacheRetention?: 'none' | 'short' | 'long';\n signal?: AbortSignal;\n },\n ): Promise<string>;\n };\n readonly selection: DoomHeadlessSelection;\n /** Present only while an authenticated remote MCP tool is running. */\n readonly mcpSkills?: DoomMcpSkillAccess;\n shutdown(): void;\n}\n\n/** Conditions narrow an eligible owner's contributions; they can never restore a disabled owner. */\nexport interface DoomHeadlessCondition {\n state?: Readonly<Record<string, string>>;\n attribution?: { kind: 'minor' | 'domain'; mode: string; label?: string };\n domain?: string;\n}\n\nexport interface DoomHeadlessToolRestriction {\n when?: DoomHeadlessCondition;\n allowedTools: readonly string[];\n}\n\nexport interface DoomHeadlessTool<TParameters extends TSchema = TSchema> {\n when?: DoomHeadlessCondition;\n name: string;\n label?: string;\n description: string;\n parameters: TParameters;\n annotations?: Tool['annotations'];\n outputSchema?: Tool['outputSchema'];\n promptSnippet?: string;\n promptGuidelines?: readonly string[];\n executionMode?: 'parallel' | 'serial';\n execute(\n toolCallId: string,\n parameters: Static<TParameters>,\n signal: AbortSignal | undefined,\n onUpdate: ((result: DoomHeadlessToolResult) => void) | undefined,\n context: DoomHeadlessExecutionContext,\n ): Promise<DoomHeadlessToolResult>;\n}\n\n/**\n * One package contribution to the session's resource surface.\n *\n * `kind` decides what the model is billed for, and the difference is large:\n * - `context` is EAGER. `read()` runs on every prompt build and the text is pasted\n * into the system prompt verbatim. Reserve it for small live session state that\n * exists nowhere on disk. Never use it for a file the package ships: a README\n * registered this way costs its full length on every single turn.\n * - `skill` is LAZY. Only `name`, `description` and `path` reach the prompt; the\n * agent reads the file itself when the description matches the task.\n * - `prompt` is inert until the user invokes it by name.\n *\n * The rule in one line: if it is a file the package ships, it is a `skill`.\n */\nexport interface DoomHeadlessResource {\n when?: DoomHeadlessCondition;\n name: string;\n /** Model-visible selection signal. A `skill` without one tells the agent nothing. */\n description?: string;\n /** Absolute path of the file `read()` returns, so an advertised skill is one the agent can open. */\n path?: string;\n kind: 'prompt' | 'skill' | 'context';\n read(context: DoomHeadlessExecutionContext): string | Promise<string>;\n}\n\nexport interface DoomHeadlessCommand {\n when?: DoomHeadlessCondition;\n name: string;\n description: string;\n execute(args: string, context: DoomHeadlessExecutionContext): void | Promise<void>;\n}\n\nexport type DoomHeadlessEventName =\n | 'session_start'\n | 'session_shutdown'\n | 'session_tree'\n | 'before_agent_start'\n | 'agent_start'\n | 'agent_settled'\n | 'turn_start'\n | 'turn_end'\n | 'context'\n | 'before_provider_request'\n | 'message_start'\n | 'message_update'\n | 'message_end'\n | 'tool_call'\n | 'tool_execution_start'\n | 'tool_execution_update'\n | 'tool_execution_end'\n | 'tool_result'\n | 'model_select'\n | 'session_before_compact'\n | 'session_compact';\n\nexport type DoomHeadlessHookEvent<E extends DoomHeadlessEventName> = E extends 'before_provider_request'\n ? { lane: string; runId: string; model: { provider: string; id: string }; payload: unknown }\n : E extends 'session_before_compact'\n ? { reason: string; preparation: unknown; instructions?: string; customInstructions?: string }\n : E extends 'model_select'\n ? { model: { provider: string; id: string } }\n : Readonly<Record<string, unknown>>;\n\nexport interface DoomHeadlessCompactionResult {\n summary: string;\n tokensBefore: number;\n retainedTail: Record<string, unknown>[];\n usage?: Record<string, unknown>;\n details?: unknown;\n}\n\nexport type DoomHeadlessHookResult<E extends DoomHeadlessEventName> = E extends 'before_provider_request'\n ? { payload: unknown } | void\n : E extends 'session_before_compact'\n ? { cancel?: boolean; decline?: boolean; compaction?: DoomHeadlessCompactionResult } | void\n : E extends 'context'\n ? { messages?: unknown[]; systemPrompt?: string } | void\n : E extends 'before_agent_start'\n ? { systemPrompt?: string } | void\n : E extends 'tool_call'\n ? { args?: Record<string, unknown>; block?: { reason: string; terminate?: boolean } } | void\n : E extends 'tool_result'\n ? {\n content?: DoomHeadlessContent[];\n details?: unknown;\n isError?: boolean;\n usage?: Record<string, unknown>;\n terminate?: boolean;\n } | void\n : unknown;\n\nexport type DoomHeadlessHook<E extends DoomHeadlessEventName = DoomHeadlessEventName> = E extends DoomHeadlessEventName\n ? {\n when?: DoomHeadlessCondition;\n event: E;\n handle(\n event: Readonly<DoomHeadlessHookEvent<E>>,\n context: DoomHeadlessExecutionContext,\n ): DoomHeadlessHookResult<E> | Promise<DoomHeadlessHookResult<E>>;\n }\n : never;\n\n/** A retained facet can register activity without starting disabled watchers or services. */\nexport interface DoomHeadlessActivity {\n when?: DoomHeadlessCondition;\n name: string;\n start(context: DoomHeadlessExecutionContext): (() => void | Promise<void>) | Promise<() => void | Promise<void>>;\n}\n\n/** Registrations inherit package ownership from the caller's Cordis facet. */\nexport interface DoomHeadlessHostService {\n readonly context: DoomHeadlessExecutionContext;\n changeSelection(change: DoomHeadlessSelectionChange): Promise<void>;\n assertActive(source?: string): void;\n subscribeSelection(listener: (selection: DoomHeadlessSelection) => void | Promise<void>): () => void;\n registerToolRestriction(restriction: DoomHeadlessToolRestriction): DoomHeadlessRegistration;\n registerTool<TParameters extends TSchema>(tool: DoomHeadlessTool<TParameters>): DoomHeadlessRegistration;\n registerResource(resource: DoomHeadlessResource): DoomHeadlessRegistration;\n registerCommand(command: DoomHeadlessCommand): DoomHeadlessRegistration;\n registerHook(hook: DoomHeadlessHook): DoomHeadlessRegistration;\n registerActivity(activity: DoomHeadlessActivity): DoomHeadlessRegistration;\n}\n\ndeclare module '@deepseek-ai/cordis' {\n interface Context {\n 'doom/headless-host': DoomHeadlessHostService;\n }\n}\n\nexport function readDoomHeadlessHost(context: Context): DoomHeadlessHostService | undefined {\n return context.get(DOOM_HEADLESS_HOST_SERVICE) as DoomHeadlessHostService | undefined;\n}\n\nexport function requireDoomHeadlessHost(context: Context): DoomHeadlessHostService {\n const host = readDoomHeadlessHost(context);\n if (!host) throw new Error('This contribution requires the Doom headless session host.');\n return host;\n}\n"],"mappings":";;AASA,MAAa,6BAA6B;AAC1C,MAAa,sBAAsB,OAAO,IAAI,qBAAqB;AAkBnE,SAAgB,sBAAsB,SAAqD;CACzF,OAAQ,QAAwE;AAClF;AA0QA,SAAgB,qBAAqB,SAAuD;CAC1F,OAAO,QAAQ,IAAI,0BAA0B;AAC/C;AAEA,SAAgB,wBAAwB,SAA2C;CACjF,MAAM,OAAO,qBAAqB,OAAO;CACzC,IAAI,CAAC,MAAM,MAAM,IAAI,MAAM,4DAA4D;CACvF,OAAO;AACT"}
|
|
1
|
+
{"version":3,"file":"headless.mjs","names":[],"sources":["../../src/schemas/headless.ts"],"sourcesContent":["import type { Context } from '@deepseek-ai/cordis';\nimport type { ThinkingLevel } from '@earendil-works/pi-agent-core';\nimport type { CallToolResult, Tool } from '@modelcontextprotocol/sdk/types.js';\nimport type { Static, TSchema } from 'typebox';\n\nimport type { DoomNotificationRequest } from './notification';\nimport type { DoomServerBundleEntry } from './serverBundle';\n\n/** Session-only contributions. This is not a Pi ExtensionAPI or a TUI adapter. */\nexport const DOOM_HEADLESS_HOST_SERVICE = 'doom/headless-host';\nexport const DOOM_HEADLESS_OWNER = Symbol.for('doom/headless-owner');\n\nexport interface DoomHeadlessSelection {\n readonly majorMode: string;\n readonly activeLayers: readonly string[];\n readonly domains: readonly string[];\n readonly profile?: string;\n /** Feature-owned activation sets, keyed by the contributing capability. */\n readonly state?: Readonly<Record<string, readonly string[]>>;\n}\n\n/** One package-owned selection transition. Server facets change exactly one axis per operation. */\nexport type DoomHeadlessSelectionChange =\n | { readonly axis: 'majorMode'; readonly majorMode: string }\n | { readonly axis: 'domains'; readonly domains: readonly string[] }\n | { readonly axis: 'profile'; readonly profile?: string }\n | { readonly axis: 'state'; readonly key: string; readonly values: readonly string[] };\n\nexport function readDoomHeadlessOwner(context: Context): DoomServerBundleEntry | undefined {\n return (context as Context & { [DOOM_HEADLESS_OWNER]?: DoomServerBundleEntry })[DOOM_HEADLESS_OWNER];\n}\n\nexport interface DoomHeadlessRegistration {\n dispose(): void;\n}\n\nexport type DoomHeadlessContent = { type: 'text'; text: string } | { type: 'image'; data: string; mimeType: string };\n\nexport interface DoomHeadlessToolResult {\n content: DoomHeadlessContent[];\n /** Public MCP result data. Internal renderer details are not a remote result contract. */\n structuredContent?: Record<string, unknown>;\n /** Component-only MCP metadata, never inferred from internal renderer details. */\n _meta?: CallToolResult['_meta'];\n details?: unknown;\n isError?: boolean;\n}\n\nexport interface DoomHeadlessClientRequest {\n kind: 'confirm' | 'select' | 'input';\n title: string;\n message?: string;\n options?: readonly { label: string; description?: string; value: string }[];\n initialValue?: string;\n multiline?: boolean;\n}\n\nexport interface DoomHeadlessClient {\n /**\n * Operator-facing surface only: the body is flattened to one line and capped at 4096 characters\n * by schemas/notification.ts:73-83, and the model never sees it. Use session.admitPrompt to\n * reach the model.\n */\n notify(request: DoomNotificationRequest): void | Promise<void>;\n request(request: DoomHeadlessClientRequest, signal?: AbortSignal): Promise<unknown>;\n setStatus(source: string, text: string | undefined): void;\n appendComposerText?(text: string): void;\n}\n\nexport interface DoomHeadlessModelSettings {\n model?: { provider: string; id: string };\n thinkingLevel: ThinkingLevel;\n}\n\nexport interface DoomHeadlessSession {\n readModelSettings?(): Promise<DoomHeadlessModelSettings>;\n setModelSettings?(settings: Partial<DoomHeadlessModelSettings>): Promise<void>;\n /** Query durable history on demand; hosts do not retain the entire transcript. */\n entries(query?: {\n type?: 'custom' | 'message';\n customType?: string;\n limit?: number;\n }): readonly Record<string, unknown>[] | Promise<readonly Record<string, unknown>[]>;\n appendCustomEntry(type: string, data: unknown): Promise<void>;\n /**\n * Delivers and awaits the turn. 'steer' and 'followUp' only enqueue into a running turn; they do\n * NOT wake an idle agent.\n */\n prompt(text: string, delivery?: 'prompt' | 'steer' | 'followUp'): Promise<void>;\n /**\n * Resolves when accepted by the session, before the agent turn settles. Here 'steer' describes\n * how to deliver IF a turn is already running; an idle agent is woken either way, matching Pi's\n * ExtensionAPI.sendMessage({ triggerTurn: true, deliverAs: 'steer' }).\n */\n admitPrompt?(text: string, delivery?: 'prompt' | 'steer' | 'followUp'): Promise<void>;\n abort(): Promise<void>;\n compact(instructions?: string): Promise<void>;\n activity(): Promise<{ hasPendingMessages: boolean; isIdle: boolean }>;\n /** Capture the current persisted branch for an in-process child fork. */\n forkSource?(): Promise<{ kind: 'v4-fork'; sessionFile: string; branch: string; entryId?: string }>;\n}\n\n/** A grant-filtered skill view available only during one remote MCP tool invocation. */\nexport interface DoomMcpSkillAccess {\n list(): Promise<readonly { name: string; description: string }[]>;\n read(name: string): Promise<string>;\n}\n\nexport interface DoomHeadlessExecutionContext {\n readonly cwd: string;\n /** Admitted configuration root, distinct from the tool execution directory. */\n readonly repoRoot: string;\n readonly sessionId: string;\n /** Immutable session configuration. Facets must not read or mutate process.env. */\n readonly environment: Readonly<Record<string, string | undefined>>;\n readonly client: DoomHeadlessClient;\n readonly session: DoomHeadlessSession;\n readonly model?: { provider: string; id: string };\n readonly textCompletion?: {\n available(reference: string): boolean;\n complete(\n reference: string,\n request: {\n systemPrompt: string;\n input: string;\n maxTokens: number;\n cacheRetention?: 'none' | 'short' | 'long';\n signal?: AbortSignal;\n },\n ): Promise<string>;\n };\n readonly selection: DoomHeadlessSelection;\n /** Present only while an authenticated remote MCP tool is running. */\n readonly mcpSkills?: DoomMcpSkillAccess;\n shutdown(): void;\n}\n\n/** Conditions narrow an eligible owner's contributions; they can never restore a disabled owner. */\nexport interface DoomHeadlessCondition {\n state?: Readonly<Record<string, string>>;\n attribution?: { kind: 'minor' | 'domain'; mode: string; label?: string };\n domain?: string;\n}\n\nexport interface DoomHeadlessToolRestriction {\n when?: DoomHeadlessCondition;\n /** Optional capability ceiling. An empty list disables every tool. */\n allowedTools?: readonly string[];\n /**\n * Narrow exclusions without disabling unrelated tools. Exclude a tool your package owns, or a\n * specific foreign tool the mode exists to withdraw. Never enumerate an allowlist here.\n */\n excludedTools?: readonly string[];\n}\n\nexport interface DoomHeadlessTool<TParameters extends TSchema = TSchema> {\n when?: DoomHeadlessCondition;\n name: string;\n label?: string;\n description: string;\n parameters: TParameters;\n annotations?: Tool['annotations'];\n outputSchema?: Tool['outputSchema'];\n /** Remote presentation only. Component tool access must be explicitly opted into. */\n _meta?: Tool['_meta'] & {\n ui?: {\n resourceUri?: string;\n visibility?: ('model' | 'app')[];\n };\n };\n promptSnippet?: string;\n promptGuidelines?: readonly string[];\n executionMode?: 'parallel' | 'serial';\n execute(\n toolCallId: string,\n parameters: Static<TParameters>,\n signal: AbortSignal | undefined,\n onUpdate: ((result: DoomHeadlessToolResult) => void) | undefined,\n context: DoomHeadlessExecutionContext,\n ): Promise<DoomHeadlessToolResult>;\n}\n\n/**\n * One package contribution to the session's resource surface.\n *\n * `kind` decides what the model is billed for, and the difference is large:\n * - `context` is EAGER. `read()` runs on every prompt build and the text is pasted\n * into the system prompt verbatim. Reserve it for small live session state that\n * exists nowhere on disk. Never use it for a file the package ships: a README\n * registered this way costs its full length on every single turn.\n * - `skill` is LAZY. Only `name`, `description` and `path` reach the prompt; the\n * agent reads the file itself when the description matches the task.\n * - `prompt` is inert until the user invokes it by name.\n *\n * The rule in one line: if it is a file the package ships, it is a `skill`.\n */\nexport interface DoomHeadlessResource {\n when?: DoomHeadlessCondition;\n name: string;\n /** Model-visible selection signal. A `skill` without one tells the agent nothing. */\n description?: string;\n /** Absolute path of the file `read()` returns, so an advertised skill is one the agent can open. */\n path?: string;\n kind: 'prompt' | 'skill' | 'context';\n read(context: DoomHeadlessExecutionContext): string | Promise<string>;\n}\n\nexport interface DoomHeadlessCommand {\n when?: DoomHeadlessCondition;\n name: string;\n description: string;\n execute(args: string, context: DoomHeadlessExecutionContext): void | Promise<void>;\n}\n\nexport type DoomHeadlessEventName =\n | 'session_start'\n | 'session_shutdown'\n | 'session_tree'\n | 'before_agent_start'\n | 'agent_start'\n | 'agent_settled'\n | 'turn_start'\n | 'turn_end'\n | 'context'\n | 'before_provider_request'\n | 'message_start'\n | 'message_update'\n | 'message_end'\n | 'tool_call'\n | 'tool_execution_start'\n | 'tool_execution_update'\n | 'tool_execution_end'\n | 'tool_result'\n | 'model_select'\n | 'session_before_compact'\n | 'session_compact';\n\nexport type DoomHeadlessHookEvent<E extends DoomHeadlessEventName> = E extends 'before_provider_request'\n ? { lane: string; runId: string; model: { provider: string; id: string }; payload: unknown }\n : E extends 'session_before_compact'\n ? { reason: string; preparation: unknown; instructions?: string; customInstructions?: string }\n : E extends 'model_select'\n ? { model: { provider: string; id: string } }\n : Readonly<Record<string, unknown>>;\n\nexport interface DoomHeadlessCompactionResult {\n summary: string;\n tokensBefore: number;\n retainedTail: Record<string, unknown>[];\n usage?: Record<string, unknown>;\n details?: unknown;\n}\n\nexport type DoomHeadlessHookResult<E extends DoomHeadlessEventName> = E extends 'before_provider_request'\n ? { payload: unknown } | void\n : E extends 'session_before_compact'\n ? { cancel?: boolean; decline?: boolean; compaction?: DoomHeadlessCompactionResult } | void\n : E extends 'context'\n ? { messages?: unknown[]; systemPrompt?: string } | void\n : E extends 'before_agent_start'\n ? { systemPrompt?: string } | void\n : E extends 'tool_call'\n ? { args?: Record<string, unknown>; block?: { reason: string; terminate?: boolean } } | void\n : E extends 'tool_result'\n ? {\n content?: DoomHeadlessContent[];\n details?: unknown;\n isError?: boolean;\n usage?: Record<string, unknown>;\n terminate?: boolean;\n } | void\n : unknown;\n\nexport type DoomHeadlessHook<E extends DoomHeadlessEventName = DoomHeadlessEventName> = E extends DoomHeadlessEventName\n ? {\n when?: DoomHeadlessCondition;\n event: E;\n handle(\n event: Readonly<DoomHeadlessHookEvent<E>>,\n context: DoomHeadlessExecutionContext,\n ): DoomHeadlessHookResult<E> | Promise<DoomHeadlessHookResult<E>>;\n }\n : never;\n\n/** A retained facet can register activity without starting disabled watchers or services. */\nexport interface DoomHeadlessActivity {\n when?: DoomHeadlessCondition;\n name: string;\n start(context: DoomHeadlessExecutionContext): (() => void | Promise<void>) | Promise<() => void | Promise<void>>;\n}\n\n/** Registrations inherit package ownership from the caller's Cordis facet. */\nexport interface DoomHeadlessHostService {\n readonly context: DoomHeadlessExecutionContext;\n changeSelection(change: DoomHeadlessSelectionChange): Promise<void>;\n assertActive(source?: string): void;\n subscribeSelection(listener: (selection: DoomHeadlessSelection) => void | Promise<void>): () => void;\n registerToolRestriction(restriction: DoomHeadlessToolRestriction): DoomHeadlessRegistration;\n registerTool<TParameters extends TSchema>(tool: DoomHeadlessTool<TParameters>): DoomHeadlessRegistration;\n registerResource(resource: DoomHeadlessResource): DoomHeadlessRegistration;\n registerCommand(command: DoomHeadlessCommand): DoomHeadlessRegistration;\n registerHook(hook: DoomHeadlessHook): DoomHeadlessRegistration;\n registerActivity(activity: DoomHeadlessActivity): DoomHeadlessRegistration;\n}\n\ndeclare module '@deepseek-ai/cordis' {\n interface Context {\n 'doom/headless-host': DoomHeadlessHostService;\n }\n}\n\nexport function readDoomHeadlessHost(context: Context): DoomHeadlessHostService | undefined {\n return context.get(DOOM_HEADLESS_HOST_SERVICE) as DoomHeadlessHostService | undefined;\n}\n\nexport function requireDoomHeadlessHost(context: Context): DoomHeadlessHostService {\n const host = readDoomHeadlessHost(context);\n if (!host) throw new Error('This contribution requires the Doom headless session host.');\n return host;\n}\n"],"mappings":";;AASA,MAAa,6BAA6B;AAC1C,MAAa,sBAAsB,OAAO,IAAI,qBAAqB;AAkBnE,SAAgB,sBAAsB,SAAqD;CACzF,OAAQ,QAAwE;AAClF;AAyRA,SAAgB,qBAAqB,SAAuD;CAC1F,OAAO,QAAQ,IAAI,0BAA0B;AAC/C;AAEA,SAAgB,wBAAwB,SAA2C;CACjF,MAAM,OAAO,qBAAqB,OAAO;CACzC,IAAI,CAAC,MAAM,MAAM,IAAI,MAAM,4DAA4D;CACvF,OAAO;AACT"}
|
|
@@ -11,9 +11,14 @@ function defineMcpTool(tool) {
|
|
|
11
11
|
function defineMcpSkill(skill) {
|
|
12
12
|
return skill;
|
|
13
13
|
}
|
|
14
|
+
/** `resource/[name].mcp.ts`. Static UI resources stay separate from session guidance. */
|
|
15
|
+
function defineMcpUiResource(resource) {
|
|
16
|
+
return resource;
|
|
17
|
+
}
|
|
14
18
|
//#endregion
|
|
15
19
|
exports.defineMcpPlugin = defineMcpPlugin;
|
|
16
20
|
exports.defineMcpSkill = defineMcpSkill;
|
|
17
21
|
exports.defineMcpTool = defineMcpTool;
|
|
22
|
+
exports.defineMcpUiResource = defineMcpUiResource;
|
|
18
23
|
|
|
19
24
|
//# sourceMappingURL=mcpFacet.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcpFacet.cjs","names":[],"sources":["../../src/schemas/mcpFacet.ts"],"sourcesContent":["import type { TSchema } from 'typebox';\n\nimport type {\n DoomHeadlessExecutionContext,\n DoomHeadlessSelection,\n DoomHeadlessSelectionChange,\n DoomHeadlessTool,\n} from './headless';\n\n/** Repository-scoped instructions and applied selection safe to disclose to a remote MCP client. */\nexport interface DoomMcpContextSnapshot {\n readonly session: { readonly id: string; readonly revision: number };\n readonly repository: { readonly root: string; readonly cwd: string };\n readonly selection: {\n readonly profile: string | null;\n readonly domains: readonly string[];\n readonly majorMode: string;\n readonly activeLayers: readonly string[];\n readonly minorModes?: readonly string[];\n };\n readonly instructions: readonly { readonly path: string; readonly content: string }[];\n readonly persona: string | null;\n}\n\n/** A lazy Markdown resource available only to remote MCP clients. */\nexport interface DoomMcpSkill {\n readonly name: string;\n readonly description: string;\n read(context: DoomHeadlessExecutionContext): string | Promise<string>;\n}\n\n/** A dedicated remote surface, deliberately separate from local agent registrations. */\nexport interface DoomMcpSessionPlugin {\n readonly tools?: readonly DoomHeadlessTool<TSchema>[];\n readonly skills?: readonly DoomMcpSkill[];\n}\n\nexport interface DoomMcpServiceScope {\n /** Reads a service already mounted in this session without exposing host registration APIs. */\n get<T>(name: string): T | undefined;\n}\n\nexport interface DoomMcpPluginContext {\n readonly execution: DoomHeadlessExecutionContext;\n readonly services: DoomMcpServiceScope;\n readonly selection: {\n read(): DoomHeadlessSelection;\n change(change: DoomHeadlessSelectionChange): Promise<void>;\n };\n /** Reads the allowlisted repository context from the current applied session selection. */\n loadContext(): DoomMcpContextSnapshot;\n /** Aborted when this plugin surface is replaced or the session closes. */\n readonly signal: AbortSignal;\n /** Rebuilds the remote surface after a live MCP catalog changes. */\n refresh(): void;\n}\n\nexport interface DoomMcpPluginDefinition {\n readonly name: string;\n readonly session:\n | DoomMcpSessionPlugin\n | ((context: DoomMcpPluginContext) => DoomMcpSessionPlugin | Promise<DoomMcpSessionPlugin>);\n}\n\n/** Makes an MCP declaration's contract explicit without registering it locally. */\nexport function defineMcpPlugin(definition: DoomMcpPluginDefinition): DoomMcpPluginDefinition {\n return definition;\n}\n\n/** `tool/[name].mcp.ts`. Keeps the declaration independently typed. */\nexport function defineMcpTool<TParameters extends TSchema = TSchema, TContext = unknown>(\n tool: DoomHeadlessTool<TParameters> | ((context: TContext) => DoomHeadlessTool<TParameters>),\n): DoomHeadlessTool<TParameters> | ((context: TContext) => DoomHeadlessTool<TParameters>) {\n return tool;\n}\n\n/** `skill/[name].mcp.ts`. Keeps remote guidance out of the local prompt surface. */\nexport function defineMcpSkill<TContext = unknown>(\n skill: DoomMcpSkill | ((context: TContext) => DoomMcpSkill),\n): DoomMcpSkill | ((context: TContext) => DoomMcpSkill) {\n return skill;\n}\n"],"mappings":";;
|
|
1
|
+
{"version":3,"file":"mcpFacet.cjs","names":[],"sources":["../../src/schemas/mcpFacet.ts"],"sourcesContent":["import type { TSchema } from 'typebox';\n\nimport type {\n DoomHeadlessExecutionContext,\n DoomHeadlessSelection,\n DoomHeadlessSelectionChange,\n DoomHeadlessTool,\n} from './headless';\n\n/** Repository-scoped instructions and applied selection safe to disclose to a remote MCP client. */\nexport interface DoomMcpContextSnapshot {\n readonly session: { readonly id: string; readonly revision: number };\n readonly repository: { readonly root: string; readonly cwd: string };\n readonly selection: {\n readonly profile: string | null;\n readonly domains: readonly string[];\n readonly majorMode: string;\n readonly activeLayers: readonly string[];\n readonly minorModes?: readonly string[];\n };\n readonly instructions: readonly { readonly path: string; readonly content: string }[];\n readonly persona: string | null;\n}\n\n/** A lazy Markdown resource available only to remote MCP clients. */\nexport interface DoomMcpSkill {\n readonly name: string;\n readonly description: string;\n read(context: DoomHeadlessExecutionContext): string | Promise<string>;\n}\n\n/** A package-owned, immutable UI template. Session data belongs in tool results, never in this HTML. */\nexport interface DoomMcpUiResource {\n readonly uri: string;\n readonly name: string;\n readonly description?: string;\n readonly mimeType: 'text/html;profile=mcp-app';\n readonly _meta?: Record<string, unknown> & {\n ui?: {\n csp?: {\n connectDomains?: string[];\n resourceDomains?: string[];\n frameDomains?: string[];\n baseUriDomains?: string[];\n };\n domain?: string;\n prefersBorder?: boolean;\n };\n };\n /** Loads static packaged HTML without an execution context. */\n read(): string | Promise<string>;\n}\n\n/** A dedicated remote surface, deliberately separate from local agent registrations. */\nexport interface DoomMcpSessionPlugin {\n readonly tools?: readonly DoomHeadlessTool<TSchema>[];\n readonly skills?: readonly DoomMcpSkill[];\n readonly uiResources?: readonly DoomMcpUiResource[];\n}\n\nexport interface DoomMcpServiceScope {\n /** Reads a service already mounted in this session without exposing host registration APIs. */\n get<T>(name: string): T | undefined;\n}\n\nexport interface DoomMcpPluginContext {\n readonly execution: DoomHeadlessExecutionContext;\n readonly services: DoomMcpServiceScope;\n readonly selection: {\n read(): DoomHeadlessSelection;\n change(change: DoomHeadlessSelectionChange): Promise<void>;\n };\n /** Reads the allowlisted repository context from the current applied session selection. */\n loadContext(): DoomMcpContextSnapshot;\n /** Aborted when this plugin surface is replaced or the session closes. */\n readonly signal: AbortSignal;\n /** Rebuilds the remote surface after a live MCP catalog changes. */\n refresh(): void;\n}\n\nexport interface DoomMcpPluginDefinition {\n readonly name: string;\n readonly session:\n | DoomMcpSessionPlugin\n | ((context: DoomMcpPluginContext) => DoomMcpSessionPlugin | Promise<DoomMcpSessionPlugin>);\n}\n\n/** Makes an MCP declaration's contract explicit without registering it locally. */\nexport function defineMcpPlugin(definition: DoomMcpPluginDefinition): DoomMcpPluginDefinition {\n return definition;\n}\n\n/** `tool/[name].mcp.ts`. Keeps the declaration independently typed. */\nexport function defineMcpTool<TParameters extends TSchema = TSchema, TContext = unknown>(\n tool: DoomHeadlessTool<TParameters> | ((context: TContext) => DoomHeadlessTool<TParameters>),\n): DoomHeadlessTool<TParameters> | ((context: TContext) => DoomHeadlessTool<TParameters>) {\n return tool;\n}\n\n/** `skill/[name].mcp.ts`. Keeps remote guidance out of the local prompt surface. */\nexport function defineMcpSkill<TContext = unknown>(\n skill: DoomMcpSkill | ((context: TContext) => DoomMcpSkill),\n): DoomMcpSkill | ((context: TContext) => DoomMcpSkill) {\n return skill;\n}\n\n/** `resource/[name].mcp.ts`. Static UI resources stay separate from session guidance. */\nexport function defineMcpUiResource(resource: DoomMcpUiResource): DoomMcpUiResource {\n return resource;\n}\n"],"mappings":";;AAwFA,SAAgB,gBAAgB,YAA8D;CAC5F,OAAO;AACT;;AAGA,SAAgB,cACd,MACwF;CACxF,OAAO;AACT;;AAGA,SAAgB,eACd,OACsD;CACtD,OAAO;AACT;;AAGA,SAAgB,oBAAoB,UAAgD;CAClF,OAAO;AACT"}
|
|
@@ -30,10 +30,32 @@ export interface DoomMcpSkill {
|
|
|
30
30
|
readonly description: string;
|
|
31
31
|
read(context: DoomHeadlessExecutionContext): string | Promise<string>;
|
|
32
32
|
}
|
|
33
|
+
/** A package-owned, immutable UI template. Session data belongs in tool results, never in this HTML. */
|
|
34
|
+
export interface DoomMcpUiResource {
|
|
35
|
+
readonly uri: string;
|
|
36
|
+
readonly name: string;
|
|
37
|
+
readonly description?: string;
|
|
38
|
+
readonly mimeType: 'text/html;profile=mcp-app';
|
|
39
|
+
readonly _meta?: Record<string, unknown> & {
|
|
40
|
+
ui?: {
|
|
41
|
+
csp?: {
|
|
42
|
+
connectDomains?: string[];
|
|
43
|
+
resourceDomains?: string[];
|
|
44
|
+
frameDomains?: string[];
|
|
45
|
+
baseUriDomains?: string[];
|
|
46
|
+
};
|
|
47
|
+
domain?: string;
|
|
48
|
+
prefersBorder?: boolean;
|
|
49
|
+
};
|
|
50
|
+
};
|
|
51
|
+
/** Loads static packaged HTML without an execution context. */
|
|
52
|
+
read(): string | Promise<string>;
|
|
53
|
+
}
|
|
33
54
|
/** A dedicated remote surface, deliberately separate from local agent registrations. */
|
|
34
55
|
export interface DoomMcpSessionPlugin {
|
|
35
56
|
readonly tools?: readonly DoomHeadlessTool<TSchema>[];
|
|
36
57
|
readonly skills?: readonly DoomMcpSkill[];
|
|
58
|
+
readonly uiResources?: readonly DoomMcpUiResource[];
|
|
37
59
|
}
|
|
38
60
|
export interface DoomMcpServiceScope {
|
|
39
61
|
/** Reads a service already mounted in this session without exposing host registration APIs. */
|
|
@@ -63,5 +85,7 @@ export declare function defineMcpPlugin(definition: DoomMcpPluginDefinition): Do
|
|
|
63
85
|
export declare function defineMcpTool<TParameters extends TSchema = TSchema, TContext = unknown>(tool: DoomHeadlessTool<TParameters> | ((context: TContext) => DoomHeadlessTool<TParameters>)): DoomHeadlessTool<TParameters> | ((context: TContext) => DoomHeadlessTool<TParameters>);
|
|
64
86
|
/** `skill/[name].mcp.ts`. Keeps remote guidance out of the local prompt surface. */
|
|
65
87
|
export declare function defineMcpSkill<TContext = unknown>(skill: DoomMcpSkill | ((context: TContext) => DoomMcpSkill)): DoomMcpSkill | ((context: TContext) => DoomMcpSkill);
|
|
88
|
+
/** `resource/[name].mcp.ts`. Static UI resources stay separate from session guidance. */
|
|
89
|
+
export declare function defineMcpUiResource(resource: DoomMcpUiResource): DoomMcpUiResource;
|
|
66
90
|
//#endregion
|
|
67
91
|
//# sourceMappingURL=mcpFacet.d.cts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcpFacet.d.cts","names":[],"sources":["../../src/schemas/mcpFacet.ts"],"mappings":";;;;iBAUiB;WACN;aAAoB;aAAqB;;WACzC;aAAuB;aAAuB;;WAC9C;aACE;aACA;aACA;aACA;aACA;;WAEF;aAAkC;aAAuB;;WACzD;;;iBAIM;WACN;WACA;EACT,KAAK,SAAS,wCAAwC;;;iBAIvC;WACN,iBAAiB,iBAAiB;WAClC,kBAAkB;;
|
|
1
|
+
{"version":3,"file":"mcpFacet.d.cts","names":[],"sources":["../../src/schemas/mcpFacet.ts"],"mappings":";;;;iBAUiB;WACN;aAAoB;aAAqB;;WACzC;aAAuB;aAAuB;;WAC9C;aACE;aACA;aACA;aACA;aACA;;WAEF;aAAkC;aAAuB;;WACzD;;;iBAIM;WACN;WACA;EACT,KAAK,SAAS,wCAAwC;;;iBAIvC;WACN;WACA;WACA;WACA;WACA,QAAQ;IACf;MACE;QACE;QACA;QACA;QACA;;MAEF;MACA;;;;EAIJ,iBAAiB;;;iBAIF;WACN,iBAAiB,iBAAiB;WAClC,kBAAkB;WAClB,uBAAuB;;iBAGjB;;EAEf,IAAI,GAAG,eAAe;;iBAGP;WACN,WAAW;WACX,UAAU;WACV;IACP,QAAQ;IACR,OAAO,QAAQ,8BAA8B;;;EAG/C,eAAe;;WAEN,QAAQ;;EAEjB;;iBAGe;WACN;WACA,SACL,yBACE,SAAS,yBAAyB,uBAAuB,QAAQ;;;wBAIzD,gBAAgB,YAAY,0BAA0B;;wBAKtD,cAAc,oBAAoB,UAAU,SAAS,oBACnE,MAAM,iBAAiB,iBAAiB,SAAS,aAAa,iBAAiB,gBAC9E,iBAAiB,iBAAiB,SAAS,aAAa,iBAAiB;;wBAK5D,eAAe,oBAC7B,OAAO,iBAAiB,SAAS,aAAa,gBAC7C,iBAAiB,SAAS,aAAa;;wBAK1B,oBAAoB,UAAU,oBAAoB"}
|
|
@@ -30,10 +30,32 @@ export interface DoomMcpSkill {
|
|
|
30
30
|
readonly description: string;
|
|
31
31
|
read(context: DoomHeadlessExecutionContext): string | Promise<string>;
|
|
32
32
|
}
|
|
33
|
+
/** A package-owned, immutable UI template. Session data belongs in tool results, never in this HTML. */
|
|
34
|
+
export interface DoomMcpUiResource {
|
|
35
|
+
readonly uri: string;
|
|
36
|
+
readonly name: string;
|
|
37
|
+
readonly description?: string;
|
|
38
|
+
readonly mimeType: 'text/html;profile=mcp-app';
|
|
39
|
+
readonly _meta?: Record<string, unknown> & {
|
|
40
|
+
ui?: {
|
|
41
|
+
csp?: {
|
|
42
|
+
connectDomains?: string[];
|
|
43
|
+
resourceDomains?: string[];
|
|
44
|
+
frameDomains?: string[];
|
|
45
|
+
baseUriDomains?: string[];
|
|
46
|
+
};
|
|
47
|
+
domain?: string;
|
|
48
|
+
prefersBorder?: boolean;
|
|
49
|
+
};
|
|
50
|
+
};
|
|
51
|
+
/** Loads static packaged HTML without an execution context. */
|
|
52
|
+
read(): string | Promise<string>;
|
|
53
|
+
}
|
|
33
54
|
/** A dedicated remote surface, deliberately separate from local agent registrations. */
|
|
34
55
|
export interface DoomMcpSessionPlugin {
|
|
35
56
|
readonly tools?: readonly DoomHeadlessTool<TSchema>[];
|
|
36
57
|
readonly skills?: readonly DoomMcpSkill[];
|
|
58
|
+
readonly uiResources?: readonly DoomMcpUiResource[];
|
|
37
59
|
}
|
|
38
60
|
export interface DoomMcpServiceScope {
|
|
39
61
|
/** Reads a service already mounted in this session without exposing host registration APIs. */
|
|
@@ -63,5 +85,7 @@ export declare function defineMcpPlugin(definition: DoomMcpPluginDefinition): Do
|
|
|
63
85
|
export declare function defineMcpTool<TParameters extends TSchema = TSchema, TContext = unknown>(tool: DoomHeadlessTool<TParameters> | ((context: TContext) => DoomHeadlessTool<TParameters>)): DoomHeadlessTool<TParameters> | ((context: TContext) => DoomHeadlessTool<TParameters>);
|
|
64
86
|
/** `skill/[name].mcp.ts`. Keeps remote guidance out of the local prompt surface. */
|
|
65
87
|
export declare function defineMcpSkill<TContext = unknown>(skill: DoomMcpSkill | ((context: TContext) => DoomMcpSkill)): DoomMcpSkill | ((context: TContext) => DoomMcpSkill);
|
|
88
|
+
/** `resource/[name].mcp.ts`. Static UI resources stay separate from session guidance. */
|
|
89
|
+
export declare function defineMcpUiResource(resource: DoomMcpUiResource): DoomMcpUiResource;
|
|
66
90
|
//#endregion
|
|
67
91
|
//# sourceMappingURL=mcpFacet.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcpFacet.d.mts","names":[],"sources":["../../src/schemas/mcpFacet.ts"],"mappings":";;;;iBAUiB;WACN;aAAoB;aAAqB;;WACzC;aAAuB;aAAuB;;WAC9C;aACE;aACA;aACA;aACA;aACA;;WAEF;aAAkC;aAAuB;;WACzD;;;iBAIM;WACN;WACA;EACT,KAAK,SAAS,wCAAwC;;;iBAIvC;WACN,iBAAiB,iBAAiB;WAClC,kBAAkB;;
|
|
1
|
+
{"version":3,"file":"mcpFacet.d.mts","names":[],"sources":["../../src/schemas/mcpFacet.ts"],"mappings":";;;;iBAUiB;WACN;aAAoB;aAAqB;;WACzC;aAAuB;aAAuB;;WAC9C;aACE;aACA;aACA;aACA;aACA;;WAEF;aAAkC;aAAuB;;WACzD;;;iBAIM;WACN;WACA;EACT,KAAK,SAAS,wCAAwC;;;iBAIvC;WACN;WACA;WACA;WACA;WACA,QAAQ;IACf;MACE;QACE;QACA;QACA;QACA;;MAEF;MACA;;;;EAIJ,iBAAiB;;;iBAIF;WACN,iBAAiB,iBAAiB;WAClC,kBAAkB;WAClB,uBAAuB;;iBAGjB;;EAEf,IAAI,GAAG,eAAe;;iBAGP;WACN,WAAW;WACX,UAAU;WACV;IACP,QAAQ;IACR,OAAO,QAAQ,8BAA8B;;;EAG/C,eAAe;;WAEN,QAAQ;;EAEjB;;iBAGe;WACN;WACA,SACL,yBACE,SAAS,yBAAyB,uBAAuB,QAAQ;;;wBAIzD,gBAAgB,YAAY,0BAA0B;;wBAKtD,cAAc,oBAAoB,UAAU,SAAS,oBACnE,MAAM,iBAAiB,iBAAiB,SAAS,aAAa,iBAAiB,gBAC9E,iBAAiB,iBAAiB,SAAS,aAAa,iBAAiB;;wBAK5D,eAAe,oBAC7B,OAAO,iBAAiB,SAAS,aAAa,gBAC7C,iBAAiB,SAAS,aAAa;;wBAK1B,oBAAoB,UAAU,oBAAoB"}
|
|
@@ -11,7 +11,11 @@ function defineMcpTool(tool) {
|
|
|
11
11
|
function defineMcpSkill(skill) {
|
|
12
12
|
return skill;
|
|
13
13
|
}
|
|
14
|
+
/** `resource/[name].mcp.ts`. Static UI resources stay separate from session guidance. */
|
|
15
|
+
function defineMcpUiResource(resource) {
|
|
16
|
+
return resource;
|
|
17
|
+
}
|
|
14
18
|
//#endregion
|
|
15
|
-
export { defineMcpPlugin, defineMcpSkill, defineMcpTool };
|
|
19
|
+
export { defineMcpPlugin, defineMcpSkill, defineMcpTool, defineMcpUiResource };
|
|
16
20
|
|
|
17
21
|
//# sourceMappingURL=mcpFacet.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcpFacet.mjs","names":[],"sources":["../../src/schemas/mcpFacet.ts"],"sourcesContent":["import type { TSchema } from 'typebox';\n\nimport type {\n DoomHeadlessExecutionContext,\n DoomHeadlessSelection,\n DoomHeadlessSelectionChange,\n DoomHeadlessTool,\n} from './headless';\n\n/** Repository-scoped instructions and applied selection safe to disclose to a remote MCP client. */\nexport interface DoomMcpContextSnapshot {\n readonly session: { readonly id: string; readonly revision: number };\n readonly repository: { readonly root: string; readonly cwd: string };\n readonly selection: {\n readonly profile: string | null;\n readonly domains: readonly string[];\n readonly majorMode: string;\n readonly activeLayers: readonly string[];\n readonly minorModes?: readonly string[];\n };\n readonly instructions: readonly { readonly path: string; readonly content: string }[];\n readonly persona: string | null;\n}\n\n/** A lazy Markdown resource available only to remote MCP clients. */\nexport interface DoomMcpSkill {\n readonly name: string;\n readonly description: string;\n read(context: DoomHeadlessExecutionContext): string | Promise<string>;\n}\n\n/** A dedicated remote surface, deliberately separate from local agent registrations. */\nexport interface DoomMcpSessionPlugin {\n readonly tools?: readonly DoomHeadlessTool<TSchema>[];\n readonly skills?: readonly DoomMcpSkill[];\n}\n\nexport interface DoomMcpServiceScope {\n /** Reads a service already mounted in this session without exposing host registration APIs. */\n get<T>(name: string): T | undefined;\n}\n\nexport interface DoomMcpPluginContext {\n readonly execution: DoomHeadlessExecutionContext;\n readonly services: DoomMcpServiceScope;\n readonly selection: {\n read(): DoomHeadlessSelection;\n change(change: DoomHeadlessSelectionChange): Promise<void>;\n };\n /** Reads the allowlisted repository context from the current applied session selection. */\n loadContext(): DoomMcpContextSnapshot;\n /** Aborted when this plugin surface is replaced or the session closes. */\n readonly signal: AbortSignal;\n /** Rebuilds the remote surface after a live MCP catalog changes. */\n refresh(): void;\n}\n\nexport interface DoomMcpPluginDefinition {\n readonly name: string;\n readonly session:\n | DoomMcpSessionPlugin\n | ((context: DoomMcpPluginContext) => DoomMcpSessionPlugin | Promise<DoomMcpSessionPlugin>);\n}\n\n/** Makes an MCP declaration's contract explicit without registering it locally. */\nexport function defineMcpPlugin(definition: DoomMcpPluginDefinition): DoomMcpPluginDefinition {\n return definition;\n}\n\n/** `tool/[name].mcp.ts`. Keeps the declaration independently typed. */\nexport function defineMcpTool<TParameters extends TSchema = TSchema, TContext = unknown>(\n tool: DoomHeadlessTool<TParameters> | ((context: TContext) => DoomHeadlessTool<TParameters>),\n): DoomHeadlessTool<TParameters> | ((context: TContext) => DoomHeadlessTool<TParameters>) {\n return tool;\n}\n\n/** `skill/[name].mcp.ts`. Keeps remote guidance out of the local prompt surface. */\nexport function defineMcpSkill<TContext = unknown>(\n skill: DoomMcpSkill | ((context: TContext) => DoomMcpSkill),\n): DoomMcpSkill | ((context: TContext) => DoomMcpSkill) {\n return skill;\n}\n"],"mappings":";;
|
|
1
|
+
{"version":3,"file":"mcpFacet.mjs","names":[],"sources":["../../src/schemas/mcpFacet.ts"],"sourcesContent":["import type { TSchema } from 'typebox';\n\nimport type {\n DoomHeadlessExecutionContext,\n DoomHeadlessSelection,\n DoomHeadlessSelectionChange,\n DoomHeadlessTool,\n} from './headless';\n\n/** Repository-scoped instructions and applied selection safe to disclose to a remote MCP client. */\nexport interface DoomMcpContextSnapshot {\n readonly session: { readonly id: string; readonly revision: number };\n readonly repository: { readonly root: string; readonly cwd: string };\n readonly selection: {\n readonly profile: string | null;\n readonly domains: readonly string[];\n readonly majorMode: string;\n readonly activeLayers: readonly string[];\n readonly minorModes?: readonly string[];\n };\n readonly instructions: readonly { readonly path: string; readonly content: string }[];\n readonly persona: string | null;\n}\n\n/** A lazy Markdown resource available only to remote MCP clients. */\nexport interface DoomMcpSkill {\n readonly name: string;\n readonly description: string;\n read(context: DoomHeadlessExecutionContext): string | Promise<string>;\n}\n\n/** A package-owned, immutable UI template. Session data belongs in tool results, never in this HTML. */\nexport interface DoomMcpUiResource {\n readonly uri: string;\n readonly name: string;\n readonly description?: string;\n readonly mimeType: 'text/html;profile=mcp-app';\n readonly _meta?: Record<string, unknown> & {\n ui?: {\n csp?: {\n connectDomains?: string[];\n resourceDomains?: string[];\n frameDomains?: string[];\n baseUriDomains?: string[];\n };\n domain?: string;\n prefersBorder?: boolean;\n };\n };\n /** Loads static packaged HTML without an execution context. */\n read(): string | Promise<string>;\n}\n\n/** A dedicated remote surface, deliberately separate from local agent registrations. */\nexport interface DoomMcpSessionPlugin {\n readonly tools?: readonly DoomHeadlessTool<TSchema>[];\n readonly skills?: readonly DoomMcpSkill[];\n readonly uiResources?: readonly DoomMcpUiResource[];\n}\n\nexport interface DoomMcpServiceScope {\n /** Reads a service already mounted in this session without exposing host registration APIs. */\n get<T>(name: string): T | undefined;\n}\n\nexport interface DoomMcpPluginContext {\n readonly execution: DoomHeadlessExecutionContext;\n readonly services: DoomMcpServiceScope;\n readonly selection: {\n read(): DoomHeadlessSelection;\n change(change: DoomHeadlessSelectionChange): Promise<void>;\n };\n /** Reads the allowlisted repository context from the current applied session selection. */\n loadContext(): DoomMcpContextSnapshot;\n /** Aborted when this plugin surface is replaced or the session closes. */\n readonly signal: AbortSignal;\n /** Rebuilds the remote surface after a live MCP catalog changes. */\n refresh(): void;\n}\n\nexport interface DoomMcpPluginDefinition {\n readonly name: string;\n readonly session:\n | DoomMcpSessionPlugin\n | ((context: DoomMcpPluginContext) => DoomMcpSessionPlugin | Promise<DoomMcpSessionPlugin>);\n}\n\n/** Makes an MCP declaration's contract explicit without registering it locally. */\nexport function defineMcpPlugin(definition: DoomMcpPluginDefinition): DoomMcpPluginDefinition {\n return definition;\n}\n\n/** `tool/[name].mcp.ts`. Keeps the declaration independently typed. */\nexport function defineMcpTool<TParameters extends TSchema = TSchema, TContext = unknown>(\n tool: DoomHeadlessTool<TParameters> | ((context: TContext) => DoomHeadlessTool<TParameters>),\n): DoomHeadlessTool<TParameters> | ((context: TContext) => DoomHeadlessTool<TParameters>) {\n return tool;\n}\n\n/** `skill/[name].mcp.ts`. Keeps remote guidance out of the local prompt surface. */\nexport function defineMcpSkill<TContext = unknown>(\n skill: DoomMcpSkill | ((context: TContext) => DoomMcpSkill),\n): DoomMcpSkill | ((context: TContext) => DoomMcpSkill) {\n return skill;\n}\n\n/** `resource/[name].mcp.ts`. Static UI resources stay separate from session guidance. */\nexport function defineMcpUiResource(resource: DoomMcpUiResource): DoomMcpUiResource {\n return resource;\n}\n"],"mappings":";;AAwFA,SAAgB,gBAAgB,YAA8D;CAC5F,OAAO;AACT;;AAGA,SAAgB,cACd,MACwF;CACxF,OAAO;AACT;;AAGA,SAAgB,eACd,OACsD;CACtD,OAAO;AACT;;AAGA,SAAgB,oBAAoB,UAAgD;CAClF,OAAO;AACT"}
|
|
@@ -37,10 +37,13 @@ function grantedSurface(grant, surface) {
|
|
|
37
37
|
const snapshot = surface.readSurface();
|
|
38
38
|
const toolNames = new Set(grant.tools);
|
|
39
39
|
const skillNames = new Set(grant.skills);
|
|
40
|
+
const tools = grant.scope === "session" ? snapshot.tools : snapshot.tools.filter((tool) => toolNames.has(tool.name));
|
|
41
|
+
const resourceUris = new Set(tools.map((tool) => tool._meta?.ui?.resourceUri));
|
|
40
42
|
return {
|
|
41
43
|
snapshot,
|
|
42
|
-
tools
|
|
43
|
-
skills: grant.scope === "session" ? snapshot.skills : snapshot.skills.filter((skill) => skillNames.has(skill.name))
|
|
44
|
+
tools,
|
|
45
|
+
skills: grant.scope === "session" ? snapshot.skills : snapshot.skills.filter((skill) => skillNames.has(skill.name)),
|
|
46
|
+
uiResources: (snapshot.uiResources ?? []).filter((resource) => resourceUris.has(resource.uri))
|
|
44
47
|
};
|
|
45
48
|
}
|
|
46
49
|
/** Creates a Bearer-only, stateless Streamable HTTP MCP request handler for session capabilities. */
|
|
@@ -108,7 +111,14 @@ function createSessionMcpHttpHandler(options) {
|
|
|
108
111
|
description: tool.description,
|
|
109
112
|
inputSchema: tool.parameters,
|
|
110
113
|
...tool.annotations === void 0 ? {} : { annotations: tool.annotations },
|
|
111
|
-
...tool.outputSchema === void 0 ? {} : { outputSchema: tool.outputSchema }
|
|
114
|
+
...tool.outputSchema === void 0 ? {} : { outputSchema: tool.outputSchema },
|
|
115
|
+
_meta: {
|
|
116
|
+
...tool._meta,
|
|
117
|
+
ui: {
|
|
118
|
+
...tool._meta?.ui,
|
|
119
|
+
visibility: tool._meta?.ui?.visibility ?? ["model"]
|
|
120
|
+
}
|
|
121
|
+
}
|
|
112
122
|
})) };
|
|
113
123
|
});
|
|
114
124
|
server.setRequestHandler(_modelcontextprotocol_sdk_types_js.CallToolRequestSchema, async (message, extra) => {
|
|
@@ -152,7 +162,7 @@ function createSessionMcpHttpHandler(options) {
|
|
|
152
162
|
const active = await resolveTarget(true);
|
|
153
163
|
const { snapshot, tools } = grantedSurface(active.grant, active.target.toolSurface);
|
|
154
164
|
const selected = tools.find((tool) => tool.name === message.params.name);
|
|
155
|
-
if (!selected || !(0, node_util.isDeepStrictEqual)(selected.parameters, advertised.parameters) || !(0, node_util.isDeepStrictEqual)(selected.outputSchema, advertised.outputSchema) || !(0, node_util.isDeepStrictEqual)(selected.annotations, advertised.annotations)) throw new require_index.SessionMcpConversationError("SESSION_TOOL_SURFACE_CHANGED", "The target session does not expose the approved tool contract. Refresh the connection or restore a compatible session selection.");
|
|
165
|
+
if (!selected || !(0, node_util.isDeepStrictEqual)(selected.parameters, advertised.parameters) || !(0, node_util.isDeepStrictEqual)(selected.outputSchema, advertised.outputSchema) || !(0, node_util.isDeepStrictEqual)(selected.annotations, advertised.annotations) || !(0, node_util.isDeepStrictEqual)(selected._meta, advertised._meta)) throw new require_index.SessionMcpConversationError("SESSION_TOOL_SURFACE_CHANGED", "The target session does not expose the approved tool contract. Refresh the connection or restore a compatible session selection.");
|
|
156
166
|
const recheck = async () => {
|
|
157
167
|
const current = await resolveTarget(false);
|
|
158
168
|
if (current.target.toolSurface !== active.target.toolSurface || current.target.generation !== active.target.generation || current.target.sessionId !== active.target.sessionId) throw new _modelcontextprotocol_sdk_types_js.McpError(_modelcontextprotocol_sdk_types_js.ErrorCode.InvalidRequest, "The session tool surface has changed.");
|
|
@@ -198,6 +208,7 @@ function createSessionMcpHttpHandler(options) {
|
|
|
198
208
|
return {
|
|
199
209
|
content: result.content,
|
|
200
210
|
...result.structuredContent === void 0 ? {} : { structuredContent: result.structuredContent },
|
|
211
|
+
...result._meta === void 0 ? {} : { _meta: result._meta },
|
|
201
212
|
isError: result.isError ?? false
|
|
202
213
|
};
|
|
203
214
|
} catch (error) {
|
|
@@ -221,19 +232,32 @@ function createSessionMcpHttpHandler(options) {
|
|
|
221
232
|
});
|
|
222
233
|
server.setRequestHandler(_modelcontextprotocol_sdk_types_js.ListResourcesRequestSchema, async () => {
|
|
223
234
|
const active = await authorizeOperation();
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
return { resources: skills.map((skill) => ({
|
|
235
|
+
const { skills, uiResources } = grantedSurface(active.grant, active.target.toolSurface);
|
|
236
|
+
return { resources: [...uiResources, ...active.grant.routing === "conversation" ? [] : skills.map((skill) => ({
|
|
227
237
|
uri: skill.uri,
|
|
228
238
|
name: skill.name,
|
|
229
239
|
description: skill.description,
|
|
230
240
|
mimeType: "text/markdown"
|
|
231
|
-
})) };
|
|
241
|
+
}))] };
|
|
232
242
|
});
|
|
233
243
|
server.setRequestHandler(_modelcontextprotocol_sdk_types_js.ReadResourceRequestSchema, async (message) => {
|
|
234
244
|
const active = await authorizeOperation();
|
|
245
|
+
const { snapshot, skills, uiResources } = grantedSurface(active.grant, active.target.toolSurface);
|
|
246
|
+
const resource = uiResources.find((candidate) => candidate.uri === message.params.uri);
|
|
247
|
+
if (resource !== void 0 && active.target.toolSurface.readUiResource !== void 0) {
|
|
248
|
+
request.signal.throwIfAborted();
|
|
249
|
+
const text = await active.target.toolSurface.readUiResource(snapshot.revision, resource.uri);
|
|
250
|
+
request.signal.throwIfAborted();
|
|
251
|
+
const current = await authorizeOperation();
|
|
252
|
+
const after = grantedSurface(current.grant, current.target.toolSurface);
|
|
253
|
+
if (current.target.toolSurface !== active.target.toolSurface || after.snapshot.revision !== snapshot.revision || !(0, node_util.isDeepStrictEqual)(after.uiResources.find((candidate) => candidate.uri === resource.uri), resource)) throw new _modelcontextprotocol_sdk_types_js.McpError(_modelcontextprotocol_sdk_types_js.ErrorCode.InvalidRequest, "The session UI resource surface has changed.");
|
|
254
|
+
return { contents: [{
|
|
255
|
+
...resource,
|
|
256
|
+
text
|
|
257
|
+
}] };
|
|
258
|
+
}
|
|
259
|
+
if (message.params.uri.startsWith("ui:")) throw new _modelcontextprotocol_sdk_types_js.McpError(_modelcontextprotocol_sdk_types_js.ErrorCode.InvalidParams, "UI resource is not granted or active.");
|
|
235
260
|
if (active.grant.routing === "conversation") throw new _modelcontextprotocol_sdk_types_js.McpError(_modelcontextprotocol_sdk_types_js.ErrorCode.InvalidParams, "Use load_skill with conversation metadata to read target-session guidance.");
|
|
236
|
-
const { snapshot, skills } = grantedSurface(active.grant, active.target.toolSurface);
|
|
237
261
|
const skill = skills.find((candidate) => candidate.uri === message.params.uri);
|
|
238
262
|
if (skill === void 0) throw new _modelcontextprotocol_sdk_types_js.McpError(_modelcontextprotocol_sdk_types_js.ErrorCode.InvalidParams, "Skill resource is not granted or active.");
|
|
239
263
|
const text = await active.target.toolSurface.readSkill(snapshot.revision, skill.uri);
|