@yansigit/opencodex 2.36.1-dev.20260829.35 → 2.36.1-dev.20260829.39
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/gui/dist/assets/{ApiKeys-Dmc3vk4f.js → ApiKeys-BDLkAqHs.js} +1 -1
- package/gui/dist/assets/{Claude-B8nBn_TE.js → Claude-CbTHl2B0.js} +1 -1
- package/gui/dist/assets/{CodexSet-RKnAl3Rr.js → CodexSet-BWMY8up4.js} +1 -1
- package/gui/dist/assets/{FileIntegrationPage-LBYKB5gf.js → FileIntegrationPage-BFywFnu_.js} +1 -1
- package/gui/dist/assets/{Grok-B6nDl-pq.js → Grok-D7_rD_UK.js} +1 -1
- package/gui/dist/assets/{Integrations-DPcI3mwy.js → Integrations-BM5cNRt8.js} +2 -2
- package/gui/dist/assets/{IntegrationsOverview-BLgOYwUO.js → IntegrationsOverview-DUL8qhww.js} +1 -1
- package/gui/dist/assets/{Logs-BkM5ic5m.js → Logs-BG9kIs3A.js} +1 -1
- package/gui/dist/assets/Models-BJWzO0Kh.js +1 -0
- package/gui/dist/assets/{NumberStepper-Dsiahf_V.js → NumberStepper-K9tocDBx.js} +1 -1
- package/gui/dist/assets/{Providers-DFBGM2BG.js → Providers-BLweq_Hw.js} +1 -1
- package/gui/dist/assets/{RestoreDialog-0YZ3cmhw.js → RestoreDialog-D9aPE4O0.js} +1 -1
- package/gui/dist/assets/{Startup-BRXwp250.js → Startup-CkcpO3Jv.js} +1 -1
- package/gui/dist/assets/{Storage-D0Ve2fj0.js → Storage-YIqUviJJ.js} +1 -1
- package/gui/dist/assets/Subagents-C1AfLEl9.js +1 -0
- package/gui/dist/assets/{Usage-C0T5SUrf.js → Usage-BerHlEN0.js} +1 -1
- package/gui/dist/assets/codex-stale-banner-D4gvSWnO.js +1 -0
- package/gui/dist/assets/{data-surface-D8RXShV2.js → data-surface-BtO3lwam.js} +1 -1
- package/gui/dist/assets/{data-surface-Bfu-W0pf.js → data-surface-DCct07RT.js} +1 -1
- package/gui/dist/assets/{index-WNYAjf83.js → index-Bs27ITj_.js} +3 -3
- package/gui/dist/assets/{model-display-hWp9VTdv.js → model-display-KCeq505s.js} +1 -1
- package/gui/dist/assets/{provider-payload-F7zzYMeI.js → provider-payload-DHs_ctdK.js} +1 -1
- package/gui/dist/assets/{section-tabs-DEASco68.js → section-tabs-BP7gEPK6.js} +1 -1
- package/gui/dist/assets/shared-BdYGV-yJ.js +69 -0
- package/gui/dist/index.html +2 -2
- package/package.json +1 -1
- package/src/codex/app-server-processes.ts +160 -54
- package/src/codex/internal/catalog-writer.ts +3 -0
- package/src/codex/subagent-defaults.ts +114 -0
- package/src/codex/sync.ts +5 -0
- package/src/generated/compatibility-version.json +13 -13
- package/src/server/effort-policy.ts +43 -12
- package/src/server/index.ts +6 -0
- package/src/server/management/agent-settings-routes.ts +2 -0
- package/src/server/request-log.ts +7 -0
- package/src/server/responses/collaboration.ts +20 -4
- package/src/server/responses/core.ts +6 -4
- package/src/server/ws-bridge.ts +5 -0
- package/src/usage/log.ts +9 -0
- package/gui/dist/assets/Models-uh6UTNK5.js +0 -1
- package/gui/dist/assets/Subagents-TaTl5eEL.js +0 -1
- package/gui/dist/assets/shared-p0R307IX.js +0 -69
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
},
|
|
11
11
|
{
|
|
12
12
|
"path": "package.json",
|
|
13
|
-
"sha256": "
|
|
13
|
+
"sha256": "0056c7ad8f06271be7aceee8ea055ad817e2aeeb3ede46fcf21b48e812c1c420"
|
|
14
14
|
},
|
|
15
15
|
{
|
|
16
16
|
"path": "scripts/model-metadata.source.json",
|
|
@@ -730,7 +730,7 @@
|
|
|
730
730
|
},
|
|
731
731
|
{
|
|
732
732
|
"path": "src/codex/app-server-processes.ts",
|
|
733
|
-
"sha256": "
|
|
733
|
+
"sha256": "00e00faf3a032c13db509e4b38c3c7dc9e1a7b532a1b48dc34d7d5de10d80615"
|
|
734
734
|
},
|
|
735
735
|
{
|
|
736
736
|
"path": "src/codex/app-server-restart-service.ts",
|
|
@@ -910,7 +910,7 @@
|
|
|
910
910
|
},
|
|
911
911
|
{
|
|
912
912
|
"path": "src/codex/internal/catalog-writer.ts",
|
|
913
|
-
"sha256": "
|
|
913
|
+
"sha256": "d59f218683c102f5f629ee092a0076deeefb01cc8a20ecde13d197d3ec4a034b"
|
|
914
914
|
},
|
|
915
915
|
{
|
|
916
916
|
"path": "src/codex/internal/history-writer.ts",
|
|
@@ -1098,7 +1098,7 @@
|
|
|
1098
1098
|
},
|
|
1099
1099
|
{
|
|
1100
1100
|
"path": "src/codex/subagent-defaults.ts",
|
|
1101
|
-
"sha256": "
|
|
1101
|
+
"sha256": "08e3efa192430891d9d221d41e5124177c2c03656e3eb832087fdfb778a7703e"
|
|
1102
1102
|
},
|
|
1103
1103
|
{
|
|
1104
1104
|
"path": "src/codex/subagent-model-fallback.ts",
|
|
@@ -1106,7 +1106,7 @@
|
|
|
1106
1106
|
},
|
|
1107
1107
|
{
|
|
1108
1108
|
"path": "src/codex/sync.ts",
|
|
1109
|
-
"sha256": "
|
|
1109
|
+
"sha256": "b2b413f985c058024f5cf0714255ab8b3f74858d159631d22201c237c9aea134"
|
|
1110
1110
|
},
|
|
1111
1111
|
{
|
|
1112
1112
|
"path": "src/codex/transition-state.ts",
|
|
@@ -2662,7 +2662,7 @@
|
|
|
2662
2662
|
},
|
|
2663
2663
|
{
|
|
2664
2664
|
"path": "src/server/effort-policy.ts",
|
|
2665
|
-
"sha256": "
|
|
2665
|
+
"sha256": "d00bd3a42975adec4c62560d57e564da28e4fc7476cc57fea7103f3d61080fc3"
|
|
2666
2666
|
},
|
|
2667
2667
|
{
|
|
2668
2668
|
"path": "src/server/github-copilot-responses-repair.ts",
|
|
@@ -2682,7 +2682,7 @@
|
|
|
2682
2682
|
},
|
|
2683
2683
|
{
|
|
2684
2684
|
"path": "src/server/index.ts",
|
|
2685
|
-
"sha256": "
|
|
2685
|
+
"sha256": "e39a7d1b9812bdf91677f27be4b4ef0a486015170f41e69fb3d8c330970f0aba"
|
|
2686
2686
|
},
|
|
2687
2687
|
{
|
|
2688
2688
|
"path": "src/server/lifecycle.ts",
|
|
@@ -2710,7 +2710,7 @@
|
|
|
2710
2710
|
},
|
|
2711
2711
|
{
|
|
2712
2712
|
"path": "src/server/management/agent-settings-routes.ts",
|
|
2713
|
-
"sha256": "
|
|
2713
|
+
"sha256": "2ba31a9adb7ba798a7a9fdeada3a2430ad2497205ec3671f4c3a5bfbab68f8c5"
|
|
2714
2714
|
},
|
|
2715
2715
|
{
|
|
2716
2716
|
"path": "src/server/management/api-access.ts",
|
|
@@ -2874,7 +2874,7 @@
|
|
|
2874
2874
|
},
|
|
2875
2875
|
{
|
|
2876
2876
|
"path": "src/server/request-log.ts",
|
|
2877
|
-
"sha256": "
|
|
2877
|
+
"sha256": "b05d8d7b84f9cc6bf7cdd003aae7b2ef3791eed9353ee9441f10b87dd34b1621"
|
|
2878
2878
|
},
|
|
2879
2879
|
{
|
|
2880
2880
|
"path": "src/server/responses-custom-tool-repair.ts",
|
|
@@ -2934,7 +2934,7 @@
|
|
|
2934
2934
|
},
|
|
2935
2935
|
{
|
|
2936
2936
|
"path": "src/server/responses/collaboration.ts",
|
|
2937
|
-
"sha256": "
|
|
2937
|
+
"sha256": "c06f21efd00814eb1021b73e4fe16e693a93205768f8f1a55c63e854e657075d"
|
|
2938
2938
|
},
|
|
2939
2939
|
{
|
|
2940
2940
|
"path": "src/server/responses/combo-stream-preflight.ts",
|
|
@@ -2946,7 +2946,7 @@
|
|
|
2946
2946
|
},
|
|
2947
2947
|
{
|
|
2948
2948
|
"path": "src/server/responses/core.ts",
|
|
2949
|
-
"sha256": "
|
|
2949
|
+
"sha256": "ff08c82f4289d3227725566fd7637e8f7b382bb0a1f303846f9c2da9c7889acf"
|
|
2950
2950
|
},
|
|
2951
2951
|
{
|
|
2952
2952
|
"path": "src/server/responses/empty-completion-guard.ts",
|
|
@@ -3034,7 +3034,7 @@
|
|
|
3034
3034
|
},
|
|
3035
3035
|
{
|
|
3036
3036
|
"path": "src/server/ws-bridge.ts",
|
|
3037
|
-
"sha256": "
|
|
3037
|
+
"sha256": "0f7ea03225ddd992fad14dab1dda99a3890a380061f99f0e94fb05efb33e421f"
|
|
3038
3038
|
},
|
|
3039
3039
|
{
|
|
3040
3040
|
"path": "src/service-manager-probe.ts",
|
|
@@ -3250,7 +3250,7 @@
|
|
|
3250
3250
|
},
|
|
3251
3251
|
{
|
|
3252
3252
|
"path": "src/usage/log.ts",
|
|
3253
|
-
"sha256": "
|
|
3253
|
+
"sha256": "a559008076a3d43365d4aa87f7d1b24c939822d915c143f7221cd3b915dc1f96"
|
|
3254
3254
|
},
|
|
3255
3255
|
{
|
|
3256
3256
|
"path": "src/usage/summary.ts",
|
|
@@ -17,6 +17,43 @@ import { modelInList } from "../types";
|
|
|
17
17
|
import { codexEffortRank, configuredReasoningEfforts, isCodexReasoningEffort, modelRecordValue } from "../reasoning-effort";
|
|
18
18
|
import { catalogModelEfforts } from "../codex/catalog";
|
|
19
19
|
|
|
20
|
+
export type AgentKind = "main" | "subagent" | "internal";
|
|
21
|
+
|
|
22
|
+
type MarkerValue = { value: string; valid: boolean } | undefined;
|
|
23
|
+
|
|
24
|
+
function turnMetadataMarker(headers: Headers): MarkerValue {
|
|
25
|
+
const raw = headers.get("x-codex-turn-metadata");
|
|
26
|
+
if (raw === null) return undefined;
|
|
27
|
+
try {
|
|
28
|
+
const parsed = JSON.parse(raw) as unknown;
|
|
29
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return { value: "", valid: false };
|
|
30
|
+
const metadata = parsed as Record<string, unknown>;
|
|
31
|
+
if (!("subagent_kind" in metadata)) return undefined;
|
|
32
|
+
const value = metadata.subagent_kind;
|
|
33
|
+
if (typeof value !== "string" || value.trim().length === 0) return { value: "", valid: false };
|
|
34
|
+
return { value, valid: true };
|
|
35
|
+
} catch {
|
|
36
|
+
return { value: "", valid: false };
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** Classify Responses-origin headers without retaining any marker values. */
|
|
41
|
+
export function classifyAgentKind(headers: Headers, traffic?: "responses"): AgentKind | undefined {
|
|
42
|
+
const headerRaw = headers.get("x-openai-subagent");
|
|
43
|
+
const headerMarker: MarkerValue = headerRaw === null
|
|
44
|
+
? undefined
|
|
45
|
+
: { value: headerRaw, valid: headerRaw.length > 0 };
|
|
46
|
+
const metadataMarker = turnMetadataMarker(headers);
|
|
47
|
+
|
|
48
|
+
// A genuine spawn marker is authoritative even when a sibling marker is stale or malformed.
|
|
49
|
+
if (headerMarker?.value === "collab_spawn" || metadataMarker?.value === "thread_spawn") return "subagent";
|
|
50
|
+
const present = [headerMarker, metadataMarker].filter((marker): marker is NonNullable<MarkerValue> => marker !== undefined);
|
|
51
|
+
if (present.some(marker => !marker.valid)) return undefined;
|
|
52
|
+
if (present.length > 1 && present[0].value !== present[1].value) return undefined;
|
|
53
|
+
if (present.length > 0) return "internal";
|
|
54
|
+
return traffic === "responses" ? "main" : undefined;
|
|
55
|
+
}
|
|
56
|
+
|
|
20
57
|
/**
|
|
21
58
|
* True when the request carries codex-rs's spawned-child markers, matched EXACTLY.
|
|
22
59
|
* Source of truth (openai/codex @ 6138909d): every collab-spawned child turn sends
|
|
@@ -30,16 +67,8 @@ import { catalogModelEfforts } from "../codex/catalog";
|
|
|
30
67
|
* sources — responses_metadata.rs subagent_source). Those are maintenance turns,
|
|
31
68
|
* not spawned children, and must never trip subagentEffortCap.
|
|
32
69
|
*/
|
|
33
|
-
export function isThreadSpawnRequest(headers: Headers): boolean {
|
|
34
|
-
|
|
35
|
-
const turnMeta = headers.get("x-codex-turn-metadata");
|
|
36
|
-
if (!turnMeta) return false;
|
|
37
|
-
try {
|
|
38
|
-
const parsed = JSON.parse(turnMeta) as { subagent_kind?: unknown };
|
|
39
|
-
return parsed.subagent_kind === "thread_spawn";
|
|
40
|
-
} catch {
|
|
41
|
-
return false;
|
|
42
|
-
}
|
|
70
|
+
export function isThreadSpawnRequest(headers: Headers, agentKind?: AgentKind): boolean {
|
|
71
|
+
return (agentKind ?? classifyAgentKind(headers)) === "subagent";
|
|
43
72
|
}
|
|
44
73
|
|
|
45
74
|
/** The effective ceiling for this turn, or undefined when no configured cap applies. */
|
|
@@ -73,10 +102,11 @@ export function effortCapAppliesTo(
|
|
|
73
102
|
headers: Headers,
|
|
74
103
|
config: OcxConfig,
|
|
75
104
|
compaction = false,
|
|
105
|
+
agentKind?: AgentKind,
|
|
76
106
|
): boolean {
|
|
77
107
|
if (compaction) return false;
|
|
78
108
|
if (config.multiAgentMode === "v1") return false;
|
|
79
|
-
return surface === "v2" || isThreadSpawnRequest(headers);
|
|
109
|
+
return surface === "v2" || isThreadSpawnRequest(headers, agentKind);
|
|
80
110
|
}
|
|
81
111
|
|
|
82
112
|
/**
|
|
@@ -185,8 +215,9 @@ export function applyEffortCap(
|
|
|
185
215
|
headers: Headers,
|
|
186
216
|
config: OcxConfig,
|
|
187
217
|
supported?: readonly string[] | undefined,
|
|
218
|
+
agentKind?: AgentKind,
|
|
188
219
|
): { from: string; to: string; subagent: boolean } | null {
|
|
189
|
-
const subagent = isThreadSpawnRequest(headers);
|
|
220
|
+
const subagent = isThreadSpawnRequest(headers, agentKind);
|
|
190
221
|
const cap = effortCapFor(config, subagent);
|
|
191
222
|
if (!cap) return null;
|
|
192
223
|
const resolved = resolveCappedEffort(cap, supported);
|
package/src/server/index.ts
CHANGED
|
@@ -113,6 +113,7 @@ import {
|
|
|
113
113
|
type RequestLogEntry,
|
|
114
114
|
} from "./request-log";
|
|
115
115
|
import { sessionLaneIdFromRequest } from "./request-log-conversation";
|
|
116
|
+
import { classifyAgentKind } from "./effort-policy";
|
|
116
117
|
export {
|
|
117
118
|
addFinalRequestLog,
|
|
118
119
|
filterRequestLogs,
|
|
@@ -972,12 +973,14 @@ export function startServer(port?: number, deps: StartServerDeps = {}): Server<W
|
|
|
972
973
|
// binding. They are the same object for the public listener, but the
|
|
973
974
|
// unauthenticated loopback listener (#1102) is a second Bun.serve, and handing its
|
|
974
975
|
// request to the public server's upgrade would fail or cross sockets.
|
|
976
|
+
const agentKind = classifyAgentKind(req.headers, "responses");
|
|
975
977
|
if (requestServer.upgrade(req, {
|
|
976
978
|
data: buildResponsesWsData(
|
|
977
979
|
selectForwardHeaders(req.headers),
|
|
978
980
|
admission,
|
|
979
981
|
websocketLease,
|
|
980
982
|
sessionLaneIdFromRequest(req.headers),
|
|
983
|
+
agentKind,
|
|
981
984
|
),
|
|
982
985
|
})) return undefined as unknown as Response;
|
|
983
986
|
websocketLease.release();
|
|
@@ -1395,6 +1398,7 @@ export function startServer(port?: number, deps: StartServerDeps = {}): Server<W
|
|
|
1395
1398
|
provider: "unknown",
|
|
1396
1399
|
...admissionFields(admission),
|
|
1397
1400
|
inboundProtocol: "responses",
|
|
1401
|
+
agentKind: classifyAgentKind(req.headers, "responses"),
|
|
1398
1402
|
};
|
|
1399
1403
|
return runAdmittedHttpTurn(req, policy, async turnAdmissionLease => {
|
|
1400
1404
|
let response: Response;
|
|
@@ -1508,6 +1512,7 @@ export function startServer(port?: number, deps: StartServerDeps = {}): Server<W
|
|
|
1508
1512
|
provider: "unknown",
|
|
1509
1513
|
...admissionFields(admission),
|
|
1510
1514
|
inboundProtocol: "responses",
|
|
1515
|
+
agentKind: classifyAgentKind(req.headers, "responses"),
|
|
1511
1516
|
};
|
|
1512
1517
|
if (req.headers.get("x-opencodex-grok") === "1") logCtx.surface = "grok";
|
|
1513
1518
|
let logged = false;
|
|
@@ -1857,6 +1862,7 @@ export function startServer(port?: number, deps: StartServerDeps = {}): Server<W
|
|
|
1857
1862
|
provider: "unknown",
|
|
1858
1863
|
...(wsAdmission ? admissionFields(wsAdmission) : {}),
|
|
1859
1864
|
inboundProtocol: "responses",
|
|
1865
|
+
agentKind: ws.data.agentKind,
|
|
1860
1866
|
};
|
|
1861
1867
|
let logged = false;
|
|
1862
1868
|
const finalizeLog = (
|
|
@@ -797,6 +797,7 @@ export async function handleAgentSettingsRoutes(ctx: ManagementContext): Promise
|
|
|
797
797
|
const disabled = new Set(config.disabledModels ?? []);
|
|
798
798
|
const { listCatalogNativeSlugs } = await import("../../codex/catalog");
|
|
799
799
|
const { CODEX_REASONING_LEVELS } = await import("../../reasoning-effort");
|
|
800
|
+
const { resolveNativeDefaultState } = await import("../../codex/subagent-defaults");
|
|
800
801
|
const nativeModels = listCatalogNativeSlugs()
|
|
801
802
|
.filter(slug => !disabled.has(slug))
|
|
802
803
|
.map(slug => ({ provider: "openai", model: slug, namespaced: slug }));
|
|
@@ -811,6 +812,7 @@ export async function handleAgentSettingsRoutes(ctx: ManagementContext): Promise
|
|
|
811
812
|
model: config.injectionModel ?? null,
|
|
812
813
|
effort: config.injectionEffort ?? null,
|
|
813
814
|
prompt: config.injectionPrompt ?? null,
|
|
815
|
+
nativeDefaultState: await resolveNativeDefaultState(config),
|
|
814
816
|
efforts: CODEX_REASONING_LEVELS.map(l => l.effort),
|
|
815
817
|
available: [...nativeModels, ...routedModels],
|
|
816
818
|
});
|
|
@@ -17,6 +17,7 @@ import type { AdapterTierMetadata } from "../providers/fastwire";
|
|
|
17
17
|
import { redactSecretString, sanitizeLogMetadataString } from "../lib/redact";
|
|
18
18
|
import {
|
|
19
19
|
appendUsageEntry,
|
|
20
|
+
isKnownAgentKind,
|
|
20
21
|
isKnownAdmissionKind,
|
|
21
22
|
isKnownInboundProtocol,
|
|
22
23
|
isKnownUsageSurface,
|
|
@@ -31,6 +32,7 @@ import {
|
|
|
31
32
|
type PersistedUsageEntry,
|
|
32
33
|
type UsageStatus,
|
|
33
34
|
} from "../usage/log";
|
|
35
|
+
import type { AgentKind } from "./effort-policy";
|
|
34
36
|
import {
|
|
35
37
|
appendUsageDebug,
|
|
36
38
|
isUsageDebugEnabled,
|
|
@@ -63,6 +65,7 @@ export interface RequestLogContext {
|
|
|
63
65
|
* product: widening that enum would merge Responses and Chat Completions,
|
|
64
66
|
* since both leave it undefined. */
|
|
65
67
|
inboundProtocol?: "responses" | "chat" | "messages";
|
|
68
|
+
agentKind?: AgentKind;
|
|
66
69
|
/** Stable non-PII Codex Pool account identity for durable usage attribution. */
|
|
67
70
|
accountLogLabel?: string;
|
|
68
71
|
requestedModel?: string;
|
|
@@ -143,6 +146,7 @@ export interface RequestLogEntry {
|
|
|
143
146
|
* product: widening that enum would merge Responses and Chat Completions,
|
|
144
147
|
* since both leave it undefined. */
|
|
145
148
|
inboundProtocol?: "responses" | "chat" | "messages";
|
|
149
|
+
agentKind?: AgentKind;
|
|
146
150
|
accountLogLabel?: string;
|
|
147
151
|
/** Best-effort chat/session correlation for Logs grouping (#330). */
|
|
148
152
|
conversationId?: string;
|
|
@@ -256,6 +260,7 @@ export function requestLogEntryFromPersistedUsage(entry: PersistedUsageEntry): R
|
|
|
256
260
|
timestamp: entry.timestamp,
|
|
257
261
|
model: entry.model,
|
|
258
262
|
provider: entry.provider,
|
|
263
|
+
...(isKnownAgentKind(entry.agentKind) ? { agentKind: entry.agentKind } : {}),
|
|
259
264
|
...(entry.firstOutputMs !== undefined ? { firstOutputMs: entry.firstOutputMs } : {}),
|
|
260
265
|
...(isKnownUsageSurface(entry.surface) ? { surface: entry.surface } : {}),
|
|
261
266
|
...(entry.conversationId ? { conversationId: entry.conversationId } : {}),
|
|
@@ -378,6 +383,7 @@ export function addRequestLog(entry: RequestLogEntry) {
|
|
|
378
383
|
...(entry.apiKeyId ? { apiKeyId: entry.apiKeyId } : {}),
|
|
379
384
|
...(isKnownAdmissionKind(entry.admissionKind) ? { admissionKind: entry.admissionKind } : {}),
|
|
380
385
|
...(isKnownInboundProtocol(entry.inboundProtocol) ? { inboundProtocol: entry.inboundProtocol } : {}),
|
|
386
|
+
...(isKnownAgentKind(entry.agentKind) ? { agentKind: entry.agentKind } : {}),
|
|
381
387
|
...(isPersistableAccountLogLabel(entry.accountLogLabel)
|
|
382
388
|
? { accountLogLabel: entry.accountLogLabel }
|
|
383
389
|
: {}),
|
|
@@ -970,6 +976,7 @@ export function addFinalRequestLog(
|
|
|
970
976
|
...(logCtx.apiKeyId ? { apiKeyId: logCtx.apiKeyId } : {}),
|
|
971
977
|
...(logCtx.admissionKind ? { admissionKind: logCtx.admissionKind } : {}),
|
|
972
978
|
...(logCtx.inboundProtocol ? { inboundProtocol: logCtx.inboundProtocol } : {}),
|
|
979
|
+
...(logCtx.agentKind ? { agentKind: logCtx.agentKind } : {}),
|
|
973
980
|
...(isPersistableAccountLogLabel(logCtx.accountLogLabel)
|
|
974
981
|
? { accountLogLabel: logCtx.accountLogLabel }
|
|
975
982
|
: {}),
|
|
@@ -77,6 +77,7 @@ import { registerTurn, trackStreamLifetime, unregisterTurn } from "../lifecycle"
|
|
|
77
77
|
import { redactSecretString } from "../../lib/redact";
|
|
78
78
|
import { readBoundedResponseBody } from "../../lib/bounded-body";
|
|
79
79
|
import { supportedLadderFor } from "../effort-policy";
|
|
80
|
+
import { resolveNativeDefaultState, type NativeDefaultState } from "../../codex/subagent-defaults";
|
|
80
81
|
import {
|
|
81
82
|
beginRequestAttempt,
|
|
82
83
|
catalogModelSupportsServiceTier,
|
|
@@ -216,11 +217,18 @@ export interface MultiAgentGuidanceOptions {
|
|
|
216
217
|
subagentModelFallback?: string[];
|
|
217
218
|
injectionPrompt?: string;
|
|
218
219
|
subagentRoles?: OcxSubagentRole[];
|
|
220
|
+
nativeDefaultState?: NativeDefaultState;
|
|
221
|
+
syncCodexSubagentDefaults?: boolean;
|
|
219
222
|
}
|
|
220
223
|
|
|
221
224
|
|
|
222
225
|
|
|
223
226
|
export interface MultiAgentGuidanceDeps {
|
|
227
|
+
resolveNativeDefaultState?: (config: {
|
|
228
|
+
injectionModel?: string;
|
|
229
|
+
injectionEffort?: string;
|
|
230
|
+
syncCodexSubagentDefaults?: boolean;
|
|
231
|
+
}) => NativeDefaultState | Promise<NativeDefaultState>;
|
|
224
232
|
resolveEffectiveSubagentRoster?: (
|
|
225
233
|
configuredModels: readonly string[],
|
|
226
234
|
surface: SpawnAgentSurface,
|
|
@@ -308,6 +316,8 @@ export async function multiAgentGuidanceText(
|
|
|
308
316
|
subagentModelFallback,
|
|
309
317
|
injectionPrompt,
|
|
310
318
|
subagentRoles,
|
|
319
|
+
nativeDefaultState: configuredNativeDefaultState,
|
|
320
|
+
syncCodexSubagentDefaults,
|
|
311
321
|
} = options;
|
|
312
322
|
const activeAccountNamespace = codexAccountNamespace?.length
|
|
313
323
|
? codexAccountNamespace
|
|
@@ -340,6 +350,10 @@ export async function multiAgentGuidanceText(
|
|
|
340
350
|
if (catalogState.state === "stale" || catalogState.state === "unknown") {
|
|
341
351
|
return null;
|
|
342
352
|
}
|
|
353
|
+
const nativeDefaultState = configuredNativeDefaultState
|
|
354
|
+
?? await (deps.resolveNativeDefaultState ?? resolveNativeDefaultState)({
|
|
355
|
+
injectionModel, injectionEffort, syncCodexSubagentDefaults,
|
|
356
|
+
});
|
|
343
357
|
// codex-rs supplies the Proactive text on v2; the proxy only adds model-designation
|
|
344
358
|
// guidance, and only when there is something concrete to designate: a configured
|
|
345
359
|
// injectionModel and/or a roster entry that resolves in the injected catalog.
|
|
@@ -417,7 +431,7 @@ export async function multiAgentGuidanceText(
|
|
|
417
431
|
// fallback only for explicit routed/account-qualified ids.
|
|
418
432
|
const promptModel = preferred?.model
|
|
419
433
|
?? (injectionModel?.includes("/") ? injectionModel : undefined);
|
|
420
|
-
return `<multi_agent_mode>${applyInjectionPlaceholders(injectionPrompt, promptModel, injectionEffort, roster, fallbackGuidance, customRolesText)}</multi_agent_mode>`;
|
|
434
|
+
return `<multi_agent_mode>${applyInjectionPlaceholders(injectionPrompt, promptModel, injectionEffort, roster, fallbackGuidance, customRolesText, nativeDefaultState)}</multi_agent_mode>`;
|
|
421
435
|
}
|
|
422
436
|
if (!preferred && roster === "" && fallbackGuidance === "" && customRolesText === "") return null;
|
|
423
437
|
const preamble = "When the active spawn_agent tool supports optional \"model\" or \"reasoning_effort\" overrides, "
|
|
@@ -425,13 +439,14 @@ export async function multiAgentGuidanceText(
|
|
|
425
439
|
+ "When setting either override, set fork_turns to \"none\" "
|
|
426
440
|
+ "(or a positive turn count such as \"3\"; full-history forks reject overrides) "
|
|
427
441
|
+ "and make the task message self-contained. "
|
|
428
|
-
+ "When specifying model overrides,
|
|
442
|
+
+ "When specifying model overrides, preserve any caller-provided agent_type; do not replace it with \"worker\". "
|
|
429
443
|
+ "Subagent exec runs in a pure V8 isolate without require('fs'); "
|
|
430
444
|
+ "escape nested template literals in tools.apply_patch to prevent JavaScript syntax errors (e.g., write \\` and \\\${var}).";
|
|
431
445
|
let preferredText = "";
|
|
432
446
|
if (preferred) {
|
|
433
447
|
preferredText = ` Preferred sub-agent: model "${preferred.model}"`
|
|
434
448
|
+ (injectionEffort ? `, reasoning_effort "${injectionEffort}"` : "")
|
|
449
|
+
+ `; nativeDefaultState: ${nativeDefaultState}.`
|
|
435
450
|
+ " — use it unless the user names another.";
|
|
436
451
|
}
|
|
437
452
|
const specialist = (catalog: string): string =>
|
|
@@ -465,13 +480,14 @@ export async function multiAgentGuidanceText(
|
|
|
465
480
|
|
|
466
481
|
export const V2_GUIDANCE_CHAR_BUDGET = 1200;
|
|
467
482
|
|
|
468
|
-
export function applyInjectionPlaceholders(prompt: string, model?: string, effort?: string, roster?: string, fallback?: string, roles?: string): string {
|
|
483
|
+
export function applyInjectionPlaceholders(prompt: string, model?: string, effort?: string, roster?: string, fallback?: string, roles?: string, nativeDefaultState?: NativeDefaultState): string {
|
|
469
484
|
return prompt
|
|
470
485
|
.replaceAll("{{model}}", model ?? "")
|
|
471
486
|
.replaceAll("{{effort}}", effort ?? "")
|
|
472
487
|
.replaceAll("{{roster}}", roster ?? "")
|
|
473
488
|
.replaceAll("{{fallback}}", fallback ?? "")
|
|
474
|
-
.replaceAll("{{roles}}", roles ?? "")
|
|
489
|
+
.replaceAll("{{roles}}", roles ?? "")
|
|
490
|
+
.replaceAll("{{nativeDefaultState}}", nativeDefaultState ?? "");
|
|
475
491
|
}
|
|
476
492
|
|
|
477
493
|
|
|
@@ -1879,6 +1879,7 @@ async function applyFinalRouteRequestNormalization(args: {
|
|
|
1879
1879
|
subagentModelFallback: config.subagentModelFallback,
|
|
1880
1880
|
injectionPrompt: config.injectionPrompt,
|
|
1881
1881
|
subagentRoles: config.subagentRoles,
|
|
1882
|
+
syncCodexSubagentDefaults: config.syncCodexSubagentDefaults === true,
|
|
1882
1883
|
});
|
|
1883
1884
|
if (guidance) {
|
|
1884
1885
|
injectDeveloperMessage(parsed, guidance);
|
|
@@ -1893,8 +1894,8 @@ async function applyFinalRouteRequestNormalization(args: {
|
|
|
1893
1894
|
{
|
|
1894
1895
|
const { applyEffortCap, effortCapAppliesTo, supportedLadderFor } = await import("../effort-policy");
|
|
1895
1896
|
const surface = collabSurface(parsed);
|
|
1896
|
-
if (effortCapAppliesTo(surface, req.headers, config, parsed._compactionRequest === true)) {
|
|
1897
|
-
const capped = applyEffortCap(parsed, req.headers, config, supportedLadderFor(route));
|
|
1897
|
+
if (effortCapAppliesTo(surface, req.headers, config, parsed._compactionRequest === true, logCtx.agentKind)) {
|
|
1898
|
+
const capped = applyEffortCap(parsed, req.headers, config, supportedLadderFor(route), logCtx.agentKind);
|
|
1898
1899
|
if (capped) {
|
|
1899
1900
|
logCtx.requestedEffort = `${capped.from}->${capped.to}`;
|
|
1900
1901
|
if (isInjectionDebugEnabled()) {
|
|
@@ -2057,6 +2058,7 @@ export async function handleComboResponses(
|
|
|
2057
2058
|
const childLog: RequestLogContext = {
|
|
2058
2059
|
model: pick.target.model,
|
|
2059
2060
|
provider: pick.target.provider,
|
|
2061
|
+
...(logCtx.agentKind ? { agentKind: logCtx.agentKind } : {}),
|
|
2060
2062
|
...(logCtx.conversationId ? { conversationId: logCtx.conversationId } : {}),
|
|
2061
2063
|
...(logCtx.surface ? { surface: logCtx.surface } : {}),
|
|
2062
2064
|
};
|
|
@@ -2613,7 +2615,7 @@ async function handleResponsesInner(
|
|
|
2613
2615
|
&& isMultiAgentV2Enabled()
|
|
2614
2616
|
&& isCanonicalOpenAiForwardProvider(route.provider)
|
|
2615
2617
|
&& collabSurface(parsed) === "v2"
|
|
2616
|
-
&& !isThreadSpawnRequest(req.headers)
|
|
2618
|
+
&& !isThreadSpawnRequest(req.headers, logCtx.agentKind)
|
|
2617
2619
|
&& !req.headers.has("x-openai-subagent")
|
|
2618
2620
|
&& !options.comboAttempt
|
|
2619
2621
|
&& parsed._compactionRequest !== true
|
|
@@ -2632,7 +2634,7 @@ async function handleResponsesInner(
|
|
|
2632
2634
|
// Exact account selectors are isolated from Pool-wide quota work. A canonical replay miss must
|
|
2633
2635
|
// also fail closed without polling quota upstream. Cached fallback state can still select a
|
|
2634
2636
|
// provider with native continuation support below.
|
|
2635
|
-
const threadSpawn = isThreadSpawnRequest(req.headers);
|
|
2637
|
+
const threadSpawn = isThreadSpawnRequest(req.headers, logCtx.agentKind);
|
|
2636
2638
|
const initialSubagentFallbackChain = threadSpawn && !options.comboAttempt
|
|
2637
2639
|
? resolveSubagentFallbackChain(parsed, config)
|
|
2638
2640
|
: null;
|
package/src/server/ws-bridge.ts
CHANGED
|
@@ -7,6 +7,7 @@ import type { ResponsesTerminalStatus } from "../bridge";
|
|
|
7
7
|
import type { DataPlaneAdmission } from "./auth-cors";
|
|
8
8
|
import type { AdmissionLease, AdmissionReservation } from "../lib/admission";
|
|
9
9
|
import { BoundedSseFrameBuffer } from "./sse-frame-buffer";
|
|
10
|
+
import { classifyAgentKind, type AgentKind } from "./effort-policy";
|
|
10
11
|
|
|
11
12
|
const OPEN = 1;
|
|
12
13
|
type ResponsesTerminalReporter = (status: ResponsesTerminalStatus) => void;
|
|
@@ -23,6 +24,7 @@ const SAFE_RESPONSE_HEADER_EXACT = new Set([
|
|
|
23
24
|
|
|
24
25
|
export interface WsData {
|
|
25
26
|
headers?: Headers; // base inbound forward headers only; per-turn auth refresh injects current pool tokens
|
|
27
|
+
agentKind?: AgentKind;
|
|
26
28
|
/**
|
|
27
29
|
* Resolved once at the handshake. Auth is handshake-time only on this path, so
|
|
28
30
|
* the per-frame log contexts have no request headers left to re-resolve from.
|
|
@@ -67,11 +69,14 @@ export function buildResponsesWsData(
|
|
|
67
69
|
admission: DataPlaneAdmission,
|
|
68
70
|
admissionLease?: AdmissionReservation<ServerWebSocket<WsData>>,
|
|
69
71
|
sessionLaneId?: string,
|
|
72
|
+
agentKind?: AgentKind,
|
|
70
73
|
): WsData {
|
|
71
74
|
// Auth is handshake-time only on this path: the per-frame contexts have no
|
|
72
75
|
// request headers left to re-resolve from, so the decision rides along here.
|
|
76
|
+
const resolvedAgentKind = arguments.length >= 5 ? agentKind : classifyAgentKind(headers, "responses");
|
|
73
77
|
return {
|
|
74
78
|
headers,
|
|
79
|
+
agentKind: resolvedAgentKind,
|
|
75
80
|
admission,
|
|
76
81
|
...(admissionLease ? { admissionLease } : {}),
|
|
77
82
|
...(sessionLaneId ? { sessionLaneId } : {}),
|
package/src/usage/log.ts
CHANGED
|
@@ -9,6 +9,7 @@ import { usageDisplayTotalTokens } from "./totals";
|
|
|
9
9
|
import type { AttemptTierOutcome, OcxUsage } from "../types";
|
|
10
10
|
import { normalizeRouteDecisionTrace, type RouteDecisionTraceV1 } from "../routing/trace";
|
|
11
11
|
import { CODEX_ACCOUNT_LOG_LABEL_RE } from "../codex/account-label";
|
|
12
|
+
import type { AgentKind } from "../server/effort-policy";
|
|
12
13
|
|
|
13
14
|
export type UsageStatus = "reported" | "unreported" | "unsupported" | "estimated";
|
|
14
15
|
export type CodexUsageAccountLogLabel = "main" | `p${string}`;
|
|
@@ -80,6 +81,8 @@ export interface PersistedUsageAttempt {
|
|
|
80
81
|
}
|
|
81
82
|
|
|
82
83
|
export interface PersistedUsageEntry {
|
|
84
|
+
/** Responses request origin; absent for unrelated traffic and old rows. */
|
|
85
|
+
agentKind?: AgentKind;
|
|
83
86
|
requestedAlias?: string;
|
|
84
87
|
requestId: string;
|
|
85
88
|
timestamp: number;
|
|
@@ -163,6 +166,11 @@ const KNOWN_ADMISSION_KINDS = new Set<NonNullable<PersistedUsageEntry["admission
|
|
|
163
166
|
const KNOWN_INBOUND_PROTOCOLS = new Set<NonNullable<PersistedUsageEntry["inboundProtocol"]>>([
|
|
164
167
|
"responses", "chat", "messages",
|
|
165
168
|
]);
|
|
169
|
+
const KNOWN_AGENT_KINDS = new Set<AgentKind>(["main", "subagent", "internal"]);
|
|
170
|
+
|
|
171
|
+
export function isKnownAgentKind(value: unknown): value is AgentKind {
|
|
172
|
+
return typeof value === "string" && KNOWN_AGENT_KINDS.has(value as AgentKind);
|
|
173
|
+
}
|
|
166
174
|
|
|
167
175
|
/** Same closed-set discipline as `isKnownUsageSurface`: an old or corrupted row
|
|
168
176
|
* carrying an unexpected value drops the field instead of poisoning the enum. */
|
|
@@ -454,6 +462,7 @@ function normalizeUsageEntry(entry: PersistedUsageEntry): PersistedUsageEntry {
|
|
|
454
462
|
timestamp: entry.timestamp,
|
|
455
463
|
provider: entry.provider,
|
|
456
464
|
model: entry.model,
|
|
465
|
+
...(isKnownAgentKind(entry.agentKind) ? { agentKind: entry.agentKind } : {}),
|
|
457
466
|
...(isKnownUsageSurface(entry.surface) ? { surface: entry.surface } : {}),
|
|
458
467
|
...(typeof entry.apiKeyId === "string" && entry.apiKeyId.trim()
|
|
459
468
|
// Deliberately NOT capped. `capMetadataString` protects free-form metadata
|