@memnexus-ai/cli 1.7.216 → 1.7.218

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
@@ -24,6 +24,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
24
24
  */
25
25
  const config_1 = require("./lib/config");
26
26
  const package_json_1 = __importDefault(require("../package.json"));
27
+ const code_context_1 = require("./lib/commit-context/code-context");
27
28
  // Inject X-MX-Client header into all outgoing fetch requests for API-layer analytics
28
29
  const originalFetch = globalThis.fetch;
29
30
  globalThis.fetch = (input, init) => {
@@ -39,6 +40,12 @@ globalThis.fetch = (input, init) => {
39
40
  ].join(' ');
40
41
  headers.set('X-MX-Client', clientInfo);
41
42
  }
43
+ // Per-project attribution (v3.89a, source='cli') — resolved once and cached.
44
+ // Only set when resolved (unresolved-silent).
45
+ for (const [key, value] of Object.entries((0, code_context_1.resolveAttributionHeadersCached)(process.cwd()))) {
46
+ if (!headers.has(key))
47
+ headers.set(key, value);
48
+ }
42
49
  return originalFetch(input, { ...init, headers });
43
50
  };
44
51
  const commander_1 = require("commander");
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -7,6 +7,36 @@
7
7
  * Returns undefined when neither is present or usable (no regression).
8
8
  *
9
9
  * @param projectRoot Repository root — where `.mx-code-context.json` lives.
10
+ * @param options.silent When true, suppress the dimmed stdout notice emitted
11
+ * when scope is resolved from the repo file. Telemetry attribution (the MCP
12
+ * bridge and the CLI global-fetch wrapper) MUST pass `silent: true` because
13
+ * their stdout is a protocol / data channel — a stray log line corrupts it.
14
+ * The commit hook leaves it false so the operator still sees the notice.
10
15
  */
11
- export declare function resolveCommitCodeContext(projectRoot: string): Record<string, string> | undefined;
16
+ export declare function resolveCommitCodeContext(projectRoot: string, options?: {
17
+ silent?: boolean;
18
+ }): Record<string, string> | undefined;
19
+ /**
20
+ * Build the per-project telemetry attribution headers from a resolved
21
+ * CodeContext. Returns `X-MX-Project` (from `product`) and `X-MX-Team` (from
22
+ * `team`) when present. Empty object when the context is undefined, lacks those
23
+ * keys, or the values sanitize to empty — the caller then sends nothing
24
+ * (unresolved-silent).
25
+ *
26
+ * Values are already capped at 200 chars by resolveCommitCodeContext, but come
27
+ * from the untrusted repo file, so we re-sanitize (strip control chars + cap 50)
28
+ * before they reach Headers.set. Shared by the MCP bridge (`mx mcp serve`) and
29
+ * the CLI global-fetch wrapper so both the source='mcp' and source='cli'
30
+ * analytics paths attribute identically.
31
+ */
32
+ export declare function attributionHeaders(codeContext: Record<string, string> | undefined): Record<string, string>;
33
+ /**
34
+ * Resolve the per-project attribution headers for the direct-CLI path, resolving
35
+ * the CodeContext at most once per process and caching the result. The CLI is
36
+ * per-invocation, so the file read is deferred to the first outgoing request and
37
+ * never repeated. `silent: true` keeps stdout clean for JSON output modes.
38
+ */
39
+ export declare function resolveAttributionHeadersCached(projectRoot: string): Record<string, string>;
40
+ /** Test-only: clear the process-level attribution cache. */
41
+ export declare function _resetAttributionCache(): void;
12
42
  //# sourceMappingURL=code-context.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"code-context.d.ts","sourceRoot":"","sources":["../../../src/lib/commit-context/code-context.ts"],"names":[],"mappings":"AAoEA;;;;;;;;;GASG;AACH,wBAAgB,wBAAwB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAyBhG"}
