driggsby 0.1.12 → 0.1.13

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.
Files changed (46) hide show
  1. package/.gitignore +2 -0
  2. package/README.md +16 -11
  3. package/binary-install.js +212 -0
  4. package/binary.js +128 -0
  5. package/install.js +4 -0
  6. package/npm-shrinkwrap.json +545 -0
  7. package/package.json +53 -41
  8. package/run-driggsby.js +4 -0
  9. package/dist/auth/browser.js +0 -31
  10. package/dist/auth/config.js +0 -23
  11. package/dist/auth/discovery.js +0 -42
  12. package/dist/auth/dpop.js +0 -44
  13. package/dist/auth/login.js +0 -126
  14. package/dist/auth/loopback.js +0 -157
  15. package/dist/auth/oauth.js +0 -136
  16. package/dist/auth/pkce.js +0 -12
  17. package/dist/auth/url-security.js +0 -16
  18. package/dist/broker/authentication.js +0 -49
  19. package/dist/broker/client.js +0 -148
  20. package/dist/broker/daemon.js +0 -65
  21. package/dist/broker/file-secret-store.js +0 -130
  22. package/dist/broker/installation.js +0 -154
  23. package/dist/broker/ipc.js +0 -12
  24. package/dist/broker/keyring-secret-store.js +0 -42
  25. package/dist/broker/launch.js +0 -35
  26. package/dist/broker/lock.js +0 -84
  27. package/dist/broker/remote-mcp.js +0 -129
  28. package/dist/broker/remote-session.js +0 -173
  29. package/dist/broker/resolve-secret-store.js +0 -52
  30. package/dist/broker/secret-store.js +0 -13
  31. package/dist/broker/server.js +0 -177
  32. package/dist/broker/session.js +0 -31
  33. package/dist/broker/test-support.js +0 -258
  34. package/dist/broker/types.js +0 -1
  35. package/dist/cli/commands/broker-daemon.js +0 -4
  36. package/dist/cli/commands/login.js +0 -35
  37. package/dist/cli/commands/logout.js +0 -20
  38. package/dist/cli/commands/status.js +0 -13
  39. package/dist/cli/format.js +0 -84
  40. package/dist/index.js +0 -39
  41. package/dist/lib/json-file.js +0 -36
  42. package/dist/lib/retry.js +0 -22
  43. package/dist/lib/runtime-paths.js +0 -62
  44. package/dist/lib/user-guidance.js +0 -19
  45. package/dist/shim/server.js +0 -143
  46. package/dist/shim/stdio-transport.js +0 -106
package/.gitignore ADDED
@@ -0,0 +1,2 @@
1
+ /node_modules
2
+
package/README.md CHANGED
@@ -8,15 +8,21 @@
8
8
  - a local MCP server for tools like Codex and Claude Code
9
9
  - access to supported Driggsby tools from your AI client
10
10
 
11
+ ## Run
12
+
13
+ ```bash
14
+ npx driggsby@latest login
15
+ ```
16
+
11
17
  ## Install
12
18
 
13
19
  ```bash
14
20
  npm install -g driggsby
15
21
  ```
16
22
 
17
- Node `20+` is required.
18
-
19
- If you prefer not to install globally, you can also use `npx -y driggsby ...`.
23
+ If you prefer not to install globally, use `npx driggsby@latest` for
24
+ human-invoked commands like `login`, `status`, and `logout`, and use
25
+ `npx -y driggsby@latest mcp-server` for non-interactive MCP launcher flows.
20
26
 
21
27
  On machines without working platform keyring support, such as some headless
22
28
  Linux servers, Driggsby falls back to an owner-only local file-backed secret
@@ -27,29 +33,28 @@ store so the CLI can still complete login and run the broker.
27
33
  1. Sign in:
28
34
 
29
35
  ```bash
30
- driggsby login
36
+ npx driggsby@latest login
31
37
  ```
32
38
 
33
39
  2. Add Driggsby as an MCP server in your client:
34
40
 
35
41
  ```bash
36
- codex mcp add driggsby -- driggsby mcp-server
42
+ codex mcp add driggsby -- npx -y driggsby@latest mcp-server
37
43
  ```
38
44
 
39
45
  3. Check broker status any time:
