jinzd-ai-cli 0.4.200 → 0.4.202

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 (66) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +435 -435
  3. package/README.zh-CN.md +450 -450
  4. package/dist/agent-client-6GX6QQDU.js +0 -0
  5. package/dist/auth-FSTAKSYF.js +0 -0
  6. package/dist/{batch-5N4CXARG.js → batch-UF4EWYFD.js} +2 -2
  7. package/dist/chat-index-FDSGKWQV.js +0 -0
  8. package/dist/{chunk-JP6ESDV7.js → chunk-2NINHXEZ.js} +13 -1
  9. package/dist/{chunk-FQF6YJ6F.js → chunk-2YLYDFEX.js} +55 -14
  10. package/dist/chunk-4BKXL7SM.js +0 -0
  11. package/dist/chunk-5UR6ZOF4.js +0 -0
  12. package/dist/{chunk-HUTS2F6Y.js → chunk-75SUTNYY.js} +1 -1
  13. package/dist/chunk-A4GUGWEY.js +0 -0
  14. package/dist/chunk-BXP6YZ2P.js +0 -0
  15. package/dist/chunk-CITDVXXM.js +0 -0
  16. package/dist/chunk-CKH4KQ4E.js +0 -0
  17. package/dist/chunk-E44DTERW.js +0 -0
  18. package/dist/{chunk-JZCXULOJ.js → chunk-GOKVKOG3.js} +1 -1
  19. package/dist/chunk-HLWUDRBO.js +0 -0
  20. package/dist/chunk-HOSJZMQS.js +0 -0
  21. package/dist/{chunk-IDMCBIYZ.js → chunk-HZKC424D.js} +1 -1
  22. package/dist/chunk-IW3Q7AE5.js +0 -0
  23. package/dist/{chunk-NULOZSFA.js → chunk-JCY7RQIA.js} +1 -1
  24. package/dist/chunk-JVKAL5Q3.js +0 -0
  25. package/dist/chunk-KHYD3WXE.js +0 -0
  26. package/dist/chunk-MC34ISJU.js +0 -0
  27. package/dist/chunk-NZ4X6GUC.js +0 -0
  28. package/dist/chunk-O6UFCEUZ.js +0 -0
  29. package/dist/chunk-OJL3PY36.js +0 -0
  30. package/dist/{chunk-5SA7IACI.js → chunk-Q2MBPMTW.js} +2 -2
  31. package/dist/chunk-Q3ZUDA6S.js +0 -0
  32. package/dist/{chunk-2G62CKDL.js → chunk-SB77W6XS.js} +1 -1
  33. package/dist/chunk-SLSWPBK3.js +0 -0
  34. package/dist/chunk-T2NL5ZIA.js +0 -0
  35. package/dist/chunk-TB4W4Y4T.js +0 -0
  36. package/dist/chunk-TZQHYZKT.js +0 -0
  37. package/dist/{chunk-TBGVHRCL.js → chunk-Y6U6FMVV.js} +1 -1
  38. package/dist/{ci-2ZSBYWJE.js → ci-YOJTTP4J.js} +3 -3
  39. package/dist/{constants-GMPGZM4D.js → constants-VP7TYJL7.js} +1 -1
  40. package/dist/{doctor-cli-PG52ECBH.js → doctor-cli-PCIKXTNV.js} +5 -5
  41. package/dist/electron-server.js +67 -14
  42. package/dist/file-checkpoint-NKBHGC7L.js +0 -0
  43. package/dist/git-context-EXOEHQSF.js +0 -0
  44. package/dist/{hub-AI4ICH5E.js → hub-N2ZRAXRO.js} +1 -1
  45. package/dist/hub-server-LJ2JSKZ2.js +0 -0
  46. package/dist/index.js +17 -17
  47. package/dist/indexer-AKWMYNJI.js +0 -0
  48. package/dist/persist-L54DPLI7.js +0 -0
  49. package/dist/project-trust-NKYHL3VZ.js +0 -0
  50. package/dist/{run-tests-G2MCAQJL.js → run-tests-AXPZOPX7.js} +1 -1
  51. package/dist/{run-tests-NUWLWMHZ.js → run-tests-RNU733RF.js} +2 -2
  52. package/dist/semantic-PK7AUOJT.js +0 -0
  53. package/dist/{server-Y3XEAXTC.js → server-SLFGYGBO.js} +8 -8
  54. package/dist/{server-74PZ2PDM.js → server-YIBPZJ34.js} +28 -11
  55. package/dist/store-MWNHVGJT.js +0 -0
  56. package/dist/{task-orchestrator-IF3XCVZ7.js → task-orchestrator-FM4EXIBZ.js} +4 -4
  57. package/dist/{usage-7BAT3772.js → usage-QFW2XPF3.js} +2 -2
  58. package/dist/vector-store-BBDXB5IQ.js +0 -0
  59. package/dist/wasm/web-tree-sitter.wasm +0 -0
  60. package/dist/web/client/app.js +3351 -3351
  61. package/dist/web/client/icon.svg +22 -22
  62. package/dist/web/client/index.html +360 -360
  63. package/dist/web/client/manifest.json +15 -15
  64. package/dist/web/client/style.css +991 -991
  65. package/dist/web/client/sw.js +86 -86
  66. package/package.json +1 -1
