@omercnet/paseo-pr-radar 0.4.1 → 1.0.0-next.155.1

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.
package/README.md CHANGED
@@ -30,7 +30,7 @@ Paseo supplies normalized workspace pull request status. A daemon-side plugin ha
30
30
 
31
31
  ## Install
32
32
 
33
- ### Paseo 0.9 beta
33
+ ### Paseo 0.9
34
34
 
35
35
  Paseo 0.9 supports npm plugin sources. Install the published package on the daemon host:
36
36
 
@@ -44,44 +44,25 @@ Update an npm installation to the latest published release:
44
44
  paseo plugin update pr-radar
45
45
  ```
46
46
 
47
- The npm install and update flow requires Paseo 0.9. Paseo 0.8 does not accept npm plugin sources.
47
+ The npm install and update flow requires Paseo 0.9.
48
48
 
49
- ### Paseo 0.8
50
-
51
- Install from the Git monorepo:
52
-
53
- ```bash
54
- paseo plugin add omercnet/paseo-plugins:pr-radar
55
- ```
56
-
57
- Or install a local checkout by absolute path on the daemon host:
58
-
59
- ```bash
60
- paseo plugin install /absolute/path/to/paseo-plugins/pr-radar
61
- ```
62
-
63
- On Paseo 0.8, `plugin update` updates Git-managed installations only. Local directory
64
- installations continue to use their checked-out source and require `plugin reload` after edits.
65
49
 
66
50
  The daemon must have plugins enabled and `gh` authenticated for GitHub viewer-aware triage.
67
51
 
68
52
  ## Develop
69
53
 
70
54
  ```bash
