mirror of
https://github.com/getpaseo/paseo.git
synced 2026-07-29 12:01:31 +00:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aa1dc3ac21 | ||
|
|
00659bc32d | ||
|
|
6c11a082c5 |
@@ -1,5 +1,13 @@
|
||||
# Changelog
|
||||
|
||||
## 0.1.29 - 2026-03-18
|
||||
|
||||
### Improved
|
||||
- Improved `paseo daemon status` with provider binary resolution and version checks for Claude, Codex, and OpenCode.
|
||||
|
||||
### Fixed
|
||||
- Fixed desktop-managed agent startup failures caused by the daemon using the GUI process PATH instead of the user's login shell PATH.
|
||||
|
||||
## 0.1.28 - 2026-03-15
|
||||
|
||||
### Added
|
||||
|
||||
28
package-lock.json
generated
28
package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "paseo",
|
||||
"version": "0.1.28",
|
||||
"version": "0.1.29",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "paseo",
|
||||
"version": "0.1.28",
|
||||
"version": "0.1.29",
|
||||
"hasInstallScript": true,
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"workspaces": [
|
||||
@@ -31450,15 +31450,15 @@
|
||||
},
|
||||
"packages/app": {
|
||||
"name": "@getpaseo/app",
|
||||
"version": "0.1.28",
|
||||
"version": "0.1.29",
|
||||
"dependencies": {
|
||||
"@dnd-kit/core": "^6.3.1",
|
||||
"@dnd-kit/sortable": "^10.0.0",
|
||||
"@dnd-kit/utilities": "^3.2.2",
|
||||
"@expo/vector-icons": "^15.0.2",
|
||||
"@floating-ui/react-native": "^0.10.7",
|
||||
"@getpaseo/expo-two-way-audio": "0.1.28",
|
||||
"@getpaseo/server": "0.1.28",
|
||||
"@getpaseo/expo-two-way-audio": "0.1.29",
|
||||
"@getpaseo/server": "0.1.29",
|
||||
"@gorhom/bottom-sheet": "^5.2.6",
|
||||
"@gorhom/portal": "^1.0.14",
|
||||
"@lezer/common": "^1.5.0",
|
||||
@@ -31576,11 +31576,11 @@
|
||||
},
|
||||
"packages/cli": {
|
||||
"name": "@getpaseo/cli",
|
||||
"version": "0.1.28",
|
||||
"version": "0.1.29",
|
||||
"dependencies": {
|
||||
"@clack/prompts": "^1.0.0",
|
||||
"@getpaseo/relay": "0.1.28",
|
||||
"@getpaseo/server": "0.1.28",
|
||||
"@getpaseo/relay": "0.1.29",
|
||||
"@getpaseo/server": "0.1.29",
|
||||
"chalk": "^5.3.0",
|
||||
"commander": "^12.0.0",
|
||||
"mime-types": "^2.1.35",
|
||||
@@ -31617,14 +31617,14 @@
|
||||
},
|
||||
"packages/desktop": {
|
||||
"name": "@getpaseo/desktop",
|
||||
"version": "0.1.28",
|
||||
"version": "0.1.29",
|
||||
"devDependencies": {
|
||||
"@tauri-apps/cli": "^2.9.6"
|
||||
}
|
||||
},
|
||||
"packages/expo-two-way-audio": {
|
||||
"name": "@getpaseo/expo-two-way-audio",
|
||||
"version": "0.1.28",
|
||||
"version": "0.1.29",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@biomejs/biome": "1.9.4",
|
||||
@@ -31661,7 +31661,7 @@
|
||||
},
|
||||
"packages/relay": {
|
||||
"name": "@getpaseo/relay",
|
||||
"version": "0.1.28",
|
||||
"version": "0.1.29",
|
||||
"dependencies": {
|
||||
"base64-js": "^1.5.1",
|
||||
"tweetnacl": "^1.0.3",
|
||||
@@ -31677,12 +31677,12 @@
|
||||
},
|
||||
"packages/server": {
|
||||
"name": "@getpaseo/server",
|
||||
"version": "0.1.28",
|
||||
"version": "0.1.29",
|
||||
"dependencies": {
|
||||
"@ai-sdk/openai": "2.0.52",
|
||||
"@anthropic-ai/claude-agent-sdk": "^0.2.11",
|
||||
"@deepgram/sdk": "^3.4.0",
|
||||
"@getpaseo/relay": "0.1.28",
|
||||
"@getpaseo/relay": "0.1.29",
|
||||
"@lezer/common": "^1.5.0",
|
||||
"@lezer/css": "^1.3.0",
|
||||
"@lezer/highlight": "^1.2.3",
|
||||
@@ -32039,7 +32039,7 @@
|
||||
},
|
||||
"packages/website": {
|
||||
"name": "@getpaseo/website",
|
||||
"version": "0.1.28",
|
||||
"version": "0.1.29",
|
||||
"dependencies": {
|
||||
"@cloudflare/vite-plugin": "^1.20.3",
|
||||
"@cloudflare/workers-types": "^4.20260114.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "paseo",
|
||||
"version": "0.1.28",
|
||||
"version": "0.1.29",
|
||||
"private": true,
|
||||
"workspaces": [
|
||||
"packages/expo-two-way-audio",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@getpaseo/app",
|
||||
"main": "index.ts",
|
||||
"version": "0.1.28",
|
||||
"version": "0.1.29",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"start": "expo start",
|
||||
@@ -26,13 +26,13 @@
|
||||
"deploy:web": "npm run build:web && wrangler pages deploy dist --project-name paseo-app --branch main"
|
||||
},
|
||||
"dependencies": {
|
||||
"@getpaseo/expo-two-way-audio": "0.1.28",
|
||||
"@getpaseo/expo-two-way-audio": "0.1.29",
|
||||
"@dnd-kit/core": "^6.3.1",
|
||||
"@dnd-kit/sortable": "^10.0.0",
|
||||
"@dnd-kit/utilities": "^3.2.2",
|
||||
"@expo/vector-icons": "^15.0.2",
|
||||
"@floating-ui/react-native": "^0.10.7",
|
||||
"@getpaseo/server": "0.1.28",
|
||||
"@getpaseo/server": "0.1.29",
|
||||
"@gorhom/bottom-sheet": "^5.2.6",
|
||||
"@gorhom/portal": "^1.0.14",
|
||||
"@lezer/common": "^1.5.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@getpaseo/cli",
|
||||
"version": "0.1.28",
|
||||
"version": "0.1.29",
|
||||
"description": "Paseo CLI - control your AI coding agents from the command line",
|
||||
"type": "module",
|
||||
"files": [
|
||||
@@ -24,8 +24,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@clack/prompts": "^1.0.0",
|
||||
"@getpaseo/relay": "0.1.28",
|
||||
"@getpaseo/server": "0.1.28",
|
||||
"@getpaseo/relay": "0.1.29",
|
||||
"@getpaseo/server": "0.1.29",
|
||||
"chalk": "^5.3.0",
|
||||
"commander": "^12.0.0",
|
||||
"mime-types": "^2.1.35",
|
||||
|
||||
@@ -1,11 +1,18 @@
|
||||
import type { Command } from 'commander'
|
||||
import { execFileSync } from 'node:child_process'
|
||||
import { createRequire } from 'node:module'
|
||||
import { getOrCreateServerId } from '@getpaseo/server'
|
||||
import { getOrCreateServerId, findExecutable, applyProviderEnv } from '@getpaseo/server'
|
||||
import { tryConnectToDaemon } from '../../utils/client.js'
|
||||
import type { CommandOptions, ListResult, OutputSchema } from '../../output/index.js'
|
||||
import { resolveLocalDaemonState, resolveTcpHostFromListen } from './local-daemon.js'
|
||||
import { resolveNodePathFromPid } from './runtime-toolchain.js'
|
||||
|
||||
interface ProviderBinaryStatus {
|
||||
label: string
|
||||
path: string | null
|
||||
version: string | null
|
||||
}
|
||||
|
||||
interface DaemonStatus {
|
||||
serverId: string | null
|
||||
status: 'running' | 'stopped' | 'unresponsive'
|
||||
@@ -21,6 +28,7 @@ interface DaemonStatus {
|
||||
daemonNode: string
|
||||
cliNode: string
|
||||
cliVersion: string
|
||||
providers: ProviderBinaryStatus[]
|
||||
note?: string
|
||||
}
|
||||
|
||||
@@ -77,16 +85,17 @@ function createStatusSchema(status: DaemonStatus): OutputSchema<StatusRow> {
|
||||
header: 'VALUE',
|
||||
field: 'value',
|
||||
color: (_, item) => {
|
||||
if (item.key !== 'Status') {
|
||||
return undefined
|
||||
if (item.key === 'Status') {
|
||||
if (item.value === 'running') return 'green'
|
||||
if (item.value === 'unresponsive') return 'yellow'
|
||||
return 'red'
|
||||
}
|
||||
if (item.value === 'running') {
|
||||
if (item.key.startsWith(' ')) {
|
||||
if (item.value === 'not found') return 'red'
|
||||
if (item.value.endsWith('(--version failed)')) return 'yellow'
|
||||
return 'green'
|
||||
}
|
||||
if (item.value === 'unresponsive') {
|
||||
return 'yellow'
|
||||
}
|
||||
return 'red'
|
||||
return undefined
|
||||
},
|
||||
},
|
||||
],
|
||||
@@ -126,9 +135,53 @@ function toStatusRows(status: DaemonStatus): StatusRow[] {
|
||||
rows.push({ key: 'Note', value: status.note })
|
||||
}
|
||||
|
||||
rows.push({ key: '', value: '' })
|
||||
rows.push({ key: 'Providers', value: '' })
|
||||
for (const provider of status.providers) {
|
||||
if (!provider.path) {
|
||||
rows.push({ key: ` ${provider.label}`, value: 'not found' })
|
||||
} else if (!provider.version) {
|
||||
rows.push({ key: ` ${provider.label}`, value: `${provider.path} (--version failed)` })
|
||||
} else {
|
||||
rows.push({ key: ` ${provider.label}`, value: `${provider.path} (${provider.version})` })
|
||||
}
|
||||
}
|
||||
|
||||
return rows
|
||||
}
|
||||
|
||||
const PROVIDER_BINARIES: { label: string; binary: string }[] = [
|
||||
{ label: 'Claude', binary: 'claude' },
|
||||
{ label: 'Codex', binary: 'codex' },
|
||||
{ label: 'OpenCode', binary: 'opencode' },
|
||||
]
|
||||
|
||||
function checkProviderBinary(binary: string): { path: string | null; version: string | null } {
|
||||
const binaryPath = findExecutable(binary)
|
||||
if (!binaryPath) {
|
||||
return { path: null, version: null }
|
||||
}
|
||||
const env = applyProviderEnv(process.env)
|
||||
try {
|
||||
const output = execFileSync(binaryPath, ['--version'], {
|
||||
encoding: 'utf8',
|
||||
timeout: 5000,
|
||||
stdio: ['ignore', 'pipe', 'pipe'],
|
||||
env,
|
||||
}).trim()
|
||||
return { path: binaryPath, version: output || null }
|
||||
} catch {
|
||||
return { path: binaryPath, version: null }
|
||||
}
|
||||
}
|
||||
|
||||
function checkProviderBinaries(): ProviderBinaryStatus[] {
|
||||
return PROVIDER_BINARIES.map(({ label, binary }) => {
|
||||
const result = checkProviderBinary(binary)
|
||||
return { label, ...result }
|
||||
})
|
||||
}
|
||||
|
||||
function resolveOwnerLabel(uid: number | undefined, hostname: string | undefined): string | null {
|
||||
if (uid === undefined && !hostname) {
|
||||
return null
|
||||
@@ -201,6 +254,8 @@ export async function runStatusCommand(
|
||||
note = appendNote(note, `serverId unavailable: ${shortenMessage(normalizeError(error))}`)
|
||||
}
|
||||
|
||||
const providers = checkProviderBinaries()
|
||||
|
||||
const daemonStatus: DaemonStatus = {
|
||||
serverId,
|
||||
status,
|
||||
@@ -216,6 +271,7 @@ export async function runStatusCommand(
|
||||
daemonNode,
|
||||
cliNode,
|
||||
cliVersion,
|
||||
providers,
|
||||
note,
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@getpaseo/desktop",
|
||||
"version": "0.1.28",
|
||||
"version": "0.1.29",
|
||||
"private": true,
|
||||
"description": "Paseo desktop app (Tauri wrapper)",
|
||||
"scripts": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "paseo"
|
||||
version = "0.1.28"
|
||||
version = "0.1.29"
|
||||
description = "Paseo Desktop"
|
||||
authors = ["moboudra"]
|
||||
license = "MIT"
|
||||
@@ -54,3 +54,4 @@ mac-notification-sys = "0.6"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -7,9 +7,9 @@
|
||||
<key>CFBundleName</key>
|
||||
<string>Paseo</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>0.1.28</string>
|
||||
<string>0.1.29</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>0.1.28</string>
|
||||
<string>0.1.29</string>
|
||||
<key>NSMicrophoneUsageDescription</key>
|
||||
<string>Paseo needs access to your microphone for voice dictation and voice mode.</string>
|
||||
</dict>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "../node_modules/@tauri-apps/cli/config.schema.json",
|
||||
"productName": "Paseo",
|
||||
"version": "0.1.28",
|
||||
"version": "0.1.29",
|
||||
"identifier": "dev.paseo.desktop",
|
||||
"build": {
|
||||
"frontendDist": "../../app/dist",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@getpaseo/expo-two-way-audio",
|
||||
"version": "0.1.28",
|
||||
"version": "0.1.29",
|
||||
"description": "Native module for two way audio streaming",
|
||||
"main": "build/index.js",
|
||||
"types": "build/index.d.ts",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@getpaseo/relay",
|
||||
"version": "0.1.28",
|
||||
"version": "0.1.29",
|
||||
"description": "Paseo relay for bridging daemon and client connections",
|
||||
"type": "module",
|
||||
"publishConfig": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@getpaseo/server",
|
||||
"version": "0.1.28",
|
||||
"version": "0.1.29",
|
||||
"description": "Paseo backend server",
|
||||
"type": "module",
|
||||
"publishConfig": {
|
||||
@@ -64,7 +64,7 @@
|
||||
"@ai-sdk/openai": "2.0.52",
|
||||
"@anthropic-ai/claude-agent-sdk": "^0.2.11",
|
||||
"@deepgram/sdk": "^3.4.0",
|
||||
"@getpaseo/relay": "0.1.28",
|
||||
"@getpaseo/relay": "0.1.29",
|
||||
"@lezer/common": "^1.5.0",
|
||||
"@lezer/css": "^1.3.0",
|
||||
"@lezer/highlight": "^1.2.3",
|
||||
|
||||
@@ -92,6 +92,25 @@ describe("applyProviderEnv", () => {
|
||||
expect(env.FOO).toBe("bar");
|
||||
expect(Object.keys(env).length).toBeGreaterThanOrEqual(3);
|
||||
});
|
||||
|
||||
test("shell env PATH wins over base env PATH", () => {
|
||||
const base = { PATH: "/usr/bin:/bin" };
|
||||
const shellEnv = { PATH: "/usr/local/bin:/usr/bin:/bin:/home/user/.nvm/bin" };
|
||||
|
||||
const env = applyProviderEnv(base, undefined, shellEnv);
|
||||
|
||||
expect(env.PATH).toBe("/usr/local/bin:/usr/bin:/bin:/home/user/.nvm/bin");
|
||||
});
|
||||
|
||||
test("runtimeSettings env wins over shell env", () => {
|
||||
const base = { PATH: "/usr/bin" };
|
||||
const shellEnv = { PATH: "/usr/local/bin:/usr/bin" };
|
||||
const runtime: ProviderRuntimeSettings = { env: { PATH: "/custom/path" } };
|
||||
|
||||
const env = applyProviderEnv(base, runtime, shellEnv);
|
||||
|
||||
expect(env.PATH).toBe("/custom/path");
|
||||
});
|
||||
});
|
||||
|
||||
describe("findExecutable", () => {
|
||||
|
||||
@@ -131,8 +131,8 @@ export function applyProviderEnv(
|
||||
shellEnv?: Record<string, string>
|
||||
): Record<string, string | undefined> {
|
||||
return {
|
||||
...(shellEnv ?? resolveShellEnv()),
|
||||
...baseEnv,
|
||||
...(shellEnv ?? resolveShellEnv()),
|
||||
...(runtimeSettings?.env ?? {}),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -24,6 +24,9 @@ export {
|
||||
type SherpaLoaderEnvResolution,
|
||||
} from "./speech/providers/local/sherpa/sherpa-runtime-env.js";
|
||||
|
||||
// Provider binary resolution
|
||||
export { findExecutable, applyProviderEnv } from "./agent/provider-launch-config.js";
|
||||
|
||||
// Agent SDK types for CLI commands
|
||||
export type {
|
||||
AgentMode,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@getpaseo/website",
|
||||
"version": "0.1.28",
|
||||
"version": "0.1.29",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
||||
Reference in New Issue
Block a user