File without changes
File without changes
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  ConfigManager
4
- } from "./chunk-NULOZSFA.js";
4
+ } from "./chunk-JCY7RQIA.js";
5
5
  import "./chunk-TZQHYZKT.js";
6
- import "./chunk-IDMCBIYZ.js";
6
+ import "./chunk-HZKC424D.js";
7
7
  import {
8
8
  atomicWriteFileSync
9
9
  } from "./chunk-IW3Q7AE5.js";
File without changes
@@ -925,6 +925,18 @@ function toUsage(u) {
925
925
  if (cached > 0) usage.cacheReadTokens = cached;
926
926
  return usage;
927
927
  }
928
+ function isLoopbackBaseUrl(baseUrl) {
929
+ if (!baseUrl) return false;
930
+ let host;
931
+ try {
932
+ host = new URL(baseUrl).hostname;
933
+ } catch {
934
+ return false;
935
+ }
936
+ host = host.replace(/^\[|\]$/g, "").toLowerCase();
937
+ if (host === "localhost" || host === "::1" || host === "0.0.0.0") return true;
938
+ return /^127(?:\.\d{1,3}){3}$/.test(host);
939
+ }
928
940
  var OpenAICompatibleProvider = class extends BaseProvider {
929
941
  client;
930
942
  defaultTimeout = 6e4;
@@ -940,7 +952,7 @@ var OpenAICompatibleProvider = class extends BaseProvider {
940
952
  baseURL: options?.baseUrl ?? this.defaultBaseUrl,
941
953
  timeout: this.defaultTimeout
942
954
  };
943
- const proxyUrl = options?.proxy;
955
+ const proxyUrl = isLoopbackBaseUrl(clientOptions.baseURL) ? void 0 : options?.proxy;
944
956
  try {
945
957
  const { Agent, ProxyAgent, fetch: undiciFetch } = await import("undici");
946
958
  const STREAM_BODY_TIMEOUT = 30 * 60 * 1e3;
@@ -5,10 +5,10 @@ import {
5
5
  } from "./chunk-T2NL5ZIA.js";
6
6
  import {
7
7
  runTestsTool
8
- } from "./chunk-HUTS2F6Y.js";
8
+ } from "./chunk-75SUTNYY.js";
9
9
  import {
10
10
  runTool
11
- } from "./chunk-JZCXULOJ.js";
11
+ } from "./chunk-GOKVKOG3.js";
12
12
  import {
13
13
  getDangerLevel,
14
14
  isFileWriteTool,
@@ -26,7 +26,7 @@ import {
26
26
  SUBAGENT_ALLOWED_TOOLS,
27
27
  SUBAGENT_DEFAULT_MAX_ROUNDS,
28
28
  SUBAGENT_MAX_ROUNDS_LIMIT
29
- } from "./chunk-IDMCBIYZ.js";
29
+ } from "./chunk-HZKC424D.js";
30
30
  import {
31
31
  fileCheckpoints
32
32
  } from "./chunk-4BKXL7SM.js";
@@ -222,12 +222,12 @@ Important rules:
222
222
  3. Multiple commands can be combined with semicolons in a single call to reduce rounds.
223
223
  4. To delete directories, use Remove-Item -Recurse (the system will automatically optimize to a more reliable method).
224
224
  5. IMPORTANT: On Windows, "curl" is an alias for Invoke-WebRequest and does NOT support curl flags like -s, -X, -H. Use Invoke-RestMethod instead for HTTP requests. Example: Invoke-RestMethod -Uri "http://localhost:3000/api/health" -Method Get