71
- npm ci
72
- npm run check
73
- npm test
74
- npm run test:coverage
75
- npm run typecheck
76
- npx paseo plugin install "$PWD"
77
- npx paseo plugin reload pr-radar
55
+ bun install
56
+ bun run check
57
+ bun run test
58
+ bun run test:coverage
59
+ bun run typecheck
78
60
  ```
79
61
 
80
62
  Release Please maintains the version, changelog, component tag, and GitHub release from
81
63
  Conventional Commits in the monorepo.
82
64
 
83
- The manifest supports Paseo `0.8.x`, including compatible `0.8` prereleases, and Paseo
84
- `0.9.0-beta.1`. Development uses the `0.9.0-beta.1` CLI, client, plugin SDK, and protocol packages
85
- together while preserving runtime compatibility with 0.8 hosts. Host-owned navigation opens
86
- linked agents and workspaces without private routes or page reloads on web, desktop, iOS, and
87
- Android. React `19.1` and React Native `0.81` match the versions supplied by the plugin host.
65
+ The manifest requires Paseo `^0.9.0`. Development uses the `0.9.0` CLI, client, plugin SDK, and
66
+ protocol packages together. Host-owned navigation opens linked agents and workspaces without private
67
+ routes or page reloads on web, desktop, iOS, and Android. React `19.1` and React Native `0.81`
68
+ match the versions supplied by the plugin host.
@@ -0,0 +1,55 @@
1
+ import type { PaseoApi } from "./radar";
2
+
3
+ export function observeDirectoryInvalidation(
4
+ paseo: PaseoApi,
5
+ invalidate: () => void,
6
+ debounceMs: number,
7
+ ): () => void {
8
+ const lifetime = new AbortController();
9
+ const subscriptions: Array<{ release(): Promise<void> }> = [];
10
+ const unsubscribes: Array<() => void> = [];
11
+ let stopped = false;
12
+ let timer: NodeJS.Timeout | undefined;
13
+ const scheduleInvalidation = () => {
14
+ if (stopped || timer !== undefined) return;
15
+ timer = setTimeout(() => {
16
+ timer = undefined;
17
+ if (!stopped) invalidate();
18
+ }, debounceMs);
19
+ };
20
+ const attach = (subscription: {
21
+ subscribe(observer: { snapshot(): void; update(message: unknown): void }): () => void;
22
+ release(): Promise<void>;
23
+ }) => {
24
+ subscriptions.push(subscription);
25
+ if (stopped) {
26
+ void subscription.release().catch(() => undefined);
27
+ return;
28
+ }
29
+ unsubscribes.push(
30
+ subscription.subscribe({
31
+ snapshot: scheduleInvalidation,
32
+ update: scheduleInvalidation,
33
+ }),
34
+ );
35
+ };
36
+
37
+ void paseo.agents
38
+ .list({ subscribe: {}, signal: lifetime.signal })
39
+ .then(({ subscription }) => attach(subscription))
40
+ .catch(() => undefined);
41
+ void paseo.workspaces
42
+ .list({ subscribe: {} })
43
+ .then(({ subscription }) => attach(subscription))
44
+ .catch(() => undefined);
45
+
46
+ return () => {
47
+ stopped = true;
48
+ lifetime.abort();
49
+ if (timer !== undefined) clearTimeout(timer);
50
+ for (const unsubscribe of unsubscribes) unsubscribe();
51
+ void Promise.all(subscriptions.map((subscription) => subscription.release())).catch(
52
+ () => undefined,
53
+ );
54
+ };
55
+ }
@@ -1,17 +1,14 @@
1
- import * as PaseoClient from "@getpaseo/plugin/client";
2
- import { type PluginSurfaceProps, usePaseo, useRpc } from "@getpaseo/plugin/client";
1
+ import {
2
+ openExternalUrl,
3
+ type PluginSurfaceProps,
4
+ usePaseo,
5
+ useRpc,
6
+ } from "@getpaseo/plugin/client";
3
7
  import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
4
8
  import { useCallback, useEffect, useMemo, useState } from "react";
5
- import {
6
- ActivityIndicator,
7
- FlatList,
8
- Linking,
9
- Pressable,
10
- Text,
11
- TextInput,
12
- View,
13
- } from "react-native";
9
+ import { ActivityIndicator, FlatList, Pressable, Text, TextInput, View } from "react-native";
14
10
  import { acknowledgeViewerScope, viewerScope } from "../shared/viewer-scope";
11
+ import { observeDirectoryInvalidation } from "./directory-observation";
15
12
  import {
16
13
  type AgentEntry,
17
14
  agentActionFor,
@@ -40,11 +37,6 @@ const CLOCK_TICK_MS = 30_000;
40
37
 
41
38
  type SavedView = "security" | "updated" | "stale" | "automation";
42
39
 
43
- const openExternalUrlCandidate: unknown = Reflect.get(PaseoClient, "openExternalUrl");
44
- const guardedOpenExternalUrl =
45
- typeof openExternalUrlCandidate === "function"
46
- ? (openExternalUrlCandidate as (url: string) => Promise<void>)
47
- : undefined;
48
40
  const SAVED_VIEW_TITLES: Record<SavedView, string> = {
49
41
  security: "Security",
50
42
  updated: "Updated",
@@ -136,23 +128,15 @@ export function PrRadar({ theme, layout, host, navigation }: PluginSurfaceProps)
136
128
  return () => clearInterval(clock);
137
129
  }, []);
138
130
 
139
- useEffect(() => {
140
- let timer: ReturnType<typeof setTimeout> | undefined;
141
- const invalidate = () => {
142
- if (timer) return;
143
- timer = setTimeout(() => {
144
- timer = undefined;
145
- void queryClient.invalidateQueries({ queryKey });
146
- }, EVENT_DEBOUNCE_MS);
147
- };
148
- const unsubscribeAgents = paseo.agents.subscribe(invalidate);
149
- const unsubscribeWorkspaces = paseo.workspaces.subscribe(invalidate);
150
- return () => {
151
- clearTimeout(timer);
152
- unsubscribeAgents();
153
- unsubscribeWorkspaces();
154
- };
155
- }, [paseo, queryClient, queryKey]);
131
+ useEffect(
132
+ () =>
133
+ observeDirectoryInvalidation(
134
+ paseo,
135
+ () => void queryClient.invalidateQueries({ queryKey }),
136
+ EVENT_DEBOUNCE_MS,
137
+ ),
138
+ [paseo, queryClient, queryKey],
139
+ );
156
140
 
157
141
  const rawRows = data?.rows ?? [];
158
142
  const scopeUrls = useMemo(() => rawRows.map((row) => row.url), [rawRows]);
@@ -523,7 +507,7 @@ export function PrRadar({ theme, layout, host, navigation }: PluginSurfaceProps)
523
507
  const openPr = useCallback(async (row: RadarRow) => {
524
508
  setOpenError(null);
525
509
  try {
526
- await openPullRequestUrl(row.url, guardedOpenExternalUrl, Linking);
510
+ await openPullRequestUrl(row.url, openExternalUrl);
527
511
  } catch {
528
512
  setOpenError(`Could not open ${row.repository}#${row.number ?? "PR"}.`);
