mirror of
https://github.com/getpaseo/paseo.git
synced 2026-07-29 12:01:31 +00:00
fix: honor current branch in new workspace flow (#908)
* fix: honor current branch in new workspace flow * Use OpenCode global event stream (#916) * Use OpenCode global event stream * Use stable OpenCode model in initial prompt e2e * Clean up OpenCode verification notes * chore: changelog for 0.1.74 * chore(release): cut 0.1.74 * Fix custom Codex provider base URL routing (#915) * Wire Copilot Allow All mode to ACP permissions (#935) * Add trace logging and tighten daemon log defaults (#933) * Add trace logging and tighten daemon log defaults * Clean up daemon trace logging shape * Clean up daemon trace logging * Route provider turn-id checks through shared helper * Fix supervisor log config test paths on Windows * Expect resolved supervisor log path on Windows * nix: declarative config, typed relay options, desktop packaging (#923) * nix: expose npmDepsHash as a callPackage arg Downstream flakes that follow a different nixpkgs revision can hit a hash mismatch on the npm-deps FOD even though package-lock.json is unchanged, because fetchNpmDeps output is sensitive to nixpkgs version. The standard fix — `.overrideAttrs { npmDepsHash = ...; }` — does not work for buildNpmPackage: npmDepsHash is destructured from args, so the default `npmDeps = fetchNpmDeps { hash = npmDepsHash; }` is already bound by the time overrideAttrs runs. Promote npmDepsHash to a callPackage arg with the current value as the default. Consumers can now `.override { npmDepsHash = "sha256-..."; }` and have it propagate to the npmDeps fetcher. Upstream CI behavior is unchanged — update-nix.sh is adjusted to match the new `npmDepsHash ? "..."` pattern. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * nix: move npmDepsHash default to a sidecar file Read the default `npmDepsHash` from `nix/npm-deps.hash` via `lib.fileContents` instead of inlining it as a string literal in `nix/package.nix`. The CI auto-updater becomes a one-line file write instead of a regex against a .nix source — decoupling lockfile bumps from the formatting of the package definition. No behavior change: same hash, same default, same `.override` surface. Lockfile diffs become smaller and the update path stops being load- bearing on a sed pattern. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * nix: declarative config via services.paseo.settings Today only a handful of `config.json` fields are surfaced as module options (listen, port, hostnames, relay.enable). Anything richer — custom agent providers, MCP injection, log config, voice features — requires hand-editing `$PASEO_HOME/config.json`. Add `services.paseo.settings` as a freeform attrset rendered to JSON via `pkgs.formats.json` and installed at `$PASEO_HOME/config.json` on each service start. Standard NixOS idiom. `install` on `preStart` rather than a `tmpfiles` symlink because the daemon writes to `config.json` at runtime via `DaemonConfigStore.patch` (MCP / provider toggles). A read-only symlink would break those writes; a copy-on-start lets the daemon mutate freely within a session while the Nix-managed file remains the source of truth at boot. The full schema is `PersistedConfigSchema` in `packages/server/src/server/persisted-config.ts`. Documented in the option description that runtime mutations don't survive restarts when `settings` is non-empty. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * nix: typed services.paseo.relay options with auto-wired endpoint Addresses #224 (option surface only). Today `services.paseo.relay.enable` is a bool that just toggles `--no-relay`. Pointing the daemon at a self-hosted relay requires hand-setting `PASEO_RELAY_ENDPOINT` and `PASEO_RELAY_USE_TLS` via the freeform `environment` option. Add a typed relay subtree: - `relay.mode = "hosted" | "remote"` selects how the daemon reaches the relay when enabled. Default is `"hosted"` (current behavior). - `relay.{host,port,useTls}` configure the `"remote"` case. - The module auto-wires `PASEO_RELAY_ENDPOINT` and `PASEO_RELAY_USE_TLS` when `mode = "remote"`. - Assertion fires at eval time when `mode = "remote"` but `host` is empty. - `relay.enable` keeps its current semantics — bool answers "is it on?", the new options answer "how is it configured?". The `"local"` mode from #224 (running a relay on the same host as a systemd unit) is deliberately not added here: `packages/relay` ships only a Cloudflare Workers adapter, so there's no Node.js runtime to package as a binary. Adding a Node adapter is a TS-side feature change worth its own design discussion; tracked as a follow-up. No breaking changes — existing `relay.enable = true|false` configs evaluate unchanged with the new `mode = "hosted"` default. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * nix: package paseo desktop app for Linux NixOS users have no easy way to run the desktop app today — electron-builder's outputs (.deb, .rpm, .AppImage) don't fit Nix's model, so `nix run github:getpaseo/paseo#desktop` doesn't exist. Add `packages.<linux>.desktop` following the standard nixpkgs Electron pattern (see e.g. signal-desktop, vscode): skip electron-builder entirely, build the desktop main process with `tsc`, bundle the Expo web export and built daemon workspaces, and wrap `pkgs.electron` with `makeWrapper`. Output is a runnable derivation usable via `nix run` or `environment.systemPackages`. The install layout preserves the monorepo source tree (`packages/desktop/dist/main.js`, `packages/app/dist`, `node_modules` at the workspace root) so `main.ts`'s dev-mode path resolution (`__dirname/../../app/dist`, `__dirname/../assets/icon.png`) works without any source patches. When Electron is invoked unpackaged via `electron path/to/main.js`, `app.isPackaged` is false and these relative paths are used. `--no-sandbox` is set on the launcher: Chromium's setuid sandbox can't live in `/nix/store` (immutable, no setuid). A follow-up can wire `security.wrappers` from a NixOS module for users who want the renderer sandbox. No CI changes — `desktop-release.yml` continues to produce .deb/.AppImage/.rpm/macOS/Windows installers as today. This is purely additive for NixOS users. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * nix: copy full packages/ tree in desktop derivation The previous installPhase selectively copied built artifacts (dist/ under server, cli, relay, highlight, expo-two-way-audio), which left two workspace symlinks dangling and failed noBrokenSymlinks: - node_modules/@getpaseo/expo-two-way-audio → packages/expo-two-way-audio (the Expo native module ships source + native projects, no built dist/) - node_modules/.bin/paseo → @getpaseo/cli/bin/paseo (the CLI launcher script lives under bin/, not dist/) npm workspace symlinks expect every workspace package to exist at its source path. Copy the whole packages/ tree instead. The cleanSourceWith filter already excludes the heavy platform-specific paths (android/ios under packages/app, website, tests), and the remaining ~16MB of src is acceptable for an Electron app derivation. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * nix: route desktop renderer through paseo:// protocol handler When `paseo-desktop` is launched via `electron path/to/main.js` (our unpackaged Nix layout), `app.isPackaged` is false and main.ts loads `DEV_SERVER_URL` — which defaults to http://localhost:8081 (the Expo dev server). That URL has nothing listening in a Nix-installed run, so the renderer fails with ERR_CONNECTION_REFUSED. main.ts already supports overriding this via the `EXPO_DEV_URL` env var. Set it to `paseo://app/` so the request goes through the `paseo://` protocol handler that main.ts registers unconditionally. The handler resolves files via `getAppDistDir()`, which in the unpackaged branch returns `__dirname/../../app/dist` — exactly where our install layout places the Expo web export. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * ci: track nix/npm-deps.hash in nix-build commit step The commit step still referenced nix/package.nix in its diff check and git add. After moving the hash to nix/npm-deps.hash, the auto-updated hash would never be staged and the new value would sit unstaged in the working tree forever. * ci: push nix-build hash commits via paseo-ai[bot] App token The default GITHUB_TOKEN cannot bypass main's required status checks, so the auto-commit of stale Nix hash updates has been silently failing. Mint an installation token for the paseo-ai App (which is in the ruleset bypass list) and use it for checkout and push. --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-authored-by: Mohamed Boudra <boudra.moha@gmail.com> * Normalize HEIC image attachments on the client (#934) * Normalize HEIC attachments before persistence * Preserve native JPEG and PNG picks * fix: update lockfile signatures and Nix hash * ci: skip App token on PRs in nix-build Fork PRs cannot read repo secrets, so the App-token step failed with 'Input required and not supplied: app-id'. Gate the App-token step on push-to-main and fall back to github.token for the checkout on PRs, since PRs only need to validate the build. * ci: skip CI on nix-build auto hash commits The hash-update commit only changes package-lock.json and nix/npm-deps.hash. The parent commit already passed all 13 required checks, and the file diff is content-only, so re-running the full suite on every hash bump is wasted CI minutes. * ci: drop unused contents: write override in nix-build GITHUB_TOKEN no longer pushes anything in this workflow. PR runs are read-only, and main pushes go through the paseo-ai App token. The workflow-level 'contents: read' is sufficient. Addresses #365. * ci: gate nix-build on same-repo PRs only scripts/update-nix.sh and scripts/fix-lockfile.mjs are executed from the PR's checked-out tree. A fork PR can modify those scripts to run arbitrary code on the runner. Same-repo PRs and push-to-main still run; fork PRs skip the job entirely. Closes #365. * ci: split nix workflow into build (anywhere) + update-hash (main only) build runs on push to main and every PR including forks. Same model as the test/lint/typecheck workflows: read-only token, no secrets injected, runs scripts/update-nix.sh + nix build to validate. No commit, no push. update-hash runs only on push to main. Mints the paseo-ai App token, re-runs the update + build, and commits the refreshed hash via the ruleset bypass. The default GITHUB_TOKEN no longer pushes anywhere. Rename file to nix.yml since it's no longer just a build job. * ci: split nix into two workflows nix.yml: PR-only build check. nix-update-hash.yml: push-to-main hash update via paseo-ai App token. * Fix iPad sidebar safe area background (#937) Co-authored-by: zbl <zbl@zbl-M4Pro.local> * Fix desktop daemon stale PID startup (#913) * Configure STT language from settings (#941) * Configure STT language from settings * Update websocket speech mock for language config * Handle Windows shell wrappers in Codex command summaries (#931) * fix(app): respect iPad safe area in settings sidebar (#922) Co-authored-by: zbl <zbl@zbl-M4Pro.local> * ci(nix): smoke test daemon boot (#939) * Fix scheduled agent cleanup (#945) * Fail Codex resume requests explicitly (#947) * fix(copilot): preserve legacy autopilot mode alias * docs(changelog): draft 0.1.75 entry * chore(release): cut 0.1.75 * fix: update lockfile signatures and Nix hash [skip ci] * docs(changelog): refine 0.1.75 entry * fix: preserve worktree action literal types --------- Co-authored-by: Mohamed Boudra <boudra.moha@gmail.com> Co-authored-by: Matan Bendix Shenhav <matan@shenhav.fyi> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-authored-by: paseo-ai[bot] <266920839+paseo-ai[bot]@users.noreply.github.com> Co-authored-by: Bolun Zhang <zhaggbl@mail.ustc.edu.cn> Co-authored-by: zbl <zbl@zbl-M4Pro.local> Co-authored-by: Biao Ma <sigemaict@gmail.com> Co-authored-by: ezra <ezra.ora.c@gmail.com>
This commit is contained in:
@@ -30,14 +30,32 @@ import { navigateToPreparedWorkspaceTab } from "@/utils/workspace-navigation";
|
||||
import type { ComposerAttachment, UserComposerAttachment } from "@/attachments/types";
|
||||
import type { ImageAttachment, MessagePayload } from "@/components/message-input";
|
||||
import type { AgentAttachment, GitHubSearchItem } from "@server/shared/messages";
|
||||
import type { CreatePaseoWorktreeInput } from "@server/client/daemon-client";
|
||||
import type { AgentProvider } from "@server/server/agent/agent-sdk-types";
|
||||
import { isEmptyWorkspaceSubmission, runCreateEmptyWorkspace } from "./new-workspace-empty";
|
||||
import { pickerItemToCheckoutRequest, type PickerItem } from "./new-workspace-picker-item";
|
||||
import {
|
||||
pickerItemToCheckoutRequest,
|
||||
type PickerCheckoutRequest,
|
||||
type PickerItem,
|
||||
} from "./new-workspace-picker-item";
|
||||
import {
|
||||
deriveAutoPickerItemFromAttachments,
|
||||
syncPickerPrAttachment,
|
||||
} from "./new-workspace-picker-state";
|
||||
|
||||
function resolveCheckoutRequest(
|
||||
selectedItem: PickerItem | null,
|
||||
currentBranch: string | null,
|
||||
): PickerCheckoutRequest | undefined {
|
||||
const selectedCheckoutRequest = pickerItemToCheckoutRequest(selectedItem);
|
||||
if (selectedCheckoutRequest) return selectedCheckoutRequest;
|
||||
if (!currentBranch) return undefined;
|
||||
return {
|
||||
action: "branch-off",
|
||||
refName: currentBranch,
|
||||
};
|
||||
}
|
||||
|
||||
interface NewWorkspaceScreenProps {
|
||||
serverId: string;
|
||||
sourceDirectory: string;
|
||||
@@ -583,8 +601,12 @@ export function NewWorkspaceScreen({
|
||||
}, []);
|
||||
|
||||
const buildCreateWorktreeInput = useCallback(
|
||||
(input: { cwd: string; prompt: string; attachments: AgentAttachment[] }) => {
|
||||
const checkoutRequest = pickerItemToCheckoutRequest(selectedItem);
|
||||
(input: {
|
||||
cwd: string;
|
||||
prompt: string;
|
||||
attachments: AgentAttachment[];
|
||||
}): CreatePaseoWorktreeInput => {
|
||||
const checkoutRequest = resolveCheckoutRequest(selectedItem, currentBranch);
|
||||
const trimmedPrompt = input.prompt.trim();
|
||||
const hasFirstAgentContext = trimmedPrompt.length > 0 || input.attachments.length > 0;
|
||||
|
||||
@@ -602,7 +624,7 @@ export function NewWorkspaceScreen({
|
||||
...checkoutRequest,
|
||||
};
|
||||
},
|
||||
[selectedItem],
|
||||
[currentBranch, selectedItem],
|
||||
);
|
||||
|
||||
const ensureWorkspace = useCallback(
|
||||
|
||||
Reference in New Issue
Block a user