@hasna/terminal 0.8.0 → 1.0.0

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/cli.js CHANGED
@@ -178,7 +178,9 @@ if (args[0] === "exec") {
178
178
  // Command failed — parse error output for structured diagnosis
179
179
  const stderr = e.stderr?.toString() ?? "";
180
180
  const stdout = e.stdout?.toString() ?? "";
181
- const errorOutput = stripNoise(stripAnsi(stdout + stderr)).cleaned;
181
+ // Deduplicate: if stderr content appears in stdout, skip it
182
+ const combined = stderr && stdout.includes(stderr.trim()) ? stdout : stdout + stderr;
183
+ const errorOutput = stripNoise(stripAnsi(combined)).cleaned;
182
184
  // Try structured error parsing
183
185
  const { errorParser } = await import("./parsers/errors.js");
184
186
  if (errorOutput.length > 200 && errorParser.detect(actualCmd, errorOutput)) {
@@ -33,6 +33,21 @@ const NOISE_PATTERNS = [
33
33
  // Generic download/upload progress
34
34
  /^\s*\d+(\.\d+)?\s*[KMG]?B\s*\/\s*\d+(\.\d+)?\s*[KMG]?B\b/,
35
35
  ];
36
+ // Sensitive env var patterns — redact values, keep names only if needed
37
+ const SENSITIVE_PATTERNS = [
38
+ /^(.*(?:KEY|TOKEN|SECRET|PASSWORD|CREDENTIAL|AUTH).*?)=(.+)$/i,
39
+ /^(.*(?:API_KEY|ACCESS_KEY|PRIVATE_KEY|CLIENT_SECRET).*?)=(.+)$/i,
40
+ ];
41
+ /** Redact sensitive values in output (env vars, credentials) */
42
+ function redactSensitive(line) {
43
+ for (const pattern of SENSITIVE_PATTERNS) {
44
+ const match = line.match(pattern);
45
+ if (match) {
46
+ return `${match[1]}=[REDACTED]`;
47
+ }
48
+ }
49
+ return line;
50
+ }
36
51
  /** Strip noise lines from output. Returns cleaned output + count of lines removed. */
37
52
  export function stripNoise(output) {
38
53
  const lines = output.split("\n");
@@ -64,7 +79,8 @@ export function stripNoise(output) {
64
79
  kept.push(parts[parts.length - 1]);
65
80
  continue;
66
81
  }
67
- kept.push(line);
82
+ // Redact sensitive values (env vars with KEY, TOKEN, SECRET, etc.)
83
+ kept.push(redactSensitive(line));
68
84
  }
69
85
  return { cleaned: kept.join("\n"), linesRemoved: removed };
70
86
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/terminal",
3
- "version": "0.8.0",
3
+ "version": "1.0.0",
4
4
  "description": "Smart terminal wrapper for AI agents and humans — structured output, token compression, MCP server, natural language",
5
5
  "type": "module",
6
6
  "bin": {
package/src/cli.tsx CHANGED
@@ -181,7 +181,9 @@ if (args[0] === "exec") {
181
181
  // Command failed — parse error output for structured diagnosis
182
182
  const stderr = e.stderr?.toString() ?? "";
183
183
  const stdout = e.stdout?.toString() ?? "";
184
- const errorOutput = stripNoise(stripAnsi(stdout + stderr)).cleaned;
184
+ // Deduplicate: if stderr content appears in stdout, skip it
185
+ const combined = stderr && stdout.includes(stderr.trim()) ? stdout : stdout + stderr;
186
+ const errorOutput = stripNoise(stripAnsi(combined)).cleaned;
185
187
 
186
188
  // Try structured error parsing
187
189
  const { errorParser } = await import("./parsers/errors.js");
@@ -41,6 +41,23 @@ const NOISE_PATTERNS: RegExp[] = [
41
41
  /^\s*\d+(\.\d+)?\s*[KMG]?B\s*\/\s*\d+(\.\d+)?\s*[KMG]?B\b/,
42
42
  ];
43
43
 
44
+ // Sensitive env var patterns — redact values, keep names only if needed
45
+ const SENSITIVE_PATTERNS = [
46
+ /^(.*(?:KEY|TOKEN|SECRET|PASSWORD|CREDENTIAL|AUTH).*?)=(.+)$/i,
47
+ /^(.*(?:API_KEY|ACCESS_KEY|PRIVATE_KEY|CLIENT_SECRET).*?)=(.+)$/i,
48
+ ];
49
+
50
+ /** Redact sensitive values in output (env vars, credentials) */
51
+ function redactSensitive(line: string): string {
52
+ for (const pattern of SENSITIVE_PATTERNS) {
53
+ const match = line.match(pattern);
54
+ if (match) {
55
+ return `${match[1]}=[REDACTED]`;
56
+ }
57
+ }
58
+ return line;
59
+ }
60
+
44
61
  /** Strip noise lines from output. Returns cleaned output + count of lines removed. */
45
62
  export function stripNoise(output: string): { cleaned: string; linesRemoved: number } {
46
63
  const lines = output.split("\n");
@@ -76,7 +93,8 @@ export function stripNoise(output: string): { cleaned: string; linesRemoved: num
76
93
  continue;
77
94
  }
78
95
 
79
- kept.push(line);
96
+ // Redact sensitive values (env vars with KEY, TOKEN, SECRET, etc.)
97
+ kept.push(redactSensitive(line));
80
98
  }
81
99
 
82
100
  return { cleaned: kept.join("\n"), linesRemoved: removed };