@unikode/cli 1.0.8 → 1.0.10

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.
Files changed (2) hide show
  1. package/dist/index.js +50 -35
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -971,6 +971,9 @@ var SUPPORTED_CHAT_MODELS = [
971
971
  }
972
972
  }
973
973
  ];
974
+ function findSupportedChatModel(modelId) {
975
+ return SUPPORTED_CHAT_MODELS.find((model) => model.id === modelId);
976
+ }
974
977
  var DEFAULT_CHAT_MODEL_ID = "gemini-2.5-flash";
975
978
  // ../shared/src/schemas.ts
976
979
  import { z } from "zod";
@@ -1007,10 +1010,10 @@ var toolInputSchemas = {
1007
1010
  oldString: z.string().describe("Exact text to replace; must be unique"),
1008
1011
  newString: z.string().describe("Replacement text")
1009
1012
  }),
1010
- bash: z.object({
1011
- command: z.string().describe("Shell command to run"),
1012
- description: z.string().optional().describe("Short description of the command"),
1013
- timeout: z.number().optional().describe("Timeout in milliseconds")
1013
+ terminalTool: z.object({
1014
+ command: z.string().describe("The terminal command to execute (using Windows PowerShell or CMD syntax)."),
1015
+ cwd: z.string().optional().describe("The working directory for execution. Defaults to the current project root."),
1016
+ explanation: z.string().describe("A 1-sentence explanation of why this command is being run, for logging and user transparency.")
1014
1017
  }),
1015
1018
  webSearchTool: z.object({
1016
1019
  query: z.string().describe("The search query. Keep it short and specific (3-8 words works best)."),
@@ -1130,9 +1133,9 @@ var buildToolContracts = {
1130
1133
  description: "Replace exact text in a file under the current project directory.",
1131
1134
  inputSchema: toolInputSchemas.editFile
1132
1135
  }),
1133
- bash: tool({
1134
- description: "Run a shell command in the current project directory.",
1135
- inputSchema: toolInputSchemas.bash
1136
+ terminalTool: tool({
1137
+ description: "Execute a terminal command on the local Windows system. Use this to run CLI tools, navigate the filesystem, manage packages, or execute scripts. Do NOT use interactive commands that require user input (e.g., 'npm init' or interactive git rebases).",
1138
+ inputSchema: toolInputSchemas.terminalTool
1136
1139
  }),
1137
1140
  undoLastEditSchema: tool({
1138
1141
  description: "Reverts the specified file to its exact state before the most recent modification. Use this immediately if your last edit introduced syntax errors, broke tests, or failed to solve the issue.",
@@ -1359,14 +1362,19 @@ var ModelsDialogContent = ({ models, onSelectModel }) => {
1359
1362
  onSelectModel(modelId);
1360
1363
  dialog.close();
1361
1364
  }, [dialog, onSelectModel]);
1365
+ const getDisplayName = useCallback7((modelId) => {
1366
+ const model = findSupportedChatModel(modelId);
1367
+ const isLocal = model ? model.provider === "local-docker" || model.provider === "local-ollama" : false;
1368
+ return isLocal ? `${modelId} (L)` : modelId;
1369
+ }, []);
1362
1370
  return /* @__PURE__ */ jsxDEV10(DialogSearchList, {
1363
1371
  items: models,
1364
1372
  onSelect: handleSelect,
1365
- filterFn: (modelId, query) => modelId.toLowerCase().includes(query.toLowerCase()),
1373
+ filterFn: (modelId, query) => getDisplayName(modelId).toLowerCase().includes(query.toLowerCase()),
1366
1374
  renderItem: (modelId, isSelected) => /* @__PURE__ */ jsxDEV10("text", {
1367
1375
  selectable: false,
1368
1376
  fg: isSelected ? "black" : "white",
1369
- children: modelId
1377
+ children: getDisplayName(modelId)
1370
1378
  }, undefined, false, undefined, this),
1371
1379
  getKey: (modelId) => modelId,
1372
1380
  placeholder: "Search models",
@@ -3402,11 +3410,14 @@ import fs from "fs/promises";
3402
3410
  import path from "path";
3403
3411
  import { createReadStream } from "fs";
3404
3412
  import readline from "readline";
3413
+ import { exec } from "child_process";
3414
+ import { promisify } from "util";
3415
+ var execAsync = promisify(exec);
3416
+ var DEFAULT_TIMEOUT_MS = 120000;
3417
+ var MAX_BUFFER_SIZE = 1024 * 1024 * 5;
3405
3418
  var MAX_FILE_SIZE = 1e4;
3406
3419
  var MAX_RESULTS = 200;
3407
3420
  var MAX_MATCHES = 50;
3408
- var MAX_OUTPUT = 20000;
3409
- var DEFAULT_TIMEOUT = 30000;
3410
3421
  var MAX_CONTENT_LENGTH = 15000;
3411
3422
  var FETCH_TIMEOUT_MS = 1e4;
3412
3423
  var turndownService = new TurndownService({
@@ -3428,10 +3439,6 @@ function recordEdit(resolvedPath, oldString, newString) {
3428
3439
  stack.push({ oldString, newString });
3429
3440
  editHistory.set(resolvedPath, stack);
3430
3441
  }
3431
- function truncate(value, limit) {
3432
- return value.length > limit ? `${value.slice(0, limit)}
3433
- ... (truncated, ${value.length} total chars)` : value;
3434
- }
3435
3442
  async function countLines(filePath) {
3436
3443
  return new Promise((resolve3, reject) => {
3437
3444
  let lines = 0;
@@ -3563,26 +3570,34 @@ async function executeLocalTool(toolName, input, mode) {
3563
3570
  recordEdit(resolved, oldString, newString);
3564
3571
  return { success: true, path: relative2(cwd, resolved) };
3565
3572
  }
3566
- case "bash": {
3567
- const { command, timeout = DEFAULT_TIMEOUT } = toolInputSchemas.bash.parse(input);
3568
- const proc = Bun.spawn(["bash", "-c", command], {
3569
- cwd: resolveInsideCwd(".").resolved,
3570
- stdout: "pipe",
3571
- stderr: "pipe",
3572
- env: { ...process.env, TERM: "dumb" }
3573
- });
3574
- const timer = setTimeout(() => proc.kill(), timeout);
3575
- const [stdout, stderr] = await Promise.all([
3576
- new Response(proc.stdout).text(),
3577
- new Response(proc.stderr).text()
3578
- ]);
3579
- const exitCode = await proc.exited;
3580
- clearTimeout(timer);
3581
- return {
3582
- stdout: truncate(stdout, MAX_OUTPUT),
3583
- stderr: truncate(stderr, MAX_OUTPUT),
3584
- exitCode
3585
- };
3573
+ case "terminalTool": {
3574
+ const { command, cwd, explanation } = toolInputSchemas.terminalTool.parse(input);
3575
+ const targetDir = cwd ? path.resolve(process.cwd(), cwd) : process.cwd();
3576
+ try {
3577
+ const { stdout, stderr } = await execAsync(command, {
3578
+ cwd: targetDir,
3579
+ timeout: DEFAULT_TIMEOUT_MS,
3580
+ maxBuffer: MAX_BUFFER_SIZE,
3581
+ windowsHide: true
3582
+ });
3583
+ return {
3584
+ success: true,
3585
+ cwd: targetDir,
3586
+ explanation,
3587
+ output: stdout.trim() || "Command executed successfully with no output.",
3588
+ error: stderr.trim() || null
3589
+ };
3590
+ } catch (error) {
3591
+ const isTimeout = error.killed && error.signal === "SIGTERM";
3592
+ return {
3593
+ success: false,
3594
+ cwd: targetDir,
3595
+ explanation,
3596
+ exitCode: error.code ?? -1,
3597
+ output: error.stdout?.toString().trim() || null,
3598
+ error: isTimeout ? `Command timed out after ${DEFAULT_TIMEOUT_MS / 1000} seconds. Did you run an interactive command?` : error.stderr?.toString().trim() || error.message || "Unknown execution error"
3599
+ };
3600
+ }
3586
3601
  }
3587
3602
  case "webSearchTool": {
3588
3603
  const { query, searchDepth, maxResults, includeAnswer } = toolInputSchemas.webSearchTool.parse(input);
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@unikode/cli",
3
- "version": "1.0.8",
3
+ "version": "1.0.10",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "bin": {
7
- "Claude-Code-Clone": "./bin/Claude-Code-Clone"
7
+ "unikode": "./bin/Claude-Code-Clone"
8
8
  },
9
9
  "files": [
10
10
  "dist",