MCPcopy Create free account
hub / github.com/tiann/hapi / constructor

Method constructor

cli/src/api/apiMachine.ts:80–209  ·  view source on GitHub ↗
(
        private readonly token: string,
        private readonly machine: Machine,
        private readonly workspaceRoots?: string[]
    )

Source from the content-addressed store, hash-verified

78 private readonly normalizedWorkspaceRoots: string[] | undefined
79
80 constructor(
81 private readonly token: string,
82 private readonly machine: Machine,
83 private readonly workspaceRoots?: string[]
84 ) {
85 // Realpath roots once so all subsequent comparisons are against
86 // canonical, symlink-resolved locations. Falls back to lexical
87 // resolution if realpath fails so we still get protection.
88 this.normalizedWorkspaceRoots = normalizeWorkspaceRoots(workspaceRoots)
89
90 this.rpcHandlerManager = new RpcHandlerManager({
91 scopePrefix: this.machine.id,
92 logger: (msg, data) => logger.debug(msg, data)
93 })
94
95 registerCommonHandlers(this.rpcHandlerManager, getInvokedCwd())
96
97 this.rpcHandlerManager.registerHandler<PathExistsRequest, PathExistsResponse>(RPC_METHODS.PathExists, async (params) => {
98 const rawPaths = Array.isArray(params?.paths) ? params.paths : []
99 const uniquePaths = Array.from(new Set(rawPaths.filter((path): path is string => typeof path === 'string')))
100 const exists: Record<string, boolean> = {}
101
102 await Promise.all(uniquePaths.map(async (path) => {
103 const trimmed = path.trim()
104 if (!trimmed) return
105 try {
106 const stats = await stat(trimmed)
107 exists[trimmed] = stats.isDirectory()
108 } catch {
109 exists[trimmed] = false
110 }
111 }))
112
113 return { exists }
114 })
115
116 this.rpcHandlerManager.registerHandler<ListMachineDirectoryRequest, MachineListDirectoryResponse>(RPC_METHODS.ListMachineDirectory, async (params) => {
117 if (!this.normalizedWorkspaceRoots?.length) {
118 return { success: false, error: 'Workspace browsing is not enabled for this machine' }
119 }
120
121 const rawPath = typeof params?.path === 'string' ? params.path.trim() : ''
122 if (!rawPath) {
123 return { success: false, error: 'Path is required' }
124 }
125
126 const targetPath = await this.resolveForWorkspaceCheck(rawPath)
127 if (!this.isWithinWorkspaceRoots(targetPath)) {
128 return { success: false, error: 'Path is outside workspace roots' }
129 }
130
131 try {
132 const dirStat = await stat(targetPath)
133 if (!dirStat.isDirectory()) {
134 return { success: false, error: 'Path is not a directory' }
135 }
136
137 const dirEntries = await readdir(targetPath, { withFileTypes: true })

Callers

nothing calls this directly

Calls 9

registerCommonHandlersFunction · 0.90
getInvokedCwdFunction · 0.90
listOpencodeModelsForCwdFunction · 0.90
normalizeWorkspaceRootsFunction · 0.85
debugMethod · 0.80
registerHandlerMethod · 0.45
pushMethod · 0.45

Tested by

no test coverage detected