codexuse-cli 3.9.7 → 3.9.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1386 -340
- package/dist/index.js.map +1 -1
- package/dist/server/index.mjs +1730 -613
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -2478,7 +2478,9 @@ function createDefaultAppState() {
|
|
|
2478
2478
|
lastObservedPid: null,
|
|
2479
2479
|
lastRestartStatus: null,
|
|
2480
2480
|
lastRestartReason: null,
|
|
2481
|
-
|
|
2481
|
+
activity: [],
|
|
2482
|
+
instancesByProfileName: {},
|
|
2483
|
+
pendingRestartDebt: null
|
|
2482
2484
|
},
|
|
2483
2485
|
app: {
|
|
2484
2486
|
lastAppVersion: null,
|
|
@@ -2582,6 +2584,9 @@ function asString(value) {
|
|
|
2582
2584
|
function asNumberOrNull(value) {
|
|
2583
2585
|
return typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
2584
2586
|
}
|
|
2587
|
+
function asBooleanOrNull(value) {
|
|
2588
|
+
return typeof value === "boolean" ? value : null;
|
|
2589
|
+
}
|
|
2585
2590
|
function normalizeAppState(raw) {
|
|
2586
2591
|
const defaults = createDefaultAppState();
|
|
2587
2592
|
if (!isRecord2(raw)) {
|
|
@@ -2616,6 +2621,32 @@ function normalizeAppState(raw) {
|
|
|
2616
2621
|
merged.officialCodex.lastRestartReason = asString(
|
|
2617
2622
|
merged.officialCodex.lastRestartReason
|
|
2618
2623
|
);
|
|
2624
|
+
merged.officialCodex.activity = Array.isArray(merged.officialCodex.activity) ? merged.officialCodex.activity.filter((entry) => isRecord2(entry)).map((entry) => ({
|
|
2625
|
+
id: asString(entry.id) ?? "",
|
|
2626
|
+
at: asString(entry.at) ?? (/* @__PURE__ */ new Date(0)).toISOString(),
|
|
2627
|
+
kind: entry.kind === "auto-roll-eval" || entry.kind === "profile-switch" || entry.kind === "auth-verified" || entry.kind === "official-codex-restart" || entry.kind === "reset-window-activation" || entry.kind === "low-remaining-alert" ? entry.kind : "auto-roll-eval",
|
|
2628
|
+
status: asString(entry.status) ?? "unknown",
|
|
2629
|
+
reason: asString(entry.reason),
|
|
2630
|
+
decisionId: asString(entry.decisionId),
|
|
2631
|
+
profileName: asString(entry.profileName),
|
|
2632
|
+
sourceProfileName: asString(entry.sourceProfileName),
|
|
2633
|
+
targetProfileName: asString(entry.targetProfileName),
|
|
2634
|
+
remainingPercent: asNumberOrNull(entry.remainingPercent),
|
|
2635
|
+
threshold: asNumberOrNull(entry.threshold),
|
|
2636
|
+
snapshotAgeMs: asNumberOrNull(entry.snapshotAgeMs),
|
|
2637
|
+
snapshotSource: asString(entry.snapshotSource),
|
|
2638
|
+
phase: asString(entry.phase),
|
|
2639
|
+
pid: asNumberOrNull(entry.pid),
|
|
2640
|
+
profileKeyHash: asString(entry.profileKeyHash),
|
|
2641
|
+
switchVerified: asBooleanOrNull(entry.switchVerified),
|
|
2642
|
+
restartRequested: asBooleanOrNull(entry.restartRequested),
|
|
2643
|
+
restartResult: asString(entry.restartResult),
|
|
2644
|
+
observedProfileName: asString(entry.observedProfileName),
|
|
2645
|
+
observedProfileKeyHash: asString(entry.observedProfileKeyHash),
|
|
2646
|
+
observedProfileMatchSource: asString(
|
|
2647
|
+
entry.observedProfileMatchSource
|
|
2648
|
+
)
|
|
2649
|
+
})).filter((entry) => entry.id && entry.at).slice(-50) : [];
|
|
2619
2650
|
if (!isRecord2(merged.officialCodex.instancesByProfileName)) {
|
|
2620
2651
|
merged.officialCodex.instancesByProfileName = {};
|
|
2621
2652
|
} else {
|
|
@@ -2646,6 +2677,21 @@ function normalizeAppState(raw) {
|
|
|
2646
2677
|
}
|
|
2647
2678
|
merged.officialCodex.instancesByProfileName = nextInstances;
|
|
2648
2679
|
}
|
|
2680
|
+
if (isRecord2(merged.officialCodex.pendingRestartDebt)) {
|
|
2681
|
+
const debt = merged.officialCodex.pendingRestartDebt;
|
|
2682
|
+
const targetProfileName = asString(debt.targetProfileName);
|
|
2683
|
+
merged.officialCodex.pendingRestartDebt = targetProfileName ? {
|
|
2684
|
+
targetProfileName,
|
|
2685
|
+
targetProfileKey: asString(debt.targetProfileKey),
|
|
2686
|
+
sourceProfileName: asString(debt.sourceProfileName),
|
|
2687
|
+
sourceProfileKey: asString(debt.sourceProfileKey),
|
|
2688
|
+
decisionId: asString(debt.decisionId),
|
|
2689
|
+
attempts: asNumberOrNull(debt.attempts) ?? 0,
|
|
2690
|
+
lastReason: asString(debt.lastReason)
|
|
2691
|
+
} : null;
|
|
2692
|
+
} else {
|
|
2693
|
+
merged.officialCodex.pendingRestartDebt = null;
|
|
2694
|
+
}
|
|
2649
2695
|
merged.app.lastAppVersion = asString(merged.app.lastAppVersion);
|
|
2650
2696
|
merged.app.pendingUpdateVersion = asString(merged.app.pendingUpdateVersion);
|
|
2651
2697
|
merged.app.lastProfileName = asString(merged.app.lastProfileName);
|
|
@@ -2723,7 +2769,9 @@ function normalizeAppState(raw) {
|
|
|
2723
2769
|
merged.ui.profiles.groupBy = asString(merged.ui.profiles.groupBy);
|
|
2724
2770
|
merged.ui.profiles.planFilter = asString(merged.ui.profiles.planFilter);
|
|
2725
2771
|
merged.ui.profiles.healthFilter = asString(merged.ui.profiles.healthFilter);
|
|
2726
|
-
merged.ui.profiles.customGroupFilter = asString(
|
|
2772
|
+
merged.ui.profiles.customGroupFilter = asString(
|
|
2773
|
+
merged.ui.profiles.customGroupFilter
|
|
2774
|
+
);
|
|
2727
2775
|
if (typeof merged.ui.profiles.toolbarOpen !== "boolean") {
|
|
2728
2776
|
merged.ui.profiles.toolbarOpen = null;
|
|
2729
2777
|
}
|
|
@@ -2731,13 +2779,15 @@ function normalizeAppState(raw) {
|
|
|
2731
2779
|
merged.ui.profiles.collapsedSections = {};
|
|
2732
2780
|
} else {
|
|
2733
2781
|
merged.ui.profiles.collapsedSections = Object.fromEntries(
|
|
2734
|
-
Object.entries(merged.ui.profiles.collapsedSections).flatMap(
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
|
|
2782
|
+
Object.entries(merged.ui.profiles.collapsedSections).flatMap(
|
|
2783
|
+
([key, value]) => {
|
|
2784
|
+
const normalizedKey = asString(key);
|
|
2785
|
+
if (!normalizedKey || typeof value !== "boolean") {
|
|
2786
|
+
return [];
|
|
2787
|
+
}
|
|
2788
|
+
return [[normalizedKey, value]];
|
|
2738
2789
|
}
|
|
2739
|
-
|
|
2740
|
-
})
|
|
2790
|
+
)
|
|
2741
2791
|
);
|
|
2742
2792
|
}
|
|
2743
2793
|
if (!isRecord2(merged.ui.onboarding)) {
|
|
@@ -2766,26 +2816,30 @@ function normalizeAppState(raw) {
|
|
|
2766
2816
|
merged.ui.onboarding.nudgeCooldowns = {};
|
|
2767
2817
|
} else {
|
|
2768
2818
|
merged.ui.onboarding.nudgeCooldowns = Object.fromEntries(
|
|
2769
|
-
Object.entries(merged.ui.onboarding.nudgeCooldowns).flatMap(
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
2819
|
+
Object.entries(merged.ui.onboarding.nudgeCooldowns).flatMap(
|
|
2820
|
+
([key, value]) => {
|
|
2821
|
+
const normalizedKey = asString(key);
|
|
2822
|
+
if (!normalizedKey || !Number.isFinite(value)) {
|
|
2823
|
+
return [];
|
|
2824
|
+
}
|
|
2825
|
+
return [[normalizedKey, Number(value)]];
|
|
2773
2826
|
}
|
|
2774
|
-
|
|
2775
|
-
})
|
|
2827
|
+
)
|
|
2776
2828
|
);
|
|
2777
2829
|
}
|
|
2778
2830
|
if (!isRecord2(merged.ui.onboarding.nudgeDismissCount)) {
|
|
2779
2831
|
merged.ui.onboarding.nudgeDismissCount = {};
|
|
2780
2832
|
} else {
|
|
2781
2833
|
merged.ui.onboarding.nudgeDismissCount = Object.fromEntries(
|
|
2782
|
-
Object.entries(merged.ui.onboarding.nudgeDismissCount).flatMap(
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
2834
|
+
Object.entries(merged.ui.onboarding.nudgeDismissCount).flatMap(
|
|
2835
|
+
([key, value]) => {
|
|
2836
|
+
const normalizedKey = asString(key);
|
|
2837
|
+
if (!normalizedKey || !Number.isFinite(value)) {
|
|
2838
|
+
return [];
|
|
2839
|
+
}
|
|
2840
|
+
return [[normalizedKey, Number(value)]];
|
|
2786
2841
|
}
|
|
2787
|
-
|
|
2788
|
-
})
|
|
2842
|
+
)
|
|
2789
2843
|
);
|
|
2790
2844
|
}
|
|
2791
2845
|
if (typeof merged.ui.onboarding.proUnlockedCelebrated !== "boolean") {
|
|
@@ -2795,17 +2849,21 @@ function normalizeAppState(raw) {
|
|
|
2795
2849
|
merged.ui.projectThreadSelections = {};
|
|
2796
2850
|
} else {
|
|
2797
2851
|
merged.ui.projectThreadSelections = Object.fromEntries(
|
|
2798
|
-
Object.entries(merged.ui.projectThreadSelections).flatMap(
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2852
|
+
Object.entries(merged.ui.projectThreadSelections).flatMap(
|
|
2853
|
+
([projectId, threadId]) => {
|
|
2854
|
+
const normalizedProjectId = asString(projectId);
|
|
2855
|
+
if (!normalizedProjectId) {
|
|
2856
|
+
return [];
|
|
2857
|
+
}
|
|
2858
|
+
const normalizedThreadId = typeof threadId === "string" && threadId.trim().length > 0 ? threadId.trim() : null;
|
|
2859
|
+
return [[normalizedProjectId, normalizedThreadId]];
|
|
2802
2860
|
}
|
|
2803
|
-
|
|
2804
|
-
return [[normalizedProjectId, normalizedThreadId]];
|
|
2805
|
-
})
|
|
2861
|
+
)
|
|
2806
2862
|
);
|
|
2807
2863
|
}
|
|
2808
|
-
merged.ui.duplicateWarningDismissedKey = asString(
|
|
2864
|
+
merged.ui.duplicateWarningDismissedKey = asString(
|
|
2865
|
+
merged.ui.duplicateWarningDismissedKey
|
|
2866
|
+
);
|
|
2809
2867
|
if (typeof merged.ui.pendingLicenseActivation !== "boolean") {
|
|
2810
2868
|
merged.ui.pendingLicenseActivation = false;
|
|
2811
2869
|
}
|
|
@@ -2824,14 +2882,16 @@ function normalizeAppState(raw) {
|
|
|
2824
2882
|
merged.profileDashboard.customGroupsByAccountKey = {};
|
|
2825
2883
|
} else {
|
|
2826
2884
|
merged.profileDashboard.customGroupsByAccountKey = Object.fromEntries(
|
|
2827
|
-
Object.entries(merged.profileDashboard.customGroupsByAccountKey).flatMap(
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2885
|
+
Object.entries(merged.profileDashboard.customGroupsByAccountKey).flatMap(
|
|
2886
|
+
([key, value]) => {
|
|
2887
|
+
const normalizedKey = asString(key);
|
|
2888
|
+
const normalizedValue = asString(value);
|
|
2889
|
+
if (!normalizedKey || !normalizedValue) {
|
|
2890
|
+
return [];
|
|
2891
|
+
}
|
|
2892
|
+
return [[normalizedKey, normalizedValue]];
|
|
2832
2893
|
}
|
|
2833
|
-
|
|
2834
|
-
})
|
|
2894
|
+
)
|
|
2835
2895
|
);
|
|
2836
2896
|
}
|
|
2837
2897
|
{
|
|
@@ -2898,7 +2958,9 @@ function normalizeAppState(raw) {
|
|
|
2898
2958
|
}
|
|
2899
2959
|
merged.analytics.anonymousId = asString(merged.analytics.anonymousId);
|
|
2900
2960
|
if (!merged.analytics.anonymousId) {
|
|
2901
|
-
const legacyInstallId = asString(
|
|
2961
|
+
const legacyInstallId = asString(
|
|
2962
|
+
merged.telemetry?.installId
|
|
2963
|
+
);
|
|
2902
2964
|
merged.analytics.anonymousId = legacyInstallId;
|
|
2903
2965
|
}
|
|
2904
2966
|
if (typeof merged.analytics.enabled !== "boolean") {
|
|
@@ -2969,10 +3031,18 @@ async function readLegacyAppStateFromDisk() {
|
|
|
2969
3031
|
}
|
|
2970
3032
|
}
|
|
2971
3033
|
async function readAppStateFromStorage() {
|
|
2972
|
-
return readDocument(
|
|
3034
|
+
return readDocument(
|
|
3035
|
+
resolveStorageDbPath(),
|
|
3036
|
+
APP_STATE_DOCUMENT,
|
|
3037
|
+
normalizeAppState
|
|
3038
|
+
);
|
|
2973
3039
|
}
|
|
2974
3040
|
async function writeAppStateToStorage(state) {
|
|
2975
|
-
return writeDocument(
|
|
3041
|
+
return writeDocument(
|
|
3042
|
+
resolveStorageDbPath(),
|
|
3043
|
+
APP_STATE_DOCUMENT,
|
|
3044
|
+
normalizeAppState(state)
|
|
3045
|
+
);
|
|
2976
3046
|
}
|
|
2977
3047
|
async function ensureInitialized() {
|
|
2978
3048
|
if (appStateCache) {
|
|
@@ -3985,16 +4055,133 @@ function logError(...args) {
|
|
|
3985
4055
|
console.error(...args);
|
|
3986
4056
|
}
|
|
3987
4057
|
function logInfo(...args) {
|
|
3988
|
-
if (isTestEnv && !isMocked(console.
|
|
4058
|
+
if (isTestEnv && !isMocked(console.info)) {
|
|
3989
4059
|
return;
|
|
3990
4060
|
}
|
|
3991
|
-
console.
|
|
4061
|
+
console.info(...args);
|
|
3992
4062
|
}
|
|
3993
4063
|
|
|
3994
4064
|
// ../../packages/runtime-codex/src/codex/rpc.ts
|
|
3995
4065
|
var RPC_TIMEOUT_MS = 1e4;
|
|
4066
|
+
var ACTIVATION_TURN_TIMEOUT_MS = 9e4;
|
|
4067
|
+
var ACTIVATION_PROMPT = "Reply with exactly: ok.";
|
|
4068
|
+
var ACTIVATION_MODEL = "gpt-5.1-codex-mini";
|
|
3996
4069
|
var MAX_STDERR_CAPTURE_CHARS = 32768;
|
|
3997
4070
|
var REFRESH_TOKEN_REDEEMED_SNIPPET = "refresh token was already used";
|
|
4071
|
+
function isRecord4(value) {
|
|
4072
|
+
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
4073
|
+
}
|
|
4074
|
+
function asString3(value) {
|
|
4075
|
+
return typeof value === "string" ? value : value != null ? String(value) : "";
|
|
4076
|
+
}
|
|
4077
|
+
function createRpcMessageReader(rl) {
|
|
4078
|
+
const queue = [];
|
|
4079
|
+
const waiters = [];
|
|
4080
|
+
let closedError = null;
|
|
4081
|
+
const rejectAll = (error) => {
|
|
4082
|
+
closedError = error;
|
|
4083
|
+
while (waiters.length > 0) {
|
|
4084
|
+
const waiter = waiters.shift();
|
|
4085
|
+
clearTimeout(waiter.timer);
|
|
4086
|
+
waiter.reject(error);
|
|
4087
|
+
}
|
|
4088
|
+
};
|
|
4089
|
+
const onLine = (line) => {
|
|
4090
|
+
let parsed;
|
|
4091
|
+
try {
|
|
4092
|
+
parsed = JSON.parse(line);
|
|
4093
|
+
} catch {
|
|
4094
|
+
rejectAll(new Error("codex RPC returned malformed JSON"));
|
|
4095
|
+
return;
|
|
4096
|
+
}
|
|
4097
|
+
const waiterIndex = waiters.findIndex((waiter) => waiter.predicate(parsed));
|
|
4098
|
+
if (waiterIndex >= 0) {
|
|
4099
|
+
const [waiter] = waiters.splice(waiterIndex, 1);
|
|
4100
|
+
clearTimeout(waiter.timer);
|
|
4101
|
+
waiter.resolve(parsed);
|
|
4102
|
+
return;
|
|
4103
|
+
}
|
|
4104
|
+
queue.push(parsed);
|
|
4105
|
+
};
|
|
4106
|
+
const onClose = () => {
|
|
4107
|
+
rejectAll(new Error("codex RPC stream closed before response"));
|
|
4108
|
+
};
|
|
4109
|
+
rl.on("line", onLine);
|
|
4110
|
+
rl.on("close", onClose);
|
|
4111
|
+
return {
|
|
4112
|
+
read(predicate, timeoutMs) {
|
|
4113
|
+
const queuedIndex = queue.findIndex(predicate);
|
|
4114
|
+
if (queuedIndex >= 0) {
|
|
4115
|
+
const [message] = queue.splice(queuedIndex, 1);
|
|
4116
|
+
return Promise.resolve(message);
|
|
4117
|
+
}
|
|
4118
|
+
if (closedError) {
|
|
4119
|
+
return Promise.reject(closedError);
|
|
4120
|
+
}
|
|
4121
|
+
return new Promise((resolve, reject) => {
|
|
4122
|
+
const waiter = {
|
|
4123
|
+
predicate,
|
|
4124
|
+
resolve,
|
|
4125
|
+
reject,
|
|
4126
|
+
timer: setTimeout(
|
|
4127
|
+
() => {
|
|
4128
|
+
const index = waiters.indexOf(waiter);
|
|
4129
|
+
if (index >= 0) {
|
|
4130
|
+
waiters.splice(index, 1);
|
|
4131
|
+
}
|
|
4132
|
+
reject(new Error("codex RPC timed out"));
|
|
4133
|
+
},
|
|
4134
|
+
Math.max(1, timeoutMs)
|
|
4135
|
+
)
|
|
4136
|
+
};
|
|
4137
|
+
waiters.push(waiter);
|
|
4138
|
+
});
|
|
4139
|
+
},
|
|
4140
|
+
dispose() {
|
|
4141
|
+
rl.off("line", onLine);
|
|
4142
|
+
rl.off("close", onClose);
|
|
4143
|
+
while (waiters.length > 0) {
|
|
4144
|
+
const waiter = waiters.shift();
|
|
4145
|
+
clearTimeout(waiter.timer);
|
|
4146
|
+
}
|
|
4147
|
+
}
|
|
4148
|
+
};
|
|
4149
|
+
}
|
|
4150
|
+
function readThreadIdFromResult(result) {
|
|
4151
|
+
if (!isRecord4(result)) return null;
|
|
4152
|
+
const thread = isRecord4(result.thread) ? result.thread : {};
|
|
4153
|
+
const value = asString3(thread.id ?? result.threadId).trim();
|
|
4154
|
+
return value.length > 0 ? value : null;
|
|
4155
|
+
}
|
|
4156
|
+
function readTurnIdFromResult(result) {
|
|
4157
|
+
if (!isRecord4(result)) return null;
|
|
4158
|
+
const turn = isRecord4(result.turn) ? result.turn : {};
|
|
4159
|
+
const value = asString3(turn.id ?? result.turnId).trim();
|
|
4160
|
+
return value.length > 0 ? value : null;
|
|
4161
|
+
}
|
|
4162
|
+
function readTurnIdFromNotification(message) {
|
|
4163
|
+
if (!isRecord4(message.params)) return null;
|
|
4164
|
+
const turn = isRecord4(message.params.turn) ? message.params.turn : {};
|
|
4165
|
+
const value = asString3(turn.id ?? message.params.turnId).trim();
|
|
4166
|
+
return value.length > 0 ? value : null;
|
|
4167
|
+
}
|
|
4168
|
+
function readTurnStatusFromNotification(message) {
|
|
4169
|
+
if (!isRecord4(message.params)) {
|
|
4170
|
+
return { status: null, reason: null };
|
|
4171
|
+
}
|
|
4172
|
+
const turn = isRecord4(message.params.turn) ? message.params.turn : {};
|
|
4173
|
+
const error = isRecord4(turn.error) ? turn.error : null;
|
|
4174
|
+
return {
|
|
4175
|
+
status: asString3(turn.status).trim() || null,
|
|
4176
|
+
reason: error ? asString3(error.message).trim() || null : null
|
|
4177
|
+
};
|
|
4178
|
+
}
|
|
4179
|
+
function readLegacyEventTurnId(message) {
|
|
4180
|
+
if (!isRecord4(message.params)) return null;
|
|
4181
|
+
const msg = isRecord4(message.params.msg) ? message.params.msg : {};
|
|
4182
|
+
const value = asString3(message.params.id ?? msg.turn_id ?? msg.turnId).trim();
|
|
4183
|
+
return value.length > 0 ? value : null;
|
|
4184
|
+
}
|
|
3998
4185
|
function parseTimestamp2(value) {
|
|
3999
4186
|
if (typeof value !== "string" || value.trim().length === 0) {
|
|
4000
4187
|
return null;
|
|
@@ -4045,8 +4232,17 @@ function extractAuthRecencyMs(content) {
|
|
|
4045
4232
|
const rootLastRefresh = parseTimestamp2(parsed.last_refresh);
|
|
4046
4233
|
const nestedLastRefresh = parseTimestamp2(parsed.tokens?.last_refresh);
|
|
4047
4234
|
const rootAccessIssuedAt = extractJwtIssuedAtMs(parsed.access_token);
|
|
4048
|
-
const nestedAccessIssuedAt = extractJwtIssuedAtMs(
|
|
4049
|
-
|
|
4235
|
+
const nestedAccessIssuedAt = extractJwtIssuedAtMs(
|
|
4236
|
+
parsed.tokens?.access_token
|
|
4237
|
+
);
|
|
4238
|
+
const candidates = [
|
|
4239
|
+
rootLastRefresh,
|
|
4240
|
+
nestedLastRefresh,
|
|
4241
|
+
rootAccessIssuedAt,
|
|
4242
|
+
nestedAccessIssuedAt
|
|
4243
|
+
].filter(
|
|
4244
|
+
(value) => typeof value === "number" && Number.isFinite(value)
|
|
4245
|
+
);
|
|
4050
4246
|
if (candidates.length === 0) {
|
|
4051
4247
|
return null;
|
|
4052
4248
|
}
|
|
@@ -4097,10 +4293,13 @@ function isRpcResponseForRequest(message, requestId) {
|
|
|
4097
4293
|
}
|
|
4098
4294
|
async function readRpcResponseById(rl, requestId, timeoutMs) {
|
|
4099
4295
|
return new Promise((resolve, reject) => {
|
|
4100
|
-
const timer = setTimeout(
|
|
4101
|
-
|
|
4102
|
-
|
|
4103
|
-
|
|
4296
|
+
const timer = setTimeout(
|
|
4297
|
+
() => {
|
|
4298
|
+
cleanup();
|
|
4299
|
+
reject(new Error("codex RPC timed out"));
|
|
4300
|
+
},
|
|
4301
|
+
Math.max(1, timeoutMs)
|
|
4302
|
+
);
|
|
4104
4303
|
const cleanup = () => {
|
|
4105
4304
|
clearTimeout(timer);
|
|
4106
4305
|
rl.off("line", onLine);
|
|
@@ -4250,7 +4449,11 @@ async function fetchRateLimitsViaRpc(envOverride, options = {}) {
|
|
|
4250
4449
|
throw new Error(formatRpcError("initialize", initializeResponse.error));
|
|
4251
4450
|
}
|
|
4252
4451
|
await sendPayload(child, { method: "initialized", params: {} });
|
|
4253
|
-
await sendPayload(child, {
|
|
4452
|
+
await sendPayload(child, {
|
|
4453
|
+
id: 2,
|
|
4454
|
+
method: "account/rateLimits/read",
|
|
4455
|
+
params: {}
|
|
4456
|
+
});
|
|
4254
4457
|
const message = await readRpcResponseById(rl, 2, RPC_TIMEOUT_MS);
|
|
4255
4458
|
if (message.error) {
|
|
4256
4459
|
const base = formatRpcError("account/rateLimits/read", message.error);
|
|
@@ -4271,11 +4474,181 @@ async function fetchRateLimitsViaRpc(envOverride, options = {}) {
|
|
|
4271
4474
|
if (shouldWriteBackAuth(initialSourceAuth, currentSourceAuth, updatedAuth)) {
|
|
4272
4475
|
await import_node_fs5.promises.writeFile(sourceAuthPath, updatedAuth, "utf8");
|
|
4273
4476
|
} else if (currentSourceAuth && currentSourceAuth !== updatedAuth && currentSourceAuth !== initialSourceAuth) {
|
|
4274
|
-
logWarn(
|
|
4275
|
-
|
|
4276
|
-
|
|
4277
|
-
|
|
4278
|
-
|
|
4477
|
+
logWarn(
|
|
4478
|
+
"Skipped stale auth sync-back after rate-limit probe; source auth changed in flight.",
|
|
4479
|
+
{
|
|
4480
|
+
sourceAuthPath,
|
|
4481
|
+
currentRecencyMs: extractAuthRecencyMs(currentSourceAuth),
|
|
4482
|
+
updatedRecencyMs: extractAuthRecencyMs(updatedAuth)
|
|
4483
|
+
}
|
|
4484
|
+
);
|
|
4485
|
+
}
|
|
4486
|
+
}
|
|
4487
|
+
} catch {
|
|
4488
|
+
}
|
|
4489
|
+
await import_node_fs5.promises.rm(tempHome, { recursive: true, force: true }).catch(() => {
|
|
4490
|
+
});
|
|
4491
|
+
}
|
|
4492
|
+
}
|
|
4493
|
+
async function activateResetWindowViaRpc(envOverride, options = {}) {
|
|
4494
|
+
const binaryPath = options.codexPath ?? await requireCodexCli();
|
|
4495
|
+
const tempHome = await import_node_fs5.promises.mkdtemp(
|
|
4496
|
+
import_node_path6.default.join(import_node_os2.default.tmpdir(), "codex-activation-")
|
|
4497
|
+
);
|
|
4498
|
+
const tempAuthPath = import_node_path6.default.join(tempHome, "auth.json");
|
|
4499
|
+
let initialSourceAuth = null;
|
|
4500
|
+
const sourceAuthPath = options.authPath ?? (envOverride?.CODEX_HOME ? import_node_path6.default.join(envOverride.CODEX_HOME, "auth.json") : import_node_path6.default.join(
|
|
4501
|
+
envOverride?.HOME ?? process.env.HOME ?? process.env.USERPROFILE ?? import_node_os2.default.homedir(),
|
|
4502
|
+
".codex",
|
|
4503
|
+
"auth.json"
|
|
4504
|
+
));
|
|
4505
|
+
try {
|
|
4506
|
+
initialSourceAuth = await import_node_fs5.promises.readFile(sourceAuthPath, "utf8").catch(() => null);
|
|
4507
|
+
if (!initialSourceAuth) {
|
|
4508
|
+
await import_node_fs5.promises.rm(tempHome, { recursive: true, force: true }).catch(() => {
|
|
4509
|
+
});
|
|
4510
|
+
return { status: "skipped", reason: "auth-missing" };
|
|
4511
|
+
}
|
|
4512
|
+
await import_node_fs5.promises.writeFile(tempAuthPath, initialSourceAuth, "utf8");
|
|
4513
|
+
} catch {
|
|
4514
|
+
await import_node_fs5.promises.rm(tempHome, { recursive: true, force: true }).catch(() => {
|
|
4515
|
+
});
|
|
4516
|
+
return { status: "skipped", reason: "auth-missing" };
|
|
4517
|
+
}
|
|
4518
|
+
const childEnv = {
|
|
4519
|
+
...process.env,
|
|
4520
|
+
...envOverride ?? {},
|
|
4521
|
+
HOME: tempHome,
|
|
4522
|
+
USERPROFILE: tempHome,
|
|
4523
|
+
CODEX_HOME: tempHome,
|
|
4524
|
+
CODEX_TELEMETRY_LABEL: "codex-reset-activation",
|
|
4525
|
+
ELECTRON_RUN_AS_NODE: "1"
|
|
4526
|
+
};
|
|
4527
|
+
const command = buildCodexCommand(
|
|
4528
|
+
binaryPath,
|
|
4529
|
+
["-s", "read-only", "-a", "untrusted", "app-server"],
|
|
4530
|
+
childEnv
|
|
4531
|
+
);
|
|
4532
|
+
const child = (0, import_node_child_process2.spawn)(command.command, command.args, {
|
|
4533
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
4534
|
+
env: childEnv,
|
|
4535
|
+
shell: command.shell
|
|
4536
|
+
});
|
|
4537
|
+
const rl = import_node_readline.default.createInterface({
|
|
4538
|
+
input: child.stdout,
|
|
4539
|
+
crlfDelay: Infinity
|
|
4540
|
+
});
|
|
4541
|
+
const reader = createRpcMessageReader(rl);
|
|
4542
|
+
let stderrOutput = "";
|
|
4543
|
+
child.stderr?.on("data", (chunk) => {
|
|
4544
|
+
if (stderrOutput.length >= MAX_STDERR_CAPTURE_CHARS) {
|
|
4545
|
+
return;
|
|
4546
|
+
}
|
|
4547
|
+
const text = chunk.toString("utf8");
|
|
4548
|
+
const remaining = MAX_STDERR_CAPTURE_CHARS - stderrOutput.length;
|
|
4549
|
+
stderrOutput += text.slice(0, Math.max(0, remaining));
|
|
4550
|
+
});
|
|
4551
|
+
try {
|
|
4552
|
+
await sendPayload(child, {
|
|
4553
|
+
id: 1,
|
|
4554
|
+
method: "initialize",
|
|
4555
|
+
params: { clientInfo: { name: "codexuse", version: "0.0.0" } }
|
|
4556
|
+
});
|
|
4557
|
+
const initializeResponse = await reader.read(
|
|
4558
|
+
(message) => isRpcResponseForRequest(message, 1),
|
|
4559
|
+
RPC_TIMEOUT_MS
|
|
4560
|
+
);
|
|
4561
|
+
if (initializeResponse.error) {
|
|
4562
|
+
throw new Error(formatRpcError("initialize", initializeResponse.error));
|
|
4563
|
+
}
|
|
4564
|
+
await sendPayload(child, { method: "initialized", params: {} });
|
|
4565
|
+
await sendPayload(child, {
|
|
4566
|
+
id: 2,
|
|
4567
|
+
method: "thread/start",
|
|
4568
|
+
params: {
|
|
4569
|
+
cwd: tempHome,
|
|
4570
|
+
model: ACTIVATION_MODEL,
|
|
4571
|
+
approvalPolicy: "untrusted",
|
|
4572
|
+
sandbox: "read-only",
|
|
4573
|
+
experimentalRawEvents: false
|
|
4574
|
+
}
|
|
4575
|
+
});
|
|
4576
|
+
const threadResponse = await reader.read(
|
|
4577
|
+
(message) => isRpcResponseForRequest(message, 2),
|
|
4578
|
+
RPC_TIMEOUT_MS
|
|
4579
|
+
);
|
|
4580
|
+
if (threadResponse.error) {
|
|
4581
|
+
throw new Error(formatRpcError("thread/start", threadResponse.error));
|
|
4582
|
+
}
|
|
4583
|
+
const threadId = readThreadIdFromResult(threadResponse.result);
|
|
4584
|
+
if (!threadId) {
|
|
4585
|
+
throw new Error("thread/start response did not include a thread id.");
|
|
4586
|
+
}
|
|
4587
|
+
await sendPayload(child, {
|
|
4588
|
+
id: 3,
|
|
4589
|
+
method: "turn/start",
|
|
4590
|
+
params: {
|
|
4591
|
+
threadId,
|
|
4592
|
+
model: ACTIVATION_MODEL,
|
|
4593
|
+
effort: "low",
|
|
4594
|
+
input: [
|
|
4595
|
+
{
|
|
4596
|
+
type: "text",
|
|
4597
|
+
text: ACTIVATION_PROMPT,
|
|
4598
|
+
text_elements: []
|
|
4599
|
+
}
|
|
4600
|
+
]
|
|
4601
|
+
}
|
|
4602
|
+
});
|
|
4603
|
+
const turnResponse = await reader.read(
|
|
4604
|
+
(message) => isRpcResponseForRequest(message, 3),
|
|
4605
|
+
RPC_TIMEOUT_MS
|
|
4606
|
+
);
|
|
4607
|
+
if (turnResponse.error) {
|
|
4608
|
+
const base = formatRpcError("turn/start", turnResponse.error);
|
|
4609
|
+
const hint = inferRefreshFailureHint(stderrOutput);
|
|
4610
|
+
if (hint && !base.toLowerCase().includes(hint)) {
|
|
4611
|
+
throw new Error(`${base}; ${hint}`);
|
|
4612
|
+
}
|
|
4613
|
+
throw new Error(base);
|
|
4614
|
+
}
|
|
4615
|
+
const turnId = readTurnIdFromResult(turnResponse.result);
|
|
4616
|
+
if (!turnId) {
|
|
4617
|
+
throw new Error("turn/start response did not include a turn id.");
|
|
4618
|
+
}
|
|
4619
|
+
const completed = await reader.read(
|
|
4620
|
+
(message) => message.method === "turn/completed" && readTurnIdFromNotification(message) === turnId || message.method === "codex/event/task_complete" && readLegacyEventTurnId(message) === turnId,
|
|
4621
|
+
ACTIVATION_TURN_TIMEOUT_MS
|
|
4622
|
+
);
|
|
4623
|
+
const turnStatus = readTurnStatusFromNotification(completed);
|
|
4624
|
+
if (turnStatus.status === "failed") {
|
|
4625
|
+
return {
|
|
4626
|
+
status: "failed",
|
|
4627
|
+
reason: turnStatus.reason ?? "turn-failed",
|
|
4628
|
+
threadId,
|
|
4629
|
+
turnId
|
|
4630
|
+
};
|
|
4631
|
+
}
|
|
4632
|
+
return { status: "completed", reason: null, threadId, turnId };
|
|
4633
|
+
} finally {
|
|
4634
|
+
child.kill();
|
|
4635
|
+
reader.dispose();
|
|
4636
|
+
rl.close();
|
|
4637
|
+
try {
|
|
4638
|
+
const updatedAuth = await import_node_fs5.promises.readFile(tempAuthPath, "utf8");
|
|
4639
|
+
if (updatedAuth.trim().length > 0) {
|
|
4640
|
+
const currentSourceAuth = await import_node_fs5.promises.readFile(sourceAuthPath, "utf8").catch(() => null);
|
|
4641
|
+
if (shouldWriteBackAuth(initialSourceAuth, currentSourceAuth, updatedAuth)) {
|
|
4642
|
+
await import_node_fs5.promises.writeFile(sourceAuthPath, updatedAuth, "utf8");
|
|
4643
|
+
} else if (currentSourceAuth && currentSourceAuth !== updatedAuth && currentSourceAuth !== initialSourceAuth) {
|
|
4644
|
+
logWarn(
|
|
4645
|
+
"Skipped stale auth sync-back after reset-window activation; source auth changed in flight.",
|
|
4646
|
+
{
|
|
4647
|
+
sourceAuthPath,
|
|
4648
|
+
currentRecencyMs: extractAuthRecencyMs(currentSourceAuth),
|
|
4649
|
+
updatedRecencyMs: extractAuthRecencyMs(updatedAuth)
|
|
4650
|
+
}
|
|
4651
|
+
);
|
|
4279
4652
|
}
|
|
4280
4653
|
}
|
|
4281
4654
|
} catch {
|
|
@@ -5402,13 +5775,13 @@ var ProfileManager = class {
|
|
|
5402
5775
|
const existingIdentity = this.resolveProfileIdentityFromData(profileName, existing, existingMetadata);
|
|
5403
5776
|
const nextIdentity = this.resolveProfileIdentityFromData(profileName, normalized, metadata);
|
|
5404
5777
|
if (existingIdentity && nextIdentity && existingIdentity !== nextIdentity) {
|
|
5405
|
-
|
|
5778
|
+
logInfo(
|
|
5406
5779
|
`Skipped syncing tokens for profile '${profileName}' because Codex auth switched to a different OpenAI identity.`
|
|
5407
5780
|
);
|
|
5408
5781
|
return;
|
|
5409
5782
|
}
|
|
5410
5783
|
if (this.normalizeWorkspaceId(existing.workspace_id) !== this.normalizeWorkspaceId(normalized.workspace_id)) {
|
|
5411
|
-
|
|
5784
|
+
logInfo(
|
|
5412
5785
|
`Skipped syncing tokens for profile '${profileName}' because Codex auth switched to a different workspace.`
|
|
5413
5786
|
);
|
|
5414
5787
|
return;
|
|
@@ -5824,6 +6197,25 @@ var ProfileManager = class {
|
|
|
5824
6197
|
});
|
|
5825
6198
|
}
|
|
5826
6199
|
}
|
|
6200
|
+
async activateResetWindow(name, options = {}) {
|
|
6201
|
+
const profileName = this.normalizeProfileName(name);
|
|
6202
|
+
try {
|
|
6203
|
+
return await this.enqueueProfileOperation(
|
|
6204
|
+
profileName,
|
|
6205
|
+
() => this.runWithPreparedProfileHome(
|
|
6206
|
+
profileName,
|
|
6207
|
+
(env) => activateResetWindowViaRpc(env, { codexPath: options.codexPath }),
|
|
6208
|
+
{ syncFromActiveAuthBeforeAction: false }
|
|
6209
|
+
)
|
|
6210
|
+
);
|
|
6211
|
+
} finally {
|
|
6212
|
+
await this.enqueueAuthSwap(async () => {
|
|
6213
|
+
await this.syncActiveAuthFromProfileIfCurrent(profileName);
|
|
6214
|
+
}).catch((error) => {
|
|
6215
|
+
logWarn(`Failed to sync active auth after reset-window activation for '${profileName}':`, error);
|
|
6216
|
+
});
|
|
6217
|
+
}
|
|
6218
|
+
}
|
|
5827
6219
|
/**
|
|
5828
6220
|
* Rename a profile
|
|
5829
6221
|
*/
|
|
@@ -6276,7 +6668,7 @@ var MODEL_SLUG_ALIASES = {
|
|
|
6276
6668
|
function asRecord2(value) {
|
|
6277
6669
|
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
6278
6670
|
}
|
|
6279
|
-
function
|
|
6671
|
+
function asString4(value) {
|
|
6280
6672
|
if (typeof value !== "string") {
|
|
6281
6673
|
return null;
|
|
6282
6674
|
}
|
|
@@ -6287,7 +6679,7 @@ function asNumber(value) {
|
|
|
6287
6679
|
return typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
6288
6680
|
}
|
|
6289
6681
|
function normalizeIsoString(value) {
|
|
6290
|
-
const normalized =
|
|
6682
|
+
const normalized = asString4(value);
|
|
6291
6683
|
if (!normalized) {
|
|
6292
6684
|
return null;
|
|
6293
6685
|
}
|
|
@@ -6299,7 +6691,7 @@ function normalizeStringArray(value) {
|
|
|
6299
6691
|
const result = [];
|
|
6300
6692
|
const seen = /* @__PURE__ */ new Set();
|
|
6301
6693
|
for (const entry of input) {
|
|
6302
|
-
const normalized =
|
|
6694
|
+
const normalized = asString4(entry);
|
|
6303
6695
|
if (!normalized || seen.has(normalized)) {
|
|
6304
6696
|
continue;
|
|
6305
6697
|
}
|
|
@@ -6309,7 +6701,7 @@ function normalizeStringArray(value) {
|
|
|
6309
6701
|
return result;
|
|
6310
6702
|
}
|
|
6311
6703
|
function normalizeReasoningEffort(value) {
|
|
6312
|
-
const normalized =
|
|
6704
|
+
const normalized = asString4(value)?.toLowerCase() ?? null;
|
|
6313
6705
|
return normalized && normalized.length > 0 ? normalized : null;
|
|
6314
6706
|
}
|
|
6315
6707
|
function normalizeRoutingStrategy(value) {
|
|
@@ -6343,7 +6735,7 @@ function normalizeAccountPoolExposedModels(value, fallbackToDefault) {
|
|
|
6343
6735
|
const seen = /* @__PURE__ */ new Set();
|
|
6344
6736
|
const input = Array.isArray(value) ? value : [];
|
|
6345
6737
|
for (const entry of input) {
|
|
6346
|
-
const raw =
|
|
6738
|
+
const raw = asString4(entry);
|
|
6347
6739
|
const normalized = normalizeCodexModelSlug(raw) ?? raw;
|
|
6348
6740
|
if (!normalized || seen.has(normalized)) {
|
|
6349
6741
|
continue;
|
|
@@ -6459,8 +6851,8 @@ function normalizeSessionStatus(value) {
|
|
|
6459
6851
|
}
|
|
6460
6852
|
function normalizeApiKeyRecord(id, value) {
|
|
6461
6853
|
const record = asRecord2(value);
|
|
6462
|
-
const tokenHash =
|
|
6463
|
-
const tokenPreview =
|
|
6854
|
+
const tokenHash = asString4(record.tokenHash);
|
|
6855
|
+
const tokenPreview = asString4(record.tokenPreview);
|
|
6464
6856
|
const createdAt = normalizeIsoString(record.createdAt);
|
|
6465
6857
|
if (!tokenHash || !tokenPreview || !createdAt) {
|
|
6466
6858
|
return null;
|
|
@@ -6476,7 +6868,7 @@ function normalizeApiKeyRecord(id, value) {
|
|
|
6476
6868
|
}
|
|
6477
6869
|
function normalizeLegacySessionRecord(id, value) {
|
|
6478
6870
|
const record = asRecord2(value);
|
|
6479
|
-
const profileName =
|
|
6871
|
+
const profileName = asString4(record.profileName);
|
|
6480
6872
|
const createdAt = normalizeIsoString(record.createdAt);
|
|
6481
6873
|
const lastUsedAt = normalizeIsoString(record.lastUsedAt);
|
|
6482
6874
|
if (!profileName || !createdAt || !lastUsedAt) {
|
|
@@ -6486,16 +6878,16 @@ function normalizeLegacySessionRecord(id, value) {
|
|
|
6486
6878
|
return {
|
|
6487
6879
|
id,
|
|
6488
6880
|
affinityKind,
|
|
6489
|
-
affinityKey:
|
|
6881
|
+
affinityKey: asString4(record.affinityKey),
|
|
6490
6882
|
profileName,
|
|
6491
|
-
threadId:
|
|
6492
|
-
model:
|
|
6883
|
+
threadId: asString4(record.threadId) ?? id,
|
|
6884
|
+
model: asString4(record.model),
|
|
6493
6885
|
status: normalizeSessionStatus(record.status),
|
|
6494
|
-
lastError:
|
|
6886
|
+
lastError: asString4(record.lastError),
|
|
6495
6887
|
createdAt,
|
|
6496
6888
|
lastUsedAt,
|
|
6497
6889
|
expiresAt: normalizeIsoString(record.expiresAt),
|
|
6498
|
-
lastResponseId:
|
|
6890
|
+
lastResponseId: asString4(record.lastResponseId),
|
|
6499
6891
|
responseIds: normalizeStringArray(record.responseIds).slice(0, MAX_RESPONSE_IDS_PER_SESSION)
|
|
6500
6892
|
};
|
|
6501
6893
|
}
|
|
@@ -6517,7 +6909,7 @@ function normalizeLegacyStore(value) {
|
|
|
6517
6909
|
}
|
|
6518
6910
|
const responseIndex = {};
|
|
6519
6911
|
for (const [responseId, sessionId] of Object.entries(asRecord2(record.responseIndex))) {
|
|
6520
|
-
const normalizedSessionId =
|
|
6912
|
+
const normalizedSessionId = asString4(sessionId);
|
|
6521
6913
|
if (normalizedSessionId) {
|
|
6522
6914
|
responseIndex[responseId] = normalizedSessionId;
|
|
6523
6915
|
}
|
|
@@ -6532,7 +6924,7 @@ function normalizeLegacyStore(value) {
|
|
|
6532
6924
|
}
|
|
6533
6925
|
function normalizeSessionRecord(id, value) {
|
|
6534
6926
|
const record = asRecord2(value);
|
|
6535
|
-
const activeSegmentId =
|
|
6927
|
+
const activeSegmentId = asString4(record.activeSegmentId);
|
|
6536
6928
|
const createdAt = normalizeIsoString(record.createdAt);
|
|
6537
6929
|
const lastUsedAt = normalizeIsoString(record.lastUsedAt);
|
|
6538
6930
|
if (!activeSegmentId || !createdAt || !lastUsedAt) {
|
|
@@ -6542,25 +6934,25 @@ function normalizeSessionRecord(id, value) {
|
|
|
6542
6934
|
return {
|
|
6543
6935
|
id,
|
|
6544
6936
|
affinityKind,
|
|
6545
|
-
affinityKey:
|
|
6937
|
+
affinityKey: asString4(record.affinityKey),
|
|
6546
6938
|
activeSegmentId,
|
|
6547
6939
|
segmentIds: normalizeStringArray(record.segmentIds),
|
|
6548
|
-
model:
|
|
6940
|
+
model: asString4(record.model),
|
|
6549
6941
|
status: normalizeSessionStatus(record.status),
|
|
6550
|
-
lastError:
|
|
6942
|
+
lastError: asString4(record.lastError),
|
|
6551
6943
|
createdAt,
|
|
6552
6944
|
lastUsedAt,
|
|
6553
6945
|
expiresAt: normalizeIsoString(record.expiresAt),
|
|
6554
|
-
lastResponseId:
|
|
6946
|
+
lastResponseId: asString4(record.lastResponseId),
|
|
6555
6947
|
responseIds: normalizeStringArray(record.responseIds).slice(0, MAX_RESPONSE_IDS_PER_SESSION),
|
|
6556
6948
|
rolloverCount: asNumber(record.rolloverCount) ?? 0,
|
|
6557
|
-
lastRolloverReason:
|
|
6949
|
+
lastRolloverReason: asString4(record.lastRolloverReason)
|
|
6558
6950
|
};
|
|
6559
6951
|
}
|
|
6560
6952
|
function normalizeSegmentRecord(id, value) {
|
|
6561
6953
|
const record = asRecord2(value);
|
|
6562
|
-
const sessionId =
|
|
6563
|
-
const profileName =
|
|
6954
|
+
const sessionId = asString4(record.sessionId);
|
|
6955
|
+
const profileName = asString4(record.profileName);
|
|
6564
6956
|
const createdAt = normalizeIsoString(record.createdAt);
|
|
6565
6957
|
const lastUsedAt = normalizeIsoString(record.lastUsedAt);
|
|
6566
6958
|
if (!sessionId || !profileName || !createdAt || !lastUsedAt) {
|
|
@@ -6576,8 +6968,8 @@ function normalizeSegmentRecord(id, value) {
|
|
|
6576
6968
|
}
|
|
6577
6969
|
function normalizeResponseIndexRecord(value) {
|
|
6578
6970
|
const record = asRecord2(value);
|
|
6579
|
-
const sessionId =
|
|
6580
|
-
const segmentId =
|
|
6971
|
+
const sessionId = asString4(record.sessionId);
|
|
6972
|
+
const segmentId = asString4(record.segmentId);
|
|
6581
6973
|
const createdAt = normalizeIsoString(record.createdAt) ?? (/* @__PURE__ */ new Date(0)).toISOString();
|
|
6582
6974
|
if (!sessionId || !segmentId) {
|
|
6583
6975
|
return null;
|
|
@@ -7252,7 +7644,7 @@ async function handleAccountPoolCommand(args, version) {
|
|
|
7252
7644
|
params,
|
|
7253
7645
|
key: "accountPoolExposedModels",
|
|
7254
7646
|
defaultValues: DEFAULT_ACCOUNT_POOL_EXPOSED_MODELS,
|
|
7255
|
-
normalizeValue: (value) => normalizeCodexModelSlug(value) ??
|
|
7647
|
+
normalizeValue: (value) => normalizeCodexModelSlug(value) ?? asString4(value)
|
|
7256
7648
|
});
|
|
7257
7649
|
return;
|
|
7258
7650
|
case "reasoning":
|
|
@@ -8000,18 +8392,17 @@ async function assertProfileCreationAllowed(profileManager) {
|
|
|
8000
8392
|
|
|
8001
8393
|
// ../../packages/runtime-codex/src/codex/officialAppRestart.ts
|
|
8002
8394
|
var import_node_child_process7 = require("child_process");
|
|
8395
|
+
var import_node_crypto6 = require("crypto");
|
|
8003
8396
|
var import_node_fs8 = require("fs");
|
|
8004
8397
|
var import_node_os5 = require("os");
|
|
8005
8398
|
var import_node_path11 = __toESM(require("path"), 1);
|
|
8006
|
-
var RESTART_COOLDOWN_MS = 6e4;
|
|
8007
8399
|
var COMMAND_TIMEOUT_MS = 3e3;
|
|
8008
8400
|
var EXIT_WAIT_MS = 1e4;
|
|
8009
8401
|
var LAUNCH_WAIT_MS = 15e3;
|
|
8010
8402
|
var POLL_INTERVAL_MS = 250;
|
|
8011
8403
|
var APP_DISCOVERY_CACHE_TTL_MS = 6e4;
|
|
8012
8404
|
var APP_DISCOVERY_MISS_CACHE_TTL_MS = 5e3;
|
|
8013
|
-
var
|
|
8014
|
-
var lastRestartStartedAt = 0;
|
|
8405
|
+
var OFFICIAL_CODEX_ACTIVITY_LIMIT = 50;
|
|
8015
8406
|
var profileActionLock = Promise.resolve();
|
|
8016
8407
|
var appDiscoveryCache = null;
|
|
8017
8408
|
function logOfficialCodexRestart(level, message, context) {
|
|
@@ -8022,6 +8413,55 @@ function logOfficialCodexRestart(level, message, context) {
|
|
|
8022
8413
|
}
|
|
8023
8414
|
logger(`[official-codex-restart] ${message}`);
|
|
8024
8415
|
}
|
|
8416
|
+
function hashProfileKey(profileKey) {
|
|
8417
|
+
if (!profileKey) {
|
|
8418
|
+
return null;
|
|
8419
|
+
}
|
|
8420
|
+
return (0, import_node_crypto6.createHash)("sha256").update(profileKey).digest("hex").slice(0, 12);
|
|
8421
|
+
}
|
|
8422
|
+
async function recordOfficialCodexActivity(input) {
|
|
8423
|
+
const now = /* @__PURE__ */ new Date();
|
|
8424
|
+
const entry = {
|
|
8425
|
+
id: `${now.getTime().toString(36)}-${Math.random().toString(36).slice(2, 8)}`,
|
|
8426
|
+
at: now.toISOString(),
|
|
8427
|
+
kind: input.kind,
|
|
8428
|
+
status: input.status,
|
|
8429
|
+
reason: input.reason ?? null,
|
|
8430
|
+
decisionId: input.decisionId ?? null,
|
|
8431
|
+
profileName: input.profileName ?? null,
|
|
8432
|
+
sourceProfileName: input.sourceProfileName ?? null,
|
|
8433
|
+
targetProfileName: input.targetProfileName ?? null,
|
|
8434
|
+
remainingPercent: input.remainingPercent ?? null,
|
|
8435
|
+
threshold: input.threshold ?? null,
|
|
8436
|
+
snapshotAgeMs: input.snapshotAgeMs ?? null,
|
|
8437
|
+
snapshotSource: input.snapshotSource ?? null,
|
|
8438
|
+
phase: input.phase ?? null,
|
|
8439
|
+
pid: input.pid ?? null,
|
|
8440
|
+
profileKeyHash: input.profileKeyHash ?? hashProfileKey(input.profileKey),
|
|
8441
|
+
switchVerified: input.switchVerified ?? null,
|
|
8442
|
+
restartRequested: input.restartRequested ?? null,
|
|
8443
|
+
restartResult: input.restartResult ?? null,
|
|
8444
|
+
observedProfileName: input.observedProfileName ?? null,
|
|
8445
|
+
observedProfileKeyHash: input.observedProfileKeyHash ?? hashProfileKey(input.observedProfileKey),
|
|
8446
|
+
observedProfileMatchSource: input.observedProfileMatchSource ?? null
|
|
8447
|
+
};
|
|
8448
|
+
try {
|
|
8449
|
+
await updateAppState((state) => ({
|
|
8450
|
+
officialCodex: {
|
|
8451
|
+
activity: [...state.officialCodex.activity, entry].slice(
|
|
8452
|
+
-OFFICIAL_CODEX_ACTIVITY_LIMIT
|
|
8453
|
+
)
|
|
8454
|
+
}
|
|
8455
|
+
}));
|
|
8456
|
+
} catch (error) {
|
|
8457
|
+
logOfficialCodexRestart("warn", "Failed to record official Codex activity.", {
|
|
8458
|
+
kind: entry.kind,
|
|
8459
|
+
status: entry.status,
|
|
8460
|
+
profileKeyHash: entry.profileKeyHash,
|
|
8461
|
+
error: error instanceof Error ? error.message : String(error)
|
|
8462
|
+
});
|
|
8463
|
+
}
|
|
8464
|
+
}
|
|
8025
8465
|
function runCommand2(command, args, timeoutMs = COMMAND_TIMEOUT_MS) {
|
|
8026
8466
|
return new Promise((resolve) => {
|
|
8027
8467
|
const child = (0, import_node_child_process7.spawn)(command, args, {
|
|
@@ -8055,44 +8495,316 @@ function runCommand2(command, args, timeoutMs = COMMAND_TIMEOUT_MS) {
|
|
|
8055
8495
|
});
|
|
8056
8496
|
});
|
|
8057
8497
|
}
|
|
8058
|
-
|
|
8059
|
-
const
|
|
8060
|
-
|
|
8061
|
-
|
|
8498
|
+
function enqueueProfileAction(work) {
|
|
8499
|
+
const run = profileActionLock.then(work, work);
|
|
8500
|
+
profileActionLock = run.then(
|
|
8501
|
+
() => void 0,
|
|
8502
|
+
() => void 0
|
|
8503
|
+
);
|
|
8504
|
+
return run;
|
|
8505
|
+
}
|
|
8506
|
+
async function readProcessRows() {
|
|
8507
|
+
const result = await runCommand2(
|
|
8508
|
+
"/bin/ps",
|
|
8509
|
+
["-axo", "pid=,ppid=,lstart=,args="],
|
|
8510
|
+
2e3
|
|
8511
|
+
);
|
|
8512
|
+
if (result.code !== 0) {
|
|
8513
|
+
return [];
|
|
8062
8514
|
}
|
|
8063
|
-
|
|
8064
|
-
|
|
8065
|
-
|
|
8066
|
-
|
|
8067
|
-
|
|
8068
|
-
|
|
8069
|
-
|
|
8070
|
-
|
|
8515
|
+
return result.stdout.split(/\r?\n/).flatMap((line) => {
|
|
8516
|
+
const match = line.match(
|
|
8517
|
+
/^\s*(\d+)\s+(\d+)\s+([A-Z][a-z]{2}\s+[A-Z][a-z]{2}\s+\d+\s+\d+:\d+:\d+\s+\d{4})\s+(.+)$/
|
|
8518
|
+
);
|
|
8519
|
+
if (!match) {
|
|
8520
|
+
return [];
|
|
8521
|
+
}
|
|
8522
|
+
const pid = Number(match[1]);
|
|
8523
|
+
const ppid = Number(match[2]);
|
|
8524
|
+
const parsedStartedAt = Date.parse(match[3] ?? "");
|
|
8525
|
+
const startedAt = Number.isFinite(parsedStartedAt) ? parsedStartedAt : null;
|
|
8526
|
+
const args = match[4] ?? "";
|
|
8527
|
+
if (!Number.isInteger(pid) || !Number.isInteger(ppid) || !args) {
|
|
8528
|
+
return [];
|
|
8529
|
+
}
|
|
8530
|
+
return [{ pid, ppid, startedAt, args }];
|
|
8531
|
+
});
|
|
8532
|
+
}
|
|
8533
|
+
function getMainExecutablePath(candidate) {
|
|
8534
|
+
return import_node_path11.default.join(candidate.appPath, "Contents", "MacOS", candidate.executableName);
|
|
8535
|
+
}
|
|
8536
|
+
function isMainProcessRow(row, candidate) {
|
|
8537
|
+
return row.args.includes(getMainExecutablePath(candidate));
|
|
8538
|
+
}
|
|
8539
|
+
function findAppServerPid(rows, mainPid) {
|
|
8540
|
+
return rows.find(
|
|
8541
|
+
(row) => row.ppid === mainPid && row.args.includes("/Contents/Resources/codex app-server")
|
|
8542
|
+
)?.pid ?? null;
|
|
8543
|
+
}
|
|
8544
|
+
async function processMatchesProfileHome(pid, profileHome) {
|
|
8545
|
+
const result = await runCommand2(
|
|
8546
|
+
"/bin/ps",
|
|
8547
|
+
["eww", "-p", String(pid), "-o", "command="],
|
|
8548
|
+
2e3
|
|
8549
|
+
);
|
|
8071
8550
|
if (result.code !== 0) {
|
|
8072
|
-
return
|
|
8551
|
+
return false;
|
|
8073
8552
|
}
|
|
8074
|
-
|
|
8075
|
-
return bundleId.length > 0 ? bundleId : null;
|
|
8553
|
+
return result.stdout.includes(`CODEX_HOME=${profileHome}`) || result.stdout.includes(profileHome);
|
|
8076
8554
|
}
|
|
8077
|
-
async function
|
|
8078
|
-
const
|
|
8079
|
-
|
|
8080
|
-
|
|
8081
|
-
|
|
8555
|
+
async function findAppServerPidForProfile(rows, mainPid, profileHome) {
|
|
8556
|
+
const candidates = rows.filter(
|
|
8557
|
+
(row) => row.ppid === mainPid && row.args.includes("/Contents/Resources/codex app-server")
|
|
8558
|
+
);
|
|
8559
|
+
for (const row of candidates) {
|
|
8560
|
+
if (row.args.includes(profileHome) || await processMatchesProfileHome(row.pid, profileHome)) {
|
|
8561
|
+
return row.pid;
|
|
8562
|
+
}
|
|
8082
8563
|
}
|
|
8083
|
-
|
|
8084
|
-
|
|
8085
|
-
|
|
8564
|
+
return null;
|
|
8565
|
+
}
|
|
8566
|
+
async function describeUnmanagedProfileHint(appServerPid) {
|
|
8567
|
+
if (!appServerPid) {
|
|
8568
|
+
return {};
|
|
8086
8569
|
}
|
|
8087
|
-
|
|
8088
|
-
|
|
8089
|
-
|
|
8090
|
-
|
|
8091
|
-
["kMDItemFSName == 'Codex.app'"],
|
|
8092
|
-
1500
|
|
8570
|
+
const result = await runCommand2(
|
|
8571
|
+
"/bin/ps",
|
|
8572
|
+
["eww", "-p", String(appServerPid), "-o", "command="],
|
|
8573
|
+
2e3
|
|
8093
8574
|
);
|
|
8094
|
-
if (
|
|
8095
|
-
|
|
8575
|
+
if (result.code !== 0) {
|
|
8576
|
+
return {};
|
|
8577
|
+
}
|
|
8578
|
+
const telemetryMatch = result.stdout.match(
|
|
8579
|
+
/CODEX_TELEMETRY_LABEL=codexuse-profile-([^\s]+)/
|
|
8580
|
+
);
|
|
8581
|
+
if (telemetryMatch?.[1]) {
|
|
8582
|
+
const encodedProfileName = telemetryMatch[1];
|
|
8583
|
+
let profileName = encodedProfileName;
|
|
8584
|
+
try {
|
|
8585
|
+
profileName = decodeURIComponent(encodedProfileName);
|
|
8586
|
+
} catch {
|
|
8587
|
+
profileName = encodedProfileName;
|
|
8588
|
+
}
|
|
8589
|
+
return {
|
|
8590
|
+
profileName,
|
|
8591
|
+
profileMatchSource: "telemetry-label"
|
|
8592
|
+
};
|
|
8593
|
+
}
|
|
8594
|
+
const profileHomeMatch = result.stdout.match(/profile-homes\/([^\s]+)/);
|
|
8595
|
+
if (profileHomeMatch?.[1]) {
|
|
8596
|
+
return {
|
|
8597
|
+
profileName: profileHomeMatch[1],
|
|
8598
|
+
profileMatchSource: "profile-home"
|
|
8599
|
+
};
|
|
8600
|
+
}
|
|
8601
|
+
return {};
|
|
8602
|
+
}
|
|
8603
|
+
function getDescendantPids(rootPid, rows) {
|
|
8604
|
+
const descendants = [];
|
|
8605
|
+
const queue = [rootPid];
|
|
8606
|
+
const seen = /* @__PURE__ */ new Set();
|
|
8607
|
+
while (queue.length > 0) {
|
|
8608
|
+
const current = queue.shift();
|
|
8609
|
+
if (seen.has(current)) {
|
|
8610
|
+
continue;
|
|
8611
|
+
}
|
|
8612
|
+
seen.add(current);
|
|
8613
|
+
for (const row of rows) {
|
|
8614
|
+
if (row.ppid !== current || seen.has(row.pid)) {
|
|
8615
|
+
continue;
|
|
8616
|
+
}
|
|
8617
|
+
descendants.push(row.pid);
|
|
8618
|
+
queue.push(row.pid);
|
|
8619
|
+
}
|
|
8620
|
+
}
|
|
8621
|
+
return descendants;
|
|
8622
|
+
}
|
|
8623
|
+
async function waitForNewMainPid(candidate, previousPids) {
|
|
8624
|
+
const deadline = Date.now() + LAUNCH_WAIT_MS;
|
|
8625
|
+
while (Date.now() < deadline) {
|
|
8626
|
+
const rows = await readProcessRows();
|
|
8627
|
+
const pid = rows.find((row) => isMainProcessRow(row, candidate) && !previousPids.has(row.pid))?.pid ?? null;
|
|
8628
|
+
if (pid !== null) {
|
|
8629
|
+
return pid;
|
|
8630
|
+
}
|
|
8631
|
+
await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));
|
|
8632
|
+
}
|
|
8633
|
+
return null;
|
|
8634
|
+
}
|
|
8635
|
+
async function waitForMainPid(candidate, pid, timeoutMs) {
|
|
8636
|
+
const deadline = Date.now() + timeoutMs;
|
|
8637
|
+
while (Date.now() < deadline) {
|
|
8638
|
+
const rows = await readProcessRows();
|
|
8639
|
+
if (rows.some((row) => row.pid === pid && isMainProcessRow(row, candidate))) {
|
|
8640
|
+
return true;
|
|
8641
|
+
}
|
|
8642
|
+
await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));
|
|
8643
|
+
}
|
|
8644
|
+
return false;
|
|
8645
|
+
}
|
|
8646
|
+
async function waitForAppServerPid(mainPid, profileHome) {
|
|
8647
|
+
const deadline = Date.now() + LAUNCH_WAIT_MS;
|
|
8648
|
+
while (Date.now() < deadline) {
|
|
8649
|
+
const pid = await findAppServerPidForProfile(
|
|
8650
|
+
await readProcessRows(),
|
|
8651
|
+
mainPid,
|
|
8652
|
+
profileHome
|
|
8653
|
+
);
|
|
8654
|
+
if (pid !== null) {
|
|
8655
|
+
return pid;
|
|
8656
|
+
}
|
|
8657
|
+
await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));
|
|
8658
|
+
}
|
|
8659
|
+
return null;
|
|
8660
|
+
}
|
|
8661
|
+
async function waitForMainPidExit(pid, timeoutMs) {
|
|
8662
|
+
const deadline = Date.now() + timeoutMs;
|
|
8663
|
+
while (Date.now() < deadline) {
|
|
8664
|
+
const rows = await readProcessRows();
|
|
8665
|
+
if (!rows.some((row) => row.pid === pid)) {
|
|
8666
|
+
return true;
|
|
8667
|
+
}
|
|
8668
|
+
await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));
|
|
8669
|
+
}
|
|
8670
|
+
return false;
|
|
8671
|
+
}
|
|
8672
|
+
function managedInstanceToPayload(instance, running, appServerPid = instance.appServerPid, startedAt = null) {
|
|
8673
|
+
const runningStartedAt = startedAt ?? instance.launchedAt;
|
|
8674
|
+
return {
|
|
8675
|
+
profileName: instance.profileName,
|
|
8676
|
+
profileKey: instance.profileKey,
|
|
8677
|
+
appPath: instance.appPath,
|
|
8678
|
+
bundleId: instance.bundleId,
|
|
8679
|
+
pid: running ? instance.pid : null,
|
|
8680
|
+
appServerPid: running ? appServerPid : null,
|
|
8681
|
+
running,
|
|
8682
|
+
startedAt: running ? toIso(runningStartedAt) : null,
|
|
8683
|
+
uptimeMs: running && typeof runningStartedAt === "number" ? Math.max(0, Date.now() - runningStartedAt) : null,
|
|
8684
|
+
launchedAt: toIso(instance.launchedAt),
|
|
8685
|
+
lastVerifiedAt: toIso(instance.lastVerifiedAt),
|
|
8686
|
+
lastStatus: instance.lastStatus,
|
|
8687
|
+
lastError: instance.lastError
|
|
8688
|
+
};
|
|
8689
|
+
}
|
|
8690
|
+
async function patchManagedInstance(instance) {
|
|
8691
|
+
await patchAppState({
|
|
8692
|
+
officialCodex: {
|
|
8693
|
+
instancesByProfileName: {
|
|
8694
|
+
[instance.profileName]: instance
|
|
8695
|
+
}
|
|
8696
|
+
}
|
|
8697
|
+
});
|
|
8698
|
+
}
|
|
8699
|
+
async function readManagedInstance(profileName) {
|
|
8700
|
+
const state = await getAppState();
|
|
8701
|
+
return state.officialCodex.instancesByProfileName[profileName] ?? null;
|
|
8702
|
+
}
|
|
8703
|
+
async function resolveInstanceRuntimeState(args) {
|
|
8704
|
+
const pid = args.instance.pid;
|
|
8705
|
+
if (!pid) {
|
|
8706
|
+
return { running: false, appServerPid: null, startedAt: null };
|
|
8707
|
+
}
|
|
8708
|
+
const mainRow = args.rows.find((row) => row.pid === pid);
|
|
8709
|
+
if (!mainRow || !isMainProcessRow(mainRow, args.candidate)) {
|
|
8710
|
+
return { running: false, appServerPid: null, startedAt: null };
|
|
8711
|
+
}
|
|
8712
|
+
const appServerPid = args.instance.profileHome ? await findAppServerPidForProfile(args.rows, pid, args.instance.profileHome) : findAppServerPid(args.rows, pid);
|
|
8713
|
+
if (args.instance.profileHome && appServerPid === null) {
|
|
8714
|
+
return { running: false, appServerPid: null, startedAt: null };
|
|
8715
|
+
}
|
|
8716
|
+
return {
|
|
8717
|
+
running: true,
|
|
8718
|
+
appServerPid,
|
|
8719
|
+
startedAt: mainRow.startedAt
|
|
8720
|
+
};
|
|
8721
|
+
}
|
|
8722
|
+
async function openCodexWithProfileHome(candidate, profileHome, profileName, previousPids) {
|
|
8723
|
+
const executablePath = getMainExecutablePath(candidate);
|
|
8724
|
+
if (!(0, import_node_fs8.existsSync)(executablePath)) {
|
|
8725
|
+
return { opened: false, pid: null };
|
|
8726
|
+
}
|
|
8727
|
+
const telemetryLabel = `codexuse-profile-${encodeURIComponent(profileName)}`;
|
|
8728
|
+
let child;
|
|
8729
|
+
try {
|
|
8730
|
+
child = (0, import_node_child_process7.spawn)(executablePath, [], {
|
|
8731
|
+
detached: true,
|
|
8732
|
+
env: {
|
|
8733
|
+
...process.env,
|
|
8734
|
+
CODEX_HOME: profileHome,
|
|
8735
|
+
CODEX_TELEMETRY_LABEL: telemetryLabel
|
|
8736
|
+
},
|
|
8737
|
+
stdio: "ignore"
|
|
8738
|
+
});
|
|
8739
|
+
} catch {
|
|
8740
|
+
return { opened: false, pid: null };
|
|
8741
|
+
}
|
|
8742
|
+
const childPid = child.pid ?? null;
|
|
8743
|
+
child.unref();
|
|
8744
|
+
const spawnError = await new Promise((resolve) => {
|
|
8745
|
+
let settled = false;
|
|
8746
|
+
const settle = (failed) => {
|
|
8747
|
+
if (settled) {
|
|
8748
|
+
return;
|
|
8749
|
+
}
|
|
8750
|
+
settled = true;
|
|
8751
|
+
resolve(failed);
|
|
8752
|
+
};
|
|
8753
|
+
child.once("error", () => settle(true));
|
|
8754
|
+
setTimeout(() => settle(false), POLL_INTERVAL_MS);
|
|
8755
|
+
});
|
|
8756
|
+
if (spawnError) {
|
|
8757
|
+
return { opened: false, pid: null };
|
|
8758
|
+
}
|
|
8759
|
+
if (childPid !== null) {
|
|
8760
|
+
const verified = await waitForMainPid(candidate, childPid, 2e3);
|
|
8761
|
+
if (verified) {
|
|
8762
|
+
return { opened: true, pid: childPid };
|
|
8763
|
+
}
|
|
8764
|
+
}
|
|
8765
|
+
return {
|
|
8766
|
+
opened: true,
|
|
8767
|
+
pid: await waitForNewMainPid(candidate, previousPids)
|
|
8768
|
+
};
|
|
8769
|
+
}
|
|
8770
|
+
async function readBundleString(appPath, key) {
|
|
8771
|
+
const plistPath = import_node_path11.default.join(appPath, "Contents", "Info.plist");
|
|
8772
|
+
if (!(0, import_node_fs8.existsSync)(plistPath)) {
|
|
8773
|
+
return null;
|
|
8774
|
+
}
|
|
8775
|
+
const result = await runCommand2("/usr/bin/plutil", [
|
|
8776
|
+
"-extract",
|
|
8777
|
+
key,
|
|
8778
|
+
"raw",
|
|
8779
|
+
"-o",
|
|
8780
|
+
"-",
|
|
8781
|
+
plistPath
|
|
8782
|
+
]);
|
|
8783
|
+
if (result.code !== 0) {
|
|
8784
|
+
return null;
|
|
8785
|
+
}
|
|
8786
|
+
const bundleId = result.stdout.trim();
|
|
8787
|
+
return bundleId.length > 0 ? bundleId : null;
|
|
8788
|
+
}
|
|
8789
|
+
async function discoverCodexAppCandidates() {
|
|
8790
|
+
const now = Date.now();
|
|
8791
|
+
const envPath = process.env.CODEXUSE_OFFICIAL_CODEX_APP_PATH?.trim() || null;
|
|
8792
|
+
if (appDiscoveryCache && appDiscoveryCache.envPath === envPath && appDiscoveryCache.expiresAt > now) {
|
|
8793
|
+
return appDiscoveryCache.candidates;
|
|
8794
|
+
}
|
|
8795
|
+
const rawPaths = /* @__PURE__ */ new Set();
|
|
8796
|
+
if (envPath) {
|
|
8797
|
+
rawPaths.add(envPath);
|
|
8798
|
+
}
|
|
8799
|
+
rawPaths.add("/Applications/Codex.app");
|
|
8800
|
+
rawPaths.add(import_node_path11.default.join((0, import_node_os5.homedir)(), "Applications", "Codex.app"));
|
|
8801
|
+
const mdfind = await runCommand2(
|
|
8802
|
+
"/usr/bin/mdfind",
|
|
8803
|
+
["kMDItemFSName == 'Codex.app'"],
|
|
8804
|
+
1500
|
|
8805
|
+
);
|
|
8806
|
+
if (mdfind.code === 0) {
|
|
8807
|
+
for (const line of mdfind.stdout.split(/\r?\n/)) {
|
|
8096
8808
|
const trimmed = line.trim();
|
|
8097
8809
|
if (trimmed.endsWith("/Codex.app")) {
|
|
8098
8810
|
rawPaths.add(trimmed);
|
|
@@ -8187,17 +8899,6 @@ async function resolveCodexAppTarget() {
|
|
|
8187
8899
|
]);
|
|
8188
8900
|
return { candidate: fallback, runningPids, mainPids };
|
|
8189
8901
|
}
|
|
8190
|
-
async function waitForCodexExit(candidate, timeoutMs) {
|
|
8191
|
-
const deadline = Date.now() + timeoutMs;
|
|
8192
|
-
while (Date.now() < deadline) {
|
|
8193
|
-
const pids = await getRunningCodexPids(candidate);
|
|
8194
|
-
if (pids.length === 0) {
|
|
8195
|
-
return true;
|
|
8196
|
-
}
|
|
8197
|
-
await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));
|
|
8198
|
-
}
|
|
8199
|
-
return false;
|
|
8200
|
-
}
|
|
8201
8902
|
async function signalPids(pids, signal) {
|
|
8202
8903
|
const signaled = [];
|
|
8203
8904
|
for (const pid of pids) {
|
|
@@ -8209,25 +8910,8 @@ async function signalPids(pids, signal) {
|
|
|
8209
8910
|
}
|
|
8210
8911
|
return signaled;
|
|
8211
8912
|
}
|
|
8212
|
-
|
|
8213
|
-
|
|
8214
|
-
if (byBundle.code === 0) {
|
|
8215
|
-
return true;
|
|
8216
|
-
}
|
|
8217
|
-
const byPath = await runCommand2("/usr/bin/open", [candidate.appPath]);
|
|
8218
|
-
return byPath.code === 0;
|
|
8219
|
-
}
|
|
8220
|
-
async function waitForCodexLaunch(candidate) {
|
|
8221
|
-
const deadline = Date.now() + LAUNCH_WAIT_MS;
|
|
8222
|
-
while (Date.now() < deadline) {
|
|
8223
|
-
const pids = await getRunningCodexMainPids(candidate);
|
|
8224
|
-
const pid = pids[0] ?? null;
|
|
8225
|
-
if (pid !== null) {
|
|
8226
|
-
return pid;
|
|
8227
|
-
}
|
|
8228
|
-
await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));
|
|
8229
|
-
}
|
|
8230
|
-
return null;
|
|
8913
|
+
function toIso(value) {
|
|
8914
|
+
return typeof value === "number" && Number.isFinite(value) ? new Date(value).toISOString() : null;
|
|
8231
8915
|
}
|
|
8232
8916
|
async function rememberProfileSwitch(profileKey) {
|
|
8233
8917
|
await patchAppState({
|
|
@@ -8250,157 +8934,360 @@ async function rememberRestartResult(args) {
|
|
|
8250
8934
|
}
|
|
8251
8935
|
});
|
|
8252
8936
|
}
|
|
8253
|
-
|
|
8937
|
+
function recordOfficialCodexRestartResult(args) {
|
|
8938
|
+
return rememberRestartResult(args);
|
|
8939
|
+
}
|
|
8940
|
+
function recordOfficialCodexProfileSwitch(profileKey) {
|
|
8941
|
+
return rememberProfileSwitch(profileKey);
|
|
8942
|
+
}
|
|
8943
|
+
async function getOfficialCodexProfileInstances() {
|
|
8254
8944
|
if (process.platform !== "darwin") {
|
|
8255
|
-
|
|
8256
|
-
|
|
8257
|
-
|
|
8258
|
-
|
|
8259
|
-
|
|
8260
|
-
|
|
8261
|
-
|
|
8262
|
-
|
|
8263
|
-
profileKey: options.currentProfileKey
|
|
8264
|
-
});
|
|
8265
|
-
return { status: "skipped", reason: "cooldown" };
|
|
8945
|
+
return {
|
|
8946
|
+
state: "unsupported",
|
|
8947
|
+
appPath: null,
|
|
8948
|
+
bundleId: null,
|
|
8949
|
+
version: null,
|
|
8950
|
+
instances: [],
|
|
8951
|
+
unmanaged: []
|
|
8952
|
+
};
|
|
8266
8953
|
}
|
|
8267
|
-
const { candidate,
|
|
8954
|
+
const { candidate, mainPids } = await resolveCodexAppTarget();
|
|
8268
8955
|
if (!candidate) {
|
|
8269
|
-
|
|
8270
|
-
|
|
8271
|
-
|
|
8272
|
-
|
|
8956
|
+
return {
|
|
8957
|
+
state: "not-found",
|
|
8958
|
+
appPath: null,
|
|
8959
|
+
bundleId: null,
|
|
8960
|
+
version: null,
|
|
8961
|
+
instances: [],
|
|
8962
|
+
unmanaged: []
|
|
8963
|
+
};
|
|
8964
|
+
}
|
|
8965
|
+
const [state, rows] = await Promise.all([getAppState(), readProcessRows()]);
|
|
8966
|
+
const managed = [];
|
|
8967
|
+
for (const instance of Object.values(state.officialCodex.instancesByProfileName)) {
|
|
8968
|
+
const runtime = await resolveInstanceRuntimeState({ instance, candidate, rows });
|
|
8969
|
+
managed.push(
|
|
8970
|
+
managedInstanceToPayload(
|
|
8971
|
+
instance,
|
|
8972
|
+
runtime.running,
|
|
8973
|
+
runtime.appServerPid,
|
|
8974
|
+
runtime.startedAt
|
|
8975
|
+
)
|
|
8976
|
+
);
|
|
8977
|
+
}
|
|
8978
|
+
managed.sort((a, b) => a.profileName.localeCompare(b.profileName));
|
|
8979
|
+
const managedPids = new Set(
|
|
8980
|
+
managed.flatMap((entry) => entry.running && entry.pid ? [entry.pid] : [])
|
|
8981
|
+
);
|
|
8982
|
+
const unmanaged = [];
|
|
8983
|
+
for (const pid of mainPids.filter((entry) => !managedPids.has(entry))) {
|
|
8984
|
+
const appServerPid = findAppServerPid(rows, pid);
|
|
8985
|
+
const startedAt = rows.find((row) => row.pid === pid)?.startedAt ?? null;
|
|
8986
|
+
unmanaged.push({
|
|
8987
|
+
pid,
|
|
8988
|
+
appServerPid,
|
|
8989
|
+
startedAt: toIso(startedAt),
|
|
8990
|
+
uptimeMs: typeof startedAt === "number" ? Math.max(0, Date.now() - startedAt) : null,
|
|
8991
|
+
...await describeUnmanagedProfileHint(appServerPid)
|
|
8273
8992
|
});
|
|
8274
|
-
return { status: "skipped", reason: "official-codex-app-not-found" };
|
|
8275
8993
|
}
|
|
8276
|
-
|
|
8277
|
-
|
|
8278
|
-
|
|
8994
|
+
return {
|
|
8995
|
+
state: "found",
|
|
8996
|
+
appPath: candidate.appPath,
|
|
8997
|
+
bundleId: candidate.bundleId,
|
|
8998
|
+
version: candidate.version,
|
|
8999
|
+
instances: managed,
|
|
9000
|
+
unmanaged
|
|
9001
|
+
};
|
|
9002
|
+
}
|
|
9003
|
+
function launchOfficialCodexProfileInstance(options) {
|
|
9004
|
+
return enqueueProfileAction(() => launchOfficialCodexProfileInstanceOnce(options));
|
|
9005
|
+
}
|
|
9006
|
+
async function launchOfficialCodexProfileInstanceOnce(options) {
|
|
9007
|
+
if (process.platform !== "darwin") {
|
|
9008
|
+
return {
|
|
8279
9009
|
status: "skipped",
|
|
8280
|
-
|
|
8281
|
-
|
|
8282
|
-
|
|
8283
|
-
|
|
9010
|
+
profileName: options.profileName,
|
|
9011
|
+
instance: null,
|
|
9012
|
+
reason: "unsupported-platform"
|
|
9013
|
+
};
|
|
8284
9014
|
}
|
|
8285
|
-
|
|
8286
|
-
|
|
9015
|
+
const { candidate, mainPids } = await resolveCodexAppTarget();
|
|
9016
|
+
if (!candidate) {
|
|
9017
|
+
return {
|
|
9018
|
+
status: "skipped",
|
|
9019
|
+
profileName: options.profileName,
|
|
9020
|
+
instance: null,
|
|
9021
|
+
reason: "official-codex-app-not-found"
|
|
9022
|
+
};
|
|
8287
9023
|
}
|
|
8288
|
-
|
|
8289
|
-
|
|
8290
|
-
|
|
8291
|
-
|
|
8292
|
-
|
|
8293
|
-
|
|
8294
|
-
|
|
8295
|
-
|
|
8296
|
-
|
|
8297
|
-
|
|
8298
|
-
|
|
8299
|
-
|
|
8300
|
-
|
|
8301
|
-
|
|
8302
|
-
|
|
8303
|
-
|
|
8304
|
-
|
|
8305
|
-
|
|
8306
|
-
|
|
8307
|
-
|
|
8308
|
-
|
|
8309
|
-
|
|
8310
|
-
|
|
8311
|
-
|
|
8312
|
-
const failed = {
|
|
8313
|
-
status: "failed",
|
|
8314
|
-
appPath: candidate.appPath,
|
|
8315
|
-
bundleId: candidate.bundleId,
|
|
8316
|
-
reason: "force-quit-timeout",
|
|
8317
|
-
phase: "quit"
|
|
9024
|
+
const existing = await readManagedInstance(options.profileName);
|
|
9025
|
+
if (existing) {
|
|
9026
|
+
const rows = await readProcessRows();
|
|
9027
|
+
const runtime = await resolveInstanceRuntimeState({ instance: existing, candidate, rows });
|
|
9028
|
+
if (runtime.running) {
|
|
9029
|
+
const verified = {
|
|
9030
|
+
...existing,
|
|
9031
|
+
profileHome: existing.profileHome ?? options.profileHome,
|
|
9032
|
+
appServerPid: runtime.appServerPid,
|
|
9033
|
+
lastVerifiedAt: Date.now(),
|
|
9034
|
+
lastStatus: "already-running",
|
|
9035
|
+
lastError: null
|
|
9036
|
+
};
|
|
9037
|
+
await patchManagedInstance(verified);
|
|
9038
|
+
return {
|
|
9039
|
+
status: "already-running",
|
|
9040
|
+
profileName: options.profileName,
|
|
9041
|
+
instance: managedInstanceToPayload(
|
|
9042
|
+
verified,
|
|
9043
|
+
true,
|
|
9044
|
+
runtime.appServerPid,
|
|
9045
|
+
runtime.startedAt
|
|
9046
|
+
),
|
|
9047
|
+
reason: null
|
|
8318
9048
|
};
|
|
8319
|
-
await rememberRestartResult({
|
|
8320
|
-
status: failed.status,
|
|
8321
|
-
reason: failed.reason,
|
|
8322
|
-
profileKey: options.currentProfileKey
|
|
8323
|
-
});
|
|
8324
|
-
return failed;
|
|
8325
9049
|
}
|
|
8326
|
-
logOfficialCodexRestart("info", "Official Codex exited after force kill.", {
|
|
8327
|
-
appPath: candidate.appPath,
|
|
8328
|
-
bundleId: candidate.bundleId,
|
|
8329
|
-
source: options.source
|
|
8330
|
-
});
|
|
8331
9050
|
}
|
|
8332
|
-
const
|
|
8333
|
-
|
|
9051
|
+
const launch = await openCodexWithProfileHome(
|
|
9052
|
+
candidate,
|
|
9053
|
+
options.profileHome,
|
|
9054
|
+
options.profileName,
|
|
9055
|
+
new Set(mainPids)
|
|
9056
|
+
);
|
|
9057
|
+
if (!launch.opened) {
|
|
8334
9058
|
const failed = {
|
|
8335
|
-
|
|
9059
|
+
profileName: options.profileName,
|
|
9060
|
+
profileKey: options.profileKey,
|
|
9061
|
+
profileHome: options.profileHome,
|
|
8336
9062
|
appPath: candidate.appPath,
|
|
8337
9063
|
bundleId: candidate.bundleId,
|
|
8338
|
-
|
|
8339
|
-
|
|
9064
|
+
pid: null,
|
|
9065
|
+
appServerPid: null,
|
|
9066
|
+
launchedAt: null,
|
|
9067
|
+
lastVerifiedAt: null,
|
|
9068
|
+
lastStatus: "failed",
|
|
9069
|
+
lastError: "open-failed"
|
|
9070
|
+
};
|
|
9071
|
+
await patchManagedInstance(failed);
|
|
9072
|
+
return {
|
|
9073
|
+
status: "failed",
|
|
9074
|
+
profileName: options.profileName,
|
|
9075
|
+
instance: managedInstanceToPayload(failed, false),
|
|
9076
|
+
reason: "open-failed"
|
|
8340
9077
|
};
|
|
8341
|
-
await rememberRestartResult({
|
|
8342
|
-
status: failed.status,
|
|
8343
|
-
reason: failed.reason,
|
|
8344
|
-
profileKey: options.currentProfileKey
|
|
8345
|
-
});
|
|
8346
|
-
return failed;
|
|
8347
9078
|
}
|
|
8348
|
-
const launchedPid =
|
|
9079
|
+
const launchedPid = launch.pid;
|
|
8349
9080
|
if (launchedPid === null) {
|
|
8350
|
-
|
|
9081
|
+
const failed = {
|
|
9082
|
+
profileName: options.profileName,
|
|
9083
|
+
profileKey: options.profileKey,
|
|
9084
|
+
profileHome: options.profileHome,
|
|
8351
9085
|
appPath: candidate.appPath,
|
|
8352
9086
|
bundleId: candidate.bundleId,
|
|
8353
|
-
|
|
8354
|
-
|
|
8355
|
-
|
|
9087
|
+
pid: null,
|
|
9088
|
+
appServerPid: null,
|
|
9089
|
+
launchedAt: null,
|
|
9090
|
+
lastVerifiedAt: null,
|
|
9091
|
+
lastStatus: "failed",
|
|
9092
|
+
lastError: "launch-timeout"
|
|
9093
|
+
};
|
|
9094
|
+
await patchManagedInstance(failed);
|
|
9095
|
+
return {
|
|
8356
9096
|
status: "failed",
|
|
9097
|
+
profileName: options.profileName,
|
|
9098
|
+
instance: managedInstanceToPayload(failed, false),
|
|
9099
|
+
reason: "launch-timeout"
|
|
9100
|
+
};
|
|
9101
|
+
}
|
|
9102
|
+
const appServerPid = await waitForAppServerPid(
|
|
9103
|
+
launchedPid,
|
|
9104
|
+
options.profileHome
|
|
9105
|
+
);
|
|
9106
|
+
if (appServerPid === null) {
|
|
9107
|
+
const failed = {
|
|
9108
|
+
profileName: options.profileName,
|
|
9109
|
+
profileKey: options.profileKey,
|
|
9110
|
+
profileHome: options.profileHome,
|
|
8357
9111
|
appPath: candidate.appPath,
|
|
8358
9112
|
bundleId: candidate.bundleId,
|
|
8359
|
-
|
|
8360
|
-
|
|
9113
|
+
pid: null,
|
|
9114
|
+
appServerPid: null,
|
|
9115
|
+
launchedAt: null,
|
|
9116
|
+
lastVerifiedAt: Date.now(),
|
|
9117
|
+
lastStatus: "failed",
|
|
9118
|
+
lastError: "app-server-not-verified"
|
|
9119
|
+
};
|
|
9120
|
+
await patchManagedInstance(failed);
|
|
9121
|
+
return {
|
|
9122
|
+
status: "failed",
|
|
9123
|
+
profileName: options.profileName,
|
|
9124
|
+
instance: managedInstanceToPayload(failed, false),
|
|
9125
|
+
reason: "app-server-not-verified"
|
|
8361
9126
|
};
|
|
8362
|
-
await rememberRestartResult({
|
|
8363
|
-
status: failed.status,
|
|
8364
|
-
reason: failed.reason,
|
|
8365
|
-
profileKey: options.currentProfileKey
|
|
8366
|
-
});
|
|
8367
|
-
return failed;
|
|
8368
9127
|
}
|
|
8369
|
-
const
|
|
8370
|
-
|
|
9128
|
+
const now = Date.now();
|
|
9129
|
+
const instance = {
|
|
9130
|
+
profileName: options.profileName,
|
|
9131
|
+
profileKey: options.profileKey,
|
|
9132
|
+
profileHome: options.profileHome,
|
|
8371
9133
|
appPath: candidate.appPath,
|
|
8372
9134
|
bundleId: candidate.bundleId,
|
|
8373
|
-
|
|
8374
|
-
|
|
8375
|
-
|
|
8376
|
-
|
|
8377
|
-
|
|
8378
|
-
|
|
8379
|
-
|
|
8380
|
-
|
|
8381
|
-
});
|
|
9135
|
+
pid: launchedPid,
|
|
9136
|
+
appServerPid,
|
|
9137
|
+
launchedAt: now,
|
|
9138
|
+
lastVerifiedAt: now,
|
|
9139
|
+
lastStatus: "started",
|
|
9140
|
+
lastError: null
|
|
9141
|
+
};
|
|
9142
|
+
await patchManagedInstance(instance);
|
|
8382
9143
|
return {
|
|
8383
|
-
status,
|
|
8384
|
-
|
|
8385
|
-
|
|
8386
|
-
|
|
9144
|
+
status: "started",
|
|
9145
|
+
profileName: options.profileName,
|
|
9146
|
+
instance: managedInstanceToPayload(instance, true, appServerPid),
|
|
9147
|
+
reason: null
|
|
8387
9148
|
};
|
|
8388
9149
|
}
|
|
8389
|
-
function
|
|
8390
|
-
|
|
8391
|
-
|
|
8392
|
-
|
|
8393
|
-
|
|
8394
|
-
|
|
9150
|
+
async function stopOfficialCodexProfileInstanceOnce(profileName) {
|
|
9151
|
+
const existing = await readManagedInstance(profileName);
|
|
9152
|
+
if (!existing) {
|
|
9153
|
+
return {
|
|
9154
|
+
status: "not-running",
|
|
9155
|
+
profileName,
|
|
9156
|
+
instance: null,
|
|
9157
|
+
reason: "not-managed"
|
|
9158
|
+
};
|
|
9159
|
+
}
|
|
9160
|
+
const { candidate } = await resolveCodexAppTarget();
|
|
9161
|
+
if (!candidate) {
|
|
9162
|
+
const stopped2 = {
|
|
9163
|
+
...existing,
|
|
9164
|
+
pid: null,
|
|
9165
|
+
appServerPid: null,
|
|
9166
|
+
lastVerifiedAt: Date.now(),
|
|
9167
|
+
lastStatus: "not-running",
|
|
9168
|
+
lastError: "official-codex-app-not-found"
|
|
9169
|
+
};
|
|
9170
|
+
await patchManagedInstance(stopped2);
|
|
9171
|
+
return {
|
|
9172
|
+
status: "not-running",
|
|
9173
|
+
profileName,
|
|
9174
|
+
instance: managedInstanceToPayload(stopped2, false),
|
|
9175
|
+
reason: "official-codex-app-not-found"
|
|
9176
|
+
};
|
|
9177
|
+
}
|
|
9178
|
+
const rows = await readProcessRows();
|
|
9179
|
+
const runtime = await resolveInstanceRuntimeState({ instance: existing, candidate, rows });
|
|
9180
|
+
if (!runtime.running || !existing.pid) {
|
|
9181
|
+
const stopped2 = {
|
|
9182
|
+
...existing,
|
|
9183
|
+
pid: null,
|
|
9184
|
+
appServerPid: null,
|
|
9185
|
+
lastVerifiedAt: Date.now(),
|
|
9186
|
+
lastStatus: "not-running",
|
|
9187
|
+
lastError: null
|
|
9188
|
+
};
|
|
9189
|
+
await patchManagedInstance(stopped2);
|
|
9190
|
+
return {
|
|
9191
|
+
status: "not-running",
|
|
9192
|
+
profileName,
|
|
9193
|
+
instance: managedInstanceToPayload(stopped2, false),
|
|
9194
|
+
reason: null
|
|
9195
|
+
};
|
|
8395
9196
|
}
|
|
8396
|
-
|
|
8397
|
-
|
|
8398
|
-
|
|
8399
|
-
|
|
8400
|
-
|
|
8401
|
-
|
|
9197
|
+
const tree = [existing.pid, ...getDescendantPids(existing.pid, rows)].filter((pid, index, all) => all.indexOf(pid) === index).sort((a, b) => b - a);
|
|
9198
|
+
await signalPids(tree, "SIGTERM");
|
|
9199
|
+
const exited = await waitForMainPidExit(existing.pid, 5e3);
|
|
9200
|
+
if (!exited) {
|
|
9201
|
+
await signalPids(tree, "SIGKILL");
|
|
9202
|
+
await waitForMainPidExit(existing.pid, EXIT_WAIT_MS);
|
|
9203
|
+
}
|
|
9204
|
+
const stillRunning = (await readProcessRows()).some((row) => row.pid === existing.pid);
|
|
9205
|
+
const stopped = {
|
|
9206
|
+
...existing,
|
|
9207
|
+
pid: stillRunning ? existing.pid : null,
|
|
9208
|
+
appServerPid: stillRunning ? runtime.appServerPid : null,
|
|
9209
|
+
lastVerifiedAt: Date.now(),
|
|
9210
|
+
lastStatus: stillRunning ? "failed" : "stopped",
|
|
9211
|
+
lastError: stillRunning ? "stop-timeout" : null
|
|
9212
|
+
};
|
|
9213
|
+
await patchManagedInstance(stopped);
|
|
9214
|
+
return {
|
|
9215
|
+
status: stillRunning ? "failed" : "stopped",
|
|
9216
|
+
profileName,
|
|
9217
|
+
instance: managedInstanceToPayload(
|
|
9218
|
+
stopped,
|
|
9219
|
+
stillRunning,
|
|
9220
|
+
stopped.appServerPid,
|
|
9221
|
+
runtime.startedAt
|
|
9222
|
+
),
|
|
9223
|
+
reason: stillRunning ? "stop-timeout" : null
|
|
9224
|
+
};
|
|
9225
|
+
}
|
|
9226
|
+
function stopOfficialCodexObservedProfileInstance(profileName, pid, appServerPid) {
|
|
9227
|
+
return enqueueProfileAction(async () => {
|
|
9228
|
+
const { candidate } = await resolveCodexAppTarget();
|
|
9229
|
+
if (!candidate) {
|
|
9230
|
+
return {
|
|
9231
|
+
status: "not-running",
|
|
9232
|
+
profileName,
|
|
9233
|
+
instance: null,
|
|
9234
|
+
reason: "official-codex-app-not-found"
|
|
9235
|
+
};
|
|
9236
|
+
}
|
|
9237
|
+
const rows = await readProcessRows();
|
|
9238
|
+
const mainRow = rows.find((row) => row.pid === pid);
|
|
9239
|
+
if (!mainRow || !isMainProcessRow(mainRow, candidate)) {
|
|
9240
|
+
return {
|
|
9241
|
+
status: "not-running",
|
|
9242
|
+
profileName,
|
|
9243
|
+
instance: null,
|
|
9244
|
+
reason: null
|
|
9245
|
+
};
|
|
9246
|
+
}
|
|
9247
|
+
const runtimeAppServerPid = findAppServerPid(rows, pid) ?? appServerPid;
|
|
9248
|
+
const tree = [pid, ...getDescendantPids(pid, rows)].filter((entry, index, all) => all.indexOf(entry) === index).sort((a, b) => b - a);
|
|
9249
|
+
await signalPids(tree, "SIGTERM");
|
|
9250
|
+
const exited = await waitForMainPidExit(pid, 5e3);
|
|
9251
|
+
if (!exited) {
|
|
9252
|
+
await signalPids(tree, "SIGKILL");
|
|
9253
|
+
await waitForMainPidExit(pid, EXIT_WAIT_MS);
|
|
9254
|
+
}
|
|
9255
|
+
const stillRunning = (await readProcessRows()).some((row) => row.pid === pid);
|
|
9256
|
+
const instance = {
|
|
9257
|
+
profileName,
|
|
9258
|
+
profileKey: null,
|
|
9259
|
+
appPath: candidate.appPath,
|
|
9260
|
+
bundleId: candidate.bundleId,
|
|
9261
|
+
pid: stillRunning ? pid : null,
|
|
9262
|
+
appServerPid: stillRunning ? runtimeAppServerPid : null,
|
|
9263
|
+
running: stillRunning,
|
|
9264
|
+
startedAt: stillRunning ? toIso(mainRow.startedAt) : null,
|
|
9265
|
+
uptimeMs: stillRunning && typeof mainRow.startedAt === "number" ? Math.max(0, Date.now() - mainRow.startedAt) : null,
|
|
9266
|
+
launchedAt: null,
|
|
9267
|
+
lastVerifiedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
9268
|
+
lastStatus: stillRunning ? "failed" : "stopped",
|
|
9269
|
+
lastError: stillRunning ? "stop-timeout" : null
|
|
9270
|
+
};
|
|
9271
|
+
return {
|
|
9272
|
+
status: stillRunning ? "failed" : "stopped",
|
|
9273
|
+
profileName,
|
|
9274
|
+
instance,
|
|
9275
|
+
reason: stillRunning ? "stop-timeout" : null
|
|
9276
|
+
};
|
|
9277
|
+
});
|
|
9278
|
+
}
|
|
9279
|
+
async function restartOfficialCodexProfileInstance(options) {
|
|
9280
|
+
return enqueueProfileAction(async () => {
|
|
9281
|
+
const stopped = await stopOfficialCodexProfileInstanceOnce(options.profileName);
|
|
9282
|
+
if (stopped.status === "failed") {
|
|
9283
|
+
return stopped;
|
|
9284
|
+
}
|
|
9285
|
+
const launched = await launchOfficialCodexProfileInstanceOnce(options);
|
|
9286
|
+
return {
|
|
9287
|
+
...launched,
|
|
9288
|
+
status: launched.status === "started" ? "restarted" : launched.status
|
|
9289
|
+
};
|
|
8402
9290
|
});
|
|
8403
|
-
return restartPromise;
|
|
8404
9291
|
}
|
|
8405
9292
|
|
|
8406
9293
|
// src/commands/profile.ts
|
|
@@ -8852,33 +9739,190 @@ async function rememberOfficialCodexSwitch(profileKey) {
|
|
|
8852
9739
|
);
|
|
8853
9740
|
}
|
|
8854
9741
|
}
|
|
8855
|
-
function
|
|
9742
|
+
function formatOfficialCodexProfileAction(result) {
|
|
8856
9743
|
if (result.status === "restarted") {
|
|
8857
9744
|
return "Official Codex restarted.";
|
|
8858
9745
|
}
|
|
8859
9746
|
if (result.status === "started") {
|
|
8860
9747
|
return "Official Codex started.";
|
|
8861
9748
|
}
|
|
9749
|
+
if (result.status === "already-running") {
|
|
9750
|
+
return "Official Codex already running.";
|
|
9751
|
+
}
|
|
8862
9752
|
if (result.status === "failed") {
|
|
8863
9753
|
return `Official Codex restart failed: ${result.reason}.`;
|
|
8864
9754
|
}
|
|
8865
|
-
if (result.status === "skipped") {
|
|
9755
|
+
if (result.status === "skipped" || result.status === "not-running") {
|
|
8866
9756
|
return `Official Codex restart skipped: ${result.reason}.`;
|
|
8867
9757
|
}
|
|
8868
9758
|
return "Official Codex restart status unknown.";
|
|
8869
9759
|
}
|
|
9760
|
+
function findUnmanagedOfficialCodexRestartTarget(instances, profileName, profileKey) {
|
|
9761
|
+
const restartable = instances.unmanaged.filter((instance) => instance.pid);
|
|
9762
|
+
const matched = restartable.find((instance) => {
|
|
9763
|
+
if (profileKey && instance.profileKey) {
|
|
9764
|
+
return instance.profileKey === profileKey;
|
|
9765
|
+
}
|
|
9766
|
+
if (instance.profileKey) {
|
|
9767
|
+
return false;
|
|
9768
|
+
}
|
|
9769
|
+
return instance.profileName === profileName;
|
|
9770
|
+
}) ?? null;
|
|
9771
|
+
if (matched) {
|
|
9772
|
+
return { target: matched, ambiguous: false, unverified: false };
|
|
9773
|
+
}
|
|
9774
|
+
if (restartable.length > 1) {
|
|
9775
|
+
return { target: null, ambiguous: true, unverified: false };
|
|
9776
|
+
}
|
|
9777
|
+
return { target: null, ambiguous: false, unverified: restartable.length === 1 };
|
|
9778
|
+
}
|
|
9779
|
+
async function restartUnmanagedOfficialCodexWindow(profileName, launchOptions, target) {
|
|
9780
|
+
const stopped = await stopOfficialCodexObservedProfileInstance(
|
|
9781
|
+
target.profileName ?? profileName,
|
|
9782
|
+
target.pid,
|
|
9783
|
+
target.appServerPid
|
|
9784
|
+
);
|
|
9785
|
+
if (stopped.status === "failed") {
|
|
9786
|
+
return stopped;
|
|
9787
|
+
}
|
|
9788
|
+
const launched = await launchOfficialCodexProfileInstance(launchOptions);
|
|
9789
|
+
return {
|
|
9790
|
+
...launched,
|
|
9791
|
+
status: stopped.status === "stopped" && launched.status === "started" ? "restarted" : launched.status
|
|
9792
|
+
};
|
|
9793
|
+
}
|
|
9794
|
+
async function recordCliOfficialCodexRestartResult(profileName, profileKey, action) {
|
|
9795
|
+
const pid = action.status === "started" || action.status === "restarted" ? action.instance?.pid ?? null : null;
|
|
9796
|
+
const status = action.status === "started" || action.status === "restarted" ? action.status : action.status === "failed" ? "failed" : "skipped";
|
|
9797
|
+
const reason = action.status === "started" || action.status === "restarted" ? null : action.reason ?? action.status;
|
|
9798
|
+
try {
|
|
9799
|
+
await recordOfficialCodexRestartResult({
|
|
9800
|
+
status,
|
|
9801
|
+
reason,
|
|
9802
|
+
profileKey,
|
|
9803
|
+
pid
|
|
9804
|
+
});
|
|
9805
|
+
await recordOfficialCodexActivity({
|
|
9806
|
+
kind: "official-codex-restart",
|
|
9807
|
+
status,
|
|
9808
|
+
reason,
|
|
9809
|
+
targetProfileName: profileName,
|
|
9810
|
+
profileKey,
|
|
9811
|
+
phase: "cli",
|
|
9812
|
+
pid,
|
|
9813
|
+
restartRequested: true,
|
|
9814
|
+
restartResult: status
|
|
9815
|
+
});
|
|
9816
|
+
} catch (error) {
|
|
9817
|
+
console.warn(
|
|
9818
|
+
`Could not record official Codex restart state: ${error instanceof Error ? error.message : String(error)}`
|
|
9819
|
+
);
|
|
9820
|
+
}
|
|
9821
|
+
}
|
|
9822
|
+
async function recordCliOfficialCodexRestartSkipped(profileName, profileKey, reason) {
|
|
9823
|
+
await recordCliOfficialCodexRestartResult(profileName, profileKey, {
|
|
9824
|
+
status: "skipped",
|
|
9825
|
+
profileName,
|
|
9826
|
+
instance: null,
|
|
9827
|
+
reason
|
|
9828
|
+
});
|
|
9829
|
+
}
|
|
8870
9830
|
async function maybeRestartOfficialCodex(options) {
|
|
8871
9831
|
if (!options.enabled) {
|
|
8872
9832
|
return null;
|
|
8873
9833
|
}
|
|
8874
9834
|
try {
|
|
8875
|
-
const
|
|
8876
|
-
|
|
8877
|
-
|
|
8878
|
-
|
|
8879
|
-
|
|
8880
|
-
|
|
9835
|
+
const runtime = await options.manager.prepareProfileRuntime(options.profileName);
|
|
9836
|
+
const launchOptions = {
|
|
9837
|
+
profileName: options.profileName,
|
|
9838
|
+
profileKey: options.profileKey,
|
|
9839
|
+
profileHome: runtime.profileHome
|
|
9840
|
+
};
|
|
9841
|
+
const instances = await getOfficialCodexProfileInstances();
|
|
9842
|
+
if (instances.state === "unsupported") {
|
|
9843
|
+
await recordCliOfficialCodexRestartSkipped(
|
|
9844
|
+
options.profileName,
|
|
9845
|
+
options.profileKey,
|
|
9846
|
+
"unsupported-platform"
|
|
9847
|
+
);
|
|
9848
|
+
return "Official Codex restart skipped: unsupported-platform.";
|
|
9849
|
+
}
|
|
9850
|
+
if (instances.state === "not-found") {
|
|
9851
|
+
await recordCliOfficialCodexRestartSkipped(
|
|
9852
|
+
options.profileName,
|
|
9853
|
+
options.profileKey,
|
|
9854
|
+
"official-codex-app-not-found"
|
|
9855
|
+
);
|
|
9856
|
+
return "Official Codex restart skipped: official-codex-app-not-found.";
|
|
9857
|
+
}
|
|
9858
|
+
const managedRunning = instances.instances.some(
|
|
9859
|
+
(instance) => instance.profileName === options.profileName && instance.running
|
|
9860
|
+
);
|
|
9861
|
+
const unmanaged = findUnmanagedOfficialCodexRestartTarget(
|
|
9862
|
+
instances,
|
|
9863
|
+
options.profileName,
|
|
9864
|
+
options.profileKey
|
|
9865
|
+
);
|
|
9866
|
+
if (unmanaged.target && !managedRunning) {
|
|
9867
|
+
const action2 = await restartUnmanagedOfficialCodexWindow(
|
|
9868
|
+
options.profileName,
|
|
9869
|
+
launchOptions,
|
|
9870
|
+
unmanaged.target
|
|
9871
|
+
);
|
|
9872
|
+
await recordCliOfficialCodexRestartResult(
|
|
9873
|
+
options.profileName,
|
|
9874
|
+
options.profileKey,
|
|
9875
|
+
action2
|
|
9876
|
+
);
|
|
9877
|
+
return formatOfficialCodexProfileAction(action2);
|
|
9878
|
+
}
|
|
9879
|
+
if (unmanaged.ambiguous && !managedRunning) {
|
|
9880
|
+
await recordCliOfficialCodexRestartSkipped(
|
|
9881
|
+
options.profileName,
|
|
9882
|
+
options.profileKey,
|
|
9883
|
+
"ambiguous-official-codex-windows"
|
|
9884
|
+
);
|
|
9885
|
+
return "Official Codex restart skipped: ambiguous-official-codex-windows.";
|
|
9886
|
+
}
|
|
9887
|
+
if (unmanaged.unverified && !managedRunning) {
|
|
9888
|
+
await recordCliOfficialCodexRestartSkipped(
|
|
9889
|
+
options.profileName,
|
|
9890
|
+
options.profileKey,
|
|
9891
|
+
"unverified-official-codex-window"
|
|
9892
|
+
);
|
|
9893
|
+
return "Official Codex restart skipped: unverified-official-codex-window.";
|
|
9894
|
+
}
|
|
9895
|
+
if (options.launchIfNotRunning === false) {
|
|
9896
|
+
if (!managedRunning) {
|
|
9897
|
+
await recordCliOfficialCodexRestartSkipped(
|
|
9898
|
+
options.profileName,
|
|
9899
|
+
options.profileKey,
|
|
9900
|
+
"official-codex-app-not-running"
|
|
9901
|
+
);
|
|
9902
|
+
return "Official Codex restart skipped: official-codex-app-not-running.";
|
|
9903
|
+
}
|
|
9904
|
+
const action2 = await restartOfficialCodexProfileInstance(launchOptions);
|
|
9905
|
+
await recordCliOfficialCodexRestartResult(
|
|
9906
|
+
options.profileName,
|
|
9907
|
+
options.profileKey,
|
|
9908
|
+
action2
|
|
9909
|
+
);
|
|
9910
|
+
return formatOfficialCodexProfileAction(action2);
|
|
9911
|
+
}
|
|
9912
|
+
const action = await restartOfficialCodexProfileInstance(launchOptions);
|
|
9913
|
+
await recordCliOfficialCodexRestartResult(
|
|
9914
|
+
options.profileName,
|
|
9915
|
+
options.profileKey,
|
|
9916
|
+
action
|
|
9917
|
+
);
|
|
9918
|
+
return formatOfficialCodexProfileAction(action);
|
|
8881
9919
|
} catch (error) {
|
|
9920
|
+
await recordCliOfficialCodexRestartResult(options.profileName, options.profileKey, {
|
|
9921
|
+
status: "failed",
|
|
9922
|
+
profileName: options.profileName,
|
|
9923
|
+
instance: null,
|
|
9924
|
+
reason: error instanceof Error ? error.message : "restart-threw"
|
|
9925
|
+
});
|
|
8882
9926
|
return `Official Codex restart failed: ${error instanceof Error ? error.message : String(error)}.`;
|
|
8883
9927
|
}
|
|
8884
9928
|
}
|
|
@@ -9014,8 +10058,9 @@ async function runAutoRollPass(manager, options) {
|
|
|
9014
10058
|
const targetProfileKey = profileRateLimitKey(candidate.profile);
|
|
9015
10059
|
await rememberOfficialCodexSwitch(targetProfileKey);
|
|
9016
10060
|
const restartMessage = await maybeRestartOfficialCodex({
|
|
10061
|
+
manager,
|
|
9017
10062
|
enabled: options.restartOfficialCodex,
|
|
9018
|
-
|
|
10063
|
+
profileName: candidate.profile.name,
|
|
9019
10064
|
profileKey: targetProfileKey,
|
|
9020
10065
|
launchIfNotRunning: options.launchOfficialCodexWhenClosed === true
|
|
9021
10066
|
});
|
|
@@ -9129,8 +10174,9 @@ async function handleProfileCommand(args, version) {
|
|
|
9129
10174
|
console.log(`Switched to profile: ${name}`);
|
|
9130
10175
|
await rememberOfficialCodexSwitch(targetProfileKey);
|
|
9131
10176
|
const restartMessage = await maybeRestartOfficialCodex({
|
|
10177
|
+
manager,
|
|
9132
10178
|
enabled: restartOfficialCodex,
|
|
9133
|
-
|
|
10179
|
+
profileName: name,
|
|
9134
10180
|
profileKey: targetProfileKey
|
|
9135
10181
|
});
|
|
9136
10182
|
if (restartMessage) {
|
|
@@ -9244,7 +10290,7 @@ var import_node_path15 = __toESM(require("path"), 1);
|
|
|
9244
10290
|
var CLOUD_SYNC_SCHEMA_VERSION = 1;
|
|
9245
10291
|
|
|
9246
10292
|
// ../../packages/shared/src/core/type-guards.ts
|
|
9247
|
-
function
|
|
10293
|
+
function isRecord5(value) {
|
|
9248
10294
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
9249
10295
|
}
|
|
9250
10296
|
function toIsoOrNull(value) {
|
|
@@ -9282,10 +10328,10 @@ function buildSyncUrl(pathname) {
|
|
|
9282
10328
|
return `${baseUrl}${normalizedPath}`;
|
|
9283
10329
|
}
|
|
9284
10330
|
function normalizeSnapshot(value) {
|
|
9285
|
-
if (!
|
|
10331
|
+
if (!isRecord5(value)) {
|
|
9286
10332
|
return null;
|
|
9287
10333
|
}
|
|
9288
|
-
if (
|
|
10334
|
+
if (isRecord5(value.snapshot)) {
|
|
9289
10335
|
const nested = normalizeSnapshot(value.snapshot);
|
|
9290
10336
|
if (nested) {
|
|
9291
10337
|
return nested;
|
|
@@ -9300,9 +10346,9 @@ function normalizeSnapshot(value) {
|
|
|
9300
10346
|
return null;
|
|
9301
10347
|
}
|
|
9302
10348
|
const rawProfiles = Array.isArray(value.profiles) ? value.profiles : [];
|
|
9303
|
-
const profiles = rawProfiles.map((entry) =>
|
|
9304
|
-
const data =
|
|
9305
|
-
const metadata =
|
|
10349
|
+
const profiles = rawProfiles.map((entry) => isRecord5(entry) ? entry : null).filter((entry) => Boolean(entry)).map((entry) => {
|
|
10350
|
+
const data = isRecord5(entry.data) ? entry.data : {};
|
|
10351
|
+
const metadata = isRecord5(entry.metadata) ? entry.metadata : void 0;
|
|
9306
10352
|
return {
|
|
9307
10353
|
name: typeof entry.name === "string" ? entry.name : "",
|
|
9308
10354
|
displayName: typeof entry.displayName === "string" ? entry.displayName : null,
|
|
@@ -9318,7 +10364,7 @@ function normalizeSnapshot(value) {
|
|
|
9318
10364
|
};
|
|
9319
10365
|
}).filter((entry) => entry.name.trim().length > 0);
|
|
9320
10366
|
const rawSettings = value.settingsJson;
|
|
9321
|
-
const settingsJson =
|
|
10367
|
+
const settingsJson = isRecord5(rawSettings) ? rawSettings : null;
|
|
9322
10368
|
return {
|
|
9323
10369
|
schemaVersion: CLOUD_SYNC_SCHEMA_VERSION,
|
|
9324
10370
|
updatedAt,
|
|
@@ -9502,7 +10548,7 @@ var FALLBACK_FEATURE_KEYS = [
|
|
|
9502
10548
|
];
|
|
9503
10549
|
var metadataCache = null;
|
|
9504
10550
|
var metadataCacheAt = 0;
|
|
9505
|
-
function
|
|
10551
|
+
function isRecord6(value) {
|
|
9506
10552
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
9507
10553
|
}
|
|
9508
10554
|
function uniqueSorted(values) {
|
|
@@ -9567,16 +10613,16 @@ function parseFeatureCatalog(output) {
|
|
|
9567
10613
|
}
|
|
9568
10614
|
function parseSchemaKeys(schemaRaw) {
|
|
9569
10615
|
const parsed = JSON.parse(schemaRaw);
|
|
9570
|
-
if (!
|
|
10616
|
+
if (!isRecord6(parsed)) {
|
|
9571
10617
|
return {
|
|
9572
10618
|
topLevelKeys: FALLBACK_SCHEMA_TOP_LEVEL_KEYS,
|
|
9573
10619
|
featureKeys: FALLBACK_FEATURE_KEYS
|
|
9574
10620
|
};
|
|
9575
10621
|
}
|
|
9576
|
-
const properties =
|
|
10622
|
+
const properties = isRecord6(parsed.properties) ? parsed.properties : {};
|
|
9577
10623
|
const topLevelKeys = uniqueSorted(Object.keys(properties));
|
|
9578
|
-
const features =
|
|
9579
|
-
const featureProperties =
|
|
10624
|
+
const features = isRecord6(properties.features) ? properties.features : {};
|
|
10625
|
+
const featureProperties = isRecord6(features.properties) ? features.properties : {};
|
|
9580
10626
|
const featureKeys = uniqueSorted(Object.keys(featureProperties));
|
|
9581
10627
|
return {
|
|
9582
10628
|
topLevelKeys: topLevelKeys.length > 0 ? topLevelKeys : FALLBACK_SCHEMA_TOP_LEVEL_KEYS,
|
|
@@ -10362,15 +11408,15 @@ var SYNC_SIZE_WARN_BYTES = 1 * 1024 * 1024;
|
|
|
10362
11408
|
var SYNC_SIZE_MAX_BYTES = 5 * 1024 * 1024;
|
|
10363
11409
|
var MB_DIVISOR = 1024 * 1024;
|
|
10364
11410
|
function mapProfilesFromAppState(raw) {
|
|
10365
|
-
if (!
|
|
11411
|
+
if (!isRecord5(raw)) {
|
|
10366
11412
|
return [];
|
|
10367
11413
|
}
|
|
10368
11414
|
const profiles = [];
|
|
10369
11415
|
for (const [name, value] of Object.entries(raw)) {
|
|
10370
|
-
if (!
|
|
11416
|
+
if (!isRecord5(value)) {
|
|
10371
11417
|
continue;
|
|
10372
11418
|
}
|
|
10373
|
-
const data =
|
|
11419
|
+
const data = isRecord5(value.data) ? value.data : null;
|
|
10374
11420
|
if (!data) {
|
|
10375
11421
|
continue;
|
|
10376
11422
|
}
|
|
@@ -10382,7 +11428,7 @@ function mapProfilesFromAppState(raw) {
|
|
|
10382
11428
|
name: normalizedName,
|
|
10383
11429
|
displayName: typeof value.displayName === "string" ? value.displayName : null,
|
|
10384
11430
|
data,
|
|
10385
|
-
metadata:
|
|
11431
|
+
metadata: isRecord5(value.metadata) ? value.metadata : void 0,
|
|
10386
11432
|
accountId: typeof value.accountId === "string" ? value.accountId : null,
|
|
10387
11433
|
workspaceId: typeof value.workspaceId === "string" ? value.workspaceId : null,
|
|
10388
11434
|
workspaceName: typeof value.workspaceName === "string" ? value.workspaceName : null,
|
|
@@ -10396,7 +11442,7 @@ function mapProfilesFromAppState(raw) {
|
|
|
10396
11442
|
}
|
|
10397
11443
|
function summarizeSnapshot(snapshot) {
|
|
10398
11444
|
const configBytes = typeof snapshot.configTomlContent === "string" ? snapshot.configTomlContent.length : 0;
|
|
10399
|
-
const settingsKeys =
|
|
11445
|
+
const settingsKeys = isRecord5(snapshot.settingsJson) ? Object.keys(snapshot.settingsJson).length : 0;
|
|
10400
11446
|
return {
|
|
10401
11447
|
profiles: snapshot.profiles.length,
|
|
10402
11448
|
configBytes,
|
|
@@ -10501,7 +11547,7 @@ async function buildLocalSnapshot(profileManager, options = {}) {
|
|
|
10501
11547
|
const settingsJson = await readCodexSettingsJsonRaw();
|
|
10502
11548
|
const hasProfiles = profiles.length > 0;
|
|
10503
11549
|
const hasConfig = typeof config.content === "string" && config.content.trim().length > 0;
|
|
10504
|
-
const hasSettings =
|
|
11550
|
+
const hasSettings = isRecord5(settingsJson) && Object.keys(settingsJson).length > 0;
|
|
10505
11551
|
if (enforcePushGuards && !hasProfiles && !hasConfig && !hasSettings) {
|
|
10506
11552
|
throw new Error("Refusing to push an empty cloud sync snapshot.");
|
|
10507
11553
|
}
|
|
@@ -10525,7 +11571,7 @@ async function applyRemoteSnapshot(profileManager, snapshot) {
|
|
|
10525
11571
|
codexHomePath: runtimeContext.codexHomePath
|
|
10526
11572
|
});
|
|
10527
11573
|
}
|
|
10528
|
-
if (snapshot.settingsJson &&
|
|
11574
|
+
if (snapshot.settingsJson && isRecord5(snapshot.settingsJson)) {
|
|
10529
11575
|
await writeCodexSettingsJsonRaw(snapshot.settingsJson);
|
|
10530
11576
|
} else {
|
|
10531
11577
|
await writeCodexSettingsJsonRaw({});
|
|
@@ -10778,10 +11824,10 @@ var LEGACY_SKILL_CACHE_DIR = "skill-cache";
|
|
|
10778
11824
|
var LEGACY_SKILLS_REPOS_FILE = "repos.json";
|
|
10779
11825
|
var LEGACY_SKILL_MANIFEST = ".codexuse-skill.json";
|
|
10780
11826
|
var LEGACY_LICENSE_SECRET_FILE2 = "license.secret";
|
|
10781
|
-
function
|
|
11827
|
+
function isRecord7(value) {
|
|
10782
11828
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
10783
11829
|
}
|
|
10784
|
-
function
|
|
11830
|
+
function asString5(value) {
|
|
10785
11831
|
if (typeof value !== "string") {
|
|
10786
11832
|
return null;
|
|
10787
11833
|
}
|
|
@@ -10950,7 +11996,7 @@ function pickAutoRoll(raw) {
|
|
|
10950
11996
|
}
|
|
10951
11997
|
}
|
|
10952
11998
|
function parseLegacyLicense(raw) {
|
|
10953
|
-
if (!
|
|
11999
|
+
if (!isRecord7(raw)) {
|
|
10954
12000
|
return {
|
|
10955
12001
|
licenseKey: null,
|
|
10956
12002
|
purchaseEmail: null,
|
|
@@ -10961,25 +12007,25 @@ function parseLegacyLicense(raw) {
|
|
|
10961
12007
|
signature: null
|
|
10962
12008
|
};
|
|
10963
12009
|
}
|
|
10964
|
-
const statusCandidate =
|
|
12010
|
+
const statusCandidate = asString5(raw.status);
|
|
10965
12011
|
const status = ["inactive", "active", "grace", "error"].includes(statusCandidate ?? "") ? statusCandidate : "inactive";
|
|
10966
12012
|
return {
|
|
10967
|
-
licenseKey:
|
|
10968
|
-
purchaseEmail:
|
|
10969
|
-
lastVerifiedAt:
|
|
10970
|
-
nextCheckAt:
|
|
10971
|
-
lastVerificationError:
|
|
12013
|
+
licenseKey: asString5(raw.licenseKey ?? raw.license_key),
|
|
12014
|
+
purchaseEmail: asString5(raw.purchaseEmail ?? raw.purchase_email),
|
|
12015
|
+
lastVerifiedAt: asString5(raw.lastVerifiedAt ?? raw.last_verified_at),
|
|
12016
|
+
nextCheckAt: asString5(raw.nextCheckAt ?? raw.next_check_at),
|
|
12017
|
+
lastVerificationError: asString5(raw.lastVerificationError ?? raw.last_verification_error),
|
|
10972
12018
|
status,
|
|
10973
|
-
signature:
|
|
12019
|
+
signature: asString5(raw.signature)
|
|
10974
12020
|
};
|
|
10975
12021
|
}
|
|
10976
12022
|
function parseLegacyProfileRecord(name, raw) {
|
|
10977
|
-
if (!
|
|
12023
|
+
if (!isRecord7(raw)) {
|
|
10978
12024
|
return null;
|
|
10979
12025
|
}
|
|
10980
12026
|
const dataRaw = raw.data;
|
|
10981
12027
|
let data = null;
|
|
10982
|
-
if (
|
|
12028
|
+
if (isRecord7(dataRaw)) {
|
|
10983
12029
|
data = dataRaw;
|
|
10984
12030
|
} else if (typeof dataRaw === "string") {
|
|
10985
12031
|
try {
|
|
@@ -10993,31 +12039,31 @@ function parseLegacyProfileRecord(name, raw) {
|
|
|
10993
12039
|
}
|
|
10994
12040
|
return {
|
|
10995
12041
|
name,
|
|
10996
|
-
displayName:
|
|
12042
|
+
displayName: asString5(raw.displayName ?? raw.display_name) ?? name,
|
|
10997
12043
|
data,
|
|
10998
|
-
metadata:
|
|
10999
|
-
accountId:
|
|
11000
|
-
workspaceId:
|
|
11001
|
-
workspaceName:
|
|
11002
|
-
email:
|
|
11003
|
-
authMethod:
|
|
11004
|
-
createdAt:
|
|
11005
|
-
updatedAt:
|
|
12044
|
+
metadata: isRecord7(raw.metadata) ? raw.metadata : void 0,
|
|
12045
|
+
accountId: asString5(raw.accountId ?? raw.account_id),
|
|
12046
|
+
workspaceId: asString5(raw.workspaceId ?? raw.workspace_id),
|
|
12047
|
+
workspaceName: asString5(raw.workspaceName ?? raw.workspace_name),
|
|
12048
|
+
email: asString5(raw.email),
|
|
12049
|
+
authMethod: asString5(raw.authMethod ?? raw.auth_method),
|
|
12050
|
+
createdAt: asString5(raw.createdAt ?? raw.created_at),
|
|
12051
|
+
updatedAt: asString5(raw.updatedAt ?? raw.updated_at)
|
|
11006
12052
|
};
|
|
11007
12053
|
}
|
|
11008
12054
|
async function loadLegacySettingsPatch() {
|
|
11009
12055
|
const filePath = resolveLegacyPath(LEGACY_SETTINGS_FILE);
|
|
11010
12056
|
const raw = await readJsonFileIfExists(filePath);
|
|
11011
|
-
if (!
|
|
12057
|
+
if (!isRecord7(raw)) {
|
|
11012
12058
|
return {};
|
|
11013
12059
|
}
|
|
11014
12060
|
const autoRoll = pickAutoRoll(raw.autoRoll ?? raw.auto_roll);
|
|
11015
12061
|
const license = parseLegacyLicense(raw.license ?? raw.license_data ?? raw.license_state);
|
|
11016
12062
|
return {
|
|
11017
12063
|
app: {
|
|
11018
|
-
lastAppVersion:
|
|
11019
|
-
pendingUpdateVersion:
|
|
11020
|
-
lastProfileName:
|
|
12064
|
+
lastAppVersion: asString5(raw.lastAppVersion ?? raw.last_app_version),
|
|
12065
|
+
pendingUpdateVersion: asString5(raw.pendingUpdateVersion ?? raw.pending_update_version),
|
|
12066
|
+
lastProfileName: asString5(raw.lastProfileName ?? raw.last_profile_name)
|
|
11021
12067
|
},
|
|
11022
12068
|
license,
|
|
11023
12069
|
autoRoll: autoRoll ? {
|
|
@@ -11035,22 +12081,22 @@ async function loadLegacySettingsPatch() {
|
|
|
11035
12081
|
async function loadLegacySyncPatch() {
|
|
11036
12082
|
const filePath = resolveLegacyPath(LEGACY_SYNC_STATE_FILE);
|
|
11037
12083
|
const raw = await readJsonFileIfExists(filePath);
|
|
11038
|
-
if (!
|
|
12084
|
+
if (!isRecord7(raw)) {
|
|
11039
12085
|
return {};
|
|
11040
12086
|
}
|
|
11041
12087
|
return {
|
|
11042
12088
|
sync: {
|
|
11043
|
-
lastPushAt:
|
|
11044
|
-
lastPullAt:
|
|
11045
|
-
lastError:
|
|
11046
|
-
remoteUpdatedAt:
|
|
12089
|
+
lastPushAt: asString5(raw.lastPushAt),
|
|
12090
|
+
lastPullAt: asString5(raw.lastPullAt),
|
|
12091
|
+
lastError: asString5(raw.lastError),
|
|
12092
|
+
remoteUpdatedAt: asString5(raw.remoteUpdatedAt)
|
|
11047
12093
|
}
|
|
11048
12094
|
};
|
|
11049
12095
|
}
|
|
11050
12096
|
async function loadLegacyAppSettingsParityPatch() {
|
|
11051
12097
|
const filePath = import_node_path16.default.join(getUserDataDir(), LEGACY_APP_SETTINGS_PARITY_FILE);
|
|
11052
12098
|
const raw = await readJsonFileIfExists(filePath);
|
|
11053
|
-
if (!
|
|
12099
|
+
if (!isRecord7(raw)) {
|
|
11054
12100
|
return {};
|
|
11055
12101
|
}
|
|
11056
12102
|
return {
|
|
@@ -11090,21 +12136,21 @@ async function loadLegacyProfilesPatch() {
|
|
|
11090
12136
|
return { profilesByName };
|
|
11091
12137
|
}
|
|
11092
12138
|
function parseSkillInstallMetadata(raw) {
|
|
11093
|
-
if (!
|
|
12139
|
+
if (!isRecord7(raw)) {
|
|
11094
12140
|
return null;
|
|
11095
12141
|
}
|
|
11096
|
-
const id =
|
|
12142
|
+
const id = asString5(raw.id);
|
|
11097
12143
|
if (!id) {
|
|
11098
12144
|
return null;
|
|
11099
12145
|
}
|
|
11100
12146
|
return {
|
|
11101
12147
|
id,
|
|
11102
|
-
repo:
|
|
11103
|
-
repoPath:
|
|
11104
|
-
sourceLabel:
|
|
12148
|
+
repo: asString5(raw.repo),
|
|
12149
|
+
repoPath: asString5(raw.repoPath),
|
|
12150
|
+
sourceLabel: asString5(raw.sourceLabel),
|
|
11105
12151
|
sourceType: raw.sourceType === "official" || raw.sourceType === "community" || raw.sourceType === "local" ? raw.sourceType : void 0,
|
|
11106
|
-
viewUrl:
|
|
11107
|
-
createdAt:
|
|
12152
|
+
viewUrl: asString5(raw.viewUrl),
|
|
12153
|
+
createdAt: asString5(raw.createdAt)
|
|
11108
12154
|
};
|
|
11109
12155
|
}
|
|
11110
12156
|
async function loadLegacySkillsPatch() {
|
|
@@ -11135,7 +12181,7 @@ async function loadLegacySkillsPatch() {
|
|
|
11135
12181
|
}
|
|
11136
12182
|
installsBySlug[entry.name] = parsed;
|
|
11137
12183
|
}
|
|
11138
|
-
const sources =
|
|
12184
|
+
const sources = isRecord7(reposRaw) && Array.isArray(reposRaw.sources) ? reposRaw.sources : [];
|
|
11139
12185
|
if (sources.length === 0 && Object.keys(installsBySlug).length === 0) {
|
|
11140
12186
|
return {};
|
|
11141
12187
|
}
|
|
@@ -11167,7 +12213,7 @@ function mergeLegacyLocalStoragePatch(payload) {
|
|
|
11167
12213
|
}
|
|
11168
12214
|
};
|
|
11169
12215
|
const settingsStorage = payload["settings-storage"];
|
|
11170
|
-
if (
|
|
12216
|
+
if (isRecord7(settingsStorage)) {
|
|
11171
12217
|
const nextExcludeFolders = Array.isArray(settingsStorage.excludeFolders) ? settingsStorage.excludeFolders.filter((item) => typeof item === "string") : void 0;
|
|
11172
12218
|
const nextBeep = typeof settingsStorage.enableTaskCompleteBeep === "boolean" ? settingsStorage.enableTaskCompleteBeep : void 0;
|
|
11173
12219
|
const nextSleep = typeof settingsStorage.preventSleepDuringTasks === "boolean" ? settingsStorage.preventSleepDuringTasks : void 0;
|
|
@@ -11186,15 +12232,15 @@ function mergeLegacyLocalStoragePatch(payload) {
|
|
|
11186
12232
|
markSkippedIfPresent("provider", hasKey2("provider"));
|
|
11187
12233
|
markSkippedIfPresent("sandbox-storage", hasKey2("sandbox-storage"));
|
|
11188
12234
|
const projectSettings = payload["project-settings-storage"];
|
|
11189
|
-
if (
|
|
12235
|
+
if (isRecord7(projectSettings) && isRecord7(projectSettings.settingsByPath)) {
|
|
11190
12236
|
patch.workspaceSettingsByPath = projectSettings.settingsByPath;
|
|
11191
12237
|
markSkippedIfPresent("project-settings-storage", true);
|
|
11192
12238
|
} else {
|
|
11193
12239
|
markSkippedIfPresent("project-settings-storage", false);
|
|
11194
12240
|
}
|
|
11195
12241
|
const folder = payload["folder-storage"];
|
|
11196
|
-
if (
|
|
11197
|
-
const folderHistory = Array.isArray(folder.folderHistory) ? folder.folderHistory.filter(
|
|
12242
|
+
if (isRecord7(folder)) {
|
|
12243
|
+
const folderHistory = Array.isArray(folder.folderHistory) ? folder.folderHistory.filter(isRecord7) : void 0;
|
|
11198
12244
|
const pinnedPaths = Array.isArray(folder.pinnedPaths) ? folder.pinnedPaths.filter((item) => typeof item === "string") : void 0;
|
|
11199
12245
|
patch.preferences = {
|
|
11200
12246
|
...patch.preferences ?? {},
|
|
@@ -11207,12 +12253,12 @@ function mergeLegacyLocalStoragePatch(payload) {
|
|
|
11207
12253
|
}
|
|
11208
12254
|
const categories = payload["conversation-categories-storage"];
|
|
11209
12255
|
let consumedCategories = false;
|
|
11210
|
-
if (
|
|
11211
|
-
if (
|
|
12256
|
+
if (isRecord7(categories)) {
|
|
12257
|
+
if (isRecord7(categories.categoriesByCwd)) {
|
|
11212
12258
|
patch.conversationCategoriesByCwd = categories.categoriesByCwd;
|
|
11213
12259
|
consumedCategories = true;
|
|
11214
12260
|
}
|
|
11215
|
-
if (
|
|
12261
|
+
if (isRecord7(categories.conversationCategoryByCwd)) {
|
|
11216
12262
|
patch.conversationCategoryAssignmentsByCwd = categories.conversationCategoryByCwd;
|
|
11217
12263
|
consumedCategories = true;
|
|
11218
12264
|
}
|
|
@@ -11435,7 +12481,7 @@ async function importLegacyLocalStorageOnce(payload) {
|
|
|
11435
12481
|
if (current.migration.status === "pending") {
|
|
11436
12482
|
return { completed: false, importedKeys: [], skippedKeys: [] };
|
|
11437
12483
|
}
|
|
11438
|
-
if (!payload || !
|
|
12484
|
+
if (!payload || !isRecord7(payload)) {
|
|
11439
12485
|
return { completed: true, importedKeys: [], skippedKeys: [] };
|
|
11440
12486
|
}
|
|
11441
12487
|
const { patch, consumedKeys, skippedKeys } = mergeLegacyLocalStoragePatch(payload);
|
|
@@ -11503,7 +12549,7 @@ async function ensureCliStorageReady() {
|
|
|
11503
12549
|
}
|
|
11504
12550
|
|
|
11505
12551
|
// src/app/main.ts
|
|
11506
|
-
var VERSION = true ? "3.9.
|
|
12552
|
+
var VERSION = true ? "3.9.9" : "0.0.0";
|
|
11507
12553
|
async function runCli() {
|
|
11508
12554
|
const args = process.argv.slice(2);
|
|
11509
12555
|
if (args.length === 0) {
|