mossbear 0.1.0-alpha.32 → 0.1.0-alpha.33

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.
@@ -6,8 +6,11 @@
6
6
  * without ever passing through a clipboard.
7
7
  *
8
8
  * **Two modes, and the second is not a fallback.** Interactive is the developer
9
- * at a terminal. *Delegating* (`--print-url`, and automatic when stdout is not
10
- * a TTY) prints the URL and code on their own lines and keeps polling, so an
9
+ * at a terminal, and there the approval page is *opened for them* — the URL is
10
+ * still printed, because a launcher that fails silently would otherwise leave
11
+ * nothing to click (`login/open-browser.ts` says which failures it cannot see).
12
+ * *Delegating* (`--print-url`, and automatic when stdout is not a TTY) prints
13
+ * the URL and code on their own lines, opens nothing, and keeps polling, so an
11
14
  * agent running this can courier the URL to its human and still be holding the
12
15
  * connection when they approve. That mode is what `agent-driven-setup` needs
13
16
  * and what a cloud container with no browser has instead of one; it is named in
@@ -27,6 +30,13 @@ export type LoginEnvironment = {
27
30
  /** Whether stdout is a terminal. Decides the mode when no flag is given. */
28
31
  isTty: boolean;
29
32
  log: (line: string) => void;
33
+ /**
34
+ * Launch the approval page. Returns whether a launcher was started — false
35
+ * covers "nothing to launch into" (no display, `BROWSER=none`) as well as a
36
+ * launcher that could not be spawned, and the caller only uses it to choose
37
+ * a sentence.
38
+ */
39
+ openBrowser: (url: string) => boolean;
30
40
  transport: PairingTransport;
31
41
  writeToken: (token: string) => Promise<void>;
32
42
  hostname: () => string;
@@ -53,6 +63,7 @@ export type LoginResult = {
53
63
  */
54
64
  export declare function performLogin(options: {
55
65
  printUrl: boolean;
66
+ open?: boolean;
56
67
  dashboardUrlFlag?: string;
57
68
  }, environment: LoginEnvironment): Promise<LoginResult>;
58
69
  export declare const loginCommand: import("citty").CommandDef<{
@@ -61,6 +72,11 @@ export declare const loginCommand: import("citty").CommandDef<{
61
72
  description: string;
62
73
  default: false;
63
74
  };
75
+ open: {
76
+ type: "boolean";
77
+ description: string;
78
+ default: true;
79
+ };
64
80
  'dashboard-url': {
65
81
  type: "string";
66
82
  description: string;
@@ -1 +1 @@
1
- {"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAcH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AAE3D,uEAAuE;AACvE,MAAM,MAAM,gBAAgB,GAAG;IAC7B,GAAG,EAAE,MAAM,CAAC,UAAU,CAAA;IACtB,4EAA4E;IAC5E,KAAK,EAAE,OAAO,CAAA;IACd,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IAC3B,SAAS,EAAE,gBAAgB,CAAA;IAC3B,UAAU,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC5C,QAAQ,EAAE,MAAM,MAAM,CAAA;CACvB,CAAA;AAED,MAAM,MAAM,WAAW,GACnB;IAAE,MAAM,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAC1C;IAAE,MAAM,EAAE,QAAQ,CAAA;CAAE,GACpB;IAAE,MAAM,EAAE,SAAS,CAAA;CAAE,GACrB;IAAE,MAAM,EAAE,WAAW,CAAA;CAAE,GACvB;IAAE,MAAM,EAAE,QAAQ,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAA;AAEzC;;;;;;GAMG;AACH,wBAAsB,YAAY,CAChC,OAAO,EAAE;IAAE,QAAQ,EAAE,OAAO,CAAC;IAAC,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAAE,EACzD,WAAW,EAAE,gBAAgB,GAC5B,OAAO,CAAC,WAAW,CAAC,CAkFtB;AAED,eAAO,MAAM,YAAY;;;;;;;;;;EA8CvB,CAAA"}
1
+ {"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAeH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AAE3D,uEAAuE;AACvE,MAAM,MAAM,gBAAgB,GAAG;IAC7B,GAAG,EAAE,MAAM,CAAC,UAAU,CAAA;IACtB,4EAA4E;IAC5E,KAAK,EAAE,OAAO,CAAA;IACd,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IAC3B;;;;;OAKG;IACH,WAAW,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAA;IACrC,SAAS,EAAE,gBAAgB,CAAA;IAC3B,UAAU,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC5C,QAAQ,EAAE,MAAM,MAAM,CAAA;CACvB,CAAA;AAED,MAAM,MAAM,WAAW,GACnB;IAAE,MAAM,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAC1C;IAAE,MAAM,EAAE,QAAQ,CAAA;CAAE,GACpB;IAAE,MAAM,EAAE,SAAS,CAAA;CAAE,GACrB;IAAE,MAAM,EAAE,WAAW,CAAA;CAAE,GACvB;IAAE,MAAM,EAAE,QAAQ,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAA;AAEzC;;;;;;GAMG;AACH,wBAAsB,YAAY,CAChC,OAAO,EAAE;IAAE,QAAQ,EAAE,OAAO,CAAC;IAAC,IAAI,CAAC,EAAE,OAAO,CAAC;IAAC,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAAE,EACzE,WAAW,EAAE,gBAAgB,GAC5B,OAAO,CAAC,WAAW,CAAC,CA0FtB;AAED,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;EAsDvB,CAAA"}
@@ -6,8 +6,11 @@
6
6
  * without ever passing through a clipboard.
7
7
  *
8
8
  * **Two modes, and the second is not a fallback.** Interactive is the developer
9
- * at a terminal. *Delegating* (`--print-url`, and automatic when stdout is not
10
- * a TTY) prints the URL and code on their own lines and keeps polling, so an
9
+ * at a terminal, and there the approval page is *opened for them* — the URL is
10
+ * still printed, because a launcher that fails silently would otherwise leave
11
+ * nothing to click (`login/open-browser.ts` says which failures it cannot see).
12
+ * *Delegating* (`--print-url`, and automatic when stdout is not a TTY) prints
13
+ * the URL and code on their own lines, opens nothing, and keeps polling, so an
11
14
  * agent running this can courier the URL to its human and still be holding the
12
15
  * connection when they approve. That mode is what `agent-driven-setup` needs
13
16
  * and what a cloud container with no browser has instead of one; it is named in
@@ -23,6 +26,7 @@
23
26
  import { defineCommand } from 'citty';
24
27
  import { MOSSBEAR_TOKEN_ENV, readEnvToken, resolveDashboardUrl, writeConfigToken, } from '../config.js';
25
28
  import { errText } from '../err-text.js';
29
+ import { openInBrowser } from '../login/open-browser.js';
26
30
  import { defaultTransport, pollForToken, startPairing } from '../login/pairing.js';
27
31
  import { CLI_VERSION } from '../version.js';
28
32
  /**
@@ -72,7 +76,12 @@ export async function performLogin(options, environment) {
72
76
  environment.log(` Open ${session.verificationUriComplete}`);
73
77
  environment.log(` Code ${session.userCode}`);
74
78
  environment.log('');
75
- environment.log(' Waiting for you to approve it…');
79
+ // Printed first, launched second: whatever the browser does with focus,
80
+ // the URL and the code are already on screen to fall back to.
81
+ const opening = options.open !== false && environment.openBrowser(session.verificationUriComplete);
82
+ environment.log(opening
83
+ ? ' Opening that in your browser. Waiting for you to approve it…'
84
+ : ' Waiting for you to approve it…');
76
85
  }
77
86
  let outcome;
78
87
  try {
@@ -111,6 +120,11 @@ export const loginCommand = defineCommand({
111
120
  description: 'Print the approval URL and code on their own lines and keep waiting, instead of assuming someone is at this terminal. Automatic when stdout is not a TTY',
112
121
  default: false,
113
122
  },
123
+ open: {
124
+ type: 'boolean',
125
+ description: 'Open the approval page in your browser. On by default at a terminal; use --no-open to just print it. Never happens with --print-url, or when stdout is not a TTY',
126
+ default: true,
127
+ },
114
128
  'dashboard-url': {
115
129
  type: 'string',
116
130
  description: 'Dashboard to pair with. Defaults to the configured one',
@@ -120,11 +134,13 @@ export const loginCommand = defineCommand({
120
134
  const { hostname } = await import('node:os');
121
135
  const result = await performLogin({
122
136
  printUrl: Boolean(args['print-url']),
137
+ open: args.open !== false,
123
138
  dashboardUrlFlag: typeof args['dashboard-url'] === 'string' ? args['dashboard-url'] : '',
124
139
  }, {
125
140
  env: process.env,
126
141
  isTty: Boolean(process.stdout.isTTY),
127
142
  log: (line) => console.log(line),
143
+ openBrowser: (url) => openInBrowser(url),
128
144
  transport: defaultTransport,
129
145
  writeToken: (token) => writeConfigToken(token),
130
146
  hostname,
@@ -1 +1 @@
1
- {"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAA;AAErC,OAAO,EACL,kBAAkB,EAClB,YAAY,EACZ,mBAAmB,EACnB,gBAAgB,GACjB,MAAM,cAAc,CAAA;AACrB,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAA;AACxC,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAClF,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAsB3C;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,OAAyD,EACzD,WAA6B;IAE7B,MAAM,QAAQ,GAAG,YAAY,CAAC,WAAW,CAAC,GAAG,CAAC,CAAA;IAC9C,IAAI,QAAQ,EAAE,CAAC;QACb,0EAA0E;QAC1E,0EAA0E;QAC1E,8CAA8C;QAC9C,WAAW,CAAC,GAAG,CACb,GAAG,kBAAkB,0DAA0D;YAC7E,wCAAwC,CAC3C,CAAA;QACD,WAAW,CAAC,GAAG,CACb,8CAA8C,kBAAkB,oCAAoC,CACrG,CAAA;QACD,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,CAAA;IAChC,CAAC;IAED,IAAI,YAAoB,CAAA;IACxB,IAAI,CAAC;QACH,YAAY,GAAG,MAAM,mBAAmB,CAAC,OAAO,CAAC,gBAAgB,IAAI,EAAE,CAAC,CAAA;IAC1E,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,EAAE,CAAA;IACpD,CAAC;IAED,IAAI,OAAO,CAAA;IACX,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,YAAY,CAC1B,YAAY,EACZ,EAAE,UAAU,EAAE,WAAW,CAAC,QAAQ,EAAE,EAAE,UAAU,EAAE,WAAW,EAAE,EAC/D,WAAW,CAAC,SAAS,CACtB,CAAA;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,EAAE,CAAA;IACpD,CAAC;IAED,2EAA2E;IAC3E,0EAA0E;IAC1E,8BAA8B;IAC9B,MAAM,UAAU,GAAG,OAAO,CAAC,QAAQ,IAAI,CAAC,WAAW,CAAC,KAAK,CAAA;IACzD,IAAI,UAAU,EAAE,CAAC;QACf,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,uBAAuB,CAAC,CAAA;QAChD,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;QACjC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QACnB,WAAW,CAAC,GAAG,CAAC,oDAAoD,CAAC,CAAA;IACvE,CAAC;SAAM,CAAC;QACN,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QACnB,WAAW,CAAC,GAAG,CAAC,WAAW,OAAO,CAAC,uBAAuB,EAAE,CAAC,CAAA;QAC7D,WAAW,CAAC,GAAG,CAAC,WAAW,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAA;QAC9C,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QACnB,WAAW,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAA;IACrD,CAAC;IAED,IAAI,OAAO,CAAA;IACX,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,YAAY,CAAC,YAAY,EAAE,OAAO,EAAE,WAAW,CAAC,SAAS,CAAC,CAAA;IAC5E,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,EAAE,CAAA;IACpD,CAAC;IAED,IAAI,OAAO,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;QACjC,WAAW,CAAC,GAAG,CAAC,iDAAiD,CAAC,CAAA;QAClE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAA;IAC7B,CAAC;IAED,IAAI,OAAO,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;QAClC,WAAW,CAAC,GAAG,CACb,uEAAuE,CACxE,CAAA;QACD,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,CAAA;IAC9B,CAAC;IAED,IAAI,CAAC;QACH,MAAM,WAAW,CAAC,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;IAC7C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,EAAE,CAAA;IACpD,CAAC;IAED,WAAW,CAAC,GAAG,CACb,OAAO,CAAC,KAAK;QACX,CAAC,CAAC,aAAa,OAAO,CAAC,KAAK,4CAA4C;QACxE,CAAC,CAAC,kDAAkD,CACvD,CAAA;IACD,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAA;AACnD,CAAC;AAED,MAAM,CAAC,MAAM,YAAY,GAAG,aAAa,CAAC;IACxC,IAAI,EAAE;QACJ,IAAI,EAAE,OAAO;QACb,WAAW,EACT,wJAAwJ;KAC3J;IACD,IAAI,EAAE;QACJ,WAAW,EAAE;YACX,IAAI,EAAE,SAAS;YACf,WAAW,EACT,0JAA0J;YAC5J,OAAO,EAAE,KAAK;SACf;QACD,eAAe,EAAE;YACf,IAAI,EAAE,QAAQ;YACd,WAAW,EAAE,wDAAwD;SACtE;KACF;IACD,KAAK,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE;QAChB,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,CAAA;QAE5C,MAAM,MAAM,GAAG,MAAM,YAAY,CAC/B;YACE,QAAQ,EAAE,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YACpC,gBAAgB,EACd,OAAO,IAAI,CAAC,eAAe,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,EAAE;SACzE,EACD;YACE,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,KAAK,EAAE,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC;YACpC,GAAG,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;YAChC,SAAS,EAAE,gBAAgB;YAC3B,UAAU,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,gBAAgB,CAAC,KAAK,CAAC;YAC9C,QAAQ;SACT,CACF,CAAA;QAED,IAAI,MAAM,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;YAC/B,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;QAC/B,CAAC;QAED,yEAAyE;QACzE,0EAA0E;QAC1E,8CAA8C;QAC9C,OAAO,CAAC,QAAQ,GAAG,MAAM,CAAC,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;IACxF,CAAC;CACF,CAAC,CAAA"}
1
+ {"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Hand a URL to the machine's own browser.
3
+ *
4
+ * `mossbear login` prints an approval URL that is useless until a human loads
5
+ * it, and the shortest path from "printed" to "loaded" is not the user
6
+ * selecting a wrapped URL out of a terminal. So interactive mode launches it
7
+ * for them — while still printing it, because a launcher that silently fails is
8
+ * worse than no launcher at all and every branch here can fail for reasons this
9
+ * process cannot see.
10
+ *
11
+ * Three rules the shape here exists to keep:
12
+ *
13
+ * - **Only ever a plain `http(s)` URL, passed as an argument.** The value comes
14
+ * off the wire from whatever dashboard is configured, and handing an
15
+ * arbitrary string to a shell — or to a `file:`/`javascript:` handler — turns
16
+ * a misconfigured `dashboardUrl` into local code execution. `spawn` with an
17
+ * argument array never involves a shell, and {@link isLaunchableUrl} refuses
18
+ * anything that is not http(s).
19
+ * - **Never block the login.** The child is detached and unref'd, so a
20
+ * launcher that waits for the browser to exit (several do) cannot hold the
21
+ * poll loop, and an `ENOENT` for a launcher that is not installed is an
22
+ * ignored event rather than a crash.
23
+ * - **Don't launch into a machine with no display.** On a headless Linux box
24
+ * `xdg-open` may fall through to a *terminal* browser, which would take over
25
+ * the very terminal the user is reading the code from.
26
+ */
27
+ import { spawn as nodeSpawn } from 'node:child_process';
28
+ /** Injected in tests; the real caller uses the process it runs in. */
29
+ export type BrowserLauncher = {
30
+ platform: NodeJS.Platform;
31
+ env: NodeJS.ProcessEnv;
32
+ spawn: typeof nodeSpawn;
33
+ };
34
+ export declare const defaultLauncher: BrowserLauncher;
35
+ /**
36
+ * Whether this URL is safe to pass to a system handler.
37
+ *
38
+ * http(s) only, and deliberately not "whatever `new URL` accepts": `file:`,
39
+ * `javascript:` and custom app schemes are all valid URLs and none of them
40
+ * should be openable by a value the CLI received over a network.
41
+ */
42
+ export declare function isLaunchableUrl(url: string): boolean;
43
+ /**
44
+ * The command that opens a URL here, or null when nothing should be launched.
45
+ *
46
+ * `BROWSER=none` is the convention already understood by the tools developers
47
+ * run beside this one, so it is honoured rather than reinvented as a
48
+ * Mossbear-specific variable; any other `BROWSER` value is left to the
49
+ * platform handler, which on Linux reads it itself.
50
+ */
51
+ export declare function launchCommand(url: string, launcher: BrowserLauncher): {
52
+ command: string;
53
+ args: string[];
54
+ } | null;
55
+ /**
56
+ * Try to open `url`, and say whether a launcher was actually started.
57
+ *
58
+ * "Started" is the strongest claim available without waiting for a browser
59
+ * that may take seconds to paint, so the caller's copy must stay at
60
+ * "opened in your browser" rather than promising the page is up.
61
+ */
62
+ export declare function openInBrowser(url: string, launcher?: BrowserLauncher): boolean;
63
+ //# sourceMappingURL=open-browser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"open-browser.d.ts","sourceRoot":"","sources":["../../src/login/open-browser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EAAE,KAAK,IAAI,SAAS,EAAE,MAAM,oBAAoB,CAAA;AAEvD,sEAAsE;AACtE,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAA;IACzB,GAAG,EAAE,MAAM,CAAC,UAAU,CAAA;IACtB,KAAK,EAAE,OAAO,SAAS,CAAA;CACxB,CAAA;AAED,eAAO,MAAM,eAAe,EAAE,eAI7B,CAAA;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAOpD;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAC3B,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,eAAe,GACxB;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,GAAG,IAAI,CAqB5C;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAC3B,GAAG,EAAE,MAAM,EACX,QAAQ,GAAE,eAAiC,GAC1C,OAAO,CAmBT"}
@@ -0,0 +1,107 @@
1
+ /**
2
+ * Hand a URL to the machine's own browser.
3
+ *
4
+ * `mossbear login` prints an approval URL that is useless until a human loads
5
+ * it, and the shortest path from "printed" to "loaded" is not the user
6
+ * selecting a wrapped URL out of a terminal. So interactive mode launches it
7
+ * for them — while still printing it, because a launcher that silently fails is
8
+ * worse than no launcher at all and every branch here can fail for reasons this
9
+ * process cannot see.
10
+ *
11
+ * Three rules the shape here exists to keep:
12
+ *
13
+ * - **Only ever a plain `http(s)` URL, passed as an argument.** The value comes
14
+ * off the wire from whatever dashboard is configured, and handing an
15
+ * arbitrary string to a shell — or to a `file:`/`javascript:` handler — turns
16
+ * a misconfigured `dashboardUrl` into local code execution. `spawn` with an
17
+ * argument array never involves a shell, and {@link isLaunchableUrl} refuses
18
+ * anything that is not http(s).
19
+ * - **Never block the login.** The child is detached and unref'd, so a
20
+ * launcher that waits for the browser to exit (several do) cannot hold the
21
+ * poll loop, and an `ENOENT` for a launcher that is not installed is an
22
+ * ignored event rather than a crash.
23
+ * - **Don't launch into a machine with no display.** On a headless Linux box
24
+ * `xdg-open` may fall through to a *terminal* browser, which would take over
25
+ * the very terminal the user is reading the code from.
26
+ */
27
+ import { spawn as nodeSpawn } from 'node:child_process';
28
+ export const defaultLauncher = {
29
+ platform: process.platform,
30
+ env: process.env,
31
+ spawn: nodeSpawn,
32
+ };
33
+ /**
34
+ * Whether this URL is safe to pass to a system handler.
35
+ *
36
+ * http(s) only, and deliberately not "whatever `new URL` accepts": `file:`,
37
+ * `javascript:` and custom app schemes are all valid URLs and none of them
38
+ * should be openable by a value the CLI received over a network.
39
+ */
40
+ export function isLaunchableUrl(url) {
41
+ try {
42
+ const parsed = new URL(url);
43
+ return parsed.protocol === 'http:' || parsed.protocol === 'https:';
44
+ }
45
+ catch {
46
+ return false;
47
+ }
48
+ }
49
+ /**
50
+ * The command that opens a URL here, or null when nothing should be launched.
51
+ *
52
+ * `BROWSER=none` is the convention already understood by the tools developers
53
+ * run beside this one, so it is honoured rather than reinvented as a
54
+ * Mossbear-specific variable; any other `BROWSER` value is left to the
55
+ * platform handler, which on Linux reads it itself.
56
+ */
57
+ export function launchCommand(url, launcher) {
58
+ const browser = launcher.env.BROWSER?.trim().toLowerCase();
59
+ if (browser === 'none')
60
+ return null;
61
+ if (launcher.platform === 'darwin')
62
+ return { command: 'open', args: [url] };
63
+ if (launcher.platform === 'win32') {
64
+ // Not `cmd /c start`: `cmd` re-parses its arguments, and this URL carries a
65
+ // query string, so an `&` in it would be read as a command separator.
66
+ return { command: 'rundll32', args: ['url.dll,FileProtocolHandler', url] };
67
+ }
68
+ // WSL has a Linux platform and no Linux browser — `wslview` (wslu) hands the
69
+ // URL to Windows. Absent that package the spawn fails and the printed URL is
70
+ // still there, which is the same outcome as any other missing launcher.
71
+ if (launcher.env.WSL_DISTRO_NAME)
72
+ return { command: 'wslview', args: [url] };
73
+ // A Linux session with no display server. See the module header: launching
74
+ // here can capture the terminal the user is reading.
75
+ if (!launcher.env.DISPLAY && !launcher.env.WAYLAND_DISPLAY)
76
+ return null;
77
+ return { command: 'xdg-open', args: [url] };
78
+ }
79
+ /**
80
+ * Try to open `url`, and say whether a launcher was actually started.
81
+ *
82
+ * "Started" is the strongest claim available without waiting for a browser
83
+ * that may take seconds to paint, so the caller's copy must stay at
84
+ * "opened in your browser" rather than promising the page is up.
85
+ */
86
+ export function openInBrowser(url, launcher = defaultLauncher) {
87
+ if (!isLaunchableUrl(url))
88
+ return false;
89
+ const launch = launchCommand(url, launcher);
90
+ if (!launch)
91
+ return false;
92
+ try {
93
+ const child = launcher.spawn(launch.command, launch.args, {
94
+ detached: true,
95
+ stdio: 'ignore',
96
+ });
97
+ // Without this an ENOENT for a missing launcher is an unhandled 'error'
98
+ // event, which ends the process — during a login the user is mid-approval on.
99
+ child.on('error', () => { });
100
+ child.unref();
101
+ return true;
102
+ }
103
+ catch {
104
+ return false;
105
+ }
106
+ }
107
+ //# sourceMappingURL=open-browser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"open-browser.js","sourceRoot":"","sources":["../../src/login/open-browser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EAAE,KAAK,IAAI,SAAS,EAAE,MAAM,oBAAoB,CAAA;AASvD,MAAM,CAAC,MAAM,eAAe,GAAoB;IAC9C,QAAQ,EAAE,OAAO,CAAC,QAAQ;IAC1B,GAAG,EAAE,OAAO,CAAC,GAAG;IAChB,KAAK,EAAE,SAAS;CACjB,CAAA;AAED;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,CAAC,GAAW;IACzC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAA;QAC3B,OAAO,MAAM,CAAC,QAAQ,KAAK,OAAO,IAAI,MAAM,CAAC,QAAQ,KAAK,QAAQ,CAAA;IACpE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAA;IACd,CAAC;AACH,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,aAAa,CAC3B,GAAW,EACX,QAAyB;IAEzB,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,WAAW,EAAE,CAAA;IAC1D,IAAI,OAAO,KAAK,MAAM;QAAE,OAAO,IAAI,CAAA;IAEnC,IAAI,QAAQ,CAAC,QAAQ,KAAK,QAAQ;QAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE,CAAA;IAC3E,IAAI,QAAQ,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QAClC,4EAA4E;QAC5E,sEAAsE;QACtE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,6BAA6B,EAAE,GAAG,CAAC,EAAE,CAAA;IAC5E,CAAC;IAED,6EAA6E;IAC7E,6EAA6E;IAC7E,wEAAwE;IACxE,IAAI,QAAQ,CAAC,GAAG,CAAC,eAAe;QAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE,CAAA;IAE5E,2EAA2E;IAC3E,qDAAqD;IACrD,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,eAAe;QAAE,OAAO,IAAI,CAAA;IAEvE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE,CAAA;AAC7C,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,aAAa,CAC3B,GAAW,EACX,WAA4B,eAAe;IAE3C,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC;QAAE,OAAO,KAAK,CAAA;IAEvC,MAAM,MAAM,GAAG,aAAa,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAA;IAC3C,IAAI,CAAC,MAAM;QAAE,OAAO,KAAK,CAAA;IAEzB,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,IAAI,EAAE;YACxD,QAAQ,EAAE,IAAI;YACd,KAAK,EAAE,QAAQ;SAChB,CAAC,CAAA;QACF,wEAAwE;QACxE,8EAA8E;QAC9E,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;QAC3B,KAAK,CAAC,KAAK,EAAE,CAAA;QACb,OAAO,IAAI,CAAA;IACb,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAA;IACd,CAAC;AACH,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mossbear",
3
- "version": "0.1.0-alpha.32",
3
+ "version": "0.1.0-alpha.33",
4
4
  "private": false,
5
5
  "description": "Local-first CLI for Mossbear — records what your AI coding agents did and syncs it to your dashboard, which grades it against the rules and skills you wrote.",
6
6
  "license": "MIT",
@@ -54,9 +54,9 @@
54
54
  },
55
55
  "dependencies": {
56
56
  "@modelcontextprotocol/sdk": "1.30.0",
57
- "@mossbear/eval-core": "0.1.0-alpha.32",
58
- "@mossbear/projections": "0.1.0-alpha.32",
59
- "@mossbear/protocol": "0.1.0-alpha.32",
57
+ "@mossbear/eval-core": "0.1.0-alpha.33",
58
+ "@mossbear/projections": "0.1.0-alpha.33",
59
+ "@mossbear/protocol": "0.1.0-alpha.33",
60
60
  "citty": "^0.1.6",
61
61
  "valibot": "^1.4.2"
62
62
  },