529
513
  }
package/client/radar.ts CHANGED
@@ -314,19 +314,10 @@ export function buildAgentPrompt(row: RadarRow): string {
314
314
 
315
315
  type UrlOpener = (url: string) => Promise<unknown>;
316
316
 
317
- export async function openPullRequestUrl(
318
- url: string,
319
- guardedOpen: UrlOpener | undefined,
320
- fallback: { openURL: UrlOpener },
321
- ): Promise<void> {
317
+ export async function openPullRequestUrl(url: string, open: UrlOpener): Promise<void> {
322
318
  const parsed = HttpsUrlSchema.safeParse(url);
323
319
  if (!parsed.success) throw new Error("Only HTTPS pull request URLs are supported.");
324
-
325
- if (guardedOpen) {
326
- await guardedOpen(parsed.data);
327
- return;
328
- }
329
- await fallback.openURL(parsed.data);
320
+ await open(parsed.data);
330
321
  }
331
322
 
332
323
  export function buildRadarSnapshot(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@omercnet/paseo-pr-radar",
3
- "version": "0.4.1",
3
+ "version": "1.0.0-next.155.1",
4
4
  "type": "module",
5
5
  "description": "A viewer-aware delivery queue for pull requests linked to Paseo workspaces.",
6
6
  "license": "MIT",
@@ -17,7 +17,7 @@
17
17
  "publishConfig": {
18
18
  "access": "public"
19
19
  },
20
- "packageManager": "npm@11.19.1",
20
+ "packageManager": "bun@1.4.2",
21
21
  "engines": {
22
22
  "node": ">=24"
23
23
  },
@@ -42,24 +42,23 @@
42
42
  "check:write": "biome check --write .",
43
43
  "test": "vitest run",
44
44
  "test:coverage": "vitest run --coverage --coverage.reporter=text --coverage.reporter=lcov --coverage.thresholds.lines=90 --coverage.thresholds.functions=85",
45
- "typecheck": "tsc --noEmit",
46
- "package:release": "node scripts/package-release.ts"
45
+ "typecheck": "tsc --noEmit"
47
46
  },
48
47
  "devDependencies": {
49
48
  "@biomejs/biome": "^2.5.10",
50
- "@getpaseo/cli": "0.9.0-beta.1",
51
- "@getpaseo/client": "0.9.0-beta.1",
52
- "@getpaseo/plugin": "0.9.0-beta.1",
53
- "@getpaseo/protocol": "0.9.0-beta.1",
49
+ "@getpaseo/cli": "0.9.0",
50
+ "@getpaseo/client": "0.9.0",
51
+ "@getpaseo/plugin": "0.9.0",
52
+ "@getpaseo/protocol": "0.9.0",
54
53
  "@tanstack/react-query": "^5.102.3",
55
- "@types/node": "^24.5.2",
56
- "@types/react": "~19.2.0",
54
+ "@types/node": "^24.10.1",
55
+ "@types/react": "^19.2.18",
56
+ "@vitest/coverage-v8": "^5.0.0",
57
57
  "fflate": "^0.8.3",
58
58
  "react": "19.1.0",
59
59
  "react-native": "0.81.5",
60
- "typescript": "^7.0.0",
61
- "@vitest/coverage-v8": "^5.0.0",
60
+ "typescript": "^7.0.2",
62
61
  "vitest": "^5.0.0",
63
- "zod": "^4.4.3"
62
+ "zod": "4.4.3"
64
63
  }
65
64
  }
package/paseo-plugin.json CHANGED
@@ -1,4 +1,5 @@
1
1
  {
2
2
  "id": "pr-radar",
3
- "requirements": { "paseo": "^0.8.0 || ^0.9.0-beta.1" }
3
+ "description": "A viewer-aware delivery queue for pull requests linked to Paseo workspaces.",
4
+ "requirements": { "paseo": "^0.9.0" }
4
5
  }