@dopemarkets/agent 0.1.2 → 0.1.3

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/dist/index.js CHANGED
@@ -15,7 +15,7 @@ const markets_js_1 = require("./commands/markets.js");
15
15
  const stack_js_1 = require("./commands/stack.js");
16
16
  const agent_key_js_1 = require("./commands/agent_key.js");
17
17
  const mcp_js_1 = require("./commands/mcp.js");
18
- const VERSION = '0.1.2';
18
+ const VERSION = '0.1.3';
19
19
  const HELP = `dope — DOPE Agent Mode CLI (v${VERSION})
20
20
 
21
21
  Usage:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dopemarkets/agent",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "DOPE Agent Mode CLI. Run agentic Stack trades on DOPE from the terminal.",
5
5
  "bin": {
6
6
  "dope": "bin/dope.js"
@@ -5,20 +5,32 @@
5
5
  // unambiguous "the install succeeded — here's what to do next" line.
6
6
  // Non-developers won't otherwise know the install worked.
7
7
  //
8
- // Note: we tried gating this on `process.env.npm_config_global === 'true'`
9
- // so the banner would only appear on `-g` installs and stay quiet when
10
- // the package was pulled in as a transitive dep. In practice npm 11
11
- // does not reliably set that env var for postinstall scripts, so the
12
- // banner never fired on the install path that actually matters.
13
- // `@dopemarkets/agent` is a CLI; the global install is overwhelmingly
14
- // the intended use, and a stray banner on a rare local install is not
15
- // worth losing the signal on the common path. Always print.
8
+ // Two non-obvious things make this trickier than it looks:
16
9
  //
17
- // Rules that remain:
18
- // - Print to stderr so it sits alongside npm's own install chatter
19
- // and never contaminates a script's stdout.
20
- // - Never throw. Postinstall failures bubble up as install failures,
21
- // and a banner is not worth breaking somebody's machine over.
10
+ // 1. npm 9+ runs postinstall scripts in background mode by default
11
+ // (the `--foreground-scripts` flag is opt-in). In background
12
+ // mode npm captures the child's stdout/stderr and only surfaces
13
+ // them on failure. Writing to `process.stderr` is therefore
14
+ // invisible to the user on a normal `npm install -g` run. To
15
+ // reach the user's terminal we open `/dev/tty` for writing and
16
+ // print there, bypassing npm's stream capture entirely. This
17
+ // requires a controlling terminal (so e.g. CI shows nothing,
18
+ // which is the right outcome — no human to read the banner).
19
+ //
20
+ // 2. We previously tried gating this on `npm_config_global` so the
21
+ // banner would only print on `-g` installs. npm 11 does not
22
+ // reliably set that env var for postinstall scripts, so the
23
+ // gate silently no-op'd on the install path that actually
24
+ // matters. `@dopemarkets/agent` is a CLI; the global install
25
+ // is overwhelmingly the intended use. We always print.
26
+ //
27
+ // Rules:
28
+ // - Try the controlling TTY first (works on the common case).
29
+ // - Fall back to stderr (covers Windows, `--foreground-scripts`,
30
+ // and any environment without a usable /dev/tty).
31
+ // - Never throw. Postinstall failures bubble up as install
32
+ // failures, and a banner is never worth breaking somebody's
33
+ // machine over.
22
34
 
23
35
  'use strict';
24
36
 
@@ -33,7 +45,24 @@ try {
33
45
  'Run `dope --help` to see every command.',
34
46
  '',
35
47
  ];
36
- process.stderr.write(lines.join('\n'));
48
+ const message = lines.join('\n');
49
+
50
+ let wroteToTty = false;
51
+ if (process.platform !== 'win32') {
52
+ try {
53
+ // Synchronous open + write so we don't leak across npm's
54
+ // postinstall lifecycle boundary.
55
+ const fs = require('fs');
56
+ fs.writeFileSync('/dev/tty', message);
57
+ wroteToTty = true;
58
+ } catch {
59
+ // No controlling TTY (e.g. CI). Fall through to stderr.
60
+ }
61
+ }
62
+
63
+ if (!wroteToTty) {
64
+ process.stderr.write(message);
65
+ }
37
66
  } catch {
38
67
  // Intentionally swallow. A banner is never worth a failed install.
39
68
  }