@opengeni/runtime 4.3.0-canary.36844267522001 → 4.3.0
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/dist/assets/codemode-client.json +1 -1
- package/dist/{chunk-XFDVXBB7.js → chunk-22M75RJF.js} +413 -502
- package/dist/chunk-22M75RJF.js.map +1 -0
- package/dist/claude-subscription-usage.d.ts +1 -3
- package/dist/index.d.ts +0 -6
- package/dist/index.js +1 -3
- package/dist/mcp-run-credentials.d.ts +2 -3
- package/dist/model-preparation-diagnostics.d.ts +0 -9
- package/dist/model-request-capture.d.ts +0 -9
- package/dist/replayable-json-body.d.ts +1 -2
- package/dist/workspace-tool-gateway.js +1 -1
- package/package.json +12 -12
- package/src/bundled_default_skills/opengeni-client/SKILL.md +0 -5
- package/src/bundled_default_skills/opengeni-client/references/api-workflows.md +0 -8
- package/src/bundled_default_skills/opengeni-client/references/product-shapes-and-ui.md +3 -16
- package/src/claude-subscription-usage.ts +4 -23
- package/src/index.ts +2 -20
- package/src/lazy-tool-transport.ts +14 -22
- package/src/mcp-run-credentials.ts +3 -18
- package/src/model-preparation-diagnostics.ts +1 -48
- package/src/model-provider-client.ts +1 -5
- package/src/model-request-capture.ts +1 -28
- package/src/replayable-json-body.ts +2 -19
- package/dist/chunk-XFDVXBB7.js.map +0 -1
- package/src/bundled_default_skills/opengeni-client/references/usage-allowances.md +0 -178
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
type Observer = (providerId: string, response: Response) => void;
|
|
2
|
-
type Prepare = (providerId: string, headers: Headers) => Promise<Headers>;
|
|
3
2
|
/** Like Codex usage headers: free observations within this turn's provider context. */
|
|
4
|
-
export declare function withClaudeUsageObserver<T>(observer: Observer, run: () => Promise<T
|
|
5
|
-
export declare function prepareClaudeSubscriptionRequest(providerId: string, input: Parameters<typeof fetch>[0], init?: RequestInit): Promise<RequestInit | undefined>;
|
|
3
|
+
export declare function withClaudeUsageObserver<T>(observer: Observer, run: () => Promise<T>): Promise<T>;
|
|
6
4
|
export declare function observeClaudeUsageResponse(providerId: string, response: Response): void;
|
|
7
5
|
export {};
|
package/dist/index.d.ts
CHANGED
|
@@ -35,8 +35,6 @@ import { type WorkspaceSkillSearchPath } from "./workspace-skills.js";
|
|
|
35
35
|
import { type EffectiveSkillSelection, type RuntimeSkillActivation, type RuntimeSkillIndexEntry } from "./runtime-skills.js";
|
|
36
36
|
export { composeRuntimeSkills, loadNativeToolSkillArtifacts, readRuntimeSkill, skillCatalogFromComposition, type EffectiveSkillSelection, type InstalledSkillActivation, type NativeToolSkillSet, type RuntimeSkillActivation, type RuntimeSkillArtifact, type RuntimeSkillArtifactFile, type RuntimeSkillComposition, type RuntimeSkillDescriptor, type RuntimeSkillIndexEntry, type SessionSkillActivation, } from "./runtime-skills.js";
|
|
37
37
|
import { type PersistentAgentInstructionInspection } from "./model-context-inspector.js";
|
|
38
|
-
import { type ModelCallLifecycle } from "./model-request-capture.js";
|
|
39
|
-
export { beforeModelRequest as awaitModelCallAdmission } from "./model-request-capture.js";
|
|
40
38
|
import { type ModelPreparationMeasurement } from "./model-preparation-diagnostics.js";
|
|
41
39
|
import type { ModelResponseUsage, NormalizedRuntimeEvent, SerializedHumanInputInterruption, SerializedInteractionInterventionInterruption } from "./run-events.js";
|
|
42
40
|
export { buildPortableSkillArtifact, getSkillLibraryEntry, isSkillLibraryEntryId, listSkillLibraryEntries, loadSkillLibrarySkill, PORTABLE_SKILL_MAX_FILE_BYTES, PORTABLE_SKILL_MAX_FILES, PORTABLE_SKILL_MAX_TOTAL_BYTES, parsePortableSkillFrontmatter, skillLibraryRepositoryUrl, skillArtifactContentSha256, type PortableSkillArtifact, type SkillLibraryEntry, type SkillLibraryFile, type SkillLibrarySkill, } from "./skill-library.js";
|
|
@@ -1041,10 +1039,6 @@ export declare function restoreInterruptedRunState(agent: Agent<any, any>, seria
|
|
|
1041
1039
|
export declare const TURN_OPERATIONAL_NOTICE_PREFIX = "[OpenGeni turn-scoped operational notice]\n";
|
|
1042
1040
|
export declare function prepareRunInput(agent: Agent<any, any>, input: AgentSegmentInput, options?: PrepareInputOptions): Promise<PreparedAgentInput>;
|
|
1043
1041
|
export type RunAgentStreamOptions = {
|
|
1044
|
-
/** Producer-side gate before calling any resolved model/provider. */
|
|
1045
|
-
beforeModelRequest?: ModelCallLifecycle["beforeModelRequest"];
|
|
1046
|
-
/** Register terminal response settlement before the next producer model request. */
|
|
1047
|
-
onModelResponse?: ModelCallLifecycle["onModelResponse"];
|
|
1048
1042
|
/** Abort the provider/tool loop when the owning activity is cancelled. */
|
|
1049
1043
|
signal?: AbortSignal;
|
|
1050
1044
|
/** Nonblocking phase measurements for request preparation before provider I/O. */
|
package/dist/index.js
CHANGED
|
@@ -87,7 +87,6 @@ import {
|
|
|
87
87
|
attemptToolCallMeta,
|
|
88
88
|
azureCliLoginCommand,
|
|
89
89
|
azureOpenAIDefaultQuery,
|
|
90
|
-
beforeModelRequest,
|
|
91
90
|
boundModelToolOutputsFilterForSettings,
|
|
92
91
|
buildAgentCapabilities,
|
|
93
92
|
buildCompactionPromptInput,
|
|
@@ -284,7 +283,7 @@ import {
|
|
|
284
283
|
workspaceEnvironmentInstructions,
|
|
285
284
|
wrapAttemptToolDefinitions,
|
|
286
285
|
wrapAttemptToolExecute
|
|
287
|
-
} from "./chunk-
|
|
286
|
+
} from "./chunk-22M75RJF.js";
|
|
288
287
|
import {
|
|
289
288
|
ActiveBackendUnresolvableError,
|
|
290
289
|
BROWSER_CONTROL_ADMIN_TOKEN_FILE,
|
|
@@ -791,7 +790,6 @@ export {
|
|
|
791
790
|
assertProviderRegistryInvariants,
|
|
792
791
|
assertSafeRelPath,
|
|
793
792
|
attemptToolCallMeta,
|
|
794
|
-
beforeModelRequest as awaitModelCallAdmission,
|
|
795
793
|
azureCliLoginCommand,
|
|
796
794
|
azureOpenAIDefaultQuery,
|
|
797
795
|
backendSupportsOs,
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { CredentialProviderMcpMaterial
|
|
1
|
+
import { CredentialProviderMcpMaterial } from "@opengeni/contracts";
|
|
2
2
|
export type RunMcpCredentialTarget = {
|
|
3
3
|
id: string;
|
|
4
4
|
url: string;
|
|
5
|
-
connectionRef?: McpServerConnectionRef | undefined;
|
|
6
5
|
};
|
|
7
6
|
export type RunMcpCredentialMaterial = {
|
|
8
7
|
mcp?: CredentialProviderMcpMaterial;
|
|
@@ -27,7 +26,7 @@ export declare class RunMcpCredentials {
|
|
|
27
26
|
/** Validate a complete replacement before changing any live request headers. */
|
|
28
27
|
prepare(material: RunMcpCredentialMaterial | null): () => void;
|
|
29
28
|
replace(material: RunMcpCredentialMaterial | null): void;
|
|
30
|
-
/** Refuse credentials for
|
|
29
|
+
/** Refuse credentials for omitted, local, or rewritten server routes. */
|
|
31
30
|
assertRemoteTargets(targets: readonly RunMcpCredentialTarget[]): void;
|
|
32
31
|
excludeLocalTarget(id: string): void;
|
|
33
32
|
has(id: string): boolean;
|
|
@@ -6,21 +6,12 @@ export type ModelPreparationMeasurement = {
|
|
|
6
6
|
count?: number;
|
|
7
7
|
};
|
|
8
8
|
type ModelPreparationObserver = (measurement: ModelPreparationMeasurement) => void;
|
|
9
|
-
type ModelTransportFetch = (...args: Parameters<typeof fetch>) => ReturnType<typeof fetch>;
|
|
10
9
|
export declare function withModelPreparationObserver<T>(observer: ModelPreparationObserver | undefined, callback: () => T): T;
|
|
11
10
|
/** Bind one attempt-local durable checkpoint immediately before generic model
|
|
12
11
|
* transport enters fetch. Cached provider clients are process-global, so this
|
|
13
12
|
* authority must be async-local rather than stored on the client instance. */
|
|
14
13
|
export declare function withModelTransportStartedObserver<T>(observer: (() => Promise<void> | void) | undefined, callback: () => T): T;
|
|
15
14
|
export declare function recordModelTransportStarted(): Promise<void>;
|
|
16
|
-
/** The OpenAI SDK retries thrown fetch errors and replaces their identity with
|
|
17
|
-
* APIConnectionError. Carry only our pre-wire refusal through its HTTP-error
|
|
18
|
-
* path, which honors the retry veto. Native transports keep the original throw.
|
|
19
|
-
* Each fetch owns its context even when concurrent turns share a cached client.
|
|
20
|
-
*/
|
|
21
|
-
export declare function sdkModelTransportAdmissionFetch(inner: ModelTransportFetch): ModelTransportFetch;
|
|
22
|
-
/** Restore the exact host-owned error after the SDK has suppressed retries. */
|
|
23
|
-
export declare function rethrowModelTransportAdmissionRefusal(headers: Headers): void;
|
|
24
15
|
/** Record the first routed sandbox operation boundary without publishing an
|
|
25
16
|
* overlapping parent duration. The observer receives only exclusive leaf
|
|
26
17
|
* buckets; this boundary exists solely to split the surrounding SDK work. */
|
|
@@ -3,15 +3,6 @@ export type ModelRequestCapture = ((request: ModelRequest) => void | Promise<voi
|
|
|
3
3
|
nextProviderRequestIndex?: () => number;
|
|
4
4
|
onProviderRequest?: (provider: string, body: string | null, reason?: string, index?: number) => void | Promise<void>;
|
|
5
5
|
};
|
|
6
|
-
/** Awaited producer-side authority, separate from observational request capture. */
|
|
7
|
-
export type ModelCallLifecycle = {
|
|
8
|
-
beforeModelRequest?: () => Promise<void>;
|
|
9
|
-
/** Register before yielding so the next model entry waits for consumer settlement. */
|
|
10
|
-
onModelResponse?: (event: StreamEvent) => Promise<void>;
|
|
11
|
-
};
|
|
12
|
-
export declare function withModelCallLifecycle<T>(lifecycle: ModelCallLifecycle, fn: () => T): T;
|
|
13
|
-
export declare function beforeModelRequest(): Promise<void>;
|
|
14
|
-
export declare function modelResponseSettlement(event: StreamEvent): Promise<void> | undefined;
|
|
15
6
|
/** The same agent can re-enter runAgentStream after in-activity compaction. */
|
|
16
7
|
export declare function nextModelContextCaptureIndex(agent: object): number;
|
|
17
8
|
export declare function withModelRequestCapture<T>(capture: ModelRequestCapture | undefined, fn: () => T): T;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import OpenAI
|
|
1
|
+
import OpenAI from "openai";
|
|
2
2
|
import type { APIPromise } from "openai/core/api-promise";
|
|
3
3
|
/** Internal fetch-init hook used only when a transport performs its own retry. */
|
|
4
4
|
export declare const REPLAYABLE_REQUEST_BODY_FACTORY: unique symbol;
|
|
@@ -46,7 +46,6 @@ export declare function requestBodyText(body: BodyInit | null | undefined): Prom
|
|
|
46
46
|
export declare class ReplayableJsonOpenAI extends OpenAI {
|
|
47
47
|
private readonly modelRequestPolicy;
|
|
48
48
|
constructor(options: OpenAIOptions, hooks?: ReplayableJsonOpenAIHooks);
|
|
49
|
-
protected makeStatusError(status: number, error: NonNullable<Parameters<typeof APIError.generate>[1]>, message: string | undefined, headers: Headers): APIError;
|
|
50
49
|
post<Rsp>(path: string, opts?: OpenAIPostOptions): APIPromise<Rsp>;
|
|
51
50
|
buildRequest(inputOptions: OpenAIBuildOptions, context?: OpenAIBuildContext): Promise<OpenAIBuildResult>;
|
|
52
51
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opengeni/runtime",
|
|
3
|
-
"version": "4.3.0
|
|
3
|
+
"version": "4.3.0",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -63,17 +63,17 @@
|
|
|
63
63
|
"@openai/agents": "0.14.3",
|
|
64
64
|
"@openai/agents-core": "0.14.3",
|
|
65
65
|
"@openai/agents-extensions": "0.14.3",
|
|
66
|
-
"@opengeni/agent-proto": "^0.6.0
|
|
67
|
-
"@opengeni/capabilities": "^0.3.4
|
|
68
|
-
"@opengeni/codemode": "^0.6.5
|
|
69
|
-
"@opengeni/codex": "^0.2.29
|
|
70
|
-
"@opengeni/config": "^3.1.1
|
|
71
|
-
"@opengeni/contracts": "^5.4.0
|
|
72
|
-
"@opengeni/network": "^0.3.1
|
|
73
|
-
"@opengeni/observability": "^0.8.35
|
|
74
|
-
"@opengeni/sdk": "^7.4.0
|
|
75
|
-
"@opengeni/tool-gateway": "^0.1.16
|
|
76
|
-
"@opengeni/xai-subscription": "^0.1.4
|
|
66
|
+
"@opengeni/agent-proto": "^0.6.0",
|
|
67
|
+
"@opengeni/capabilities": "^0.3.4",
|
|
68
|
+
"@opengeni/codemode": "^0.6.5",
|
|
69
|
+
"@opengeni/codex": "^0.2.29",
|
|
70
|
+
"@opengeni/config": "^3.1.1",
|
|
71
|
+
"@opengeni/contracts": "^5.4.0",
|
|
72
|
+
"@opengeni/network": "^0.3.1",
|
|
73
|
+
"@opengeni/observability": "^0.8.35",
|
|
74
|
+
"@opengeni/sdk": "^7.4.0",
|
|
75
|
+
"@opengeni/tool-gateway": "^0.1.16",
|
|
76
|
+
"@opengeni/xai-subscription": "^0.1.4",
|
|
77
77
|
"debug": "4.4.3",
|
|
78
78
|
"modal": "0.9.0",
|
|
79
79
|
"openai": "6.47.0",
|
|
@@ -184,11 +184,6 @@ Read selectively: [Product integration shapes](references/product-integration-sh
|
|
|
184
184
|
[Data tools and credentials](references/data-tools-and-credentials.md), and
|
|
185
185
|
[External users and embedded connection setup](references/external-users-and-connect.md).
|
|
186
186
|
|
|
187
|
-
For per-seat included usage, administrator splits, top-ups, team budgets, or
|
|
188
|
-
browser progress meters, read [Usage allowances](references/usage-allowances.md).
|
|
189
|
-
Keep organization-budget writes on the backend; the conversation proxy exposes
|
|
190
|
-
only own usage. These are post-call ceilings, not prepaid reservations.
|
|
191
|
-
|
|
192
187
|
## Build Gotchas
|
|
193
188
|
|
|
194
189
|
- Always pass `baseUrl` (`process.env.OPENGENI_API_BASE_URL`); the chat facade
|
|
@@ -25,8 +25,6 @@ Only add `x-opengeni-access-key` when the operator says the deployment
|
|
|
25
25
|
shared-key boundary is enabled. It is not a replacement for organization API
|
|
26
26
|
keys in managed SaaS.
|
|
27
27
|
|
|
28
|
-
A full organization API key can provision workspaces, members and asUser sessions; /v1/access/me reports this as credential.effectiveWorkspacePermissions.
|
|
29
|
-
|
|
30
28
|
## Minimal Server-Side Session Client
|
|
31
29
|
|
|
32
30
|
```ts
|
|
@@ -249,12 +247,6 @@ Never distribute an OpenGeni credential to a Connected Machine or try to inject
|
|
|
249
247
|
|
|
250
248
|
## Billing And Limits
|
|
251
249
|
|
|
252
|
-
For per-seat plans, team budgets, administrator splits, and top-ups, read
|
|
253
|
-
[Usage allowances](usage-allowances.md). Amounts are integer USD micros,
|
|
254
|
-
configuration/member writes are versioned, grants are operation-keyed, and
|
|
255
|
-
the conversation proxy exposes only `/usage/me`. Verify actual debit/reset
|
|
256
|
-
and webhook behavior before promising enforcement or notifications.
|
|
257
|
-
|
|
258
250
|
Managed SaaS uses prepaid Stripe credits and local usage/cost accounting. Client behavior should be simple:
|
|
259
251
|
|
|
260
252
|
- Show billing/credit status from `/v1/billing` when the user has billing permission.
|
|
@@ -31,22 +31,9 @@ console routes and 404 on the product origin. Never pass them to a raw `<a>`.
|
|
|
31
31
|
proxy `sandboxFiles: true` (default off) plus `files:read`; they are confined
|
|
32
32
|
to the selected working directory, including on Connected Machines, and
|
|
33
33
|
refuse symlinked paths. Disabled sandbox links render unavailable.
|
|
34
|
-
-
|
|
35
|
-
`
|
|
36
|
-
`
|
|
37
|
-
(for example the main area beside an assistant panel, a full-screen sheet on
|
|
38
|
-
phones) and pass `onOpenArtifact` to `SessionConversation` (or
|
|
39
|
-
`viewerLinkResolver` to `MessageTimeline`). Enable the proxy's
|
|
40
|
-
`artifacts: true`; editors also need the document, spreadsheet, and
|
|
41
|
-
presentation runtimes (`@opengeni/artifact-kernel-wasm-document`,
|
|
42
|
-
`@opengeni/artifact-kernel-wasm-spreadsheet`,
|
|
43
|
-
`@opengeni/artifact-kernel-wasm-presentation`) plus the SDK Worker URL
|
|
44
|
-
(`editableRuntimes`). A custom host proxy reports the viewer capability with
|
|
45
|
-
`artifactViewerCapability` from `@opengeni/sdk`. Close the viewer when the session changes.
|
|
46
|
-
Translate its copy with `labels` (partial `ArtifactLabels`) or
|
|
47
|
-
`ArtifactLabelsProvider`.
|
|
48
|
-
- Other routing: `resolveLink={(target) => ... ({ href } | { open } | null)}`
|
|
49
|
-
on `SessionConversation` or `MessageTimeline`, or `OpenGeniLinkProvider` for a
|
|
34
|
+
- Route editable artifacts and Sites to the product's own UI with
|
|
35
|
+
`resolveLink={(target) => ... ({ href } | { open } | null)}` on
|
|
36
|
+
`SessionConversation` or `MessageTimeline`, or `OpenGeniLinkProvider` for a
|
|
50
37
|
subtree; it also covers `Markdown` inside a custom `renderMessageText`.
|
|
51
38
|
Unresolved targets render as unavailable text, not broken links.
|
|
52
39
|
- `MessageTimeline` alone has no defaults; add
|
|
@@ -1,34 +1,15 @@
|
|
|
1
1
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
2
2
|
|
|
3
3
|
type Observer = (providerId: string, response: Response) => void;
|
|
4
|
-
|
|
5
|
-
const observers = new AsyncLocalStorage<{
|
|
6
|
-
observe: Observer;
|
|
7
|
-
prepare?: Prepare;
|
|
8
|
-
}>();
|
|
4
|
+
const observers = new AsyncLocalStorage<Observer>();
|
|
9
5
|
|
|
10
6
|
/** Like Codex usage headers: free observations within this turn's provider context. */
|
|
11
|
-
export function withClaudeUsageObserver<T>(
|
|
12
|
-
observer
|
|
13
|
-
run: () => Promise<T>,
|
|
14
|
-
prepare?: Prepare,
|
|
15
|
-
): Promise<T> {
|
|
16
|
-
return observers.run({ observe: observer, ...(prepare ? { prepare } : {}) }, run);
|
|
17
|
-
}
|
|
18
|
-
export async function prepareClaudeSubscriptionRequest(
|
|
19
|
-
providerId: string,
|
|
20
|
-
input: Parameters<typeof fetch>[0],
|
|
21
|
-
init?: RequestInit,
|
|
22
|
-
) {
|
|
23
|
-
const prepare = observers.getStore()?.prepare;
|
|
24
|
-
if (!prepare) return init;
|
|
25
|
-
const headers = new Headers(input instanceof Request ? input.headers : undefined);
|
|
26
|
-
new Headers(init?.headers).forEach((value, key) => headers.set(key, value));
|
|
27
|
-
return { ...init, headers: await prepare(providerId, headers) };
|
|
7
|
+
export function withClaudeUsageObserver<T>(observer: Observer, run: () => Promise<T>): Promise<T> {
|
|
8
|
+
return observers.run(observer, run);
|
|
28
9
|
}
|
|
29
10
|
export function observeClaudeUsageResponse(providerId: string, response: Response): void {
|
|
30
11
|
try {
|
|
31
|
-
observers.getStore()?.
|
|
12
|
+
observers.getStore()?.(providerId, response);
|
|
32
13
|
} catch {
|
|
33
14
|
// Usage telemetry must never change or consume a model response.
|
|
34
15
|
}
|
package/src/index.ts
CHANGED
|
@@ -369,13 +369,10 @@ import {
|
|
|
369
369
|
ModelRequestCaptureProvider,
|
|
370
370
|
notifyModelRequestCapture,
|
|
371
371
|
withModelRequestCapture,
|
|
372
|
-
withModelCallLifecycle,
|
|
373
|
-
type ModelCallLifecycle,
|
|
374
372
|
type ModelRequestCapture,
|
|
375
373
|
nextModelContextCaptureIndex,
|
|
376
374
|
} from "./model-request-capture";
|
|
377
375
|
import { decodeValidatedViewImageDataUrl } from "./view-image-validation";
|
|
378
|
-
export { beforeModelRequest as awaitModelCallAdmission } from "./model-request-capture";
|
|
379
376
|
import {
|
|
380
377
|
baseModelInputFilterForSettings,
|
|
381
378
|
boundModelToolOutputsFilterForSettings,
|
|
@@ -4381,7 +4378,6 @@ export async function prepareAgentTools(
|
|
|
4381
4378
|
settings.mcpServers.filter(
|
|
4382
4379
|
(config) =>
|
|
4383
4380
|
tools.some((tool) => tool.id === config.id) &&
|
|
4384
|
-
!config.connectionRef &&
|
|
4385
4381
|
!localRegistry.has(config.id) &&
|
|
4386
4382
|
!isFirstPartyMcpServer(settings, config) &&
|
|
4387
4383
|
!isCodexAppsMcpServer(config),
|
|
@@ -5005,7 +5001,6 @@ export function selectedSessionRemoteMcpTargets(
|
|
|
5005
5001
|
if (configs.length !== 1) return [];
|
|
5006
5002
|
const config = configs[0]!;
|
|
5007
5003
|
if (
|
|
5008
|
-
config.connectionRef ||
|
|
5009
5004
|
isFirstPartyMcpServer(settings, config) ||
|
|
5010
5005
|
isCodexAppsMcpServer(config) ||
|
|
5011
5006
|
BUILT_IN_MCP_BRIDGE_ADAPTERS.some((adapter) =>
|
|
@@ -8055,10 +8050,6 @@ export async function prepareRunInput(
|
|
|
8055
8050
|
}
|
|
8056
8051
|
|
|
8057
8052
|
export type RunAgentStreamOptions = {
|
|
8058
|
-
/** Producer-side gate before calling any resolved model/provider. */
|
|
8059
|
-
beforeModelRequest?: ModelCallLifecycle["beforeModelRequest"];
|
|
8060
|
-
/** Register terminal response settlement before the next producer model request. */
|
|
8061
|
-
onModelResponse?: ModelCallLifecycle["onModelResponse"];
|
|
8062
8053
|
/** Abort the provider/tool loop when the owning activity is cancelled. */
|
|
8063
8054
|
signal?: AbortSignal;
|
|
8064
8055
|
/** Nonblocking phase measurements for request preparation before provider I/O. */
|
|
@@ -8302,17 +8293,8 @@ export async function runAgentStream(
|
|
|
8302
8293
|
const scope = gate?.beginStream(overrides.signal);
|
|
8303
8294
|
try {
|
|
8304
8295
|
if (scope) agent.toolUseBehavior = scope.toolUseBehavior;
|
|
8305
|
-
const stream = await
|
|
8306
|
-
|
|
8307
|
-
...(overrides.beforeModelRequest
|
|
8308
|
-
? { beforeModelRequest: overrides.beforeModelRequest }
|
|
8309
|
-
: {}),
|
|
8310
|
-
...(overrides.onModelResponse ? { onModelResponse: overrides.onModelResponse } : {}),
|
|
8311
|
-
},
|
|
8312
|
-
() =>
|
|
8313
|
-
withPreparedCompactionRequest(agent, () =>
|
|
8314
|
-
runAgentStreamInternal(agent, input, settings, overrides, scope),
|
|
8315
|
-
),
|
|
8296
|
+
const stream = await withPreparedCompactionRequest(agent, () =>
|
|
8297
|
+
runAgentStreamInternal(agent, input, settings, overrides, scope),
|
|
8316
8298
|
);
|
|
8317
8299
|
// Observe the SDK's own settlement promise before exposing the stream. Do
|
|
8318
8300
|
// not wrap/replace SDK history, errors, cancellation, or stream iteration.
|
|
@@ -12,11 +12,7 @@ import {
|
|
|
12
12
|
} from "@openai/agents";
|
|
13
13
|
import { isSearchableMcpFunctionTool, searchToolPool } from "./codex-tool-search";
|
|
14
14
|
import { MCP_MAX_TOOL_SEARCH_DISCLOSURE_BYTES } from "./mcp-network";
|
|
15
|
-
import {
|
|
16
|
-
beforeModelRequest,
|
|
17
|
-
modelResponseSettlement,
|
|
18
|
-
notifyModelRequestCapture,
|
|
19
|
-
} from "./model-request-capture";
|
|
15
|
+
import { notifyModelRequestCapture } from "./model-request-capture";
|
|
20
16
|
|
|
21
17
|
/** Provider-contained progressive-disclosure strategy for one resolved turn. */
|
|
22
18
|
export type LazyToolTransport = "codex_native" | "openai_native" | "generic_dispatch";
|
|
@@ -833,7 +829,6 @@ class LazyToolModel implements Model {
|
|
|
833
829
|
) {}
|
|
834
830
|
|
|
835
831
|
async getResponse(request: ModelRequest): Promise<ModelResponse> {
|
|
836
|
-
await beforeModelRequest();
|
|
837
832
|
const prepared = prepareLazyToolRequest(request, this.runtime);
|
|
838
833
|
rememberPreparedModelRequest(prepared);
|
|
839
834
|
void notifyModelRequestCapture(prepared);
|
|
@@ -847,7 +842,6 @@ class LazyToolModel implements Model {
|
|
|
847
842
|
}
|
|
848
843
|
|
|
849
844
|
async *getStreamedResponse(request: ModelRequest): AsyncIterable<StreamEvent> {
|
|
850
|
-
await beforeModelRequest();
|
|
851
845
|
const prepared = prepareLazyToolRequest(request, this.runtime);
|
|
852
846
|
rememberPreparedModelRequest(prepared);
|
|
853
847
|
void notifyModelRequestCapture(prepared);
|
|
@@ -857,21 +851,19 @@ class LazyToolModel implements Model {
|
|
|
857
851
|
await this.runtime.ensurePrepared();
|
|
858
852
|
}
|
|
859
853
|
}
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
void settlement?.catch(() => undefined);
|
|
874
|
-
yield delivered;
|
|
854
|
+
if (this.runtime.transport === "generic_dispatch" && event.type === "response_done") {
|
|
855
|
+
yield {
|
|
856
|
+
...event,
|
|
857
|
+
response: {
|
|
858
|
+
...event.response,
|
|
859
|
+
output: event.response.output.flatMap((item) =>
|
|
860
|
+
transformGenericDispatchCall(item, this.runtime),
|
|
861
|
+
) as typeof event.response.output,
|
|
862
|
+
},
|
|
863
|
+
} as StreamEvent;
|
|
864
|
+
} else {
|
|
865
|
+
yield event;
|
|
866
|
+
}
|
|
875
867
|
}
|
|
876
868
|
}
|
|
877
869
|
|
|
@@ -1,14 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
CredentialProviderMcpMaterial,
|
|
3
3
|
normalizeCredentialProviderMcpUrl,
|
|
4
|
-
type McpServerConnectionRef,
|
|
5
4
|
} from "@opengeni/contracts";
|
|
6
5
|
|
|
7
|
-
export type RunMcpCredentialTarget = {
|
|
8
|
-
id: string;
|
|
9
|
-
url: string;
|
|
10
|
-
connectionRef?: McpServerConnectionRef | undefined;
|
|
11
|
-
};
|
|
6
|
+
export type RunMcpCredentialTarget = { id: string; url: string };
|
|
12
7
|
export type RunMcpCredentialMaterial = {
|
|
13
8
|
mcp?: CredentialProviderMcpMaterial;
|
|
14
9
|
expiresAt: Date | null;
|
|
@@ -48,9 +43,7 @@ export class RunMcpCredentials {
|
|
|
48
43
|
targets: readonly RunMcpCredentialTarget[],
|
|
49
44
|
options: { signal?: AbortSignal; now?: () => number } = {},
|
|
50
45
|
) {
|
|
51
|
-
this.#targets = targets
|
|
52
|
-
.filter((target) => !target.connectionRef)
|
|
53
|
-
.map(({ id, url }) => ({ id, url }));
|
|
46
|
+
this.#targets = targets.map(({ id, url }) => ({ id, url }));
|
|
54
47
|
this.#signal = options.signal;
|
|
55
48
|
this.#now = options.now ?? Date.now;
|
|
56
49
|
this.#signal?.addEventListener("abort", this.#onAbort, { once: true });
|
|
@@ -142,12 +135,11 @@ export class RunMcpCredentials {
|
|
|
142
135
|
this.prepare(material)();
|
|
143
136
|
}
|
|
144
137
|
|
|
145
|
-
/** Refuse credentials for
|
|
138
|
+
/** Refuse credentials for omitted, local, or rewritten server routes. */
|
|
146
139
|
assertRemoteTargets(targets: readonly RunMcpCredentialTarget[]): void {
|
|
147
140
|
this.#remoteTargets = this.#targets.filter((original) =>
|
|
148
141
|
targets.some(
|
|
149
142
|
(target) =>
|
|
150
|
-
!target.connectionRef &&
|
|
151
143
|
target.id === original.id &&
|
|
152
144
|
normalizedUrl(target.url) !== null &&
|
|
153
145
|
normalizedUrl(target.url) === normalizedUrl(original.url),
|
|
@@ -203,13 +195,6 @@ export class RunMcpCredentials {
|
|
|
203
195
|
init?: RequestInit,
|
|
204
196
|
): RequestInit | undefined {
|
|
205
197
|
this.#assertOpen();
|
|
206
|
-
// Native connection authority and attribution own all authentication on
|
|
207
|
-
// this route. Even a stale or manually supplied provider grant must never
|
|
208
|
-
// replace its bearer or inject alternate authentication headers.
|
|
209
|
-
if (target.connectionRef) {
|
|
210
|
-
this.excludeLocalTarget(target.id);
|
|
211
|
-
return init;
|
|
212
|
-
}
|
|
213
198
|
this.assertAvailable(target.id);
|
|
214
199
|
const entry = this.#entries.get(target.id);
|
|
215
200
|
if (!entry) return init;
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
2
2
|
import { setTraceProcessors, type Span, type Trace, type TracingProcessor } from "@openai/agents";
|
|
3
|
-
import { beforeModelRequest } from "./model-request-capture";
|
|
4
3
|
|
|
5
4
|
export type ModelPreparationPhase =
|
|
6
5
|
| "sandbox_agent_preparation"
|
|
@@ -65,10 +64,6 @@ type ModelPreparationObservation = {
|
|
|
65
64
|
|
|
66
65
|
const modelPreparationObserver = new AsyncLocalStorage<ModelPreparationObservation>();
|
|
67
66
|
const modelTransportStartedObserver = new AsyncLocalStorage<() => Promise<void> | void>();
|
|
68
|
-
type ModelTransportAdmission = { refusal?: { error: unknown } };
|
|
69
|
-
type ModelTransportFetch = (...args: Parameters<typeof fetch>) => ReturnType<typeof fetch>;
|
|
70
|
-
const modelTransportAdmission = new AsyncLocalStorage<ModelTransportAdmission>();
|
|
71
|
-
const modelTransportRefusals = new WeakMap<Headers, { error: unknown }>();
|
|
72
67
|
|
|
73
68
|
class ModelPreparationTraceProcessor implements TracingProcessor {
|
|
74
69
|
async onTraceStart(_trace: Trace): Promise<void> {}
|
|
@@ -132,49 +127,7 @@ export function withModelTransportStartedObserver<T>(
|
|
|
132
127
|
}
|
|
133
128
|
|
|
134
129
|
export async function recordModelTransportStarted(): Promise<void> {
|
|
135
|
-
|
|
136
|
-
await beforeModelRequest();
|
|
137
|
-
await modelTransportStartedObserver.getStore()?.();
|
|
138
|
-
} catch (error) {
|
|
139
|
-
const admission = modelTransportAdmission.getStore();
|
|
140
|
-
if (admission) admission.refusal = { error };
|
|
141
|
-
throw error;
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
/** The OpenAI SDK retries thrown fetch errors and replaces their identity with
|
|
146
|
-
* APIConnectionError. Carry only our pre-wire refusal through its HTTP-error
|
|
147
|
-
* path, which honors the retry veto. Native transports keep the original throw.
|
|
148
|
-
* Each fetch owns its context even when concurrent turns share a cached client.
|
|
149
|
-
*/
|
|
150
|
-
export function sdkModelTransportAdmissionFetch(inner: ModelTransportFetch): ModelTransportFetch {
|
|
151
|
-
return async (input, init) => {
|
|
152
|
-
const admission: ModelTransportAdmission = {};
|
|
153
|
-
return modelTransportAdmission.run(admission, async () => {
|
|
154
|
-
try {
|
|
155
|
-
return await inner(input, init);
|
|
156
|
-
} catch (error) {
|
|
157
|
-
if (!admission.refusal || admission.refusal.error !== error) throw error;
|
|
158
|
-
// This is a local SDK handoff, not a provider or public API response.
|
|
159
|
-
// Identity, not response bytes/headers supplied by a provider, grants
|
|
160
|
-
// access to the original error at the SDK's status-error boundary.
|
|
161
|
-
const response = new Response(null, {
|
|
162
|
-
status: 400,
|
|
163
|
-
headers: { "x-should-retry": "false" },
|
|
164
|
-
});
|
|
165
|
-
modelTransportRefusals.set(response.headers, admission.refusal);
|
|
166
|
-
return response;
|
|
167
|
-
}
|
|
168
|
-
});
|
|
169
|
-
};
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
/** Restore the exact host-owned error after the SDK has suppressed retries. */
|
|
173
|
-
export function rethrowModelTransportAdmissionRefusal(headers: Headers): void {
|
|
174
|
-
const refusal = modelTransportRefusals.get(headers);
|
|
175
|
-
if (!refusal) return;
|
|
176
|
-
modelTransportRefusals.delete(headers);
|
|
177
|
-
throw refusal.error;
|
|
130
|
+
await modelTransportStartedObserver.getStore()?.();
|
|
178
131
|
}
|
|
179
132
|
|
|
180
133
|
/** Record the first routed sandbox operation boundary without publishing an
|
|
@@ -29,10 +29,7 @@ import { ReplayableJsonOpenAI } from "./replayable-json-body";
|
|
|
29
29
|
import { recordModelTransportStarted } from "./model-preparation-diagnostics";
|
|
30
30
|
import { captureProviderRequestBody } from "./model-request-capture";
|
|
31
31
|
import { withoutQuotaExhaustedRetries } from "./provider-quota";
|
|
32
|
-
import {
|
|
33
|
-
observeClaudeUsageResponse,
|
|
34
|
-
prepareClaudeSubscriptionRequest,
|
|
35
|
-
} from "./claude-subscription-usage";
|
|
32
|
+
import { observeClaudeUsageResponse } from "./claude-subscription-usage";
|
|
36
33
|
|
|
37
34
|
let runtimeMetricsHooks: RuntimeMetricsHooks | null = null;
|
|
38
35
|
|
|
@@ -403,7 +400,6 @@ export function instrumentedModelFetch(provider: string, inner: typeof fetch): t
|
|
|
403
400
|
if (!isModelCallFetch(input)) {
|
|
404
401
|
return await inner(input, init);
|
|
405
402
|
}
|
|
406
|
-
init = await prepareClaudeSubscriptionRequest(provider, input, init);
|
|
407
403
|
// The attempt-local observer durably checkpoints provider dispatch before
|
|
408
404
|
// this process can place request bytes on the network.
|
|
409
405
|
await recordModelTransportStarted();
|
|
@@ -14,27 +14,6 @@ export type ModelRequestCapture = ((request: ModelRequest) => void | Promise<voi
|
|
|
14
14
|
const modelRequestCapture = new AsyncLocalStorage<ModelRequestCapture>();
|
|
15
15
|
const captureIndices = new WeakMap<object, number>();
|
|
16
16
|
|
|
17
|
-
/** Awaited producer-side authority, separate from observational request capture. */
|
|
18
|
-
export type ModelCallLifecycle = {
|
|
19
|
-
beforeModelRequest?: () => Promise<void>;
|
|
20
|
-
/** Register before yielding so the next model entry waits for consumer settlement. */
|
|
21
|
-
onModelResponse?: (event: StreamEvent) => Promise<void>;
|
|
22
|
-
};
|
|
23
|
-
const modelCallLifecycle = new AsyncLocalStorage<ModelCallLifecycle>();
|
|
24
|
-
|
|
25
|
-
export function withModelCallLifecycle<T>(lifecycle: ModelCallLifecycle, fn: () => T): T {
|
|
26
|
-
return modelCallLifecycle.run(lifecycle, fn);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export async function beforeModelRequest(): Promise<void> {
|
|
30
|
-
await modelCallLifecycle.getStore()?.beforeModelRequest?.();
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export function modelResponseSettlement(event: StreamEvent): Promise<void> | undefined {
|
|
34
|
-
if (event.type !== "response_done") return undefined;
|
|
35
|
-
return modelCallLifecycle.getStore()?.onModelResponse?.(event);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
17
|
/** The same agent can re-enter runAgentStream after in-activity compaction. */
|
|
39
18
|
export function nextModelContextCaptureIndex(agent: object): number {
|
|
40
19
|
const index = (captureIndices.get(agent) ?? 0) + 1;
|
|
@@ -154,21 +133,15 @@ export class ModelRequestCaptureModel implements Model {
|
|
|
154
133
|
constructor(private readonly inner: Model) {}
|
|
155
134
|
|
|
156
135
|
async getResponse(request: ModelRequest) {
|
|
157
|
-
await beforeModelRequest();
|
|
158
136
|
rememberPreparedModelRequest(request);
|
|
159
137
|
void notifyModelRequestCapture(request);
|
|
160
138
|
return this.inner.getResponse(request);
|
|
161
139
|
}
|
|
162
140
|
|
|
163
141
|
async *getStreamedResponse(request: ModelRequest): AsyncIterable<StreamEvent> {
|
|
164
|
-
await beforeModelRequest();
|
|
165
142
|
rememberPreparedModelRequest(request);
|
|
166
143
|
void notifyModelRequestCapture(request);
|
|
167
|
-
|
|
168
|
-
const settlement = modelResponseSettlement(event);
|
|
169
|
-
void settlement?.catch(() => undefined);
|
|
170
|
-
yield event;
|
|
171
|
-
}
|
|
144
|
+
yield* this.inner.getStreamedResponse(request);
|
|
172
145
|
}
|
|
173
146
|
|
|
174
147
|
getRetryAdvice(args: Parameters<NonNullable<Model["getRetryAdvice"]>>[0]) {
|
|
@@ -1,10 +1,6 @@
|
|
|
1
|
-
import OpenAI
|
|
1
|
+
import OpenAI from "openai";
|
|
2
2
|
import type { APIPromise } from "openai/core/api-promise";
|
|
3
3
|
import { types as utilTypes } from "node:util";
|
|
4
|
-
import {
|
|
5
|
-
rethrowModelTransportAdmissionRefusal,
|
|
6
|
-
sdkModelTransportAdmissionFetch,
|
|
7
|
-
} from "./model-preparation-diagnostics";
|
|
8
4
|
|
|
9
5
|
const TARGET_CHUNK_CHARS = 64 * 1024;
|
|
10
6
|
const LARGE_STRING_SOURCE_CHARS = 32 * 1024;
|
|
@@ -103,23 +99,10 @@ export class ReplayableJsonOpenAI extends OpenAI {
|
|
|
103
99
|
private readonly modelRequestPolicy: ModelJsonRequestPolicy | undefined;
|
|
104
100
|
|
|
105
101
|
constructor(options: OpenAIOptions, hooks: ReplayableJsonOpenAIHooks = {}) {
|
|
106
|
-
super(
|
|
107
|
-
...options,
|
|
108
|
-
fetch: sdkModelTransportAdmissionFetch(options?.fetch ?? globalThis.fetch),
|
|
109
|
-
});
|
|
102
|
+
super(options);
|
|
110
103
|
this.modelRequestPolicy = hooks.modelRequestPolicy;
|
|
111
104
|
}
|
|
112
105
|
|
|
113
|
-
protected override makeStatusError(
|
|
114
|
-
status: number,
|
|
115
|
-
error: NonNullable<Parameters<typeof APIError.generate>[1]>,
|
|
116
|
-
message: string | undefined,
|
|
117
|
-
headers: Headers,
|
|
118
|
-
): APIError {
|
|
119
|
-
rethrowModelTransportAdmissionRefusal(headers);
|
|
120
|
-
return super.makeStatusError(status, error, message, headers);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
106
|
override post<Rsp>(path: string, opts?: OpenAIPostOptions): APIPromise<Rsp> {
|
|
124
107
|
if (!isModelRequestPath(path) || opts === undefined) {
|
|
125
108
|
return super.post<Rsp>(path, opts);
|