codex-to-im 1.0.57 → 1.0.58
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/README_EN.md +2 -2
- package/dist/cli.mjs +10 -4
- package/dist/daemon.mjs +52 -13
- package/dist/ui-server.mjs +177 -21
- package/docs/install-windows.md +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -183,7 +183,7 @@ codex-to-im uninstall
|
|
|
183
183
|
- `/new`:在当前正式会话目录下新建线程。
|
|
184
184
|
- `/new <路径或项目名>`:按指定目录新建线程。
|
|
185
185
|
- `/mode <ask|code|plan>`:切换运行模式。
|
|
186
|
-
- `/reasoning <1-5
|
|
186
|
+
- `/reasoning <low|medium|high|xhigh|max|ultra>`:切换思考级别;数字 `1-5` 仍兼容旧映射,`6=max`、`7=ultra` 仅适用于支持这些档位的模型。
|
|
187
187
|
- `/model`:查看当前模型和可选模型。
|
|
188
188
|
- `/model <模型名>`:切换当前 IM 会话模型。
|
|
189
189
|
- `/history`:查看当前线程历史摘要。
|
|
@@ -196,7 +196,7 @@ codex-to-im uninstall
|
|
|
196
196
|
|
|
197
197
|
- 默认工作空间:用于 `/new my-project` 这类相对路径。
|
|
198
198
|
- Codex 文件系统权限:如 `workspace-write`、`danger-full-access`。
|
|
199
|
-
- Codex
|
|
199
|
+
- Codex 思考级别:按当前模型的 Codex catalog 展示,例如 `low`、`medium`、`high`、`xhigh`,部分新模型支持 `max`、`ultra`。
|
|
200
200
|
- 默认模型:从本机可用模型中选择。
|
|
201
201
|
- 反馈使用 markdown:控制 bridge 发到通道里的文本反馈是否走 markdown。
|
|
202
202
|
- 允许局域网访问 Web 控制台:便于手机或局域网设备访问。
|
package/README_EN.md
CHANGED
|
@@ -182,7 +182,7 @@ You can also specify a directory explicitly:
|
|
|
182
182
|
- `/new`: create a new thread under the current formal session directory.
|
|
183
183
|
- `/new <path or project name>`: create a new thread under the specified directory.
|
|
184
184
|
- `/mode <ask|code|plan>`: change the runtime mode.
|
|
185
|
-
- `/reasoning <
|
|
185
|
+
- `/reasoning <low|medium|high|xhigh|max|ultra>`: change the reasoning effort; numeric `1-5` aliases remain compatible, while `6=max` and `7=ultra` only apply to models that support them.
|
|
186
186
|
- `/model`: inspect the current model and available models.
|
|
187
187
|
- `/model <model name>`: change the model for the current IM session.
|
|
188
188
|
- `/history`: inspect the current thread history summary.
|
|
@@ -195,7 +195,7 @@ Common settings in the workbench include:
|
|
|
195
195
|
|
|
196
196
|
- Default workspace root: used for relative paths such as `/new my-project`.
|
|
197
197
|
- Codex filesystem permission: for example `workspace-write` or `danger-full-access`.
|
|
198
|
-
- Codex reasoning effort: `
|
|
198
|
+
- Codex reasoning effort: shown from the selected model's Codex catalog, for example `low`, `medium`, `high`, `xhigh`; some newer models also support `max` and `ultra`.
|
|
199
199
|
- Default model: chosen from the models available on the local machine.
|
|
200
200
|
- Use Markdown for feedback: controls whether bridge text feedback is sent through markdown rendering.
|
|
201
201
|
- Allow LAN access to the Web console: useful when opening the workbench from a phone or another device on the same LAN.
|
package/dist/cli.mjs
CHANGED
|
@@ -17,6 +17,15 @@ import os from "node:os";
|
|
|
17
17
|
import path from "node:path";
|
|
18
18
|
|
|
19
19
|
// src/runtime-options.ts
|
|
20
|
+
var RUNTIME_REASONING_EFFORTS = [
|
|
21
|
+
"minimal",
|
|
22
|
+
"low",
|
|
23
|
+
"medium",
|
|
24
|
+
"high",
|
|
25
|
+
"xhigh",
|
|
26
|
+
"max",
|
|
27
|
+
"ultra"
|
|
28
|
+
];
|
|
20
29
|
function parseSandboxMode(value) {
|
|
21
30
|
if (value === "read-only" || value === "workspace-write" || value === "danger-full-access") {
|
|
22
31
|
return value;
|
|
@@ -24,10 +33,7 @@ function parseSandboxMode(value) {
|
|
|
24
33
|
return void 0;
|
|
25
34
|
}
|
|
26
35
|
function parseReasoningEffort(value) {
|
|
27
|
-
|
|
28
|
-
return value;
|
|
29
|
-
}
|
|
30
|
-
return void 0;
|
|
36
|
+
return RUNTIME_REASONING_EFFORTS.includes(value) ? value : void 0;
|
|
31
37
|
}
|
|
32
38
|
function normalizeChannelId(value) {
|
|
33
39
|
return value.trim().toLowerCase().replace(/[^a-z0-9_-]+/g, "-").replace(/^-+|-+$/g, "") || "channel";
|
package/dist/daemon.mjs
CHANGED
|
@@ -43,10 +43,7 @@ function normalizeSandboxMode(value, fallback = "workspace-write") {
|
|
|
43
43
|
return parseSandboxMode(value) || fallback;
|
|
44
44
|
}
|
|
45
45
|
function parseReasoningEffort(value) {
|
|
46
|
-
|
|
47
|
-
return value;
|
|
48
|
-
}
|
|
49
|
-
return void 0;
|
|
46
|
+
return RUNTIME_REASONING_EFFORTS.includes(value) ? value : void 0;
|
|
50
47
|
}
|
|
51
48
|
function normalizeReasoningEffort(value, fallback = "medium") {
|
|
52
49
|
return parseReasoningEffort(value) || fallback;
|
|
@@ -54,9 +51,19 @@ function normalizeReasoningEffort(value, fallback = "medium") {
|
|
|
54
51
|
function normalizeChannelId(value) {
|
|
55
52
|
return value.trim().toLowerCase().replace(/[^a-z0-9_-]+/g, "-").replace(/^-+|-+$/g, "") || "channel";
|
|
56
53
|
}
|
|
54
|
+
var RUNTIME_REASONING_EFFORTS;
|
|
57
55
|
var init_runtime_options = __esm({
|
|
58
56
|
"src/runtime-options.ts"() {
|
|
59
57
|
"use strict";
|
|
58
|
+
RUNTIME_REASONING_EFFORTS = [
|
|
59
|
+
"minimal",
|
|
60
|
+
"low",
|
|
61
|
+
"medium",
|
|
62
|
+
"high",
|
|
63
|
+
"xhigh",
|
|
64
|
+
"max",
|
|
65
|
+
"ultra"
|
|
66
|
+
];
|
|
60
67
|
}
|
|
61
68
|
});
|
|
62
69
|
|
|
@@ -11708,7 +11715,7 @@ function validateMode(mode) {
|
|
|
11708
11715
|
}
|
|
11709
11716
|
|
|
11710
11717
|
// src/lib/bridge/command-aliases.ts
|
|
11711
|
-
|
|
11718
|
+
init_runtime_options();
|
|
11712
11719
|
var DEFAULT_DESKTOP_THREAD_LIST_LIMIT = 10;
|
|
11713
11720
|
var MAX_DESKTOP_THREAD_LIST_LIMIT = 200;
|
|
11714
11721
|
function parseListIndex(raw) {
|
|
@@ -11758,9 +11765,8 @@ function parseDesktopThreadListArgs(args) {
|
|
|
11758
11765
|
function normalizeReasoningEffort2(raw) {
|
|
11759
11766
|
const token = raw.trim().toLowerCase();
|
|
11760
11767
|
if (!token) return null;
|
|
11761
|
-
|
|
11762
|
-
|
|
11763
|
-
}
|
|
11768
|
+
const named = parseReasoningEffort(token);
|
|
11769
|
+
if (named) return named;
|
|
11764
11770
|
switch (token) {
|
|
11765
11771
|
case "1":
|
|
11766
11772
|
return "minimal";
|
|
@@ -11772,6 +11778,10 @@ function normalizeReasoningEffort2(raw) {
|
|
|
11772
11778
|
return "high";
|
|
11773
11779
|
case "5":
|
|
11774
11780
|
return "xhigh";
|
|
11781
|
+
case "6":
|
|
11782
|
+
return "max";
|
|
11783
|
+
case "7":
|
|
11784
|
+
return "ultra";
|
|
11775
11785
|
default:
|
|
11776
11786
|
return null;
|
|
11777
11787
|
}
|
|
@@ -11809,6 +11819,10 @@ function formatReasoningEffort(reasoning) {
|
|
|
11809
11819
|
return "high (4)";
|
|
11810
11820
|
case "xhigh":
|
|
11811
11821
|
return "xhigh (5)";
|
|
11822
|
+
case "max":
|
|
11823
|
+
return "max (6)";
|
|
11824
|
+
case "ultra":
|
|
11825
|
+
return "ultra (7)";
|
|
11812
11826
|
default:
|
|
11813
11827
|
return reasoning;
|
|
11814
11828
|
}
|
|
@@ -12942,6 +12956,28 @@ function readConfiguredCodexModel(configPath = DEFAULT_CODEX_CONFIG_PATH) {
|
|
|
12942
12956
|
return null;
|
|
12943
12957
|
}
|
|
12944
12958
|
}
|
|
12959
|
+
function parseReasoningLevel(value) {
|
|
12960
|
+
if (typeof value !== "string") return void 0;
|
|
12961
|
+
const trimmed = value.trim();
|
|
12962
|
+
return trimmed ? trimmed : void 0;
|
|
12963
|
+
}
|
|
12964
|
+
function parseSupportedReasoningLevels(value) {
|
|
12965
|
+
if (!Array.isArray(value)) return [];
|
|
12966
|
+
const seen = /* @__PURE__ */ new Set();
|
|
12967
|
+
const levels = [];
|
|
12968
|
+
for (const level of value) {
|
|
12969
|
+
if (!level || typeof level !== "object") continue;
|
|
12970
|
+
const raw = level;
|
|
12971
|
+
const effort = parseReasoningLevel(raw.effort);
|
|
12972
|
+
if (!effort || seen.has(effort)) continue;
|
|
12973
|
+
seen.add(effort);
|
|
12974
|
+
levels.push({
|
|
12975
|
+
effort,
|
|
12976
|
+
description: typeof raw.description === "string" ? raw.description.trim() : ""
|
|
12977
|
+
});
|
|
12978
|
+
}
|
|
12979
|
+
return levels;
|
|
12980
|
+
}
|
|
12945
12981
|
function listCachedCodexModels(cachePath = DEFAULT_CODEX_MODELS_CACHE_PATH) {
|
|
12946
12982
|
try {
|
|
12947
12983
|
const raw = fs6.readFileSync(cachePath, "utf-8");
|
|
@@ -12954,11 +12990,14 @@ function listCachedCodexModels(cachePath = DEFAULT_CODEX_MODELS_CACHE_PATH) {
|
|
|
12954
12990
|
const slug = model.slug.trim();
|
|
12955
12991
|
if (seen.has(slug)) continue;
|
|
12956
12992
|
seen.add(slug);
|
|
12993
|
+
const defaultReasoningLevel = parseReasoningLevel(model.default_reasoning_level);
|
|
12957
12994
|
models.push({
|
|
12958
12995
|
slug,
|
|
12959
12996
|
displayName: typeof model.display_name === "string" && model.display_name.trim() ? model.display_name.trim() : slug,
|
|
12960
12997
|
visibility: typeof model.visibility === "string" && model.visibility.trim() ? model.visibility.trim() : "list",
|
|
12961
|
-
supportedInApi: model.supported_in_api === true
|
|
12998
|
+
supportedInApi: model.supported_in_api === true,
|
|
12999
|
+
supportedReasoningLevels: parseSupportedReasoningLevels(model.supported_reasoning_levels),
|
|
13000
|
+
...defaultReasoningLevel ? { defaultReasoningLevel } : {}
|
|
12962
13001
|
});
|
|
12963
13002
|
}
|
|
12964
13003
|
return models;
|
|
@@ -13276,7 +13315,7 @@ ${attachmentResult.error || "\u672A\u77E5\u9519\u8BEF"}`,
|
|
|
13276
13315
|
|
|
13277
13316
|
// src/lib/bridge/command-dispatch.ts
|
|
13278
13317
|
var MODE_OPTIONS_TEXT = "\u53EF\u9009\uFF1A`code`\uFF08\u76F4\u63A5\u6267\u884C\uFF0C\u9ED8\u8BA4\uFF09 `plan`\uFF08\u5148\u5206\u6790\u518D\u884C\u52A8\uFF09 `ask`\uFF08\u8F7B\u5BF9\u8BDD / \u8349\u7A3F\uFF09";
|
|
13279
|
-
var REASONING_OPTIONS_TEXT = "\u53EF\u9009\uFF1A`1=minimal` `2=low` `3=medium` `4=high` `5=xhigh`";
|
|
13318
|
+
var REASONING_OPTIONS_TEXT = "\u53EF\u9009\uFF1A`low` `medium` `high` `xhigh`\uFF0C\u90E8\u5206\u65B0\u6A21\u578B\u8FD8\u652F\u6301 `max`\u3001`ultra`\uFF1B\u6570\u5B57\u517C\u5BB9\uFF1A`1=minimal` `2=low` `3=medium` `4=high` `5=xhigh` `6=max` `7=ultra`";
|
|
13280
13319
|
function parseForceFlag(args) {
|
|
13281
13320
|
const forcePattern = /(^|\s)--force(?=\s|$)/;
|
|
13282
13321
|
const force = forcePattern.test(args);
|
|
@@ -13596,7 +13635,7 @@ async function handleBridgeCommand(adapter, msg, text2, deps) {
|
|
|
13596
13635
|
response = buildCommandFields(
|
|
13597
13636
|
"\u5F53\u524D\u601D\u8003\u7EA7\u522B",
|
|
13598
13637
|
[["\u7EA7\u522B", formatReasoningEffort(resolveEffectiveReasoningEffort(session))]],
|
|
13599
|
-
[REASONING_OPTIONS_TEXT, "\u53D1\u9001 `/r
|
|
13638
|
+
[REASONING_OPTIONS_TEXT, "\u53D1\u9001 `/r high` \u53EF\u5207\u6362\u3002"],
|
|
13600
13639
|
responseParseMode === "Markdown"
|
|
13601
13640
|
);
|
|
13602
13641
|
break;
|
|
@@ -13605,8 +13644,8 @@ async function handleBridgeCommand(adapter, msg, text2, deps) {
|
|
|
13605
13644
|
if (!reasoning) {
|
|
13606
13645
|
response = buildCommandFields(
|
|
13607
13646
|
"\u601D\u8003\u7EA7\u522B\u7528\u6CD5",
|
|
13608
|
-
[["\u547D\u4EE4", "`/reasoning
|
|
13609
|
-
["\u4E5F\u652F\u6301\
|
|
13647
|
+
[["\u547D\u4EE4", "`/reasoning low|medium|high|xhigh|max|ultra`"]],
|
|
13648
|
+
["\u4E5F\u652F\u6301\u517C\u5BB9\u6570\u5B57\uFF1A`/reasoning 1|2|3|4|5|6|7`", REASONING_OPTIONS_TEXT],
|
|
13610
13649
|
responseParseMode === "Markdown"
|
|
13611
13650
|
);
|
|
13612
13651
|
break;
|
package/dist/ui-server.mjs
CHANGED
|
@@ -4576,6 +4576,15 @@ import os from "node:os";
|
|
|
4576
4576
|
import path from "node:path";
|
|
4577
4577
|
|
|
4578
4578
|
// src/runtime-options.ts
|
|
4579
|
+
var RUNTIME_REASONING_EFFORTS = [
|
|
4580
|
+
"minimal",
|
|
4581
|
+
"low",
|
|
4582
|
+
"medium",
|
|
4583
|
+
"high",
|
|
4584
|
+
"xhigh",
|
|
4585
|
+
"max",
|
|
4586
|
+
"ultra"
|
|
4587
|
+
];
|
|
4579
4588
|
function parseSandboxMode(value) {
|
|
4580
4589
|
if (value === "read-only" || value === "workspace-write" || value === "danger-full-access") {
|
|
4581
4590
|
return value;
|
|
@@ -4583,10 +4592,7 @@ function parseSandboxMode(value) {
|
|
|
4583
4592
|
return void 0;
|
|
4584
4593
|
}
|
|
4585
4594
|
function parseReasoningEffort(value) {
|
|
4586
|
-
|
|
4587
|
-
return value;
|
|
4588
|
-
}
|
|
4589
|
-
return void 0;
|
|
4595
|
+
return RUNTIME_REASONING_EFFORTS.includes(value) ? value : void 0;
|
|
4590
4596
|
}
|
|
4591
4597
|
function normalizeChannelId(value) {
|
|
4592
4598
|
return value.trim().toLowerCase().replace(/[^a-z0-9_-]+/g, "-").replace(/^-+|-+$/g, "") || "channel";
|
|
@@ -7554,6 +7560,28 @@ function readConfiguredCodexModel(configPath = DEFAULT_CODEX_CONFIG_PATH) {
|
|
|
7554
7560
|
return null;
|
|
7555
7561
|
}
|
|
7556
7562
|
}
|
|
7563
|
+
function parseReasoningLevel(value) {
|
|
7564
|
+
if (typeof value !== "string") return void 0;
|
|
7565
|
+
const trimmed = value.trim();
|
|
7566
|
+
return trimmed ? trimmed : void 0;
|
|
7567
|
+
}
|
|
7568
|
+
function parseSupportedReasoningLevels(value) {
|
|
7569
|
+
if (!Array.isArray(value)) return [];
|
|
7570
|
+
const seen = /* @__PURE__ */ new Set();
|
|
7571
|
+
const levels = [];
|
|
7572
|
+
for (const level of value) {
|
|
7573
|
+
if (!level || typeof level !== "object") continue;
|
|
7574
|
+
const raw = level;
|
|
7575
|
+
const effort = parseReasoningLevel(raw.effort);
|
|
7576
|
+
if (!effort || seen.has(effort)) continue;
|
|
7577
|
+
seen.add(effort);
|
|
7578
|
+
levels.push({
|
|
7579
|
+
effort,
|
|
7580
|
+
description: typeof raw.description === "string" ? raw.description.trim() : ""
|
|
7581
|
+
});
|
|
7582
|
+
}
|
|
7583
|
+
return levels;
|
|
7584
|
+
}
|
|
7557
7585
|
function listCachedCodexModels(cachePath = DEFAULT_CODEX_MODELS_CACHE_PATH) {
|
|
7558
7586
|
try {
|
|
7559
7587
|
const raw = fs8.readFileSync(cachePath, "utf-8");
|
|
@@ -7566,11 +7594,14 @@ function listCachedCodexModels(cachePath = DEFAULT_CODEX_MODELS_CACHE_PATH) {
|
|
|
7566
7594
|
const slug = model.slug.trim();
|
|
7567
7595
|
if (seen.has(slug)) continue;
|
|
7568
7596
|
seen.add(slug);
|
|
7597
|
+
const defaultReasoningLevel = parseReasoningLevel(model.default_reasoning_level);
|
|
7569
7598
|
models.push({
|
|
7570
7599
|
slug,
|
|
7571
7600
|
displayName: typeof model.display_name === "string" && model.display_name.trim() ? model.display_name.trim() : slug,
|
|
7572
7601
|
visibility: typeof model.visibility === "string" && model.visibility.trim() ? model.visibility.trim() : "list",
|
|
7573
|
-
supportedInApi: model.supported_in_api === true
|
|
7602
|
+
supportedInApi: model.supported_in_api === true,
|
|
7603
|
+
supportedReasoningLevels: parseSupportedReasoningLevels(model.supported_reasoning_levels),
|
|
7604
|
+
...defaultReasoningLevel ? { defaultReasoningLevel } : {}
|
|
7574
7605
|
});
|
|
7575
7606
|
}
|
|
7576
7607
|
return models;
|
|
@@ -7586,8 +7617,7 @@ function listSelectableCodexModels(cachePath = DEFAULT_CODEX_MODELS_CACHE_PATH)
|
|
|
7586
7617
|
var port = 4781;
|
|
7587
7618
|
var serverStartTime = (/* @__PURE__ */ new Date()).toISOString();
|
|
7588
7619
|
var AUTH_COOKIE_NAME = "cti_ui_auth";
|
|
7589
|
-
var
|
|
7590
|
-
var availableCodexModelSlugs = new Set(availableCodexModels.map((model) => model.slug));
|
|
7620
|
+
var FALLBACK_REASONING_EFFORTS = ["low", "medium", "high", "xhigh"];
|
|
7591
7621
|
var FEISHU_CHAT_LABEL_TTL_MS = 5 * 60 * 1e3;
|
|
7592
7622
|
var feishuChatLabelCache = /* @__PURE__ */ new Map();
|
|
7593
7623
|
var feishuTenantTokenCache = /* @__PURE__ */ new Map();
|
|
@@ -7596,6 +7626,34 @@ function parsePreferredPort() {
|
|
|
7596
7626
|
if (!Number.isInteger(raw) || raw <= 0 || raw > 65535) return 4781;
|
|
7597
7627
|
return raw;
|
|
7598
7628
|
}
|
|
7629
|
+
function getAvailableCodexModels() {
|
|
7630
|
+
return listSelectableCodexModels();
|
|
7631
|
+
}
|
|
7632
|
+
function getAvailableCodexModelSlugs(models = getAvailableCodexModels()) {
|
|
7633
|
+
return new Set(models.map((model) => model.slug));
|
|
7634
|
+
}
|
|
7635
|
+
function getCodexModelMetadata(modelSlug, models = getAvailableCodexModels()) {
|
|
7636
|
+
if (!modelSlug) return null;
|
|
7637
|
+
return models.find((model) => model.slug === modelSlug) || null;
|
|
7638
|
+
}
|
|
7639
|
+
function getSupportedReasoningEfforts(modelSlug, models = getAvailableCodexModels()) {
|
|
7640
|
+
const metadata = getCodexModelMetadata(modelSlug, models);
|
|
7641
|
+
const levels = metadata?.supportedReasoningLevels.map((level) => parseReasoningEffort(level.effort)).filter((level) => Boolean(level)) || [];
|
|
7642
|
+
return levels.length > 0 ? levels : FALLBACK_REASONING_EFFORTS;
|
|
7643
|
+
}
|
|
7644
|
+
function getDefaultReasoningEffort(modelSlug, models = getAvailableCodexModels()) {
|
|
7645
|
+
const metadata = getCodexModelMetadata(modelSlug, models);
|
|
7646
|
+
const supported = getSupportedReasoningEfforts(modelSlug, models);
|
|
7647
|
+
const catalogDefault = parseReasoningEffort(metadata?.defaultReasoningLevel);
|
|
7648
|
+
if (catalogDefault && supported.includes(catalogDefault)) return catalogDefault;
|
|
7649
|
+
if (supported.includes("medium")) return "medium";
|
|
7650
|
+
return supported[0] || "medium";
|
|
7651
|
+
}
|
|
7652
|
+
function isReasoningEffortSupportedByModel(value, modelSlug, models = getAvailableCodexModels()) {
|
|
7653
|
+
const metadata = getCodexModelMetadata(modelSlug, models);
|
|
7654
|
+
if (!metadata || metadata.supportedReasoningLevels.length === 0) return true;
|
|
7655
|
+
return getSupportedReasoningEfforts(modelSlug, models).includes(value);
|
|
7656
|
+
}
|
|
7599
7657
|
async function canListen(portToCheck) {
|
|
7600
7658
|
return await new Promise((resolve) => {
|
|
7601
7659
|
const probe = net.createServer();
|
|
@@ -7796,12 +7854,16 @@ function isRemoteAuthenticated(request, config) {
|
|
|
7796
7854
|
return timingSafeMatch(parseCookies(request).get(AUTH_COOKIE_NAME), config.uiAccessToken);
|
|
7797
7855
|
}
|
|
7798
7856
|
function configToPayload(config) {
|
|
7857
|
+
const availableModels = getAvailableCodexModels();
|
|
7858
|
+
const codexDefaultModel = readConfiguredCodexModel() || "";
|
|
7859
|
+
const effectiveModel = config.defaultModel || codexDefaultModel;
|
|
7799
7860
|
return {
|
|
7800
7861
|
runtime: config.runtime,
|
|
7801
7862
|
defaultWorkspaceRoot: config.defaultWorkspaceRoot || "",
|
|
7802
7863
|
defaultModel: config.defaultModel || "",
|
|
7803
|
-
codexDefaultModel
|
|
7804
|
-
availableModels
|
|
7864
|
+
codexDefaultModel,
|
|
7865
|
+
availableModels,
|
|
7866
|
+
availableReasoningEfforts: getSupportedReasoningEfforts(effectiveModel, availableModels),
|
|
7805
7867
|
defaultMode: config.defaultMode,
|
|
7806
7868
|
historyMessageLimit: config.historyMessageLimit ?? 8,
|
|
7807
7869
|
streamStatusIdleStartSeconds: config.streamStatusIdleStartSeconds ?? 180,
|
|
@@ -7816,7 +7878,17 @@ function configToPayload(config) {
|
|
|
7816
7878
|
}
|
|
7817
7879
|
function mergeConfig(payload) {
|
|
7818
7880
|
const current = loadConfig();
|
|
7881
|
+
const availableCodexModels = getAvailableCodexModels();
|
|
7882
|
+
const availableCodexModelSlugs = getAvailableCodexModelSlugs(availableCodexModels);
|
|
7883
|
+
const codexDefaultModel = readConfiguredCodexModel() || "";
|
|
7819
7884
|
const rawDefaultModel = typeof payload.defaultModel === "string" ? payload.defaultModel.trim() : void 0;
|
|
7885
|
+
const nextDefaultModel = rawDefaultModel === void 0 ? current.defaultModel : rawDefaultModel === "" ? void 0 : availableCodexModelSlugs.has(rawDefaultModel) ? rawDefaultModel : current.defaultModel;
|
|
7886
|
+
const currentEffectiveModel = current.defaultModel || codexDefaultModel;
|
|
7887
|
+
const nextEffectiveModel = nextDefaultModel || codexDefaultModel;
|
|
7888
|
+
const rawReasoningEffort = asString(payload.codexReasoningEffort);
|
|
7889
|
+
const parsedReasoningEffort = parseReasoningEffort(rawReasoningEffort);
|
|
7890
|
+
const preserveCurrentReasoning = parsedReasoningEffort && parsedReasoningEffort === current.codexReasoningEffort && nextEffectiveModel === currentEffectiveModel;
|
|
7891
|
+
const nextReasoningEffort = parsedReasoningEffort && (isReasoningEffortSupportedByModel(parsedReasoningEffort, nextEffectiveModel, availableCodexModels) || preserveCurrentReasoning) ? parsedReasoningEffort : getDefaultReasoningEffort(nextEffectiveModel, availableCodexModels);
|
|
7820
7892
|
const uiAllowLan = payload.uiAllowLan === true;
|
|
7821
7893
|
const requestedUiAccessToken = asString(payload.uiAccessToken);
|
|
7822
7894
|
const uiAccessToken = requestedUiAccessToken || current.uiAccessToken || (uiAllowLan ? generateAccessToken() : void 0);
|
|
@@ -7825,14 +7897,14 @@ function mergeConfig(payload) {
|
|
|
7825
7897
|
runtime: "codex",
|
|
7826
7898
|
enabledChannels: current.enabledChannels,
|
|
7827
7899
|
defaultWorkspaceRoot: asString(payload.defaultWorkspaceRoot),
|
|
7828
|
-
defaultModel:
|
|
7900
|
+
defaultModel: nextDefaultModel,
|
|
7829
7901
|
defaultMode: payload.defaultMode === "plan" || payload.defaultMode === "ask" ? payload.defaultMode : "code",
|
|
7830
7902
|
historyMessageLimit: asPositiveInt(payload.historyMessageLimit) || current.historyMessageLimit || 8,
|
|
7831
7903
|
streamStatusIdleStartSeconds: asPositiveInt(payload.streamStatusIdleStartSeconds) || current.streamStatusIdleStartSeconds || 180,
|
|
7832
7904
|
streamStatusCheckIntervalSeconds: asPositiveInt(payload.streamStatusCheckIntervalSeconds) || current.streamStatusCheckIntervalSeconds || 10,
|
|
7833
7905
|
codexSkipGitRepoCheck: payload.codexSkipGitRepoCheck === true,
|
|
7834
7906
|
codexSandboxMode: payload.codexSandboxMode === "read-only" || payload.codexSandboxMode === "danger-full-access" ? payload.codexSandboxMode : "workspace-write",
|
|
7835
|
-
codexReasoningEffort:
|
|
7907
|
+
codexReasoningEffort: nextReasoningEffort,
|
|
7836
7908
|
uiAllowLan,
|
|
7837
7909
|
uiAccessToken,
|
|
7838
7910
|
channels: current.channels
|
|
@@ -9692,16 +9764,10 @@ function renderHtml() {
|
|
|
9692
9764
|
</label>
|
|
9693
9765
|
<label>
|
|
9694
9766
|
Codex \u601D\u8003\u7EA7\u522B
|
|
9695
|
-
<select id="codexReasoningEffort">
|
|
9696
|
-
<option value="medium">medium</option>
|
|
9697
|
-
<option value="minimal">minimal</option>
|
|
9698
|
-
<option value="low">low</option>
|
|
9699
|
-
<option value="high">high</option>
|
|
9700
|
-
<option value="xhigh">xhigh</option>
|
|
9701
|
-
</select>
|
|
9767
|
+
<select id="codexReasoningEffort"></select>
|
|
9702
9768
|
</label>
|
|
9703
9769
|
</div>
|
|
9704
|
-
<div class="small">\u672A\u7ED1\u5B9A\u7684 IM \u804A\u5929\u4F1A\u5148\u8FDB\u5165\u4E34\u65F6\u8349\u7A3F\u7EBF\u7A0B\uFF08\u7B49\u540C <code>/t 0</code>\uFF09\uFF1B\u201C\u9ED8\u8BA4\u5DE5\u4F5C\u7A7A\u95F4\u201D\u53EA\u7528\u4E8E <code>/new proj1</code> \u8FD9\u7C7B\u76F8\u5BF9\u9879\u76EE\u540D\u3002\u7559\u7A7A\u65F6\u4F1A\u6309\u5F53\u524D\u7CFB\u7EDF\u81EA\u52A8\u56DE\u9000\u5230 <code>~/cx2im</code>\u3002\u9ED8\u8BA4\u6A21\u578B\u5019\u9009\u9879\u6765\u81EA\
|
|
9770
|
+
<div class="small">\u672A\u7ED1\u5B9A\u7684 IM \u804A\u5929\u4F1A\u5148\u8FDB\u5165\u4E34\u65F6\u8349\u7A3F\u7EBF\u7A0B\uFF08\u7B49\u540C <code>/t 0</code>\uFF09\uFF1B\u201C\u9ED8\u8BA4\u5DE5\u4F5C\u7A7A\u95F4\u201D\u53EA\u7528\u4E8E <code>/new proj1</code> \u8FD9\u7C7B\u76F8\u5BF9\u9879\u76EE\u540D\u3002\u7559\u7A7A\u65F6\u4F1A\u6309\u5F53\u524D\u7CFB\u7EDF\u81EA\u52A8\u56DE\u9000\u5230 <code>~/cx2im</code>\u3002\u9ED8\u8BA4\u6A21\u578B\u5019\u9009\u9879\u6765\u81EA\u6309\u9700\u8BFB\u53D6\u7684 Codex \u6A21\u578B\u7F13\u5B58\uFF1A\u9690\u85CF\u6A21\u578B\u4E0D\u4F1A\u5C55\u793A\uFF0CCLI only \u6A21\u578B\u4F1A\u6807\u6210\u201C\u4EC5 IM / CLI\u201D\u3002\u7559\u7A7A\u5219\u7EE7\u7EED\u8DDF\u968F Codex \u5F53\u524D\u9ED8\u8BA4\u6A21\u578B\u3002\u6587\u4EF6\u7CFB\u7EDF\u6743\u9650\u662F\u5168\u5C40\u9ED8\u8BA4\u503C\uFF0C\u601D\u8003\u7EA7\u522B\u53EF\u5728 IM \u4F1A\u8BDD\u91CC\u518D\u5355\u72EC\u8986\u76D6\u3002\u4E0A\u6B21\u54CD\u5E94\u8DDD\u4ECA\u914D\u7F6E\u53EA\u5F71\u54CD\u98DE\u4E66\u957F\u4EFB\u52A1\u5E95\u90E8\u201C\u4E0A\u6B21\u54CD\u5E94\u8DDD\u4ECA X\u201D\u7684\u51FA\u73B0\u65F6\u673A\u3002</div>
|
|
9705
9771
|
<div class="small">\u5F53\u524D\u9700\u8981\u91CD\u542F Bridge \u7684\u914D\u7F6E\uFF1A<code>Runtime</code>\u3001<code>\u5141\u8BB8\u5728\u672A\u4FE1\u4EFB Git \u76EE\u5F55\u8FD0\u884C Codex</code>\u3002\u901A\u9053\u5B9E\u4F8B\u7684\u63A5\u5165\u914D\u7F6E\u8BF7\u5728\u201C\u901A\u9053\u201D\u9875\u7EF4\u62A4\u3002</div>
|
|
9706
9772
|
<div class="checkbox-row">
|
|
9707
9773
|
<label class="checkbox"><input id="codexSkipGitRepoCheck" type="checkbox" checked /> \u5141\u8BB8\u5728\u672A\u4FE1\u4EFB Git \u76EE\u5F55\u8FD0\u884C Codex</label>
|
|
@@ -9776,7 +9842,7 @@ function renderHtml() {
|
|
|
9776
9842
|
<div class="command-list">
|
|
9777
9843
|
<div class="command-list-head"><div>\u547D\u4EE4</div><div>\u539F\u59CB\u547D\u4EE4</div><div>\u8BF4\u660E</div></div>
|
|
9778
9844
|
<div class="command-item"><div class="command-col-command"><code>/m</code></div><div class="command-col-original"><code>/mode</code></div><div class="command-col-desc">\u67E5\u770B\u5F53\u524D\u6A21\u5F0F\uFF1B\u53EF\u9009 <code>code</code>\u3001<code>plan</code>\u3001<code>ask</code>\u3002</div></div>
|
|
9779
|
-
<div class="command-item"><div class="command-col-command"><code>/r</code></div><div class="command-col-original"><code>/reasoning</code></div><div class="command-col-desc">\u67E5\u770B\u5F53\u524D\u601D\u8003\u7EA7\u522B\uFF1B\u53EF\u9009 <code>
|
|
9845
|
+
<div class="command-item"><div class="command-col-command"><code>/r</code></div><div class="command-col-original"><code>/reasoning</code></div><div class="command-col-desc">\u67E5\u770B\u5F53\u524D\u601D\u8003\u7EA7\u522B\uFF1B\u53EF\u9009 <code>low</code>\u3001<code>medium</code>\u3001<code>high</code>\u3001<code>xhigh</code>\uFF0C\u90E8\u5206\u65B0\u6A21\u578B\u8FD8\u652F\u6301 <code>max</code>\u3001<code>ultra</code>\u3002</div></div>
|
|
9780
9846
|
<div class="command-item"><div class="command-col-command"><code>/model [slug|default]</code></div><div class="command-col-original"><code>/model [slug|default]</code></div><div class="command-col-desc">\u67E5\u770B\u6216\u5207\u6362\u5F53\u524D IM \u4F1A\u8BDD\u4F7F\u7528\u7684\u6A21\u578B\uFF1BCLI only \u6A21\u578B\u4F1A\u6807\u6CE8\u201C\u4EC5 IM / CLI\u201D\uFF0C\u5171\u4EAB\u684C\u9762\u7EBF\u7A0B\u53EA\u5141\u8BB8\u67E5\u770B\u4E0D\u5141\u8BB8\u5207\u6362\u3002</div></div>
|
|
9781
9847
|
<div class="command-item"><div class="command-col-command"><code>/t 0</code></div><div class="command-col-original"><code>/thread 0</code></div><div class="command-col-desc">\u5207\u6362\u5230\u5F53\u524D\u804A\u5929\u7684\u4E34\u65F6\u8349\u7A3F\u7EBF\u7A0B\u3002</div></div>
|
|
9782
9848
|
<div class="command-item"><div class="command-col-command"><code>/t 0 reset</code></div><div class="command-col-original"><code>/thread 0 reset</code></div><div class="command-col-desc">\u4E22\u5F03\u5F53\u524D\u8349\u7A3F\u4E0A\u4E0B\u6587\u5E76\u91CD\u5EFA\u4E00\u6761\u65B0\u7684\u8349\u7A3F\u7EBF\u7A0B\u3002</div></div>
|
|
@@ -9930,6 +9996,89 @@ function renderHtml() {
|
|
|
9930
9996
|
select.value = currentValue;
|
|
9931
9997
|
}
|
|
9932
9998
|
|
|
9999
|
+
function findAvailableModel(slug) {
|
|
10000
|
+
if (!slug) return null;
|
|
10001
|
+
return (state.availableModels || []).find((model) => model && model.slug === slug) || null;
|
|
10002
|
+
}
|
|
10003
|
+
|
|
10004
|
+
function fallbackReasoningLevels(config) {
|
|
10005
|
+
const efforts = Array.isArray(config && config.availableReasoningEfforts)
|
|
10006
|
+
? config.availableReasoningEfforts
|
|
10007
|
+
: ['low', 'medium', 'high', 'xhigh'];
|
|
10008
|
+
return efforts
|
|
10009
|
+
.filter((effort) => typeof effort === 'string' && effort)
|
|
10010
|
+
.map((effort) => ({ effort, description: '' }));
|
|
10011
|
+
}
|
|
10012
|
+
|
|
10013
|
+
function reasoningLevelsForModel(config, modelSlug) {
|
|
10014
|
+
const model = findAvailableModel(modelSlug);
|
|
10015
|
+
const levels = model && Array.isArray(model.supportedReasoningLevels)
|
|
10016
|
+
? model.supportedReasoningLevels
|
|
10017
|
+
: [];
|
|
10018
|
+
if (levels.length === 0) return fallbackReasoningLevels(config);
|
|
10019
|
+
return levels
|
|
10020
|
+
.filter((level) => level && typeof level.effort === 'string' && level.effort)
|
|
10021
|
+
.map((level) => ({
|
|
10022
|
+
effort: level.effort,
|
|
10023
|
+
description: typeof level.description === 'string' ? level.description : '',
|
|
10024
|
+
}));
|
|
10025
|
+
}
|
|
10026
|
+
|
|
10027
|
+
function defaultReasoningForModel(config, modelSlug, levels) {
|
|
10028
|
+
const model = findAvailableModel(modelSlug);
|
|
10029
|
+
const catalogDefault = model && typeof model.defaultReasoningLevel === 'string'
|
|
10030
|
+
? model.defaultReasoningLevel
|
|
10031
|
+
: '';
|
|
10032
|
+
if (catalogDefault && levels.some((level) => level.effort === catalogDefault)) {
|
|
10033
|
+
return catalogDefault;
|
|
10034
|
+
}
|
|
10035
|
+
if (levels.some((level) => level.effort === 'medium')) return 'medium';
|
|
10036
|
+
return levels[0] ? levels[0].effort : (config.codexReasoningEffort || 'medium');
|
|
10037
|
+
}
|
|
10038
|
+
|
|
10039
|
+
function selectedDefaultModel(config) {
|
|
10040
|
+
const select = document.getElementById('defaultModel');
|
|
10041
|
+
const selected = select ? select.value : '';
|
|
10042
|
+
return selected || (config && config.codexDefaultModel) || '';
|
|
10043
|
+
}
|
|
10044
|
+
|
|
10045
|
+
function renderReasoningEffortOptions(config, options) {
|
|
10046
|
+
const opts = options || {};
|
|
10047
|
+
const select = document.getElementById('codexReasoningEffort');
|
|
10048
|
+
const modelSlug = selectedDefaultModel(config || {});
|
|
10049
|
+
const levels = reasoningLevelsForModel(config || {}, modelSlug);
|
|
10050
|
+
const currentValue = typeof opts.currentValue === 'string'
|
|
10051
|
+
? opts.currentValue
|
|
10052
|
+
: (config && typeof config.codexReasoningEffort === 'string' ? config.codexReasoningEffort : 'medium');
|
|
10053
|
+
const preserveUnsupported = opts.preserveUnsupported !== false;
|
|
10054
|
+
const modelDefault = defaultReasoningForModel(config || {}, modelSlug, levels);
|
|
10055
|
+
const items = [];
|
|
10056
|
+
const seen = new Set();
|
|
10057
|
+
|
|
10058
|
+
for (const level of levels) {
|
|
10059
|
+
if (seen.has(level.effort)) continue;
|
|
10060
|
+
seen.add(level.effort);
|
|
10061
|
+
const labelParts = [level.effort];
|
|
10062
|
+
if (level.effort === modelDefault) labelParts.push('\u6A21\u578B\u9ED8\u8BA4');
|
|
10063
|
+
if (level.description) labelParts.push(level.description);
|
|
10064
|
+
items.push(
|
|
10065
|
+
'<option value="' + escapeHtml(level.effort) + '">' + escapeHtml(labelParts.join(' \xB7 ')) + '</option>'
|
|
10066
|
+
);
|
|
10067
|
+
}
|
|
10068
|
+
|
|
10069
|
+
if (currentValue && !seen.has(currentValue) && preserveUnsupported) {
|
|
10070
|
+
items.push(
|
|
10071
|
+
'<option value="' + escapeHtml(currentValue) + '">\u5F53\u524D\u914D\u7F6E\u503C\uFF08\u5F53\u524D\u6A21\u578B\u672A\u5217\u51FA\uFF09\uFF1A' + escapeHtml(currentValue) + '</option>'
|
|
10072
|
+
);
|
|
10073
|
+
}
|
|
10074
|
+
|
|
10075
|
+
select.innerHTML = items.join('');
|
|
10076
|
+
select.value = seen.has(currentValue) || preserveUnsupported ? currentValue : modelDefault;
|
|
10077
|
+
if (!select.value && items.length > 0) {
|
|
10078
|
+
select.value = modelDefault;
|
|
10079
|
+
}
|
|
10080
|
+
}
|
|
10081
|
+
|
|
9933
10082
|
function shortId(value) {
|
|
9934
10083
|
if (!value) return '-';
|
|
9935
10084
|
return value.length > 14 ? value.slice(0, 8) + '...' + value.slice(-4) : value;
|
|
@@ -10794,9 +10943,9 @@ function renderHtml() {
|
|
|
10794
10943
|
document.getElementById('streamStatusCheckIntervalSeconds').value = String(config.streamStatusCheckIntervalSeconds || 10);
|
|
10795
10944
|
document.getElementById('defaultWorkspaceRoot').value = config.defaultWorkspaceRoot || '';
|
|
10796
10945
|
renderDefaultModelOptions(config);
|
|
10946
|
+
renderReasoningEffortOptions(config);
|
|
10797
10947
|
document.getElementById('codexSkipGitRepoCheck').checked = config.codexSkipGitRepoCheck === true;
|
|
10798
10948
|
document.getElementById('codexSandboxMode').value = config.codexSandboxMode || 'workspace-write';
|
|
10799
|
-
document.getElementById('codexReasoningEffort').value = config.codexReasoningEffort || 'medium';
|
|
10800
10949
|
document.getElementById('uiAllowLan').checked = config.uiAllowLan === true;
|
|
10801
10950
|
document.getElementById('uiAccessToken').value = config.uiAccessToken || '';
|
|
10802
10951
|
renderUiAccess();
|
|
@@ -11204,6 +11353,13 @@ function renderHtml() {
|
|
|
11204
11353
|
showMessage('configMessage', 'success', '\u5DF2\u751F\u6210\u65B0\u7684\u8BBF\u95EE token\uFF0C\u70B9\u51FB\u201C\u4FDD\u5B58\u914D\u7F6E\u201D\u540E\u751F\u6548\u3002');
|
|
11205
11354
|
});
|
|
11206
11355
|
|
|
11356
|
+
document.getElementById('defaultModel').addEventListener('change', () => {
|
|
11357
|
+
renderReasoningEffortOptions(state.config || {}, {
|
|
11358
|
+
currentValue: document.getElementById('codexReasoningEffort').value,
|
|
11359
|
+
preserveUnsupported: false,
|
|
11360
|
+
});
|
|
11361
|
+
});
|
|
11362
|
+
|
|
11207
11363
|
document.getElementById('saveConfigBtn').addEventListener('click', async () => {
|
|
11208
11364
|
try {
|
|
11209
11365
|
await saveConfig({ messageId: 'configMessage', scope: 'all' });
|
package/docs/install-windows.md
CHANGED
|
@@ -234,7 +234,7 @@ Web 工作台现在只展示自动启动状态;真正的启用和关闭请使
|
|
|
234
234
|
- 另外,当前 `codex` runtime 下正文通常不是逐字流式输出;更常见的效果是先显示 `Thinking / Tool Progress`,正文在回答完成时一次性落到卡片里。
|
|
235
235
|
- IM 里发送 `/history` 可以查看当前会话最近 N 条消息,N 由“基础配置”中的返回条数控制。
|
|
236
236
|
- IM 里发送 `/history` 默认返回整理后的摘要;发送 `/history raw` 才会查看最近 N 条原始消息。
|
|
237
|
-
- IM 里发送 `/reasoning high` 或 `/reasoning 4`
|
|
237
|
+
- IM 里发送 `/reasoning high`、`/reasoning max` 或 `/reasoning 4` 之类命令,可以只对当前会话覆盖思考级别;具体可用档位取决于当前模型。
|
|
238
238
|
- IM 里发送 `/thread 0` 会进入临时草稿线程,适合短讨论或临时想法。
|
|
239
239
|
- “通道”页现在管理的是多个通道实例,而不是固定的一组飞书/微信配置。
|
|
240
240
|
- 每个实例都可以有自己的别名;别名只用于区分不同聊天入口,不会改变 Codex 会话语义。
|
|
@@ -249,7 +249,7 @@ Web 工作台现在只展示自动启动状态;真正的启用和关闭请使
|
|
|
249
249
|
- `/n` / `/new` 在当前正式会话目录下新建线程;这类线程当前只保证在 IM 中可继续,不会自动出现在 Codex Desktop 会话列表中
|
|
250
250
|
- `/n proj1` / `/new proj1` 新建项目会话
|
|
251
251
|
- `/m` / `/mode` 查看或切换模式,可选 `code` / `plan` / `ask`
|
|
252
|
-
- `/r` / `/reasoning`
|
|
252
|
+
- `/r` / `/reasoning` 查看或切换思考级别,支持 `low|medium|high|xhigh|max|ultra`,数字 `1|2|3|4|5|6|7` 作为兼容别名
|
|
253
253
|
- `/his` / `/history` 历史摘要,`/his raw` / `/history raw` 原始记录
|
|
254
254
|
- `/t 0` / `/thread 0` 临时草稿线程
|
|
255
255
|
- 如果 `测试 Codex` 失败,优先检查当前 Windows 用户下是否已经存在可用的 Codex 登录态或 API Key。
|
package/package.json
CHANGED