agent-sh 0.12.14 → 0.12.16

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.
@@ -83,11 +83,21 @@ export class ConversationState {
83
83
  this.eagerNucleateUser(text);
84
84
  }
85
85
  addAssistantMessage(content, toolCalls, extras) {
86
- // extras is opaque provider payload to echo back (reasoning_content,
87
- // reasoning_details, etc.). Spread verbatim; shape is the stream
88
- // parser's concern.
89
- const base = { role: "assistant", content: content ?? (toolCalls?.length ? null : "") };
90
- if (toolCalls?.length) {
86
+ const hasToolCalls = !!toolCalls?.length;
87
+ // Promote reasoning into content on reasoning-only turns; strict
88
+ // providers (DeepSeek native) reject content="" with no tool_calls.
89
+ if (!content && !hasToolCalls) {
90
+ const r = (extras?.reasoning_content ?? extras?.reasoning);
91
+ if (typeof r === "string" && r)
92
+ content = r;
93
+ }
94
+ if (!content && !hasToolCalls)
95
+ return;
96
+ const base = {
97
+ role: "assistant",
98
+ content: hasToolCalls ? (content ?? null) : content,
99
+ };
100
+ if (hasToolCalls) {
91
101
  base.tool_calls = toolCalls.map((tc) => ({
92
102
  id: tc.id,
93
103
  type: "function",
@@ -1,7 +1,30 @@
1
+ import { spawnSync } from "node:child_process";
1
2
  import { executeArgv, killSession } from "../../executor.js";
2
- // Targets PowerShell 7+ (`pwsh`). Legacy `powershell.exe` is intentionally
3
- // not auto-fallback its tool surface diverges enough that compatibility
4
- // shims aren't worth the maintenance.
3
+ let cachedPwshPath;
4
+ /** Resolve a usable PowerShell binary, or null if none is on PATH.
5
+ * Prefers PowerShell 7+ (`pwsh`), falls back to Windows PowerShell (`powershell`). */
6
+ function findPwsh() {
7
+ if (cachedPwshPath !== undefined)
8
+ return cachedPwshPath;
9
+ // Prefer PowerShell 7 (pwsh)
10
+ const pwsh = spawnSync("where", ["pwsh"], { encoding: "utf-8" });
11
+ if (pwsh.status === 0) {
12
+ cachedPwshPath = pwsh.stdout.split(/\r?\n/)[0].trim() || null;
13
+ if (cachedPwshPath)
14
+ return cachedPwshPath;
15
+ }
16
+ // Fallback to Windows PowerShell (powershell.exe)
17
+ const ps = spawnSync("where", ["powershell"], { encoding: "utf-8" });
18
+ cachedPwshPath = ps.status === 0 ? ps.stdout.split(/\r?\n/)[0].trim() || null : null;
19
+ return cachedPwshPath;
20
+ }
21
+ /** Return the PowerShell executable name for display purposes. */
22
+ function getPwshDisplayName() {
23
+ const path = findPwsh();
24
+ if (!path)
25
+ return "PowerShell";
26
+ return path.toLowerCase().includes("pwsh") ? "pwsh" : "powershell";
27
+ }
5
28
  export function createPwshTool(opts) {
6
29
  return {
7
30
  name: "pwsh",
@@ -54,8 +77,16 @@ export function createPwshTool(opts) {
54
77
  isError: false,
55
78
  };
56
79
  }
80
+ const pwshPath = findPwsh();
81
+ if (!pwshPath) {
82
+ return {
83
+ content: "PowerShell not found on PATH. Neither pwsh (PowerShell 7+) nor powershell (Windows PowerShell) is available.",
84
+ exitCode: 1,
85
+ isError: true,
86
+ };
87
+ }
57
88
  const { session, done } = executeArgv({
58
- file: "pwsh",
89
+ file: pwshPath,
59
90
  args: ["-NoProfile", "-NonInteractive", "-Command", command],
60
91
  cwd: opts.getCwd(),
61
92
  env: opts.getEnv(),
@@ -72,7 +103,7 @@ export function createPwshTool(opts) {
72
103
  }
73
104
  if (session.spawnFailed) {
74
105
  return {
75
- content: "PowerShell (pwsh) not found on PATH. Install PowerShell 7: winget install Microsoft.PowerShell.",
106
+ content: `${getPwshDisplayName()} not found on PATH. Install PowerShell 7: winget install Microsoft.PowerShell.`,
76
107
  exitCode: 1,
77
108
  isError: true,
78
109
  };
package/dist/executor.js CHANGED
@@ -53,7 +53,8 @@ export function executeCommand(opts) {
53
53
  stdio: ["ignore", "pipe", "pipe"],
54
54
  cwd: opts.cwd,
55
55
  env,
56
- detached: true,
56
+ detached: process.platform !== "win32",
57
+ windowsHide: true,
57
58
  });
58
59
  }
59
60
  catch (err) {
@@ -214,12 +215,14 @@ export function killSession(session) {
214
215
  if (!proc || !proc.pid)
215
216
  return () => { };
216
217
  // Try process-group kill first (works for executeCommand's detached bash
217
- // children); fall back to direct kill (executeArgv's non-detached spawn,
218
- // and Windows where negative pids aren't supported).
219
- try {
220
- process.kill(-proc.pid, "SIGTERM");
218
+ // children on Unix); fall back to direct kill (executeArgv's non-detached
219
+ // spawn, and Windows where negative pids aren't supported).
220
+ if (process.platform !== "win32") {
221
+ try {
222
+ process.kill(-proc.pid, "SIGTERM");
223
+ }
224
+ catch { }
221
225
  }
222
- catch { }
223
226
  try {
224
227
  proc.kill("SIGTERM");
225
228
  }
@@ -227,10 +230,12 @@ export function killSession(session) {
227
230
  let settled = false;
228
231
  const fallback = setTimeout(() => {
229
232
  if (!settled && !session.done && proc.pid) {
230
- try {
231
- process.kill(-proc.pid, "SIGKILL");
233
+ if (process.platform !== "win32") {
234
+ try {
235
+ process.kill(-proc.pid, "SIGKILL");
236
+ }
237
+ catch { }
232
238
  }
233
- catch { }
234
239
  try {
235
240
  proc.kill("SIGKILL");
236
241
  }
package/dist/index.js CHANGED
@@ -9,6 +9,7 @@ import { loadExtensions } from "./extension-loader.js";
9
9
  import { getSettings } from "./settings.js";
10
10
  import { discoverSkills } from "./agent/skills.js";
11
11
  import { runInit } from "./init.js";
12
+ import { PACKAGE_VERSION } from "./utils/package-version.js";
12
13
  /**
13
14
  * Capture the user's full shell environment.
14
15
  * This picks up env vars exported in .zshrc/.bashrc that the
@@ -102,6 +103,10 @@ function parseArgs(argv) {
102
103
  const exts = argv[++i].split(",").map(s => s.trim());
103
104
  extensions = extensions ? [...extensions, ...exts] : exts;
104
105
  }
106
+ else if (arg === "--version" || arg === "-V") {
107
+ console.log(PACKAGE_VERSION);
108
+ process.exit(0);
109
+ }
105
110
  else if (arg === "--help" || arg === "-h") {
106
111
  console.log(`agent-sh — a shell-first terminal where AI is one keystroke away
107
112
 
@@ -120,6 +125,7 @@ General Options:
120
125
  --shell <path> Shell to use (default: $SHELL or /bin/bash)
121
126
  -e, --extensions Extensions to load (comma-separated, repeatable)
122
127
  -h, --help Show this help
128
+ -V, --version Print version and exit
123
129
 
124
130
  Environment Variables:
125
131
  OPENAI_API_KEY API key for LLM provider
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-sh",
3
- "version": "0.12.14",
3
+ "version": "0.12.16",
4
4
  "description": "A shell-first terminal where AI is one keystroke away",
5
5
  "type": "module",
6
6
  "main": "dist/core.js",