chore: bump version to 11.1.0

This commit is contained in:
can1357
2026-02-05 08:11:32 +01:00
parent a1786ce3b5
commit d1ccb24e7e
16 changed files with 80 additions and 149 deletions
Generated
+1 -1
View File
@@ -1989,7 +1989,7 @@ dependencies = [
[[package]]
name = "pi-natives"
version = "11.0.3"
version = "11.1.0"
dependencies = [
"arboard",
"brush-builtins",
+1 -1
View File
@@ -4,7 +4,7 @@ exclude = ["crates/brush-core-vendored", "crates/brush-builtins-vendored"]
resolver = "3"
[workspace.package]
version = "11.0.3"
version = "11.1.0"
edition = "2024"
license = "MIT"
authors = ["Can Boluk"]
+7 -7
View File
@@ -22,7 +22,7 @@
},
"packages/agent": {
"name": "@oh-my-pi/pi-agent-core",
"version": "11.0.3",
"version": "11.1.0",
"dependencies": {
"@oh-my-pi/pi-ai": "workspace:*",
"@oh-my-pi/pi-tui": "workspace:*",
@@ -35,7 +35,7 @@
},
"packages/ai": {
"name": "@oh-my-pi/pi-ai",
"version": "11.0.3",
"version": "11.1.0",
"bin": {
"pi-ai": "./src/cli.ts",
},
@@ -63,7 +63,7 @@
},
"packages/coding-agent": {
"name": "@oh-my-pi/pi-coding-agent",
"version": "11.0.3",
"version": "11.1.0",
"bin": {
"omp": "src/cli.ts",
},
@@ -102,7 +102,7 @@
},
"packages/natives": {
"name": "@oh-my-pi/pi-natives",
"version": "11.0.3",
"version": "11.1.0",
"dependencies": {
"@oh-my-pi/pi-utils": "workspace:*",
},
@@ -130,7 +130,7 @@
},
"packages/stats": {
"name": "@oh-my-pi/omp-stats",
"version": "11.0.3",
"version": "11.1.0",
"bin": {
"omp-stats": "./src/index.ts",
},
@@ -150,7 +150,7 @@
},
"packages/tui": {
"name": "@oh-my-pi/pi-tui",
"version": "11.0.3",
"version": "11.1.0",
"dependencies": {
"@oh-my-pi/pi-natives": "workspace:*",
"@oh-my-pi/pi-utils": "workspace:*",
@@ -166,7 +166,7 @@
},
"packages/utils": {
"name": "@oh-my-pi/pi-utils",
"version": "11.0.3",
"version": "11.1.0",
"dependencies": {
"winston": "^3.19.0",
"winston-daily-rotate-file": "^5.0.0",
-16
View File
@@ -12,9 +12,6 @@ use crate::sys;
use crate::trace_categories;
use crate::traps;
#[cfg(windows)]
use std::os::windows::io::OwnedHandle;
pub(crate) type JobJoinHandle = tokio::task::JoinHandle<Result<ExecutionResult, error::Error>>;
pub(crate) type JobResult = (Job, Result<ExecutionResult, error::Error>);
@@ -450,17 +447,4 @@ impl Job {
self.pgid.or_else(|| self.representative_pid())
}
/// Duplicates process handles for termination on Windows.
#[cfg(windows)]
pub fn duplicate_kill_handles(&self) -> Vec<OwnedHandle> {
let mut handles = Vec::new();
for task in &self.tasks {
if let JobTask::External(process) = task {
if let Some(handle) = process.duplicate_kill_handle() {
handles.push(handle);
}
}
}
handles
}
}
+40 -103
View File
@@ -1,41 +1,21 @@
//! Process management
use futures::FutureExt;
use tokio_util::sync::CancellationToken;
#[cfg(windows)]
use std::os::windows::io::{AsRawHandle, OwnedHandle, RawHandle};
use crate::{error, sys};
/// A waitable future that will yield the results of a child process's execution.
pub(crate) type WaitableChildProcess = std::pin::Pin<
Box<dyn futures::Future<Output = Result<std::process::Output, std::io::Error>> + Send + Sync>,
>;
/// Tracks a child process being awaited.
pub struct ChildProcess {
/// If available, the process ID of the child.
pid: Option<sys::process::ProcessId>,
/// A waitable future that will yield the results of a child process's execution.
exec_future: WaitableChildProcess,
#[cfg(windows)]
/// Windows handle duplicated from the child process for safe termination.
kill_handle: Option<OwnedHandle>,
/// Child process handle kept alive for cancellation/termination.
child: sys::process::Child,
}
impl ChildProcess {
/// Wraps a child process and its future.
pub fn new(pid: Option<sys::process::ProcessId>, child: sys::process::Child) -> Self {
#[cfg(windows)]
let kill_handle = duplicate_handle(child.as_raw_handle());
Self {
pid,
exec_future: Box::pin(child.wait_with_output()),
#[cfg(windows)]
kill_handle,
}
Self { pid, child }
}
/// Returns the process's ID.
@@ -43,13 +23,6 @@ impl ChildProcess {
self.pid
}
/// Duplicates the process handle for termination use on Windows.
#[cfg(windows)]
pub fn duplicate_kill_handle(&self) -> Option<OwnedHandle> {
let handle = self.kill_handle.as_ref()?;
duplicate_handle(handle.as_raw_handle())
}
/// Waits for the process to exit.
///
/// If a cancellation token is provided and triggered, the process will be killed.
@@ -72,90 +45,54 @@ impl ChildProcess {
#[allow(clippy::ignored_unit_patterns)]
loop {
tokio::select! {
output = &mut self.exec_future => {
break Ok(ProcessWaitResult::Completed(output?))
},
_ = &mut cancelled => {
let status = {
let wait_future = self.child.wait();
tokio::pin!(wait_future);
tokio::select! {
status = &mut wait_future => Some(status),
_ = &mut cancelled => None,
_ = sigtstp.recv() => return Ok(ProcessWaitResult::Stopped),
_ = sigchld.recv() => {
if sys::signal::poll_for_stopped_children()? {
return Ok(ProcessWaitResult::Stopped);
}
continue;
},
_ = sys::signal::await_ctrl_c() => {
// SIGINT got thrown. Handle it and continue looping. The child should
// have received it as well, and either handled it or ended up getting
// terminated (in which case we'll see the child exit).
continue;
},
}
};
return match status {
Some(status) => Ok(ProcessWaitResult::Completed(output_from_status(status?))),
None => {
self.kill();
break Ok(ProcessWaitResult::Cancelled)
},
_ = sigtstp.recv() => {
break Ok(ProcessWaitResult::Stopped)
},
_ = sigchld.recv() => {
if sys::signal::poll_for_stopped_children()? {
break Ok(ProcessWaitResult::Stopped);
}
},
_ = sys::signal::await_ctrl_c() => {
// SIGINT got thrown. Handle it and continue looping. The child should
// have received it as well, and either handled it or ended up getting
// terminated (in which case we'll see the child exit).
},
}
Ok(ProcessWaitResult::Cancelled)
}
};
}
}
/// Terminates the process if we have a PID.
fn kill(&self) {
let Some(pid) = self.pid else { return };
#[cfg(unix)]
{
let _ = nix::sys::signal::kill(nix::unistd::Pid::from_raw(pid), nix::sys::signal::Signal::SIGKILL);
}
#[cfg(windows)]
{
use windows_sys::Win32::Foundation::CloseHandle;
use windows_sys::Win32::System::Threading::{OpenProcess, TerminateProcess, PROCESS_TERMINATE};
// SAFETY: Windows API calls with proper handle management
unsafe {
#[expect(clippy::cast_sign_loss)]
let handle = OpenProcess(PROCESS_TERMINATE, 0, pid as u32);
if !handle.is_null() {
let _ = TerminateProcess(handle, 1);
CloseHandle(handle);
}
}
}
fn kill(&mut self) {
let _ = self.child.start_kill();
}
pub(crate) fn poll(&mut self) -> Option<Result<std::process::Output, error::Error>> {
let checkable_future = &mut self.exec_future;
checkable_future
.now_or_never()
.map(|result| result.map_err(Into::into))
match self.child.try_wait() {
Ok(Some(status)) => Some(Ok(output_from_status(status))),
Ok(None) => None,
Err(err) => Some(Err(err.into())),
}
}
}
#[cfg(windows)]
fn duplicate_handle(handle: RawHandle) -> Option<OwnedHandle> {
use std::os::windows::io::FromRawHandle;
use windows_sys::Win32::System::Threading::{
DuplicateHandle, GetCurrentProcess, DUPLICATE_SAME_ACCESS,
};
let current = unsafe { GetCurrentProcess() };
let mut out_handle = std::ptr::null_mut();
let ok = unsafe {
DuplicateHandle(
current,
handle as _,
current,
&mut out_handle,
0,
0,
DUPLICATE_SAME_ACCESS,
)
};
if ok == 0 || out_handle.is_null() {
return None;
}
Some(unsafe { OwnedHandle::from_raw_handle(out_handle) })
fn output_from_status(status: std::process::ExitStatus) -> std::process::Output {
std::process::Output { status, stdout: Vec::new(), stderr: Vec::new() }
}
/// Represents the result of waiting for an executing process.
@@ -10,10 +10,14 @@ pub enum Signal {}
/// Minimal signal representation for Windows.
#[cfg(windows)]
#[allow(unnameable_types)]
#[derive(Clone, Copy, Eq, Hash, PartialEq)]
pub enum Signal {
/// Terminate signal.
Terminate,
/// Kill signal.
Kill,
/// Interrupt signal.
Interrupt,
}
@@ -83,7 +87,7 @@ pub fn kill_process(
let pid = _pid as u32;
unsafe {
let handle = OpenProcess(PROCESS_TERMINATE, 0, pid);
if handle == 0 {
if handle.is_null() {
return Err(error::ErrorKind::FailedToSendSignal.into());
}
let ok = TerminateProcess(handle, 1);
@@ -7,7 +7,7 @@ pub use crate::sys::stubs::resource;
/// Signal processing utilities
pub mod signal {
pub(crate) use crate::sys::stubs::signal::*;
pub use crate::sys::stubs::signal::*;
pub(crate) use tokio::signal::ctrl_c as await_ctrl_c;
}
+16 -12
View File
@@ -12,6 +12,8 @@
//! });
//! ```
#[cfg(windows)]
use std::collections::HashSet;
use std::{
collections::HashMap,
fs,
@@ -20,8 +22,6 @@ use std::{
sync::Arc,
time::Duration,
};
#[cfg(windows)]
use std::{collections::HashSet, os::windows::io::AsRawHandle};
#[cfg(windows)]
mod windows;
@@ -45,8 +45,6 @@ use tokio::io::AsyncReadExt as _;
use tokio_util::sync::CancellationToken;
#[cfg(windows)]
use windows::configure_windows_path;
#[cfg(windows)]
use windows_sys::Win32::System::Threading::TerminateProcess;
use crate::task;
@@ -614,20 +612,26 @@ fn terminate_background_jobs(shell: &BrushShell) {
if shell.jobs.jobs.is_empty() {
return;
}
let mut handles = Vec::new();
let Ok(signal) = "TERM".parse::<traps::TrapSignal>() else {
return;
};
let mut pids = Vec::new();
for job in &shell.jobs.jobs {
handles.extend(job.duplicate_kill_handles());
if let Some(pid) = job.process_group_id().or_else(|| job.representative_pid()) {
let _ = sys::signal::kill_process(pid, signal);
pids.push(pid);
}
}
if handles.is_empty() {
if pids.is_empty() {
return;
}
tokio::spawn(async move {
time::sleep(Duration::from_millis(500)).await;
for handle in handles {
// SAFETY: OwnedHandle keeps the duplicated handle alive for the duration.
unsafe {
let _ = TerminateProcess(handle.as_raw_handle() as _, 1);
}
let Ok(signal) = "KILL".parse::<traps::TrapSignal>() else {
return;
};
for pid in pids {
let _ = sys::signal::kill_process(pid, signal);
}
});
}
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@oh-my-pi/pi-agent-core",
"version": "11.0.3",
"version": "11.1.0",
"description": "General-purpose agent with transport abstraction, state management, and attachment support",
"type": "module",
"main": "./src/index.ts",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@oh-my-pi/pi-ai",
"version": "11.0.3",
"version": "11.1.0",
"description": "Unified LLM API with automatic model discovery and provider configuration",
"type": "module",
"main": "./src/index.ts",
+2
View File
@@ -2,6 +2,8 @@
## [Unreleased]
## [11.1.0] - 2026-02-05
### Added
- Added `sortDiagnostics()` utility function to sort diagnostics by severity, location, and message for consistent output ordering
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@oh-my-pi/pi-coding-agent",
"version": "11.0.3",
"version": "11.1.0",
"description": "Coding agent CLI with read, bash, edit, write tools and session management",
"type": "module",
"ompConfig": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@oh-my-pi/pi-natives",
"version": "11.0.3",
"version": "11.1.0",
"description": "Native Rust functionality via N-API",
"type": "module",
"main": "./src/index.ts",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@oh-my-pi/omp-stats",
"version": "11.0.3",
"version": "11.1.0",
"description": "Local observability dashboard for pi AI usage statistics",
"type": "module",
"main": "./src/index.ts",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@oh-my-pi/pi-tui",
"version": "11.0.3",
"version": "11.1.0",
"description": "Terminal User Interface library with differential rendering for efficient text-based applications",
"type": "module",
"main": "./src/index.ts",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@oh-my-pi/pi-utils",
"version": "11.0.3",
"version": "11.1.0",
"description": "Shared utilities for pi packages",
"type": "module",
"main": "./src/index.ts",