dsh-vscode-mode 0.17.0 → 0.18.0

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/src/rpc.ts CHANGED
@@ -33,6 +33,7 @@ import { newContentSearcher } from './search/content.js'
33
33
  import { restoreFile, revertCall, revertHunk, revertHunks, type Result } from './revert.js'
34
34
  import { rulesList, rulesRead, rulesRemove, rulesSave, rulesToggle } from './rules.js'
35
35
  import { isSnippetFilePath, snippetsEntries, snippetsList, snippetsRead, snippetsRemove, snippetsSave } from './snippets.js'
36
+ import { runtimeOf } from './mcpRuntime.js'
36
37
  import { listMcp, refreshMcp, removeMcp, saveMcp, toggleMcp } from './mcp.js'
37
38
  import { listProjects, projectRefresh, projectRemove, projectSave, projectToggle, mcpSnapshot } from './mcpProject.js'
38
39
  import { normalizeFileOpenTool, FILE_OPEN_DEFAULT, FILE_OPEN_SETTINGS_NS, sectionOf, updateSection } from './fileOpenSettings.js'
@@ -1170,6 +1171,7 @@ export function buildHandlers(
1170
1171
  },
1171
1172
  'mcp.list': async () => ({ ok: true, ...listMcp(ctx) }),
1172
1173
  'mcp.snapshot': async () => ({ ok: true, ...mcpSnapshot(ctx) }),
