@agentrouter-top/relay-dsh-plugin-codex 0.2.2-agentrouter.2 → 0.2.2-agentrouter.4
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/AGENTROUTER-FORK.md +1 -1
- package/docs/context-admission.md +27 -0
- package/docs/kernel-policy.md +12 -0
- package/docs/presentation-policy.md +29 -0
- package/docs/transcript-presentation.md +20 -0
- package/lib/client.js +335 -0
- package/lib/client.js.map +1 -1
- package/lib/host-plugin.js +31 -5
- package/lib/host-plugin.js.map +1 -1
- package/package.json +16 -4
- package/presentation-api.d.mts +20 -0
- package/presentation-api.mjs +25 -0
package/AGENTROUTER-FORK.md
CHANGED
|
@@ -2,6 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
Upstream: https://github.com/yangbobo2021/relay-dsh-plugin-codex.git @ 75918b3e06880df25375154321109f364124a544 (MIT).
|
|
4
4
|
|
|
5
|
-
Changes: version 1 generic codexHome/codexEnv launch interface, optional codexBehaviorDefaults=native (see docs/behavior-defaults.md), Codex 0.153.4, and package/build identity. No agent protocol, model picker, effort controls or tool implementation replaced.
|
|
5
|
+
Changes: version 1 generic codexHome/codexEnv launch interface, optional codexBehaviorDefaults=native (see docs/behavior-defaults.md), DSH pre-step context admission (see docs/context-admission.md), Codex 0.153.4, and package/build identity. No agent protocol, model picker, effort controls or tool implementation replaced.
|
|
6
6
|
|
|
7
7
|
Sources and checksummed contributions: https://github.com/Maybank01/agentrouter-dsh-plugins/tree/main/upstream/relay-codex
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Codex context admission
|
|
2
|
+
|
|
3
|
+
Relay uses DSH's public `agent/pre-step` waterfall to align newly recorded
|
|
4
|
+
context messages with the adapter's existing native-input source policy.
|
|
5
|
+
For the effective `relay-codex` preset, it awaits downstream decisions and
|
|
6
|
+
DSH's runtime snapshot, then removes messages from unsupported sources before
|
|
7
|
+
the loop appends them as `user/message` events. DSH's ordinary chat/trajectory
|
|
8
|
+
views therefore no longer label these unforwarded messages as injected.
|
|
9
|
+
|
|
10
|
+
Both admission and native input selection use the same source predicate:
|
|
11
|
+
user input and Relay's existing `source.plugin = "relay"` activation messages
|
|
12
|
+
are supported. Arbitrary DSH system/preset/plugin knowledge is still **not**
|
|
13
|
+
automatically bridged. This fix does not enable more prompt injection, change
|
|
14
|
+
the existing latest-input selection, or classify text heuristically.
|
|
15
|
+
|
|
16
|
+
The hook preserves accepted message identities/attachments, upstream rejection
|
|
17
|
+
decisions, request-series metadata and normal empty-step semantics. It follows
|
|
18
|
+
the effective preset after switching and leaves other agents untouched. It is
|
|
19
|
+
disposed with Relay. No Desktop/private API or extra plugin is needed, and
|
|
20
|
+
AgentRouter's authentication and Codex Home composition do not implement it.
|
|
21
|
+
|
|
22
|
+
This is admission for submission, not a receipt from the model: a later failed
|
|
23
|
+
network request is still a failed request. Historical session events and native
|
|
24
|
+
thread history are not rewritten; old misleading rows can remain in old chats.
|
|
25
|
+
The DSH assembled request header is not a native Codex prompt dump. Native
|
|
26
|
+
permissions, tools, behavior defaults and auxiliary requests keep their existing
|
|
27
|
+
paths. A future knowledge bridge must update this same admission/input contract.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Kernel/model consistency
|
|
2
|
+
|
|
3
|
+
Relay's `relay-codex` preset owns Codex execution. Primary calls from that
|
|
4
|
+
preset must explicitly select the `relay-codex` model route. Selecting another
|
|
5
|
+
route is an error, not permission to silently use the native default. A
|
|
6
|
+
non-Codex session cannot select the Codex route either. Auxiliary calls with
|
|
7
|
+
an explicit purpose retain their existing behavior.
|
|
8
|
+
|
|
9
|
+
This is a route-ownership check, not a GPT/DeepSeek model-name allowlist.
|
|
10
|
+
Native model and effort catalogs, permissions, tools and history stay upstream
|
|
11
|
+
owned. Product-only preset visibility and provider activation belong to the
|
|
12
|
+
deployment's ordinary DSH plugin/profile composition, not this generic adapter.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Optional Codex presentation policy, version 1
|
|
2
|
+
|
|
3
|
+
Relay owns Codex event projection, process/transcript presentation, kernel labels,
|
|
4
|
+
blank-session preset selection and the native model seat guard. Integration
|
|
5
|
+
plugins configure the browser Cordis service `relayCodexPresentation`; they do
|
|
6
|
+
not render Codex components. Types are exported from the `./presentation` subpath.
|
|
7
|
+
|
|
8
|
+
Wait for the service with `ctx.inject(['relayCodexPresentation'], ...)`, check
|
|
9
|
+
`version === 1`, then call `configure({ kernelMode: 'codex-only', hideFeedback:
|
|
10
|
+
true, hideStatistics: true })`. Register the returned disposer with the owner's
|
|
11
|
+
lifecycle. Only one configuration owner is accepted. Dispose before reconfiguring.
|
|
12
|
+
Without configuration Relay retains its upstream coexistence UI.
|
|
13
|
+
|
|
14
|
+
`kernelMode` defaults to `coexist`. `codex-only` enables the Codex label/settings,
|
|
15
|
+
selects Codex only for blank sessions through the public preset transaction, and
|
|
16
|
+
guards the existing DSH model picker. The integrating host remains responsible
|
|
17
|
+
for enforcing its execution policy. Existing sessions/presets are not deleted or
|
|
18
|
+
retargeted. Model catalogs and effort controls remain upstream implementations.
|
|
19
|
+
|
|
20
|
+
`hideFeedback` and `hideStatistics` default to false. They shadow only the native
|
|
21
|
+
feedback/statistics public leaf slots for the rendered Codex session. Other
|
|
22
|
+
kernels and other plugins' entries remain unchanged. Changed/unknown leaf
|
|
23
|
+
contracts are left visible. Unloading or disposing restores native entries.
|
|
24
|
+
|
|
25
|
+
The current DSH turn-tail component has no separate public switch for its copy,
|
|
26
|
+
branch, timing and timestamp actions. Version 1 does **not** hide that parent:
|
|
27
|
+
it also owns deliverable child slots. No private DOM/CSS manipulation, event
|
|
28
|
+
rewriting or DSH component fork is used. Files, errors, approvals and history are
|
|
29
|
+
unaffected. Account credentials and runtime launch options never enter this API.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Codex transcript presentation
|
|
2
|
+
|
|
3
|
+
Relay hides the `permission` command row and the DSH `request/header.system`
|
|
4
|
+
chat row for sessions whose effective preset is `relay-codex`. This includes
|
|
5
|
+
replayed and failed turns; it does not depend on a successful Codex response.
|
|
6
|
+
The primary adapter does not forward DSH's `options.system` to Codex. Native
|
|
7
|
+
Codex instructions, explicitly admitted plugin context, and task-specific
|
|
8
|
+
auxiliary instructions are not affected by this presentation rule.
|
|
9
|
+
|
|
10
|
+
This uses the public `conversation.chat.commandview` permission specialization
|
|
11
|
+
and a leaf shadow of `conversation.chat.node/system-prompt`. Other commands,
|
|
12
|
+
tool approvals, turn errors and the original event log remain unchanged.
|
|
13
|
+
Other or unknown presets retain a permission disclosure built from the public
|
|
14
|
+
DSH primitive and the original system-prompt renderer. DSH does not export its
|
|
15
|
+
generic command card; Relay does not copy it or claim its child slots.
|
|
16
|
+
|
|
17
|
+
No Desktop patch, private DOM mutation, log deletion, authentication change or
|
|
18
|
+
permission-policy change is involved. Removing Relay restores native renderers.
|
|
19
|
+
Changes to the native system-prompt leaf contract fail open. If the primary
|
|
20
|
+
adapter starts forwarding system prompts in future, update this policy with it.
|
package/lib/client.js
CHANGED
|
@@ -36319,6 +36319,339 @@ window.__ModuleLoader__.load({
|
|
|
36319
36319
|
});
|
|
36320
36320
|
}
|
|
36321
36321
|
//#endregion
|
|
36322
|
+
//#region src/client/transcript-presentation.tsx
|
|
36323
|
+
function isCodexSession(state, sessionId) {
|
|
36324
|
+
return sessionPreset(state.byId[sessionId]) === "relay-codex";
|
|
36325
|
+
}
|
|
36326
|
+
/** Only the permission command seat is ours; all other commands stay with DSH. */
|
|
36327
|
+
function PermissionTranscriptRow({ sessionId, useSessions, node, t }) {
|
|
36328
|
+
const codex = useSessions((state) => isCodexSession(state, sessionId));
|
|
36329
|
+
const [open, setOpen] = (0, react.useState)(false);
|
|
36330
|
+
if (codex) return null;
|
|
36331
|
+
const failed = node.outcome?.kind === "error";
|
|
36332
|
+
const summary = node.outcome?.text ?? t(node.outcome === null ? "row.running" : failed ? "row.failed" : "ok");
|
|
36333
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.DisclosureRow, {
|
|
36334
|
+
title: "permission",
|
|
36335
|
+
open,
|
|
36336
|
+
expandable: true,
|
|
36337
|
+
expandOnRowClick: true,
|
|
36338
|
+
icon: failed ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.StateDot, { state: "error" }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconApiOutline14, { size: 14 }),
|
|
36339
|
+
onToggle: () => setOpen((value) => !value),
|
|
36340
|
+
keepContentWhenOpen: true,
|
|
36341
|
+
collapsedContent: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
36342
|
+
style: {
|
|
36343
|
+
marginInlineStart: 8,
|
|
36344
|
+
whiteSpace: "pre-wrap"
|
|
36345
|
+
},
|
|
36346
|
+
children: summary
|
|
36347
|
+
}),
|
|
36348
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", {
|
|
36349
|
+
style: {
|
|
36350
|
+
whiteSpace: "pre-wrap",
|
|
36351
|
+
overflowWrap: "anywhere"
|
|
36352
|
+
},
|
|
36353
|
+
children: [node.args, summary].filter(Boolean).join("\n")
|
|
36354
|
+
})
|
|
36355
|
+
});
|
|
36356
|
+
}
|
|
36357
|
+
/** Presentation only: keep request headers, permission events and approvals intact. */
|
|
36358
|
+
function installTranscriptPresentation(ctx) {
|
|
36359
|
+
ctx.slots.inject("conversation.chat.commandview", () => {
|
|
36360
|
+
const locale = ctx.slots.entries("conversation.chat.node").find((entry) => entry.children?.["conversation.chat.commandview"])?.locale;
|
|
36361
|
+
if (locale !== "chat" && locale !== "conversation") return () => {};
|
|
36362
|
+
return ctx.slots.register({
|
|
36363
|
+
name: "conversation.chat.commandview",
|
|
36364
|
+
key: "permission",
|
|
36365
|
+
priority: -20,
|
|
36366
|
+
locale
|
|
36367
|
+
}, PermissionTranscriptRow);
|
|
36368
|
+
});
|
|
36369
|
+
ctx.slots.inject("conversation.chat.node", () => {
|
|
36370
|
+
let previous;
|
|
36371
|
+
let dispose;
|
|
36372
|
+
const reconcile = () => {
|
|
36373
|
+
const original = ctx.slots.entries("conversation.chat.node").find((entry) => entry.options.key === "system-prompt" && (entry.options.priority ?? 0) >= 0);
|
|
36374
|
+
if (original === previous) return;
|
|
36375
|
+
dispose?.();
|
|
36376
|
+
dispose = void 0;
|
|
36377
|
+
previous = original;
|
|
36378
|
+
if (!original || original.children || original.store || original.inject || original.locale !== "chat" && original.locale !== "conversation") return;
|
|
36379
|
+
const Original = original.component;
|
|
36380
|
+
dispose = ctx.slots.register({
|
|
36381
|
+
name: "conversation.chat.node",
|
|
36382
|
+
key: "system-prompt",
|
|
36383
|
+
priority: -20,
|
|
36384
|
+
locale: original.locale
|
|
36385
|
+
}, function CodexRequestPromptBoundary(props) {
|
|
36386
|
+
return props.useSessions((state) => isCodexSession(state, props.sessionId)) ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Original, { ...props });
|
|
36387
|
+
});
|
|
36388
|
+
};
|
|
36389
|
+
const unsubscribe = ctx.slots.subscribe("conversation.chat.node", reconcile);
|
|
36390
|
+
reconcile();
|
|
36391
|
+
return () => {
|
|
36392
|
+
unsubscribe();
|
|
36393
|
+
dispose?.();
|
|
36394
|
+
};
|
|
36395
|
+
});
|
|
36396
|
+
}
|
|
36397
|
+
//#endregion
|
|
36398
|
+
//#region presentation-api.mjs
|
|
36399
|
+
/** Public, optional browser presentation policy. No account/runtime configuration. */
|
|
36400
|
+
function createPresentationController(install) {
|
|
36401
|
+
let active;
|
|
36402
|
+
return {
|
|
36403
|
+
service: Object.freeze({
|
|
36404
|
+
version: 1,
|
|
36405
|
+
configure(options = {}) {
|
|
36406
|
+
if (active) throw new Error("Relay Codex presentation already has a configuration owner");
|
|
36407
|
+
const { kernelMode = "coexist", hideFeedback = false, hideStatistics = false } = options;
|
|
36408
|
+
if (!["coexist", "codex-only"].includes(kernelMode) || typeof hideFeedback !== "boolean" || typeof hideStatistics !== "boolean" || Object.keys(options).some((key) => ![
|
|
36409
|
+
"kernelMode",
|
|
36410
|
+
"hideFeedback",
|
|
36411
|
+
"hideStatistics"
|
|
36412
|
+
].includes(key))) throw new TypeError("Unsupported Relay Codex presentation policy");
|
|
36413
|
+
const remove = install(Object.freeze({
|
|
36414
|
+
kernelMode,
|
|
36415
|
+
hideFeedback,
|
|
36416
|
+
hideStatistics
|
|
36417
|
+
}));
|
|
36418
|
+
const release = () => {
|
|
36419
|
+
if (active !== release) return;
|
|
36420
|
+
active = void 0;
|
|
36421
|
+
remove();
|
|
36422
|
+
};
|
|
36423
|
+
active = release;
|
|
36424
|
+
return release;
|
|
36425
|
+
}
|
|
36426
|
+
}),
|
|
36427
|
+
dispose: () => active?.()
|
|
36428
|
+
};
|
|
36429
|
+
}
|
|
36430
|
+
//#endregion
|
|
36431
|
+
//#region src/client/kernel-presentation.tsx
|
|
36432
|
+
const CODEX_PRESET = "relay-codex";
|
|
36433
|
+
const UNSUPPORTED_KERNEL = "当前会话不是 Codex 内核。此客户端暂不支持执行,请新建 Codex 会话;原会话和历史记录会保留。";
|
|
36434
|
+
const isCodex = (session) => sessionPreset(session) === CODEX_PRESET;
|
|
36435
|
+
function KernelSection() {
|
|
36436
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
36437
|
+
style: {
|
|
36438
|
+
maxWidth: 600,
|
|
36439
|
+
lineHeight: 1.7
|
|
36440
|
+
},
|
|
36441
|
+
"aria-label": "执行内核",
|
|
36442
|
+
children: [
|
|
36443
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", { children: "执行内核" }),
|
|
36444
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: "当前产品仅支持 Codex App Server。" }),
|
|
36445
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: "模型、思考强度、工具和执行行为由 Codex 适配器提供。原生 DSH / DeepSeek 内核暂不提供执行入口。" }),
|
|
36446
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: "已有预设、自建预设和会话没有被删除;非 Codex 历史仍可查看。通用插件的共存模式不限制宿主的其他内核。" })
|
|
36447
|
+
]
|
|
36448
|
+
});
|
|
36449
|
+
}
|
|
36450
|
+
function KernelLabel({ sessionId, useSessions }) {
|
|
36451
|
+
const codex = useSessions((state) => isCodex(state.byId[sessionId]));
|
|
36452
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
36453
|
+
role: "status",
|
|
36454
|
+
"data-relay-codex-kernel": codex ? "codex" : "unsupported",
|
|
36455
|
+
style: {
|
|
36456
|
+
fontSize: 12,
|
|
36457
|
+
lineHeight: 1.4,
|
|
36458
|
+
maxWidth: "min(65vw, 440px)",
|
|
36459
|
+
whiteSpace: "normal"
|
|
36460
|
+
},
|
|
36461
|
+
title: codex ? "Codex App Server 执行内核" : UNSUPPORTED_KERNEL,
|
|
36462
|
+
children: codex ? "Codex" : "非 Codex 内核 · 当前不支持执行,请新建 Codex 会话"
|
|
36463
|
+
});
|
|
36464
|
+
}
|
|
36465
|
+
function KernelModelSeat({ Upstream, ...props }) {
|
|
36466
|
+
return props.useSessions((state) => isCodex(state.byId[props.sessionId])) ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Upstream, { ...props }) : null;
|
|
36467
|
+
}
|
|
36468
|
+
function installModelSeatGuard(ctx) {
|
|
36469
|
+
const slot = "conversation.input.model";
|
|
36470
|
+
let source, release;
|
|
36471
|
+
const reconcile = () => {
|
|
36472
|
+
const next = ctx.slots.entries(slot).find((entry) => entry.locale === "model" && (entry.options.priority ?? 0) === 0);
|
|
36473
|
+
if (next === source) return;
|
|
36474
|
+
source = next;
|
|
36475
|
+
const previous = release;
|
|
36476
|
+
release = void 0;
|
|
36477
|
+
previous?.();
|
|
36478
|
+
if (!next?.inject || next.children || next.store) return;
|
|
36479
|
+
const original = next.inject;
|
|
36480
|
+
release = ctx.slots.register({
|
|
36481
|
+
name: slot,
|
|
36482
|
+
priority: -50,
|
|
36483
|
+
locale: "model",
|
|
36484
|
+
inject: (sessionId) => {
|
|
36485
|
+
const face = original(sessionId);
|
|
36486
|
+
return {
|
|
36487
|
+
...face,
|
|
36488
|
+
Upstream: next.component,
|
|
36489
|
+
select: (selection) => isCodex(ctx.sessions.list.getSnapshot().byId[sessionId]) ? face.select(selection) : Promise.resolve(false)
|
|
36490
|
+
};
|
|
36491
|
+
}
|
|
36492
|
+
}, KernelModelSeat);
|
|
36493
|
+
};
|
|
36494
|
+
const stop = ctx.slots.subscribe(slot, reconcile);
|
|
36495
|
+
reconcile();
|
|
36496
|
+
return () => {
|
|
36497
|
+
stop();
|
|
36498
|
+
release?.();
|
|
36499
|
+
};
|
|
36500
|
+
}
|
|
36501
|
+
function CodexSeat({ useSessions, selectCodex }) {
|
|
36502
|
+
const session = useSessions((state) => state.current === void 0 ? void 0 : state.byId[state.current]);
|
|
36503
|
+
const id = session?.id;
|
|
36504
|
+
const preset = sessionPreset(session), blank = session?.blank;
|
|
36505
|
+
const [failure, setFailure] = (0, react.useState)();
|
|
36506
|
+
const [attempt, setAttempt] = (0, react.useState)(0);
|
|
36507
|
+
(0, react.useEffect)(() => {
|
|
36508
|
+
if (!id || !blank || preset === CODEX_PRESET) return;
|
|
36509
|
+
let stopped = false;
|
|
36510
|
+
setFailure(void 0);
|
|
36511
|
+
selectCodex(id).then((message) => {
|
|
36512
|
+
if (!stopped && message) setFailure({
|
|
36513
|
+
id,
|
|
36514
|
+
message
|
|
36515
|
+
});
|
|
36516
|
+
}).catch((error) => {
|
|
36517
|
+
if (!stopped) setFailure({
|
|
36518
|
+
id,
|
|
36519
|
+
message: error instanceof Error ? error.message : "无法选择 Codex 预设,请重试。"
|
|
36520
|
+
});
|
|
36521
|
+
});
|
|
36522
|
+
return () => {
|
|
36523
|
+
stopped = true;
|
|
36524
|
+
};
|
|
36525
|
+
}, [
|
|
36526
|
+
id,
|
|
36527
|
+
blank,
|
|
36528
|
+
preset,
|
|
36529
|
+
selectCodex,
|
|
36530
|
+
attempt
|
|
36531
|
+
]);
|
|
36532
|
+
const error = preset !== CODEX_PRESET && failure?.id === id ? failure?.message : void 0;
|
|
36533
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
36534
|
+
style: {
|
|
36535
|
+
fontSize: 13,
|
|
36536
|
+
maxWidth: "60vw"
|
|
36537
|
+
},
|
|
36538
|
+
"aria-label": "Codex 执行内核",
|
|
36539
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
36540
|
+
role: "status",
|
|
36541
|
+
children: !id || preset === CODEX_PRESET ? "Codex" : error ? "Codex 未就绪" : "正在准备 Codex…"
|
|
36542
|
+
}), error && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
36543
|
+
role: "alert",
|
|
36544
|
+
children: [
|
|
36545
|
+
error,
|
|
36546
|
+
" ",
|
|
36547
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
36548
|
+
type: "button",
|
|
36549
|
+
onClick: () => setAttempt((value) => value + 1),
|
|
36550
|
+
children: "重试"
|
|
36551
|
+
})
|
|
36552
|
+
]
|
|
36553
|
+
})]
|
|
36554
|
+
});
|
|
36555
|
+
}
|
|
36556
|
+
/** Opt-in single-kernel product UI. Never retarget or delete existing history. */
|
|
36557
|
+
function installExclusiveKernelPresentation(ctx) {
|
|
36558
|
+
const selectCodex = async (id) => {
|
|
36559
|
+
const session = ctx.sessions.list.getSnapshot().byId[id];
|
|
36560
|
+
if (!session?.blank || isCodex(session)) return;
|
|
36561
|
+
const result = await ctx.remote.agentPresets.select(id, CODEX_PRESET);
|
|
36562
|
+
return result.ok ? void 0 : `${result.error.code}: ${result.error.message}`;
|
|
36563
|
+
};
|
|
36564
|
+
const releases = [];
|
|
36565
|
+
const dispose = () => {
|
|
36566
|
+
while (releases.length) releases.pop()();
|
|
36567
|
+
};
|
|
36568
|
+
try {
|
|
36569
|
+
releases.push(ctx.slots.inject("conversation.input.model", () => installModelSeatGuard(ctx)));
|
|
36570
|
+
releases.push(ctx.slots.inject("conversation.hero.agentPreset", () => ctx.slots.register({
|
|
36571
|
+
name: "conversation.hero.agentPreset",
|
|
36572
|
+
priority: -50,
|
|
36573
|
+
inject: () => ({ selectCodex })
|
|
36574
|
+
}, CodexSeat)));
|
|
36575
|
+
releases.push(ctx.slots.inject("settings.section", () => ctx.slots.register({
|
|
36576
|
+
name: "settings.section",
|
|
36577
|
+
id: "relay-codex-kernels",
|
|
36578
|
+
order: 20,
|
|
36579
|
+
label: () => "执行内核"
|
|
36580
|
+
}, KernelSection)));
|
|
36581
|
+
releases.push(ctx.slots.inject("conversation.session.header.actions", () => ctx.slots.register({
|
|
36582
|
+
name: "conversation.session.header.actions",
|
|
36583
|
+
id: "relay-codex-kernel",
|
|
36584
|
+
order: -10
|
|
36585
|
+
}, KernelLabel)));
|
|
36586
|
+
return dispose;
|
|
36587
|
+
} catch (error) {
|
|
36588
|
+
dispose();
|
|
36589
|
+
throw error;
|
|
36590
|
+
}
|
|
36591
|
+
}
|
|
36592
|
+
//#endregion
|
|
36593
|
+
//#region src/client/presentation.tsx
|
|
36594
|
+
function NativeNonCodexLeaf({ Upstream, ...props }) {
|
|
36595
|
+
return props.useSessions((state) => sessionPreset(state.byId[props.sessionId]) === "relay-codex") ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Upstream, { ...props });
|
|
36596
|
+
}
|
|
36597
|
+
/** Shadow only a known public leaf. Parent ownership and unrelated entries stay intact. */
|
|
36598
|
+
function hideNativeLeaf(ctx, name, id) {
|
|
36599
|
+
return ctx.slots.inject(name, () => {
|
|
36600
|
+
let source, release;
|
|
36601
|
+
const reconcile = () => {
|
|
36602
|
+
const next = ctx.slots.entries(name).find((entry) => entry.options.id === id && (entry.options.priority ?? 0) === 0);
|
|
36603
|
+
if (next === source) return;
|
|
36604
|
+
source = next;
|
|
36605
|
+
const previous = release;
|
|
36606
|
+
release = void 0;
|
|
36607
|
+
previous?.();
|
|
36608
|
+
if (!next || next.children || next.store) return;
|
|
36609
|
+
if (name === "conversation.composer.dock" && next.inject) return;
|
|
36610
|
+
if (next.locale !== void 0 && next.locale !== "chat" && next.locale !== "conversation" && next.locale !== "feedback") return;
|
|
36611
|
+
const originalInject = next.inject;
|
|
36612
|
+
release = ctx.slots.register({
|
|
36613
|
+
name,
|
|
36614
|
+
id,
|
|
36615
|
+
priority: -50,
|
|
36616
|
+
order: next.options.order,
|
|
36617
|
+
locale: next.locale,
|
|
36618
|
+
inject: (sessionId) => ({
|
|
36619
|
+
...originalInject?.(sessionId),
|
|
36620
|
+
Upstream: next.component
|
|
36621
|
+
})
|
|
36622
|
+
}, NativeNonCodexLeaf);
|
|
36623
|
+
};
|
|
36624
|
+
const stop = ctx.slots.subscribe(name, reconcile);
|
|
36625
|
+
reconcile();
|
|
36626
|
+
return () => {
|
|
36627
|
+
stop();
|
|
36628
|
+
release?.();
|
|
36629
|
+
};
|
|
36630
|
+
});
|
|
36631
|
+
}
|
|
36632
|
+
function installPresentationPolicy(ctx, options) {
|
|
36633
|
+
const releases = [];
|
|
36634
|
+
const dispose = () => {
|
|
36635
|
+
while (releases.length) releases.pop()();
|
|
36636
|
+
};
|
|
36637
|
+
try {
|
|
36638
|
+
if (options.kernelMode === "codex-only") releases.push(installExclusiveKernelPresentation(ctx));
|
|
36639
|
+
if (options.hideStatistics) releases.push(hideNativeLeaf(ctx, "conversation.composer.dock", "stats"));
|
|
36640
|
+
if (options.hideFeedback) releases.push(hideNativeLeaf(ctx, "conversation.chat.assistant-actions", "feedback"));
|
|
36641
|
+
return dispose;
|
|
36642
|
+
} catch (error) {
|
|
36643
|
+
dispose();
|
|
36644
|
+
throw error;
|
|
36645
|
+
}
|
|
36646
|
+
}
|
|
36647
|
+
function installPresentationService(ctx) {
|
|
36648
|
+
ctx.inject(["remote", "remote.agentPresets"], (scope) => {
|
|
36649
|
+
const controller = createPresentationController((options) => installPresentationPolicy(scope, options));
|
|
36650
|
+
scope.effect(() => controller.dispose, "relay-codex: optional presentation policy");
|
|
36651
|
+
scope.provide("relayCodexPresentation", controller.service);
|
|
36652
|
+
});
|
|
36653
|
+
}
|
|
36654
|
+
//#endregion
|
|
36322
36655
|
//#region src/client/codex-activity.ts
|
|
36323
36656
|
const codexActivityDefinition = {
|
|
36324
36657
|
kind: "relay-codex-activity",
|
|
@@ -37085,6 +37418,7 @@ window.__ModuleLoader__.load({
|
|
|
37085
37418
|
"connection"
|
|
37086
37419
|
];
|
|
37087
37420
|
function apply(ctx) {
|
|
37421
|
+
installPresentationService(ctx);
|
|
37088
37422
|
const advancedDebug = applyAdvancedDebug(ctx);
|
|
37089
37423
|
applyWorkspaceImport(ctx);
|
|
37090
37424
|
applySessionOpenSync(ctx);
|
|
@@ -37092,6 +37426,7 @@ window.__ModuleLoader__.load({
|
|
|
37092
37426
|
return withConversationRuntime(ctx, (inner) => {
|
|
37093
37427
|
applyActivityPresentation(inner);
|
|
37094
37428
|
installProcessPresentation(inner, advancedDebug);
|
|
37429
|
+
installTranscriptPresentation(inner);
|
|
37095
37430
|
return installModelSelection(inner, "relay-codex", "relay-codex", "relay-claude");
|
|
37096
37431
|
});
|
|
37097
37432
|
}
|