@cyanheads/git-mcp-server 2.0.1 → 2.0.3
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 +55 -89
- package/{build → dist}/config/index.js +16 -18
- package/{build → dist}/index.js +80 -30
- package/dist/mcp-server/server.js +296 -0
- package/{build → dist}/mcp-server/tools/gitAdd/logic.js +9 -6
- package/{build → dist}/mcp-server/tools/gitAdd/registration.js +7 -4
- package/{build → dist}/mcp-server/tools/gitBranch/logic.js +23 -12
- package/{build → dist}/mcp-server/tools/gitBranch/registration.js +8 -5
- package/{build → dist}/mcp-server/tools/gitCheckout/logic.js +92 -44
- package/{build → dist}/mcp-server/tools/gitCheckout/registration.js +8 -5
- package/{build → dist}/mcp-server/tools/gitCherryPick/logic.js +10 -7
- package/{build → dist}/mcp-server/tools/gitCherryPick/registration.js +8 -5
- package/{build → dist}/mcp-server/tools/gitClean/logic.js +9 -6
- package/{build → dist}/mcp-server/tools/gitClean/registration.js +8 -5
- package/{build → dist}/mcp-server/tools/gitClearWorkingDir/logic.js +3 -2
- package/{build → dist}/mcp-server/tools/gitClearWorkingDir/registration.js +7 -4
- package/{build → dist}/mcp-server/tools/gitClone/logic.js +8 -5
- package/{build → dist}/mcp-server/tools/gitClone/registration.js +7 -4
- package/dist/mcp-server/tools/gitCommit/logic.js +207 -0
- package/{build → dist}/mcp-server/tools/gitCommit/registration.js +22 -15
- package/{build → dist}/mcp-server/tools/gitDiff/logic.js +9 -6
- package/{build → dist}/mcp-server/tools/gitDiff/registration.js +8 -5
- package/{build → dist}/mcp-server/tools/gitFetch/logic.js +10 -7
- package/{build → dist}/mcp-server/tools/gitFetch/registration.js +8 -5
- package/{build → dist}/mcp-server/tools/gitInit/index.js +2 -2
- package/{build → dist}/mcp-server/tools/gitInit/logic.js +9 -6
- package/dist/mcp-server/tools/gitInit/registration.js +98 -0
- package/{build → dist}/mcp-server/tools/gitLog/logic.js +53 -16
- package/{build → dist}/mcp-server/tools/gitLog/registration.js +8 -5
- package/{build → dist}/mcp-server/tools/gitMerge/logic.js +9 -6
- package/{build → dist}/mcp-server/tools/gitMerge/registration.js +8 -5
- package/{build → dist}/mcp-server/tools/gitPull/logic.js +11 -8
- package/{build → dist}/mcp-server/tools/gitPull/registration.js +7 -4
- package/{build → dist}/mcp-server/tools/gitPush/logic.js +12 -9
- package/{build → dist}/mcp-server/tools/gitPush/registration.js +7 -4
- package/{build → dist}/mcp-server/tools/gitRebase/logic.js +9 -6
- package/{build → dist}/mcp-server/tools/gitRebase/registration.js +8 -5
- package/{build → dist}/mcp-server/tools/gitRemote/logic.js +4 -5
- package/{build → dist}/mcp-server/tools/gitRemote/registration.js +2 -4
- package/{build → dist}/mcp-server/tools/gitReset/logic.js +5 -6
- package/{build → dist}/mcp-server/tools/gitReset/registration.js +2 -4
- package/{build → dist}/mcp-server/tools/gitSetWorkingDir/logic.js +5 -6
- package/{build → dist}/mcp-server/tools/gitSetWorkingDir/registration.js +22 -13
- package/{build → dist}/mcp-server/tools/gitShow/logic.js +5 -6
- package/{build → dist}/mcp-server/tools/gitShow/registration.js +3 -5
- package/{build → dist}/mcp-server/tools/gitStash/logic.js +5 -6
- package/{build → dist}/mcp-server/tools/gitStash/registration.js +3 -5
- package/{build → dist}/mcp-server/tools/gitStatus/logic.js +5 -6
- package/{build → dist}/mcp-server/tools/gitStatus/registration.js +2 -4
- package/{build → dist}/mcp-server/tools/gitTag/logic.js +3 -4
- package/{build → dist}/mcp-server/tools/gitTag/registration.js +2 -4
- package/dist/mcp-server/transports/authentication/authMiddleware.js +145 -0
- package/dist/mcp-server/transports/httpTransport.js +432 -0
- package/dist/mcp-server/transports/stdioTransport.js +87 -0
- package/{build → dist}/types-global/errors.js +2 -2
- package/dist/utils/index.js +12 -0
- package/{build/utils → dist/utils/internal}/errorHandler.js +18 -8
- package/dist/utils/internal/index.js +3 -0
- package/dist/utils/internal/logger.js +254 -0
- package/{build/utils → dist/utils/internal}/requestContext.js +2 -3
- package/dist/utils/metrics/index.js +1 -0
- package/{build/utils → dist/utils/metrics}/tokenCounter.js +3 -3
- package/dist/utils/parsing/dateParser.js +62 -0
- package/dist/utils/parsing/index.js +2 -0
- package/{build/utils → dist/utils/parsing}/jsonParser.js +3 -2
- package/{build/utils → dist/utils/security}/idGenerator.js +4 -5
- package/dist/utils/security/index.js +3 -0
- package/{build/utils → dist/utils/security}/rateLimiter.js +7 -10
- package/{build/utils → dist/utils/security}/sanitization.js +4 -3
- package/package.json +20 -16
- package/build/mcp-server/server.js +0 -572
- package/build/mcp-server/tools/gitCommit/logic.js +0 -129
- package/build/mcp-server/tools/gitInit/registration.js +0 -44
- package/build/types-global/mcp.js +0 -59
- package/build/types-global/tool.js +0 -1
- package/build/utils/index.js +0 -11
- package/build/utils/logger.js +0 -266
- /package/{build → dist}/mcp-server/tools/gitAdd/index.js +0 -0
- /package/{build → dist}/mcp-server/tools/gitBranch/index.js +0 -0
- /package/{build → dist}/mcp-server/tools/gitCheckout/index.js +0 -0
- /package/{build → dist}/mcp-server/tools/gitCherryPick/index.js +0 -0
- /package/{build → dist}/mcp-server/tools/gitClean/index.js +0 -0
- /package/{build → dist}/mcp-server/tools/gitClearWorkingDir/index.js +0 -0
- /package/{build → dist}/mcp-server/tools/gitClone/index.js +0 -0
- /package/{build → dist}/mcp-server/tools/gitCommit/index.js +0 -0
- /package/{build → dist}/mcp-server/tools/gitDiff/index.js +0 -0
- /package/{build → dist}/mcp-server/tools/gitFetch/index.js +0 -0
- /package/{build → dist}/mcp-server/tools/gitLog/index.js +0 -0
- /package/{build → dist}/mcp-server/tools/gitMerge/index.js +0 -0
- /package/{build → dist}/mcp-server/tools/gitPull/index.js +0 -0
- /package/{build → dist}/mcp-server/tools/gitPush/index.js +0 -0
- /package/{build → dist}/mcp-server/tools/gitRebase/index.js +0 -0
- /package/{build → dist}/mcp-server/tools/gitRemote/index.js +0 -0
- /package/{build → dist}/mcp-server/tools/gitReset/index.js +0 -0
- /package/{build → dist}/mcp-server/tools/gitSetWorkingDir/index.js +0 -0
- /package/{build → dist}/mcp-server/tools/gitShow/index.js +0 -0
- /package/{build → dist}/mcp-server/tools/gitStash/index.js +0 -0
- /package/{build → dist}/mcp-server/tools/gitStatus/index.js +0 -0
- /package/{build → dist}/mcp-server/tools/gitTag/index.js +0 -0
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { BaseErrorCode, McpError } from '../../../types-global/errors.js';
|
|
4
|
+
import { ErrorHandler, logger, requestContextService, sanitization } from '../../../utils/index.js';
|
|
5
|
+
import { GitInitInputSchema, gitInitLogic } from './logic.js';
|
|
6
|
+
const TOOL_NAME = 'git_init';
|
|
7
|
+
const TOOL_DESCRIPTION = 'Initializes a new Git repository at the specified path. If path is relative or omitted, it resolves against the session working directory (if you have set the git_working_dir). Can optionally set the initial branch name and create a bare repository.';
|
|
8
|
+
const RegistrationSchema = GitInitInputSchema.extend({
|
|
9
|
+
path: z.string().min(1).optional().default('.'),
|
|
10
|
+
}).shape;
|
|
11
|
+
// --- Module-level State Accessors ---
|
|
12
|
+
// These will be populated by the initialize function called from server.ts
|
|
13
|
+
let _getWorkingDirectory = () => undefined;
|
|
14
|
+
let _getSessionIdFromContext = () => undefined;
|
|
15
|
+
/**
|
|
16
|
+
* Initializes state accessor functions for the git_init tool.
|
|
17
|
+
* This function is called by the main server setup to provide the tool
|
|
18
|
+
* with a way to access session-specific state (like the working directory)
|
|
19
|
+
* without needing direct access to the server or transport layer internals.
|
|
20
|
+
*
|
|
21
|
+
* @param getWorkingDirectory - Function to retrieve the working directory for a given session ID.
|
|
22
|
+
* @param getSessionIdFromContext - Function to extract the session ID from a tool's execution context.
|
|
23
|
+
*/
|
|
24
|
+
export function initializeGitInitStateAccessors(getWorkingDirectory, getSessionIdFromContext) {
|
|
25
|
+
_getWorkingDirectory = getWorkingDirectory;
|
|
26
|
+
_getSessionIdFromContext = getSessionIdFromContext;
|
|
27
|
+
logger.debug(`State accessors initialized for ${TOOL_NAME}`);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Registers the git_init tool with the MCP server.
|
|
31
|
+
*
|
|
32
|
+
* @param {McpServer} server - The McpServer instance to register the tool with.
|
|
33
|
+
* @returns {Promise<void>}
|
|
34
|
+
* @throws {Error} If registration fails.
|
|
35
|
+
*/
|
|
36
|
+
export const registerGitInitTool = async (server) => {
|
|
37
|
+
const operation = 'registerGitInitTool';
|
|
38
|
+
const context = requestContextService.createRequestContext({ operation });
|
|
39
|
+
await ErrorHandler.tryCatch(async () => {
|
|
40
|
+
server.tool(TOOL_NAME, TOOL_DESCRIPTION, RegistrationSchema, async (validatedArgs, callContext) => {
|
|
41
|
+
const toolOperation = 'tool:git_init';
|
|
42
|
+
const requestContext = requestContextService.createRequestContext({ operation: toolOperation, parentContext: callContext });
|
|
43
|
+
// Use the initialized accessor to get the session ID
|
|
44
|
+
const sessionId = _getSessionIdFromContext(requestContext); // Pass the created context
|
|
45
|
+
if (!sessionId && !path.isAbsolute(validatedArgs.path)) {
|
|
46
|
+
// If path is relative, we NEED a session ID to resolve against a potential working dir
|
|
47
|
+
logger.error('Session ID is missing in context, cannot resolve relative path', requestContext);
|
|
48
|
+
throw new McpError(BaseErrorCode.INTERNAL_ERROR, 'Session context is unavailable for relative path resolution.', { context: requestContext, operation: toolOperation });
|
|
49
|
+
}
|
|
50
|
+
logger.info(`Executing tool: ${TOOL_NAME}`, requestContext);
|
|
51
|
+
return await ErrorHandler.tryCatch(async () => {
|
|
52
|
+
// Use the initialized accessor to get the working directory
|
|
53
|
+
const sessionWorkingDirectory = _getWorkingDirectory(sessionId);
|
|
54
|
+
const inputPath = validatedArgs.path;
|
|
55
|
+
let resolvedPath;
|
|
56
|
+
try {
|
|
57
|
+
if (path.isAbsolute(inputPath)) {
|
|
58
|
+
resolvedPath = sanitization.sanitizePath(inputPath);
|
|
59
|
+
logger.debug(`Using absolute path: ${resolvedPath}`, requestContext);
|
|
60
|
+
}
|
|
61
|
+
else if (sessionWorkingDirectory) {
|
|
62
|
+
resolvedPath = sanitization.sanitizePath(path.resolve(sessionWorkingDirectory, inputPath));
|
|
63
|
+
logger.debug(`Resolved relative path '${inputPath}' to absolute path: ${resolvedPath} using session CWD`, requestContext);
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
// This case should now only be hit if the path is relative AND there's no session CWD set.
|
|
67
|
+
logger.error(`Relative path '${inputPath}' provided but no session working directory is set.`, requestContext);
|
|
68
|
+
throw new McpError(BaseErrorCode.VALIDATION_ERROR, `Relative path '${inputPath}' provided but no session working directory is set. Please provide an absolute path or set a working directory using git_set_working_dir.`, { context: requestContext, operation: toolOperation });
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
logger.error('Path resolution or sanitization failed', { ...requestContext, operation: toolOperation, error });
|
|
73
|
+
if (error instanceof McpError)
|
|
74
|
+
throw error;
|
|
75
|
+
throw new McpError(BaseErrorCode.VALIDATION_ERROR, `Invalid path processing: ${error instanceof Error ? error.message : String(error)}`, { context: requestContext, operation: toolOperation, originalError: error });
|
|
76
|
+
}
|
|
77
|
+
const logicArgs = {
|
|
78
|
+
...validatedArgs,
|
|
79
|
+
path: resolvedPath,
|
|
80
|
+
};
|
|
81
|
+
const initResult = await gitInitLogic(logicArgs, requestContext);
|
|
82
|
+
const resultContent = {
|
|
83
|
+
type: 'text',
|
|
84
|
+
text: JSON.stringify(initResult, null, 2), // Pretty-print JSON
|
|
85
|
+
contentType: 'application/json',
|
|
86
|
+
};
|
|
87
|
+
logger.info(`Tool ${TOOL_NAME} executed successfully, returning JSON`, requestContext);
|
|
88
|
+
return { content: [resultContent] };
|
|
89
|
+
}, {
|
|
90
|
+
operation: toolOperation,
|
|
91
|
+
context: requestContext,
|
|
92
|
+
input: validatedArgs,
|
|
93
|
+
errorCode: BaseErrorCode.INTERNAL_ERROR,
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
logger.info(`Tool registered: ${TOOL_NAME}`, context);
|
|
97
|
+
}, { operation, context, critical: true });
|
|
98
|
+
};
|
|
@@ -1,9 +1,12 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
2
|
-
import { promisify } from 'util';
|
|
3
1
|
import { exec } from 'child_process';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
|
|
2
|
+
import { promisify } from 'util';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
// Import utils from barrel (logger from ../utils/internal/logger.js)
|
|
5
|
+
import { logger } from '../../../utils/index.js';
|
|
6
|
+
// Import utils from barrel (RequestContext from ../utils/internal/requestContext.js)
|
|
7
|
+
import { BaseErrorCode, McpError } from '../../../types-global/errors.js'; // Keep direct import for types-global
|
|
8
|
+
// Import utils from barrel (sanitization from ../utils/security/sanitization.js)
|
|
9
|
+
import { sanitization } from '../../../utils/index.js';
|
|
7
10
|
const execAsync = promisify(exec);
|
|
8
11
|
// Define the structure for a single commit entry
|
|
9
12
|
export const CommitEntrySchema = z.object({
|
|
@@ -16,13 +19,14 @@ export const CommitEntrySchema = z.object({
|
|
|
16
19
|
});
|
|
17
20
|
// Define the input schema for the git_log tool using Zod
|
|
18
21
|
export const GitLogInputSchema = z.object({
|
|
19
|
-
path: z.string().min(1).optional().default('.').describe("Path to the Git repository. Defaults to the session
|
|
22
|
+
path: z.string().min(1).optional().default('.').describe("Path to the Git repository. Defaults to the directory set via `git_set_working_dir` for the session; set 'git_set_working_dir' if not set."),
|
|
20
23
|
maxCount: z.number().int().positive().optional().describe("Limit the number of commits to output."),
|
|
21
24
|
author: z.string().optional().describe("Limit commits to those matching the specified author pattern."),
|
|
22
25
|
since: z.string().optional().describe("Show commits more recent than a specific date (e.g., '2 weeks ago', '2023-01-01')."),
|
|
23
26
|
until: z.string().optional().describe("Show commits older than a specific date."),
|
|
24
|
-
branchOrFile: z.string().optional().describe("Show logs for a specific branch, tag, or file path."),
|
|
25
|
-
|
|
27
|
+
branchOrFile: z.string().optional().describe("Show logs for a specific branch (e.g., 'main'), tag, or file path (e.g., 'src/utils/logger.ts')."),
|
|
28
|
+
showSignature: z.boolean().optional().default(false).describe("Show signature verification status for commits. Returns raw output instead of parsed JSON."),
|
|
29
|
+
// Note: We use a fixed pretty format for reliable parsing unless showSignature is true.
|
|
26
30
|
});
|
|
27
31
|
// Delimiters for parsing the custom format
|
|
28
32
|
const FIELD_SEP = '\x1f'; // Unit Separator
|
|
@@ -62,11 +66,29 @@ export async function logGitHistory(input, context) {
|
|
|
62
66
|
throw new McpError(BaseErrorCode.VALIDATION_ERROR, `Invalid path: ${error instanceof Error ? error.message : String(error)}`, { context, operation, originalError: error });
|
|
63
67
|
}
|
|
64
68
|
try {
|
|
65
|
-
|
|
66
|
-
//
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
command
|
|
69
|
+
let command;
|
|
70
|
+
let isRawOutput = false; // Flag to indicate if we should parse or return raw
|
|
71
|
+
if (input.showSignature) {
|
|
72
|
+
isRawOutput = true;
|
|
73
|
+
command = `git -C "${targetPath}" log --show-signature`;
|
|
74
|
+
logger.info('Show signature requested, returning raw output.', { ...context, operation });
|
|
75
|
+
// Append other filters if provided
|
|
76
|
+
if (input.maxCount)
|
|
77
|
+
command += ` -n ${input.maxCount}`;
|
|
78
|
+
if (input.author)
|
|
79
|
+
command += ` --author="${input.author.replace(/[`"$&;*()|<>]/g, '')}"`;
|
|
80
|
+
if (input.since)
|
|
81
|
+
command += ` --since="${input.since.replace(/[`"$&;*()|<>]/g, '')}"`;
|
|
82
|
+
if (input.until)
|
|
83
|
+
command += ` --until="${input.until.replace(/[`"$&;*()|<>]/g, '')}"`;
|
|
84
|
+
if (input.branchOrFile)
|
|
85
|
+
command += ` ${input.branchOrFile.replace(/[`"$&;*()|<>]/g, '')}`;
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
// Construct the git log command with the fixed format for parsing
|
|
89
|
+
command = `git -C "${targetPath}" log ${GIT_LOG_FORMAT}`;
|
|
90
|
+
if (input.maxCount)
|
|
91
|
+
command += ` -n ${input.maxCount}`;
|
|
70
92
|
}
|
|
71
93
|
if (input.author) {
|
|
72
94
|
// Basic sanitization for author string
|
|
@@ -90,13 +112,28 @@ export async function logGitHistory(input, context) {
|
|
|
90
112
|
const { stdout, stderr } = await execAsync(command, { maxBuffer: 1024 * 1024 * 10 }); // 10MB buffer
|
|
91
113
|
if (stderr) {
|
|
92
114
|
// Log stderr as warning, as git log might sometimes use it for non-fatal info
|
|
93
|
-
|
|
115
|
+
// Exception: If showing signature, stderr about allowedSignersFile is expected, treat as info
|
|
116
|
+
if (isRawOutput && stderr.includes('allowedSignersFile needs to be configured')) {
|
|
117
|
+
logger.info(`Git log stderr (signature verification note): ${stderr.trim()}`, { ...context, operation });
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
logger.warning(`Git log stderr: ${stderr.trim()}`, { ...context, operation });
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
// If raw output was requested, return it directly
|
|
124
|
+
if (isRawOutput) {
|
|
125
|
+
const message = `Raw log output (showSignature=true):\n${stdout}`;
|
|
126
|
+
logger.info(`${operation} completed successfully (raw output).`, { ...context, operation, path: targetPath });
|
|
127
|
+
return { success: true, commits: [], message: message };
|
|
94
128
|
}
|
|
95
|
-
//
|
|
129
|
+
// Otherwise, parse the structured output
|
|
96
130
|
const commits = [];
|
|
97
131
|
const commitRecords = stdout.split(RECORD_SEP).filter(record => record.trim() !== ''); // Split records and remove empty ones
|
|
98
132
|
for (const record of commitRecords) {
|
|
99
|
-
const
|
|
133
|
+
const trimmedRecord = record.trim(); // Trim leading/trailing whitespace (like newlines)
|
|
134
|
+
if (!trimmedRecord)
|
|
135
|
+
continue; // Skip empty records after trimming
|
|
136
|
+
const fields = trimmedRecord.split(FIELD_SEP); // Split the trimmed record
|
|
100
137
|
if (fields.length >= 5) { // Need at least hash, name, email, timestamp, subject
|
|
101
138
|
try {
|
|
102
139
|
const commitEntry = {
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
3
|
-
|
|
1
|
+
// Import utils from barrel (ErrorHandler from ../utils/internal/errorHandler.js)
|
|
2
|
+
import { ErrorHandler } from '../../../utils/index.js';
|
|
3
|
+
// Import utils from barrel (logger from ../utils/internal/logger.js)
|
|
4
|
+
import { logger } from '../../../utils/index.js';
|
|
5
|
+
// Import utils from barrel (requestContextService, RequestContext from ../utils/internal/requestContext.js)
|
|
6
|
+
import { BaseErrorCode } from '../../../types-global/errors.js'; // Keep direct import for types-global
|
|
7
|
+
import { requestContextService } from '../../../utils/index.js';
|
|
4
8
|
import { GitLogInputSchema, logGitHistory } from './logic.js';
|
|
5
|
-
import { BaseErrorCode } from '../../../types-global/errors.js';
|
|
6
9
|
let _getWorkingDirectory;
|
|
7
10
|
let _getSessionId;
|
|
8
11
|
/**
|
|
@@ -17,7 +20,7 @@ export function initializeGitLogStateAccessors(getWdFn, getSidFn) {
|
|
|
17
20
|
logger.info('State accessors initialized for git_log tool registration.');
|
|
18
21
|
}
|
|
19
22
|
const TOOL_NAME = 'git_log';
|
|
20
|
-
const TOOL_DESCRIPTION = "Shows commit logs for the repository. Supports limiting count, filtering by author, date range, and specific branch/file. Returns a list of commit objects.";
|
|
23
|
+
const TOOL_DESCRIPTION = "Shows commit logs for the repository. Supports limiting count, filtering by author, date range, and specific branch/file. Returns a list of commit objects by default. Can optionally show signature verification status (`showSignature: true`), which returns raw text output instead of JSON.";
|
|
21
24
|
/**
|
|
22
25
|
* Registers the git_log tool with the MCP server.
|
|
23
26
|
*
|
|
@@ -1,14 +1,17 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
2
|
-
import { promisify } from 'util';
|
|
3
1
|
import { exec } from 'child_process';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
|
|
2
|
+
import { promisify } from 'util';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
// Import utils from barrel (logger from ../utils/internal/logger.js)
|
|
5
|
+
import { logger } from '../../../utils/index.js';
|
|
6
|
+
// Import utils from barrel (RequestContext from ../utils/internal/requestContext.js)
|
|
7
|
+
import { BaseErrorCode, McpError } from '../../../types-global/errors.js'; // Keep direct import for types-global
|
|
8
|
+
// Import utils from barrel (sanitization from ../utils/security/sanitization.js)
|
|
7
9
|
import path from 'path'; // Import path module
|
|
10
|
+
import { sanitization } from '../../../utils/index.js';
|
|
8
11
|
const execAsync = promisify(exec);
|
|
9
12
|
// Define the input schema for the git_merge tool
|
|
10
13
|
export const GitMergeInputSchema = z.object({
|
|
11
|
-
path: z.string().min(1).optional().default('.').describe("Path to the Git repository. Defaults to the session
|
|
14
|
+
path: z.string().min(1).optional().default('.').describe("Path to the Git repository. Defaults to the directory set via `git_set_working_dir` for the session; set 'git_set_working_dir' if not set."),
|
|
12
15
|
branch: z.string().min(1).describe('The name of the branch to merge into the current branch.'),
|
|
13
16
|
commitMessage: z.string().optional().describe('Commit message to use for the merge commit (if required, e.g., not fast-forward).'),
|
|
14
17
|
noFf: z.boolean().default(false).describe('Create a merge commit even when the merge resolves as a fast-forward (`--no-ff`).'),
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
import {
|
|
5
|
-
|
|
1
|
+
// Import utils from barrel (logger from ../utils/internal/logger.js)
|
|
2
|
+
import { logger } from '../../../utils/index.js';
|
|
3
|
+
// Import utils from barrel (ErrorHandler from ../utils/internal/errorHandler.js)
|
|
4
|
+
import { ErrorHandler } from '../../../utils/index.js';
|
|
5
|
+
// Import utils from barrel (requestContextService from ../utils/internal/requestContext.js)
|
|
6
|
+
import { BaseErrorCode } from '../../../types-global/errors.js'; // Keep direct import for types-global
|
|
7
|
+
import { requestContextService } from '../../../utils/index.js';
|
|
8
|
+
import { GitMergeInputSchema, gitMergeLogic } from './logic.js';
|
|
6
9
|
let _getWorkingDirectory;
|
|
7
10
|
let _getSessionId;
|
|
8
11
|
/**
|
|
@@ -1,15 +1,18 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
2
|
-
import { promisify } from 'util';
|
|
3
1
|
import { exec } from 'child_process';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
|
|
2
|
+
import { promisify } from 'util';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
// Import utils from barrel (logger from ../utils/internal/logger.js)
|
|
5
|
+
import { logger } from '../../../utils/index.js';
|
|
6
|
+
// Import utils from barrel (RequestContext from ../utils/internal/requestContext.js)
|
|
7
|
+
import { BaseErrorCode, McpError } from '../../../types-global/errors.js'; // Keep direct import for types-global
|
|
8
|
+
// Import utils from barrel (sanitization from ../utils/security/sanitization.js)
|
|
9
|
+
import { sanitization } from '../../../utils/index.js';
|
|
7
10
|
const execAsync = promisify(exec);
|
|
8
11
|
// Define the input schema for the git_pull tool using Zod
|
|
9
12
|
export const GitPullInputSchema = z.object({
|
|
10
|
-
path: z.string().min(1).optional().default('.').describe("Path to the Git repository. Defaults to the session
|
|
13
|
+
path: z.string().min(1).optional().default('.').describe("Path to the Git repository. Defaults to the directory set via `git_set_working_dir` for the session; set 'git_set_working_dir' if not set."),
|
|
11
14
|
remote: z.string().optional().describe("The remote repository to pull from (e.g., 'origin'). Defaults to the tracked upstream or 'origin'."),
|
|
12
|
-
branch: z.string().optional().describe("The remote branch to pull. Defaults to the current branch's upstream."),
|
|
15
|
+
branch: z.string().optional().describe("The remote branch to pull (e.g., 'main'). Defaults to the current branch's upstream."),
|
|
13
16
|
rebase: z.boolean().optional().default(false).describe("Use 'git pull --rebase' instead of merge."),
|
|
14
17
|
ffOnly: z.boolean().optional().default(false).describe("Use '--ff-only' to only allow fast-forward merges."),
|
|
15
18
|
// Add other relevant git pull options as needed (e.g., --prune, --tags, --depth)
|
|
@@ -125,7 +128,7 @@ export async function pullGitChanges(input, context) {
|
|
|
125
128
|
throw new McpError(BaseErrorCode.NOT_FOUND, `Path is not a Git repository: ${targetPath}`, { context, operation, originalError: error });
|
|
126
129
|
}
|
|
127
130
|
if (errorMessage.includes('resolve host') || errorMessage.includes('Could not read from remote repository')) {
|
|
128
|
-
throw new McpError(BaseErrorCode.
|
|
131
|
+
throw new McpError(BaseErrorCode.SERVICE_UNAVAILABLE, `Failed to connect to remote repository. Error: ${errorMessage}`, { context, operation, originalError: error });
|
|
129
132
|
}
|
|
130
133
|
if (errorMessage.includes('merge conflict') || errorMessage.includes('fix conflicts')) {
|
|
131
134
|
// This might be caught here if execAsync throws due to non-zero exit code during conflict
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
3
|
-
|
|
1
|
+
// Import utils from barrel (ErrorHandler from ../utils/internal/errorHandler.js)
|
|
2
|
+
import { ErrorHandler } from '../../../utils/index.js';
|
|
3
|
+
// Import utils from barrel (logger from ../utils/internal/logger.js)
|
|
4
|
+
import { logger } from '../../../utils/index.js';
|
|
5
|
+
// Import utils from barrel (requestContextService, RequestContext from ../utils/internal/requestContext.js)
|
|
6
|
+
import { BaseErrorCode } from '../../../types-global/errors.js'; // Keep direct import for types-global
|
|
7
|
+
import { requestContextService } from '../../../utils/index.js';
|
|
4
8
|
import { GitPullInputSchema, pullGitChanges } from './logic.js';
|
|
5
|
-
import { BaseErrorCode } from '../../../types-global/errors.js';
|
|
6
9
|
let _getWorkingDirectory;
|
|
7
10
|
let _getSessionId;
|
|
8
11
|
/**
|
|
@@ -1,16 +1,19 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
2
|
-
import { promisify } from 'util';
|
|
3
1
|
import { exec } from 'child_process';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
|
|
2
|
+
import { promisify } from 'util';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
// Import utils from barrel (logger from ../utils/internal/logger.js)
|
|
5
|
+
import { logger } from '../../../utils/index.js';
|
|
6
|
+
// Import utils from barrel (RequestContext from ../utils/internal/requestContext.js)
|
|
7
|
+
import { BaseErrorCode, McpError } from '../../../types-global/errors.js'; // Keep direct import for types-global
|
|
8
|
+
// Import utils from barrel (sanitization from ../utils/security/sanitization.js)
|
|
9
|
+
import { sanitization } from '../../../utils/index.js';
|
|
7
10
|
const execAsync = promisify(exec);
|
|
8
11
|
// Define the input schema for the git_push tool using Zod
|
|
9
12
|
export const GitPushInputSchema = z.object({
|
|
10
|
-
path: z.string().min(1).optional().default('.').describe("Path to the Git repository. Defaults to the session
|
|
13
|
+
path: z.string().min(1).optional().default('.').describe("Path to the Git repository. Defaults to the directory set via `git_set_working_dir` for the session; set 'git_set_working_dir' if not set."),
|
|
11
14
|
remote: z.string().optional().describe("The remote repository to push to (e.g., 'origin'). Defaults to the tracked upstream or 'origin'."),
|
|
12
|
-
branch: z.string().optional().describe("The local branch to push. Defaults to the current branch."),
|
|
13
|
-
remoteBranch: z.string().optional().describe("The remote branch to push to. Defaults to the same name as the local branch."),
|
|
15
|
+
branch: z.string().optional().describe("The local branch to push (e.g., 'main', 'feat/new-login'). Defaults to the current branch."),
|
|
16
|
+
remoteBranch: z.string().optional().describe("The remote branch to push to (e.g., 'main', 'develop'). Defaults to the same name as the local branch."),
|
|
14
17
|
force: z.boolean().optional().default(false).describe("Force the push (use with caution: `--force-with-lease` is generally safer)."),
|
|
15
18
|
forceWithLease: z.boolean().optional().default(false).describe("Force the push only if the remote ref is the expected value (`--force-with-lease`). Safer than --force."),
|
|
16
19
|
setUpstream: z.boolean().optional().default(false).describe("Set the upstream tracking configuration (`-u` or `--set-upstream`)."),
|
|
@@ -169,7 +172,7 @@ export async function pushGitChanges(input, context) {
|
|
|
169
172
|
throw new McpError(BaseErrorCode.NOT_FOUND, `Path is not a Git repository: ${targetPath}`, { context, operation, originalError: error });
|
|
170
173
|
}
|
|
171
174
|
if (errorMessage.includes('resolve host') || errorMessage.includes('Could not read from remote repository') || errorMessage.includes('Connection timed out')) {
|
|
172
|
-
throw new McpError(BaseErrorCode.
|
|
175
|
+
throw new McpError(BaseErrorCode.SERVICE_UNAVAILABLE, `Failed to connect to remote repository. Error: ${errorMessage}`, { context, operation, originalError: error });
|
|
173
176
|
}
|
|
174
177
|
if (errorMessage.includes('rejected') || errorMessage.includes('failed to push some refs')) {
|
|
175
178
|
// This might be caught here if execAsync throws due to non-zero exit code on rejection
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
3
|
-
|
|
1
|
+
// Import utils from barrel (ErrorHandler from ../utils/internal/errorHandler.js)
|
|
2
|
+
import { ErrorHandler } from '../../../utils/index.js';
|
|
3
|
+
// Import utils from barrel (logger from ../utils/internal/logger.js)
|
|
4
|
+
import { logger } from '../../../utils/index.js';
|
|
5
|
+
// Import utils from barrel (requestContextService, RequestContext from ../utils/internal/requestContext.js)
|
|
6
|
+
import { BaseErrorCode } from '../../../types-global/errors.js'; // Keep direct import for types-global
|
|
7
|
+
import { requestContextService } from '../../../utils/index.js';
|
|
4
8
|
import { GitPushInputSchema, pushGitChanges } from './logic.js';
|
|
5
|
-
import { BaseErrorCode } from '../../../types-global/errors.js';
|
|
6
9
|
let _getWorkingDirectory;
|
|
7
10
|
let _getSessionId;
|
|
8
11
|
/**
|
|
@@ -1,13 +1,16 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
2
|
-
import { promisify } from 'util';
|
|
3
1
|
import { exec } from 'child_process';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
|
|
2
|
+
import { promisify } from 'util';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
// Import utils from barrel (logger from ../utils/internal/logger.js)
|
|
5
|
+
import { logger } from '../../../utils/index.js';
|
|
6
|
+
// Import utils from barrel (RequestContext from ../utils/internal/requestContext.js)
|
|
7
|
+
import { BaseErrorCode, McpError } from '../../../types-global/errors.js'; // Keep direct import for types-global
|
|
8
|
+
// Import utils from barrel (sanitization from ../utils/security/sanitization.js)
|
|
9
|
+
import { sanitization } from '../../../utils/index.js';
|
|
7
10
|
const execAsync = promisify(exec);
|
|
8
11
|
// Define the BASE input schema for the git_rebase tool using Zod
|
|
9
12
|
export const GitRebaseBaseSchema = z.object({
|
|
10
|
-
path: z.string().min(1).optional().default('.').describe("Path to the local Git repository.
|
|
13
|
+
path: z.string().min(1).optional().default('.').describe("Path to the local Git repository. Defaults to the directory set via `git_set_working_dir` for the session; set 'git_set_working_dir' if not set."),
|
|
11
14
|
mode: z.enum(['start', 'continue', 'abort', 'skip']).default('start').describe("Rebase operation mode: 'start' (initiate rebase), 'continue', 'abort', 'skip' (manage ongoing rebase)."),
|
|
12
15
|
upstream: z.string().min(1).optional().describe("The upstream branch or commit to rebase onto. Required for 'start' mode unless 'interactive' is true with default base."),
|
|
13
16
|
branch: z.string().min(1).optional().describe("The branch to rebase. Defaults to the current branch if omitted."),
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
import {
|
|
5
|
-
|
|
1
|
+
// Import utils from barrel (logger from ../utils/internal/logger.js)
|
|
2
|
+
import { logger } from '../../../utils/index.js';
|
|
3
|
+
// Import utils from barrel (ErrorHandler from ../utils/internal/errorHandler.js)
|
|
4
|
+
import { ErrorHandler } from '../../../utils/index.js';
|
|
5
|
+
// Import utils from barrel (requestContextService from ../utils/internal/requestContext.js)
|
|
6
|
+
import { BaseErrorCode } from '../../../types-global/errors.js'; // Keep direct import for types-global
|
|
7
|
+
import { requestContextService } from '../../../utils/index.js';
|
|
8
|
+
import { GitRebaseBaseSchema, gitRebaseLogic } from './logic.js';
|
|
6
9
|
let _getWorkingDirectory;
|
|
7
10
|
let _getSessionId;
|
|
8
11
|
/**
|
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
import { exec } from 'child_process';
|
|
2
2
|
import { promisify } from 'util';
|
|
3
3
|
import { z } from 'zod';
|
|
4
|
-
import { BaseErrorCode, McpError } from '../../../types-global/errors.js';
|
|
5
|
-
import { logger } from '../../../utils/
|
|
6
|
-
import { sanitization } from '../../../utils/sanitization.js';
|
|
4
|
+
import { BaseErrorCode, McpError } from '../../../types-global/errors.js'; // Direct import for types-global
|
|
5
|
+
import { logger, sanitization } from '../../../utils/index.js'; // Logger (./utils/internal/logger.js) & RequestContext (./utils/internal/requestContext.js) & sanitization (./utils/security/sanitization.js)
|
|
7
6
|
const execAsync = promisify(exec);
|
|
8
7
|
// Define the input schema for the git_remote tool using Zod
|
|
9
8
|
export const GitRemoteInputSchema = z.object({
|
|
10
|
-
path: z.string().min(1).optional().default('.').describe("Path to the Git repository. Defaults to the session
|
|
9
|
+
path: z.string().min(1).optional().default('.').describe("Path to the Git repository. Defaults to the directory set via `git_set_working_dir` for the session; set 'git_set_working_dir' if not set."),
|
|
11
10
|
mode: z.enum(['list', 'add', 'remove', 'show']).describe("Operation mode: 'list', 'add', 'remove', 'show'"),
|
|
12
11
|
name: z.string().min(1).optional().describe("Remote name (required for 'add', 'remove', 'show')"),
|
|
13
|
-
url: z.string().
|
|
12
|
+
url: z.string().optional().describe("Remote URL (required for 'add')"), // Removed .url() validation
|
|
14
13
|
});
|
|
15
14
|
/**
|
|
16
15
|
* Executes git remote commands based on the specified mode.
|
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import { BaseErrorCode } from '../../../types-global/errors.js';
|
|
2
|
-
import { ErrorHandler } from '../../../utils/
|
|
3
|
-
import { logger } from '../../../utils/logger.js';
|
|
4
|
-
import { requestContextService } from '../../../utils/requestContext.js';
|
|
1
|
+
import { BaseErrorCode } from '../../../types-global/errors.js'; // Direct import for types-global
|
|
2
|
+
import { ErrorHandler, logger, requestContextService } from '../../../utils/index.js'; // ErrorHandler (./utils/internal/errorHandler.js), logger (./utils/internal/logger.js), requestContextService (./utils/internal/requestContext.js)
|
|
5
3
|
import { GitRemoteInputSchema, gitRemoteLogic } from './logic.js';
|
|
6
4
|
let _getWorkingDirectory;
|
|
7
5
|
let _getSessionId;
|
|
@@ -1,15 +1,14 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
2
|
-
import { promisify } from 'util';
|
|
3
1
|
import { exec } from 'child_process';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
2
|
+
import { promisify } from 'util';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
import { BaseErrorCode, McpError } from '../../../types-global/errors.js'; // Direct import for types-global
|
|
5
|
+
import { logger, sanitization } from '../../../utils/index.js'; // logger (./utils/internal/logger.js), RequestContext (./utils/internal/requestContext.js), sanitization (./utils/security/sanitization.js)
|
|
7
6
|
const execAsync = promisify(exec);
|
|
8
7
|
// Define the reset modes
|
|
9
8
|
const ResetModeEnum = z.enum(['soft', 'mixed', 'hard', 'merge', 'keep']);
|
|
10
9
|
// Define the input schema for the git_reset tool using Zod
|
|
11
10
|
export const GitResetInputSchema = z.object({
|
|
12
|
-
path: z.string().min(1).optional().default('.').describe("Path to the Git repository. Defaults to the session
|
|
11
|
+
path: z.string().min(1).optional().default('.').describe("Path to the Git repository. Defaults to the directory set via `git_set_working_dir` for the session; set 'git_set_working_dir' if not set."),
|
|
13
12
|
mode: ResetModeEnum.optional().default('mixed').describe("Reset mode: 'soft' (reset HEAD only), 'mixed' (reset HEAD and index, default), 'hard' (reset HEAD, index, and working tree - USE WITH CAUTION), 'merge', 'keep'."),
|
|
14
13
|
commit: z.string().optional().describe("Commit, branch, or ref to reset to. Defaults to HEAD (useful for unstaging with 'mixed' mode)."),
|
|
15
14
|
// file: z.string().optional().describe("If specified, reset only this file in the index (unstaging). Mode must be 'mixed' or omitted."), // Git reset [<mode>] [<tree-ish>] [--] <paths>… is complex, handle separately if needed
|
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { logger } from '../../../utils/
|
|
3
|
-
import { requestContextService } from '../../../utils/requestContext.js';
|
|
1
|
+
import { BaseErrorCode } from '../../../types-global/errors.js'; // Direct import for types-global
|
|
2
|
+
import { ErrorHandler, logger, requestContextService } from '../../../utils/index.js'; // ErrorHandler (./utils/internal/errorHandler.js), logger (./utils/internal/logger.js), requestContextService & RequestContext (./utils/internal/requestContext.js)
|
|
4
3
|
import { GitResetInputSchema, resetGitState } from './logic.js';
|
|
5
|
-
import { BaseErrorCode } from '../../../types-global/errors.js';
|
|
6
4
|
let _getWorkingDirectory;
|
|
7
5
|
let _getSessionId;
|
|
8
6
|
/**
|
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
2
1
|
import { exec } from 'child_process';
|
|
3
|
-
import { promisify } from 'util';
|
|
4
2
|
import fs from 'fs/promises';
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
3
|
+
import { promisify } from 'util';
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
import { BaseErrorCode, McpError } from '../../../types-global/errors.js'; // Direct import for types-global
|
|
6
|
+
import { logger, sanitization } from '../../../utils/index.js'; // RequestContext (./utils/internal/requestContext.js), logger (./utils/internal/logger.js), sanitization (./utils/security/sanitization.js)
|
|
8
7
|
const execAsync = promisify(exec);
|
|
9
8
|
// Define the Zod schema for input validation
|
|
10
9
|
export const GitSetWorkingDirInputSchema = z.object({
|
|
11
|
-
path: z.string().min(1, "Path cannot be empty.").describe("The absolute path to set as the default working directory for the current session."),
|
|
10
|
+
path: z.string().min(1, "Path cannot be empty.").describe("The absolute path to set as the default working directory for the current session. Set this before using other git_* tools."),
|
|
12
11
|
validateGitRepo: z.boolean().default(true).describe("Whether to validate that the path is a Git repository"),
|
|
13
12
|
});
|
|
14
13
|
/**
|
|
@@ -1,19 +1,21 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { logger } from '../../../utils/
|
|
3
|
-
import { requestContextService } from '../../../utils/requestContext.js';
|
|
1
|
+
import { BaseErrorCode } from '../../../types-global/errors.js'; // Direct import for types-global
|
|
2
|
+
import { ErrorHandler, logger, requestContextService } from '../../../utils/index.js'; // ErrorHandler (./utils/internal/errorHandler.js), logger (./utils/internal/logger.js), requestContextService & RequestContext (./utils/internal/requestContext.js)
|
|
4
3
|
import { GitSetWorkingDirInputSchema, gitSetWorkingDirLogic } from './logic.js';
|
|
5
|
-
|
|
4
|
+
let _getWorkingDirectory; // Added getter
|
|
6
5
|
let _setWorkingDirectory;
|
|
7
6
|
let _getSessionId;
|
|
8
7
|
/**
|
|
9
8
|
* Initializes the state accessors needed by the tool registration.
|
|
10
9
|
* This should be called once during server setup.
|
|
11
|
-
* @param
|
|
12
|
-
* @param
|
|
10
|
+
* @param getWdFn - Function to get the working directory for a session.
|
|
11
|
+
* @param setWdFn - Function to set the working directory for a session.
|
|
12
|
+
* @param getSidFn - Function to get the session ID from context.
|
|
13
13
|
*/
|
|
14
|
-
export function initializeGitSetWorkingDirStateAccessors(
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
export function initializeGitSetWorkingDirStateAccessors(getWdFn, // Added getter parameter
|
|
15
|
+
setWdFn, getSidFn) {
|
|
16
|
+
_getWorkingDirectory = getWdFn; // Store getter
|
|
17
|
+
_setWorkingDirectory = setWdFn;
|
|
18
|
+
_getSessionId = getSidFn;
|
|
17
19
|
logger.info('State accessors initialized for git_set_working_dir tool registration.');
|
|
18
20
|
}
|
|
19
21
|
const TOOL_NAME = 'git_set_working_dir';
|
|
@@ -25,8 +27,9 @@ const TOOL_DESCRIPTION = "Sets the default working directory for the current ses
|
|
|
25
27
|
* @throws {Error} If state accessors are not initialized.
|
|
26
28
|
*/
|
|
27
29
|
export async function registerGitSetWorkingDirTool(server) {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
+
// Check all required accessors
|
|
31
|
+
if (!_getWorkingDirectory || !_setWorkingDirectory || !_getSessionId) {
|
|
32
|
+
throw new Error('State accessors (getWD, setWD, getSID) for git_set_working_dir must be initialized before registration.');
|
|
30
33
|
}
|
|
31
34
|
try {
|
|
32
35
|
server.tool(TOOL_NAME, TOOL_DESCRIPTION, GitSetWorkingDirInputSchema.shape, // Pass the shape for SDK validation
|
|
@@ -40,11 +43,17 @@ export async function registerGitSetWorkingDirTool(server) {
|
|
|
40
43
|
const setWorkingDirectoryForSession = (path) => {
|
|
41
44
|
_setWorkingDirectory(sessionId, path); // Non-null assertion
|
|
42
45
|
};
|
|
43
|
-
//
|
|
46
|
+
// Define the session-specific getter function (needed by logic?)
|
|
47
|
+
// If the logic needs the current WD, pass the getter too. Assuming it might.
|
|
48
|
+
const getWorkingDirectoryForSession = () => {
|
|
49
|
+
return _getWorkingDirectory(sessionId); // Non-null assertion
|
|
50
|
+
};
|
|
51
|
+
// Enhance context with session ID and the getter/setter functions
|
|
44
52
|
const logicContext = {
|
|
45
53
|
...requestContext,
|
|
46
54
|
sessionId: sessionId,
|
|
47
|
-
|
|
55
|
+
getWorkingDirectory: getWorkingDirectoryForSession, // Pass getter
|
|
56
|
+
setWorkingDirectory: setWorkingDirectoryForSession, // Pass setter
|
|
48
57
|
};
|
|
49
58
|
return await ErrorHandler.tryCatch(async () => {
|
|
50
59
|
// Call the core logic function with validated args and enhanced context
|