225
- 6. For long-running server commands (node server.js, npm run dev, etc.), use Start-Process -NoNewWindow to run in background, otherwise the tool will block until timeout.` : `Execute commands in ${SHELL}.
225
+ 6. NEVER run long-running / never-exiting commands through bash \u2014 they block until timeout. This includes starting an Android emulator (emulator -avd X), streaming logs (adb logcat), and dev servers (node server.js, npm run dev, metro / react-native start). Use the 'task_create' tool to run these in the background, then poll status with short bash calls (e.g. adb shell getprop sys.boot_completed).` : `Execute commands in ${SHELL}.
226
226
  Important rules:
227
227
  1. Each bash call runs in an independent subprocess; cd commands do not persist. To run in a specific directory, use the cwd parameter, or combine commands: e.g. "cd mydir && ls" or "mkdir -p mydir && touch mydir/file.txt".
228
228
  2. If a command fails (returns an error or non-zero exit code), stop immediately, report the error to the user, and do not retry the same or similar commands.
229
229
  3. Multiple commands can be combined with && in a single call to reduce rounds.
230
- 4. For long-running server commands (node server.js, npm start, npm run dev, etc.), run in background with & or nohup, otherwise the tool will block until timeout.`,
230
+ 4. NEVER run long-running / never-exiting commands through bash \u2014 they block until timeout. This includes starting an Android emulator (emulator -avd X), streaming logs (adb logcat), and dev servers (node server.js, npm run dev, metro / react-native start). Use the 'task_create' tool to run these in the background, then poll status with short bash calls (e.g. adb shell getprop sys.boot_completed).`,
231
231
  parameters: {
232
232
  command: {
233
233
  type: "string",
@@ -256,6 +256,10 @@ Important rules:
256
256
  if (!command.trim()) {
257
257
  throw new ToolError("bash", "command is required");
258
258
  }
259
+ const blockingHint = detectBlockingCommand(command);
260
+ if (blockingHint) {
261
+ throw new ToolError("bash", blockingHint);
262
+ }
259
263
  let currentCwd = getCwd();
260
264
  if (!existsSync2(currentCwd)) {
261
265
  const fallback = process.cwd();
@@ -442,6 +446,28 @@ function buildErrorHint(command, stderr) {
442
446
  }
443
447
  return hints.length > 0 ? hints.map((h) => `\u{1F4A1} ${h}`).join("\n\n") : null;
444
448
  }
449
+ function detectBlockingCommand(command) {
450
+ if (/\bemulator(?:\.exe)?\b/i.test(command) && /(?:^|\s)(?:-avd\b|@[\w.-]+)/.test(command)) {
451
+ return blockingMessage("emulator -avd <name>", "launch an Android emulator");
452
+ }
453
+ const logcat = command.match(/\badb\b[^|;&\n]*\blogcat\b([^|;&\n]*)/i);
454
+ if (logcat && !/(?:^|\s)-(?:d|t|c|g)\b/.test(logcat[1] ?? "")) {
455
+ return blockingMessage("adb logcat", "stream device logs");
456
+ }
457
+ return null;
458
+ }
459
+ function blockingMessage(example, what) {
460
+ return `This command (${example}) is used to ${what}, which runs forever and never exits on its own. Running it through 'bash' will BLOCK until the tool times out, and the timeout cleanup (taskkill /T) then kills the very emulator/process you just started \u2014 so it can never stay up.
461
+
462
+ Use the 'task_create' tool to run it in the background instead, e.g.:
463
+ task_create(command: "${example} ...", description: "${what}")
464
+
465
+ Then poll readiness with SHORT bash calls (these DO exit), e.g.:
466
+ adb devices # is the device/emulator listed?
467
+ adb shell getprop sys.boot_completed # prints "1" once the emulator is fully booted
468
+
469
+ [Do NOT run this long-running command through bash \u2014 it will hang.]`;
470
+ }
445
471
  function snapshotDir(dir) {
446
472
  try {
447
473
  return new Set(readdirSync(dir).map((name) => resolve(dir, name)));
@@ -4544,15 +4570,30 @@ function stopTask(id) {
4544
4570
  const task = tasks.get(id);
4545
4571
  if (!task || task.status !== "running") return false;
4546
4572
  try {
4547
- task.process.kill("SIGTERM");
4548
- setTimeout(() => {
4549
- if (task.status === "running") {
4550
- try {
4551
- task.process.kill("SIGKILL");
4552
- } catch {
4553
- }
4573
+ const proc = task.process;
4574
+ if (platform3() === "win32" && proc.pid) {
4575
+ try {
4576
+ spawn3("taskkill", ["/PID", String(proc.pid), "/T", "/F"], {
4577
+ windowsHide: true,
4578
+ stdio: "ignore"
4579
+ });
4580
+ } catch {
4554
4581
  }
4555
- }, 3e3);
4582
+ try {
4583
+ proc.kill();
4584
+ } catch {
4585
+ }
4586
+ } else {
4587
+ proc.kill("SIGTERM");
4588
+ setTimeout(() => {
4589
+ if (proc.exitCode === null && proc.signalCode === null) {
4590
+ try {
4591
+ proc.kill("SIGKILL");
4592
+ } catch {
4593
+ }
4594
+ }
4595
+ }, 3e3).unref();
4596
+ }
4556
4597
  task.status = "stopped";
4557
4598
  task.endTime = Date.now();
4558
4599
  return true;
@@ -4565,7 +4606,7 @@ function stopTask(id) {
4565
4606
  var taskCreateTool = {
4566
4607
  definition: {
4567
4608
  name: "task_create",
4568
- description: `Start a command running in the background. Returns a task ID for monitoring with task_list. Use this to run long-running processes (dev servers, builds, tests) while continuing other work.`,
4609
+ description: `Start a command running in the background and return immediately with a task ID (monitor via task_list, stop via task_stop). Use this for ANY long-running or never-exiting command, including: dev servers (npm run dev, metro / react-native start), Android emulator launch (emulator -avd X), device log streaming (adb logcat), file watchers, and builds you want to monitor while continuing other work. Running such commands via 'bash' instead would block until timeout.`,
4569
4610
  parameters: {
4570
4611
  command: {
4571
4612
  type: "string",
File without changes
File without changes
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  TEST_TIMEOUT
4
- } from "./chunk-IDMCBIYZ.js";
4
+ } from "./chunk-HZKC424D.js";
5
5
 
6
6
  // src/tools/builtin/run-tests.ts
7
7
  import { execSync, spawnSync } from "child_process";
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  CONFIG_DIR_NAME
4
- } from "./chunk-IDMCBIYZ.js";
4
+ } from "./chunk-HZKC424D.js";
5
5
  import {
6
6
  atomicWriteFileSync
7
7
  } from "./chunk-IW3Q7AE5.js";
File without changes
File without changes
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/core/constants.ts
4
- var VERSION = "0.4.200";
4
+ var VERSION = "0.4.202";
5
5
  var APP_NAME = "ai-cli";
6
6
  var CONFIG_DIR_NAME = ".aicli";
7
7
  var CONFIG_FILE_NAME = "config.json";
File without changes
@@ -8,7 +8,7 @@ import {
8
8
  CONFIG_FILE_NAME,
9
9
  HISTORY_DIR_NAME,
10
10
  PLUGINS_DIR_NAME
11
- } from "./chunk-IDMCBIYZ.js";
11
+ } from "./chunk-HZKC424D.js";
12
12
 
13
13
  // src/config/config-manager.ts
14
14
  import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  truncateForPersist
4
- } from "./chunk-FQF6YJ6F.js";
4
+ } from "./chunk-2YLYDFEX.js";
5
5
  import {
6
6
  APP_NAME,
7
7
  CONFIG_DIR_NAME,
@@ -11,7 +11,7 @@ import {
11
11
  MCP_PROTOCOL_VERSION,
12
12
  MCP_TOOL_PREFIX,
13
13
  VERSION
14
- } from "./chunk-IDMCBIYZ.js";
14
+ } from "./chunk-HZKC424D.js";
15
15
 
16
16
  // src/mcp/client.ts
17
17
  import { spawn } from "child_process";
File without changes
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  CONFIG_DIR_NAME,
4
4
  VERSION
5
- } from "./chunk-IDMCBIYZ.js";
5
+ } from "./chunk-HZKC424D.js";
6
6
 
7
7
  // src/diagnostics/crash-log.ts
8
8
  import {
File without changes
File without changes
File without changes
File without changes
@@ -6,7 +6,7 @@ import { platform } from "os";
6
6
  import chalk from "chalk";
7
7
 
8
8
  // src/core/constants.ts
9
- var VERSION = "0.4.200";
9
+ var VERSION = "0.4.202";
10
10
  var APP_NAME = "ai-cli";
11
11
  var CONFIG_DIR_NAME = ".aicli";
12
12
  var CONFIG_FILE_NAME = "config.json";
@@ -6,15 +6,15 @@ import {
6
6
  } from "./chunk-HLWUDRBO.js";
7
7
  import {
8
8
  ProviderRegistry
9
- } from "./chunk-JP6ESDV7.js";
9
+ } from "./chunk-2NINHXEZ.js";
10
10
  import "./chunk-5UR6ZOF4.js";
11
11
  import {
12
12
  ConfigManager
13
- } from "./chunk-NULOZSFA.js";
13
+ } from "./chunk-JCY7RQIA.js";
14
14
  import "./chunk-TZQHYZKT.js";
15
15
  import {
16
16
  VERSION
17
- } from "./chunk-IDMCBIYZ.js";
17
+ } from "./chunk-HZKC424D.js";
18
18
 
19
19
  // src/cli/ci.ts
20
20
  import { execFileSync, execSync } from "child_process";
@@ -36,7 +36,7 @@ import {
36
36
  TEST_TIMEOUT,
37
37
  VERSION,
38
38
  buildUserIdentityPrompt
39
- } from "./chunk-IDMCBIYZ.js";
39
+ } from "./chunk-HZKC424D.js";
40
40
  export {
41
41
  AGENTIC_BEHAVIOR_GUIDELINE,
42
42
  APP_NAME,
@@ -2,26 +2,26 @@
2
2
  import {
3
3
  getConfigDirUsage,
4
4
  listRecentCrashes
5
- } from "./chunk-2G62CKDL.js";
5
+ } from "./chunk-SB77W6XS.js";
6
6
  import {
7
7
  ProviderRegistry
8
- } from "./chunk-JP6ESDV7.js";
8
+ } from "./chunk-2NINHXEZ.js";
9
9
  import {
10
10
  getStatsSnapshot,
11
11
  getTopFailingTools,
12
12
  getTopUsedTools,
13
13
  resetStats
14
- } from "./chunk-JZCXULOJ.js";
14
+ } from "./chunk-GOKVKOG3.js";
15
15
  import "./chunk-5UR6ZOF4.js";
