@omercnet/paseo-omp 1.3.3-next.232.1 → 1.3.3-next.241.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/OVERVIEW.md CHANGED
@@ -2,7 +2,7 @@ OMP adds an agent provider for the OMP coding agent, plus an OMP sidebar and wor
2
2
 
3
3
  ## Setup
4
4
 
5
- - Paseo 0.9.2 through 0.9.x, 0.10.x or 0.11.x.
5
+ - Paseo ^0.11.0.
6
6
  - OMP 18.1.15 or newer on the daemon host, speaking RPC protocol v2. Older runtimes are rejected.
7
7
  - Provider options let you change the OMP command, set environment values, choose an output redaction mode and set a session directory and timeout. Named OMP profiles appear as separate `OMP · <profile>` providers.
8
8
 
package/README.md CHANGED
@@ -24,7 +24,7 @@ before capture.
24
24
 
25
25
  ## Quick start
26
26
 
27
- Requirements: Paseo `^0.9.2 || ^0.10.0 || ^0.11.0`, OMP `18.1.15` or newer, and OMP RPC protocol v2. Paseo 0.9.2 is required for reliable plugin-provider request failure containment, reload cleanup, and daemon shutdown ordering; 0.10.1 is verified against the same public plugin contracts.
27
+ Requirements: Paseo `^0.11.0`, OMP `18.1.15` or newer, and OMP RPC protocol v2. The config screen and Hub row use the 0.11 screen and sidebar APIs, so Paseo 0.9 and 0.10 hosts are no longer supported.
28
28
 