1
+ {"version":3,"file":"code-context.d.ts","sourceRoot":"","sources":["../../../src/lib/commit-context/code-context.ts"],"names":[],"mappings":"AA4EA;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,wBAAwB,CACtC,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAO,GACjC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAiCpC;AAmCD;;;;;;;;;;;;GAYG;AACH,wBAAgB,kBAAkB,CAChC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,GAC9C,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAWxB;AAKD;;;;;GAKG;AACH,wBAAgB,+BAA+B,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAO3F;AAED,4DAA4D;AAC5D,wBAAgB,sBAAsB,IAAI,IAAI,CAE7C"}
@@ -4,6 +4,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.resolveCommitCodeContext = resolveCommitCodeContext;
7
+ exports.attributionHeaders = attributionHeaders;
8
+ exports.resolveAttributionHeadersCached = resolveAttributionHeadersCached;
9
+ exports._resetAttributionCache = _resetAttributionCache;
7
10
  /**
8
11
  * Code Context Resolver — resolves the CodeContext scope tags to attach to
9
12
  * auto-memories created by the CommitContext hook.
@@ -30,6 +33,13 @@ const chalk_1 = __importDefault(require("chalk"));
30
33
  const KNOWN_KEYS = ['product', 'repo', 'service', 'component', 'team', 'role'];
31
34
  /** Max length per value — matches the server's CodeContextSchema (.max(200)). */
32
35
  const MAX_VALUE_LENGTH = 200;
36
+ /**
37
+ * Max size of the untrusted `.mx-code-context.json` we will read. A legitimate
38
+ * scope file is a handful of short string values (< 1KB). The bound stops a
39
+ * hostile or accidental multi-GB file from OOMing the bridge startup / CLI
40
+ * hot path. Over the bound we fail open (skip the file), same as a missing one.
41
+ */
42
+ const MAX_FILE_SIZE_BYTES = 64 * 1024;
33
43
  /**
34
44
  * Normalize a raw parsed object into a clean CodeContext record:
35
45
  * - keep only known keys
@@ -74,8 +84,13 @@ function parseCodeContext(json) {
74
84
  * Returns undefined when neither is present or usable (no regression).
75
85
  *
76
86
  * @param projectRoot Repository root — where `.mx-code-context.json` lives.
87
+ * @param options.silent When true, suppress the dimmed stdout notice emitted
88
+ * when scope is resolved from the repo file. Telemetry attribution (the MCP
89
+ * bridge and the CLI global-fetch wrapper) MUST pass `silent: true` because
90
+ * their stdout is a protocol / data channel — a stray log line corrupts it.
91
+ * The commit hook leaves it false so the operator still sees the notice.
77
92
  */