16
16
  import {
17
17
  ConfigManager
18
- } from "./chunk-NULOZSFA.js";
18
+ } from "./chunk-JCY7RQIA.js";
19
19
  import "./chunk-TZQHYZKT.js";
20
20
  import {
21
21
  DEV_STATE_FILE_NAME,
22
22
  MEMORY_FILE_NAME,
23
23
  VERSION
24
- } from "./chunk-IDMCBIYZ.js";
24
+ } from "./chunk-HZKC424D.js";
25
25
  import "./chunk-IW3Q7AE5.js";
26
26
 
27
27
  // src/diagnostics/doctor-cli.ts
@@ -36,7 +36,7 @@ import {
36
36
  VERSION,
37
37
  buildUserIdentityPrompt,
38
38
  runTestsTool
39
- } from "./chunk-TBGVHRCL.js";
39
+ } from "./chunk-Y6U6FMVV.js";
40
40
  import {
41
41
  hasSemanticIndex,
42
42
  semanticSearch
@@ -2563,6 +2563,18 @@ function toUsage(u) {
2563
2563
  if (cached > 0) usage.cacheReadTokens = cached;
2564
2564
  return usage;
2565
2565
  }
2566
+ function isLoopbackBaseUrl(baseUrl) {
2567
+ if (!baseUrl) return false;
2568
+ let host;
2569
+ try {
2570
+ host = new URL(baseUrl).hostname;
2571
+ } catch {
2572
+ return false;
2573
+ }
2574
+ host = host.replace(/^\[|\]$/g, "").toLowerCase();
2575
+ if (host === "localhost" || host === "::1" || host === "0.0.0.0") return true;
2576
+ return /^127(?:\.\d{1,3}){3}$/.test(host);
2577
+ }
2566
2578
  var OpenAICompatibleProvider = class extends BaseProvider {
2567
2579
  client;
2568
2580
  defaultTimeout = 6e4;
@@ -2578,7 +2590,7 @@ var OpenAICompatibleProvider = class extends BaseProvider {
2578
2590
  baseURL: options?.baseUrl ?? this.defaultBaseUrl,
2579
2591
  timeout: this.defaultTimeout
2580
2592
  };
2581
- const proxyUrl = options?.proxy;
2593
+ const proxyUrl = isLoopbackBaseUrl(clientOptions.baseURL) ? void 0 : options?.proxy;
2582
2594
  try {
2583
2595
  const { Agent: Agent2, ProxyAgent, fetch: undiciFetch } = await import("undici");
2584
2596
  const STREAM_BODY_TIMEOUT = 30 * 60 * 1e3;
@@ -4871,12 +4883,12 @@ Important rules:
4871
4883
  3. Multiple commands can be combined with semicolons in a single call to reduce rounds.
4872
4884
  4. To delete directories, use Remove-Item -Recurse (the system will automatically optimize to a more reliable method).
4873
4885
  5. IMPORTANT: On Windows, "curl" is an alias for Invoke-WebRequest and does NOT support curl flags like -s, -X, -H. Use Invoke-RestMethod instead for HTTP requests. Example: Invoke-RestMethod -Uri "http://localhost:3000/api/health" -Method Get
4874
- 6. For long-running server commands (node server.js, npm run dev, etc.), use Start-Process -NoNewWindow to run in background, otherwise the tool will block until timeout.` : `Execute commands in ${SHELL}.
4886
+ 6. NEVER run long-running / never-exiting commands through bash \u2014 they block until timeout. This includes starting an Android emulator (emulator -avd X), streaming logs (adb logcat), and dev servers (node server.js, npm run dev, metro / react-native start). Use the 'task_create' tool to run these in the background, then poll status with short bash calls (e.g. adb shell getprop sys.boot_completed).` : `Execute commands in ${SHELL}.
4875
4887
  Important rules:
4876
4888
  1. Each bash call runs in an independent subprocess; cd commands do not persist. To run in a specific directory, use the cwd parameter, or combine commands: e.g. "cd mydir && ls" or "mkdir -p mydir && touch mydir/file.txt".
4877
4889
  2. If a command fails (returns an error or non-zero exit code), stop immediately, report the error to the user, and do not retry the same or similar commands.
4878
4890
  3. Multiple commands can be combined with && in a single call to reduce rounds.
4879
- 4. For long-running server commands (node server.js, npm start, npm run dev, etc.), run in background with & or nohup, otherwise the tool will block until timeout.`,
4891
+ 4. NEVER run long-running / never-exiting commands through bash \u2014 they block until timeout. This includes starting an Android emulator (emulator -avd X), streaming logs (adb logcat), and dev servers (node server.js, npm run dev, metro / react-native start). Use the 'task_create' tool to run these in the background, then poll status with short bash calls (e.g. adb shell getprop sys.boot_completed).`,
4880
4892
  parameters: {
4881
4893
  command: {
4882
4894
  type: "string",
@@ -4905,6 +4917,10 @@ Important rules:
4905
4917
  if (!command.trim()) {
4906
4918
  throw new ToolError("bash", "command is required");
4907
4919
  }
4920
+ const blockingHint = detectBlockingCommand(command);
4921
+ if (blockingHint) {
4922
+ throw new ToolError("bash", blockingHint);
4923
+ }
4908
4924
  let currentCwd = getCwd();
4909
4925
  if (!existsSync4(currentCwd)) {
4910
4926
  const fallback = process.cwd();
@@ -5091,6 +5107,28 @@ function buildErrorHint(command, stderr) {
5091
5107
  }
5092
5108
  return hints.length > 0 ? hints.map((h) => `\u{1F4A1} ${h}`).join("\n\n") : null;
5093
5109
  }
5110
+ function detectBlockingCommand(command) {
5111
+ if (/\bemulator(?:\.exe)?\b/i.test(command) && /(?:^|\s)(?:-avd\b|@[\w.-]+)/.test(command)) {
5112
+ return blockingMessage("emulator -avd <name>", "launch an Android emulator");
5113
+ }
5114
+ const logcat = command.match(/\badb\b[^|;&\n]*\blogcat\b([^|;&\n]*)/i);
5115
+ if (logcat && !/(?:^|\s)-(?:d|t|c|g)\b/.test(logcat[1] ?? "")) {
5116
+ return blockingMessage("adb logcat", "stream device logs");
5117
+ }
5118
+ return null;
5119
+ }
5120
+ function blockingMessage(example, what) {
5121
+ return `This command (${example}) is used to ${what}, which runs forever and never exits on its own. Running it through 'bash' will BLOCK until the tool times out, and the timeout cleanup (taskkill /T) then kills the very emulator/process you just started \u2014 so it can never stay up.
5122
+
5123
+ Use the 'task_create' tool to run it in the background instead, e.g.:
5124
+ task_create(command: "${example} ...", description: "${what}")
5125
+
5126
+ Then poll readiness with SHORT bash calls (these DO exit), e.g.:
5127
+ adb devices # is the device/emulator listed?
5128
+ adb shell getprop sys.boot_completed # prints "1" once the emulator is fully booted
5129
+
5130
+ [Do NOT run this long-running command through bash \u2014 it will hang.]`;
5131
+ }
5094
5132
  function snapshotDir(dir) {
5095
5133
  try {
5096
5134
  return new Set(readdirSync2(dir).map((name) => resolve(dir, name)));
@@ -9241,15 +9279,30 @@ function stopTask(id) {
9241
9279
  const task = tasks.get(id);
9242
9280
  if (!task || task.status !== "running") return false;
9243
9281
  try {
9244
- task.process.kill("SIGTERM");
9245
- setTimeout(() => {
9246
- if (task.status === "running") {
9247
- try {
9248
- task.process.kill("SIGKILL");
9249
- } catch {
9250
- }
9282
+ const proc = task.process;
9283
+ if (platform3() === "win32" && proc.pid) {
9284
+ try {
9285
+ spawn3("taskkill", ["/PID", String(proc.pid), "/T", "/F"], {
9286
+ windowsHide: true,
9287
+ stdio: "ignore"
9288
+ });
9289
+ } catch {
9251
9290
  }
9252
- }, 3e3);
9291
+ try {
9292
+ proc.kill();
9293
+ } catch {
9294
+ }
9295
+ } else {
9296
+ proc.kill("SIGTERM");
9297
+ setTimeout(() => {
9298
+ if (proc.exitCode === null && proc.signalCode === null) {
9299
+ try {
9300
+ proc.kill("SIGKILL");
9301
+ } catch {
9302
+ }
9303
+ }
9304
+ }, 3e3).unref();
9305
+ }
9253
9306
  task.status = "stopped";
9254
9307
  task.endTime = Date.now();
9255
9308
  return true;
@@ -9262,7 +9315,7 @@ function stopTask(id) {
9262
9315
  var taskCreateTool = {
9263
9316
  definition: {
9264
9317
  name: "task_create",
9265
- description: `Start a command running in the background. Returns a task ID for monitoring with task_list. Use this to run long-running processes (dev servers, builds, tests) while continuing other work.`,
9318
+ description: `Start a command running in the background and return immediately with a task ID (monitor via task_list, stop via task_stop). Use this for ANY long-running or never-exiting command, including: dev servers (npm run dev, metro / react-native start), Android emulator launch (emulator -avd X), device log streaming (adb logcat), file watchers, and builds you want to monitor while continuing other work. Running such commands via 'bash' instead would block until timeout.`,
9266
9319
  parameters: {
9267
9320
  command: {
9268
9321
  type: "string",
@@ -14251,7 +14304,7 @@ ${undoResults.map((r) => ` \u2022 ${r}`).join("\n")}` });
14251
14304
  case "test": {
14252
14305
  this.send({ type: "info", message: "\u{1F9EA} Running tests..." });
14253
14306
  try {
14254
- const { executeTests } = await import("./run-tests-G2MCAQJL.js");
14307
+ const { executeTests } = await import("./run-tests-AXPZOPX7.js");
14255
14308
  const argStr = args.join(" ").trim();
14256
14309
  let testArgs = {};
14257
14310
  if (argStr) {
File without changes
File without changes
@@ -154,7 +154,7 @@ ${content}`);
154
154
  }
155
155
  }
156
156
  async function runTaskMode(config, providers, configManager, topic) {
157
- const { TaskOrchestrator } = await import("./task-orchestrator-IF3XCVZ7.js");
157
+ const { TaskOrchestrator } = await import("./task-orchestrator-FM4EXIBZ.js");
158
158
  const orchestrator = new TaskOrchestrator(config, providers, configManager);
159
159
  let interrupted = false;
160
160
  const onSigint = () => {
File without changes