MCPcopy Create free account
hub / github.com/UsefulSoftwareCo/executor / resolveToolInvocation

Function resolveToolInvocation

apps/cli/src/tooling.ts:149–206  ·  view source on GitHub ↗
(input: {
  rawPathParts: ReadonlyArray<string>;
})

Source from the content-addressed store, hash-verified

147 });
148
149export const resolveToolInvocation = (input: {
150 rawPathParts: ReadonlyArray<string>;
151}): Effect.Effect<{ path: string; args: Record<string, unknown> }, Error, FileSystem.FileSystem> =>
152 Effect.gen(function* () {
153 if (!Array.isArray(input.rawPathParts)) {
154 return yield* Effect.fail(
155 new Error("Invalid tool invocation: path parts were not parsed as an array"),
156 );
157 }
158
159 // The trailing argument carries the tool's JSON input — either inline
160 // (`'{"k":"v"}'`) or, via `@path`, read from a file. The file form is the
161 // cross-platform equivalent of the Unix `"$(cat file)"`: it dodges shell
162 // quote-mangling for large or double-quote-heavy payloads (notably
163 // PowerShell, which corrupts inline JSON passed to a native binary).
164 const rawLast = input.rawPathParts.at(-1)?.trim();
165 const isFileArg = rawLast !== undefined && rawLast.startsWith("@");
166 const filePath = isFileArg ? rawLast.slice(1) : undefined;
167 if (isFileArg && filePath === "") {
168 return yield* Effect.fail(
169 new Error("Tool input '@' requires a file path, e.g. `@./input.json`."),
170 );
171 }
172 const jsonText =
173 filePath !== undefined
174 ? (yield* (yield* FileSystem.FileSystem).readFileString(filePath).pipe(
175 // Surface a path-bearing message instead of a raw ENOENT PlatformError.
176 Effect.mapError(
177 (cause) => new Error(`Cannot read tool input file '${filePath}': ${cause}`),
178 ),
179 )).trim()
180 : rawLast;
181 const hasInlineJsonArg = jsonText !== undefined && jsonText.startsWith("{");
182 if (isFileArg && !hasInlineJsonArg) {
183 return yield* Effect.fail(
184 new Error(`Tool input file '${filePath}' must contain a JSON object starting with '{'.`),
185 );
186 }
187 const pathParts =
188 isFileArg || hasInlineJsonArg ? input.rawPathParts.slice(0, -1) : input.rawPathParts;
189 const args = hasInlineJsonArg ? yield* parseJsonObjectInput(jsonText) : {};
190
191 if (pathParts.some((part) => part.trim().startsWith("-"))) {
192 return yield* Effect.fail(
193 new Error(
194 "Tool invocation no longer accepts flags. Use: executor call <path...> '{...json...}'",
195 ),
196 );
197 }
198
199 const path = yield* Effect.try({
200 try: () => buildToolPath(pathParts),
201 catch: (cause) =>
202 cause instanceof Error ? cause : new Error(`Invalid tool path: ${String(cause)}`),
203 });
204
205 return { path, args };
206 });

Callers 2

tooling.test.tsFile · 0.90
main.tsFile · 0.90

Calls 2

parseJsonObjectInputFunction · 0.85
buildToolPathFunction · 0.85

Tested by

no test coverage detected