78
- function resolveCommitCodeContext(projectRoot) {
93
+ function resolveCommitCodeContext(projectRoot, options = {}) {
79
94
  // 1. Env var — MX_CODE_CONTEXT (operator-controlled, higher trust).
80
95
  const fromEnv = process.env.MX_CODE_CONTEXT;
81
96
  if (fromEnv) {
@@ -87,10 +102,18 @@ function resolveCommitCodeContext(projectRoot) {
87
102
  // 2. File — <projectRoot>/.mx-code-context.json (repo-controlled, lower trust).
88
103
  try {
89
104
  const filePath = (0, path_1.join)(projectRoot, '.mx-code-context.json');
105
+ // Size-bound the untrusted file before reading it into memory — a multi-GB
106
+ // file would OOM the bridge startup / CLI hot path. Over the bound: fail
107
+ // open (skip), identical to the file being absent.
108
+ if ((0, fs_1.statSync)(filePath).size > MAX_FILE_SIZE_BYTES) {
109
+ return undefined;
110
+ }
90
111
  const contents = (0, fs_1.readFileSync)(filePath, 'utf8');
91
112
  const fromFile = parseCodeContext(contents);
92
113
  if (fromFile) {
93
- logFileScope(fromFile);
114
+ if (!options.silent) {
115
+ logFileScope(fromFile);
116
+ }
94
117
  return fromFile;
95
118
  }
96
119
  }
@@ -100,6 +123,82 @@ function resolveCommitCodeContext(projectRoot) {
100
123
  // 3. Nothing usable — undefined (current behavior, no regression).
101
124
  return undefined;
102
125
  }
126
+ /**
127
+ * Characters stripped from untrusted attribution values before they become
128
+ * HTTP header values or analytics labels. Covers:
129
+ * - ASCII control chars (\x00-\x1f, \x7f) — undici Headers.set throws on these
130
+ * - zero-width chars (U+200B–U+200F)
131
+ * - line/paragraph separators + bidi controls (U+2028–U+202E)
132
+ * - bidi isolates (U+2066–U+2069)
133
+ * The Unicode format/control classes (bidi override U+202E, line separator
134
+ * U+2028, etc.) survive a plain ASCII strip and can spoof how a value renders
135
+ * in dashboards/logs, so they are removed at every hop (this fn, the MCP
136
+ * server's sanitizeAttribution, core-api's getMcpClientProps) identically.
137
+ */
138
+ // eslint-disable-next-line no-control-regex
139
+ const UNSAFE_HEADER_CHARS = /[\x00-\x1f\x7f\u200b-\u200f\u2028-\u202e\u2066-\u2069]/g;
140
+ /**
141
+ * Sanitize a value for use as an HTTP header. Strips unsafe control/format
142
+ * characters and caps at 50 chars — mirroring the MCP server's
143
+ * sanitizeAttribution and core-api's attribution strip exactly.
144
+ *
145
+ * SECURITY (must-not-throw contract): the repo `.mx-code-context.json` is
146
+ * untrusted input. undici's Headers.set THROWS a TypeError on control
147
+ * characters (\r, \n, \x00, ...), so a hostile or typo'd value like
148
+ * {"product":"a\nb"} would break EVERY `mx` command and the `mx mcp serve`
149
+ * bridge in that repo — the opposite of this module's fail-open contract.
150
+ * Stripping unsafe chars here guarantees Headers.set cannot throw downstream.
151
+ * Returns undefined when nothing usable remains.
152
+ */
153
+ function sanitizeHeaderValue(value) {
154
+ const cleaned = value.replace(UNSAFE_HEADER_CHARS, '').slice(0, 50);
155
+ return cleaned.length > 0 ? cleaned : undefined;
156
+ }
157
+ /**
158
+ * Build the per-project telemetry attribution headers from a resolved
159
+ * CodeContext. Returns `X-MX-Project` (from `product`) and `X-MX-Team` (from
160
+ * `team`) when present. Empty object when the context is undefined, lacks those
161
+ * keys, or the values sanitize to empty — the caller then sends nothing
162
+ * (unresolved-silent).
163
+ *
164
+ * Values are already capped at 200 chars by resolveCommitCodeContext, but come
165
+ * from the untrusted repo file, so we re-sanitize (strip control chars + cap 50)
166
+ * before they reach Headers.set. Shared by the MCP bridge (`mx mcp serve`) and
167
+ * the CLI global-fetch wrapper so both the source='mcp' and source='cli'
168
+ * analytics paths attribute identically.
169
+ */
170
+ function attributionHeaders(codeContext) {
171
+ const headers = {};
172
+ if (codeContext?.product) {
173
+ const project = sanitizeHeaderValue(codeContext.product);
174
+ if (project)
175
+ headers['X-MX-Project'] = project;
176
+ }
177
+ if (codeContext?.team) {
178
+ const team = sanitizeHeaderValue(codeContext.team);
179
+ if (team)
180
+ headers['X-MX-Team'] = team;
181
+ }
182
+ return headers;
183
+ }
184
+ /** Module-level cache for the direct-CLI attribution headers. */
185
+ let cachedAttributionHeaders = null;
186
+ /**
187
+ * Resolve the per-project attribution headers for the direct-CLI path, resolving
188
+ * the CodeContext at most once per process and caching the result. The CLI is
189
+ * per-invocation, so the file read is deferred to the first outgoing request and
190
+ * never repeated. `silent: true` keeps stdout clean for JSON output modes.
191
+ */
192
+ function resolveAttributionHeadersCached(projectRoot) {
193
+ if (cachedAttributionHeaders === null) {
194
+ cachedAttributionHeaders = attributionHeaders(resolveCommitCodeContext(projectRoot, { silent: true }));
195
+ }
196
+ return cachedAttributionHeaders;
197
+ }
198
+ /** Test-only: clear the process-level attribution cache. */
199
+ function _resetAttributionCache() {
200
+ cachedAttributionHeaders = null;
201
+ }
103
202
  /**
104
203
  * Log once, dimmed, when scope is resolved from the repo file so the operator
105
204
  * can see what is being attached to the commit's auto-memory. Best-effort —
@@ -1 +1 @@
1
- {"version":3,"file":"code-context.js","sourceRoot":"","sources":["../../../src/lib/commit-context/code-context.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"code-context.js","sourceRoot":"","sources":["../../../src/lib/commit-context/code-context.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@memnexus-ai/cli",
3
- "version": "1.7.216",
3
+ "version": "1.7.218",
4
4
  "description": "Command-line interface for MemNexus Core API",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -34,7 +34,7 @@
34
34
  "node": ">=18.0.0"
35
35
  },
36
36
  "dependencies": {
37
- "@memnexus-ai/typescript-sdk": "^1.60.3",
37
+ "@memnexus-ai/typescript-sdk": "^1.60.7",
38
38
  "@modelcontextprotocol/sdk": "^1.27.1",
39
39
  "axios": "^1.13.6",
40
40
  "chalk": "^5.3.0",