@hasna/terminal 0.7.1 → 0.7.2

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
@@ -151,10 +151,30 @@ if (args[0] === "exec") {
151
151
  }
152
152
  }
153
153
  catch (e) {
154
- // Command failed — show error output
154
+ // Command failed — parse error output for structured diagnosis
155
155
  const stderr = e.stderr?.toString() ?? "";
156
156
  const stdout = e.stdout?.toString() ?? "";
157
- console.log(stripNoise(stripAnsi(stdout + stderr)).cleaned);
157
+ const errorOutput = stripNoise(stripAnsi(stdout + stderr)).cleaned;
158
+ // Try structured error parsing
159
+ const { errorParser } = await import("./parsers/errors.js");
160
+ if (errorOutput.length > 200 && errorParser.detect(actualCmd, errorOutput)) {
161
+ const info = errorParser.parse(actualCmd, errorOutput);
162
+ if (jsonMode) {
163
+ console.log(JSON.stringify({ exitCode: e.status ?? 1, error: info }));
164
+ }
165
+ else {
166
+ console.log(`Error: ${info.type}`);
167
+ console.log(` ${info.message}`);
168
+ if (info.file)
169
+ console.log(` File: ${info.file}${info.line ? `:${info.line}` : ""}`);
170
+ if (info.suggestion)
171
+ console.log(` Fix: ${info.suggestion}`);
172
+ }
173
+ }
174
+ else {
175
+ // Short error or no parser match — pass through cleaned
176
+ console.log(errorOutput);
177
+ }
158
178
  process.exit(e.status ?? 1);
159
179
  }
160
180
  process.exit(0);
@@ -7,6 +7,19 @@ export const gitLogParser = {
7
7
  parse(_command, output) {
8
8
  const entries = [];
9
9
  const lines = output.split("\n");
10
+ // Detect oneline format: "abc1234 commit message"
11
+ const firstLine = lines[0]?.trim() ?? "";
12
+ const isOneline = /^[a-f0-9]{7,12}\s+/.test(firstLine) && !firstLine.startsWith("commit ");
13
+ if (isOneline) {
14
+ for (const line of lines) {
15
+ const match = line.trim().match(/^([a-f0-9]{7,12})\s+(.+)$/);
16
+ if (match) {
17
+ entries.push({ hash: match[1], author: "", date: "", message: match[2] });
18
+ }
19
+ }
20
+ return entries;
21
+ }
22
+ // Verbose format
10
23
  let hash = "", author = "", date = "", message = [];
11
24
  for (const line of lines) {
12
25
  const commitMatch = line.match(/^commit\s+([a-f0-9]+)/);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/terminal",
3
- "version": "0.7.1",
3
+ "version": "0.7.2",
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
@@ -155,10 +155,27 @@ if (args[0] === "exec") {
155
155
  console.error(`[open-terminal] saved ${savedTokens} tokens (noise filter)`);
156
156
  }
157
157
  } catch (e: any) {
158
- // Command failed — show error output
158
+ // Command failed — parse error output for structured diagnosis
159
159
  const stderr = e.stderr?.toString() ?? "";
160
160
  const stdout = e.stdout?.toString() ?? "";
161
- console.log(stripNoise(stripAnsi(stdout + stderr)).cleaned);
161
+ const errorOutput = stripNoise(stripAnsi(stdout + stderr)).cleaned;
162
+
163
+ // Try structured error parsing
164
+ const { errorParser } = await import("./parsers/errors.js");
165
+ if (errorOutput.length > 200 && errorParser.detect(actualCmd, errorOutput)) {
166
+ const info = errorParser.parse(actualCmd, errorOutput);
167
+ if (jsonMode) {
168
+ console.log(JSON.stringify({ exitCode: e.status ?? 1, error: info }));
169
+ } else {
170
+ console.log(`Error: ${info.type}`);
171
+ console.log(` ${info.message}`);
172
+ if (info.file) console.log(` File: ${info.file}${info.line ? `:${info.line}` : ""}`);
173
+ if (info.suggestion) console.log(` Fix: ${info.suggestion}`);
174
+ }
175
+ } else {
176
+ // Short error or no parser match — pass through cleaned
177
+ console.log(errorOutput);
178
+ }
162
179
  process.exit(e.status ?? 1);
163
180
  }
164
181
  process.exit(0);
@@ -13,6 +13,21 @@ export const gitLogParser: Parser<GitLogEntry[]> = {
13
13
  const entries: GitLogEntry[] = [];
14
14
  const lines = output.split("\n");
15
15
 
16
+ // Detect oneline format: "abc1234 commit message"
17
+ const firstLine = lines[0]?.trim() ?? "";
18
+ const isOneline = /^[a-f0-9]{7,12}\s+/.test(firstLine) && !firstLine.startsWith("commit ");
19
+
20
+ if (isOneline) {
21
+ for (const line of lines) {
22
+ const match = line.trim().match(/^([a-f0-9]{7,12})\s+(.+)$/);
23
+ if (match) {
24
+ entries.push({ hash: match[1], author: "", date: "", message: match[2] });
25
+ }
26
+ }
27
+ return entries;
28
+ }
29
+
30
+ // Verbose format
16
31
  let hash = "", author = "", date = "", message: string[] = [];
17
32
 
18
33
  for (const line of lines) {