@tryglen/cli 0.5.2 → 0.6.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 +3 -3
- package/dist/_utils/agents-table.d.ts +10 -0
- package/dist/_utils/agents-table.js +26 -0
- package/dist/_utils/agents-table.js.map +1 -0
- package/dist/_utils/cli-error.d.ts +11 -0
- package/dist/_utils/cli-error.js +24 -0
- package/dist/_utils/cli-error.js.map +1 -0
- package/dist/_utils/codex-app-server.js +4 -1
- package/dist/_utils/codex-app-server.js.map +1 -1
- package/dist/_utils/config.js +3 -1
- package/dist/_utils/config.js.map +1 -1
- package/dist/_utils/credentials.d.ts +1 -1
- package/dist/_utils/credentials.js +8 -3
- package/dist/_utils/credentials.js.map +1 -1
- package/dist/_utils/ensure-global-cli.d.ts +7 -5
- package/dist/_utils/ensure-global-cli.js +47 -17
- package/dist/_utils/ensure-global-cli.js.map +1 -1
- package/dist/_utils/find-bin.d.ts +6 -0
- package/dist/_utils/find-bin.js +85 -0
- package/dist/_utils/find-bin.js.map +1 -0
- package/dist/_utils/http.d.ts +10 -3
- package/dist/_utils/http.js +56 -5
- package/dist/_utils/http.js.map +1 -1
- package/dist/_utils/loopback-server.d.ts +1 -1
- package/dist/_utils/loopback-server.js +17 -2
- package/dist/_utils/loopback-server.js.map +1 -1
- package/dist/_utils/open-browser.js +3 -0
- package/dist/_utils/open-browser.js.map +1 -1
- package/dist/_utils/plugin-status.d.ts +4 -0
- package/dist/_utils/plugin-status.js +23 -0
- package/dist/_utils/plugin-status.js.map +1 -0
- package/dist/_utils/run-bin.d.ts +13 -0
- package/dist/_utils/run-bin.js +51 -0
- package/dist/_utils/run-bin.js.map +1 -0
- package/dist/_utils/state-line.js +3 -1
- package/dist/_utils/state-line.js.map +1 -1
- package/dist/_utils/state.d.ts +1 -1
- package/dist/_utils/state.js +8 -2
- package/dist/_utils/state.js.map +1 -1
- package/dist/_utils/update.d.ts +20 -2
- package/dist/_utils/update.js +111 -15
- package/dist/_utils/update.js.map +1 -1
- package/dist/_utils/version.js +12 -1
- package/dist/_utils/version.js.map +1 -1
- package/dist/_utils/which.d.ts +3 -2
- package/dist/_utils/which.js +5 -12
- package/dist/_utils/which.js.map +1 -1
- package/dist/bin.js +44 -22
- package/dist/bin.js.map +1 -1
- package/dist/commands/doctor.d.ts +6 -3
- package/dist/commands/doctor.js +68 -54
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/incognito.d.ts +2 -1
- package/dist/commands/incognito.js +16 -4
- package/dist/commands/incognito.js.map +1 -1
- package/dist/commands/ingest.d.ts +1 -5
- package/dist/commands/ingest.js +47 -16
- package/dist/commands/ingest.js.map +1 -1
- package/dist/commands/install.d.ts +5 -1
- package/dist/commands/install.js +114 -62
- package/dist/commands/install.js.map +1 -1
- package/dist/commands/login.d.ts +2 -1
- package/dist/commands/login.js +41 -10
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/logout.d.ts +2 -1
- package/dist/commands/logout.js +20 -5
- package/dist/commands/logout.js.map +1 -1
- package/dist/commands/onboard.d.ts +2 -1
- package/dist/commands/onboard.js +7 -3
- package/dist/commands/onboard.js.map +1 -1
- package/dist/commands/org.d.ts +3 -2
- package/dist/commands/org.js +40 -9
- package/dist/commands/org.js.map +1 -1
- package/dist/commands/search.d.ts +2 -4
- package/dist/commands/search.js +25 -16
- package/dist/commands/search.js.map +1 -1
- package/dist/commands/session-start.d.ts +6 -3
- package/dist/commands/session-start.js +16 -6
- package/dist/commands/session-start.js.map +1 -1
- package/dist/commands/status.d.ts +2 -1
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/statusline.d.ts +7 -5
- package/dist/commands/statusline.js +18 -8
- package/dist/commands/statusline.js.map +1 -1
- package/dist/commands/uninstall.d.ts +2 -1
- package/dist/commands/uninstall.js +8 -3
- package/dist/commands/uninstall.js.map +1 -1
- package/dist/commands/update.d.ts +10 -3
- package/dist/commands/update.js +111 -12
- package/dist/commands/update.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -21,9 +21,9 @@ glen login
|
|
|
21
21
|
| `glen org list` | List your organizations; active one is marked with `✓`. |
|
|
22
22
|
| `glen org switch [slug]` | Switch the active organization for this machine (interactive picker without `slug`). |
|
|
23
23
|
| `glen ingest [--agent <name>]` | Ingest a turn from stdin — used by agent hooks (`claude-code` or `codex`). |
|
|
24
|
-
| `glen install` |
|
|
25
|
-
| `glen update` | Update the glen CLI
|
|
26
|
-
| `glen doctor [--auto]` |
|
|
24
|
+
| `glen install [--agent <claude\|codex>]` | Set up or update glen for detected coding agents (plugin + hooks); idempotent, so re-running repairs a broken setup. `--claude-path <path>` / `--codex-path <path>` point at a binary when auto-detection fails. |
|
|
25
|
+
| `glen update` | Update the glen CLI **and** any installed glen plugins, and re-verify the Codex hook registration. Never installs a plugin that isn't already installed — that's `glen install`'s job. |
|
|
26
|
+
| `glen doctor [--auto]` | Print machine-readable `status:` lines (CLI version/latest/channel, login + org, per-agent plugin + hook state) plus `→` remedy lines — the glen-setup skill branches on them. `--auto` runs background updates silently (used by hooks). |
|
|
27
27
|
| `glen statusline` | Output a single status line for the agent's UI status bar — used by hooks. |
|
|
28
28
|
| `glen session-start [--agent <name>]` | Output hook JSON for the agent's `SessionStart` event — used by hooks. |
|
|
29
29
|
| `glen version` | Print the CLI version. |
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
type Agent = {
|
|
2
|
+
readonly name: string;
|
|
3
|
+
readonly bin: "claude" | "codex";
|
|
4
|
+
readonly steps: readonly (readonly string[])[];
|
|
5
|
+
readonly updateSteps: readonly (readonly string[])[];
|
|
6
|
+
readonly postInstall: "claude" | "codex";
|
|
7
|
+
};
|
|
8
|
+
declare const AGENTS: readonly Agent[];
|
|
9
|
+
export { AGENTS };
|
|
10
|
+
export type { Agent };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
const AGENTS = [
|
|
2
|
+
{
|
|
3
|
+
name: "Claude Code",
|
|
4
|
+
bin: "claude",
|
|
5
|
+
steps: [
|
|
6
|
+
["plugin", "marketplace", "add", "Glen-Web-App/glen-claude-code-plugin"],
|
|
7
|
+
["plugin", "install", "glen@glen"],
|
|
8
|
+
],
|
|
9
|
+
updateSteps: [["plugin", "update", "glen@glen"]],
|
|
10
|
+
postInstall: "claude",
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
name: "Codex",
|
|
14
|
+
bin: "codex",
|
|
15
|
+
steps: [
|
|
16
|
+
["plugin", "marketplace", "add", "Glen-Web-App/glen-codex-plugin"],
|
|
17
|
+
// codex requires the <plugin>@<marketplace> form (or --marketplace);
|
|
18
|
+
// a bare "glen" fails with "plugin requires --marketplace".
|
|
19
|
+
["plugin", "add", "glen@glen"],
|
|
20
|
+
],
|
|
21
|
+
updateSteps: [["plugin", "marketplace", "upgrade", "glen"]],
|
|
22
|
+
postInstall: "codex",
|
|
23
|
+
},
|
|
24
|
+
];
|
|
25
|
+
export { AGENTS };
|
|
26
|
+
//# sourceMappingURL=agents-table.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agents-table.js","sourceRoot":"","sources":["../../src/_utils/agents-table.ts"],"names":[],"mappings":"AAcA,MAAM,MAAM,GAAqB;IAC/B;QACE,IAAI,EAAE,aAAa;QACnB,GAAG,EAAE,QAAQ;QACb,KAAK,EAAE;YACL,CAAC,QAAQ,EAAE,aAAa,EAAE,KAAK,EAAE,sCAAsC,CAAC;YACxE,CAAC,QAAQ,EAAE,SAAS,EAAE,WAAW,CAAC;SACnC;QACD,WAAW,EAAE,CAAC,CAAC,QAAQ,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC;QAChD,WAAW,EAAE,QAAQ;KACtB;IACD;QACE,IAAI,EAAE,OAAO;QACb,GAAG,EAAE,OAAO;QACZ,KAAK,EAAE;YACL,CAAC,QAAQ,EAAE,aAAa,EAAE,KAAK,EAAE,gCAAgC,CAAC;YAClE,qEAAqE;YACrE,4DAA4D;YAC5D,CAAC,QAAQ,EAAE,KAAK,EAAE,WAAW,CAAC;SAC/B;QACD,WAAW,EAAE,CAAC,CAAC,QAAQ,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;QAC3D,WAAW,EAAE,OAAO;KACrB;CACF,CAAC;AAEF,OAAO,EAAE,MAAM,EAAE,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
type CliError = {
|
|
2
|
+
readonly what: string;
|
|
3
|
+
readonly why?: string;
|
|
4
|
+
readonly path?: string;
|
|
5
|
+
readonly remedy: string;
|
|
6
|
+
};
|
|
7
|
+
declare const cliErr: (e: CliError) => CliError;
|
|
8
|
+
declare const causeOf: (e: unknown) => string;
|
|
9
|
+
declare const formatCliError: (e: CliError) => string;
|
|
10
|
+
export { cliErr, causeOf, formatCliError };
|
|
11
|
+
export type { CliError };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// Identity constructor — exists so call sites read as cliErr({...}) and the
|
|
2
|
+
// contract scan can distinguish structured errors from raw strings.
|
|
3
|
+
const cliErr = (e) => e;
|
|
4
|
+
// Best-effort root-cause string from an unknown caught value.
|
|
5
|
+
const causeOf = (e) => {
|
|
6
|
+
if (typeof e === "string" && e.length > 0)
|
|
7
|
+
return e;
|
|
8
|
+
if (e instanceof Error) {
|
|
9
|
+
const code = e.code;
|
|
10
|
+
return code ? `${code}: ${e.message}` : e.message;
|
|
11
|
+
}
|
|
12
|
+
return "unknown error";
|
|
13
|
+
};
|
|
14
|
+
const formatCliError = (e) => {
|
|
15
|
+
const lines = [`✗ ${e.what}`];
|
|
16
|
+
if (e.why)
|
|
17
|
+
lines.push(` cause: ${e.why}`);
|
|
18
|
+
if (e.path)
|
|
19
|
+
lines.push(` path: ${e.path}`);
|
|
20
|
+
lines.push(` → ${e.remedy}`);
|
|
21
|
+
return `${lines.join("\n")}\n`;
|
|
22
|
+
};
|
|
23
|
+
export { cliErr, causeOf, formatCliError };
|
|
24
|
+
//# sourceMappingURL=cli-error.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-error.js","sourceRoot":"","sources":["../../src/_utils/cli-error.ts"],"names":[],"mappings":"AAYA,4EAA4E;AAC5E,oEAAoE;AACpE,MAAM,MAAM,GAAG,CAAC,CAAW,EAAY,EAAE,CAAC,CAAC,CAAC;AAE5C,8DAA8D;AAC9D,MAAM,OAAO,GAAG,CAAC,CAAU,EAAU,EAAE;IACrC,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,CAAC,CAAC;IACpD,IAAI,CAAC,YAAY,KAAK,EAAE,CAAC;QACvB,MAAM,IAAI,GAAI,CAA2B,CAAC,IAAI,CAAC;QAC/C,OAAO,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;IACpD,CAAC;IACD,OAAO,eAAe,CAAC;AACzB,CAAC,CAAC;AAEF,MAAM,cAAc,GAAG,CAAC,CAAW,EAAU,EAAE;IAC7C,MAAM,KAAK,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IAC9B,IAAI,CAAC,CAAC,GAAG;QAAE,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;IAC3C,IAAI,CAAC,CAAC,IAAI;QAAE,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IAC7C,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;IAC9B,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;AACjC,CAAC,CAAC;AAEF,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { spawn } from "node:child_process";
|
|
2
|
+
import { findBin } from "./find-bin.js";
|
|
2
3
|
import { err, ok } from "./result.js";
|
|
3
4
|
import { cliVersion } from "./version.js";
|
|
4
5
|
const TIMEOUT_MS = 15_000;
|
|
@@ -30,7 +31,9 @@ const extractEntries = (msg) => {
|
|
|
30
31
|
};
|
|
31
32
|
const rpc = (id, method, params) => `${JSON.stringify({ jsonrpc: "2.0", id, method, params })}\n`;
|
|
32
33
|
const listCodexHooks = (cwd) => new Promise((resolve) => {
|
|
33
|
-
|
|
34
|
+
// Resolve via findBin so users whose codex lives off this process's PATH
|
|
35
|
+
// (well-known dirs, login-shell PATH, --codex-path override) still work.
|
|
36
|
+
const child = spawn(findBin("codex") ?? "codex", ["app-server"], {
|
|
34
37
|
stdio: ["pipe", "pipe", "ignore"],
|
|
35
38
|
});
|
|
36
39
|
const finish = (r) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codex-app-server.js","sourceRoot":"","sources":["../../src/_utils/codex-app-server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAe,GAAG,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAe1C,MAAM,UAAU,GAAG,MAAM,CAAC;AAE1B,MAAM,cAAc,GAAG,CAAC,GAAY,EAA2B,EAAE;IAC/D,MAAM,MAAM,GAAI,GAAuC,CAAC,MAAM,CAAC;IAC/D,IAAI,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACxD,MAAM,OAAO,GAAqB,EAAE,CAAC;IACrC,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,IAA6B,EAAE,CAAC;QACxD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC;YAAE,SAAS;QACzC,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,KAAkC,EAAE,CAAC;YACxD,IACE,OAAO,CAAC,CAAC,GAAG,KAAK,QAAQ;gBACzB,OAAO,CAAC,CAAC,OAAO,KAAK,QAAQ;gBAC7B,OAAO,CAAC,CAAC,MAAM,KAAK,QAAQ;gBAC5B,OAAO,CAAC,CAAC,WAAW,KAAK,QAAQ;gBACjC,OAAO,CAAC,CAAC,WAAW,KAAK,QAAQ,EACjC,CAAC;gBACD,OAAO,CAAC,IAAI,CAAC;oBACX,GAAG,EAAE,CAAC,CAAC,GAAG;oBACV,OAAO,EAAE,CAAC,CAAC,OAAO;oBAClB,MAAM,EAAE,CAAC,CAAC,MAAM;oBAChB,WAAW,EAAE,CAAC,CAAC,WAAW;oBAC1B,WAAW,EAAE,CAAC,CAAC,WAAW;iBAC3B,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC,CAAC;AAEF,MAAM,GAAG,GAAG,CAAC,EAAU,EAAE,MAAc,EAAE,MAAe,EAAU,EAAE,CAClE,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,IAAI,CAAC;AAEhE,MAAM,cAAc,GAAG,CACrB,GAAW,EACgC,EAAE,CAC7C,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;IACtB,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,EAAE,CAAC,YAAY,CAAC,EAAE;
|
|
1
|
+
{"version":3,"file":"codex-app-server.js","sourceRoot":"","sources":["../../src/_utils/codex-app-server.ts"],"names":[],"mappings":"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"}
|
package/dist/_utils/config.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
// Strip trailing slashes so a GLEN_BASE_URL like "https://x.test/" doesn't
|
|
2
|
+
// produce double-slash endpoint URLs ("https://x.test//api/…").
|
|
3
|
+
const baseUrl = (process.env.GLEN_BASE_URL ?? "https://app.tryglen.com").replace(/\/+$/, "");
|
|
2
4
|
const config = {
|
|
3
5
|
baseUrl,
|
|
4
6
|
connectUrl: `${baseUrl}/connect/cli`,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/_utils/config.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/_utils/config.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,gEAAgE;AAChE,MAAM,OAAO,GAAG,CACd,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,yBAAyB,CACvD,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AAEtB,MAAM,MAAM,GAAG;IACb,OAAO;IACP,UAAU,EAAE,GAAG,OAAO,cAAc;IACpC,WAAW,EAAE,GAAG,OAAO,2BAA2B;IAClD,OAAO,EAAE,GAAG,OAAO,qBAAqB;IACxC,SAAS,EAAE,GAAG,OAAO,uBAAuB;IAC5C,WAAW,EAAE,GAAG,OAAO,yBAAyB;IAChD,eAAe,EAAE,IAAI;IACrB,eAAe,EAAE,MAAM;IACvB,iBAAiB,EAAE,MAAM;CAC1B,CAAC;AAEF,OAAO,EAAE,MAAM,EAAE,CAAC"}
|
|
@@ -6,7 +6,7 @@ type Credentials = {
|
|
|
6
6
|
declare const credentialsPath: () => string;
|
|
7
7
|
declare const readCredentials: () => Promise<Credentials | null>;
|
|
8
8
|
declare const writeCredentials: (creds: Credentials) => Promise<Result<void, unknown>>;
|
|
9
|
-
declare const clearCredentials: () => Promise<void
|
|
9
|
+
declare const clearCredentials: () => Promise<Result<void, unknown>>;
|
|
10
10
|
declare const resolveAuthHeader: () => Promise<{
|
|
11
11
|
headerName: "x-api-key";
|
|
12
12
|
headerValue: string;
|
|
@@ -33,7 +33,8 @@ const writeCredentials = async (creds) => {
|
|
|
33
33
|
const mkdirResult = await fromPromise(mkdir(dir, { recursive: true, mode: 0o700 }));
|
|
34
34
|
if (!mkdirResult.ok)
|
|
35
35
|
return mkdirResult;
|
|
36
|
-
|
|
36
|
+
// pid-suffixed so concurrent writers never clobber each other's tmp file.
|
|
37
|
+
const tmpPath = `${filePath}.${process.pid}.tmp`;
|
|
37
38
|
const json = JSON.stringify(creds, null, 2);
|
|
38
39
|
const writeResult = await fromPromise(writeFile(tmpPath, json, { mode: 0o600 }));
|
|
39
40
|
if (!writeResult.ok)
|
|
@@ -46,9 +47,13 @@ const writeCredentials = async (creds) => {
|
|
|
46
47
|
return renameResult;
|
|
47
48
|
return { ok: true, value: undefined };
|
|
48
49
|
};
|
|
50
|
+
// ENOENT counts as success (nothing to clear); any other failure is returned
|
|
51
|
+
// so the caller can tell the user the file is still on disk.
|
|
49
52
|
const clearCredentials = async () => {
|
|
50
|
-
const
|
|
51
|
-
|
|
53
|
+
const r = await fromPromise(unlink(credentialsPath()));
|
|
54
|
+
if (!r.ok && r.error.code !== "ENOENT")
|
|
55
|
+
return r;
|
|
56
|
+
return { ok: true, value: undefined };
|
|
52
57
|
};
|
|
53
58
|
const resolveAuthHeader = async () => {
|
|
54
59
|
const creds = await readCredentials();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"credentials.js","sourceRoot":"","sources":["../../src/_utils/credentials.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,EACL,KAAK,EACL,QAAQ,EACR,MAAM,EACN,MAAM,EACN,SAAS,GACV,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAK1C,MAAM,eAAe,GAAG,GAAW,EAAE;IACnC,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC;IAClD,IAAI,OAAO;QAAE,OAAO,OAAO,CAAC;IAC5B,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,kBAAkB,CAAC,CAAC;AACtD,CAAC,CAAC;AAEF,MAAM,eAAe,GAAG,KAAK,IAAiC,EAAE;IAC9D,MAAM,QAAQ,GAAG,eAAe,EAAE,CAAC;IACnC,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;IAC9D,IAAI,CAAC,MAAM,CAAC,EAAE;QAAE,OAAO,IAAI,CAAC;IAC5B,MAAM,MAAM,GAAG,MAAM,WAAW,CAC9B,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAY,CAAC,CACrD,CAAC;IACF,IAAI,CAAC,MAAM,CAAC,EAAE;QAAE,OAAO,IAAI,CAAC;IAC5B,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC;IAC1B,IACE,OAAO,IAAI,KAAK,QAAQ;QACxB,IAAI,KAAK,IAAI;QACb,MAAM,IAAI,IAAI;QACd,KAAK,IAAI,IAAI;QACZ,IAA0B,CAAC,IAAI,KAAK,QAAQ;QAC7C,OAAQ,IAAyB,CAAC,GAAG,KAAK,QAAQ,EAClD,CAAC;QACD,OAAO,IAAmB,CAAC;IAC7B,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC,CAAC;AAEF,MAAM,gBAAgB,GAAG,KAAK,EAC5B,KAAkB,EACc,EAAE;IAClC,MAAM,QAAQ,GAAG,eAAe,EAAE,CAAC;IACnC,MAAM,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IAE9B,MAAM,WAAW,GAAG,MAAM,WAAW,CACnC,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAC7C,CAAC;IACF,IAAI,CAAC,WAAW,CAAC,EAAE;QAAE,OAAO,WAAW,CAAC;IAExC,MAAM,OAAO,GAAG,GAAG,QAAQ,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"credentials.js","sourceRoot":"","sources":["../../src/_utils/credentials.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,EACL,KAAK,EACL,QAAQ,EACR,MAAM,EACN,MAAM,EACN,SAAS,GACV,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAK1C,MAAM,eAAe,GAAG,GAAW,EAAE;IACnC,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC;IAClD,IAAI,OAAO;QAAE,OAAO,OAAO,CAAC;IAC5B,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,kBAAkB,CAAC,CAAC;AACtD,CAAC,CAAC;AAEF,MAAM,eAAe,GAAG,KAAK,IAAiC,EAAE;IAC9D,MAAM,QAAQ,GAAG,eAAe,EAAE,CAAC;IACnC,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;IAC9D,IAAI,CAAC,MAAM,CAAC,EAAE;QAAE,OAAO,IAAI,CAAC;IAC5B,MAAM,MAAM,GAAG,MAAM,WAAW,CAC9B,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAY,CAAC,CACrD,CAAC;IACF,IAAI,CAAC,MAAM,CAAC,EAAE;QAAE,OAAO,IAAI,CAAC;IAC5B,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC;IAC1B,IACE,OAAO,IAAI,KAAK,QAAQ;QACxB,IAAI,KAAK,IAAI;QACb,MAAM,IAAI,IAAI;QACd,KAAK,IAAI,IAAI;QACZ,IAA0B,CAAC,IAAI,KAAK,QAAQ;QAC7C,OAAQ,IAAyB,CAAC,GAAG,KAAK,QAAQ,EAClD,CAAC;QACD,OAAO,IAAmB,CAAC;IAC7B,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC,CAAC;AAEF,MAAM,gBAAgB,GAAG,KAAK,EAC5B,KAAkB,EACc,EAAE;IAClC,MAAM,QAAQ,GAAG,eAAe,EAAE,CAAC;IACnC,MAAM,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IAE9B,MAAM,WAAW,GAAG,MAAM,WAAW,CACnC,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAC7C,CAAC;IACF,IAAI,CAAC,WAAW,CAAC,EAAE;QAAE,OAAO,WAAW,CAAC;IAExC,0EAA0E;IAC1E,MAAM,OAAO,GAAG,GAAG,QAAQ,IAAI,OAAO,CAAC,GAAG,MAAM,CAAC;IACjD,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAE5C,MAAM,WAAW,GAAG,MAAM,WAAW,CACnC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAC1C,CAAC;IACF,IAAI,CAAC,WAAW,CAAC,EAAE;QAAE,OAAO,WAAW,CAAC;IAExC,MAAM,WAAW,GAAG,MAAM,WAAW,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC;IAC7D,IAAI,CAAC,WAAW,CAAC,EAAE;QAAE,OAAO,WAAW,CAAC;IAExC,MAAM,YAAY,GAAG,MAAM,WAAW,CAAC,MAAM,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC;IAClE,IAAI,CAAC,YAAY,CAAC,EAAE;QAAE,OAAO,YAAY,CAAC;IAE1C,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;AACxC,CAAC,CAAC;AAEF,6EAA6E;AAC7E,6DAA6D;AAC7D,MAAM,gBAAgB,GAAG,KAAK,IAAoC,EAAE;IAClE,MAAM,CAAC,GAAG,MAAM,WAAW,CAAC,MAAM,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC;IACvD,IAAI,CAAC,CAAC,CAAC,EAAE,IAAK,CAAC,CAAC,KAA+B,CAAC,IAAI,KAAK,QAAQ;QAAE,OAAO,CAAC,CAAC;IAC5E,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;AACxC,CAAC,CAAC;AAEF,MAAM,iBAAiB,GAAG,KAAK,IAGrB,EAAE;IACV,MAAM,KAAK,GAAG,MAAM,eAAe,EAAE,CAAC;IACtC,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IACxB,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,WAAW,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC;AAC7D,CAAC,CAAC;AAEF,OAAO,EACL,eAAe,EACf,eAAe,EACf,gBAAgB,EAChB,gBAAgB,EAChB,iBAAiB,GAClB,CAAC"}
|
|
@@ -15,11 +15,13 @@ type Outcome = {
|
|
|
15
15
|
readonly hadExisting: boolean;
|
|
16
16
|
};
|
|
17
17
|
/**
|
|
18
|
-
* Make sure a current `glen` binary is reachable on PATH,
|
|
19
|
-
* updating it globally via npm when it isn't. `npx
|
|
20
|
-
* runs this CLI from npx's cache without ever
|
|
21
|
-
* without this step the plugins' hooks would have
|
|
22
|
-
* silently do nothing.
|
|
18
|
+
* Make sure a current, PERSISTENT `glen` binary is reachable on PATH,
|
|
19
|
+
* installing or updating it globally via npm when it isn't. `npx
|
|
20
|
+
* @tryglen/cli install` runs this CLI from npx's transient cache without ever
|
|
21
|
+
* linking a global binary — without this step the plugins' hooks would have
|
|
22
|
+
* no `glen` to call and silently do nothing. We deliberately ignore npx's own
|
|
23
|
+
* ephemeral shim (see persistentGlenPath) so a fresh machine always gets a
|
|
24
|
+
* real global install.
|
|
23
25
|
*
|
|
24
26
|
* `onInstallStart(hadExisting)` fires just before the (slow) npm install so
|
|
25
27
|
* the caller can print a progress line first.
|
|
@@ -3,10 +3,33 @@ import { join } from "node:path";
|
|
|
3
3
|
import { newer } from "./update.js";
|
|
4
4
|
import { cliVersion } from "./version.js";
|
|
5
5
|
import { isInstalled } from "./which.js";
|
|
6
|
-
/**
|
|
7
|
-
|
|
6
|
+
/**
|
|
7
|
+
* Path to a PERSISTENT global `glen` on PATH, or null when the only matches
|
|
8
|
+
* are npx's transient shims. `npx @tryglen/cli install` runs this CLI from
|
|
9
|
+
* `~/.npm/_npx/<hash>/…/glen`, which is on PATH *only* while npx is running —
|
|
10
|
+
* it vanishes on exit, leaving the agents' hooks (which call bare `glen`)
|
|
11
|
+
* with nothing to run. A naive `which glen` reports that doomed shim, so we
|
|
12
|
+
* list every PATH match with `which -a` and ignore the ephemeral npx ones.
|
|
13
|
+
*/
|
|
14
|
+
const persistentGlenPath = () => {
|
|
15
|
+
try {
|
|
16
|
+
const out = execFileSync("which", ["-a", "glen"], {
|
|
17
|
+
encoding: "utf8",
|
|
18
|
+
timeout: 10_000,
|
|
19
|
+
});
|
|
20
|
+
return (out
|
|
21
|
+
.split("\n")
|
|
22
|
+
.map((line) => line.trim())
|
|
23
|
+
.find((line) => line.length > 0 && !line.includes("/_npx/")) ?? null);
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
/** Version reported by the `glen` at `glenPath`, or null when unreadable. */
|
|
30
|
+
const versionAt = (glenPath) => {
|
|
8
31
|
try {
|
|
9
|
-
const out = execFileSync(
|
|
32
|
+
const out = execFileSync(glenPath, ["--version"], {
|
|
10
33
|
encoding: "utf8",
|
|
11
34
|
timeout: 10_000,
|
|
12
35
|
});
|
|
@@ -46,19 +69,21 @@ const installGlobally = () => {
|
|
|
46
69
|
}
|
|
47
70
|
};
|
|
48
71
|
/**
|
|
49
|
-
* Make sure a current `glen` binary is reachable on PATH,
|
|
50
|
-
* updating it globally via npm when it isn't. `npx
|
|
51
|
-
* runs this CLI from npx's cache without ever
|
|
52
|
-
* without this step the plugins' hooks would have
|
|
53
|
-
* silently do nothing.
|
|
72
|
+
* Make sure a current, PERSISTENT `glen` binary is reachable on PATH,
|
|
73
|
+
* installing or updating it globally via npm when it isn't. `npx
|
|
74
|
+
* @tryglen/cli install` runs this CLI from npx's transient cache without ever
|
|
75
|
+
* linking a global binary — without this step the plugins' hooks would have
|
|
76
|
+
* no `glen` to call and silently do nothing. We deliberately ignore npx's own
|
|
77
|
+
* ephemeral shim (see persistentGlenPath) so a fresh machine always gets a
|
|
78
|
+
* real global install.
|
|
54
79
|
*
|
|
55
80
|
* `onInstallStart(hadExisting)` fires just before the (slow) npm install so
|
|
56
81
|
* the caller can print a progress line first.
|
|
57
82
|
*/
|
|
58
83
|
const ensureGlobalCli = (onInstallStart) => {
|
|
59
|
-
const
|
|
60
|
-
if (
|
|
61
|
-
const version =
|
|
84
|
+
const existing = persistentGlenPath();
|
|
85
|
+
if (existing) {
|
|
86
|
+
const version = versionAt(existing);
|
|
62
87
|
// Up to date (or ahead, e.g. a dev build) — nothing to do. A stale or
|
|
63
88
|
// unreadable version falls through to a reinstall.
|
|
64
89
|
if (version && !newer(cliVersion, version))
|
|
@@ -66,17 +91,22 @@ const ensureGlobalCli = (onInstallStart) => {
|
|
|
66
91
|
}
|
|
67
92
|
if (!isInstalled("npm"))
|
|
68
93
|
return { status: "no-npm" };
|
|
69
|
-
onInstallStart?.(
|
|
94
|
+
onInstallStart?.(existing !== null);
|
|
70
95
|
const result = installGlobally();
|
|
71
96
|
if (!result.ok) {
|
|
72
|
-
return {
|
|
97
|
+
return {
|
|
98
|
+
status: "failed",
|
|
99
|
+
permission: result.permission,
|
|
100
|
+
hadExisting: existing !== null,
|
|
101
|
+
};
|
|
73
102
|
}
|
|
74
|
-
if (
|
|
103
|
+
if (existing)
|
|
75
104
|
return { status: "updated" };
|
|
76
|
-
|
|
105
|
+
// Re-probe: npm linked the binary; is a persistent (non-npx) glen now on PATH?
|
|
106
|
+
if (persistentGlenPath() !== null)
|
|
77
107
|
return { status: "installed" };
|
|
78
|
-
// npm succeeded but `glen` still doesn't resolve: the global
|
|
79
|
-
// not on PATH (common with version managers / fresh Homebrew node).
|
|
108
|
+
// npm succeeded but `glen` still doesn't resolve persistently: the global
|
|
109
|
+
// bin dir is not on PATH (common with version managers / fresh Homebrew node).
|
|
80
110
|
return { status: "path-missing", binDir: npmGlobalBinDir() };
|
|
81
111
|
};
|
|
82
112
|
export { ensureGlobalCli };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ensure-global-cli.js","sourceRoot":"","sources":["../../src/_utils/ensure-global-cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAiBzC,6EAA6E;AAC7E,MAAM,
|
|
1
|
+
{"version":3,"file":"ensure-global-cli.js","sourceRoot":"","sources":["../../src/_utils/ensure-global-cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type Result } from "./result.js";
|
|
2
|
+
declare const agentsJsonPath: () => string;
|
|
3
|
+
declare const isExecutable: (p: string) => boolean;
|
|
4
|
+
declare const findBin: (bin: string) => string | null;
|
|
5
|
+
declare const persistAgentPath: (bin: string, path: string) => Promise<Result<void, unknown>>;
|
|
6
|
+
export { findBin, persistAgentPath, agentsJsonPath, isExecutable };
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { constants, accessSync, readFileSync } from "node:fs";
|
|
2
|
+
import { mkdir, rename, writeFile } from "node:fs/promises";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { dirname, join } from "node:path";
|
|
5
|
+
import { fromPromise } from "./result.js";
|
|
6
|
+
import { runBin } from "./run-bin.js";
|
|
7
|
+
const agentsJsonPath = () => process.env.GLEN_AGENTS_PATH ?? join(homedir(), ".glen", "agents.json");
|
|
8
|
+
const isExecutable = (p) => {
|
|
9
|
+
try {
|
|
10
|
+
accessSync(p, constants.X_OK);
|
|
11
|
+
return true;
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
const readOverrides = () => {
|
|
18
|
+
try {
|
|
19
|
+
const parsed = JSON.parse(readFileSync(agentsJsonPath(), "utf8"));
|
|
20
|
+
if (typeof parsed !== "object" || parsed === null)
|
|
21
|
+
return {};
|
|
22
|
+
if (Array.isArray(parsed))
|
|
23
|
+
return {};
|
|
24
|
+
return Object.fromEntries(Object.entries(parsed).filter((e) => typeof e[1] === "string"));
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return {};
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
const WELL_KNOWN_DIRS = [
|
|
31
|
+
"/opt/homebrew/bin",
|
|
32
|
+
"/usr/local/bin",
|
|
33
|
+
join(homedir(), ".local", "bin"),
|
|
34
|
+
join(homedir(), "bin"),
|
|
35
|
+
];
|
|
36
|
+
// Resolves an agent binary: persisted override → which → well-known macOS
|
|
37
|
+
// dirs → login-shell PATH probe. Returns null when nothing works — the
|
|
38
|
+
// caller owns the actionable "run `which codex` then
|
|
39
|
+
// `glen install --codex-path <path>`" message.
|
|
40
|
+
const findBin = (bin) => {
|
|
41
|
+
// Only simple binary names — guards the shell-interpolated login probe and dir joins.
|
|
42
|
+
if (!/^[A-Za-z0-9._-]+$/.test(bin))
|
|
43
|
+
return null;
|
|
44
|
+
const override = readOverrides()[bin];
|
|
45
|
+
if (override && isExecutable(override))
|
|
46
|
+
return override;
|
|
47
|
+
const viaWhich = runBin("which", [bin], { timeoutMs: 3000 });
|
|
48
|
+
if (viaWhich.ok) {
|
|
49
|
+
const p = viaWhich.value.stdout.trim();
|
|
50
|
+
if (p)
|
|
51
|
+
return p;
|
|
52
|
+
}
|
|
53
|
+
const dirs = process.env.GLEN_EXTRA_BIN_DIR
|
|
54
|
+
? [process.env.GLEN_EXTRA_BIN_DIR, ...WELL_KNOWN_DIRS]
|
|
55
|
+
: WELL_KNOWN_DIRS;
|
|
56
|
+
for (const dir of dirs) {
|
|
57
|
+
const p = join(dir, bin);
|
|
58
|
+
if (isExecutable(p))
|
|
59
|
+
return p;
|
|
60
|
+
}
|
|
61
|
+
const shell = process.env.SHELL ?? "/bin/zsh";
|
|
62
|
+
const viaLogin = runBin(shell, ["-lc", `command -v ${bin}`], {
|
|
63
|
+
timeoutMs: 4000,
|
|
64
|
+
});
|
|
65
|
+
if (viaLogin.ok) {
|
|
66
|
+
const p = viaLogin.value.stdout.trim().split("\n").pop() ?? "";
|
|
67
|
+
if (p.startsWith("/") && isExecutable(p))
|
|
68
|
+
return p;
|
|
69
|
+
}
|
|
70
|
+
return null;
|
|
71
|
+
};
|
|
72
|
+
const persistAgentPath = async (bin, path) => {
|
|
73
|
+
const file = agentsJsonPath();
|
|
74
|
+
const next = { ...readOverrides(), [bin]: path };
|
|
75
|
+
const mk = await fromPromise(mkdir(dirname(file), { recursive: true }));
|
|
76
|
+
if (!mk.ok)
|
|
77
|
+
return mk;
|
|
78
|
+
const tmp = `${file}.${process.pid}.tmp`;
|
|
79
|
+
const w = await fromPromise(writeFile(tmp, JSON.stringify(next, null, 2)));
|
|
80
|
+
if (!w.ok)
|
|
81
|
+
return w;
|
|
82
|
+
return fromPromise(rename(tmp, file));
|
|
83
|
+
};
|
|
84
|
+
export { findBin, persistAgentPath, agentsJsonPath, isExecutable };
|
|
85
|
+
//# sourceMappingURL=find-bin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"find-bin.js","sourceRoot":"","sources":["../../src/_utils/find-bin.ts"],"names":[],"mappings":"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"}
|
package/dist/_utils/http.d.ts
CHANGED
|
@@ -11,6 +11,13 @@ type HttpOptions = {
|
|
|
11
11
|
readonly body?: string;
|
|
12
12
|
readonly timeoutMs?: number;
|
|
13
13
|
};
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
type HttpFailure = {
|
|
15
|
+
readonly kind: "dns" | "refused" | "timeout" | "tls" | "network";
|
|
16
|
+
readonly host: string;
|
|
17
|
+
readonly detail: string;
|
|
18
|
+
};
|
|
19
|
+
declare const classifyFetchError: (e: unknown, url: string) => HttpFailure;
|
|
20
|
+
declare const httpJson: (url: string, options?: HttpOptions) => Promise<Result<HttpResponse, HttpFailure>>;
|
|
21
|
+
declare const networkRemedy: (failure: HttpFailure) => string;
|
|
22
|
+
export { httpJson, classifyFetchError, networkRemedy };
|
|
23
|
+
export type { HttpResponse, HttpOptions, HttpFailure };
|
package/dist/_utils/http.js
CHANGED
|
@@ -1,4 +1,43 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { causeOf } from "./cli-error.js";
|
|
2
|
+
import { err, fromPromise } from "./result.js";
|
|
3
|
+
const hostOf = (url) => {
|
|
4
|
+
try {
|
|
5
|
+
return new URL(url).host;
|
|
6
|
+
}
|
|
7
|
+
catch {
|
|
8
|
+
return url;
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
const classifyFetchError = (e, url) => {
|
|
12
|
+
const host = hostOf(url);
|
|
13
|
+
const cause = e?.cause;
|
|
14
|
+
const code = cause?.code ?? e?.code;
|
|
15
|
+
if (e?.name === "AbortError" || code === "ABORT_ERR")
|
|
16
|
+
return { kind: "timeout", host, detail: `request to ${host} timed out` };
|
|
17
|
+
if (code === "ENOTFOUND" || code === "EAI_AGAIN")
|
|
18
|
+
return {
|
|
19
|
+
kind: "dns",
|
|
20
|
+
host,
|
|
21
|
+
detail: `could not resolve ${host} (DNS lookup failed)`,
|
|
22
|
+
};
|
|
23
|
+
if (code === "ECONNREFUSED")
|
|
24
|
+
return {
|
|
25
|
+
kind: "refused",
|
|
26
|
+
host,
|
|
27
|
+
detail: `connection to ${host} refused`,
|
|
28
|
+
};
|
|
29
|
+
if (typeof code === "string" && code.startsWith("CERT_"))
|
|
30
|
+
return {
|
|
31
|
+
kind: "tls",
|
|
32
|
+
host,
|
|
33
|
+
detail: `TLS error talking to ${host} (${code}) — a proxy may be intercepting traffic`,
|
|
34
|
+
};
|
|
35
|
+
return {
|
|
36
|
+
kind: "network",
|
|
37
|
+
host,
|
|
38
|
+
detail: `network error reaching ${host} (${causeOf(e)})`,
|
|
39
|
+
};
|
|
40
|
+
};
|
|
2
41
|
const httpJson = async (url, options = {}) => {
|
|
3
42
|
const { method = "GET", headers, body, timeoutMs } = options;
|
|
4
43
|
const controller = new AbortController();
|
|
@@ -14,11 +53,17 @@ const httpJson = async (url, options = {}) => {
|
|
|
14
53
|
if (timeoutId !== undefined)
|
|
15
54
|
clearTimeout(timeoutId);
|
|
16
55
|
if (!fetchResult.ok)
|
|
17
|
-
return fetchResult;
|
|
56
|
+
return err(classifyFetchError(fetchResult.error, url));
|
|
18
57
|
const response = fetchResult.value;
|
|
19
58
|
const text = await fromPromise(response.text());
|
|
20
|
-
if (!text.ok)
|
|
21
|
-
|
|
59
|
+
if (!text.ok) {
|
|
60
|
+
const host = hostOf(url);
|
|
61
|
+
return err({
|
|
62
|
+
kind: "network",
|
|
63
|
+
host,
|
|
64
|
+
detail: `failed reading response from ${host} (${causeOf(text.error)})`,
|
|
65
|
+
});
|
|
66
|
+
}
|
|
22
67
|
const rawText = text.value.trim();
|
|
23
68
|
const json = (() => {
|
|
24
69
|
try {
|
|
@@ -38,5 +83,11 @@ const httpJson = async (url, options = {}) => {
|
|
|
38
83
|
},
|
|
39
84
|
};
|
|
40
85
|
};
|
|
41
|
-
|
|
86
|
+
// Remedy for a transport failure: HttpFailure.detail stays purely
|
|
87
|
+
// descriptive; the actionable part lives here, on the CliError side. Only
|
|
88
|
+
// refused/dns plausibly point at a misconfigured custom base URL.
|
|
89
|
+
const networkRemedy = (failure) => failure.kind === "refused" || failure.kind === "dns"
|
|
90
|
+
? "check your connection and retry; if you use a custom GLEN_BASE_URL, verify it"
|
|
91
|
+
: "check your connection and retry";
|
|
92
|
+
export { httpJson, classifyFetchError, networkRemedy };
|
|
42
93
|
//# sourceMappingURL=http.js.map
|
package/dist/_utils/http.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/_utils/http.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/_utils/http.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,5 +6,5 @@ type LoopbackServer = {
|
|
|
6
6
|
readonly redirectUri: string;
|
|
7
7
|
readonly waitForCallback: () => Promise<CallbackResult>;
|
|
8
8
|
};
|
|
9
|
-
declare const startLoopbackServer: (timeoutMs?: number, expectedState?: string) => Promise<LoopbackServer>;
|
|
9
|
+
declare const startLoopbackServer: (timeoutMs?: number, expectedState?: string, port?: number) => Promise<LoopbackServer>;
|
|
10
10
|
export { startLoopbackServer };
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { createServer } from "node:http";
|
|
2
|
+
import { causeOf, cliErr } from "./cli-error.js";
|
|
2
3
|
import { renderCallbackPage } from "./render-callback-page.js";
|
|
3
|
-
|
|
4
|
+
// `port` exists for tests (forcing an EADDRINUSE collision); production
|
|
5
|
+
// callers always bind an ephemeral port (0).
|
|
6
|
+
const startLoopbackServer = (timeoutMs = 300_000, expectedState, port = 0) => new Promise((resolveStart, rejectStart) => {
|
|
4
7
|
const callback = {
|
|
5
8
|
settled: false,
|
|
6
9
|
resolve: (_v) => { },
|
|
@@ -36,7 +39,19 @@ const startLoopbackServer = (timeoutMs = 300_000, expectedState) => new Promise(
|
|
|
36
39
|
server.close();
|
|
37
40
|
}, timeoutMs);
|
|
38
41
|
timer.unref();
|
|
39
|
-
|
|
42
|
+
// Without this handler a listen failure (EADDRINUSE/EACCES — firewall,
|
|
43
|
+
// VPN, exhausted ports) emits an uncaught 'error' event and crashes the
|
|
44
|
+
// process. Reject the start promise with a CliError instead so login can
|
|
45
|
+
// return it as a structured failure.
|
|
46
|
+
server.on("error", (e) => {
|
|
47
|
+
rejectStart(cliErr({
|
|
48
|
+
what: "could not start the local login listener on 127.0.0.1",
|
|
49
|
+
why: causeOf(e),
|
|
50
|
+
remedy: "check local firewall/VPN settings and retry `glen login`",
|
|
51
|
+
}));
|
|
52
|
+
server.close();
|
|
53
|
+
});
|
|
54
|
+
server.listen(port, "127.0.0.1", () => {
|
|
40
55
|
const addr = server.address();
|
|
41
56
|
resolveStart({
|
|
42
57
|
redirectUri: `http://127.0.0.1:${addr.port}/callback`,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loopback-server.js","sourceRoot":"","sources":["../../src/_utils/loopback-server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAW/D,MAAM,mBAAmB,GAAG,CAC1B,SAAS,GAAG,OAAO,EACnB,aAAsB,
|
|
1
|
+
{"version":3,"file":"loopback-server.js","sourceRoot":"","sources":["../../src/_utils/loopback-server.ts"],"names":[],"mappings":"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"}
|
|
@@ -11,6 +11,9 @@ const openBrowser = (url) => {
|
|
|
11
11
|
detached: true,
|
|
12
12
|
shell: process.platform === "win32",
|
|
13
13
|
});
|
|
14
|
+
child.on("error", () => {
|
|
15
|
+
// best-effort — the caller already printed the URL as a manual fallback
|
|
16
|
+
});
|
|
14
17
|
child.unref();
|
|
15
18
|
};
|
|
16
19
|
export { openBrowser };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"open-browser.js","sourceRoot":"","sources":["../../src/_utils/open-browser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAE3C,MAAM,WAAW,GAAG,CAAC,GAAW,EAAQ,EAAE;IACxC,MAAM,GAAG,GACP,OAAO,CAAC,QAAQ,KAAK,QAAQ;QAC3B,CAAC,CAAC,MAAM;QACR,CAAC,CAAC,OAAO,CAAC,QAAQ,KAAK,OAAO;YAC5B,CAAC,CAAC,OAAO;YACT,CAAC,CAAC,UAAU,CAAC;IACnB,MAAM,IAAI,GAAG,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IAC9D,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,EAAE,IAAI,EAAE;QAC7B,KAAK,EAAE,QAAQ;QACf,QAAQ,EAAE,IAAI;QACd,KAAK,EAAE,OAAO,CAAC,QAAQ,KAAK,OAAO;KACpC,CAAC,CAAC;IACH,KAAK,CAAC,KAAK,EAAE,CAAC;AAChB,CAAC,CAAC;AAEF,OAAO,EAAE,WAAW,EAAE,CAAC"}
|
|
1
|
+
{"version":3,"file":"open-browser.js","sourceRoot":"","sources":["../../src/_utils/open-browser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAE3C,MAAM,WAAW,GAAG,CAAC,GAAW,EAAQ,EAAE;IACxC,MAAM,GAAG,GACP,OAAO,CAAC,QAAQ,KAAK,QAAQ;QAC3B,CAAC,CAAC,MAAM;QACR,CAAC,CAAC,OAAO,CAAC,QAAQ,KAAK,OAAO;YAC5B,CAAC,CAAC,OAAO;YACT,CAAC,CAAC,UAAU,CAAC;IACnB,MAAM,IAAI,GAAG,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IAC9D,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,EAAE,IAAI,EAAE;QAC7B,KAAK,EAAE,QAAQ;QACf,QAAQ,EAAE,IAAI;QACd,KAAK,EAAE,OAAO,CAAC,QAAQ,KAAK,OAAO;KACpC,CAAC,CAAC;IACH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;QACrB,wEAAwE;IAC1E,CAAC,CAAC,CAAC;IACH,KAAK,CAAC,KAAK,EAAE,CAAC;AAChB,CAAC,CAAC;AAEF,OAAO,EAAE,WAAW,EAAE,CAAC"}
|