dsh-vscode-mode 0.16.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/README.md +15 -9
- package/lib/client.js +954 -133
- package/lib/client.js.map +1 -1
- package/lib/index.js +5026 -4387
- package/lib/index.js.map +1 -1
- package/locale/en.json +4 -2
- package/locale/zh.json +4 -2
- package/package.json +4 -2
- package/skills/dsh-vscodemode-mcp/SKILL.md +24 -7
- package/src/capture.ts +2 -2
- package/src/client/compat.ts +2 -1
- package/src/client/index.ts +37 -7
- package/src/client/localeClient.ts +97 -0
- package/src/client/mcpSessionState.ts +108 -0
- package/src/client/monaco/lsp/providers.ts +32 -3
- package/src/client/officialSidebar.ts +4 -1
- package/src/client/state/modelWarmer.ts +198 -0
- package/src/client/state/recordsFeed.ts +241 -0
- package/src/client/styles/editor.css +5 -1
- package/src/client/ui/ConversationDiffDock.ts +10 -19
- package/src/client/ui/DiffBadge.ts +12 -19
- package/src/client/ui/EditorPane.ts +16 -4
- package/src/client/ui/EditorView.ts +114 -51
- package/src/client/ui/McpSessionStatus.ts +75 -0
- package/src/client/ui/McpSettings.ts +47 -13
- package/src/client/ui/PerfSizeBadge.ts +7 -4
- package/src/client/ui/PluginDetailSection.ts +82 -0
- package/src/dshVersion.ts +4 -2
- package/src/fileVersions.ts +2 -2
- package/src/lsp/rpc.ts +2 -2
- package/src/mcp.ts +1 -0
- package/src/mcpBridge.ts +163 -0
- package/src/mcpDiscover.ts +38 -0
- package/src/mcpPool.ts +245 -0
- package/src/mcpProject.ts +15 -12
- package/src/mcpRuntime.ts +301 -255
- package/src/registry.ts +15 -2
- package/src/rpc.ts +15 -3
- package/src/rules.ts +9 -4
- package/src/search/fallback.ts +2 -2
- package/src/search/ripgrep.ts +2 -2
- package/src/shared/mcp.ts +47 -0
- package/src/shared/rpc.ts +5 -1
- package/src/store.ts +26 -1
- package/src/svn.ts +2 -2
package/src/registry.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import type { DiffRecord } from './shared/types.js'
|
|
7
7
|
import type { Ctx, Session } from './store.js'
|
|
8
|
-
import { loadBucket } from './store.js'
|
|
8
|
+
import { cwdOfSession, loadBucket } from './store.js'
|
|
9
9
|
|
|
10
10
|
/** cwd → 记录桶(内存缓存;随会话销毁清理)。 */
|
|
11
11
|
export type Registry = Map<string, Map<string, DiffRecord>>
|
|
@@ -19,7 +19,20 @@ export function sessionOf(ctx: Ctx, sessionId?: string): Session | undefined {
|
|
|
19
19
|
return live.length === 1 ? live[0] : undefined
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
/**
|
|
22
|
+
/**
|
|
23
|
+
* 会话工作区 cwd(跟随会话内 cd;服务缺失时回落 header.cwd)。
|
|
24
|
+
* 定义在 store.ts 以避免 registry ↔ store 循环依赖,此处仅转出为会话助手入口。
|
|
25
|
+
* @author ddj 2026年10月19号
|
|
26
|
+
*/
|
|
27
|
+
export { cwdOfSession }
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* 会话头部的原始 cwd(不跟随 cd)。仅用于会话销毁等无上下文场景:
|
|
31
|
+
* 此时投影可能已随会话卸载,读 header 才能保证拿到建会话时的目录。
|
|
32
|
+
* @author ddj 2026年10月19号
|
|
33
|
+
* @param session 目标会话
|
|
34
|
+
* @returns 绝对路径或 null
|
|
35
|
+
*/
|
|
23
36
|
export function cwdOf(session: Session | undefined): string | null {
|
|
24
37
|
return session?.header?.cwd ?? null
|
|
25
38
|
}
|
package/src/rpc.ts
CHANGED
|
@@ -25,7 +25,7 @@ import { archiveEntryFor, markDecision, recordResolved, reconstructOriginal } fr
|
|
|
25
25
|
import { clearRevertState, listArchives, pageArchives, readArchives, revertState, setRevertState, startReverts } from './archiveDb.js'
|
|
26
26
|
import { log } from './log.js'
|
|
27
27
|
import type { Registry } from './registry.js'
|
|
28
|
-
import { bucketOf,
|
|
28
|
+
import { bucketOf, cwdOfSession, sessionOf } from './registry.js'
|
|
29
29
|
import type { SearchOrchestrator } from './search/orchestrator.js'
|
|
30
30
|
import { newSearcher } from './search/orchestrator.js'
|
|
31
31
|
import type { ContentSearcher } from './search/content.js'
|
|
@@ -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'
|
|
@@ -100,7 +101,7 @@ async function requireSession(ctx: Ctx, sessionId: string | undefined): Promise<
|
|
|
100
101
|
> {
|
|
101
102
|
const session = sessionOf(ctx, sessionId)
|
|
102
103
|
if (!session) return { err: SESSION_MISSING_ERROR }
|
|
103
|
-
const cwd =
|
|
104
|
+
const cwd = cwdOfSession(ctx, session)
|
|
104
105
|
if (!cwd) return { err: SESSION_NO_WORKSPACE_ERROR }
|
|
105
106
|
return { session, cwd }
|
|
106
107
|
}
|
|
@@ -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/rules.ts
CHANGED
|
@@ -16,6 +16,7 @@ import { join, resolve } from 'node:path'
|
|
|
16
16
|
import { dshHome } from './paths.js'
|
|
17
17
|
import type { RuleInfo, RuleProject, RuleRefInput, RuleScope, RuleSaveInput, UserRuleOrigin } from './shared/rules.js'
|
|
18
18
|
import type { Ctx } from './store.js'
|
|
19
|
+
import { cwdOfSession } from './store.js'
|
|
19
20
|
|
|
20
21
|
// --region 常量与目录定位
|
|
21
22
|
/** 规则文件名白名单:字母数字开头,仅字母数字点横下划线,.mdc 后缀(天然拒绝路径分隔符)。 */
|
|
@@ -550,13 +551,17 @@ export function readUserRulesSync(dirs = userRuleDirs()): LoadedRule[] {
|
|
|
550
551
|
return mergeUserRules(current, legacy, (rule) => rule.info.file)
|
|
551
552
|
}
|
|
552
553
|
|
|
553
|
-
/**
|
|
554
|
+
/**
|
|
555
|
+
* 从装配上下文解析会话工作区 cwd(agent.id → sessions → 当前目录;缺链返回 null)。
|
|
556
|
+
* @author ddj 2026年10月19号
|
|
557
|
+
* @param ctx DSH 上下文
|
|
558
|
+
* @param asm 装配上下文(含 agent.id)
|
|
559
|
+
* @returns 项目规则根的绝对路径或 null
|
|
560
|
+
*/
|
|
554
561
|
function cwdFromAssemble(ctx: Ctx, asm: { agent?: { id?: unknown } } | undefined): string | null {
|
|
555
562
|
const id = asm?.agent?.id
|
|
556
563
|
if (typeof id !== 'string' || !id) return null
|
|
557
|
-
|
|
558
|
-
const cwd = session?.header?.cwd
|
|
559
|
-
return typeof cwd === 'string' && cwd ? cwd : null
|
|
564
|
+
return cwdOfSession(ctx, ctx.get('sessions')?.get?.(id))
|
|
560
565
|
}
|
|
561
566
|
|
|
562
567
|
/**
|
package/src/search/fallback.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* 作者 ddj 2026年08月24号
|
|
5
5
|
*/
|
|
6
6
|
import type { Ctx, Session } from '../store.js'
|
|
7
|
-
import { policyOf } from '../store.js'
|
|
7
|
+
import { cwdOfSession, policyOf } from '../store.js'
|
|
8
8
|
import { pathText, pathMatch, prepareQuery } from './query.js'
|
|
9
9
|
import type { PreparedQuery, WorkspaceSearchInput, WorkspaceSearchProvider, WorkspaceSearchResult } from './types.js'
|
|
10
10
|
|
|
@@ -61,7 +61,7 @@ export async function searchFallback(input: WorkspaceSearchInput): Promise<Works
|
|
|
61
61
|
const fs = input.ctx.get('fs') as SearchFs | undefined
|
|
62
62
|
if (!fs) throw new Error('缺少 fs')
|
|
63
63
|
const policy = policyOf(input.ctx, input.session)
|
|
64
|
-
const cwd = input.session
|
|
64
|
+
const cwd = cwdOfSession(input.ctx, input.session)
|
|
65
65
|
const rootTarget = await fs.resolve(policy?.workspaceRoot ?? '.', cwd ? { cwd, signal: input.signal } : { signal: input.signal })
|
|
66
66
|
const signal = input.signal ?? new AbortController().signal
|
|
67
67
|
const files: string[] = []
|
package/src/search/ripgrep.ts
CHANGED
|
@@ -7,7 +7,7 @@ import { existsSync } from 'node:fs'
|
|
|
7
7
|
import { join } from 'node:path'
|
|
8
8
|
import { createRequire } from 'node:module'
|
|
9
9
|
import type { Ctx, Session } from '../store.js'
|
|
10
|
-
import { policyOf } from '../store.js'
|
|
10
|
+
import { cwdOfSession, policyOf } from '../store.js'
|
|
11
11
|
import { prepareQuery, pathText } from './query.js'
|
|
12
12
|
import type { WorkspaceSearchInput, WorkspaceSearchProvider, WorkspaceSearchResult } from './types.js'
|
|
13
13
|
|
|
@@ -127,7 +127,7 @@ export async function searchRoot(ctx: Ctx, session: Session): Promise<string> {
|
|
|
127
127
|
const fs = ctx.get('fs')
|
|
128
128
|
if (!fs) throw new Error('缺少 fs')
|
|
129
129
|
const policy = policyOf(ctx, session)
|
|
130
|
-
const cwd = session
|
|
130
|
+
const cwd = cwdOfSession(ctx, session)
|
|
131
131
|
const rootTarget = await fs.resolve(policy?.workspaceRoot ?? '.', cwd ? { cwd } : {})
|
|
132
132
|
return fs.processPath(rootTarget)
|
|
133
133
|
}
|
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 }
|
package/src/store.ts
CHANGED
|
@@ -33,10 +33,35 @@ export function policyOf(ctx: Ctx, session: Session | undefined): any {
|
|
|
33
33
|
return session ? svc.resolve({ session }) : svc.resolve()
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
+
/**
|
|
37
|
+
* 读取会话当前工作目录:优先 workingDirectory 投影(DSH 0.2.1 起支持会话内 cd),
|
|
38
|
+
* 服务缺失或投影未就绪时回落到 header.cwd(会话创建时的原始目录)。
|
|
39
|
+
* 服务一律可选探测:不得写入模块 inject,否则旧版 DSH 会停等一个不存在的服务。
|
|
40
|
+
* @author ddj 2026年10月19号
|
|
41
|
+
* @param ctx DSH 上下文(用于可选探测 workingDirectory 服务)
|
|
42
|
+
* @param session 目标会话
|
|
43
|
+
* @returns 绝对路径;无法确定时 null
|
|
44
|
+
*/
|
|
45
|
+
export function cwdOfSession(ctx: Ctx, session: Session | undefined): string | null {
|
|
46
|
+
const headerCwd = session?.header?.cwd
|
|
47
|
+
const fallback = typeof headerCwd === 'string' && headerCwd ? headerCwd : null
|
|
48
|
+
if (!session) return null
|
|
49
|
+
|
|
50
|
+
const service = ctx?.get?.('workingDirectory')
|
|
51
|
+
if (!service || typeof service.get !== 'function') return fallback
|
|
52
|
+
try {
|
|
53
|
+
const current = service.get(session)
|
|
54
|
+
return typeof current === 'string' && current ? current : fallback
|
|
55
|
+
} catch {
|
|
56
|
+
// 会话已销毁或投影缺失:回落原始目录,不让新能力变成新的故障点
|
|
57
|
+
return fallback
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
36
61
|
/** 按会话 cwd 解析目标路径。 */
|
|
37
62
|
export async function resolveTarget(ctx: Ctx, session: Session | undefined, path: string): Promise<string> {
|
|
38
63
|
const fs = ctx.get('fs')
|
|
39
|
-
const cwd = session
|
|
64
|
+
const cwd = cwdOfSession(ctx, session)
|
|
40
65
|
return fs.resolve(path, cwd ? { cwd } : {})
|
|
41
66
|
}
|
|
42
67
|
|
package/src/svn.ts
CHANGED
|
@@ -10,7 +10,7 @@ import { readdir, stat } from 'node:fs/promises'
|
|
|
10
10
|
import { basename, dirname, isAbsolute, join, relative, resolve } from 'node:path'
|
|
11
11
|
import { tmpdir } from 'node:os'
|
|
12
12
|
import type { Ctx, Session } from './store.js'
|
|
13
|
-
import {
|
|
13
|
+
import { cwdOfSession, sessionOf } from './registry.js'
|
|
14
14
|
import type { SvnAction, SvnAiPlan, SvnChangeEntry, SvnConflictArtifact, SvnFeature, SvnIgnoreItem, SvnItemStatus, SvnLogEntry, SvnRemoteOutdatedEntry, SvnStatusPayload, SvnSumEntry } from './shared/svn.js'
|
|
15
15
|
import { SESSION_MISSING_ERROR, SESSION_NO_WORKSPACE_ERROR } from './shared/rpc.js'
|
|
16
16
|
import { AI_PLAN_DIFF_CAP, AI_PLAN_PATHS_CAP, BATCH_PATHS_CAP, FILE_SIZES_CAP, SVN_CLI_DEFAULT, TORTOISE_EXE, contentGuardOf, normalizeAiPlan, svnChangelistNameErrorOf, tortoiseLaunchArgv } from './shared/svn.js'
|
|
@@ -463,7 +463,7 @@ async function requireSvnSession(
|
|
|
463
463
|
): Promise<{ cwd: string } | { err: string }> {
|
|
464
464
|
const session: Session | undefined = sessionOf(ctx, sessionId)
|
|
465
465
|
if (!session) return { err: SESSION_MISSING_ERROR }
|
|
466
|
-
const cwd =
|
|
466
|
+
const cwd = cwdOfSession(ctx, session)
|
|
467
467
|
if (!cwd) return { err: SESSION_NO_WORKSPACE_ERROR }
|
|
468
468
|
return { cwd }
|
|
469
469
|
}
|