1174
+ 'mcp.sessionSnapshot': async () => ({ ok: true, ...runtimeOf(ctx).sessionSnapshot() }),
1173
1175
  'mcp.save': async (args) => {
1174
1176
  try { return { ok: true, server: await saveMcp(ctx, args.config) } }
1175
1177
  catch (error) { return { ok: false, error: String(error) } }
@@ -1190,8 +1192,18 @@ export function buildHandlers(
1190
1192
  try { return { ok: true, ...await listProjects(ctx) } }
1191
1193
  catch (error) { return { ok: false, error: String(error) } }
1192
1194
  },
1195
+ 'mcp.projectConnect': async (args) => {
1196
+ const runtime = runtimeOf(ctx)
1197
+ const agent = [...runtime.agents.keys()].find((owner) => owner.session?.id === args.sessionId)
1198
+ if (!agent || runtime.workspace(agent) !== args.workspacePath) return { ok: false, error: '请先打开此项目的活跃会话;不会激活历史会话' }
1199
+ try {
1200
+ await runtime.connect(agent, args.serverName)
1201
+ const project = mcpSnapshot(ctx).projects.find((item) => item.workspacePath === args.workspacePath)!
1202
+ return { ok: true, project }
1203
+ } catch { return { ok: false, error: '项目 MCP 连接失败,请查看会话状态和 Host 日志' } }
1204
+ },
1193
1205
  'mcp.projectSave': async (args) => {
1194
- try { return { ok: true, project: await projectSave(ctx, args.workspacePath, args.serverName, args.config) } }
1206
+ try { return { ok: true, project: await projectSave(ctx, args.workspacePath, args.serverName, args.config, args.policy) } }
1195
1207
  catch (error) { return { ok: false, error: String(error) } }
1196
1208
  },
1197
1209
  'mcp.projectRemove': async (args) => {
package/src/shared/mcp.ts CHANGED
@@ -1,6 +1,50 @@
1
1
  /** dsh-vscode-mode MCP 管理共享数据契约。作者 ddj 2026年08月22号 */
2
2
 
3
3
  export type MpcTransport = 'stdio' | 'streamable-http'
4
+ /** Project initialization only; ready does not establish transport health. */
5
+ export type McpPhase = 'preparing' | 'idle' | 'queued' | 'loading' | 'starting' | 'stopping' | 'ready' | 'error' | 'none'
6
+
7
+ export interface McpPolicy {
8
+ startup: 'on-demand' | 'background'
9
+ sharing: 'agent' | 'workspace'
10
+ startupTimeoutMs: number
11
+ }
12
+
13
+ /** @public @author ddj 2026年10月20号 @param input Project-only policy. @returns Validated defaults. @throws Invalid explicit policy. */
14
+ export function parseMcpPolicy(input?: unknown): McpPolicy {
15
+ if (input !== undefined && (!input || typeof input !== 'object' || Array.isArray(input))) throw new Error('vscodeMode 必须是对象')
16
+ const policy = (input ?? {}) as Partial<McpPolicy>
17
+ const startup = policy.startup ?? 'on-demand'
18
+ const sharing = policy.sharing ?? 'agent'
19
+ const startupTimeoutMs = policy.startupTimeoutMs ?? 60000
20
+ if (!['on-demand', 'background'].includes(startup)) throw new Error('不支持的 MCP startup')
21
+ if (!['agent', 'workspace'].includes(sharing)) throw new Error('不支持的 MCP sharing')
22
+ if (!Number.isInteger(startupTimeoutMs) || startupTimeoutMs < 1000 || startupTimeoutMs > 300000) throw new Error('MCP startupTimeoutMs 必须为 1000–300000 的整数')
23
+ return { startup, sharing, startupTimeoutMs }
24
+ }
25
+ export interface McpSessionServer {
26
+ queuedMs?: number
27
+ connectMs?: number
28
+ firstCallMs?: number
29
+ reused?: boolean
30
+ serverName: string
31
+ phase: McpPhase
32
+ startedAt: number
33
+ phaseAt: number
34
+ finishedAt?: number
35
+ error?: string
36
+ }
37
+ export interface McpSessionStatus {
38
+ configMs?: number
39
+ sessionId: string
40
+ phase: McpPhase
41
+ startedAt: number
42
+ phaseAt: number
43
+ finishedAt?: number
44
+ error?: string
45
+ servers: McpSessionServer[]
46
+ }
47
+
4
48
  export type MpcStatus = 'connected' | 'connecting' | 'error' | 'disabled' | 'configured' | 'unverified'
5
49
 
6
50
  export interface MpcTool {
@@ -32,6 +76,8 @@ export interface MpcServer {
32
76
  status: MpcStatus
33
77
  /** Mounted official plugin fibers, not verified live connections. */
34
78
  instanceCount?: number
79
+ sessionCount?: number
80
+ policy?: McpPolicy
35
81
  toolCount: number
36
82
  tools: MpcTool[]
37
83
  error?: string
@@ -50,6 +96,7 @@ export interface MpcProject {
50
96
 
51
97
  /** 项目级 MCP 保存入参:config 为该 serverName 的传输配置(不含归属信息)。 */
52
98
  export interface MpcProjectSaveInput {
99
+ policy?: McpPolicy
53
100
  workspacePath: string
54
101
  serverName: string
55
102
  config: MpcConfig
package/src/shared/rpc.ts CHANGED
@@ -12,7 +12,7 @@ import type {
12
12
  RecordView,
13
13
  StaleHunk,
14
14
  } from './types.js'
15
- import type { MpcConfig, MpcProject, MpcProjectSaveInput, MpcServer } from './mcp.js'
15
+ import type { McpSessionStatus, MpcConfig, MpcProject, MpcProjectSaveInput, MpcServer } from './mcp.js'
16
16
  import type { CompatReport, DevFormInfo } from './compat.js'
17
17
  import type { ShellIntegrationStatus, UnityListPayload, UnityProjectEntry } from './integration.js'
18
18
  import type { RuleInfo, RuleProject, RuleRefInput, RuleSaveInput } from './rules.js'
@@ -399,11 +399,13 @@ export interface RpcRequestMap {
399
399
  'edrv.fsMove': { sessionId?: string; from: string; toDir: string }
400
400
  'mcp.list': {}
401
401
  'mcp.snapshot': {}
402
+ 'mcp.sessionSnapshot': {}
402
403
  'mcp.save': { config: MpcConfig }
403
404
  'mcp.remove': { id: string }
404
405
  'mcp.toggle': { id: string; enabled: boolean }
405
406
  'mcp.refresh': { id: string }
406
407
  'mcp.projects': {}
408
+ 'mcp.projectConnect': { sessionId: string; serverName: string; workspacePath: string }
407
409
  'mcp.projectSave': MpcProjectSaveInput
408
410
  'mcp.projectRemove': { workspacePath: string; serverName: string }
409
411
  'mcp.projectToggle': { workspacePath: string; serverName: string; enabled: boolean }
@@ -565,11 +567,13 @@ export interface RpcOkMap {
565
567
  'edrv.fsMove': { from: string; to: string }
566
568
  'mcp.list': { servers: MpcServer[] }
567
569
  'mcp.snapshot': { servers: MpcServer[]; projects: MpcProject[] }
570
+ 'mcp.sessionSnapshot': { sessions: McpSessionStatus[]; sampledAt: number }
568
571
  'mcp.save': { server: MpcServer }
569
572
  'mcp.remove': object
570
573
  'mcp.toggle': { server: MpcServer }
571
574
  'mcp.refresh': { server: MpcServer }
572
575
  'mcp.projects': { projects: MpcProject[] }
576
+ 'mcp.projectConnect': { project: MpcProject }
573
577
  'mcp.projectSave': { project: MpcProject }
574
578
  'mcp.projectRemove': { project: MpcProject }
575
579
  'mcp.projectToggle': { project: MpcProject }