@omercnet/paseo-omp 4.0.0-next.313.1 → 4.0.0-next.317.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.13.0.
5
+ - Paseo ^0.14.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.13.0`, OMP `18.1.15` or newer, and OMP RPC protocol v2. Workspace discovery passes `includeBackground`, which throws on hosts that do not advertise `features.backgroundWorkspaces`; every 0.13 host does.
27
+ Requirements: Paseo `^0.14.0`, OMP `18.1.15` or newer, and OMP RPC protocol v2. Workspace discovery passes `includeBackground`, which throws on hosts that do not advertise `features.backgroundWorkspaces`; every 0.14 host does.
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.13 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.14 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
 
@@ -54,20 +54,20 @@ Profile selection is request-local: concurrent clients cannot change each other'
54
54
 
55
55
  ## Paseo provider SDK coverage
56
56
 
57
- The capability inventory is pinned to `@getpaseo/plugin` 0.13.0, with nightly compatibility checks
57
+ The capability inventory is pinned to `@getpaseo/plugin` 0.14.0-beta.1, with nightly compatibility checks
58
58
  against the latest and beta channels. Provider capability scoring covers
59
- all 17 entries in the SDK's `PROVIDER_CAPABILITIES`; the separate provider/client SDK table below
59
+ all 18 entries in the SDK's `PROVIDER_CAPABILITIES`; the separate provider/client SDK table below
60
60
  also tracks the registration, screen, and sidebar APIs introduced in 0.11. This measures strict SDK surface
61
61
  coverage, not general product quality.
62
62
 
63
- **Provider capability completeness: 61.8%.** The provider advertises 11 of 17 capabilities (64.7%); ten are complete and `session.configure` is partial.
63
+ **Provider capability completeness: 63.9%.** The provider advertises 12 of 18 capabilities (66.7%); eleven are complete and `session.configure` is partial.
64
64
 
65
65
  Scoring is deliberately mechanical so releases remain comparable:
66
66
 
67
67
  - **100%**: advertised, implemented end to end, and covered by automated provider tests.
68
68
  - **50%**: advertised with a meaningful subset, but at least one material SDK operation is rejected.
69
69
  - **0%**: not advertised; requests are rejected rather than silently approximated.
70
- - Overall completeness is the unweighted arithmetic mean of all 17 SDK capability rows.
70
+ - Overall completeness is the unweighted arithmetic mean of all 18 SDK capability rows.
71
71
 
72
72
  | SDK capability | Completeness | Support and gap |
73
73
  | --- | ---: | --- |
@@ -77,6 +77,7 @@ Scoring is deliberately mechanical so releases remain comparable:
77
77
  | `prompt.output_schema` | **0%** | Not advertised. OMP has no equivalent structured-output contract; `outputSchema` fails visibly. |
78
78
  | `prompt.steer` | **100%** | Native steering with turn ownership, user-message correlation, stale-target rejection, and terminal race handling. |
79
79
  | `session.archive` | **0%** | Not advertised. Paseo may archive its agent record, but OMP has no native transcript archive operation. |
80
+ | `session.can_stop_runtime` | **100%** | Answers Paseo's idle-release safety query. Returns `false` while a turn, permission, revert, configuration change, runtime recovery, active subagent, or OMP background async work is pending, and when OMP does not report a settled state; errors and unknown sessions fail the request, which also keeps the runtime. |
80
81
  | `session.configure` | **50%** | Live model and thinking changes commit and republish native state. Live approval-mode changes require a new session, and non-empty SDK `settings` are rejected. |
81
82
  | `session.list` | **100%** | Bounded host-wide and cwd-scoped discovery, search, previews, profile-specific session roots, and cleanup-reservation guards. |
82
83
  | `session.persistence` | **100%** | Versioned opaque handles, exact resume, import, replay-before-ready, runtime recovery, and cleanup quarantine. Archived agents whose recorded workspace has been removed load read-only from their authorized transcript when Paseo opens them with its `history` purpose, without spawning OMP or connecting MCP servers; interactive create and resume still require the workspace. |
@@ -125,7 +126,9 @@ Existing agents whose provider is `omp` remain owned by the bundled provider. Ne
125
126
 
126
127
  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.
127
128
 
128
- Paseo 0.13 is the minimum supported release. The controlled Docker canary is pinned to official 0.13.0; 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.
129
+ Paseo 0.14 is the minimum supported release. The controlled Docker canary is pinned to official 0.14.0-beta.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.
130
+
131
+ Paseo releases idle resumable agent runtimes after one hour; the agent stays listed as `closed` and the next prompt resumes the same OMP session. The plugin vetoes that release while the session has a running turn, a pending permission, an active subagent, or OMP background async work, and while OMP does not report a settled state (the plugin needs the `hasPendingAsyncWork` and `isSettled` fields in OMP's `get_state`; builds without them are never released). Set `agents.idleRuntimeCleanup: false` in the Paseo config to disable idle release for every provider.
129
132
 
130
133
  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.
131
134
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@omercnet/paseo-omp",
3
- "version": "4.0.0-next.313.1",
3
+ "version": "4.0.0-next.317.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.13.0" },
4
+ "requirements": { "paseo": "^0.14.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 = "4.0.0-next.313.1"; // x-release-please-version
2
+ export const PASEO_OMP_PACKAGE_VERSION = "4.0.0-next.317.1"; // x-release-please-version
@@ -48,6 +48,7 @@ const SUPPORTED_CAPABILITIES: Readonly<Record<string, true>> = {
48
48
  "prompt.command": true,
49
49
  "prompt.image": true,
50
50
  "prompt.steer": true,
51
+ "session.can_stop_runtime": true,
51
52
  "session.configure": true,
52
53
  "session.list": true,
53
54
  "session.persistence": true,
@@ -65,6 +66,7 @@ const SUPPORTED_INPUTS: Readonly<Record<string, true>> = {
65
66
  "session.permission": true,
66
67
  "session.revert": true,
67
68
  "session.interrupt": true,
69
+ "session.can_stop_runtime": true,
68
70
  "session.close": true,
69
71
  };
70
72
  const MAX_CONNECTION_SESSIONS = 32;
@@ -1135,6 +1137,21 @@ export function createOmpConnection(
1135
1137
  await session.interrupt(input);
1136
1138
  return;
1137
1139
  }
1140
+ case "session.can_stop_runtime": {
1141
+ const session = sessions.get(input.sessionId)?.session;
1142
+ if (!session) {
1143
+ requestFailure(input.requestId, new OmpPublicError("Unknown OMP session"));
1144
+ return;
1145
+ }
1146
+ const canStop = await session.canStopRuntime();
1147
+ emit({
1148
+ type: "session.can_stop_runtime",
1149
+ requestId: input.requestId,
1150
+ sessionId: input.sessionId,
1151
+ canStop,
1152
+ });
1153
+ return;
1154
+ }
1138
1155
  case "session.close": {
1139
1156
  const slot = sessions.get(input.sessionId);
1140
1157
  if (!slot) {
@@ -1231,6 +1231,8 @@ export const OmpSessionStateSchema = z.object({
1231
1231
  thinkingLevel: OmpCurrentThinkingLevelSchema,
1232
1232
  isStreaming: z.boolean(),
1233
1233
  isCompacting: z.boolean(),
1234
+ hasPendingAsyncWork: z.boolean().optional(),
1235
+ isSettled: z.boolean().optional(),
1234
1236
  sessionId: IDENTIFIER,
1235
1237
  autoCompactionEnabled: z.boolean().optional(),
1236
1238
  contextUsage: OmpContextUsageSchema.nullable().optional().catch(undefined),
@@ -1902,6 +1904,8 @@ export function projectSessionStateResponseData(value: unknown): unknown {
1902
1904
  "thinkingLevel",
1903
1905
  "isStreaming",
1904
1906
  "isCompacting",
1907
+ "hasPendingAsyncWork",
1908
+ "isSettled",
1905
1909
  "sessionId",
1906
1910
  "autoCompactionEnabled",
1907
1911
  "contextUsage",
@@ -97,6 +97,7 @@ const CAPABILITIES = [
97
97
  "prompt.command",
98
98
  "prompt.image",
99
99
  "prompt.steer",
100
+ "session.can_stop_runtime",
100
101
  "session.configure",
101
102
  "session.list",
102
103
  "session.persistence",
@@ -301,6 +301,10 @@ export class OmpHistorySession implements OmpOpenedSession {
301
301
  return Promise.resolve();
302
302
  }
303
303
 
304
+ canStopRuntime(): Promise<boolean> {
305
+ return Promise.resolve(true);
306
+ }
307
+
304
308
  beginConnectionShutdown(): void {
305
309
  this.lifetime.abort(new Error("OMP provider connection closed"));
306
310
  }
@@ -1150,6 +1150,16 @@ export class OmpSessionPermissions {
1150
1150
  return this.activeTurn?.turnId === pending.turnId && !this.activeTurn.terminal;
1151
1151
  }
1152
1152
 
1153
+ hasPending(): boolean {
1154
+ return (
1155
+ this.pendingPermissions.size > 0 ||
1156
+ this.inFlightPermissions.size > 0 ||
1157
+ this.pendingToolPermissions.size > 0 ||
1158
+ this.inFlightToolPermissions.size > 0 ||
1159
+ this.pendingFreeformSelection !== null
1160
+ );
1161
+ }
1162
+
1153
1163
  hasForTurn(turnId: string): boolean {
1154
1164
  const ownsTurn = (pending: PendingPermission | PendingToolPermission) =>
1155
1165
  pending.turnId === turnId;
@@ -111,6 +111,7 @@ export interface OmpOpenedSession {
111
111
  configure(input: SessionConfigureInput): Promise<void>;
112
112
  revert(input: SessionRevertInput): Promise<void>;
113
113
  interrupt(input: SessionInterruptInput): Promise<void>;
114
+ canStopRuntime(): Promise<boolean>;
114
115
  close(input?: SessionCloseInput): Promise<void>;
115
116
  abortOpen(): Promise<void>;
116
117
  beginConnectionShutdown(): void;
@@ -1465,6 +1466,28 @@ export class OmpProviderSession implements OmpOpenedSession {
1465
1466
  }
1466
1467
  }
1467
1468
 
1469
+ async canStopRuntime(): Promise<boolean> {
1470
+ const hasLocalWork =
1471
+ this.closed ||
1472
+ this.runtimeDead !== null ||
1473
+ this.recoveryPromise !== null ||
1474
+ this.activeTurn !== null ||
1475
+ this.activeAbort !== null ||
1476
+ this.revertInFlight ||
1477
+ this.configMutationInFlight ||
1478
+ this.permissions.hasPending() ||
1479
+ Boolean(this.subsessions?.hasActiveChildren());
1480
+ if (hasLocalWork) return false;
1481
+ const state = await this.runtime.getState();
1482
+ // OMP builds that predate these fields report neither, which keeps the runtime alive.
1483
+ return (
1484
+ state.isSettled === true &&
1485
+ state.hasPendingAsyncWork === false &&
1486
+ !state.isStreaming &&
1487
+ !state.isCompacting
1488
+ );
1489
+ }
1490
+
1468
1491
  async interrupt(input: SessionInterruptInput): Promise<void> {
1469
1492
  const turn = this.activeTurn;
1470
1493
  if (!turn) {