40
46
 
41
47
  ```bash
42
- driggsby status
48
+ npx driggsby@latest status
43
49
  ```
44
50
 
45
51
  ## Commands
46
52
 
47
53
  ```bash
48
- driggsby login
49
- driggsby status
50
- driggsby mcp-server
51
- driggsby logout
52
- driggsby broker-daemon
54
+ npx driggsby@latest login
55
+ npx driggsby@latest status
56
+ npx -y driggsby@latest mcp-server
57
+ npx driggsby@latest logout
53
58
  ```
54
59
 
55
60
  ## License
@@ -0,0 +1,212 @@
1
+ const { createWriteStream, existsSync, mkdirSync, mkdtemp } = require("fs");
2
+ const { join, sep } = require("path");
3
+ const { spawnSync } = require("child_process");
4
+ const { tmpdir } = require("os");
5
+
6
+ const axios = require("axios");
7
+ const rimraf = require("rimraf");
8
+ const tmpDir = tmpdir();
9
+
10
+ const error = (msg) => {
11
+ console.error(msg);
12
+ process.exit(1);
13
+ };
14
+
15
+ class Package {
16
+ constructor(platform, name, url, filename, zipExt, binaries) {
17
+ let errors = [];
18
+ if (typeof url !== "string") {
19
+ errors.push("url must be a string");
20
+ } else {
21
+ try {
22
+ new URL(url);
23
+ } catch (e) {
24
+ errors.push(e);
25
+ }
26
+ }
27
+ if (name && typeof name !== "string") {
28
+ errors.push("package name must be a string");
29
+ }
30
+ if (!name) {
31
+ errors.push("You must specify the name of your package");
32
+ }
33
+ if (binaries && typeof binaries !== "object") {
34
+ errors.push("binaries must be a string => string map");
35
+ }
36
+ if (!binaries) {
37
+ errors.push("You must specify the binaries in the package");
38
+ }
39
+
40
+ if (errors.length > 0) {
41
+ let errorMsg =
42
+ "One or more of the parameters you passed to the Binary constructor are invalid:\n";
43
+ errors.forEach((error) => {
44
+ errorMsg += error;
45
+ });
46
+ errorMsg +=
47
+ '\n\nCorrect usage: new Package("my-binary", "https://example.com/binary/download.tar.gz", {"my-binary": "my-binary"})';
48
+ error(errorMsg);
49
+ }
50
+
51
+ this.platform = platform;
52
+ this.url = url;
53
+ this.name = name;
54
+ this.filename = filename;
55
+ this.zipExt = zipExt;
56
+ this.installDirectory = join(__dirname, "node_modules", ".bin_real");
57
+ this.binaries = binaries;
58
+
59
+ if (!existsSync(this.installDirectory)) {
60
+ mkdirSync(this.installDirectory, { recursive: true });
61
+ }
62
+ }
63
+
64
+ exists() {
65
+ for (const binaryName in this.binaries) {
66
+ const binRelPath = this.binaries[binaryName];
67
+ const binPath = join(this.installDirectory, binRelPath);
68
+ if (!existsSync(binPath)) {
69
+ return false;
70
+ }
71
+ }
72
+ return true;
73
+ }
74
+
75
+ install(fetchOptions, suppressLogs = false) {
76
+ if (this.exists()) {
77
+ if (!suppressLogs) {
78
+ console.error(
79
+ `${this.name} is already installed, skipping installation.`,
80
+ );
81
+ }
82
+ return Promise.resolve();
83
+ }
84
+
85
+ if (existsSync(this.installDirectory)) {
86
+ rimraf.sync(this.installDirectory);
87
+ }
88
+
89
+ mkdirSync(this.installDirectory, { recursive: true });
90
+
91
+ if (!suppressLogs) {
92
+ console.error(`Downloading release from ${this.url}`);
93
+ }
94
+
95
+ return axios({ ...fetchOptions, url: this.url, responseType: "stream" })
96
+ .then((res) => {
97
+ return new Promise((resolve, reject) => {
98
+ mkdtemp(`${tmpDir}${sep}`, (err, directory) => {
99
+ let tempFile = join(directory, this.filename);
100
+ const sink = res.data.pipe(createWriteStream(tempFile));
101
+ sink.on("error", (err) => reject(err));
102
+ sink.on("close", () => {
103
+ if (/\.tar\.*/.test(this.zipExt)) {
104
+ const result = spawnSync("tar", [
105
+ "xf",
106
+ tempFile,
107
+ // The tarballs are stored with a leading directory
108
+ // component; we strip one component in the
109
+ // shell installers too.
110
+ "--strip-components",
111
+ "1",
112
+ "-C",
113
+ this.installDirectory,
114
+ ]);
115
+ if (result.status == 0) {
116
+ resolve();
117
+ } else if (result.error) {
118
+ reject(result.error);
119
+ } else {
120
+ reject(
121
+ new Error(
122
+ `An error occurred untarring the artifact: stdout: ${result.stdout}; stderr: ${result.stderr}`,
123
+ ),
124
+ );
125
+ }
126
+ } else if (this.zipExt == ".zip") {
127
+ let result;
128
+ if (this.platform.artifactName.includes("windows")) {
129
+ // Windows does not have "unzip" by default on many installations, instead
130
+ // we use Expand-Archive from powershell
131
+ result = spawnSync("powershell.exe", [
132
+ "-NoProfile",
133
+ "-NonInteractive",
134
+ "-Command",
135
+ `& {
136
+ param([string]$LiteralPath, [string]$DestinationPath)
137
+ Expand-Archive -LiteralPath $LiteralPath -DestinationPath $DestinationPath -Force
138
+ }`,
139
+ tempFile,
140
+ this.installDirectory,
141
+ ]);
142
+ } else {
143
+ result = spawnSync("unzip", [
144
+ "-q",
145
+ tempFile,
146
+ "-d",
147
+ this.installDirectory,
148
+ ]);
149
+ }
150
+
151
+ if (result.status == 0) {
152
+ resolve();
153
+ } else if (result.error) {
154
+ reject(result.error);
155
+ } else {
156
+ reject(
157
+ new Error(
158
+ `An error occurred unzipping the artifact: stdout: ${result.stdout}; stderr: ${result.stderr}`,
159
+ ),
160
+ );
161
+ }
162
+ } else {
163
+ reject(
164
+ new Error(`Unrecognized file extension: ${this.zipExt}`),
165
+ );
166
+ }
167
+ });
168
+ });
169
+ });
170
+ })
171
+ .then(() => {
172
+ if (!suppressLogs) {
173
+ console.error(`${this.name} has been installed!`);
174
+ }
175
+ })
176
+ .catch((e) => {
177
+ error(`Error fetching release: ${e.message}`);
178
+ });
179
+ }
180
+
181
+ run(binaryName, fetchOptions) {
182
+ const promise = !this.exists()
183
+ ? this.install(fetchOptions, true)
184
+ : Promise.resolve();
185
+
186
+ promise
187
+ .then(() => {
188
+ const [, , ...args] = process.argv;
189
+
190
+ const options = { cwd: process.cwd(), stdio: "inherit" };
191
+
192
+ const binRelPath = this.binaries[binaryName];
193
+ if (!binRelPath) {
194
+ error(`${binaryName} is not a known binary in ${this.name}`);
195
+ }
196
+ const binPath = join(this.installDirectory, binRelPath);
197
+ const result = spawnSync(binPath, args, options);
198
+
199
+ if (result.error) {
200
+ error(result.error);
201
+ }
202
+
203
+ process.exit(result.status);
204
+ })
205
+ .catch((e) => {
206
+ error(e.message);
207
+ process.exit(1);
208
+ });
209
+ }
210
+ }
211
+
212
+ module.exports.Package = Package;
package/binary.js ADDED
@@ -0,0 +1,128 @@
1
+ const { Package } = require("./binary-install");
2
+ const os = require("os");
3
+ const cTable = require("console.table");
4
+ const libc = require("detect-libc");
5
+ const { configureProxy } = require("axios-proxy-builder");
6
+
7
+ const error = (msg) => {
8
+ console.error(msg);
9
+ process.exit(1);
10
+ };
11
+
12
+ const {
13
+ name,
14
+ artifactDownloadUrls,
15
+ supportedPlatforms,
16
+ glibcMinimum,
17
+ } = require("./package.json");
18
+
19
+ // FIXME: implement NPM installer handling of fallback download URLs
20
+ const artifactDownloadUrl = artifactDownloadUrls[0];
21
+ const builderGlibcMajorVersion = glibcMinimum.major;
22
+ const builderGlibcMinorVersion = glibcMinimum.series;
23
+
24
+ const getPlatform = () => {
25
+ const rawOsType = os.type();
26
+ const rawArchitecture = os.arch();
27
+
28
+ // We want to use rust-style target triples as the canonical key
29
+ // for a platform, so translate the "os" library's concepts into rust ones
30
+ let osType = "";
31
+ switch (rawOsType) {
32
+ case "Windows_NT":
33
+ osType = "pc-windows-msvc";
34
+ break;
35
+ case "Darwin":
36
+ osType = "apple-darwin";
37
+ break;
38
+ case "Linux":
39
+ osType = "unknown-linux-gnu";
40
+ break;
41
+ }
42
+
43
+ let arch = "";
44
+ switch (rawArchitecture) {
45
+ case "x64":
46
+ arch = "x86_64";
47
+ break;
48
+ case "arm64":
49
+ arch = "aarch64";
50
+ break;
51
+ }
52
+
53
+ if (rawOsType === "Linux") {
54
+ if (libc.familySync() == "musl") {
55
+ osType = "unknown-linux-musl-dynamic";
56
+ } else if (libc.isNonGlibcLinuxSync()) {
57
+ console.warn(
58
+ "Your libc is neither glibc nor musl; trying static musl binary instead",
59
+ );
60
+ osType = "unknown-linux-musl-static";
61
+ } else {
62
+ let libcVersion = libc.versionSync();
63
+ let splitLibcVersion = libcVersion.split(".");
64
+ let libcMajorVersion = splitLibcVersion[0];
65
+ let libcMinorVersion = splitLibcVersion[1];
66
+ if (
67
+ libcMajorVersion != builderGlibcMajorVersion ||
68
+ libcMinorVersion < builderGlibcMinorVersion
69
+ ) {
70
+ // We can't run the glibc binaries, but we can run the static musl ones
71
+ // if they exist
72
+ console.warn(
73
+ "Your glibc isn't compatible; trying static musl binary instead",
74
+ );
75
+ osType = "unknown-linux-musl-static";
76
+ }
77
+ }
78
+ }
79
+
80
+ // Assume the above succeeded and build a target triple to look things up with.
81
+ // If any of it failed, this lookup will fail and we'll handle it like normal.
82
+ let targetTriple = `${arch}-${osType}`;
83
+ let platform = supportedPlatforms[targetTriple];
84
+
85
+ if (!platform) {
86
+ error(
87
+ `Platform with type "${rawOsType}" and architecture "${rawArchitecture}" is not supported by ${name}.\nYour system must be one of the following:\n\n${Object.keys(
88
+ supportedPlatforms,
89
+ ).join(",")}`,
90
+ );
91
+ }
92
+
93
+ return platform;
94
+ };
95
+
96
+ const getPackage = () => {
97
+ const platform = getPlatform();
98
+ const url = `${artifactDownloadUrl}/${platform.artifactName}`;
99
+ let filename = platform.artifactName;
100
+ let ext = platform.zipExt;
101
+ let binary = new Package(platform, name, url, filename, ext, platform.bins);
102
+
103
+ return binary;
104
+ };
105
+
106
+ const install = (suppressLogs) => {
107
+ if (!artifactDownloadUrl || artifactDownloadUrl.length === 0) {
108
+ console.warn("in demo mode, not installing binaries");
109
+ return;
110
+ }
111
+ const package = getPackage();
112
+ const proxy = configureProxy(package.url);
113
+
114
+ return package.install(proxy, suppressLogs);
115
+ };
116
+
117
+ const run = (binaryName) => {
118
+ const package = getPackage();
119
+ const proxy = configureProxy(package.url);
120
+
121
+ package.run(binaryName, proxy);
122
+ };
123
+
124
+ module.exports = {
125
+ install,
126
+ run,
127
+ getPackage,
128
+ };
package/install.js ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+
3
+ const { install } = require("./binary");
4
+ install(false);