mirror of
https://github.com/getpaseo/paseo.git
synced 2026-07-29 12:01:31 +00:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
93ec537095 | ||
|
|
9255212043 | ||
|
|
a03da6774a | ||
|
|
7c5bbc8048 | ||
|
|
76e6ad89d2 |
24
package-lock.json
generated
24
package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "paseo",
|
||||
"version": "0.1.9",
|
||||
"version": "0.1.12",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "paseo",
|
||||
"version": "0.1.9",
|
||||
"version": "0.1.12",
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"workspaces": [
|
||||
@@ -20344,7 +20344,7 @@
|
||||
},
|
||||
"packages/app": {
|
||||
"name": "@getpaseo/app",
|
||||
"version": "0.1.9",
|
||||
"version": "0.1.12",
|
||||
"dependencies": {
|
||||
"@boudra/expo-two-way-audio": "^0.1.3",
|
||||
"@dnd-kit/core": "^6.3.1",
|
||||
@@ -20352,7 +20352,7 @@
|
||||
"@dnd-kit/utilities": "^3.2.2",
|
||||
"@expo/vector-icons": "^15.0.2",
|
||||
"@floating-ui/react-native": "^0.10.7",
|
||||
"@getpaseo/server": "0.1.9",
|
||||
"@getpaseo/server": "0.1.12",
|
||||
"@gorhom/bottom-sheet": "^5.2.6",
|
||||
"@gorhom/portal": "^1.0.14",
|
||||
"@lezer/common": "^1.5.0",
|
||||
@@ -20456,11 +20456,11 @@
|
||||
},
|
||||
"packages/cli": {
|
||||
"name": "@getpaseo/cli",
|
||||
"version": "0.1.9",
|
||||
"version": "0.1.12",
|
||||
"dependencies": {
|
||||
"@clack/prompts": "^1.0.0",
|
||||
"@getpaseo/relay": "0.1.9",
|
||||
"@getpaseo/server": "0.1.9",
|
||||
"@getpaseo/relay": "0.1.12",
|
||||
"@getpaseo/server": "0.1.12",
|
||||
"chalk": "^5.3.0",
|
||||
"commander": "^12.0.0",
|
||||
"mime-types": "^2.1.35",
|
||||
@@ -20510,14 +20510,14 @@
|
||||
},
|
||||
"packages/desktop": {
|
||||
"name": "@getpaseo/desktop",
|
||||
"version": "0.1.9",
|
||||
"version": "0.1.12",
|
||||
"devDependencies": {
|
||||
"@tauri-apps/cli": "^2.9.6"
|
||||
}
|
||||
},
|
||||
"packages/relay": {
|
||||
"name": "@getpaseo/relay",
|
||||
"version": "0.1.9",
|
||||
"version": "0.1.12",
|
||||
"dependencies": {
|
||||
"base64-js": "^1.5.1",
|
||||
"tweetnacl": "^1.0.3",
|
||||
@@ -20533,12 +20533,12 @@
|
||||
},
|
||||
"packages/server": {
|
||||
"name": "@getpaseo/server",
|
||||
"version": "0.1.9",
|
||||
"version": "0.1.12",
|
||||
"dependencies": {
|
||||
"@ai-sdk/openai": "2.0.52",
|
||||
"@anthropic-ai/claude-agent-sdk": "^0.2.11",
|
||||
"@deepgram/sdk": "^3.4.0",
|
||||
"@getpaseo/relay": "0.1.9",
|
||||
"@getpaseo/relay": "0.1.12",
|
||||
"@lezer/common": "^1.5.0",
|
||||
"@lezer/css": "^1.3.0",
|
||||
"@lezer/highlight": "^1.2.3",
|
||||
@@ -20890,7 +20890,7 @@
|
||||
},
|
||||
"packages/website": {
|
||||
"name": "@getpaseo/website",
|
||||
"version": "0.1.9",
|
||||
"version": "0.1.12",
|
||||
"dependencies": {
|
||||
"@cloudflare/vite-plugin": "^1.20.3",
|
||||
"@cloudflare/workers-types": "^4.20260114.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "paseo",
|
||||
"version": "0.1.9",
|
||||
"version": "0.1.12",
|
||||
"private": true,
|
||||
"workspaces": [
|
||||
"packages/server",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@getpaseo/app",
|
||||
"main": "index.ts",
|
||||
"version": "0.1.9",
|
||||
"version": "0.1.12",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"start": "expo start",
|
||||
@@ -30,7 +30,7 @@
|
||||
"@dnd-kit/utilities": "^3.2.2",
|
||||
"@expo/vector-icons": "^15.0.2",
|
||||
"@floating-ui/react-native": "^0.10.7",
|
||||
"@getpaseo/server": "0.1.9",
|
||||
"@getpaseo/server": "0.1.12",
|
||||
"@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.9",
|
||||
"version": "0.1.12",
|
||||
"description": "Paseo CLI - control your AI coding agents from the command line",
|
||||
"type": "module",
|
||||
"files": [
|
||||
@@ -22,8 +22,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@clack/prompts": "^1.0.0",
|
||||
"@getpaseo/relay": "0.1.9",
|
||||
"@getpaseo/server": "0.1.9",
|
||||
"@getpaseo/relay": "0.1.12",
|
||||
"@getpaseo/server": "0.1.12",
|
||||
"chalk": "^5.3.0",
|
||||
"commander": "^12.0.0",
|
||||
"mime-types": "^2.1.35",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@getpaseo/desktop",
|
||||
"version": "0.1.9",
|
||||
"version": "0.1.12",
|
||||
"private": true,
|
||||
"description": "Paseo desktop app (Tauri wrapper)",
|
||||
"scripts": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@getpaseo/relay",
|
||||
"version": "0.1.9",
|
||||
"version": "0.1.12",
|
||||
"description": "Paseo relay for bridging daemon and client connections",
|
||||
"type": "module",
|
||||
"publishConfig": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@getpaseo/server",
|
||||
"version": "0.1.9",
|
||||
"version": "0.1.12",
|
||||
"description": "Paseo backend server",
|
||||
"type": "module",
|
||||
"publishConfig": {
|
||||
@@ -9,6 +9,7 @@
|
||||
"types": "./dist/server/server/exports.d.ts",
|
||||
"files": [
|
||||
"dist/server",
|
||||
"dist/src",
|
||||
"dist/scripts",
|
||||
"README.md",
|
||||
".env.example",
|
||||
@@ -53,7 +54,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@anthropic-ai/claude-agent-sdk": "^0.2.11",
|
||||
"@getpaseo/relay": "0.1.9",
|
||||
"@getpaseo/relay": "0.1.12",
|
||||
"@ai-sdk/openai": "2.0.52",
|
||||
"@deepgram/sdk": "^3.4.0",
|
||||
"@lezer/common": "^1.5.0",
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
import { describe, it, expect, afterEach } from "vitest";
|
||||
import { createTerminal, type TerminalSession } from "./terminal.js";
|
||||
import {
|
||||
createTerminal,
|
||||
ensureNodePtySpawnHelperExecutableForCurrentPlatform,
|
||||
type TerminalSession,
|
||||
} from "./terminal.js";
|
||||
import { chmodSync, mkdtempSync, mkdirSync, rmSync, statSync, writeFileSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
import { tmpdir } from "node:os";
|
||||
|
||||
// Extract text from a single row
|
||||
function getRowText(state: ReturnType<TerminalSession["getState"]>, rowIndex: number): string {
|
||||
@@ -40,12 +47,19 @@ async function waitForLines(
|
||||
|
||||
describe("Terminal", () => {
|
||||
const sessions: TerminalSession[] = [];
|
||||
const temporaryDirs: string[] = [];
|
||||
|
||||
afterEach(async () => {
|
||||
for (const session of sessions) {
|
||||
session.kill();
|
||||
}
|
||||
sessions.length = 0;
|
||||
while (temporaryDirs.length > 0) {
|
||||
const dir = temporaryDirs.pop();
|
||||
if (dir) {
|
||||
rmSync(dir, { recursive: true, force: true });
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function trackSession(session: TerminalSession): TerminalSession {
|
||||
@@ -54,6 +68,24 @@ describe("Terminal", () => {
|
||||
}
|
||||
|
||||
describe("createTerminal", () => {
|
||||
it("ensures darwin prebuild spawn-helper is executable", () => {
|
||||
const packageRoot = mkdtempSync(join(tmpdir(), "terminal-node-pty-helper-"));
|
||||
temporaryDirs.push(packageRoot);
|
||||
const prebuildDir = join(packageRoot, "prebuilds", `darwin-${process.arch}`);
|
||||
mkdirSync(prebuildDir, { recursive: true });
|
||||
const helperPath = join(prebuildDir, "spawn-helper");
|
||||
writeFileSync(helperPath, "#!/bin/sh\necho helper\n");
|
||||
chmodSync(helperPath, 0o644);
|
||||
|
||||
ensureNodePtySpawnHelperExecutableForCurrentPlatform({
|
||||
packageRoot,
|
||||
platform: "darwin",
|
||||
force: true,
|
||||
});
|
||||
|
||||
expect(statSync(helperPath).mode & 0o111).toBe(0o111);
|
||||
});
|
||||
|
||||
it("creates a terminal session with an id, name, and cwd", async () => {
|
||||
const session = trackSession(
|
||||
await createTerminal({
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
import * as pty from "node-pty";
|
||||
import xterm, { type Terminal as TerminalType } from "@xterm/headless";
|
||||
import { randomUUID } from "crypto";
|
||||
import { chmodSync, existsSync, statSync } from "node:fs";
|
||||
import { dirname, join } from "node:path";
|
||||
import { createRequire } from "node:module";
|
||||
|
||||
const { Terminal } = xterm;
|
||||
const require = createRequire(import.meta.url);
|
||||
let nodePtySpawnHelperChecked = false;
|
||||
|
||||
export interface Cell {
|
||||
char: string;
|
||||
@@ -83,6 +88,73 @@ export interface CreateTerminalOptions {
|
||||
name?: string;
|
||||
}
|
||||
|
||||
type EnsureNodePtySpawnHelperExecutableOptions = {
|
||||
packageRoot?: string;
|
||||
platform?: NodeJS.Platform;
|
||||
arch?: string;
|
||||
force?: boolean;
|
||||
};
|
||||
|
||||
function resolveNodePtyPackageRoot(): string | null {
|
||||
try {
|
||||
const packageJsonPath = require.resolve("node-pty/package.json");
|
||||
return dirname(packageJsonPath);
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function ensureExecutableBit(path: string): void {
|
||||
if (!existsSync(path)) {
|
||||
return;
|
||||
}
|
||||
const stat = statSync(path);
|
||||
if (!stat.isFile()) {
|
||||
return;
|
||||
}
|
||||
// node-pty 1.1.0 shipped darwin prebuild spawn-helper without execute bit.
|
||||
if ((stat.mode & 0o111) === 0o111) {
|
||||
return;
|
||||
}
|
||||
chmodSync(path, stat.mode | 0o111);
|
||||
}
|
||||
|
||||
export function ensureNodePtySpawnHelperExecutableForCurrentPlatform(
|
||||
options: EnsureNodePtySpawnHelperExecutableOptions = {}
|
||||
): void {
|
||||
const platform = options.platform ?? process.platform;
|
||||
if (platform !== "darwin") {
|
||||
return;
|
||||
}
|
||||
if (nodePtySpawnHelperChecked && !options.force) {
|
||||
return;
|
||||
}
|
||||
|
||||
const packageRoot = options.packageRoot ?? resolveNodePtyPackageRoot();
|
||||
if (!packageRoot) {
|
||||
return;
|
||||
}
|
||||
const arch = options.arch ?? process.arch;
|
||||
|
||||
const candidates = [
|
||||
join(packageRoot, "build", "Release", "spawn-helper"),
|
||||
join(packageRoot, "build", "Debug", "spawn-helper"),
|
||||
join(packageRoot, "prebuilds", `darwin-${arch}`, "spawn-helper"),
|
||||
];
|
||||
|
||||
for (const candidate of candidates) {
|
||||
try {
|
||||
ensureExecutableBit(candidate);
|
||||
} catch {
|
||||
// best-effort hardening only
|
||||
}
|
||||
}
|
||||
|
||||
if (!options.force) {
|
||||
nodePtySpawnHelperChecked = true;
|
||||
}
|
||||
}
|
||||
|
||||
function extractCell(terminal: TerminalType, row: number, col: number): Cell {
|
||||
const buffer = terminal.buffer.active;
|
||||
const line = buffer.getLine(row);
|
||||
@@ -212,6 +284,8 @@ export async function createTerminal(options: CreateTerminalOptions): Promise<Te
|
||||
allowProposedApi: true,
|
||||
});
|
||||
|
||||
ensureNodePtySpawnHelperExecutableForCurrentPlatform();
|
||||
|
||||
// Create PTY
|
||||
const ptyProcess = pty.spawn(shell, [], {
|
||||
name: "xterm-256color",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@getpaseo/website",
|
||||
"version": "0.1.9",
|
||||
"version": "0.1.12",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
||||
Reference in New Issue
Block a user