@omercnet/paseo-omp 1.3.3-next.241.1 → 1.3.3-next.243.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
|
@@ -95,7 +95,7 @@ Provider functionality outside the capability flags is tracked separately:
|
|
|
95
95
|
| --- | ---: | --- |
|
|
96
96
|
| Registration metadata and sanitized SVG icon | **100%** | Stable `omp-plugin` identity, label, description, and bundled icon. |
|
|
97
97
|
| Strict `providerOptionsSchema` | **100%** | Command, literal environment, names-only profile inherited environment, output-redaction mode, session directory, RPC timeout, and role-model options are validated and normalized. Host-wide inherited names are separately persisted and merged at launch. |
|
|
98
|
-
| Availability diagnostics | **50%** | The plugin implements a `checkAvailability` hook with bounded checks that distinguish missing, unrunnable, incompatible, and available OMP runtimes, but Paseo 0.
|
|
98
|
+
| Availability diagnostics | **50%** | The plugin implements a `checkAvailability` hook with bounded checks that distinguish missing, unrunnable, incompatible, and available OMP runtimes, but Paseo 0.11.1 does not call it. The host uses the `status()` hook below instead, which reuses this probe for the default launch. |
|
|
99
99
|
| Catalog cache identity | **100%** | Hash includes effective options, merged host/profile inherited-environment names, settings, scope, cwd, and default command, but never resolves or fingerprints inherited values. |
|
|
100
100
|
| Models, modes, and thinking catalog | **100%** | Native catalog is mapped to opaque public model IDs with committed defaults and permission-gated modes. |
|
|
101
101
|
| Connection `send` / `onEvent` / `close` lifecycle | **100%** | Request correlation, multi-session ownership, process recovery, teardown, and provider reload/removal are covered. |
|
|
@@ -105,7 +105,8 @@ Provider functionality outside the capability flags is tracked separately:
|
|
|
105
105
|
| Commands and committed session state events | **100%** | Publishes `session.commands`, `session.opened`, `session.config`, `session.ready`, and request completion in protocol order. |
|
|
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
|
-
| 0.11 provider `status()` | **
|
|
108
|
+
| 0.11 provider `status()` | **75%** | Registered for the plugin-owned default launch (`OMP_COMMAND` or `omp`, plus the fixed `--profile` wrapper for profile providers), using the bounded `--version`/`--help` probe. Only a missing executable reports `available: false`; slow, failing, or unrecognized probes stay available with a diagnostic. An unexpected internal probe error is not caught here, so the host reports it as unavailable. Available results are shared for 30 seconds; an unavailable result is never remembered, so installing `omp` takes effect on the next host call. The request carries only an optional daemon `launch` and never `providerOptions`, so a per-agent `providerOptions.command` or `env` is invisible. **Breaking on 0.11 hosts:** the host gates create, resume, and draft commands/features on this status, so a missing default executable blocks them all, including agents configured with an otherwise valid custom command. Any request `launch` is ignored. |
|
|
109
|
+
| 0.11 provider `command` and daemon launch | **0%** | Deliberately not declared. Declaring `command` makes the daemon resolve it against its own `PATH` and reject every `connect` when the default binary is missing. The resulting `launch.env` is the daemon's entire process environment plus overrides, indistinguishable from configured values, so adopting it would defeat names-only `inheritEnv` and the fixed profile store environment. The host never supplies `launch` without a declared `command`; `connect` and `getCatalogCacheKey` do not read it, each pinned by `tests/provider-catalog.test.ts`. Revisit if the host stops gating on the default binary or exposes configured `env` separately from the daemon environment. |
|
|
109
110
|
| 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
111
|
| 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
112
|
|
package/package.json
CHANGED
|
@@ -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.
|
|
2
|
+
export const PASEO_OMP_PACKAGE_VERSION = "1.3.3-next.243.1"; // x-release-please-version
|
|
@@ -7,7 +7,7 @@ import { ompAgentDir, ompCacheDir, ompDataDir, ompSessionDir, ompStateDir } from
|
|
|
7
7
|
import { OmpRpcRuntime, type OmpRuntime } from "./omp-rpc";
|
|
8
8
|
import type { OmpStartOptions } from "./omp-rpc-environment";
|
|
9
9
|
import { parseOmpProviderOptions } from "./provider-options";
|
|
10
|
-
import { createOmpProvider, type OmpProviderOptions } from "./registration";
|
|
10
|
+
import { createOmpProvider, createOmpStatus, type OmpProviderOptions } from "./registration";
|
|
11
11
|
import { OmpPublicError } from "./security";
|
|
12
12
|
|
|
13
13
|
const MAX_PROFILES = 128;
|
|
@@ -229,6 +229,18 @@ export function createProfileOmpProvider(profile: string, options: OmpProviderOp
|
|
|
229
229
|
sessionDir,
|
|
230
230
|
);
|
|
231
231
|
};
|
|
232
|
+
const checkAvailability = async (
|
|
233
|
+
input: Parameters<NonNullable<typeof provider.checkAvailability>>[0],
|
|
234
|
+
context?: Parameters<NonNullable<typeof provider.checkAvailability>>[1],
|
|
235
|
+
) => {
|
|
236
|
+
const command = validateCatalog(input);
|
|
237
|
+
if (!provider.checkAvailability)
|
|
238
|
+
throw new OmpPublicError("OMP availability probe is unavailable");
|
|
239
|
+
return provider.checkAvailability(
|
|
240
|
+
{ ...input, providerOptions: { ...input.providerOptions, command } },
|
|
241
|
+
context,
|
|
242
|
+
);
|
|
243
|
+
};
|
|
232
244
|
return {
|
|
233
245
|
...provider,
|
|
234
246
|
async getCatalogCacheKey(
|
|
@@ -237,18 +249,8 @@ export function createProfileOmpProvider(profile: string, options: OmpProviderOp
|
|
|
237
249
|
validateCatalog(input);
|
|
238
250
|
return provider.getCatalogCacheKey?.(input);
|
|
239
251
|
},
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
context?: Parameters<NonNullable<typeof provider.checkAvailability>>[1],
|
|
243
|
-
) {
|
|
244
|
-
const command = validateCatalog(input);
|
|
245
|
-
if (!provider.checkAvailability)
|
|
246
|
-
throw new OmpPublicError("OMP availability probe is unavailable");
|
|
247
|
-
return provider.checkAvailability(
|
|
248
|
-
{ ...input, providerOptions: { ...input.providerOptions, command } },
|
|
249
|
-
context,
|
|
250
|
-
);
|
|
251
|
-
},
|
|
252
|
+
checkAvailability,
|
|
253
|
+
status: createOmpStatus(() => checkAvailability({ scope: "global" })),
|
|
252
254
|
id,
|
|
253
255
|
label: `OMP · ${profile}`,
|
|
254
256
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import { homedir } from "node:os";
|
|
3
|
-
import type { ProviderRegistration } from "@getpaseo/plugin/server/provider";
|
|
3
|
+
import type { ProviderRegistration, ProviderStatus } from "@getpaseo/plugin/server/provider";
|
|
4
4
|
import { z } from "zod";
|
|
5
5
|
import type { OmpBrowserAuthorizationRegistry } from "../mcp-browser";
|
|
6
6
|
import type { OmpOperationalFailureReporter } from "../operational-failure-diagnostics";
|
|
@@ -41,6 +41,57 @@ type ProviderRegistrationCompat = Omit<
|
|
|
41
41
|
): Promise<ProviderAvailabilityCompat>;
|
|
42
42
|
};
|
|
43
43
|
|
|
44
|
+
const STATUS_CACHE_TTL_MS = 30_000;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* The 0.11 host calls `status` before every create, resume, and draft request and passes only
|
|
48
|
+
* the daemon-resolved launch, never per-agent `providerOptions`. Only a missing executable is
|
|
49
|
+
* definitive for the plugin-owned default launch; slow, failing, or unrecognized probes stay
|
|
50
|
+
* available with a diagnostic so load or a differently launched agent is never refused.
|
|
51
|
+
*/
|
|
52
|
+
function toProviderStatus(availability: ProviderAvailabilityCompat): ProviderStatus {
|
|
53
|
+
if (availability.status === "available") return { available: true };
|
|
54
|
+
if (availability.status === "missing") {
|
|
55
|
+
return {
|
|
56
|
+
available: false,
|
|
57
|
+
diagnostic: availability.diagnostic ?? "OMP executable was not found",
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
return {
|
|
61
|
+
available: true,
|
|
62
|
+
diagnostic: availability.diagnostic ?? `OMP launch probe reported ${availability.status}`,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Share one bounded probe across the host's frequent status calls. Only an available result is
|
|
68
|
+
* kept for the interval; an unavailable or failed result is shared by in-flight callers and then
|
|
69
|
+
* dropped, so installing the executable is picked up by the very next host call.
|
|
70
|
+
*/
|
|
71
|
+
export function createOmpStatus(
|
|
72
|
+
probe: () => Promise<ProviderAvailabilityCompat>,
|
|
73
|
+
): () => Promise<ProviderStatus> {
|
|
74
|
+
let cached: { expiresAt: number; result: Promise<ProviderStatus> } | undefined;
|
|
75
|
+
return () => {
|
|
76
|
+
const now = Date.now();
|
|
77
|
+
if (cached && cached.expiresAt > now) return cached.result;
|
|
78
|
+
const entry = {
|
|
79
|
+
expiresAt: now + STATUS_CACHE_TTL_MS,
|
|
80
|
+
result: probe().then(toProviderStatus),
|
|
81
|
+
};
|
|
82
|
+
cached = entry;
|
|
83
|
+
entry.result.then(
|
|
84
|
+
(status) => {
|
|
85
|
+
if (!status.available && cached === entry) cached = undefined;
|
|
86
|
+
},
|
|
87
|
+
() => {
|
|
88
|
+
if (cached === entry) cached = undefined;
|
|
89
|
+
},
|
|
90
|
+
);
|
|
91
|
+
return entry.result;
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
|
|
44
95
|
const CAPABILITIES = [
|
|
45
96
|
"prompt.message",
|
|
46
97
|
"prompt.command",
|
|
@@ -98,6 +149,26 @@ export function createOmpProvider(options: OmpProviderOptions = {}): ProviderReg
|
|
|
98
149
|
reportProtocolViolation: options.reportProtocolViolation,
|
|
99
150
|
});
|
|
100
151
|
const nativeReservations = new OmpNativeSessionReservations();
|
|
152
|
+
const checkAvailability: NonNullable<ProviderRegistrationCompat["checkAvailability"]> = async (
|
|
153
|
+
catalogOptions,
|
|
154
|
+
context,
|
|
155
|
+
) => {
|
|
156
|
+
if (options.availabilityProbe) {
|
|
157
|
+
return await options.availabilityProbe(catalogOptions, context?.timeoutMs);
|
|
158
|
+
}
|
|
159
|
+
const providerOptions = parseOmpProviderOptions(catalogOptions.providerOptions);
|
|
160
|
+
const environment = { ...(options.environment ?? process.env), ...providerOptions.env };
|
|
161
|
+
const configuredCommand: readonly [string, ...string[]] = providerOptions.command?.[0]
|
|
162
|
+
? [providerOptions.command[0], ...providerOptions.command.slice(1)]
|
|
163
|
+
: [environment.OMP_COMMAND || "omp"];
|
|
164
|
+
return await probeOmpAvailability({
|
|
165
|
+
command: configuredCommand,
|
|
166
|
+
cwd:
|
|
167
|
+
catalogOptions.scope === "workspace" && catalogOptions.cwd ? catalogOptions.cwd : homedir(),
|
|
168
|
+
environment,
|
|
169
|
+
timeoutMs: context?.timeoutMs,
|
|
170
|
+
});
|
|
171
|
+
};
|
|
101
172
|
return {
|
|
102
173
|
id: "omp-plugin",
|
|
103
174
|
label: "OMP Plugin",
|
|
@@ -130,25 +201,8 @@ export function createOmpProvider(options: OmpProviderOptions = {}): ProviderReg
|
|
|
130
201
|
}
|
|
131
202
|
return createHash("sha256").update(stableJson(identity)).digest("base64url");
|
|
132
203
|
},
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
return await options.availabilityProbe(catalogOptions, context?.timeoutMs);
|
|
136
|
-
}
|
|
137
|
-
const providerOptions = parseOmpProviderOptions(catalogOptions.providerOptions);
|
|
138
|
-
const environment = { ...(options.environment ?? process.env), ...providerOptions.env };
|
|
139
|
-
const configuredCommand: readonly [string, ...string[]] = providerOptions.command?.[0]
|
|
140
|
-
? [providerOptions.command[0], ...providerOptions.command.slice(1)]
|
|
141
|
-
: [environment.OMP_COMMAND || "omp"];
|
|
142
|
-
return await probeOmpAvailability({
|
|
143
|
-
command: configuredCommand,
|
|
144
|
-
cwd:
|
|
145
|
-
catalogOptions.scope === "workspace" && catalogOptions.cwd
|
|
146
|
-
? catalogOptions.cwd
|
|
147
|
-
: homedir(),
|
|
148
|
-
environment,
|
|
149
|
-
timeoutMs: context?.timeoutMs,
|
|
150
|
-
});
|
|
151
|
-
},
|
|
204
|
+
checkAvailability,
|
|
205
|
+
status: createOmpStatus(() => checkAvailability({ scope: "global" })),
|
|
152
206
|
async connect(request) {
|
|
153
207
|
if (boundedJsonBytes(request, 8 * 1024, 32, 256, 64) === Number.POSITIVE_INFINITY) {
|
|
154
208
|
throw new Error("OMP provider received an oversized connection request");
|