infra-kit 0.1.39 → 0.1.41
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/cli.js +18 -18
- package/dist/cli.js.map +4 -4
- package/dist/mcp.js +18 -1
- package/dist/mcp.js.map +4 -4
- package/package.json +3 -2
- package/src/commands/gh-merge-dev/gh-merge-dev.ts +59 -22
- package/src/commands/gh-merge-dev/index.ts +1 -1
- package/src/commands/gh-release-create/gh-release-create.ts +58 -20
- package/src/commands/gh-release-create/index.ts +1 -1
- package/src/commands/gh-release-deliver/gh-release-deliver.ts +47 -11
- package/src/commands/gh-release-deliver/index.ts +1 -1
- package/src/commands/gh-release-deploy/gh-release-deploy.ts +47 -7
- package/src/commands/gh-release-deploy/index.ts +1 -1
- package/src/commands/gh-release-list/gh-release-list.ts +37 -5
- package/src/commands/gh-release-list/index.ts +1 -1
- package/src/commands/worktrees-add/index.ts +1 -1
- package/src/commands/worktrees-add/worktrees-add.ts +45 -19
- package/src/commands/worktrees-list/index.ts +1 -1
- package/src/commands/worktrees-list/worktrees-list.ts +69 -33
- package/src/commands/worktrees-remove/index.ts +1 -1
- package/src/commands/worktrees-remove/worktrees-remove.ts +44 -18
- package/src/commands/worktrees-sync/index.ts +1 -1
- package/src/commands/worktrees-sync/worktrees-sync.ts +42 -19
- package/src/entry/cli.ts +6 -6
- package/src/entry/mcp.ts +4 -4
- package/src/lib/error-handlers/index.ts +8 -2
- package/src/lib/logger/index.ts +23 -2
- package/src/mcp/prompts/index.ts +1 -1
- package/src/mcp/resources/index.ts +1 -1
- package/src/mcp/server.ts +2 -2
- package/src/mcp/tools/index.ts +39 -1
- package/src/shared/gh-cli-auth/gh-cli-auth.ts +6 -4
- package/src/shared/gh-release-prs/gh-release-prs.ts +4 -2
- package/src/shared/logger/index.ts +4 -0
- package/src/shared/tool-handler/index.ts +1 -0
- package/src/shared/tool-handler/tool-handler.ts +29 -0
- package/src/types.ts +11 -0
|
@@ -1,28 +1,25 @@
|
|
|
1
|
-
/* eslint-disable no-console */
|
|
2
1
|
import checkbox from '@inquirer/checkbox'
|
|
3
2
|
import confirm from '@inquirer/confirm'
|
|
4
3
|
import process from 'node:process'
|
|
4
|
+
import { z } from 'zod'
|
|
5
5
|
import { $ } from 'zx'
|
|
6
6
|
|
|
7
7
|
import { WORKTREES_DIR_SUFFIX } from 'src/shared/constants'
|
|
8
8
|
import { getCurrentWorktrees, getProjectRoot } from 'src/shared/git-utils'
|
|
9
|
+
import { logger } from 'src/shared/logger'
|
|
10
|
+
import type { RequiredConfirmedOptionArg, ToolsExecutionResult } from 'src/types'
|
|
9
11
|
|
|
10
12
|
// Constants
|
|
11
|
-
interface WorktreeManagementArgs {
|
|
12
|
-
yes: boolean
|
|
13
|
+
interface WorktreeManagementArgs extends RequiredConfirmedOptionArg {
|
|
13
14
|
all: boolean
|
|
14
15
|
}
|
|
15
16
|
|
|
16
|
-
interface WorktreeManagementResult {
|
|
17
|
-
removed: string[]
|
|
18
|
-
}
|
|
19
|
-
|
|
20
17
|
/**
|
|
21
18
|
* Manage git worktrees for release branches
|
|
22
19
|
* Creates worktrees for active release branches and removes unused ones
|
|
23
20
|
*/
|
|
24
|
-
export const worktreesRemove = async (options: WorktreeManagementArgs): Promise<
|
|
25
|
-
const {
|
|
21
|
+
export const worktreesRemove = async (options: WorktreeManagementArgs): Promise<ToolsExecutionResult> => {
|
|
22
|
+
const { confirmedCommand, all } = options
|
|
26
23
|
|
|
27
24
|
try {
|
|
28
25
|
const currentWorktrees = await getCurrentWorktrees('release')
|
|
@@ -46,14 +43,14 @@ export const worktreesRemove = async (options: WorktreeManagementArgs): Promise<
|
|
|
46
43
|
}
|
|
47
44
|
|
|
48
45
|
// Ask for confirmation
|
|
49
|
-
const answer =
|
|
46
|
+
const answer = confirmedCommand
|
|
50
47
|
? true
|
|
51
48
|
: await confirm({
|
|
52
49
|
message: 'Are you sure you want to proceed with these worktree changes?',
|
|
53
50
|
})
|
|
54
51
|
|
|
55
52
|
if (!answer) {
|
|
56
|
-
|
|
53
|
+
logger.info('Operation cancelled. Exiting...')
|
|
57
54
|
process.exit(0)
|
|
58
55
|
}
|
|
59
56
|
|
|
@@ -61,11 +58,22 @@ export const worktreesRemove = async (options: WorktreeManagementArgs): Promise<
|
|
|
61
58
|
|
|
62
59
|
logResults(removedWorktrees)
|
|
63
60
|
|
|
61
|
+
const structuredContent = {
|
|
62
|
+
removedWorktrees,
|
|
63
|
+
count: removedWorktrees.length,
|
|
64
|
+
}
|
|
65
|
+
|
|
64
66
|
return {
|
|
65
|
-
|
|
67
|
+
content: [
|
|
68
|
+
{
|
|
69
|
+
type: 'text',
|
|
70
|
+
text: JSON.stringify(structuredContent, null, 2),
|
|
71
|
+
},
|
|
72
|
+
],
|
|
73
|
+
structuredContent,
|
|
66
74
|
}
|
|
67
75
|
} catch (error) {
|
|
68
|
-
|
|
76
|
+
logger.error({ error }, '❌ Error managing worktrees')
|
|
69
77
|
throw error
|
|
70
78
|
}
|
|
71
79
|
}
|
|
@@ -82,7 +90,7 @@ const removeWorktrees = async (branches: string[], worktreeDir: string): Promise
|
|
|
82
90
|
await $`git worktree remove ${worktreePath}`
|
|
83
91
|
removed.push(branch)
|
|
84
92
|
} catch (error) {
|
|
85
|
-
|
|
93
|
+
logger.error({ error, branch }, `❌ Failed to remove worktree for ${branch}`)
|
|
86
94
|
}
|
|
87
95
|
}
|
|
88
96
|
|
|
@@ -94,10 +102,28 @@ const removeWorktrees = async (branches: string[], worktreeDir: string): Promise
|
|
|
94
102
|
*/
|
|
95
103
|
const logResults = (removed: string[]): void => {
|
|
96
104
|
if (removed.length > 0) {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
105
|
+
logger.info('❌ Removed worktrees:')
|
|
106
|
+
logger.info(removed.join('\n'))
|
|
107
|
+
logger.info('')
|
|
100
108
|
} else {
|
|
101
|
-
|
|
109
|
+
logger.info('ℹ️ No unused worktrees to remove')
|
|
102
110
|
}
|
|
103
111
|
}
|
|
112
|
+
|
|
113
|
+
// MCP Tool Registration
|
|
114
|
+
const worktreesRemoveSchema = z.object({
|
|
115
|
+
all: z.boolean().describe('Remove all worktrees without prompting'),
|
|
116
|
+
})
|
|
117
|
+
|
|
118
|
+
const worktreesRemoveOutputSchema = z.object({
|
|
119
|
+
removedWorktrees: z.array(z.string()).describe('List of removed worktree branches'),
|
|
120
|
+
count: z.number().describe('Number of worktrees removed'),
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
export const worktreesRemoveMcpTool = {
|
|
124
|
+
name: 'worktrees-remove',
|
|
125
|
+
description: 'Remove selected worktrees',
|
|
126
|
+
inputSchema: worktreesRemoveSchema,
|
|
127
|
+
outputSchema: worktreesRemoveOutputSchema,
|
|
128
|
+
handler: worktreesRemove,
|
|
129
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { worktreesSync } from './worktrees-sync'
|
|
1
|
+
export { worktreesSync, worktreesSyncMcpTool } from './worktrees-sync'
|
|
@@ -1,29 +1,25 @@
|
|
|
1
|
-
/* eslint-disable no-console */
|
|
2
1
|
import confirm from '@inquirer/confirm'
|
|
3
2
|
import process from 'node:process'
|
|
3
|
+
import { z } from 'zod'
|
|
4
4
|
import { $ } from 'zx'
|
|
5
5
|
|
|
6
6
|
import { WORKTREES_DIR_SUFFIX } from 'src/shared/constants'
|
|
7
7
|
import { getReleasePRs } from 'src/shared/gh-release-prs'
|
|
8
8
|
import { getCurrentWorktrees, getProjectRoot } from 'src/shared/git-utils'
|
|
9
|
+
import { logger } from 'src/shared/logger'
|
|
10
|
+
import type { RequiredConfirmedOptionArg, ToolsExecutionResult } from 'src/types'
|
|
9
11
|
|
|
10
12
|
// Constants
|
|
11
13
|
const RELEASE_BRANCH_PREFIX = 'release/v'
|
|
12
14
|
|
|
13
|
-
interface
|
|
14
|
-
removed: string[]
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
interface WorktreeSyncArgs {
|
|
18
|
-
yes: boolean
|
|
19
|
-
}
|
|
15
|
+
interface WorktreeSyncArgs extends RequiredConfirmedOptionArg {}
|
|
20
16
|
|
|
21
17
|
/**
|
|
22
18
|
* Manage git worktrees for release branches
|
|
23
19
|
* Creates worktrees for active release branches and removes unused ones
|
|
24
20
|
*/
|
|
25
|
-
export const worktreesSync = async (options: WorktreeSyncArgs): Promise<
|
|
26
|
-
const {
|
|
21
|
+
export const worktreesSync = async (options: WorktreeSyncArgs): Promise<ToolsExecutionResult> => {
|
|
22
|
+
const { confirmedCommand } = options
|
|
27
23
|
|
|
28
24
|
try {
|
|
29
25
|
const currentWorktrees = await getCurrentWorktrees('release')
|
|
@@ -34,14 +30,14 @@ export const worktreesSync = async (options: WorktreeSyncArgs): Promise<Worktree
|
|
|
34
30
|
const releasePRsList = await getReleasePRs()
|
|
35
31
|
|
|
36
32
|
// Ask for confirmation
|
|
37
|
-
const answer =
|
|
33
|
+
const answer = confirmedCommand
|
|
38
34
|
? true
|
|
39
35
|
: await confirm({
|
|
40
36
|
message: 'Are you sure you want to proceed with these worktree changes?',
|
|
41
37
|
})
|
|
42
38
|
|
|
43
39
|
if (!answer) {
|
|
44
|
-
|
|
40
|
+
logger.info('Operation cancelled. Exiting...')
|
|
45
41
|
process.exit(0)
|
|
46
42
|
}
|
|
47
43
|
|
|
@@ -54,11 +50,22 @@ export const worktreesSync = async (options: WorktreeSyncArgs): Promise<Worktree
|
|
|
54
50
|
|
|
55
51
|
logResults(removedWorktrees)
|
|
56
52
|
|
|
53
|
+
const structuredContent = {
|
|
54
|
+
removedWorktrees,
|
|
55
|
+
count: removedWorktrees.length,
|
|
56
|
+
}
|
|
57
|
+
|
|
57
58
|
return {
|
|
58
|
-
|
|
59
|
+
content: [
|
|
60
|
+
{
|
|
61
|
+
type: 'text',
|
|
62
|
+
text: JSON.stringify(structuredContent, null, 2),
|
|
63
|
+
},
|
|
64
|
+
],
|
|
65
|
+
structuredContent,
|
|
59
66
|
}
|
|
60
67
|
} catch (error) {
|
|
61
|
-
|
|
68
|
+
logger.error({ error }, '❌ Error managing worktrees')
|
|
62
69
|
throw error
|
|
63
70
|
}
|
|
64
71
|
}
|
|
@@ -93,7 +100,7 @@ const removeWorktrees = async (branches: string[], worktreeDir: string): Promise
|
|
|
93
100
|
await $`git worktree remove ${worktreePath}`
|
|
94
101
|
removed.push(branch)
|
|
95
102
|
} catch (error) {
|
|
96
|
-
|
|
103
|
+
logger.error({ error, branch }, `❌ Failed to remove worktree for ${branch}`)
|
|
97
104
|
}
|
|
98
105
|
}
|
|
99
106
|
|
|
@@ -105,10 +112,26 @@ const removeWorktrees = async (branches: string[], worktreeDir: string): Promise
|
|
|
105
112
|
*/
|
|
106
113
|
const logResults = (removed: string[]): void => {
|
|
107
114
|
if (removed.length > 0) {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
115
|
+
logger.info('❌ Removed worktrees:')
|
|
116
|
+
logger.info(removed.join('\n'))
|
|
117
|
+
logger.info('')
|
|
111
118
|
} else {
|
|
112
|
-
|
|
119
|
+
logger.info('ℹ️ No unused worktrees to remove')
|
|
113
120
|
}
|
|
114
121
|
}
|
|
122
|
+
|
|
123
|
+
// MCP Tool Registration
|
|
124
|
+
const worktreesSyncSchema = z.object({})
|
|
125
|
+
|
|
126
|
+
const worktreesSyncOutputSchema = z.object({
|
|
127
|
+
removedWorktrees: z.array(z.string()).describe('List of removed worktree branches'),
|
|
128
|
+
count: z.number().describe('Number of worktrees removed during sync'),
|
|
129
|
+
})
|
|
130
|
+
|
|
131
|
+
export const worktreesSyncMcpTool = {
|
|
132
|
+
name: 'worktrees-sync',
|
|
133
|
+
description: 'Synchronize worktrees with active release branches',
|
|
134
|
+
inputSchema: worktreesSyncSchema,
|
|
135
|
+
outputSchema: worktreesSyncOutputSchema,
|
|
136
|
+
handler: worktreesSync,
|
|
137
|
+
}
|
package/src/entry/cli.ts
CHANGED
|
@@ -19,7 +19,7 @@ program
|
|
|
19
19
|
.option('-a, --all', 'Select all active release branches')
|
|
20
20
|
.option('-y, --yes', 'Skip confirmation prompt')
|
|
21
21
|
.action(async (options) => {
|
|
22
|
-
await ghMergeDev({ all: options.all,
|
|
22
|
+
await ghMergeDev({ all: options.all, confirmedCommand: options.yes })
|
|
23
23
|
})
|
|
24
24
|
|
|
25
25
|
program
|
|
@@ -36,7 +36,7 @@ program
|
|
|
36
36
|
.option('-y, --yes', 'Skip confirmation prompt')
|
|
37
37
|
.option('-c, --checkout', 'Checkout the created branch after creation (only works when creating a single branch)')
|
|
38
38
|
.action(async (options) => {
|
|
39
|
-
await ghReleaseCreate({ versions: options.versions,
|
|
39
|
+
await ghReleaseCreate({ versions: options.versions, confirmedCommand: options.yes, checkout: options.checkout })
|
|
40
40
|
})
|
|
41
41
|
|
|
42
42
|
program
|
|
@@ -54,7 +54,7 @@ program
|
|
|
54
54
|
.option('-v, --version <version>', 'Specify the version to release, e.g. 1.2.5')
|
|
55
55
|
.option('-y, --yes', 'Skip confirmation prompt')
|
|
56
56
|
.action(async (options) => {
|
|
57
|
-
await ghReleaseDeliver({ version: options.version,
|
|
57
|
+
await ghReleaseDeliver({ version: options.version, confirmedCommand: options.yes })
|
|
58
58
|
})
|
|
59
59
|
|
|
60
60
|
program
|
|
@@ -62,7 +62,7 @@ program
|
|
|
62
62
|
.description('Sync git worktrees for release branches')
|
|
63
63
|
.option('-y, --yes', 'Skip confirmation prompt')
|
|
64
64
|
.action(async (options) => {
|
|
65
|
-
await worktreesSync({
|
|
65
|
+
await worktreesSync({ confirmedCommand: options.yes })
|
|
66
66
|
})
|
|
67
67
|
|
|
68
68
|
program
|
|
@@ -71,7 +71,7 @@ program
|
|
|
71
71
|
.option('-y, --yes', 'Skip confirmation prompt')
|
|
72
72
|
.option('-a, --all', 'Select all active release branches')
|
|
73
73
|
.action(async (options) => {
|
|
74
|
-
await worktreesAdd({
|
|
74
|
+
await worktreesAdd({ confirmedCommand: options.yes, all: options.all })
|
|
75
75
|
})
|
|
76
76
|
|
|
77
77
|
program
|
|
@@ -87,7 +87,7 @@ program
|
|
|
87
87
|
.option('-y, --yes', 'Skip confirmation prompt')
|
|
88
88
|
.option('-a, --all', 'Select all active release branches')
|
|
89
89
|
.action(async (options) => {
|
|
90
|
-
await worktreesRemove({
|
|
90
|
+
await worktreesRemove({ confirmedCommand: options.yes, all: options.all })
|
|
91
91
|
})
|
|
92
92
|
|
|
93
93
|
await validateGitHubCliAndAuth()
|
package/src/entry/mcp.ts
CHANGED
|
@@ -2,11 +2,11 @@ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio'
|
|
|
2
2
|
import process from 'node:process'
|
|
3
3
|
|
|
4
4
|
import { setupErrorHandlers } from 'src/lib/error-handlers'
|
|
5
|
-
import {
|
|
5
|
+
import { initLoggerMcp } from 'src/lib/logger'
|
|
6
6
|
|
|
7
7
|
import { createMcpServer } from '../mcp/server'
|
|
8
8
|
|
|
9
|
-
const logger =
|
|
9
|
+
const logger = initLoggerMcp()
|
|
10
10
|
|
|
11
11
|
const startServer = async () => {
|
|
12
12
|
let server
|
|
@@ -14,7 +14,7 @@ const startServer = async () => {
|
|
|
14
14
|
server = await createMcpServer()
|
|
15
15
|
} catch (error) {
|
|
16
16
|
logger.error({ err: error, msg: 'Failed to create MCP server' })
|
|
17
|
-
|
|
17
|
+
logger.error(`Fatal error during server creation.`)
|
|
18
18
|
|
|
19
19
|
process.exit(1)
|
|
20
20
|
}
|
|
@@ -27,7 +27,7 @@ const startServer = async () => {
|
|
|
27
27
|
logger.info({ msg: 'Server connected to transport. Ready.' })
|
|
28
28
|
} catch (error) {
|
|
29
29
|
logger.error({ err: error, msg: 'Failed to initialize server' })
|
|
30
|
-
|
|
30
|
+
logger.error(`Fatal error during server transport init.`)
|
|
31
31
|
|
|
32
32
|
process.exit(1)
|
|
33
33
|
}
|
|
@@ -3,6 +3,12 @@ import type { Logger } from 'pino'
|
|
|
3
3
|
|
|
4
4
|
import { LOG_FILE_PATH } from 'src/shared/constants'
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* Setup error handlers for the application
|
|
8
|
+
* @param logger - The logger instance
|
|
9
|
+
*
|
|
10
|
+
* ONLY FOR SERVER!
|
|
11
|
+
*/
|
|
6
12
|
export const setupErrorHandlers = (logger: Logger) => {
|
|
7
13
|
process.on('SIGINT', () => {
|
|
8
14
|
logger.info({ msg: 'Received SIGINT. Shutting down...' })
|
|
@@ -16,14 +22,14 @@ export const setupErrorHandlers = (logger: Logger) => {
|
|
|
16
22
|
|
|
17
23
|
process.on('uncaughtException', (error) => {
|
|
18
24
|
logger.fatal({ err: error, msg: 'Uncaught Exception' })
|
|
19
|
-
|
|
25
|
+
logger.error(`Uncaught Exception! Check ${LOG_FILE_PATH}. Shutting down...`)
|
|
20
26
|
logger.flush()
|
|
21
27
|
process.exit(1)
|
|
22
28
|
})
|
|
23
29
|
|
|
24
30
|
process.on('unhandledRejection', (reason, promise) => {
|
|
25
31
|
logger.fatal({ reason, promise, msg: 'Unhandled Rejection' })
|
|
26
|
-
|
|
32
|
+
logger.error(`Unhandled Rejection! Check ${LOG_FILE_PATH}. Shutting down...`)
|
|
27
33
|
logger.flush()
|
|
28
34
|
process.exit(1)
|
|
29
35
|
})
|
package/src/lib/logger/index.ts
CHANGED
|
@@ -1,14 +1,35 @@
|
|
|
1
1
|
import process from 'node:process'
|
|
2
2
|
import pino from 'pino'
|
|
3
|
+
import pretty from 'pino-pretty'
|
|
3
4
|
|
|
4
5
|
import { LOG_FILE_PATH } from 'src/shared/constants'
|
|
5
6
|
|
|
6
|
-
export const
|
|
7
|
+
export const initLoggerMcp = () => {
|
|
7
8
|
const logLevel = process.argv.includes('--debug') ? 'debug' : 'info'
|
|
8
9
|
|
|
9
|
-
const logger = pino({ level: logLevel }
|
|
10
|
+
const logger = pino({ level: logLevel })
|
|
10
11
|
|
|
11
12
|
logger.info(`Logger initialized with level: ${logLevel}. Logging to: ${LOG_FILE_PATH}`)
|
|
12
13
|
|
|
13
14
|
return logger
|
|
14
15
|
}
|
|
16
|
+
|
|
17
|
+
export const initLoggerCLI = () => {
|
|
18
|
+
const logLevel = process.argv.includes('--debug') ? 'debug' : 'info'
|
|
19
|
+
|
|
20
|
+
const ignoreFields = ['time', 'pid', 'hostname']
|
|
21
|
+
|
|
22
|
+
if (logLevel === 'debug') {
|
|
23
|
+
ignoreFields.push('level')
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const logger = pino(
|
|
27
|
+
{ level: logLevel },
|
|
28
|
+
pretty({
|
|
29
|
+
ignore: ignoreFields.join(','),
|
|
30
|
+
colorize: true,
|
|
31
|
+
}),
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
return logger
|
|
35
|
+
}
|
package/src/mcp/prompts/index.ts
CHANGED
package/src/mcp/server.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { Server } from '@modelcontextprotocol/sdk/server/index.js'
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { initLoggerMcp } from 'src/lib/logger'
|
|
4
4
|
|
|
5
5
|
import { initializePrompts } from './prompts'
|
|
6
6
|
import { initializeResources } from './resources'
|
|
7
7
|
import { initializeTools } from './tools'
|
|
8
8
|
|
|
9
|
-
const logger =
|
|
9
|
+
const logger = initLoggerMcp()
|
|
10
10
|
|
|
11
11
|
export async function createMcpServer() {
|
|
12
12
|
const server = new Server(
|
package/src/mcp/tools/index.ts
CHANGED
|
@@ -1,3 +1,41 @@
|
|
|
1
1
|
import type { Server } from '@modelcontextprotocol/sdk/server/index'
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
import { ghMergeDevMcpTool } from 'src/commands/gh-merge-dev'
|
|
4
|
+
import { ghReleaseCreateMcpTool } from 'src/commands/gh-release-create'
|
|
5
|
+
import { ghReleaseDeliverMcpTool } from 'src/commands/gh-release-deliver'
|
|
6
|
+
import { ghReleaseDeployMcpTool } from 'src/commands/gh-release-deploy'
|
|
7
|
+
import { ghReleaseListMcpTool } from 'src/commands/gh-release-list'
|
|
8
|
+
import { worktreesAddMcpTool } from 'src/commands/worktrees-add'
|
|
9
|
+
import { worktreesListMcpTool } from 'src/commands/worktrees-list'
|
|
10
|
+
import { worktreesRemoveMcpTool } from 'src/commands/worktrees-remove'
|
|
11
|
+
import { worktreesSyncMcpTool } from 'src/commands/worktrees-sync'
|
|
12
|
+
import { createToolHandler } from 'src/shared/tool-handler'
|
|
13
|
+
|
|
14
|
+
const tools = [
|
|
15
|
+
ghMergeDevMcpTool,
|
|
16
|
+
ghReleaseCreateMcpTool,
|
|
17
|
+
ghReleaseDeliverMcpTool,
|
|
18
|
+
ghReleaseDeployMcpTool,
|
|
19
|
+
ghReleaseListMcpTool,
|
|
20
|
+
worktreesAddMcpTool,
|
|
21
|
+
worktreesListMcpTool,
|
|
22
|
+
worktreesRemoveMcpTool,
|
|
23
|
+
worktreesSyncMcpTool,
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
export const initializeTools = async (server: Server) => {
|
|
27
|
+
for (const tool of tools) {
|
|
28
|
+
// eslint-disable-next-line ts/ban-ts-comment
|
|
29
|
+
// @ts-expect-error
|
|
30
|
+
server.registerTool(
|
|
31
|
+
tool.name,
|
|
32
|
+
{
|
|
33
|
+
description: tool.description,
|
|
34
|
+
inputSchema: tool.inputSchema,
|
|
35
|
+
outputSchema: tool.outputSchema,
|
|
36
|
+
handler: tool.handler,
|
|
37
|
+
},
|
|
38
|
+
createToolHandler({ toolName: tool.name, handler: tool.handler }),
|
|
39
|
+
)
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import process from 'node:process'
|
|
2
2
|
import { $ } from 'zx'
|
|
3
3
|
|
|
4
|
+
import { logger } from 'src/shared/logger'
|
|
5
|
+
|
|
4
6
|
/**
|
|
5
7
|
* Validate GitHub CLI installation and authentication status and throw an error if not valid
|
|
6
8
|
*/
|
|
@@ -8,16 +10,16 @@ export const validateGitHubCliAndAuth = async () => {
|
|
|
8
10
|
try {
|
|
9
11
|
await $`gh --version`
|
|
10
12
|
} catch (error: unknown) {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
+
logger.error({ error }, 'Error: GitHub CLI (gh) is not installed.')
|
|
14
|
+
logger.error('Please install it from: https://cli.github.com/')
|
|
13
15
|
process.exit(1)
|
|
14
16
|
}
|
|
15
17
|
|
|
16
18
|
try {
|
|
17
19
|
await $`gh auth status`
|
|
18
20
|
} catch (error: unknown) {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
+
logger.error({ error }, 'Error: GitHub CLI (gh) is not authenticated.')
|
|
22
|
+
logger.error('Please authenticate it from: https://cli.github.com/manual/gh_auth_login or type "gh auth login"')
|
|
21
23
|
process.exit(1)
|
|
22
24
|
}
|
|
23
25
|
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import process from 'node:process'
|
|
2
2
|
import { $ } from 'zx'
|
|
3
3
|
|
|
4
|
+
import { logger } from 'src/shared/logger'
|
|
5
|
+
|
|
4
6
|
interface ReleasePR {
|
|
5
7
|
headRefName: string
|
|
6
8
|
number: number
|
|
@@ -25,13 +27,13 @@ export const getReleasePRs = async (): Promise<string[]> => {
|
|
|
25
27
|
const releasePRsArray: ReleasePR[] = JSON.parse(releasePRs.stdout)
|
|
26
28
|
|
|
27
29
|
if (releasePRsArray.length === 0) {
|
|
28
|
-
|
|
30
|
+
logger.error('❌ No release PRs found. Check the project folder for the script. Exiting...')
|
|
29
31
|
process.exit(1)
|
|
30
32
|
}
|
|
31
33
|
|
|
32
34
|
return releasePRsArray.map((pr) => pr.headRefName)
|
|
33
35
|
} catch (error) {
|
|
34
|
-
|
|
36
|
+
logger.error({ error }, '❌ Error fetching release PRs')
|
|
35
37
|
process.exit(1)
|
|
36
38
|
}
|
|
37
39
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { createToolHandler } from './tool-handler'
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { ToolsExecutionResult } from 'src/types'
|
|
2
|
+
|
|
3
|
+
import { logger } from '../logger'
|
|
4
|
+
|
|
5
|
+
interface ToolHandlerArgs {
|
|
6
|
+
toolName: string
|
|
7
|
+
handler: (params: any) => Promise<ToolsExecutionResult>
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const createToolHandler = (args: ToolHandlerArgs) => async (params: unknown) => {
|
|
11
|
+
const { toolName, handler } = args
|
|
12
|
+
|
|
13
|
+
logger.info({ msg: `Tool execution started: ${toolName}`, params })
|
|
14
|
+
try {
|
|
15
|
+
const payload = await handler({ ...(params as object), confirmedCommand: true })
|
|
16
|
+
|
|
17
|
+
logger.info({ msg: `Tool execution successful: ${toolName}` })
|
|
18
|
+
|
|
19
|
+
return payload
|
|
20
|
+
} catch (error) {
|
|
21
|
+
logger.error({
|
|
22
|
+
err: error,
|
|
23
|
+
params,
|
|
24
|
+
msg: `Tool execution failed: ${toolName}`,
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
throw error
|
|
28
|
+
}
|
|
29
|
+
}
|