@hasna/terminal 3.3.5 → 3.3.7

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.
@@ -64,6 +64,12 @@ function smartTruncate(text, maxTokens) {
64
64
  export function compress(command, output, options = {}) {
65
65
  const { maxTokens, stripAnsi: doStrip = true } = options;
66
66
  const originalTokens = estimateTokens(output);
67
+ // Short output — no-op, skip all processing
68
+ if (output.split("\n").length <= 20 && !maxTokens) {
69
+ const clean = doStrip ? stripAnsi(output) : output;
70
+ const cleanTokens = estimateTokens(clean);
71
+ return { content: clean, originalTokens, compressedTokens: cleanTokens, tokensSaved: Math.max(0, originalTokens - cleanTokens), savingsPercent: 0 };
72
+ }
67
73
  // Step 1: Strip ANSI codes
68
74
  let text = doStrip ? stripAnsi(output) : output;
69
75
  // Step 2: Deduplicate similar lines
@@ -232,8 +232,8 @@ export function createServer() {
232
232
  return { content: [{ type: "text", text: JSON.stringify(result) }] };
233
233
  });
234
234
  // ── search_semantic: AST-powered code search ───────────────────────────────
235
- server.tool("search_semantic", "Semantic code search — find functions, classes, components, hooks, types by meaning. Uses AST parsing, not string matching. Much more precise than grep for code navigation.", {
236
- query: z.string().describe("What to search for (e.g., 'auth functions', 'React components', 'database hooks')"),
235
+ server.tool("search_semantic", "Find functions, classes, components, hooks, types by NAME or SIGNATURE. Searches symbol declarations, NOT code behavior or content. Use search_content (grep) instead for pattern matching inside code (e.g., security audits, string searches, imports).", {
236
+ query: z.string().describe("Symbol name to search for (e.g., 'auth', 'login', 'UserService'). Matches function/class/type names, not code content."),
237
237
  path: z.string().optional().describe("Search root (default: cwd)"),
238
238
  kinds: z.array(z.enum(["function", "class", "interface", "type", "variable", "export", "import", "component", "hook"])).optional().describe("Filter by symbol kind"),
239
239
  exportedOnly: z.boolean().optional().describe("Only show exported symbols (default: false)"),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/terminal",
3
- "version": "3.3.5",
3
+ "version": "3.3.7",
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": [
@@ -89,6 +89,13 @@ export function compress(command: string, output: string, options: CompressOptio
89
89
  const { maxTokens, stripAnsi: doStrip = true } = options;
90
90
  const originalTokens = estimateTokens(output);
91
91
 
92
+ // Short output — no-op, skip all processing
93
+ if (output.split("\n").length <= 20 && !maxTokens) {
94
+ const clean = doStrip ? stripAnsi(output) : output;
95
+ const cleanTokens = estimateTokens(clean);
96
+ return { content: clean, originalTokens, compressedTokens: cleanTokens, tokensSaved: Math.max(0, originalTokens - cleanTokens), savingsPercent: 0 };
97
+ }
98
+
92
99
  // Step 1: Strip ANSI codes
93
100
  let text = doStrip ? stripAnsi(output) : output;
94
101
 
package/src/mcp/server.ts CHANGED
@@ -301,9 +301,9 @@ export function createServer(): McpServer {
301
301
 
302
302
  server.tool(
303
303
  "search_semantic",
304
- "Semantic code search — find functions, classes, components, hooks, types by meaning. Uses AST parsing, not string matching. Much more precise than grep for code navigation.",
304
+ "Find functions, classes, components, hooks, types by NAME or SIGNATURE. Searches symbol declarations, NOT code behavior or content. Use search_content (grep) instead for pattern matching inside code (e.g., security audits, string searches, imports).",
305
305
  {
306
- query: z.string().describe("What to search for (e.g., 'auth functions', 'React components', 'database hooks')"),
306
+ query: z.string().describe("Symbol name to search for (e.g., 'auth', 'login', 'UserService'). Matches function/class/type names, not code content."),
307
307
  path: z.string().optional().describe("Search root (default: cwd)"),
308
308
  kinds: z.array(z.enum(["function", "class", "interface", "type", "variable", "export", "import", "component", "hook"])).optional().describe("Filter by symbol kind"),
309
309
  exportedOnly: z.boolean().optional().describe("Only show exported symbols (default: false)"),