codexuse-cli 3.6.2 → 3.6.3
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 +1 -1
- package/dist/server/index.mjs +334 -40
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -10226,7 +10226,7 @@ async function ensureCliStorageReady() {
|
|
|
10226
10226
|
}
|
|
10227
10227
|
|
|
10228
10228
|
// src/app/main.ts
|
|
10229
|
-
var VERSION = true ? "3.6.
|
|
10229
|
+
var VERSION = true ? "3.6.3" : "0.0.0";
|
|
10230
10230
|
async function runCli() {
|
|
10231
10231
|
const args = process.argv.slice(2);
|
|
10232
10232
|
if (args.length === 0) {
|
package/dist/server/index.mjs
CHANGED
|
@@ -19324,6 +19324,10 @@ const GitStatusResult = Struct({
|
|
|
19324
19324
|
behindCount: NonNegativeInt,
|
|
19325
19325
|
pr: NullOr(GitStatusPr)
|
|
19326
19326
|
});
|
|
19327
|
+
const GitStatusUpdatedPayload = Struct({
|
|
19328
|
+
cwd: TrimmedNonEmptyStringSchema,
|
|
19329
|
+
status: GitStatusResult
|
|
19330
|
+
});
|
|
19327
19331
|
const GitListBranchesResult = Struct({
|
|
19328
19332
|
branches: Array$1(GitBranch),
|
|
19329
19333
|
isRepo: Boolean$2,
|
|
@@ -19527,43 +19531,43 @@ const EDITORS = [
|
|
|
19527
19531
|
{
|
|
19528
19532
|
id: "cursor",
|
|
19529
19533
|
label: "Cursor",
|
|
19530
|
-
|
|
19534
|
+
commands: ["cursor"],
|
|
19531
19535
|
supportsGoto: true
|
|
19532
19536
|
},
|
|
19533
19537
|
{
|
|
19534
19538
|
id: "vscode",
|
|
19535
19539
|
label: "VS Code",
|
|
19536
|
-
|
|
19540
|
+
commands: ["code"],
|
|
19537
19541
|
supportsGoto: true
|
|
19538
19542
|
},
|
|
19539
19543
|
{
|
|
19540
19544
|
id: "vscode-insiders",
|
|
19541
19545
|
label: "VS Code Insiders",
|
|
19542
|
-
|
|
19546
|
+
commands: ["code-insiders"],
|
|
19543
19547
|
supportsGoto: true
|
|
19544
19548
|
},
|
|
19545
19549
|
{
|
|
19546
19550
|
id: "vscodium",
|
|
19547
19551
|
label: "VSCodium",
|
|
19548
|
-
|
|
19552
|
+
commands: ["codium"],
|
|
19549
19553
|
supportsGoto: true
|
|
19550
19554
|
},
|
|
19551
19555
|
{
|
|
19552
19556
|
id: "zed",
|
|
19553
19557
|
label: "Zed",
|
|
19554
|
-
|
|
19558
|
+
commands: ["zed", "zeditor"],
|
|
19555
19559
|
supportsGoto: false
|
|
19556
19560
|
},
|
|
19557
19561
|
{
|
|
19558
19562
|
id: "antigravity",
|
|
19559
19563
|
label: "Antigravity",
|
|
19560
|
-
|
|
19564
|
+
commands: ["agy"],
|
|
19561
19565
|
supportsGoto: false
|
|
19562
19566
|
},
|
|
19563
19567
|
{
|
|
19564
19568
|
id: "file-manager",
|
|
19565
19569
|
label: "File Manager",
|
|
19566
|
-
|
|
19570
|
+
commands: null,
|
|
19567
19571
|
supportsGoto: false
|
|
19568
19572
|
}
|
|
19569
19573
|
];
|
|
@@ -19641,6 +19645,8 @@ const WS_METHODS = {
|
|
|
19641
19645
|
shellOpenInEditor: "shell.openInEditor",
|
|
19642
19646
|
gitPull: "git.pull",
|
|
19643
19647
|
gitStatus: "git.status",
|
|
19648
|
+
gitWatchStatus: "git.watchStatus",
|
|
19649
|
+
gitUnwatchStatus: "git.unwatchStatus",
|
|
19644
19650
|
gitRunStackedAction: "git.runStackedAction",
|
|
19645
19651
|
gitListBranches: "git.listBranches",
|
|
19646
19652
|
gitCreateWorktree: "git.createWorktree",
|
|
@@ -19713,6 +19719,7 @@ const WS_METHODS = {
|
|
|
19713
19719
|
};
|
|
19714
19720
|
const WS_CHANNELS = {
|
|
19715
19721
|
gitActionProgress: "git.actionProgress",
|
|
19722
|
+
gitStatusUpdated: "git.statusUpdated",
|
|
19716
19723
|
terminalEvent: "terminal.event",
|
|
19717
19724
|
serverWelcome: "server.welcome",
|
|
19718
19725
|
serverConfigUpdated: "server.configUpdated",
|
|
@@ -19737,6 +19744,8 @@ const WebSocketRequestBody = Union([
|
|
|
19737
19744
|
tagRequestBody(WS_METHODS.shellOpenInEditor, OpenInEditorInput),
|
|
19738
19745
|
tagRequestBody(WS_METHODS.gitPull, GitPullInput),
|
|
19739
19746
|
tagRequestBody(WS_METHODS.gitStatus, GitStatusInput),
|
|
19747
|
+
tagRequestBody(WS_METHODS.gitWatchStatus, GitStatusInput),
|
|
19748
|
+
tagRequestBody(WS_METHODS.gitUnwatchStatus, GitStatusInput),
|
|
19740
19749
|
tagRequestBody(WS_METHODS.gitRunStackedAction, GitRunStackedActionInput),
|
|
19741
19750
|
tagRequestBody(WS_METHODS.gitListBranches, GitListBranchesInput),
|
|
19742
19751
|
tagRequestBody(WS_METHODS.gitCreateWorktree, GitCreateWorktreeInput),
|
|
@@ -19862,6 +19871,7 @@ const WsPushServerWelcome = makeWsPushSchema(WS_CHANNELS.serverWelcome, WsWelcom
|
|
|
19862
19871
|
const WsPushServerConfigUpdated = makeWsPushSchema(WS_CHANNELS.serverConfigUpdated, ServerConfigUpdatedPayload);
|
|
19863
19872
|
const WsPushServerProvidersUpdated = makeWsPushSchema(WS_CHANNELS.serverProvidersUpdated, ServerProviderUpdatedPayload);
|
|
19864
19873
|
const WsPushGitActionProgress = makeWsPushSchema(WS_CHANNELS.gitActionProgress, GitActionProgressEvent);
|
|
19874
|
+
const WsPushGitStatusUpdated = makeWsPushSchema(WS_CHANNELS.gitStatusUpdated, GitStatusUpdatedPayload);
|
|
19865
19875
|
const WsPushTerminalEvent = makeWsPushSchema(WS_CHANNELS.terminalEvent, TerminalEvent);
|
|
19866
19876
|
const WsPushProfilesSwitched = makeWsPushSchema(WS_CHANNELS.profilesSwitched, Unknown);
|
|
19867
19877
|
const WsPushRateLimitsUpdated = makeWsPushSchema(WS_CHANNELS.rateLimitsUpdated, Unknown);
|
|
@@ -19870,6 +19880,7 @@ const WsPushCliStatusUpdated = makeWsPushSchema(WS_CHANNELS.cliStatusUpdated, Un
|
|
|
19870
19880
|
const WsPushOrchestrationDomainEvent = makeWsPushSchema(ORCHESTRATION_WS_CHANNELS.domainEvent, OrchestrationEvent);
|
|
19871
19881
|
const WsPushChannelSchema = Literals([
|
|
19872
19882
|
WS_CHANNELS.gitActionProgress,
|
|
19883
|
+
WS_CHANNELS.gitStatusUpdated,
|
|
19873
19884
|
WS_CHANNELS.serverWelcome,
|
|
19874
19885
|
WS_CHANNELS.serverConfigUpdated,
|
|
19875
19886
|
WS_CHANNELS.serverProvidersUpdated,
|
|
@@ -19885,6 +19896,7 @@ const WsPush = Union([
|
|
|
19885
19896
|
WsPushServerConfigUpdated,
|
|
19886
19897
|
WsPushServerProvidersUpdated,
|
|
19887
19898
|
WsPushGitActionProgress,
|
|
19899
|
+
WsPushGitStatusUpdated,
|
|
19888
19900
|
WsPushTerminalEvent,
|
|
19889
19901
|
WsPushProfilesSwitched,
|
|
19890
19902
|
WsPushRateLimitsUpdated,
|
|
@@ -19917,6 +19929,10 @@ const LINE_COLUMN_SUFFIX_PATTERN = /:\d+(?::\d+)?$/;
|
|
|
19917
19929
|
function shouldUseGotoFlag(editor, target) {
|
|
19918
19930
|
return editor.supportsGoto && LINE_COLUMN_SUFFIX_PATTERN.test(target);
|
|
19919
19931
|
}
|
|
19932
|
+
function resolveAvailableCommand(commands, options = {}) {
|
|
19933
|
+
for (const command of commands) if (isCommandAvailable(command, options)) return command;
|
|
19934
|
+
return null;
|
|
19935
|
+
}
|
|
19920
19936
|
function fileManagerCommandForPlatform(platform) {
|
|
19921
19937
|
switch (platform) {
|
|
19922
19938
|
case "darwin": return "open";
|
|
@@ -19992,26 +20008,41 @@ function isCommandAvailable(command, options = {}) {
|
|
|
19992
20008
|
}
|
|
19993
20009
|
function resolveAvailableEditors(platform = process.platform, env = process.env) {
|
|
19994
20010
|
const available = [];
|
|
19995
|
-
for (const editor of EDITORS)
|
|
19996
|
-
|
|
19997
|
-
|
|
19998
|
-
|
|
20011
|
+
for (const editor of EDITORS) {
|
|
20012
|
+
if (editor.commands === null) {
|
|
20013
|
+
if (isCommandAvailable(fileManagerCommandForPlatform(platform), {
|
|
20014
|
+
platform,
|
|
20015
|
+
env
|
|
20016
|
+
})) available.push(editor.id);
|
|
20017
|
+
continue;
|
|
20018
|
+
}
|
|
20019
|
+
if (resolveAvailableCommand(editor.commands, {
|
|
20020
|
+
platform,
|
|
20021
|
+
env
|
|
20022
|
+
}) !== null) available.push(editor.id);
|
|
20023
|
+
}
|
|
19999
20024
|
return available;
|
|
20000
20025
|
}
|
|
20001
20026
|
/**
|
|
20002
20027
|
* Open - Service tag for browser/editor launch operations.
|
|
20003
20028
|
*/
|
|
20004
20029
|
var Open = class extends Service()("t3/open") {};
|
|
20005
|
-
const resolveEditorLaunch = fnUntraced(function* (input, platform = process.platform) {
|
|
20030
|
+
const resolveEditorLaunch = fnUntraced(function* (input, platform = process.platform, env = process.env) {
|
|
20006
20031
|
const editorDef = EDITORS.find((editor) => editor.id === input.editor);
|
|
20007
20032
|
if (!editorDef) return yield* new OpenError({ message: `Unknown editor: ${input.editor}` });
|
|
20008
|
-
if (editorDef.
|
|
20009
|
-
command
|
|
20010
|
-
|
|
20011
|
-
|
|
20012
|
-
|
|
20013
|
-
|
|
20014
|
-
|
|
20033
|
+
if (editorDef.commands) {
|
|
20034
|
+
const command = resolveAvailableCommand(editorDef.commands, {
|
|
20035
|
+
platform,
|
|
20036
|
+
env
|
|
20037
|
+
}) ?? editorDef.commands[0];
|
|
20038
|
+
return shouldUseGotoFlag(editorDef, input.cwd) ? {
|
|
20039
|
+
command,
|
|
20040
|
+
args: ["--goto", input.cwd]
|
|
20041
|
+
} : {
|
|
20042
|
+
command,
|
|
20043
|
+
args: [input.cwd]
|
|
20044
|
+
};
|
|
20045
|
+
}
|
|
20015
20046
|
if (editorDef.id !== "file-manager") return yield* new OpenError({ message: `Unsupported editor: ${input.editor}` });
|
|
20016
20047
|
return {
|
|
20017
20048
|
command: fileManagerCommandForPlatform(platform),
|
|
@@ -24278,10 +24309,13 @@ function projectEvent(model, event) {
|
|
|
24278
24309
|
createdAt: payload.createdAt,
|
|
24279
24310
|
updatedAt: payload.updatedAt
|
|
24280
24311
|
}, event.type, "message");
|
|
24281
|
-
const
|
|
24312
|
+
const existingMessage = thread.messages.find((entry) => entry.id === message.id);
|
|
24313
|
+
const shouldRefreshImportedMessageCreatedAt = message.id.startsWith(`${payload.threadId}:`) && !message.streaming;
|
|
24314
|
+
const cappedMessages = (existingMessage ? thread.messages.map((entry) => entry.id === message.id ? {
|
|
24282
24315
|
...entry,
|
|
24283
24316
|
text: message.streaming ? `${entry.text}${message.text}` : message.role === "user" && message.attachments !== void 0 ? message.text : message.text.length > 0 ? message.text : entry.text,
|
|
24284
24317
|
streaming: message.streaming,
|
|
24318
|
+
createdAt: shouldRefreshImportedMessageCreatedAt ? message.createdAt : entry.createdAt,
|
|
24285
24319
|
updatedAt: message.updatedAt,
|
|
24286
24320
|
turnId: message.turnId,
|
|
24287
24321
|
...message.attachments !== void 0 ? { attachments: message.attachments } : {}
|
|
@@ -28515,6 +28549,7 @@ const makeOrchestrationProjectionPipeline = gen(function* () {
|
|
|
28515
28549
|
const existingMessage = (yield* projectionThreadMessageRepository.listByThreadId({ threadId: event.payload.threadId })).find((row) => row.messageId === event.payload.messageId);
|
|
28516
28550
|
const nextText = existingMessage && event.payload.streaming ? `${existingMessage.text}${event.payload.text}` : existingMessage && event.payload.text.length === 0 ? existingMessage.text : event.payload.text;
|
|
28517
28551
|
const nextAttachments = event.payload.attachments !== void 0 ? yield* materializeAttachmentsForProjection({ attachments: event.payload.attachments }) : existingMessage?.attachments;
|
|
28552
|
+
const shouldRefreshImportedMessageCreatedAt = event.payload.messageId.startsWith(`${event.payload.threadId}:`) && !event.payload.streaming;
|
|
28518
28553
|
yield* projectionThreadMessageRepository.upsert({
|
|
28519
28554
|
messageId: event.payload.messageId,
|
|
28520
28555
|
threadId: event.payload.threadId,
|
|
@@ -28523,7 +28558,7 @@ const makeOrchestrationProjectionPipeline = gen(function* () {
|
|
|
28523
28558
|
text: nextText,
|
|
28524
28559
|
...nextAttachments !== void 0 ? { attachments: [...nextAttachments] } : {},
|
|
28525
28560
|
isStreaming: event.payload.streaming,
|
|
28526
|
-
createdAt: existingMessage
|
|
28561
|
+
createdAt: existingMessage && !shouldRefreshImportedMessageCreatedAt ? existingMessage.createdAt : event.payload.createdAt,
|
|
28527
28562
|
updatedAt: event.payload.updatedAt
|
|
28528
28563
|
});
|
|
28529
28564
|
return;
|
|
@@ -31692,6 +31727,8 @@ const EXTERNAL_SYNC_MARKER_VERSION = 1;
|
|
|
31692
31727
|
const EXTERNAL_THREAD_PAGE_SIZE = 100;
|
|
31693
31728
|
const EXTERNAL_SYNC_FOREGROUND_THREAD_LIMIT = 8;
|
|
31694
31729
|
const EXTERNAL_SYNC_APP_SERVER_IDLE_TTL_MS = 45e3;
|
|
31730
|
+
const EXTERNAL_SYNC_WATCHER_SETTLE_MS = 350;
|
|
31731
|
+
const EXTERNAL_SYNC_WATCH_DIRECTORY_NAMES = ["sessions", "archived_sessions"];
|
|
31695
31732
|
const DEFAULT_IMPORTED_MODEL = "gpt-5-codex";
|
|
31696
31733
|
function toImportedModelSelection(model) {
|
|
31697
31734
|
return {
|
|
@@ -31720,8 +31757,10 @@ const EXTERNAL_SYNC_APP_SERVER_CLIENT_INFO = {
|
|
|
31720
31757
|
let sharedExternalSyncAppServer = null;
|
|
31721
31758
|
let sharedExternalSyncAppServerHomePath = null;
|
|
31722
31759
|
let sharedExternalSyncAppServerIdleTimer = null;
|
|
31723
|
-
let
|
|
31760
|
+
let externalCodexThreadSyncWatchers = [];
|
|
31724
31761
|
let externalCodexThreadSyncWatcherHomePath = null;
|
|
31762
|
+
let externalCodexThreadSyncWatcherSettleTimer = null;
|
|
31763
|
+
let externalCodexThreadSyncWatcherPendingTrigger = null;
|
|
31725
31764
|
const externalSyncAppServerLeaseCount = /* @__PURE__ */ new Map();
|
|
31726
31765
|
let externalCodexThreadSyncRefreshQueue = null;
|
|
31727
31766
|
function asRecord$3(value) {
|
|
@@ -31732,6 +31771,11 @@ function clearSharedExternalSyncAppServerIdleTimer() {
|
|
|
31732
31771
|
clearTimeout(sharedExternalSyncAppServerIdleTimer);
|
|
31733
31772
|
sharedExternalSyncAppServerIdleTimer = null;
|
|
31734
31773
|
}
|
|
31774
|
+
function clearExternalCodexThreadSyncWatcherSettleTimer() {
|
|
31775
|
+
if (!externalCodexThreadSyncWatcherSettleTimer) return;
|
|
31776
|
+
clearTimeout(externalCodexThreadSyncWatcherSettleTimer);
|
|
31777
|
+
externalCodexThreadSyncWatcherSettleTimer = null;
|
|
31778
|
+
}
|
|
31735
31779
|
function incrementExternalSyncAppServerLease(appServer) {
|
|
31736
31780
|
externalSyncAppServerLeaseCount.set(appServer, (externalSyncAppServerLeaseCount.get(appServer) ?? 0) + 1);
|
|
31737
31781
|
}
|
|
@@ -31798,8 +31842,10 @@ async function withExternalSyncAppServer(homePath, task) {
|
|
|
31798
31842
|
}
|
|
31799
31843
|
}
|
|
31800
31844
|
function closeExternalCodexThreadSyncWatcher() {
|
|
31801
|
-
|
|
31802
|
-
|
|
31845
|
+
clearExternalCodexThreadSyncWatcherSettleTimer();
|
|
31846
|
+
externalCodexThreadSyncWatcherPendingTrigger = null;
|
|
31847
|
+
for (const watcher of externalCodexThreadSyncWatchers) watcher.close();
|
|
31848
|
+
externalCodexThreadSyncWatchers = [];
|
|
31803
31849
|
externalCodexThreadSyncWatcherHomePath = null;
|
|
31804
31850
|
}
|
|
31805
31851
|
function setExternalCodexThreadSyncRefreshQueue(queue) {
|
|
@@ -31819,26 +31865,102 @@ async function requestExternalCodexThreadSyncRefresh(trigger) {
|
|
|
31819
31865
|
}
|
|
31820
31866
|
}
|
|
31821
31867
|
function queueExternalCodexThreadSyncRefresh(trigger) {
|
|
31822
|
-
|
|
31868
|
+
externalCodexThreadSyncWatcherPendingTrigger = trigger;
|
|
31869
|
+
if (externalCodexThreadSyncWatcherSettleTimer) return;
|
|
31870
|
+
externalCodexThreadSyncWatcherSettleTimer = setTimeout(() => {
|
|
31871
|
+
const nextTrigger = externalCodexThreadSyncWatcherPendingTrigger ?? "external-codex-thread-sync-watcher";
|
|
31872
|
+
externalCodexThreadSyncWatcherPendingTrigger = null;
|
|
31873
|
+
clearExternalCodexThreadSyncWatcherSettleTimer();
|
|
31874
|
+
requestExternalCodexThreadSyncRefresh(nextTrigger);
|
|
31875
|
+
}, EXTERNAL_SYNC_WATCHER_SETTLE_MS);
|
|
31876
|
+
externalCodexThreadSyncWatcherSettleTimer.unref();
|
|
31877
|
+
}
|
|
31878
|
+
function supportsRecursiveExternalCodexThreadSyncWatcher() {
|
|
31879
|
+
return process.platform === "darwin" || process.platform === "win32";
|
|
31880
|
+
}
|
|
31881
|
+
function collectExternalCodexThreadSyncDirectoryWatchPaths(rootPath) {
|
|
31882
|
+
const collectedPaths = [];
|
|
31883
|
+
const stack = [rootPath];
|
|
31884
|
+
const seenPaths = /* @__PURE__ */ new Set();
|
|
31885
|
+
while (stack.length > 0) {
|
|
31886
|
+
const currentPath = stack.pop();
|
|
31887
|
+
if (!currentPath) continue;
|
|
31888
|
+
const resolvedCurrentPath = path.resolve(currentPath);
|
|
31889
|
+
if (seenPaths.has(resolvedCurrentPath)) continue;
|
|
31890
|
+
seenPaths.add(resolvedCurrentPath);
|
|
31891
|
+
let stat;
|
|
31892
|
+
try {
|
|
31893
|
+
stat = fs.statSync(resolvedCurrentPath);
|
|
31894
|
+
} catch {
|
|
31895
|
+
continue;
|
|
31896
|
+
}
|
|
31897
|
+
if (!stat.isDirectory()) continue;
|
|
31898
|
+
collectedPaths.push(resolvedCurrentPath);
|
|
31899
|
+
let entries;
|
|
31900
|
+
try {
|
|
31901
|
+
entries = fs.readdirSync(resolvedCurrentPath, { withFileTypes: true });
|
|
31902
|
+
} catch {
|
|
31903
|
+
continue;
|
|
31904
|
+
}
|
|
31905
|
+
for (const entry of entries) {
|
|
31906
|
+
if (!entry.isDirectory()) continue;
|
|
31907
|
+
stack.push(path.join(resolvedCurrentPath, entry.name));
|
|
31908
|
+
}
|
|
31909
|
+
}
|
|
31910
|
+
return collectedPaths;
|
|
31911
|
+
}
|
|
31912
|
+
function collectExternalCodexThreadSyncWatchTargets(homePath) {
|
|
31913
|
+
const recursive = supportsRecursiveExternalCodexThreadSyncWatcher();
|
|
31914
|
+
const targets = [];
|
|
31915
|
+
for (const relativePath of EXTERNAL_SYNC_WATCH_DIRECTORY_NAMES) {
|
|
31916
|
+
const absolutePath = path.join(homePath, relativePath);
|
|
31917
|
+
if (!fs.existsSync(absolutePath)) continue;
|
|
31918
|
+
if (recursive) {
|
|
31919
|
+
targets.push({
|
|
31920
|
+
watchPath: absolutePath,
|
|
31921
|
+
label: relativePath,
|
|
31922
|
+
recursive: true
|
|
31923
|
+
});
|
|
31924
|
+
continue;
|
|
31925
|
+
}
|
|
31926
|
+
for (const watchPath of collectExternalCodexThreadSyncDirectoryWatchPaths(absolutePath)) targets.push({
|
|
31927
|
+
watchPath,
|
|
31928
|
+
label: path.relative(homePath, watchPath) || ".",
|
|
31929
|
+
recursive: false
|
|
31930
|
+
});
|
|
31931
|
+
}
|
|
31932
|
+
if (targets.length === 0) targets.push({
|
|
31933
|
+
watchPath: homePath,
|
|
31934
|
+
label: ".",
|
|
31935
|
+
recursive
|
|
31936
|
+
});
|
|
31937
|
+
return targets;
|
|
31823
31938
|
}
|
|
31824
31939
|
function startExternalCodexThreadSyncWatcher(homePath) {
|
|
31825
31940
|
const resolvedHomePath = path.resolve(homePath);
|
|
31826
|
-
if (
|
|
31941
|
+
if (externalCodexThreadSyncWatchers.length > 0 && externalCodexThreadSyncWatcherHomePath === resolvedHomePath) return;
|
|
31827
31942
|
closeExternalCodexThreadSyncWatcher();
|
|
31828
31943
|
try {
|
|
31829
|
-
|
|
31830
|
-
|
|
31831
|
-
|
|
31832
|
-
|
|
31833
|
-
|
|
31834
|
-
|
|
31835
|
-
console.warn("[t3 external thread sync] watcher error", {
|
|
31836
|
-
homePath: resolvedHomePath,
|
|
31837
|
-
error
|
|
31944
|
+
const watchTargets = collectExternalCodexThreadSyncWatchTargets(resolvedHomePath);
|
|
31945
|
+
for (const target of watchTargets) {
|
|
31946
|
+
const watcher = fs.watch(target.watchPath, { recursive: target.recursive }, (_eventType, filename) => {
|
|
31947
|
+
if (filename && typeof filename === "string" && !filename.trim()) return;
|
|
31948
|
+
const suffix = typeof filename === "string" && filename.trim().length > 0 ? `:${filename}` : "";
|
|
31949
|
+
queueExternalCodexThreadSyncRefresh(`${target.label}${suffix}`);
|
|
31838
31950
|
});
|
|
31839
|
-
|
|
31840
|
-
|
|
31951
|
+
watcher.on("error", (error) => {
|
|
31952
|
+
console.warn("[t3 external thread sync] watcher error", {
|
|
31953
|
+
homePath: resolvedHomePath,
|
|
31954
|
+
watchPath: target.watchPath,
|
|
31955
|
+
error
|
|
31956
|
+
});
|
|
31957
|
+
closeExternalCodexThreadSyncWatcher();
|
|
31958
|
+
});
|
|
31959
|
+
externalCodexThreadSyncWatchers.push(watcher);
|
|
31960
|
+
}
|
|
31961
|
+
externalCodexThreadSyncWatcherHomePath = resolvedHomePath;
|
|
31841
31962
|
} catch (error) {
|
|
31963
|
+
closeExternalCodexThreadSyncWatcher();
|
|
31842
31964
|
console.warn("[t3 external thread sync] failed to start watcher", {
|
|
31843
31965
|
homePath: resolvedHomePath,
|
|
31844
31966
|
error
|
|
@@ -31886,6 +32008,57 @@ function linePreview(text, fallback) {
|
|
|
31886
32008
|
if (!normalized) return fallback;
|
|
31887
32009
|
return normalized.length > 120 ? `${normalized.slice(0, 117)}...` : normalized;
|
|
31888
32010
|
}
|
|
32011
|
+
function hasImportedVisibleUserMessageContent(payload) {
|
|
32012
|
+
return firstNonEmptyString(payload.message) !== null || Array.isArray(payload.text_elements) && payload.text_elements.length > 0 || Array.isArray(payload.images) && payload.images.length > 0 || Array.isArray(payload.local_images) && payload.local_images.length > 0;
|
|
32013
|
+
}
|
|
32014
|
+
async function readImportedVisibleMessageTimeline(thread) {
|
|
32015
|
+
const threadPath = resolveLegacyFilePath(firstNonEmptyString(thread.path) ?? "");
|
|
32016
|
+
if (!threadPath) return null;
|
|
32017
|
+
let contents;
|
|
32018
|
+
try {
|
|
32019
|
+
contents = await fs$1.readFile(threadPath, "utf8");
|
|
32020
|
+
} catch {
|
|
32021
|
+
return null;
|
|
32022
|
+
}
|
|
32023
|
+
const user = [];
|
|
32024
|
+
const assistant = [];
|
|
32025
|
+
for (const rawLine of contents.split(/\r?\n/)) {
|
|
32026
|
+
const line = rawLine.trim();
|
|
32027
|
+
if (!line) continue;
|
|
32028
|
+
let entry;
|
|
32029
|
+
try {
|
|
32030
|
+
entry = JSON.parse(line);
|
|
32031
|
+
} catch {
|
|
32032
|
+
continue;
|
|
32033
|
+
}
|
|
32034
|
+
const record = asRecord$3(entry);
|
|
32035
|
+
if (!record || asTrimmedString$1(record.type) !== "event_msg") continue;
|
|
32036
|
+
const payload = asRecord$3(record.payload);
|
|
32037
|
+
if (!payload) continue;
|
|
32038
|
+
const timestamp = firstNonEmptyString(record.timestamp, payload.timestamp, payload.createdAt, payload.created_at);
|
|
32039
|
+
if (!timestamp || !Number.isFinite(Date.parse(timestamp))) continue;
|
|
32040
|
+
switch (asTrimmedString$1(payload.type)) {
|
|
32041
|
+
case "user_message":
|
|
32042
|
+
if (hasImportedVisibleUserMessageContent(payload)) user.push(timestamp);
|
|
32043
|
+
break;
|
|
32044
|
+
case "agent_message":
|
|
32045
|
+
if (firstNonEmptyString(payload.message) !== null) assistant.push(timestamp);
|
|
32046
|
+
break;
|
|
32047
|
+
}
|
|
32048
|
+
}
|
|
32049
|
+
return user.length > 0 || assistant.length > 0 ? {
|
|
32050
|
+
user,
|
|
32051
|
+
assistant
|
|
32052
|
+
} : null;
|
|
32053
|
+
}
|
|
32054
|
+
function takeImportedVisibleMessageTimestamp(timeline, role) {
|
|
32055
|
+
if (!timeline) return null;
|
|
32056
|
+
const queue = timeline[role];
|
|
32057
|
+
const nextTimestamp = queue[0];
|
|
32058
|
+
if (!nextTimestamp) return null;
|
|
32059
|
+
queue.shift();
|
|
32060
|
+
return nextTimestamp;
|
|
32061
|
+
}
|
|
31889
32062
|
function listThreadSummariesFromResponse(payload) {
|
|
31890
32063
|
const root = asRecord$3(payload);
|
|
31891
32064
|
const result = asRecord$3(root?.result) ?? root;
|
|
@@ -32216,6 +32389,7 @@ async function buildThreadImportArtifacts(input) {
|
|
|
32216
32389
|
const activities = [];
|
|
32217
32390
|
const proposedPlans = [];
|
|
32218
32391
|
const turns = Array.isArray(thread.turns) ? thread.turns : [];
|
|
32392
|
+
const visibleMessageTimeline = await readImportedVisibleMessageTimeline(thread);
|
|
32219
32393
|
let latestArtifactUpdatedAt = createdAt;
|
|
32220
32394
|
let latestUpdatedAt = summaryUpdatedAt;
|
|
32221
32395
|
for (const [turnIndex, turnEntry] of turns.entries()) {
|
|
@@ -32229,7 +32403,8 @@ async function buildThreadImportArtifacts(input) {
|
|
|
32229
32403
|
if (!item) continue;
|
|
32230
32404
|
const itemId = firstNonEmptyString(item.id) ?? `${turnIndex + 1}-${itemIndex + 1}`;
|
|
32231
32405
|
const type = asTrimmedString$1(item.type);
|
|
32232
|
-
const
|
|
32406
|
+
const visibleMessageRole = type === "userMessage" ? "user" : type === "agentMessage" ? "assistant" : null;
|
|
32407
|
+
const timestamp = nextIsoFromThreadCursor(thread, cursor, (visibleMessageRole !== null ? takeImportedVisibleMessageTimestamp(visibleMessageTimeline, visibleMessageRole) : null) ?? item.createdAt ?? item.updatedAt ?? item.startedAt ?? item.completedAt ?? turn.createdAt ?? turn.updatedAt ?? turn.startedAt ?? turn.completedAt, fallbackBaseMs);
|
|
32233
32408
|
if (timestamp > latestArtifactUpdatedAt) latestArtifactUpdatedAt = timestamp;
|
|
32234
32409
|
if (timestamp > latestUpdatedAt) latestUpdatedAt = timestamp;
|
|
32235
32410
|
if (type === "userMessage") {
|
|
@@ -32294,7 +32469,7 @@ async function buildThreadImportArtifacts(input) {
|
|
|
32294
32469
|
}
|
|
32295
32470
|
const turnError = firstNonEmptyString(turn.error);
|
|
32296
32471
|
if (turnError) {
|
|
32297
|
-
const timestamp = nextIsoFromThreadCursor(thread, cursor, turn.updatedAt ?? turn.completedAt ?? thread.updatedAt, fallbackBaseMs);
|
|
32472
|
+
const timestamp = nextIsoFromThreadCursor(thread, cursor, turn.updatedAt ?? turn.completedAt ?? turn.startedAt ?? thread.updatedAt, fallbackBaseMs);
|
|
32298
32473
|
if (timestamp > latestArtifactUpdatedAt) latestArtifactUpdatedAt = timestamp;
|
|
32299
32474
|
if (timestamp > latestUpdatedAt) latestUpdatedAt = timestamp;
|
|
32300
32475
|
const turnKey = turnId ? turnId : TurnId.makeUnsafe(`${thread.id}:turn:${turnIndex + 1}`);
|
|
@@ -32526,6 +32701,11 @@ function latestIsoTimestamp(left, right) {
|
|
|
32526
32701
|
const rightMs = toEpochMs(right, 0);
|
|
32527
32702
|
return new Date(Math.max(leftMs, rightMs)).toISOString();
|
|
32528
32703
|
}
|
|
32704
|
+
function shouldRefreshImportedMessage(input) {
|
|
32705
|
+
const { existingMessage, nextMessage } = input;
|
|
32706
|
+
if (!existingMessage) return true;
|
|
32707
|
+
return existingMessage.createdAt !== nextMessage.createdAt || existingMessage.updatedAt !== nextMessage.updatedAt || existingMessage.text !== nextMessage.text || existingMessage.turnId !== nextMessage.turnId || existingMessage.streaming !== nextMessage.streaming || JSON.stringify(existingMessage.attachments ?? null) !== JSON.stringify(nextMessage.attachments ?? null);
|
|
32708
|
+
}
|
|
32529
32709
|
function hasImportedThreadArtifacts(state) {
|
|
32530
32710
|
return state.messageIds.size > 0 || state.activityIds.size > 0 || state.planIds.size > 0;
|
|
32531
32711
|
}
|
|
@@ -32728,7 +32908,11 @@ function importExternalThreadArtifacts(input) {
|
|
|
32728
32908
|
input.state.threadStateById.set(input.threadId, existingThreadState);
|
|
32729
32909
|
let importedMessageCount = 0;
|
|
32730
32910
|
for (const message of input.importArtifacts.messages) {
|
|
32731
|
-
|
|
32911
|
+
const existingMessage = existingThreadReadModel?.messages.find((entry) => entry.id === message.id);
|
|
32912
|
+
if (!shouldRefreshImportedMessage({
|
|
32913
|
+
existingMessage,
|
|
32914
|
+
nextMessage: message
|
|
32915
|
+
}) || shouldSkipImportedMessageForLocalContinuation({
|
|
32732
32916
|
message,
|
|
32733
32917
|
dedupState: localContinuationDedupState
|
|
32734
32918
|
})) continue;
|
|
@@ -52640,6 +52824,10 @@ function sendDesktopParentMessage$1(payload) {
|
|
|
52640
52824
|
process.send(payload);
|
|
52641
52825
|
} catch {}
|
|
52642
52826
|
}
|
|
52827
|
+
const GIT_STATUS_WATCH_REFRESH_INTERVAL_MS = 1e4;
|
|
52828
|
+
function fingerprintGitStatus(status) {
|
|
52829
|
+
return JSON.stringify(status);
|
|
52830
|
+
}
|
|
52643
52831
|
function appendSessionError(session, chunk) {
|
|
52644
52832
|
const normalized = compactErrorText(chunk);
|
|
52645
52833
|
if (!normalized) return;
|
|
@@ -52742,6 +52930,8 @@ const createServer = fn(function* () {
|
|
|
52742
52930
|
});
|
|
52743
52931
|
yield* addFinalizer$1(() => promise(() => accountPool.dispose()));
|
|
52744
52932
|
const clients = yield* make$11(/* @__PURE__ */ new Set());
|
|
52933
|
+
const watchedGitStatusesByCwd = /* @__PURE__ */ new Map();
|
|
52934
|
+
const watchedGitStatusCwdsByClient = /* @__PURE__ */ new WeakMap();
|
|
52745
52935
|
const logger = createLogger("ws");
|
|
52746
52936
|
const readiness = yield* makeServerReadiness;
|
|
52747
52937
|
function logOutgoingPush(push, recipients) {
|
|
@@ -53236,6 +53426,96 @@ const createServer = fn(function* () {
|
|
|
53236
53426
|
cause
|
|
53237
53427
|
})));
|
|
53238
53428
|
const runPromise$1 = runPromiseWith(yield* services());
|
|
53429
|
+
const publishGitStatusToClient = (client, cwd, status) => pushBus.publishClient(client, WS_CHANNELS.gitStatusUpdated, {
|
|
53430
|
+
cwd,
|
|
53431
|
+
status
|
|
53432
|
+
}).pipe(asVoid);
|
|
53433
|
+
const stopGitStatusWatcher = (cwd, watcher) => {
|
|
53434
|
+
clearInterval(watcher.intervalId);
|
|
53435
|
+
watchedGitStatusesByCwd.delete(cwd);
|
|
53436
|
+
};
|
|
53437
|
+
const scheduleWatchedGitStatusRefresh = (cwd) => {
|
|
53438
|
+
const watcher = watchedGitStatusesByCwd.get(cwd);
|
|
53439
|
+
if (!watcher) return Promise.resolve();
|
|
53440
|
+
if (watcher.refreshPromise) return watcher.refreshPromise;
|
|
53441
|
+
const refreshPromise = runPromise$1(gitManager.status({ cwd }).pipe(catch_(() => succeed(null)), flatMap((status) => {
|
|
53442
|
+
if (status === null) return void_$1;
|
|
53443
|
+
return sync(() => {
|
|
53444
|
+
const currentWatcher = watchedGitStatusesByCwd.get(cwd);
|
|
53445
|
+
if (!currentWatcher) return null;
|
|
53446
|
+
const nextFingerprint = fingerprintGitStatus(status);
|
|
53447
|
+
const hasChanged = currentWatcher.lastFingerprint !== nextFingerprint;
|
|
53448
|
+
currentWatcher.lastFingerprint = nextFingerprint;
|
|
53449
|
+
currentWatcher.lastStatus = status;
|
|
53450
|
+
if (!hasChanged || currentWatcher.subscribers.size === 0) return null;
|
|
53451
|
+
return [...currentWatcher.subscribers];
|
|
53452
|
+
}).pipe(flatMap((subscribers) => subscribers === null ? void_$1 : forEach(subscribers, (client) => publishGitStatusToClient(client, cwd, status), { discard: true })));
|
|
53453
|
+
})));
|
|
53454
|
+
let trackedRefreshPromise;
|
|
53455
|
+
trackedRefreshPromise = refreshPromise.finally(() => {
|
|
53456
|
+
const currentWatcher = watchedGitStatusesByCwd.get(cwd);
|
|
53457
|
+
if (currentWatcher?.refreshPromise === trackedRefreshPromise) currentWatcher.refreshPromise = null;
|
|
53458
|
+
});
|
|
53459
|
+
watcher.refreshPromise = trackedRefreshPromise;
|
|
53460
|
+
return trackedRefreshPromise;
|
|
53461
|
+
};
|
|
53462
|
+
const getOrCreateGitStatusWatcher = (cwd) => {
|
|
53463
|
+
const existing = watchedGitStatusesByCwd.get(cwd);
|
|
53464
|
+
if (existing) return existing;
|
|
53465
|
+
const watcher = {
|
|
53466
|
+
subscribers: /* @__PURE__ */ new Set(),
|
|
53467
|
+
intervalId: setInterval(() => {
|
|
53468
|
+
scheduleWatchedGitStatusRefresh(cwd);
|
|
53469
|
+
}, GIT_STATUS_WATCH_REFRESH_INTERVAL_MS),
|
|
53470
|
+
lastFingerprint: null,
|
|
53471
|
+
lastStatus: null,
|
|
53472
|
+
refreshPromise: null
|
|
53473
|
+
};
|
|
53474
|
+
watchedGitStatusesByCwd.set(cwd, watcher);
|
|
53475
|
+
return watcher;
|
|
53476
|
+
};
|
|
53477
|
+
const removeGitStatusWatcherSubscriber = (client, cwd) => {
|
|
53478
|
+
const watcher = watchedGitStatusesByCwd.get(cwd);
|
|
53479
|
+
if (!watcher) return;
|
|
53480
|
+
watcher.subscribers.delete(client);
|
|
53481
|
+
if (watcher.subscribers.size === 0) stopGitStatusWatcher(cwd, watcher);
|
|
53482
|
+
};
|
|
53483
|
+
const watchGitStatusForClient = fnUntraced(function* (client, cwd) {
|
|
53484
|
+
let watchedCwds = watchedGitStatusCwdsByClient.get(client);
|
|
53485
|
+
if (!watchedCwds) {
|
|
53486
|
+
watchedCwds = /* @__PURE__ */ new Set();
|
|
53487
|
+
watchedGitStatusCwdsByClient.set(client, watchedCwds);
|
|
53488
|
+
}
|
|
53489
|
+
if (watchedCwds.has(cwd)) {
|
|
53490
|
+
const watcher = watchedGitStatusesByCwd.get(cwd);
|
|
53491
|
+
if (watcher?.lastStatus) yield* publishGitStatusToClient(client, cwd, watcher.lastStatus);
|
|
53492
|
+
return;
|
|
53493
|
+
}
|
|
53494
|
+
watchedCwds.add(cwd);
|
|
53495
|
+
const watcher = getOrCreateGitStatusWatcher(cwd);
|
|
53496
|
+
watcher.subscribers.add(client);
|
|
53497
|
+
if (watcher.lastStatus) {
|
|
53498
|
+
yield* publishGitStatusToClient(client, cwd, watcher.lastStatus);
|
|
53499
|
+
return;
|
|
53500
|
+
}
|
|
53501
|
+
yield* promise(() => scheduleWatchedGitStatusRefresh(cwd));
|
|
53502
|
+
});
|
|
53503
|
+
const unwatchGitStatusForClient = (client, cwd) => {
|
|
53504
|
+
const watchedCwds = watchedGitStatusCwdsByClient.get(client);
|
|
53505
|
+
if (!watchedCwds?.delete(cwd)) return;
|
|
53506
|
+
if (watchedCwds.size === 0) watchedGitStatusCwdsByClient.delete(client);
|
|
53507
|
+
removeGitStatusWatcherSubscriber(client, cwd);
|
|
53508
|
+
};
|
|
53509
|
+
const unwatchAllGitStatusForClient = (client) => {
|
|
53510
|
+
const watchedCwds = watchedGitStatusCwdsByClient.get(client);
|
|
53511
|
+
if (!watchedCwds) return;
|
|
53512
|
+
watchedGitStatusCwdsByClient.delete(client);
|
|
53513
|
+
for (const cwd of watchedCwds) removeGitStatusWatcherSubscriber(client, cwd);
|
|
53514
|
+
};
|
|
53515
|
+
yield* addFinalizer$1(sync(() => {
|
|
53516
|
+
for (const watcher of watchedGitStatusesByCwd.values()) clearInterval(watcher.intervalId);
|
|
53517
|
+
watchedGitStatusesByCwd.clear();
|
|
53518
|
+
}));
|
|
53239
53519
|
const telegramBridge = createTelegramBridge({
|
|
53240
53520
|
getSnapshot: () => runPromise$1(projectionReadModelQuery.getSnapshot()),
|
|
53241
53521
|
getThreadSnapshot: (threadId) => runPromise$1(gen(function* () {
|
|
@@ -53410,6 +53690,18 @@ const createServer = fn(function* () {
|
|
|
53410
53690
|
const body = stripRequestTag(request.body);
|
|
53411
53691
|
return yield* gitManager.status(body);
|
|
53412
53692
|
}
|
|
53693
|
+
case WS_METHODS.gitWatchStatus: {
|
|
53694
|
+
const body = stripRequestTag(request.body);
|
|
53695
|
+
if (!ws) return yield* new RouteRequestError({ message: "Git status watching requires a WebSocket client." });
|
|
53696
|
+
yield* watchGitStatusForClient(ws, yield* normalizeProjectWorkspaceRoot(body.cwd));
|
|
53697
|
+
return;
|
|
53698
|
+
}
|
|
53699
|
+
case WS_METHODS.gitUnwatchStatus: {
|
|
53700
|
+
const body = stripRequestTag(request.body);
|
|
53701
|
+
if (!ws) return yield* new RouteRequestError({ message: "Git status watching requires a WebSocket client." });
|
|
53702
|
+
unwatchGitStatusForClient(ws, yield* normalizeProjectWorkspaceRoot(body.cwd));
|
|
53703
|
+
return;
|
|
53704
|
+
}
|
|
53413
53705
|
case WS_METHODS.gitPull: {
|
|
53414
53706
|
const body = stripRequestTag(request.body);
|
|
53415
53707
|
return yield* git.pullCurrentBranch(body.cwd);
|
|
@@ -53918,12 +54210,14 @@ const createServer = fn(function* () {
|
|
|
53918
54210
|
runPromise$1(handleMessage(ws, raw).pipe(ignoreCause({ log: true })));
|
|
53919
54211
|
});
|
|
53920
54212
|
ws.on("close", () => {
|
|
54213
|
+
unwatchAllGitStatusForClient(ws);
|
|
53921
54214
|
runPromise$1(update(clients, (clients) => {
|
|
53922
54215
|
clients.delete(ws);
|
|
53923
54216
|
return clients;
|
|
53924
54217
|
}));
|
|
53925
54218
|
});
|
|
53926
54219
|
ws.on("error", () => {
|
|
54220
|
+
unwatchAllGitStatusForClient(ws);
|
|
53927
54221
|
runPromise$1(update(clients, (clients) => {
|
|
53928
54222
|
clients.delete(ws);
|
|
53929
54223
|
return clients;
|