@omercnet/paseo-omp 0.4.0-next.135.1 → 0.4.0-next.138.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 +4 -4
- package/client/omp-config-surface.tsx +15 -7
- package/client/provider-launch-settings.tsx +118 -0
- package/index.server.ts +10 -0
- package/package.json +1 -1
- package/server/package-version.ts +1 -1
- package/server/provider/config-normalization.ts +18 -2
- package/server/provider/connection.ts +3 -0
- package/server/provider/registration.ts +8 -1
- package/server/provider/session.ts +2 -0
- package/server/provider/settings.ts +8 -5
- package/shared/provider-launch-settings.ts +18 -0
package/README.md
CHANGED
|
@@ -86,12 +86,12 @@ Provider functionality outside the capability flags is tracked separately:
|
|
|
86
86
|
| Provider SDK surface | Completeness | Implementation |
|
|
87
87
|
| --- | ---: | --- |
|
|
88
88
|
| Registration metadata and sanitized SVG icon | **100%** | Stable `omp-plugin` identity, label, description, and bundled icon. |
|
|
89
|
-
| Strict `providerOptionsSchema` | **100%** | Command, literal
|
|
89
|
+
| 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. |
|
|
90
90
|
| Availability diagnostics | **100%** | Bounded checks distinguish missing, unrunnable, incompatible, and available OMP runtimes. |
|
|
91
|
-
| Catalog cache identity | **100%** | Hash includes effective options,
|
|
91
|
+
| 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. |
|
|
92
92
|
| Models, modes, and thinking catalog | **100%** | Native catalog is mapped to opaque public model IDs with committed defaults and permission-gated modes. |
|
|
93
93
|
| Connection `send` / `onEvent` / `close` lifecycle | **100%** | Request correlation, multi-session ownership, process recovery, teardown, and provider reload/removal are covered. |
|
|
94
|
-
| Session launch: cwd, env, system prompt, title, and persistence | **100%** | Complete launch configuration is bounded, validated, forwarded, and re-read on recovery; selected daemon environment values are resolved only when catalog and session children spawn. |
|
|
94
|
+
| Session launch: cwd, env, system prompt, title, and persistence | **100%** | Complete launch configuration is bounded, validated, forwarded, and re-read on recovery; selected host and profile daemon environment values are resolved only when catalog and session children spawn. |
|
|
95
95
|
| MCP server forwarding and host tools | **100%** | Configured MCP tools are discovered, namespaced, labeled, executed, canceled, and bounded. Caller-scoped Paseo orchestration tools retain their native names, such as `create_agent` and `list_profiles`, so OMP skills can invoke them directly. The MCP composer control delegates native server management to OMP instead of duplicating its profile and workspace precedence. Exact `toolPolicy` remains the separate 0% capability above. |
|
|
96
96
|
| Denied native tools | **100%** | `disallowedTools` becomes an explicit OMP allow-list; unknown names fail closed. |
|
|
97
97
|
| Commands and committed session state events | **100%** | Publishes `session.commands`, `session.opened`, `session.config`, `session.ready`, and request completion in protocol order. |
|
|
@@ -121,7 +121,7 @@ Install, update, disable, or remove `paseo-omp` independently of the bundled pro
|
|
|
121
121
|
|
|
122
122
|
The plugin validates OMP protocol data and bounds public strings and structured values. It does not heuristically redact or rewrite content produced by native OMP, models, or tools. Do not put credentials in prompts or tool output, because that content may be published unchanged after validation and bounding.
|
|
123
123
|
|
|
124
|
-
`providerOptions.outputRedaction` defaults to `none`, preserving native content subject to those bounds. `configured-values` provides best-effort literal replacement for explicitly supplied credential values and every non-empty daemon value selected through `inheritEnv`, regardless of its name. It does not detect generated secrets or encoded, transformed, or independently streamed fragments of configured values. Centralized Paseo policy is required when a deployment needs redaction guarantees.
|
|
124
|
+
`providerOptions.outputRedaction` defaults to `none`, preserving native content subject to those bounds. `configured-values` provides best-effort literal replacement for explicitly supplied credential values and every non-empty daemon value selected through host or profile `inheritEnv`, regardless of its name. It does not detect generated secrets or encoded, transformed, or independently streamed fragments of configured values. Centralized Paseo policy is required when a deployment needs redaction guarantees.
|
|
125
125
|
|
|
126
126
|
Unexpected or internal launch failures use fixed fallback messages rather than serializing the launch configuration. Explicit public validation errors may include caller-supplied configuration names or values. Deployments that require host-wide content redaction should implement it in a dedicated host or plugin layer rather than this protocol adapter.
|
|
127
127
|
|
|
@@ -63,6 +63,7 @@ import {
|
|
|
63
63
|
summarizeProviderStatus,
|
|
64
64
|
summarizeRpcUiSupport,
|
|
65
65
|
} from "./provider-diagnostics-state";
|
|
66
|
+
import { ProviderLaunchSettingsSection } from "./provider-launch-settings";
|
|
66
67
|
import {
|
|
67
68
|
refreshSupportReport,
|
|
68
69
|
type SupportReportCopyState,
|
|
@@ -141,8 +142,10 @@ function ProviderSetupSection({ styles }: { styles: OmpConfigStyles }) {
|
|
|
141
142
|
return (
|
|
142
143
|
<SectionCard styles={styles} title="OMP Plugin">
|
|
143
144
|
<Text style={styles.muted}>
|
|
144
|
-
|
|
145
|
+
Host-wide inherited environment names apply to every OMP provider. Profile launch overrides
|
|
146
|
+
remain available for narrower exceptions.
|
|
145
147
|
</Text>
|
|
148
|
+
<KeyValueRow styles={styles} label="Host policy" value="Inherited daemon environment names" />
|
|
146
149
|
<KeyValueRow
|
|
147
150
|
styles={styles}
|
|
148
151
|
label="Per agent"
|
|
@@ -151,7 +154,7 @@ function ProviderSetupSection({ styles }: { styles: OmpConfigStyles }) {
|
|
|
151
154
|
<KeyValueRow
|
|
152
155
|
styles={styles}
|
|
153
156
|
label="Provider profile"
|
|
154
|
-
value="Command, environment, session directory, RPC timeout, role models, and denied tools"
|
|
157
|
+
value="Command, additional environment, session directory, RPC timeout, role models, and denied tools"
|
|
155
158
|
/>
|
|
156
159
|
</SectionCard>
|
|
157
160
|
);
|
|
@@ -162,15 +165,15 @@ function PluginConfigurationSection({ styles }: { styles: OmpConfigStyles }) {
|
|
|
162
165
|
<>
|
|
163
166
|
<SectionCard styles={styles} title="OMP Plugin launch options">
|
|
164
167
|
<Text style={styles.muted}>
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
+
Configure inherited daemon environment names below. Paseo does not expose effective
|
|
169
|
+
profile options for active launches, so this tab documents profile overrides without
|
|
170
|
+
claiming they are active.
|
|
168
171
|
</Text>
|
|
169
172
|
<KeyValueRow styles={styles} label="Command" value="Executable and argument prefix" />
|
|
170
173
|
<KeyValueRow
|
|
171
174
|
styles={styles}
|
|
172
175
|
label="Inherited environment"
|
|
173
|
-
value="
|
|
176
|
+
value="Additional profile names copied at OMP spawn time"
|
|
174
177
|
/>
|
|
175
178
|
<KeyValueRow
|
|
176
179
|
styles={styles}
|
|
@@ -1125,7 +1128,12 @@ function OmpConfigContent({
|
|
|
1125
1128
|
</>
|
|
1126
1129
|
) : null}
|
|
1127
1130
|
|
|
1128
|
-
{view === "plugin" ?
|
|
1131
|
+
{view === "plugin" ? (
|
|
1132
|
+
<>
|
|
1133
|
+
<PluginConfigurationSection styles={styles} />
|
|
1134
|
+
{!cwd ? <ProviderLaunchSettingsSection theme={theme} /> : null}
|
|
1135
|
+
</>
|
|
1136
|
+
) : null}
|
|
1129
1137
|
|
|
1130
1138
|
{view === "plugins" ? (
|
|
1131
1139
|
<OmpPluginManagerSection theme={theme} compact={layout.compact} cwd={cwd} store={store} />
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { type PluginSurfaceProps, type SettingsState, useSettings } from "@getpaseo/plugin/client";
|
|
2
|
+
import {
|
|
3
|
+
SettingsAction,
|
|
4
|
+
SettingsCard,
|
|
5
|
+
SettingsInput,
|
|
6
|
+
SettingsSection,
|
|
7
|
+
} from "@getpaseo/plugin/client/ui";
|
|
8
|
+
import { useCallback, useEffect, useMemo, useState } from "react";
|
|
9
|
+
import { Text, View } from "react-native";
|
|
10
|
+
import {
|
|
11
|
+
providerLaunchSettings,
|
|
12
|
+
providerLaunchSettingsSchema,
|
|
13
|
+
} from "../shared/provider-launch-settings";
|
|
14
|
+
|
|
15
|
+
type ReadySettings = Extract<
|
|
16
|
+
SettingsState<typeof providerLaunchSettings.schema>,
|
|
17
|
+
{ status: "ready" }
|
|
18
|
+
>;
|
|
19
|
+
|
|
20
|
+
function ProviderLaunchSettingsControls({ settings }: { settings: ReadySettings }) {
|
|
21
|
+
const savedNames = settings.values.inheritEnv.join(", ");
|
|
22
|
+
const [rawNames, setRawNames] = useState(() => savedNames);
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
setRawNames(savedNames);
|
|
25
|
+
}, [savedNames]);
|
|
26
|
+
const inheritEnv = [
|
|
27
|
+
...new Set(
|
|
28
|
+
rawNames
|
|
29
|
+
.split(",")
|
|
30
|
+
.map((name) => name.trim())
|
|
31
|
+
.filter(Boolean),
|
|
32
|
+
),
|
|
33
|
+
];
|
|
34
|
+
const next = providerLaunchSettingsSchema.safeParse({ inheritEnv });
|
|
35
|
+
const error = next.success
|
|
36
|
+
? null
|
|
37
|
+
: (next.error.issues[0]?.message ?? "Enter valid variable names.");
|
|
38
|
+
const save = useCallback(async () => {
|
|
39
|
+
if (!next.success) return;
|
|
40
|
+
await settings.save(next.data, settings.revision);
|
|
41
|
+
}, [next, settings]);
|
|
42
|
+
|
|
43
|
+
return (
|
|
44
|
+
<View style={{ gap: 12 }}>
|
|
45
|
+
<SettingsSection
|
|
46
|
+
title="Inherited environment"
|
|
47
|
+
info="Applies to every OMP Plugin agent on this host. Names are stored, but values are read only from the daemon environment when OMP starts."
|
|
48
|
+
>
|
|
49
|
+
<SettingsCard>
|
|
50
|
+
<SettingsInput
|
|
51
|
+
key={savedNames}
|
|
52
|
+
label="Daemon variable names"
|
|
53
|
+
hint="Comma-separated names. Each selected value is available to OMP and its child processes."
|
|
54
|
+
initialValue={savedNames}
|
|
55
|
+
onChangeText={setRawNames}
|
|
56
|
+
placeholder="ACME_OMP_API_KEY, ACME_OMP_URL"
|
|
57
|
+
error={error ?? undefined}
|
|
58
|
+
disabled={settings.saving}
|
|
59
|
+
/>
|
|
60
|
+
<SettingsAction
|
|
61
|
+
label="Save inherited environment"
|
|
62
|
+
hint="Profile-specific names remain additive for narrow exceptions."
|
|
63
|
+
actionLabel="Save"
|
|
64
|
+
disabled={settings.saving || rawNames === savedNames || !next.success}
|
|
65
|
+
onPress={() => void save()}
|
|
66
|
+
/>
|
|
67
|
+
<SettingsAction
|
|
68
|
+
label="Clear inherited environment"
|
|
69
|
+
actionLabel="Clear"
|
|
70
|
+
disabled={settings.saving || settings.values.inheritEnv.length === 0}
|
|
71
|
+
onPress={async () => {
|
|
72
|
+
if (await settings.save({ inheritEnv: [] }, settings.revision)) setRawNames("");
|
|
73
|
+
}}
|
|
74
|
+
/>
|
|
75
|
+
{settings.saveError ? (
|
|
76
|
+
<SettingsAction
|
|
77
|
+
label="Reload host launch settings"
|
|
78
|
+
error={settings.saveError}
|
|
79
|
+
actionLabel="Reload"
|
|
80
|
+
disabled={settings.saving}
|
|
81
|
+
onPress={settings.reload}
|
|
82
|
+
/>
|
|
83
|
+
) : null}
|
|
84
|
+
</SettingsCard>
|
|
85
|
+
</SettingsSection>
|
|
86
|
+
</View>
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export function ProviderLaunchSettingsSection({ theme }: { theme: PluginSurfaceProps["theme"] }) {
|
|
91
|
+
const settings = useSettings(providerLaunchSettings);
|
|
92
|
+
const styles = useMemo(
|
|
93
|
+
() => ({
|
|
94
|
+
root: { gap: 12 },
|
|
95
|
+
text: { color: theme.colors.foreground },
|
|
96
|
+
error: { color: theme.colors.statusDanger },
|
|
97
|
+
}),
|
|
98
|
+
[theme],
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
if (settings.status === "loading")
|
|
102
|
+
return <Text style={styles.text}>Loading host launch settings…</Text>;
|
|
103
|
+
if (settings.status !== "ready") {
|
|
104
|
+
return (
|
|
105
|
+
<View style={styles.root}>
|
|
106
|
+
<Text accessibilityRole="alert" style={styles.error}>
|
|
107
|
+
{settings.error}
|
|
108
|
+
</Text>
|
|
109
|
+
<SettingsAction
|
|
110
|
+
label="Read host launch settings again"
|
|
111
|
+
actionLabel="Reload"
|
|
112
|
+
onPress={settings.reload}
|
|
113
|
+
/>
|
|
114
|
+
</View>
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
return <ProviderLaunchSettingsControls settings={settings} />;
|
|
118
|
+
}
|
package/index.server.ts
CHANGED
|
@@ -24,6 +24,7 @@ import {
|
|
|
24
24
|
discoverOmpProfilesSync,
|
|
25
25
|
} from "./server/provider/profile-providers";
|
|
26
26
|
import { createOmpProvider } from "./server/provider/registration";
|
|
27
|
+
import { OmpPublicError } from "./server/provider/security";
|
|
27
28
|
import { resolveGetOmpProviderHealth } from "./server/provider-diagnostics";
|
|
28
29
|
import { resolveListOmpQuotas } from "./server/quota";
|
|
29
30
|
import { resolveListOmpSessions } from "./server/sessions";
|
|
@@ -43,6 +44,7 @@ import {
|
|
|
43
44
|
import { listOmpSettings, updateOmpSettings } from "./shared/omp-settings";
|
|
44
45
|
import { listOmpStores, type OmpStore } from "./shared/omp-store";
|
|
45
46
|
import { getOmpProviderHealth } from "./shared/provider-diagnostics";
|
|
47
|
+
import { providerLaunchSettings } from "./shared/provider-launch-settings";
|
|
46
48
|
import { listOmpQuotas } from "./shared/quota";
|
|
47
49
|
import { listOmpSessions } from "./shared/sessions";
|
|
48
50
|
import { getOmpSupportReport } from "./shared/support-diagnostics";
|
|
@@ -53,6 +55,12 @@ function scoped<T extends { store?: OmpStore }, R>(handler: (input: T) => R) {
|
|
|
53
55
|
|
|
54
56
|
export default function contribute(server: PluginServerContext) {
|
|
55
57
|
server.registerSettings(composerPillSettings);
|
|
58
|
+
const launchSettings = server.registerSettings(providerLaunchSettings);
|
|
59
|
+
const resolveHostInheritEnv = async (): Promise<readonly string[]> => {
|
|
60
|
+
const current = await launchSettings.read();
|
|
61
|
+
if (current.status === "ready") return current.values.inheritEnv;
|
|
62
|
+
throw new OmpPublicError("OMP host launch settings are unavailable");
|
|
63
|
+
};
|
|
56
64
|
const browserAuthorizationRegistry = new OmpBrowserAuthorizationRegistry();
|
|
57
65
|
const protocolViolations = new OmpProtocolViolationCollector();
|
|
58
66
|
const operationalFailures = new OmpOperationalFailureCollector();
|
|
@@ -64,6 +72,7 @@ export default function contribute(server: PluginServerContext) {
|
|
|
64
72
|
browserAuthorizationRegistry,
|
|
65
73
|
reportProtocolViolation: protocolViolations.report,
|
|
66
74
|
reportOperationalFailure: operationalFailures.report,
|
|
75
|
+
resolveHostInheritEnv,
|
|
67
76
|
}),
|
|
68
77
|
);
|
|
69
78
|
}
|
|
@@ -97,6 +106,7 @@ export default function contribute(server: PluginServerContext) {
|
|
|
97
106
|
browserAuthorizationRegistry,
|
|
98
107
|
reportProtocolViolation: protocolViolations.report,
|
|
99
108
|
reportOperationalFailure: operationalFailures.report,
|
|
109
|
+
resolveHostInheritEnv,
|
|
100
110
|
}),
|
|
101
111
|
);
|
|
102
112
|
return () => {
|
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 = "0.4.0-next.
|
|
2
|
+
export const PASEO_OMP_PACKAGE_VERSION = "0.4.0-next.138.1"; // x-release-please-version
|
|
@@ -9,6 +9,7 @@ type ProviderCatalogOptionsCompat = {
|
|
|
9
9
|
settings?: Readonly<Record<string, unknown>>;
|
|
10
10
|
};
|
|
11
11
|
|
|
12
|
+
import { MAX_INHERITED_ENVIRONMENT_NAMES } from "../../shared/provider-launch-settings";
|
|
12
13
|
import { parseOmpProviderOptions } from "./provider-options";
|
|
13
14
|
import { OmpPublicError } from "./security";
|
|
14
15
|
import { OmpModeSchema } from "./settings";
|
|
@@ -59,11 +60,24 @@ function allowedOmpTools(deniedTools: readonly string[] | undefined): string[] |
|
|
|
59
60
|
|
|
60
61
|
export type NormalizedOmpStartOptions = Omit<OmpStartOptions, "environment" | "signal">;
|
|
61
62
|
export type OmpRecoveryOptions = Omit<OmpStartOptions, "resumeSessionId" | "signal">;
|
|
63
|
+
export function mergeOmpInheritedEnvironmentNames(
|
|
64
|
+
hostNames: readonly string[],
|
|
65
|
+
profileNames: readonly string[] | undefined,
|
|
66
|
+
): string[] | undefined {
|
|
67
|
+
const names = [...new Set([...hostNames, ...(profileNames ?? [])])];
|
|
68
|
+
if (names.length > MAX_INHERITED_ENVIRONMENT_NAMES) {
|
|
69
|
+
throw new OmpPublicError("OMP inherited environment has too many entries");
|
|
70
|
+
}
|
|
71
|
+
return names.length > 0 ? names : undefined;
|
|
72
|
+
}
|
|
73
|
+
|
|
62
74
|
export function normalizeOmpCatalogOptions(
|
|
63
75
|
options: ProviderCatalogOptionsCompat,
|
|
64
76
|
cwd: string,
|
|
77
|
+
hostInheritEnv: readonly string[] = [],
|
|
65
78
|
): Omit<OmpStartOptions, "environment" | "signal"> {
|
|
66
79
|
const providerOptions = parseOmpProviderOptions(options.providerOptions);
|
|
80
|
+
const inheritEnv = mergeOmpInheritedEnvironmentNames(hostInheritEnv, providerOptions.inheritEnv);
|
|
67
81
|
const params = providerOptions.params ?? {};
|
|
68
82
|
return {
|
|
69
83
|
cwd,
|
|
@@ -71,7 +85,7 @@ export function normalizeOmpCatalogOptions(
|
|
|
71
85
|
noSession: true,
|
|
72
86
|
...(providerOptions.command ? { command: providerOptions.command } : {}),
|
|
73
87
|
...(providerOptions.env ? { env: providerOptions.env } : {}),
|
|
74
|
-
...(
|
|
88
|
+
...(inheritEnv ? { inheritEnv } : {}),
|
|
75
89
|
outputRedaction: providerOptions.outputRedaction,
|
|
76
90
|
...(params.sessionDir ? { sessionDir: params.sessionDir } : {}),
|
|
77
91
|
...(params.rpcTimeoutMs
|
|
@@ -103,6 +117,7 @@ export function withCommittedOmpSelection(
|
|
|
103
117
|
export function normalizeOmpSessionConfig(
|
|
104
118
|
config: ProviderSessionConfig,
|
|
105
119
|
permissionSupported = false,
|
|
120
|
+
hostInheritEnv: readonly string[] = [],
|
|
106
121
|
): NormalizedOmpStartOptions {
|
|
107
122
|
if (Object.keys(config.settings).length > 0) {
|
|
108
123
|
throw new OmpPublicError("OMP does not expose live provider settings");
|
|
@@ -122,11 +137,12 @@ export function normalizeOmpSessionConfig(
|
|
|
122
137
|
const tools = allowedOmpTools(deniedTools);
|
|
123
138
|
const params = options.params ?? {};
|
|
124
139
|
const env = { ...options.env, ...config.env };
|
|
140
|
+
const inheritEnv = mergeOmpInheritedEnvironmentNames(hostInheritEnv, options.inheritEnv);
|
|
125
141
|
return {
|
|
126
142
|
cwd: config.cwd,
|
|
127
143
|
...(options.command ? { command: options.command } : {}),
|
|
128
144
|
...(Object.keys(env).length > 0 ? { env } : {}),
|
|
129
|
-
...(
|
|
145
|
+
...(inheritEnv ? { inheritEnv } : {}),
|
|
130
146
|
outputRedaction: options.outputRedaction,
|
|
131
147
|
mode: parsedMode.data,
|
|
132
148
|
thinkingOption: config.thinkingOption,
|
|
@@ -715,6 +715,7 @@ export function createOmpConnection(
|
|
|
715
715
|
reportDiagnostic: (diagnostic: OmpConnectionDiagnostic) => void = (diagnostic) =>
|
|
716
716
|
console.error("OMP provider failure", diagnostic),
|
|
717
717
|
reportOperationalFailure: OmpOperationalFailureReporter = () => {},
|
|
718
|
+
resolveHostInheritEnv?: () => Promise<readonly string[]>,
|
|
718
719
|
): ProviderConnection {
|
|
719
720
|
const errorDetails = (error: unknown, fallback: string): { message: string } => {
|
|
720
721
|
if (isOmpPublicError(error)) return { message: error.message };
|
|
@@ -822,6 +823,7 @@ export function createOmpConnection(
|
|
|
822
823
|
settings: configuredInput.settings,
|
|
823
824
|
},
|
|
824
825
|
input.cwd ?? homedir(),
|
|
826
|
+
(await resolveHostInheritEnv?.()) ?? [],
|
|
825
827
|
);
|
|
826
828
|
const catalog = await discoverOmpCatalog(
|
|
827
829
|
runtime,
|
|
@@ -968,6 +970,7 @@ export function createOmpConnection(
|
|
|
968
970
|
mcpConnector,
|
|
969
971
|
mcpInitializationTimeoutMs,
|
|
970
972
|
reportOperationalFailure,
|
|
973
|
+
(await resolveHostInheritEnv?.()) ?? [],
|
|
971
974
|
);
|
|
972
975
|
const discoveredNativeSessionId = session.persistenceSessionId;
|
|
973
976
|
if (discoveredNativeSessionId) nativeSessionId = discoveredNativeSessionId;
|
|
@@ -5,6 +5,7 @@ import { z } from "zod";
|
|
|
5
5
|
import type { OmpBrowserAuthorizationRegistry } from "../mcp-browser";
|
|
6
6
|
import type { OmpOperationalFailureReporter } from "../operational-failure-diagnostics";
|
|
7
7
|
import { probeOmpAvailability } from "../provider-diagnostics";
|
|
8
|
+
import { mergeOmpInheritedEnvironmentNames } from "./config-normalization";
|
|
8
9
|
import { createOmpConnection, OmpNativeSessionReservations } from "./connection";
|
|
9
10
|
import type { OmpMcpConnector } from "./host-tools";
|
|
10
11
|
import { OmpRpcRuntime, type OmpRuntime } from "./omp-rpc";
|
|
@@ -74,6 +75,7 @@ export interface OmpProviderOptions {
|
|
|
74
75
|
options: ProviderCatalogOptionsCompat,
|
|
75
76
|
timeoutMs: number | undefined,
|
|
76
77
|
) => Promise<ProviderAvailabilityCompat>;
|
|
78
|
+
resolveHostInheritEnv?: () => Promise<readonly string[]>;
|
|
77
79
|
}
|
|
78
80
|
|
|
79
81
|
function stableJson(value: unknown): string {
|
|
@@ -104,6 +106,10 @@ export function createOmpProvider(options: OmpProviderOptions = {}): ProviderReg
|
|
|
104
106
|
providerOptionsSchema: OmpProviderOptionsSchema,
|
|
105
107
|
async getCatalogCacheKey(catalogOptions) {
|
|
106
108
|
const providerOptions = parseOmpProviderOptions(catalogOptions.providerOptions);
|
|
109
|
+
const inheritEnv = mergeOmpInheritedEnvironmentNames(
|
|
110
|
+
(await options.resolveHostInheritEnv?.()) ?? [],
|
|
111
|
+
providerOptions.inheritEnv,
|
|
112
|
+
);
|
|
107
113
|
// Profile providers cannot safely hash explicit environment values because they may be
|
|
108
114
|
// credentials. Disable sharing for that case; otherwise retain every normalized option
|
|
109
115
|
// that can change discovery alongside the fixed, non-secret store identity.
|
|
@@ -112,7 +118,7 @@ export function createOmpProvider(options: OmpProviderOptions = {}): ProviderReg
|
|
|
112
118
|
scope: catalogOptions.scope,
|
|
113
119
|
...(catalogOptions.scope === "workspace" ? { cwd: catalogOptions.cwd } : {}),
|
|
114
120
|
...(options.catalogIdentity ? { store: options.catalogIdentity } : {}),
|
|
115
|
-
providerOptions,
|
|
121
|
+
providerOptions: { ...providerOptions, ...(inheritEnv ? { inheritEnv } : {}) },
|
|
116
122
|
settings: catalogOptions.settings ?? {},
|
|
117
123
|
defaultCommand: (options.environment ?? process.env).OMP_COMMAND ?? "omp",
|
|
118
124
|
};
|
|
@@ -167,6 +173,7 @@ export function createOmpProvider(options: OmpProviderOptions = {}): ProviderReg
|
|
|
167
173
|
options.browserAuthorizationRegistry,
|
|
168
174
|
undefined,
|
|
169
175
|
options.reportOperationalFailure,
|
|
176
|
+
options.resolveHostInheritEnv,
|
|
170
177
|
);
|
|
171
178
|
},
|
|
172
179
|
};
|
|
@@ -451,6 +451,7 @@ export class OmpProviderSession {
|
|
|
451
451
|
mcpConnector?: OmpMcpConnector,
|
|
452
452
|
mcpInitializationTimeoutMs?: number,
|
|
453
453
|
reportOperationalFailure: OmpOperationalFailureReporter = () => {},
|
|
454
|
+
hostInheritEnv: readonly string[] = [],
|
|
454
455
|
): Promise<OmpProviderSession> {
|
|
455
456
|
const resumeSessionId = ompPersistenceSessionId(input);
|
|
456
457
|
if (resumeSessionId && !input.config.persist) {
|
|
@@ -466,6 +467,7 @@ export class OmpProviderSession {
|
|
|
466
467
|
const normalizedConfig = normalizeOmpSessionConfig(
|
|
467
468
|
effectiveConfig,
|
|
468
469
|
capabilities.includes("permission"),
|
|
470
|
+
hostInheritEnv,
|
|
469
471
|
);
|
|
470
472
|
const configuredRedactionValues = configuredOutputRedactionValues(
|
|
471
473
|
normalizedConfig.outputRedaction ?? "none",
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
+
import {
|
|
3
|
+
environmentNameSchema,
|
|
4
|
+
MAX_INHERITED_ENVIRONMENT_NAMES,
|
|
5
|
+
} from "../../shared/provider-launch-settings";
|
|
2
6
|
|
|
3
7
|
const MAX_COMMAND_PARTS = 64;
|
|
4
|
-
const MAX_ENV_ENTRIES = 256;
|
|
5
|
-
const MAX_TEXT_BYTES = 64 * 1024;
|
|
6
|
-
const MAX_MODEL_SELECTOR_BYTES = 513;
|
|
7
8
|
const MAX_PATH_BYTES = 4_096;
|
|
8
9
|
const MAX_RPC_TIMEOUT_MS = 10 * 60 * 1_000;
|
|
10
|
+
const MAX_TEXT_BYTES = 64 * 1024;
|
|
11
|
+
const MAX_MODEL_SELECTOR_BYTES = 513;
|
|
9
12
|
|
|
10
13
|
function boundedString(maxBytes: number) {
|
|
11
14
|
return z
|
|
@@ -18,7 +21,7 @@ const CommandPartSchema = boundedString(MAX_PATH_BYTES).refine(
|
|
|
18
21
|
(value) => !value.includes("\0") && !/[\r\n]/u.test(value),
|
|
19
22
|
"command arguments cannot contain NUL or line breaks",
|
|
20
23
|
);
|
|
21
|
-
const EnvironmentNameSchema =
|
|
24
|
+
const EnvironmentNameSchema = environmentNameSchema;
|
|
22
25
|
const EnvironmentValueSchema = z
|
|
23
26
|
.string()
|
|
24
27
|
.refine((value) => Buffer.byteLength(value, "utf8") <= MAX_TEXT_BYTES && !value.includes("\0"));
|
|
@@ -63,7 +66,7 @@ export const OmpProviderOptionsSchema = z
|
|
|
63
66
|
.optional(),
|
|
64
67
|
inheritEnv: z
|
|
65
68
|
.array(EnvironmentNameSchema)
|
|
66
|
-
.max(
|
|
69
|
+
.max(MAX_INHERITED_ENVIRONMENT_NAMES)
|
|
67
70
|
.describe("Daemon environment variable names copied at OMP spawn time")
|
|
68
71
|
.optional(),
|
|
69
72
|
outputRedaction: OmpOutputRedactionSchema.describe(
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { defineSettings } from "@getpaseo/plugin";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
|
|
4
|
+
export const MAX_INHERITED_ENVIRONMENT_NAMES = 256;
|
|
5
|
+
export const environmentNameSchema = z.string().regex(/^[A-Za-z_][A-Za-z0-9_]{0,127}$/u);
|
|
6
|
+
|
|
7
|
+
export const providerLaunchSettingsSchema = z.object({
|
|
8
|
+
inheritEnv: z.array(environmentNameSchema).max(MAX_INHERITED_ENVIRONMENT_NAMES).default([]),
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
export type ProviderLaunchSettings = z.infer<typeof providerLaunchSettingsSchema>;
|
|
12
|
+
|
|
13
|
+
export const providerLaunchSettings = defineSettings({
|
|
14
|
+
id: "provider-launch",
|
|
15
|
+
scope: "host",
|
|
16
|
+
version: 1,
|
|
17
|
+
schema: providerLaunchSettingsSchema,
|
|
18
|
+
});
|