dodopayments-mcp 2.45.0 → 2.45.1
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 +32 -0
- package/code-tool-paths.cjs +53 -0
- package/code-tool-paths.cjs.map +1 -1
- package/code-tool-paths.d.cts +20 -0
- package/code-tool-paths.d.cts.map +1 -1
- package/code-tool.js +73 -24
- package/code-tool.js.map +1 -1
- package/code-tool.mjs +73 -24
- package/code-tool.mjs.map +1 -1
- package/package.json +2 -2
- package/src/code-tool-paths.cts +59 -0
- package/src/code-tool.ts +77 -22
package/README.md
CHANGED
|
@@ -76,6 +76,38 @@ isolated sandbox. To accomplish this, the server will expose two tools to your a
|
|
|
76
76
|
Using this scheme, agents are capable of performing very complex tasks deterministically
|
|
77
77
|
and repeatably.
|
|
78
78
|
|
|
79
|
+
### Requirements for the code tool
|
|
80
|
+
|
|
81
|
+
The `execute` tool runs your code in a local [Deno](https://deno.land) sandbox, so Deno must be
|
|
82
|
+
available. The server looks for it in this order:
|
|
83
|
+
|
|
84
|
+
1. A `deno` binary on your `PATH`.
|
|
85
|
+
2. A `deno` binary from the [`deno` npm package](https://www.npmjs.com/package/deno), when it is
|
|
86
|
+
installed into the same `node_modules` tree as this package.
|
|
87
|
+
|
|
88
|
+
If neither is found, the `execute` tool returns an error while every other tool, including
|
|
89
|
+
documentation search, keeps working.
|
|
90
|
+
|
|
91
|
+
> [!NOTE]
|
|
92
|
+
> Step 2 does not apply when you launch the server with `npx` or install it globally, because the
|
|
93
|
+
> server then resolves from its own cache directory rather than from your project. Since
|
|
94
|
+
> `npx -y dodopayments-mcp` is the most common way to run it, installing Deno on your `PATH` is the
|
|
95
|
+
> recommended setup.
|
|
96
|
+
|
|
97
|
+
> [!WARNING]
|
|
98
|
+
> Use **Deno 2.8 or earlier** for now. On Deno 2.9+ the sandbox fails to start, because binding the
|
|
99
|
+
> worker's Unix socket began requiring `--allow-net` permission for that socket, which the worker
|
|
100
|
+
> does not grant. Note that `npm install deno` currently installs an affected version. Tracked in
|
|
101
|
+
> [#330](https://github.com/dodopayments/dodopayments-typescript/issues/330).
|
|
102
|
+
|
|
103
|
+
> [!IMPORTANT]
|
|
104
|
+
> Local code execution is supported on **macOS and Linux only**. It does not work on Windows,
|
|
105
|
+
> because the sandbox communicates with the Deno subprocess over a Unix domain socket and Deno
|
|
106
|
+
> cannot listen on one when running on Windows (see
|
|
107
|
+
> [denoland/deno#18236](https://github.com/denoland/deno/issues/18236)). Installing Deno does not
|
|
108
|
+
> change this. On Windows, run the server under WSL2, or call the REST API or the `dodopayments`
|
|
109
|
+
> SDK directly.
|
|
110
|
+
|
|
79
111
|
## Running remotely
|
|
80
112
|
|
|
81
113
|
Launching the client with `--transport=http` launches the server as a remote server using Streamable HTTP transport. The `--port` setting can choose the port it will run on, and the `--socket` setting allows it to run on a Unix socket.
|
package/code-tool-paths.cjs
CHANGED
|
@@ -2,7 +2,60 @@
|
|
|
2
2
|
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
4
|
exports.getWorkerPath = getWorkerPath;
|
|
5
|
+
exports.getBundledDenoPath = getBundledDenoPath;
|
|
5
6
|
function getWorkerPath() {
|
|
6
7
|
return require.resolve('./code-tool-worker.mjs');
|
|
7
8
|
}
|
|
9
|
+
/**
|
|
10
|
+
* Resolves a Deno executable from the optional `deno` npm package, if it is installed.
|
|
11
|
+
*
|
|
12
|
+
* This deliberately uses a bare specifier rather than joining paths by hand: package
|
|
13
|
+
* managers hoist `deno` to a *sibling* of this package (e.g. `<root>/node_modules/deno`,
|
|
14
|
+
* not `<root>/node_modules/dodopayments-mcp/node_modules/deno`), so we need
|
|
15
|
+
* `require.resolve`'s parent `node_modules` walk to find it. `deno` declares no `exports`
|
|
16
|
+
* map, so resolving a deep path into it is legal.
|
|
17
|
+
*
|
|
18
|
+
* Resolution is anchored at this file, so it only sees `deno` when installed into the same
|
|
19
|
+
* `node_modules` tree as this package. Under `npx` or a global install it will not find a
|
|
20
|
+
* `deno` living in the user's own project, which is intentional: resolving from the launch
|
|
21
|
+
* directory would let any directory the server happens to start in supply the executable
|
|
22
|
+
* that gets spawned.
|
|
23
|
+
*
|
|
24
|
+
* `resolveModule` exists so tests can anchor resolution at a fixture tree.
|
|
25
|
+
*
|
|
26
|
+
* Returns `null` when no usable executable is available.
|
|
27
|
+
*/
|
|
28
|
+
function getBundledDenoPath(resolveModule = (specifier) => require.resolve(specifier)) {
|
|
29
|
+
let launcherPath;
|
|
30
|
+
try {
|
|
31
|
+
launcherPath = resolveModule('deno/bin.cjs');
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
const fs = require('node:fs');
|
|
37
|
+
const path = require('node:path');
|
|
38
|
+
// The `deno` package's postinstall hard-links the real binary next to `bin.cjs`.
|
|
39
|
+
// Prefer it: `bin.cjs` is a Node wrapper that runs Deno via a blocking `spawnSync`,
|
|
40
|
+
// so the Deno grandchild would outlive `worker.terminate()`.
|
|
41
|
+
const executablePath = path.join(path.dirname(launcherPath), process.platform === 'win32' ? 'deno.exe' : 'deno');
|
|
42
|
+
if (fs.existsSync(executablePath)) {
|
|
43
|
+
// The executable bit carries no meaning on Windows, so existence is the only signal
|
|
44
|
+
// there. On POSIX an interrupted install can leave the hard-link non-executable; fall
|
|
45
|
+
// through to the launcher rather than failing later with a spawn EACCES.
|
|
46
|
+
if (process.platform === 'win32') {
|
|
47
|
+
return executablePath;
|
|
48
|
+
}
|
|
49
|
+
try {
|
|
50
|
+
fs.accessSync(executablePath, fs.constants.X_OK);
|
|
51
|
+
return executablePath;
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
// Present but not executable.
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
// Fall back to the launcher, which installs the binary on first run. It relies on its
|
|
58
|
+
// shebang, so it is only directly spawnable on non-Windows platforms.
|
|
59
|
+
return process.platform === 'win32' ? null : launcherPath;
|
|
60
|
+
}
|
|
8
61
|
//# sourceMappingURL=code-tool-paths.cjs.map
|
package/code-tool-paths.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"code-tool-paths.cjs","sourceRoot":"","sources":["src/code-tool-paths.cts"],"names":[],"mappings":";AAAA,sFAAsF;;AAEtF,sCAEC;
|
|
1
|
+
{"version":3,"file":"code-tool-paths.cjs","sourceRoot":"","sources":["src/code-tool-paths.cts"],"names":[],"mappings":";AAAA,sFAAsF;;AAEtF,sCAEC;AAqBD,gDAsCC;AA7DD,SAAgB,aAAa;IAC3B,OAAO,OAAO,CAAC,OAAO,CAAC,wBAAwB,CAAC,CAAC;AACnD,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,SAAgB,kBAAkB,CAChC,gBAA+C,CAAC,SAAS,EAAE,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC;IAExF,IAAI,YAAoB,CAAC;IACzB,IAAI,CAAC;QACH,YAAY,GAAG,aAAa,CAAC,cAAc,CAAC,CAAC;IAC/C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,EAAE,GAAG,OAAO,CAAC,SAAS,CAA6B,CAAC;IAC1D,MAAM,IAAI,GAAG,OAAO,CAAC,WAAW,CAA+B,CAAC;IAEhE,iFAAiF;IACjF,oFAAoF;IACpF,6DAA6D;IAC7D,MAAM,cAAc,GAAG,IAAI,CAAC,IAAI,CAC9B,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,EAC1B,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,CACnD,CAAC;IACF,IAAI,EAAE,CAAC,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC;QAClC,oFAAoF;QACpF,sFAAsF;QACtF,yEAAyE;QACzE,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;YACjC,OAAO,cAAc,CAAC;QACxB,CAAC;QACD,IAAI,CAAC;YACH,EAAE,CAAC,UAAU,CAAC,cAAc,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;YACjD,OAAO,cAAc,CAAC;QACxB,CAAC;QAAC,MAAM,CAAC;YACP,8BAA8B;QAChC,CAAC;IACH,CAAC;IAED,sFAAsF;IACtF,sEAAsE;IACtE,OAAO,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC;AAC5D,CAAC"}
|
package/code-tool-paths.d.cts
CHANGED
|
@@ -1,2 +1,22 @@
|
|
|
1
1
|
export declare function getWorkerPath(): string;
|
|
2
|
+
/**
|
|
3
|
+
* Resolves a Deno executable from the optional `deno` npm package, if it is installed.
|
|
4
|
+
*
|
|
5
|
+
* This deliberately uses a bare specifier rather than joining paths by hand: package
|
|
6
|
+
* managers hoist `deno` to a *sibling* of this package (e.g. `<root>/node_modules/deno`,
|
|
7
|
+
* not `<root>/node_modules/dodopayments-mcp/node_modules/deno`), so we need
|
|
8
|
+
* `require.resolve`'s parent `node_modules` walk to find it. `deno` declares no `exports`
|
|
9
|
+
* map, so resolving a deep path into it is legal.
|
|
10
|
+
*
|
|
11
|
+
* Resolution is anchored at this file, so it only sees `deno` when installed into the same
|
|
12
|
+
* `node_modules` tree as this package. Under `npx` or a global install it will not find a
|
|
13
|
+
* `deno` living in the user's own project, which is intentional: resolving from the launch
|
|
14
|
+
* directory would let any directory the server happens to start in supply the executable
|
|
15
|
+
* that gets spawned.
|
|
16
|
+
*
|
|
17
|
+
* `resolveModule` exists so tests can anchor resolution at a fixture tree.
|
|
18
|
+
*
|
|
19
|
+
* Returns `null` when no usable executable is available.
|
|
20
|
+
*/
|
|
21
|
+
export declare function getBundledDenoPath(resolveModule?: (specifier: string) => string): string | null;
|
|
2
22
|
//# sourceMappingURL=code-tool-paths.d.cts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"code-tool-paths.d.cts","sourceRoot":"","sources":["src/code-tool-paths.cts"],"names":[],"mappings":"AAEA,wBAAgB,aAAa,IAAI,MAAM,CAEtC"}
|
|
1
|
+
{"version":3,"file":"code-tool-paths.d.cts","sourceRoot":"","sources":["src/code-tool-paths.cts"],"names":[],"mappings":"AAEA,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,kBAAkB,CAChC,aAAa,GAAE,CAAC,SAAS,EAAE,MAAM,KAAK,MAAkD,GACvF,MAAM,GAAG,IAAI,CAoCf"}
|
package/code-tool.js
CHANGED
|
@@ -121,54 +121,103 @@ function codeTool({ blockedMethods, codeExecutionMode, }) {
|
|
|
121
121
|
};
|
|
122
122
|
return { metadata, tool, handler };
|
|
123
123
|
}
|
|
124
|
+
let denoFoundOnPath = false;
|
|
124
125
|
const localDenoHandler = async ({ reqContext, args, }) => {
|
|
126
|
+
// `@valtown/deno-http-worker` talks to the Deno subprocess exclusively over a Unix
|
|
127
|
+
// domain socket. Deno cannot listen on one when running on Windows: `op_net_listen_unix`
|
|
128
|
+
// is stubbed out as unsupported on non-unix targets, because the underlying
|
|
129
|
+
// `tokio::net::UnixListener` is `#[cfg(unix)]`-gated. Node's side is blocked too, since
|
|
130
|
+
// libuv maps `net.connect({ path })` to named pipes on Windows.
|
|
131
|
+
//
|
|
132
|
+
// So local execution is structurally impossible here, not merely unimplemented. Fail
|
|
133
|
+
// fast with an honest message rather than sending users to install a Deno that could
|
|
134
|
+
// never work. Remove this guard once https://github.com/denoland/deno/issues/18236 lands
|
|
135
|
+
// and the worker gains a Windows transport.
|
|
136
|
+
if (process.platform === 'win32') {
|
|
137
|
+
return (0, types_1.asErrorResult)('Local code execution is not available on Windows.\n\n' +
|
|
138
|
+
'The sandbox runs your code in a Deno subprocess and communicates with it over a ' +
|
|
139
|
+
'Unix domain socket, which Deno cannot listen on when running on Windows ' +
|
|
140
|
+
'(see https://github.com/denoland/deno/issues/18236). Installing Deno will not ' +
|
|
141
|
+
'resolve this.\n\n' +
|
|
142
|
+
'Workarounds:\n' +
|
|
143
|
+
' - Run this MCP server inside WSL2, where local execution works normally.\n' +
|
|
144
|
+
' - Call the Dodo Payments REST API or the `dodopayments` SDK directly.\n\n' +
|
|
145
|
+
'Other tools on this server, such as documentation search, are unaffected.');
|
|
146
|
+
}
|
|
125
147
|
const fs = await Promise.resolve().then(() => __importStar(require('node:fs')));
|
|
126
148
|
const path = await Promise.resolve().then(() => __importStar(require('node:path')));
|
|
127
149
|
const url = await Promise.resolve().then(() => __importStar(require('node:url')));
|
|
128
150
|
const { newDenoHTTPWorker } = await Promise.resolve().then(() => __importStar(require('@valtown/deno-http-worker')));
|
|
129
|
-
const { getWorkerPath } = await Promise.resolve().then(() => __importStar(require('./code-tool-paths.cjs')));
|
|
151
|
+
const { getWorkerPath, getBundledDenoPath } = await Promise.resolve().then(() => __importStar(require('./code-tool-paths.cjs')));
|
|
130
152
|
const workerPath = getWorkerPath();
|
|
131
153
|
const client = reqContext.client;
|
|
132
154
|
const baseURLHostname = new URL(client.baseURL).hostname;
|
|
133
155
|
const { code } = args;
|
|
134
156
|
let denoPath;
|
|
135
|
-
|
|
136
|
-
const
|
|
137
|
-
//
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
157
|
+
// `code-tool-worker.mjs` is emitted at the package root, so this is the package directory.
|
|
158
|
+
const packageDir = path.dirname(workerPath);
|
|
159
|
+
// Deliberately one level above the package. The `--allow-read` grant below depends on
|
|
160
|
+
// this exact value, and it means something different per layout: in a monorepo checkout
|
|
161
|
+
// it is what makes the workspace-linked SDK readable, while in the `.mcpb` bundle it
|
|
162
|
+
// resolves to the parent of the extracted bundle directory. Narrowing it would break the
|
|
163
|
+
// former, so weigh both before changing it.
|
|
164
|
+
const workerParentDir = path.resolve(packageDir, '..');
|
|
165
|
+
// Check if deno is in PATH. `command -v` is a POSIX shell builtin and `execSync` runs
|
|
166
|
+
// under `cmd.exe` on Windows, so probe by spawning the binary directly instead: libuv
|
|
167
|
+
// applies PATHEXT, and a successful run also proves the binary is actually usable.
|
|
168
|
+
//
|
|
169
|
+
// The probe starts Deno and blocks the event loop while it runs, so only a positive
|
|
170
|
+
// result is cached. Caching a negative would force a restart on the most likely recovery
|
|
171
|
+
// path: hitting the error below, installing Deno, and retrying. The import stays above the
|
|
172
|
+
// check so that nothing awaits between reading and writing the cache, which would let
|
|
173
|
+
// concurrent calls each start their own probe.
|
|
174
|
+
const { spawnSync } = await Promise.resolve().then(() => __importStar(require('node:child_process')));
|
|
175
|
+
if (!denoFoundOnPath) {
|
|
176
|
+
const denoProbe = spawnSync('deno', ['--version'], { stdio: 'ignore', windowsHide: true });
|
|
177
|
+
denoFoundOnPath = !denoProbe.error && denoProbe.status === 0;
|
|
178
|
+
}
|
|
179
|
+
if (denoFoundOnPath) {
|
|
141
180
|
denoPath = 'deno';
|
|
142
181
|
}
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
await fs.promises.access(denoNodeModulesPath, fs.constants.X_OK);
|
|
148
|
-
denoPath = denoNodeModulesPath;
|
|
149
|
-
}
|
|
150
|
-
catch {
|
|
182
|
+
else {
|
|
183
|
+
// Use the deno binary from the `deno` npm package if it's installed.
|
|
184
|
+
const bundledDenoPath = getBundledDenoPath();
|
|
185
|
+
if (bundledDenoPath === null) {
|
|
151
186
|
return (0, types_1.asErrorResult)('Deno is required for code execution but was not found. ' +
|
|
152
187
|
'Install it from https://deno.land or run: npm install deno');
|
|
153
188
|
}
|
|
189
|
+
denoPath = bundledDenoPath;
|
|
154
190
|
}
|
|
155
191
|
const allowReadPaths = [
|
|
156
192
|
'code-tool-worker.mjs',
|
|
157
193
|
`${workerPath.replace(/([\/\\]node_modules)[\/\\].+$/, '$1')}/`,
|
|
158
|
-
|
|
194
|
+
workerParentDir,
|
|
159
195
|
];
|
|
160
|
-
// Follow symlinks in node_modules to allow read access to workspace-linked packages
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
196
|
+
// Follow symlinks in node_modules to allow read access to workspace-linked packages.
|
|
197
|
+
// The SDK sits in a different place per layout: nested inside the package for the .mcpb
|
|
198
|
+
// bundle, hoisted alongside it for a normal install, and under the package's own
|
|
199
|
+
// node_modules in a monorepo checkout.
|
|
200
|
+
const sdkPkgName = 'dodopayments';
|
|
201
|
+
for (const sdkDir of [
|
|
202
|
+
path.resolve(packageDir, 'node_modules', sdkPkgName),
|
|
203
|
+
path.resolve(workerParentDir, sdkPkgName),
|
|
204
|
+
path.resolve(workerParentDir, 'node_modules', sdkPkgName),
|
|
205
|
+
]) {
|
|
206
|
+
let realSdkDir;
|
|
207
|
+
try {
|
|
208
|
+
realSdkDir = fs.realpathSync(sdkDir);
|
|
209
|
+
}
|
|
210
|
+
catch {
|
|
211
|
+
continue;
|
|
212
|
+
}
|
|
213
|
+
// A candidate that is a real directory already sits inside a granted path and needs no
|
|
214
|
+
// grant of its own, so keep looking: stopping at it would let it shadow a symlinked
|
|
215
|
+
// candidate further down the list, silently costing the sandbox its SDK access.
|
|
165
216
|
if (realSdkDir !== sdkDir) {
|
|
166
217
|
allowReadPaths.push(realSdkDir);
|
|
218
|
+
break;
|
|
167
219
|
}
|
|
168
220
|
}
|
|
169
|
-
catch {
|
|
170
|
-
// Ignore if symlink resolution fails
|
|
171
|
-
}
|
|
172
221
|
const allowRead = allowReadPaths.join(',');
|
|
173
222
|
const worker = await newDenoHTTPWorker(url.pathToFileURL(workerPath), {
|
|
174
223
|
denoExecutable: denoPath,
|
package/code-tool.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"code-tool.js","sourceRoot":"","sources":["src/code-tool.ts"],"names":[],"mappings":";AAAA,sFAAsF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6CtF,4BAwEC;AAnHD,sCAA4G;AAG5G,wCAAqC;AAKrC,MAAM,MAAM,GAAG;;;;;;;;;;;;;;;;;;;;gGAoBiF,CAAC;AAEjG;;;;;;;;;;;;GAYG;AACH,SAAgB,QAAQ,CAAC,EACvB,cAAc,EACd,iBAAiB,GAIlB;IACC,MAAM,QAAQ,GAAa,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;IAC7E,MAAM,IAAI,GAAS;QACjB,IAAI,EAAE,SAAS;QACf,WAAW,EAAE,MAAM;QACnB,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,IAAI,EAAE;oBACJ,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,kBAAkB;iBAChC;gBACD,MAAM,EAAE;oBACN,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,iEAAiE;iBAC/E;aACF;YACD,QAAQ,EAAE,CAAC,MAAM,CAAC;SACnB;KACF,CAAC;IAEF,MAAM,MAAM,GAAG,IAAA,kBAAS,GAAE,CAAC;IAE3B,MAAM,OAAO,GAAG,KAAK,EAAE,EACrB,UAAU,EACV,IAAI,GAIL,EAA2B,EAAE;QAC5B,MAAM,IAAI,GAAG,IAAI,CAAC,IAAc,CAAC;QACjC,uEAAuE;QACvE,EAAE;QACF,gFAAgF;QAChF,yFAAyF;QACzF,0FAA0F;QAC1F,IAAI,cAAc,EAAE,CAAC;YACnB,MAAM,cAAc,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC,CAAC;YACnG,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC9B,OAAO,IAAA,qBAAa,EAClB,mGAAmG,cAAc;qBAC9G,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,kBAAkB,CAAC;qBAChC,IAAI,CAAC,IAAI,CAAC,EAAE,CAChB,CAAC;YACJ,CAAC;QACH,CAAC;QAED,IAAI,MAAsB,CAAC;QAC3B,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAE7B,MAAM,CAAC,KAAK,CAAC,0CAA0C,CAAC,CAAC;QACzD,MAAM,GAAG,MAAM,gBAAgB,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC;QAEtD,MAAM,CAAC,IAAI,CACT;YACE,iBAAiB;YACjB,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS;YAClC,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,WAAW,EAAE,MAAM,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC;SACzC,EACD,gCAAgC,CACjC,CAAC;QACF,OAAO,MAAM,CAAC;IAChB,CAAC,CAAC;IAEF,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;AACrC,CAAC;AAED,MAAM,gBAAgB,GAAG,KAAK,EAAE,EAC9B,UAAU,EACV,IAAI,GAIL,EAA2B,EAAE;IAC5B,MAAM,EAAE,GAAG,wDAAa,SAAS,GAAC,CAAC;IACnC,MAAM,IAAI,GAAG,wDAAa,WAAW,GAAC,CAAC;IACvC,MAAM,GAAG,GAAG,wDAAa,UAAU,GAAC,CAAC;IACrC,MAAM,EAAE,iBAAiB,EAAE,GAAG,wDAAa,2BAA2B,GAAC,CAAC;IACxE,MAAM,EAAE,aAAa,EAAE,GAAG,wDAAa,uBAAuB,GAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"code-tool.js","sourceRoot":"","sources":["src/code-tool.ts"],"names":[],"mappings":"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"}
|
package/code-tool.mjs
CHANGED
|
@@ -85,54 +85,103 @@ export function codeTool({ blockedMethods, codeExecutionMode, }) {
|
|
|
85
85
|
};
|
|
86
86
|
return { metadata, tool, handler };
|
|
87
87
|
}
|
|
88
|
+
let denoFoundOnPath = false;
|
|
88
89
|
const localDenoHandler = async ({ reqContext, args, }) => {
|
|
90
|
+
// `@valtown/deno-http-worker` talks to the Deno subprocess exclusively over a Unix
|
|
91
|
+
// domain socket. Deno cannot listen on one when running on Windows: `op_net_listen_unix`
|
|
92
|
+
// is stubbed out as unsupported on non-unix targets, because the underlying
|
|
93
|
+
// `tokio::net::UnixListener` is `#[cfg(unix)]`-gated. Node's side is blocked too, since
|
|
94
|
+
// libuv maps `net.connect({ path })` to named pipes on Windows.
|
|
95
|
+
//
|
|
96
|
+
// So local execution is structurally impossible here, not merely unimplemented. Fail
|
|
97
|
+
// fast with an honest message rather than sending users to install a Deno that could
|
|
98
|
+
// never work. Remove this guard once https://github.com/denoland/deno/issues/18236 lands
|
|
99
|
+
// and the worker gains a Windows transport.
|
|
100
|
+
if (process.platform === 'win32') {
|
|
101
|
+
return asErrorResult('Local code execution is not available on Windows.\n\n' +
|
|
102
|
+
'The sandbox runs your code in a Deno subprocess and communicates with it over a ' +
|
|
103
|
+
'Unix domain socket, which Deno cannot listen on when running on Windows ' +
|
|
104
|
+
'(see https://github.com/denoland/deno/issues/18236). Installing Deno will not ' +
|
|
105
|
+
'resolve this.\n\n' +
|
|
106
|
+
'Workarounds:\n' +
|
|
107
|
+
' - Run this MCP server inside WSL2, where local execution works normally.\n' +
|
|
108
|
+
' - Call the Dodo Payments REST API or the `dodopayments` SDK directly.\n\n' +
|
|
109
|
+
'Other tools on this server, such as documentation search, are unaffected.');
|
|
110
|
+
}
|
|
89
111
|
const fs = await import('node:fs');
|
|
90
112
|
const path = await import('node:path');
|
|
91
113
|
const url = await import('node:url');
|
|
92
114
|
const { newDenoHTTPWorker } = await import('@valtown/deno-http-worker');
|
|
93
|
-
const { getWorkerPath } = await import('./code-tool-paths.cjs');
|
|
115
|
+
const { getWorkerPath, getBundledDenoPath } = await import('./code-tool-paths.cjs');
|
|
94
116
|
const workerPath = getWorkerPath();
|
|
95
117
|
const client = reqContext.client;
|
|
96
118
|
const baseURLHostname = new URL(client.baseURL).hostname;
|
|
97
119
|
const { code } = args;
|
|
98
120
|
let denoPath;
|
|
99
|
-
|
|
100
|
-
const
|
|
101
|
-
//
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
121
|
+
// `code-tool-worker.mjs` is emitted at the package root, so this is the package directory.
|
|
122
|
+
const packageDir = path.dirname(workerPath);
|
|
123
|
+
// Deliberately one level above the package. The `--allow-read` grant below depends on
|
|
124
|
+
// this exact value, and it means something different per layout: in a monorepo checkout
|
|
125
|
+
// it is what makes the workspace-linked SDK readable, while in the `.mcpb` bundle it
|
|
126
|
+
// resolves to the parent of the extracted bundle directory. Narrowing it would break the
|
|
127
|
+
// former, so weigh both before changing it.
|
|
128
|
+
const workerParentDir = path.resolve(packageDir, '..');
|
|
129
|
+
// Check if deno is in PATH. `command -v` is a POSIX shell builtin and `execSync` runs
|
|
130
|
+
// under `cmd.exe` on Windows, so probe by spawning the binary directly instead: libuv
|
|
131
|
+
// applies PATHEXT, and a successful run also proves the binary is actually usable.
|
|
132
|
+
//
|
|
133
|
+
// The probe starts Deno and blocks the event loop while it runs, so only a positive
|
|
134
|
+
// result is cached. Caching a negative would force a restart on the most likely recovery
|
|
135
|
+
// path: hitting the error below, installing Deno, and retrying. The import stays above the
|
|
136
|
+
// check so that nothing awaits between reading and writing the cache, which would let
|
|
137
|
+
// concurrent calls each start their own probe.
|
|
138
|
+
const { spawnSync } = await import('node:child_process');
|
|
139
|
+
if (!denoFoundOnPath) {
|
|
140
|
+
const denoProbe = spawnSync('deno', ['--version'], { stdio: 'ignore', windowsHide: true });
|
|
141
|
+
denoFoundOnPath = !denoProbe.error && denoProbe.status === 0;
|
|
142
|
+
}
|
|
143
|
+
if (denoFoundOnPath) {
|
|
105
144
|
denoPath = 'deno';
|
|
106
145
|
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
await fs.promises.access(denoNodeModulesPath, fs.constants.X_OK);
|
|
112
|
-
denoPath = denoNodeModulesPath;
|
|
113
|
-
}
|
|
114
|
-
catch {
|
|
146
|
+
else {
|
|
147
|
+
// Use the deno binary from the `deno` npm package if it's installed.
|
|
148
|
+
const bundledDenoPath = getBundledDenoPath();
|
|
149
|
+
if (bundledDenoPath === null) {
|
|
115
150
|
return asErrorResult('Deno is required for code execution but was not found. ' +
|
|
116
151
|
'Install it from https://deno.land or run: npm install deno');
|
|
117
152
|
}
|
|
153
|
+
denoPath = bundledDenoPath;
|
|
118
154
|
}
|
|
119
155
|
const allowReadPaths = [
|
|
120
156
|
'code-tool-worker.mjs',
|
|
121
157
|
`${workerPath.replace(/([\/\\]node_modules)[\/\\].+$/, '$1')}/`,
|
|
122
|
-
|
|
158
|
+
workerParentDir,
|
|
123
159
|
];
|
|
124
|
-
// Follow symlinks in node_modules to allow read access to workspace-linked packages
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
160
|
+
// Follow symlinks in node_modules to allow read access to workspace-linked packages.
|
|
161
|
+
// The SDK sits in a different place per layout: nested inside the package for the .mcpb
|
|
162
|
+
// bundle, hoisted alongside it for a normal install, and under the package's own
|
|
163
|
+
// node_modules in a monorepo checkout.
|
|
164
|
+
const sdkPkgName = 'dodopayments';
|
|
165
|
+
for (const sdkDir of [
|
|
166
|
+
path.resolve(packageDir, 'node_modules', sdkPkgName),
|
|
167
|
+
path.resolve(workerParentDir, sdkPkgName),
|
|
168
|
+
path.resolve(workerParentDir, 'node_modules', sdkPkgName),
|
|
169
|
+
]) {
|
|
170
|
+
let realSdkDir;
|
|
171
|
+
try {
|
|
172
|
+
realSdkDir = fs.realpathSync(sdkDir);
|
|
173
|
+
}
|
|
174
|
+
catch {
|
|
175
|
+
continue;
|
|
176
|
+
}
|
|
177
|
+
// A candidate that is a real directory already sits inside a granted path and needs no
|
|
178
|
+
// grant of its own, so keep looking: stopping at it would let it shadow a symlinked
|
|
179
|
+
// candidate further down the list, silently costing the sandbox its SDK access.
|
|
129
180
|
if (realSdkDir !== sdkDir) {
|
|
130
181
|
allowReadPaths.push(realSdkDir);
|
|
182
|
+
break;
|
|
131
183
|
}
|
|
132
184
|
}
|
|
133
|
-
catch {
|
|
134
|
-
// Ignore if symlink resolution fails
|
|
135
|
-
}
|
|
136
185
|
const allowRead = allowReadPaths.join(',');
|
|
137
186
|
const worker = await newDenoHTTPWorker(url.pathToFileURL(workerPath), {
|
|
138
187
|
denoExecutable: denoPath,
|
package/code-tool.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"code-tool.mjs","sourceRoot":"","sources":["src/code-tool.ts"],"names":[],"mappings":"AAAA,sFAAsF;AAEtF,OAAO,EAAsE,aAAa,EAAE,oBAAgB;AAG5G,OAAO,EAAE,SAAS,EAAE,qBAAiB;AAKrC,MAAM,MAAM,GAAG;;;;;;;;;;;;;;;;;;;;gGAoBiF,CAAC;AAEjG;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,QAAQ,CAAC,EACvB,cAAc,EACd,iBAAiB,GAIlB;IACC,MAAM,QAAQ,GAAa,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;IAC7E,MAAM,IAAI,GAAS;QACjB,IAAI,EAAE,SAAS;QACf,WAAW,EAAE,MAAM;QACnB,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,IAAI,EAAE;oBACJ,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,kBAAkB;iBAChC;gBACD,MAAM,EAAE;oBACN,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,iEAAiE;iBAC/E;aACF;YACD,QAAQ,EAAE,CAAC,MAAM,CAAC;SACnB;KACF,CAAC;IAEF,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAE3B,MAAM,OAAO,GAAG,KAAK,EAAE,EACrB,UAAU,EACV,IAAI,GAIL,EAA2B,EAAE;QAC5B,MAAM,IAAI,GAAG,IAAI,CAAC,IAAc,CAAC;QACjC,uEAAuE;QACvE,EAAE;QACF,gFAAgF;QAChF,yFAAyF;QACzF,0FAA0F;QAC1F,IAAI,cAAc,EAAE,CAAC;YACnB,MAAM,cAAc,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC,CAAC;YACnG,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC9B,OAAO,aAAa,CAClB,mGAAmG,cAAc;qBAC9G,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,kBAAkB,CAAC;qBAChC,IAAI,CAAC,IAAI,CAAC,EAAE,CAChB,CAAC;YACJ,CAAC;QACH,CAAC;QAED,IAAI,MAAsB,CAAC;QAC3B,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAE7B,MAAM,CAAC,KAAK,CAAC,0CAA0C,CAAC,CAAC;QACzD,MAAM,GAAG,MAAM,gBAAgB,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC;QAEtD,MAAM,CAAC,IAAI,CACT;YACE,iBAAiB;YACjB,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS;YAClC,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,WAAW,EAAE,MAAM,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC;SACzC,EACD,gCAAgC,CACjC,CAAC;QACF,OAAO,MAAM,CAAC;IAChB,CAAC,CAAC;IAEF,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;AACrC,CAAC;AAED,MAAM,gBAAgB,GAAG,KAAK,EAAE,EAC9B,UAAU,EACV,IAAI,GAIL,EAA2B,EAAE;IAC5B,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,CAAC;IACnC,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,CAAC;IACvC,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,CAAC;IACrC,MAAM,EAAE,iBAAiB,EAAE,GAAG,MAAM,MAAM,CAAC,2BAA2B,CAAC,CAAC;IACxE,MAAM,EAAE,aAAa,EAAE,GAAG,MAAM,MAAM,CAAC,uBAAuB,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"code-tool.mjs","sourceRoot":"","sources":["src/code-tool.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dodopayments-mcp",
|
|
3
|
-
"version": "2.45.
|
|
3
|
+
"version": "2.45.1",
|
|
4
4
|
"description": "The official MCP Server for the Dodo Payments API",
|
|
5
5
|
"author": "Dodo Payments <support@dodopayments.com>",
|
|
6
6
|
"types": "./index.d.ts",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"fix": "eslint --fix ."
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"dodopayments": "^2.45.
|
|
30
|
+
"dodopayments": "^2.45.1",
|
|
31
31
|
"ajv": "^8.18.0",
|
|
32
32
|
"@cloudflare/cabidela": "^0.2.4",
|
|
33
33
|
"@hono/node-server": "^1.19.10",
|
package/src/code-tool-paths.cts
CHANGED
|
@@ -3,3 +3,62 @@
|
|
|
3
3
|
export function getWorkerPath(): string {
|
|
4
4
|
return require.resolve('./code-tool-worker.mjs');
|
|
5
5
|
}
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Resolves a Deno executable from the optional `deno` npm package, if it is installed.
|
|
9
|
+
*
|
|
10
|
+
* This deliberately uses a bare specifier rather than joining paths by hand: package
|
|
11
|
+
* managers hoist `deno` to a *sibling* of this package (e.g. `<root>/node_modules/deno`,
|
|
12
|
+
* not `<root>/node_modules/dodopayments-mcp/node_modules/deno`), so we need
|
|
13
|
+
* `require.resolve`'s parent `node_modules` walk to find it. `deno` declares no `exports`
|
|
14
|
+
* map, so resolving a deep path into it is legal.
|
|
15
|
+
*
|
|
16
|
+
* Resolution is anchored at this file, so it only sees `deno` when installed into the same
|
|
17
|
+
* `node_modules` tree as this package. Under `npx` or a global install it will not find a
|
|
18
|
+
* `deno` living in the user's own project, which is intentional: resolving from the launch
|
|
19
|
+
* directory would let any directory the server happens to start in supply the executable
|
|
20
|
+
* that gets spawned.
|
|
21
|
+
*
|
|
22
|
+
* `resolveModule` exists so tests can anchor resolution at a fixture tree.
|
|
23
|
+
*
|
|
24
|
+
* Returns `null` when no usable executable is available.
|
|
25
|
+
*/
|
|
26
|
+
export function getBundledDenoPath(
|
|
27
|
+
resolveModule: (specifier: string) => string = (specifier) => require.resolve(specifier),
|
|
28
|
+
): string | null {
|
|
29
|
+
let launcherPath: string;
|
|
30
|
+
try {
|
|
31
|
+
launcherPath = resolveModule('deno/bin.cjs');
|
|
32
|
+
} catch {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const fs = require('node:fs') as typeof import('node:fs');
|
|
37
|
+
const path = require('node:path') as typeof import('node:path');
|
|
38
|
+
|
|
39
|
+
// The `deno` package's postinstall hard-links the real binary next to `bin.cjs`.
|
|
40
|
+
// Prefer it: `bin.cjs` is a Node wrapper that runs Deno via a blocking `spawnSync`,
|
|
41
|
+
// so the Deno grandchild would outlive `worker.terminate()`.
|
|
42
|
+
const executablePath = path.join(
|
|
43
|
+
path.dirname(launcherPath),
|
|
44
|
+
process.platform === 'win32' ? 'deno.exe' : 'deno',
|
|
45
|
+
);
|
|
46
|
+
if (fs.existsSync(executablePath)) {
|
|
47
|
+
// The executable bit carries no meaning on Windows, so existence is the only signal
|
|
48
|
+
// there. On POSIX an interrupted install can leave the hard-link non-executable; fall
|
|
49
|
+
// through to the launcher rather than failing later with a spawn EACCES.
|
|
50
|
+
if (process.platform === 'win32') {
|
|
51
|
+
return executablePath;
|
|
52
|
+
}
|
|
53
|
+
try {
|
|
54
|
+
fs.accessSync(executablePath, fs.constants.X_OK);
|
|
55
|
+
return executablePath;
|
|
56
|
+
} catch {
|
|
57
|
+
// Present but not executable.
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Fall back to the launcher, which installs the binary on first run. It relies on its
|
|
62
|
+
// shebang, so it is only directly spawnable on non-Windows platforms.
|
|
63
|
+
return process.platform === 'win32' ? null : launcherPath;
|
|
64
|
+
}
|
package/src/code-tool.ts
CHANGED
|
@@ -117,6 +117,8 @@ export function codeTool({
|
|
|
117
117
|
return { metadata, tool, handler };
|
|
118
118
|
}
|
|
119
119
|
|
|
120
|
+
let denoFoundOnPath = false;
|
|
121
|
+
|
|
120
122
|
const localDenoHandler = async ({
|
|
121
123
|
reqContext,
|
|
122
124
|
args,
|
|
@@ -124,11 +126,35 @@ const localDenoHandler = async ({
|
|
|
124
126
|
reqContext: McpRequestContext;
|
|
125
127
|
args: unknown;
|
|
126
128
|
}): Promise<ToolCallResult> => {
|
|
129
|
+
// `@valtown/deno-http-worker` talks to the Deno subprocess exclusively over a Unix
|
|
130
|
+
// domain socket. Deno cannot listen on one when running on Windows: `op_net_listen_unix`
|
|
131
|
+
// is stubbed out as unsupported on non-unix targets, because the underlying
|
|
132
|
+
// `tokio::net::UnixListener` is `#[cfg(unix)]`-gated. Node's side is blocked too, since
|
|
133
|
+
// libuv maps `net.connect({ path })` to named pipes on Windows.
|
|
134
|
+
//
|
|
135
|
+
// So local execution is structurally impossible here, not merely unimplemented. Fail
|
|
136
|
+
// fast with an honest message rather than sending users to install a Deno that could
|
|
137
|
+
// never work. Remove this guard once https://github.com/denoland/deno/issues/18236 lands
|
|
138
|
+
// and the worker gains a Windows transport.
|
|
139
|
+
if (process.platform === 'win32') {
|
|
140
|
+
return asErrorResult(
|
|
141
|
+
'Local code execution is not available on Windows.\n\n' +
|
|
142
|
+
'The sandbox runs your code in a Deno subprocess and communicates with it over a ' +
|
|
143
|
+
'Unix domain socket, which Deno cannot listen on when running on Windows ' +
|
|
144
|
+
'(see https://github.com/denoland/deno/issues/18236). Installing Deno will not ' +
|
|
145
|
+
'resolve this.\n\n' +
|
|
146
|
+
'Workarounds:\n' +
|
|
147
|
+
' - Run this MCP server inside WSL2, where local execution works normally.\n' +
|
|
148
|
+
' - Call the Dodo Payments REST API or the `dodopayments` SDK directly.\n\n' +
|
|
149
|
+
'Other tools on this server, such as documentation search, are unaffected.',
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
|
|
127
153
|
const fs = await import('node:fs');
|
|
128
154
|
const path = await import('node:path');
|
|
129
155
|
const url = await import('node:url');
|
|
130
156
|
const { newDenoHTTPWorker } = await import('@valtown/deno-http-worker');
|
|
131
|
-
const { getWorkerPath } = await import('./code-tool-paths.cjs');
|
|
157
|
+
const { getWorkerPath, getBundledDenoPath } = await import('./code-tool-paths.cjs');
|
|
132
158
|
const workerPath = getWorkerPath();
|
|
133
159
|
|
|
134
160
|
const client = reqContext.client;
|
|
@@ -137,44 +163,73 @@ const localDenoHandler = async ({
|
|
|
137
163
|
|
|
138
164
|
let denoPath: string;
|
|
139
165
|
|
|
140
|
-
|
|
141
|
-
const
|
|
166
|
+
// `code-tool-worker.mjs` is emitted at the package root, so this is the package directory.
|
|
167
|
+
const packageDir = path.dirname(workerPath);
|
|
168
|
+
// Deliberately one level above the package. The `--allow-read` grant below depends on
|
|
169
|
+
// this exact value, and it means something different per layout: in a monorepo checkout
|
|
170
|
+
// it is what makes the workspace-linked SDK readable, while in the `.mcpb` bundle it
|
|
171
|
+
// resolves to the parent of the extracted bundle directory. Narrowing it would break the
|
|
172
|
+
// former, so weigh both before changing it.
|
|
173
|
+
const workerParentDir = path.resolve(packageDir, '..');
|
|
142
174
|
|
|
143
|
-
// Check if deno is in PATH
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
175
|
+
// Check if deno is in PATH. `command -v` is a POSIX shell builtin and `execSync` runs
|
|
176
|
+
// under `cmd.exe` on Windows, so probe by spawning the binary directly instead: libuv
|
|
177
|
+
// applies PATHEXT, and a successful run also proves the binary is actually usable.
|
|
178
|
+
//
|
|
179
|
+
// The probe starts Deno and blocks the event loop while it runs, so only a positive
|
|
180
|
+
// result is cached. Caching a negative would force a restart on the most likely recovery
|
|
181
|
+
// path: hitting the error below, installing Deno, and retrying. The import stays above the
|
|
182
|
+
// check so that nothing awaits between reading and writing the cache, which would let
|
|
183
|
+
// concurrent calls each start their own probe.
|
|
184
|
+
const { spawnSync } = await import('node:child_process');
|
|
185
|
+
if (!denoFoundOnPath) {
|
|
186
|
+
const denoProbe = spawnSync('deno', ['--version'], { stdio: 'ignore', windowsHide: true });
|
|
187
|
+
denoFoundOnPath = !denoProbe.error && denoProbe.status === 0;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
if (denoFoundOnPath) {
|
|
147
191
|
denoPath = 'deno';
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
await fs.promises.access(denoNodeModulesPath, fs.constants.X_OK);
|
|
153
|
-
denoPath = denoNodeModulesPath;
|
|
154
|
-
} catch {
|
|
192
|
+
} else {
|
|
193
|
+
// Use the deno binary from the `deno` npm package if it's installed.
|
|
194
|
+
const bundledDenoPath = getBundledDenoPath();
|
|
195
|
+
if (bundledDenoPath === null) {
|
|
155
196
|
return asErrorResult(
|
|
156
197
|
'Deno is required for code execution but was not found. ' +
|
|
157
198
|
'Install it from https://deno.land or run: npm install deno',
|
|
158
199
|
);
|
|
159
200
|
}
|
|
201
|
+
denoPath = bundledDenoPath;
|
|
160
202
|
}
|
|
161
203
|
|
|
162
204
|
const allowReadPaths = [
|
|
163
205
|
'code-tool-worker.mjs',
|
|
164
206
|
`${workerPath.replace(/([\/\\]node_modules)[\/\\].+$/, '$1')}/`,
|
|
165
|
-
|
|
207
|
+
workerParentDir,
|
|
166
208
|
];
|
|
167
209
|
|
|
168
|
-
// Follow symlinks in node_modules to allow read access to workspace-linked packages
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
210
|
+
// Follow symlinks in node_modules to allow read access to workspace-linked packages.
|
|
211
|
+
// The SDK sits in a different place per layout: nested inside the package for the .mcpb
|
|
212
|
+
// bundle, hoisted alongside it for a normal install, and under the package's own
|
|
213
|
+
// node_modules in a monorepo checkout.
|
|
214
|
+
const sdkPkgName = 'dodopayments';
|
|
215
|
+
for (const sdkDir of [
|
|
216
|
+
path.resolve(packageDir, 'node_modules', sdkPkgName),
|
|
217
|
+
path.resolve(workerParentDir, sdkPkgName),
|
|
218
|
+
path.resolve(workerParentDir, 'node_modules', sdkPkgName),
|
|
219
|
+
]) {
|
|
220
|
+
let realSdkDir: string;
|
|
221
|
+
try {
|
|
222
|
+
realSdkDir = fs.realpathSync(sdkDir);
|
|
223
|
+
} catch {
|
|
224
|
+
continue;
|
|
225
|
+
}
|
|
226
|
+
// A candidate that is a real directory already sits inside a granted path and needs no
|
|
227
|
+
// grant of its own, so keep looking: stopping at it would let it shadow a symlinked
|
|
228
|
+
// candidate further down the list, silently costing the sandbox its SDK access.
|
|
173
229
|
if (realSdkDir !== sdkDir) {
|
|
174
230
|
allowReadPaths.push(realSdkDir);
|
|
231
|
+
break;
|
|
175
232
|
}
|
|
176
|
-
} catch {
|
|
177
|
-
// Ignore if symlink resolution fails
|
|
178
233
|
}
|
|
179
234
|
|
|
180
235
|
const allowRead = allowReadPaths.join(',');
|