29
29
  ```bash
30
30
  paseo plugin install npm:@omercnet/paseo-omp@<version>
@@ -40,7 +40,7 @@ Open the **OMP** sidebar to review the provider-profile contract, choose which c
40
40
  - [Core-provider issue and parity audit](docs/core-provider-issue-audit.md)
41
41
  - [Release checklist](docs/release-checklist.md)
42
42
 
43
- The plugin uses public Paseo 0.9 and 0.10 provider and client contracts and registers distinct `omp-plugin` and `omp-plugin-<profile>` identities; it does not modify the bundled `omp` provider.
43
+ The plugin uses public Paseo 0.11 provider and client contracts and registers distinct `omp-plugin` and `omp-plugin-<profile>` identities; it does not modify the bundled `omp` provider.
44
44
 
45
45
  ## Named OMP profiles
46
46
 
@@ -55,7 +55,7 @@ Profile selection is request-local: concurrent clients cannot change each other'
55
55
  ## Paseo provider SDK coverage
56
56
 
57
57
  The capability inventory is pinned to `@getpaseo/plugin` 0.11.1, with nightly compatibility checks
58
- against supported 0.9 and 0.10 hosts and the latest/beta channels. Provider capability scoring covers
58
+ against the latest and beta channels. Provider capability scoring covers
59
59
  all 17 entries in the SDK's `PROVIDER_CAPABILITIES`; the separate provider/client SDK table below
60
60
  also tracks the 0.11 registration, screen, and sidebar APIs. This measures strict SDK surface
61
61
  coverage, not general product quality.
@@ -106,7 +106,7 @@ Provider functionality outside the capability flags is tracked separately:
106
106
  | Built-in timeline snapshots | **100%** | Assistant, reasoning, tools, todos, notifications, errors, compaction, and friendly MCP labels use stable IDs and complete snapshots. OMP emits client-safe PNG/JPEG when possible; validated legacy WebP images render on capable clients with an explicit per-image fallback elsewhere. |
107
107
  | Usage reporting | **100%** | Periodic, post-compaction, fallback, terminal, timeout, and recovered-runtime samples publish `session.usage`. |
108
108
  | 0.11 provider `status()` | **0%** | Not registered. Its request carries only an optional daemon-resolved `launch`; the daemon supplies one only when a registration declares `command`, which would move launch ownership to the daemon. Without that, status cannot see per-agent `providerOptions.command`, so probing a guessed default could wrongly mark a valid custom-command provider unavailable. |
109
- | 0.11 screens and sidebar items | **100%** | The global config surface migrates to `addScreen({ id: "config" })`, preserving legacy links and encoding profile selection in screen params. The Hub status row uses `addSidebarHeaderItem` + `SidebarRow`, lists processes and tails logs in a reusable popover. Hosts without the 0.11 APIs retain the static config row/surface; the Hub row is 0.11-only. |
109
+ | 0.11 screens and sidebar items | **100%** | The global config surface migrates to `addScreen({ id: "config" })`, preserving legacy links and encoding profile selection in screen params. The Hub status row uses `addSidebarHeaderItem` + `SidebarRow`, lists processes and tails logs in a reusable popover. The legacy static config row and surface were removed with the 0.11 floor. |
110
110
  | 0.11 usage source | **0%** | Not registered. `server/quota.ts` reads OMP's recorded `usage_history`, not live quota, so there is no live fetcher to register. Upstream Claude and Codex sources fetch live quota for the Anthropic and Codex OAuth credentials in the daemon's default or `OMP_PROFILE` store; other providers and named profiles remain covered only by this plugin's historical quota pill. |
111
111
 
112
112
  Tracking rules:
@@ -124,7 +124,7 @@ Existing agents whose provider is `omp` remain owned by the bundled provider. Ne
124
124
 
125
125
  OMP `18.1.15` is the oldest version tested end to end. The direct provider's hard compatibility gate is `rpc-ui` protocol v2: metadata-free legacy ready frames and v1-only runtimes are rejected before a provider session opens because they cannot support the advertised persistence and conversation-rewind capabilities. Typed tool approvals remain capability-gated and fall back as described above. For terminal completion, a matching `agent_end.requestId` is authoritative and mismatches are ignored before state changes. Released OMP 18.2.x builds that omit that field use an ordered fallback requiring a fresh correlated native user entry followed by current-turn assistant activity, an idle non-compacting runtime, and no conflicting permission, tool, steer, or child-session work. Ambiguous events while OMP is active are ignored; unresolved ambiguity after confirmed idle fails only the Paseo turn. This trades a bounded residual same-agent stale-event risk for compatibility with released OMP instead of terminating and lazily restarting the runtime after every later prompt. Paseo clients, including mobile clients inside reconnect grace, do not own or terminate the daemon-managed OMP session.
126
126
 
127
- Paseo 0.9.2 is the minimum supported stable release, and 0.10.1 is supported. The controlled Docker canary is pinned to official 0.11.1; nightly SDK checks cover the newest 0.9 and 0.10 patches plus the latest and beta channels. Older Paseo lines are covered by that typecheck/unit matrix, not the current Docker canary. The canary preserves nested provider-subagent ancestry and spawning-tool links, and validates npm-managed plugin sources, platform-owned external URL opening, and whole-item timeline transforms before Overview grouping.
127
+ Paseo 0.11 is the minimum supported release. The controlled Docker canary is pinned to official 0.11.1; nightly SDK checks cover the latest and beta channels. The canary preserves nested provider-subagent ancestry and spawning-tool links, and validates npm-managed plugin sources, platform-owned external URL opening, and whole-item timeline transforms before Overview grouping.
128
128
 
129
129
  Install, update, disable, or remove `paseo-omp` independently of the bundled provider. Verify the provider snapshot contains `omp-plugin` after installation; a bundled `omp` entry may remain present and is not modified by this plugin.
130
130
 
@@ -1,9 +1,6 @@
1
- import type { PluginHostProps } from "@getpaseo/plugin/client";
2
- // Namespace import: on 0.9/0.10 hosts this module lacks SidebarRow, which is only rendered from
3
- // 0.11-only sidebar items. Typed locally so older SDK typechecks still compile.
4
- import * as pluginUi from "@getpaseo/plugin/client/ui";
1
+ import type { PluginPopoverProps, PluginSidebarItemProps } from "@getpaseo/plugin/client";
2
+ import { SidebarRow } from "@getpaseo/plugin/client/ui";
5
3
  import { useQuery } from "@tanstack/react-query";
6
- import type { ComponentType, ReactNode } from "react";
7
4
  import { Text, View } from "react-native";
8
5
  import { HubProcessList } from "./hub-popover";
9
6
  import { CONFIG_SCREEN_ID, type HubSnapshot, hubTrailing } from "./sidebar-compat";
@@ -12,40 +9,7 @@ import { CONFIG_SCREEN_ID, type HubSnapshot, hubTrailing } from "./sidebar-compa
12
9
  const HUB_POLL_MS = 15_000;
13
10
  const HUB_SIDEBAR_QUERY_KEY = ["paseo-omp", "hub-sidebar"] as const;
14
11
 
15
- interface OpenScreenInput {
16
- screenId: string;
17
- params?: Record<string, string>;
18
- }
19
- type HostProps = Pick<PluginHostProps, "theme" | "layout">;
20
- interface PopoverProps extends HostProps {
21
- close(): void;
22
- openScreen(input: OpenScreenInput): void;
23
- }
24
- interface SidebarItemProps extends HostProps {
25
- currentScreen: { screenId: string; params: Record<string, string> } | null;
26
- openScreen(input: OpenScreenInput): void;
27
- openPopover(Content: ComponentType<PopoverProps>): void;
28
- }
29
- type SidebarRowComponent = ComponentType<{
30
- id?: string;
31
- icon?: string | ComponentType<{ size: number; color: string }>;
32
- label?: string;
33
- onPress(): void;
34
- active?: boolean;
35
- trailing?: ReactNode;
36
- }>;
37
-
38
- const uiModule: object = pluginUi;
39
- // Present on every 0.11 host, the only hosts that render these items. The guard and cast keep
40
- // older-SDK typechecks (which lack SidebarRow) compiling; presence check only, because host
41
- // components may be memo/forwardRef objects rather than plain functions.
42
- const SidebarRow: SidebarRowComponent | undefined =
43
- "SidebarRow" in uiModule && uiModule.SidebarRow
44
- ? (uiModule.SidebarRow as SidebarRowComponent)
45
- : undefined;
46
-
47
- export function ConfigSidebarItem({ currentScreen, openScreen }: SidebarItemProps) {
48
- if (!SidebarRow) return null;
12
+ export function ConfigSidebarItem({ currentScreen, openScreen }: PluginSidebarItemProps) {
49
13
  return (
50
14
  <SidebarRow
51
15
  icon="Settings"
@@ -64,7 +28,7 @@ export function createHubSidebar(loadSnapshot: () => Promise<HubSnapshot>) {
64
28
  refetchInterval: HUB_POLL_MS,
65
29
  });
66
30
 
67
- function HubSidebarPopover({ theme, layout }: PopoverProps) {
31
+ function HubSidebarPopover({ theme, layout }: PluginPopoverProps) {
68
32
  const snapshot = useHubSnapshot();
69
33
  const muted = { color: theme.colors.foregroundMuted, fontSize: 13 };
70
34
  if (snapshot.isLoading) return <Text style={muted}>Loading hub processes…</Text>;
@@ -102,9 +66,8 @@ export function createHubSidebar(loadSnapshot: () => Promise<HubSnapshot>) {
102
66
  );
103
67
  }
104
68
 
105
- function HubSidebarItem({ theme, openPopover }: SidebarItemProps) {
69
+ function HubSidebarItem({ theme, openPopover }: PluginSidebarItemProps) {
106
70
  const snapshot = useHubSnapshot();
107
- if (!SidebarRow) return null;
108
71
  const state = hubTrailing(snapshot.data, snapshot.error !== null);
109
72
  const trailing = state ? (
110
73
  <View
@@ -2,42 +2,12 @@ import type { HubProcess } from "../shared/hub";
2
2
  import { isOmpProfileName, type OmpStore } from "../shared/omp-store";
3
3
  import { hubProcessTone } from "./hub-status";
4
4
 
5
- /** The sidebar id the 0.10 `addSidebarItem` used; the 0.11 screen keeps it so saved links work. */
5
+ /** The config screen keeps the id of the retired 0.10 sidebar item so saved links work. */
6
6
  export const CONFIG_SCREEN_ID = "config";
7
7
  export const HUB_SIDEBAR_ITEM_ID = "hub";
8
8
 
9
9
  type ScreenParams = Readonly<Record<string, string>>;
10
10
 
11
- /**
12
- * The 0.11 screen/sidebar-item API, typed structurally so 0.9/0.10 SDK typechecks still compile.
13
- * On 0.10 hosts these members are absent at runtime.
14
- */
15
- export interface ScreenCapableClient {
16
- addScreen(contribution: {
17
- id: string;
18
- title: string | ((params: ScreenParams) => string);
19
- Component: (props: never) => unknown;
20
- }): () => void;
21
- addSidebarHeaderItem(contribution: {
22
- id: string;
23
- title: string;
24
- Component: (props: never) => unknown;
25
- }): () => void;
26
- openScreen(input: { screenId: string; params?: Record<string, string> }): void;
27
- }
28
-
29
- /** True only on Paseo 0.11+ hosts, which provide screens, header items, and `openScreen`. */
30
- export function supportsScreens<Client extends object>(
31
- client: Client,
32
- ): client is Client & ScreenCapableClient {
33
- const candidate = client as Partial<Record<keyof ScreenCapableClient, unknown>>;
34
- return (
35
- typeof candidate.addScreen === "function" &&
36
- typeof candidate.addSidebarHeaderItem === "function" &&
37
- typeof candidate.openScreen === "function"
38
- );
39
- }
40
-
41
11
  /** A `profile` screen param selects that store; anything invalid falls back to the default. */
42
12
  export function configStoreFromParams(params: ScreenParams | undefined): OmpStore | undefined {
43
13
  const profile = params?.profile?.trim();
package/index.client.tsx CHANGED
@@ -4,7 +4,6 @@ import type {
4
4
  PluginClientContext,
5
5
  PluginSurfaceProps,
6
6
  } from "@getpaseo/plugin/client";
7
- import type { ComponentType } from "react";
8
7
  import { OmpIcon } from "./client/hub-icon";
9
8
  import { HubPopover } from "./client/hub-popover";
10
9
  import { ConfigSidebarItem, createHubSidebar } from "./client/hub-sidebar";
@@ -38,7 +37,6 @@ import {
38
37
  configStoreFromParams,
39
38
  HUB_SIDEBAR_ITEM_ID,
40
39
  loadHubSnapshot,
41
- supportsScreens,
42
40
  } from "./client/sidebar-compat";
43
41
  import {
44
42
  type ComposerPillSettings,
@@ -112,29 +110,16 @@ async function loadAgents(paseo: PaseoApi): Promise<AgentEntry[]> {
112
110
  }
113
111
 
114
112
  /**
115
- * Paseo 0.11+: a param-addressable `config` screen (same id as the old sidebar item, so saved
116
- * links resolve to it), a header row that opens it, and a Hub status row. 0.9/0.10: the original
117
- * surface and static sidebar row, unchanged.
113
+ * A param-addressable `config` screen (same id as the old sidebar item, so saved links resolve to
114
+ * it), a header row that opens it, and a Hub status row.
118
115
  */
119
116
  export function registerConfigAndHub(
120
- client: Pick<PluginClientContext, "addSurface" | "addSidebarItem" | "rpc" | "paseo">,
121
- ConfigSurface: ComponentType<PluginSurfaceProps>,
117
+ client: Pick<
118
+ PluginClientContext,
119
+ "addScreen" | "addSidebarHeaderItem" | "openScreen" | "rpc" | "paseo"
120
+ >,
122
121
  onComposerPillSettingsChange: (settings: ComposerPillSettings) => void,
123
122
  ): () => void {
124
- if (!supportsScreens(client)) {
125
- const removeSurface = client.addSurface(CONFIG_SCREEN_ID, ConfigSurface);
126
- const removeItem = client.addSidebarItem({
127
- id: CONFIG_SCREEN_ID,
128
- title: "OMP",
129
- icon: "Settings",
130
- surface: CONFIG_SCREEN_ID,
131
- });
132
- return () => {
133
- removeItem();
134
- removeSurface();
135
- };
136
- }
137
- const screens = client;
138
123
  function ConfigScreen(props: PluginSurfaceProps & { params: Record<string, string> }) {
139
124
  const current = configStoreFromParams(props.params);
140
125
  return (
@@ -145,7 +130,7 @@ export function registerConfigAndHub(
145
130
  onStoreChange={(store) => {
146
131
  // Re-selecting the current store must not push a duplicate screen onto history.
147
132
  if (ompStoreKey(store) === ompStoreKey(current)) return;
148
- screens.openScreen({ screenId: CONFIG_SCREEN_ID, params: configParamsFromStore(store) });
133
+ client.openScreen({ screenId: CONFIG_SCREEN_ID, params: configParamsFromStore(store) });
149
134
  }}
150
135
  />
151
136
  );
@@ -157,13 +142,13 @@ export function registerConfigAndHub(
157
142
  ),
158
143
  );
159
144
  const removers = [
160
- screens.addScreen({ id: CONFIG_SCREEN_ID, title: configScreenTitle, Component: ConfigScreen }),
161
- screens.addSidebarHeaderItem({
145
+ client.addScreen({ id: CONFIG_SCREEN_ID, title: configScreenTitle, Component: ConfigScreen }),
146
+ client.addSidebarHeaderItem({
162
147
  id: CONFIG_SCREEN_ID,
163
148
  title: "OMP",
164
149
  Component: ConfigSidebarItem,
165
150
  }),
166
- screens.addSidebarHeaderItem({
151
+ client.addSidebarHeaderItem({
167
152
  id: HUB_SIDEBAR_ITEM_ID,
168
153
  title: "OMP Hub",
169
154
  Component: HubSidebarItem,
@@ -193,10 +178,6 @@ export default function contribute(client: PluginClientContext) {
193
178
  scheduleReconcile();
194
179
  }
195
180
 
196
- function ConfigSurface(props: PluginSurfaceProps) {
197
- return <OmpConfigSurface {...props} onComposerPillSettingsChange={applyComposerPillSettings} />;
198
- }
199
-
200
181
  const removeMemoryPanel = client.addWorkspacePanel({
201
182
  id: "memory",
202
183
  title: "OMP Memory",
@@ -233,19 +214,15 @@ export default function contribute(client: PluginClientContext) {
233
214
  openPanel("workspace", { location: "workspace" });
234
215
  },
235
216
  });
236
- const usesScreens = supportsScreens(client);
237
- const removeConfigEntry = registerConfigAndHub(client, ConfigSurface, applyComposerPillSettings);
217
+ const removeConfigEntry = registerConfigAndHub(client, applyComposerPillSettings);
238
218
  const removeOpenConfig = client.addCommandCenterItem({
239
219
  id: "open-config",
240
220
  title: "Open OMP",
241
221
  icon: "Settings",
242
222
  keywords: ["omp", "config", "settings", "models", "providers", "composer", "pills"],
243
223
  context: "global",
244
- onSelect(capabilities) {
245
- // Branch on the same gate as registration: the screen exists only on the 0.11 path.
246
- if (usesScreens && "openScreen" in capabilities) {
247
- capabilities.openScreen({ screenId: CONFIG_SCREEN_ID });
248
- } else capabilities.openSurface(CONFIG_SCREEN_ID);
224
+ onSelect({ openScreen }) {
225
+ openScreen({ screenId: CONFIG_SCREEN_ID });
249
226
  },
250
227
  });
251
228
  const removeImageRenderer = client.addTimelineRenderer({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@omercnet/paseo-omp",
3
- "version": "1.3.3-next.232.1",
3
+ "version": "1.3.3-next.241.1",
4
4
  "type": "module",
5
5
  "description": "Paseo integration for OMP, including its direct provider and workspace tooling.",
6
6
  "license": "MIT",
package/paseo-plugin.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "id": "paseo-omp",
3
3
  "description": "Paseo integration for OMP, including its direct provider and workspace tooling.",
4
- "requirements": { "paseo": "^0.9.2 || ^0.10.0 || ^0.11.0" },
4
+ "requirements": { "paseo": "^0.11.0" },
5
5
  "build": [["node", "scripts/prepare-dependencies.mjs"]]
6
6
  }
@@ -1,2 +1,2 @@
1
1
  /** Release Please keeps this bundle-safe constant aligned with package.json. */
2
- export const PASEO_OMP_PACKAGE_VERSION = "1.3.3-next.232.1"; // x-release-please-version
2
+ export const PASEO_OMP_PACKAGE_VERSION = "1.3.3-next.241.1"; // x-release-please-version
package/server/quota.ts CHANGED
@@ -15,7 +15,12 @@ const QuotaRowSchema = z.object({
15
15
  recordedAt: z.number().int(),
16
16
  });
17
17
 
18
- export function listOmpQuotasFrom(path: string): OmpQuota[] {
18
+ // Reset-less rows (no resets_at) refresh on every OMP poll, so one this old is an inactive provider.
19
+ const ABANDONED_AFTER_MS = 30 * 86_400_000;
20
+
21
+ // Only live windows are returned: a series whose newest row already reset (or never resets and was
22
+ // abandoned) would otherwise pin the pill at its last exhausted value and bloat the popover.
23
+ export function listOmpQuotasFrom(path: string, now = Date.now()): OmpQuota[] {
19
24
  try {
20
25
  const database = new DatabaseSync(path, { readOnly: true, timeout: 500 });
21
26
  try {
@@ -33,9 +38,10 @@ export function listOmpQuotasFrom(path: string): OmpQuota[] {
33
38
  FROM usage_history
34
39
  )
35
40
  WHERE position = 1
41
+ AND (resets_at > ? OR (resets_at IS NULL AND recorded_at > ?))
36
42
  ORDER BY COALESCE(usedFraction, -1) DESC, provider, label`,
37
43
  )
38
- .all();
44
+ .all(now, now - ABANDONED_AFTER_MS);
39
45
  return rows.flatMap((row) => {
40
46
  const parsed = QuotaRowSchema.safeParse(row);
41
47
  return parsed.success ? [parsed.data] : [];