@praeviso/code-env-switch 0.1.8 → 0.1.10
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 +20 -10
- package/README_zh.md +19 -10
- package/bin/cli/help.js +1 -1
- package/bin/codex/config.js +273 -0
- package/bin/commands/launch.js +6 -21
- package/bin/commands/list.js +10 -1
- package/bin/commands/unset.js +4 -3
- package/bin/commands/use.js +11 -12
- package/bin/index.js +19 -1
- package/bin/profile/display.js +15 -1
- package/bin/statusline/codex.js +159 -210
- package/bin/statusline/index.js +10 -2
- package/bin/usage/index.js +123 -21
- package/code-env.example.json +3 -6
- package/docs/usage.md +3 -0
- package/docs/usage_zh.md +2 -0
- package/package.json +5 -5
- package/src/cli/help.ts +1 -1
- package/src/codex/config.ts +309 -0
- package/src/commands/launch.ts +10 -21
- package/src/commands/list.ts +11 -1
- package/src/commands/unset.ts +4 -2
- package/src/commands/use.ts +12 -12
- package/src/index.ts +30 -1
- package/src/profile/display.ts +17 -1
- package/src/statusline/codex.ts +196 -217
- package/src/statusline/index.ts +17 -2
- package/src/types.ts +1 -4
- package/src/usage/index.ts +135 -21
package/bin/statusline/codex.js
CHANGED
|
@@ -2,24 +2,12 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ensureCodexStatuslineConfig = ensureCodexStatuslineConfig;
|
|
4
4
|
/**
|
|
5
|
-
* Codex CLI status line integration
|
|
5
|
+
* Codex CLI status line integration (official schema)
|
|
6
6
|
*/
|
|
7
7
|
const fs = require("fs");
|
|
8
|
-
const os = require("os");
|
|
9
8
|
const path = require("path");
|
|
10
|
-
const
|
|
9
|
+
const config_1 = require("../codex/config");
|
|
11
10
|
const ui_1 = require("../ui");
|
|
12
|
-
const DEFAULT_CODEX_CONFIG_PATH = path.join(os.homedir(), ".codex", "config.toml");
|
|
13
|
-
const DEFAULT_STATUSLINE_COMMAND = [
|
|
14
|
-
"codenv",
|
|
15
|
-
"statusline",
|
|
16
|
-
"--type",
|
|
17
|
-
"codex",
|
|
18
|
-
"--sync-usage",
|
|
19
|
-
];
|
|
20
|
-
const DEFAULT_SHOW_HINTS = false;
|
|
21
|
-
const DEFAULT_UPDATE_INTERVAL_MS = 300;
|
|
22
|
-
const DEFAULT_TIMEOUT_MS = 1000;
|
|
23
11
|
function parseBooleanEnv(value) {
|
|
24
12
|
if (value === undefined)
|
|
25
13
|
return null;
|
|
@@ -30,19 +18,23 @@ function parseBooleanEnv(value) {
|
|
|
30
18
|
return false;
|
|
31
19
|
return null;
|
|
32
20
|
}
|
|
33
|
-
function
|
|
21
|
+
function resolveDesiredStatusLineItems(config) {
|
|
34
22
|
var _a;
|
|
35
|
-
const
|
|
36
|
-
if (
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
23
|
+
const raw = (_a = config.codexStatusline) === null || _a === void 0 ? void 0 : _a.items;
|
|
24
|
+
if (!Array.isArray(raw))
|
|
25
|
+
return null;
|
|
26
|
+
return raw
|
|
27
|
+
.map((entry) => String(entry).trim())
|
|
28
|
+
.filter((entry) => entry);
|
|
29
|
+
}
|
|
30
|
+
function resolveDesiredStatusLineConfig(config) {
|
|
31
|
+
const statusLineItems = resolveDesiredStatusLineItems(config);
|
|
32
|
+
if (statusLineItems === null)
|
|
33
|
+
return null;
|
|
34
|
+
return {
|
|
35
|
+
statusLineItems,
|
|
36
|
+
configPath: (0, config_1.resolveCodexConfigPath)(config),
|
|
37
|
+
};
|
|
46
38
|
}
|
|
47
39
|
function readConfig(filePath) {
|
|
48
40
|
if (!fs.existsSync(filePath))
|
|
@@ -73,88 +65,75 @@ function stripInlineComment(value) {
|
|
|
73
65
|
}
|
|
74
66
|
return value.trim();
|
|
75
67
|
}
|
|
76
|
-
function
|
|
77
|
-
const trimmed = value.trim();
|
|
78
|
-
if ((trimmed.startsWith("\"") && trimmed.endsWith("\"")) ||
|
|
79
|
-
(trimmed.startsWith("'") && trimmed.endsWith("'"))) {
|
|
80
|
-
return trimmed.slice(1, -1);
|
|
81
|
-
}
|
|
82
|
-
return trimmed;
|
|
83
|
-
}
|
|
84
|
-
function parseCommandValue(raw) {
|
|
85
|
-
const trimmed = raw.trim();
|
|
86
|
-
if (!trimmed)
|
|
87
|
-
return null;
|
|
88
|
-
if (trimmed.startsWith("[")) {
|
|
89
|
-
const items = [];
|
|
90
|
-
const regex = /"((?:\\.|[^"\\])*)"/g;
|
|
91
|
-
let match = null;
|
|
92
|
-
while ((match = regex.exec(trimmed))) {
|
|
93
|
-
const item = match[1].replace(/\\"/g, "\"").replace(/\\\\/g, "\\");
|
|
94
|
-
items.push(item);
|
|
95
|
-
}
|
|
96
|
-
return items.length > 0 ? items : null;
|
|
97
|
-
}
|
|
98
|
-
return unquote(trimmed);
|
|
99
|
-
}
|
|
100
|
-
function tokenizeCommand(command) {
|
|
101
|
-
const tokens = [];
|
|
102
|
-
let current = "";
|
|
68
|
+
function hasUnquotedClosingBracket(value) {
|
|
103
69
|
let inSingle = false;
|
|
104
70
|
let inDouble = false;
|
|
105
|
-
let
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
current += ch;
|
|
110
|
-
escape = false;
|
|
111
|
-
continue;
|
|
112
|
-
}
|
|
113
|
-
if (ch === "\\" && !inSingle) {
|
|
114
|
-
escape = true;
|
|
71
|
+
for (let i = 0; i < value.length; i++) {
|
|
72
|
+
const ch = value[i];
|
|
73
|
+
if (ch === "\"" && !inSingle && value[i - 1] !== "\\") {
|
|
74
|
+
inDouble = !inDouble;
|
|
115
75
|
continue;
|
|
116
76
|
}
|
|
117
|
-
if (ch === "'" && !inDouble) {
|
|
77
|
+
if (ch === "'" && !inDouble && value[i - 1] !== "\\") {
|
|
118
78
|
inSingle = !inSingle;
|
|
119
79
|
continue;
|
|
120
80
|
}
|
|
121
|
-
if (ch === "
|
|
122
|
-
|
|
123
|
-
continue;
|
|
124
|
-
}
|
|
125
|
-
if (!inSingle && !inDouble && /\s/.test(ch)) {
|
|
126
|
-
if (current) {
|
|
127
|
-
tokens.push(current);
|
|
128
|
-
current = "";
|
|
129
|
-
}
|
|
130
|
-
continue;
|
|
81
|
+
if (!inSingle && !inDouble && ch === "]") {
|
|
82
|
+
return true;
|
|
131
83
|
}
|
|
132
|
-
current += ch;
|
|
133
84
|
}
|
|
134
|
-
|
|
135
|
-
tokens.push(current);
|
|
136
|
-
return tokens;
|
|
137
|
-
}
|
|
138
|
-
function parseBooleanValue(raw) {
|
|
139
|
-
const normalized = raw.trim().toLowerCase();
|
|
140
|
-
if (normalized === "true")
|
|
141
|
-
return true;
|
|
142
|
-
if (normalized === "false")
|
|
143
|
-
return false;
|
|
144
|
-
return null;
|
|
85
|
+
return false;
|
|
145
86
|
}
|
|
146
|
-
function
|
|
87
|
+
function parseTomlStringArray(raw) {
|
|
147
88
|
const trimmed = raw.trim();
|
|
148
|
-
if (!trimmed)
|
|
89
|
+
if (!trimmed.startsWith("[") || !hasUnquotedClosingBracket(trimmed)) {
|
|
149
90
|
return null;
|
|
150
|
-
|
|
151
|
-
if (
|
|
91
|
+
}
|
|
92
|
+
if (/^\[\s*\]$/.test(trimmed))
|
|
93
|
+
return [];
|
|
94
|
+
const items = [];
|
|
95
|
+
const regex = /"((?:\\.|[^"\\])*)"|'([^']*)'/g;
|
|
96
|
+
let match = null;
|
|
97
|
+
while ((match = regex.exec(trimmed))) {
|
|
98
|
+
if (match[0].startsWith("\"")) {
|
|
99
|
+
items.push(match[1].replace(/\\"/g, "\"").replace(/\\\\/g, "\\"));
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
items.push(match[2] || "");
|
|
103
|
+
}
|
|
104
|
+
if (items.length === 0)
|
|
152
105
|
return null;
|
|
153
|
-
return
|
|
106
|
+
return items;
|
|
107
|
+
}
|
|
108
|
+
function parseStatusLineItems(sectionText) {
|
|
109
|
+
const lines = sectionText.split(/\r?\n/).slice(1);
|
|
110
|
+
for (let i = 0; i < lines.length; i++) {
|
|
111
|
+
const trimmed = lines[i].trim();
|
|
112
|
+
if (!trimmed || trimmed.startsWith("#") || trimmed.startsWith(";"))
|
|
113
|
+
continue;
|
|
114
|
+
const matchLine = /^status_line\s*=\s*(.*)$/.exec(trimmed);
|
|
115
|
+
if (!matchLine)
|
|
116
|
+
continue;
|
|
117
|
+
const value = stripInlineComment(matchLine[1]);
|
|
118
|
+
if (!value.startsWith("["))
|
|
119
|
+
return null;
|
|
120
|
+
const parts = [value];
|
|
121
|
+
if (!hasUnquotedClosingBracket(value)) {
|
|
122
|
+
for (let j = i + 1; j < lines.length; j++) {
|
|
123
|
+
const next = stripInlineComment(lines[j]);
|
|
124
|
+
if (!next)
|
|
125
|
+
continue;
|
|
126
|
+
parts.push(next);
|
|
127
|
+
if (hasUnquotedClosingBracket(next))
|
|
128
|
+
break;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return parseTomlStringArray(parts.join(" "));
|
|
132
|
+
}
|
|
133
|
+
return null;
|
|
154
134
|
}
|
|
155
|
-
function
|
|
135
|
+
function parseSectionByHeader(text, headerRegex) {
|
|
156
136
|
var _a;
|
|
157
|
-
const headerRegex = /^\s*\[tui\.status_line\]\s*$/m;
|
|
158
137
|
const match = headerRegex.exec(text);
|
|
159
138
|
if (!match || match.index === undefined)
|
|
160
139
|
return null;
|
|
@@ -165,132 +144,83 @@ function parseStatusLineSection(text) {
|
|
|
165
144
|
const end = nextHeaderMatch
|
|
166
145
|
? afterHeader + ((_a = nextHeaderMatch.index) !== null && _a !== void 0 ? _a : rest.length)
|
|
167
146
|
: text.length;
|
|
168
|
-
const sectionText = text.slice(start, end).trimEnd();
|
|
169
|
-
const lines = sectionText.split(/\r?\n/).slice(1);
|
|
170
|
-
const config = {
|
|
171
|
-
command: null,
|
|
172
|
-
showHints: null,
|
|
173
|
-
updateIntervalMs: null,
|
|
174
|
-
timeoutMs: null,
|
|
175
|
-
};
|
|
176
|
-
for (const line of lines) {
|
|
177
|
-
const trimmed = line.trim();
|
|
178
|
-
if (!trimmed)
|
|
179
|
-
continue;
|
|
180
|
-
if (trimmed.startsWith("#") || trimmed.startsWith(";"))
|
|
181
|
-
continue;
|
|
182
|
-
const matchLine = /^([A-Za-z0-9_]+)\s*=\s*(.+)$/.exec(trimmed);
|
|
183
|
-
if (!matchLine)
|
|
184
|
-
continue;
|
|
185
|
-
const key = matchLine[1];
|
|
186
|
-
const rawValue = stripInlineComment(matchLine[2]);
|
|
187
|
-
if (key === "command") {
|
|
188
|
-
config.command = parseCommandValue(rawValue);
|
|
189
|
-
}
|
|
190
|
-
else if (key === "show_hints") {
|
|
191
|
-
config.showHints = parseBooleanValue(rawValue);
|
|
192
|
-
}
|
|
193
|
-
else if (key === "update_interval_ms") {
|
|
194
|
-
config.updateIntervalMs = parseNumberValue(rawValue);
|
|
195
|
-
}
|
|
196
|
-
else if (key === "timeout_ms") {
|
|
197
|
-
config.timeoutMs = parseNumberValue(rawValue);
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
147
|
return {
|
|
201
148
|
start,
|
|
202
149
|
end,
|
|
203
|
-
sectionText,
|
|
204
|
-
config,
|
|
150
|
+
sectionText: text.slice(start, end).trimEnd(),
|
|
205
151
|
};
|
|
206
152
|
}
|
|
207
|
-
function
|
|
208
|
-
|
|
153
|
+
function parseTuiSection(text) {
|
|
154
|
+
const section = parseSectionByHeader(text, /^\s*\[tui\]\s*$/m);
|
|
155
|
+
if (!section)
|
|
209
156
|
return null;
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
157
|
+
return {
|
|
158
|
+
start: section.start,
|
|
159
|
+
end: section.end,
|
|
160
|
+
sectionText: section.sectionText,
|
|
161
|
+
config: {
|
|
162
|
+
statusLineItems: parseStatusLineItems(section.sectionText),
|
|
163
|
+
},
|
|
164
|
+
};
|
|
217
165
|
}
|
|
218
|
-
function
|
|
166
|
+
function parseLegacyStatusLineSection(text) {
|
|
167
|
+
return parseSectionByHeader(text, /^\s*\[tui\.status_line\]\s*$/m);
|
|
168
|
+
}
|
|
169
|
+
function statusLineItemsMatch(existing, desired) {
|
|
219
170
|
if (!existing)
|
|
220
171
|
return false;
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
if (
|
|
172
|
+
if (existing.length !== desired.length)
|
|
173
|
+
return false;
|
|
174
|
+
for (let i = 0; i < desired.length; i++) {
|
|
175
|
+
if (existing[i] !== desired[i])
|
|
225
176
|
return false;
|
|
226
|
-
for (let i = 0; i < desiredTokens.length; i++) {
|
|
227
|
-
if (existingTokens[i] !== desiredTokens[i])
|
|
228
|
-
return false;
|
|
229
|
-
}
|
|
230
|
-
return true;
|
|
231
177
|
}
|
|
232
|
-
if (typeof existing === "string" && typeof desired === "string") {
|
|
233
|
-
return existing.trim() === desired.trim();
|
|
234
|
-
}
|
|
235
|
-
return false;
|
|
236
|
-
}
|
|
237
|
-
function configMatches(config, desired) {
|
|
238
|
-
if (!commandMatches(config.command, desired.command))
|
|
239
|
-
return false;
|
|
240
|
-
if (config.showHints !== desired.showHints)
|
|
241
|
-
return false;
|
|
242
|
-
if (config.updateIntervalMs !== desired.updateIntervalMs)
|
|
243
|
-
return false;
|
|
244
|
-
if (config.timeoutMs !== desired.timeoutMs)
|
|
245
|
-
return false;
|
|
246
178
|
return true;
|
|
247
179
|
}
|
|
248
|
-
function
|
|
249
|
-
|
|
250
|
-
const raw = (_a = config.codexStatusline) === null || _a === void 0 ? void 0 : _a.command;
|
|
251
|
-
if (typeof raw === "string") {
|
|
252
|
-
const trimmed = raw.trim();
|
|
253
|
-
if (trimmed)
|
|
254
|
-
return trimmed;
|
|
255
|
-
}
|
|
256
|
-
else if (Array.isArray(raw)) {
|
|
257
|
-
const cleaned = raw
|
|
258
|
-
.map((entry) => String(entry).trim())
|
|
259
|
-
.filter((entry) => entry);
|
|
260
|
-
if (cleaned.length > 0)
|
|
261
|
-
return cleaned;
|
|
262
|
-
}
|
|
263
|
-
return DEFAULT_STATUSLINE_COMMAND;
|
|
180
|
+
function configMatches(config, desired) {
|
|
181
|
+
return statusLineItemsMatch(config.statusLineItems, desired.statusLineItems);
|
|
264
182
|
}
|
|
265
|
-
function
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
const updateIntervalMs = (_d = (_c = config.codexStatusline) === null || _c === void 0 ? void 0 : _c.updateIntervalMs) !== null && _d !== void 0 ? _d : DEFAULT_UPDATE_INTERVAL_MS;
|
|
269
|
-
const timeoutMs = (_f = (_e = config.codexStatusline) === null || _e === void 0 ? void 0 : _e.timeoutMs) !== null && _f !== void 0 ? _f : DEFAULT_TIMEOUT_MS;
|
|
270
|
-
const command = resolveDesiredCommand(config);
|
|
271
|
-
const configPath = resolveCodexConfigPath(config);
|
|
272
|
-
return {
|
|
273
|
-
command,
|
|
274
|
-
showHints,
|
|
275
|
-
updateIntervalMs,
|
|
276
|
-
timeoutMs,
|
|
277
|
-
configPath,
|
|
278
|
-
};
|
|
183
|
+
function formatStatusLineItems(items) {
|
|
184
|
+
const parts = items.map((item) => JSON.stringify(item)).join(", ");
|
|
185
|
+
return `[${parts}]`;
|
|
279
186
|
}
|
|
280
|
-
function
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
187
|
+
function removeStatusLineSettingLines(lines) {
|
|
188
|
+
const kept = [];
|
|
189
|
+
let inMultilineArray = false;
|
|
190
|
+
for (const line of lines) {
|
|
191
|
+
const trimmed = line.trim();
|
|
192
|
+
if (inMultilineArray) {
|
|
193
|
+
const value = stripInlineComment(trimmed);
|
|
194
|
+
if (hasUnquotedClosingBracket(value)) {
|
|
195
|
+
inMultilineArray = false;
|
|
196
|
+
}
|
|
197
|
+
continue;
|
|
198
|
+
}
|
|
199
|
+
const matchLine = /^status_line\s*=\s*(.*)$/.exec(trimmed);
|
|
200
|
+
if (!matchLine) {
|
|
201
|
+
kept.push(line);
|
|
202
|
+
continue;
|
|
203
|
+
}
|
|
204
|
+
const value = stripInlineComment(matchLine[1]);
|
|
205
|
+
if (value.startsWith("[") && !hasUnquotedClosingBracket(value)) {
|
|
206
|
+
inMultilineArray = true;
|
|
207
|
+
}
|
|
284
208
|
}
|
|
285
|
-
return
|
|
209
|
+
return kept;
|
|
286
210
|
}
|
|
287
|
-
function
|
|
288
|
-
const
|
|
289
|
-
|
|
290
|
-
`
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
211
|
+
function buildTuiSection(section, desired) {
|
|
212
|
+
const statusLine = `status_line = ${formatStatusLineItems(desired.statusLineItems)}`;
|
|
213
|
+
if (!section) {
|
|
214
|
+
return `[tui]\n${statusLine}\n`;
|
|
215
|
+
}
|
|
216
|
+
const lines = section.sectionText.split(/\r?\n/);
|
|
217
|
+
const header = lines[0].trim() === "[tui]" ? lines[0] : "[tui]";
|
|
218
|
+
const body = removeStatusLineSettingLines(lines.slice(1));
|
|
219
|
+
while (body.length > 0 && body[body.length - 1].trim() === "") {
|
|
220
|
+
body.pop();
|
|
221
|
+
}
|
|
222
|
+
body.push(statusLine);
|
|
223
|
+
return `${header}\n${body.join("\n")}\n`;
|
|
294
224
|
}
|
|
295
225
|
function upsertSection(text, section, newSection) {
|
|
296
226
|
if (!section) {
|
|
@@ -309,6 +239,15 @@ function upsertSection(text, section, newSection) {
|
|
|
309
239
|
suffix = `\n${suffix}`;
|
|
310
240
|
return `${prefix}${newSection}${suffix}`;
|
|
311
241
|
}
|
|
242
|
+
function removeSection(text, section) {
|
|
243
|
+
let prefix = text.slice(0, section.start);
|
|
244
|
+
let suffix = text.slice(section.end);
|
|
245
|
+
if (prefix && !prefix.endsWith("\n"))
|
|
246
|
+
prefix += "\n";
|
|
247
|
+
if (suffix && !suffix.startsWith("\n"))
|
|
248
|
+
suffix = `\n${suffix}`;
|
|
249
|
+
return `${prefix}${suffix}`;
|
|
250
|
+
}
|
|
312
251
|
function writeConfig(filePath, text) {
|
|
313
252
|
try {
|
|
314
253
|
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
@@ -324,22 +263,32 @@ async function ensureCodexStatuslineConfig(config, enabled) {
|
|
|
324
263
|
if (!enabled || disabled)
|
|
325
264
|
return false;
|
|
326
265
|
const desired = resolveDesiredStatusLineConfig(config);
|
|
266
|
+
if (!desired)
|
|
267
|
+
return false;
|
|
327
268
|
const configPath = desired.configPath;
|
|
328
269
|
const raw = readConfig(configPath);
|
|
329
|
-
const
|
|
270
|
+
const legacySection = parseLegacyStatusLineSection(raw);
|
|
271
|
+
const base = legacySection ? removeSection(raw, legacySection) : raw;
|
|
272
|
+
const section = parseTuiSection(base);
|
|
330
273
|
if (section && configMatches(section.config, desired))
|
|
331
274
|
return false;
|
|
332
275
|
const force = parseBooleanEnv(process.env.CODE_ENV_CODEX_STATUSLINE_FORCE) === true;
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
console.log(
|
|
276
|
+
const hasExistingStatusLine = Boolean((section && Array.isArray(section.config.statusLineItems)) || legacySection);
|
|
277
|
+
if (hasExistingStatusLine && !force) {
|
|
278
|
+
console.log(`codenv: existing Codex tui.status_line config in ${configPath}:`);
|
|
279
|
+
if (section && Array.isArray(section.config.statusLineItems)) {
|
|
280
|
+
console.log(section.sectionText);
|
|
281
|
+
}
|
|
282
|
+
else if (legacySection) {
|
|
283
|
+
console.log(legacySection.sectionText);
|
|
284
|
+
}
|
|
336
285
|
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
337
|
-
console.warn("codenv: no TTY available to confirm status_line overwrite.");
|
|
286
|
+
console.warn("codenv: no TTY available to confirm tui.status_line overwrite.");
|
|
338
287
|
return false;
|
|
339
288
|
}
|
|
340
289
|
const rl = (0, ui_1.createReadline)();
|
|
341
290
|
try {
|
|
342
|
-
const confirm = await (0, ui_1.askConfirm)(rl, "Overwrite Codex status_line config? (y/N): ");
|
|
291
|
+
const confirm = await (0, ui_1.askConfirm)(rl, "Overwrite Codex tui.status_line config? (y/N): ");
|
|
343
292
|
if (!confirm)
|
|
344
293
|
return false;
|
|
345
294
|
}
|
|
@@ -347,9 +296,9 @@ async function ensureCodexStatuslineConfig(config, enabled) {
|
|
|
347
296
|
rl.close();
|
|
348
297
|
}
|
|
349
298
|
}
|
|
350
|
-
const updated = upsertSection(
|
|
299
|
+
const updated = upsertSection(base, section, buildTuiSection(section, desired));
|
|
351
300
|
if (!writeConfig(configPath, updated)) {
|
|
352
|
-
console.error("codenv: failed to write Codex config; status_line not updated.");
|
|
301
|
+
console.error("codenv: failed to write Codex config; tui.status_line not updated.");
|
|
353
302
|
return false;
|
|
354
303
|
}
|
|
355
304
|
return true;
|
package/bin/statusline/index.js
CHANGED
|
@@ -19,8 +19,17 @@ function buildStatuslineResult(args, config, configPath) {
|
|
|
19
19
|
}
|
|
20
20
|
let type = (0, input_1.normalizeTypeValue)(typeCandidate);
|
|
21
21
|
const envProfile = (0, input_1.resolveEnvProfile)(type);
|
|
22
|
-
|
|
22
|
+
let profileKey = (0, utils_1.firstNonEmpty)(args.profileKey, envProfile.key, inputProfile ? inputProfile.key : null);
|
|
23
23
|
let profileName = (0, utils_1.firstNonEmpty)(args.profileName, envProfile.name, inputProfile ? inputProfile.name : null);
|
|
24
|
+
const terminalTag = process.env.CODE_ENV_TERMINAL_TAG || null;
|
|
25
|
+
if (!profileKey && !profileName) {
|
|
26
|
+
const fallback = (0, usage_1.resolveProfileFromLog)(config, configPath, (0, type_1.normalizeType)(type || ""), terminalTag);
|
|
27
|
+
if (fallback) {
|
|
28
|
+
profileKey = fallback.profileKey;
|
|
29
|
+
profileName = fallback.profileName;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
const sessionId = (0, input_1.getSessionId)(stdinInput);
|
|
24
33
|
if (profileKey && !profileName && config.profiles && config.profiles[profileKey]) {
|
|
25
34
|
const profile = config.profiles[profileKey];
|
|
26
35
|
profileName = (0, type_1.getProfileDisplayName)(profileKey, profile, type || undefined);
|
|
@@ -37,7 +46,6 @@ function buildStatuslineResult(args, config, configPath) {
|
|
|
37
46
|
type = inferred;
|
|
38
47
|
}
|
|
39
48
|
const cwd = (0, utils_1.firstNonEmpty)(args.cwd, process.env.CODE_ENV_CWD, (0, input_1.getWorkspaceDir)(stdinInput), stdinInput ? stdinInput.cwd : null, process.cwd());
|
|
40
|
-
const sessionId = (0, input_1.getSessionId)(stdinInput);
|
|
41
49
|
const usageType = (0, type_1.normalizeType)(type || "");
|
|
42
50
|
const stdinUsageTotals = (0, usage_2.getUsageTotalsFromInput)(stdinInput, usageType);
|
|
43
51
|
const shouldSyncUsageFromSessions = args.syncUsage && !stdinUsageTotals;
|