@hasna/terminal 3.3.7 → 3.3.9

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.
@@ -60,7 +60,7 @@ export function createServer() {
60
60
  version: "0.2.0",
61
61
  });
62
62
  // ── execute: run a command, return structured result ──────────────────────
63
- server.tool("execute", "Run a shell command and return raw output. Prefer execute_smart for most tasks it AI-summarizes output, saving 80% tokens. Use execute only when you need the full unprocessed output (e.g., to parse it yourself).", {
63
+ server.tool("execute", "Run a shell command. Format guide: no format/raw for git commit/push (<50 tokens). format=compressed for long build output (CPU-only, no AI). format=json or format=summary for AI-summarized output (234ms, saves 80% tokens). Prefer execute_smart for most tasks.", {
64
64
  command: z.string().describe("Shell command to execute"),
65
65
  cwd: z.string().optional().describe("Working directory (default: server cwd)"),
66
66
  timeout: z.number().optional().describe("Timeout in ms (default: 30000)"),
@@ -123,7 +123,7 @@ export function createServer() {
123
123
  return {
124
124
  content: [{ type: "text", text: JSON.stringify({
125
125
  exitCode: result.exitCode, output: compressed.content, duration: result.duration,
126
- tokensSaved: compressed.tokensSaved, savingsPercent: compressed.savingsPercent,
126
+ ...(compressed.tokensSaved > 0 ? { tokensSaved: compressed.tokensSaved, savingsPercent: compressed.savingsPercent } : {}),
127
127
  }) }],
128
128
  };
129
129
  }
@@ -54,9 +54,11 @@ export async function searchContent(pattern, cwd, options = {}) {
54
54
  const totalMatches = [...fileMap.values()].reduce((sum, m) => sum + m.length, 0);
55
55
  const filtered = filteredCount > 0 ? [{ count: filteredCount, reason: "excluded directories" }] : [];
56
56
  const rawTokens = Math.ceil(raw.length / 4);
57
+ const truncated = totalMatches > files.reduce((s, f) => s + f.matches.length, 0);
57
58
  const result = { query: pattern, totalMatches, files, filtered };
58
59
  const resultTokens = Math.ceil(JSON.stringify(result).length / 4);
59
60
  result.tokensSaved = Math.max(0, rawTokens - resultTokens);
61
+ result.truncated = truncated;
60
62
  // Overflow guard — warn when results are truncated
61
63
  if (totalMatches > maxResults * 3) {
62
64
  result.overflow = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/terminal",
3
- "version": "3.3.7",
3
+ "version": "3.3.9",
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
  "files": [
package/src/mcp/server.ts CHANGED
@@ -69,7 +69,7 @@ export function createServer(): McpServer {
69
69
 
70
70
  server.tool(
71
71
  "execute",
72
- "Run a shell command and return raw output. Prefer execute_smart for most tasks it AI-summarizes output, saving 80% tokens. Use execute only when you need the full unprocessed output (e.g., to parse it yourself).",
72
+ "Run a shell command. Format guide: no format/raw for git commit/push (<50 tokens). format=compressed for long build output (CPU-only, no AI). format=json or format=summary for AI-summarized output (234ms, saves 80% tokens). Prefer execute_smart for most tasks.",
73
73
  {
74
74
  command: z.string().describe("Shell command to execute"),
75
75
  cwd: z.string().optional().describe("Working directory (default: server cwd)"),
@@ -136,7 +136,7 @@ export function createServer(): McpServer {
136
136
  return {
137
137
  content: [{ type: "text" as const, text: JSON.stringify({
138
138
  exitCode: result.exitCode, output: compressed.content, duration: result.duration,
139
- tokensSaved: compressed.tokensSaved, savingsPercent: compressed.savingsPercent,
139
+ ...(compressed.tokensSaved > 0 ? { tokensSaved: compressed.tokensSaved, savingsPercent: compressed.savingsPercent } : {}),
140
140
  }) }],
141
141
  };
142
142
  }
@@ -89,9 +89,11 @@ export async function searchContent(
89
89
  const filtered = filteredCount > 0 ? [{ count: filteredCount, reason: "excluded directories" }] : [];
90
90
 
91
91
  const rawTokens = Math.ceil(raw.length / 4);
92
+ const truncated = totalMatches > files.reduce((s, f) => s + f.matches.length, 0);
92
93
  const result: ContentSearchResult = { query: pattern, totalMatches, files, filtered };
93
94
  const resultTokens = Math.ceil(JSON.stringify(result).length / 4);
94
95
  result.tokensSaved = Math.max(0, rawTokens - resultTokens);
96
+ (result as any).truncated = truncated;
95
97
 
96
98
  // Overflow guard — warn when results are truncated
97
99
  if (totalMatches > maxResults * 3) {