@sideboard-ai/core 0.1.208 → 0.1.210
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/{abletime-I4IYZBKU.js → abletime-GDZLZRMY.js} +4 -4
- package/dist/{abletime-UWSSLXH3.js → abletime-QGGYL2G4.js} +4 -4
- package/dist/{abletime-oauth-C3BQXKW3.js → abletime-oauth-3X3BAPTF.js} +3 -3
- package/dist/{abletime-oauth-UZHPB3W2.js → abletime-oauth-F335TWKY.js} +3 -3
- package/dist/{abletime-rest-HYNYDYK3.js → abletime-rest-LAGTPAJL.js} +3 -3
- package/dist/{abletime-rest-5YPPEOKK.js → abletime-rest-PLJVY3H3.js} +3 -3
- package/dist/agents/cursor-runner.js +3 -3
- package/dist/{agents-QHQXR55O.js → agents-G3TFVFBQ.js} +6 -5
- package/dist/{agents-CCS5IEBV.js → agents-IQZUN47D.js} +6 -5
- package/dist/{app-settings-GJ6KDYEF.js → app-settings-2TN3WLZV.js} +7 -1
- package/dist/{app-settings-R2KNCT37.js → app-settings-XCRNCEEE.js} +7 -1
- package/dist/{chunk-F4LZUEIO.js → chunk-2M5B7YNY.js} +2 -2
- package/dist/{chunk-C6ZNQV5W.js → chunk-2R6BZRRB.js} +117 -25
- package/dist/{chunk-HA4EZKFY.js → chunk-3S2LDD2F.js} +3 -3
- package/dist/{chunk-6YZLSZLK.js → chunk-42IULNIY.js} +3 -3
- package/dist/{chunk-C5MNMITQ.js → chunk-AOQZZA3M.js} +119 -25
- package/dist/{chunk-4EGK47WV.js → chunk-BTC2D6LS.js} +217 -0
- package/dist/{chunk-7DKX5JLT.js → chunk-FGTPRMPS.js} +18 -3
- package/dist/{chunk-X45BV4VX.js → chunk-G4TANQC3.js} +5 -5
- package/dist/{chunk-Y4CF7LHH.js → chunk-L5CIEBLR.js} +232 -0
- package/dist/{chunk-WXWJ5MJ4.js → chunk-LS6TSOCE.js} +5 -5
- package/dist/{chunk-6J4OQ6TF.js → chunk-MN6YUD4O.js} +3 -3
- package/dist/{chunk-7PEIIN7P.js → chunk-NDE5RKZP.js} +24 -87
- package/dist/{chunk-W6X4GZJG.js → chunk-REZRGCKV.js} +3 -3
- package/dist/{chunk-NJ2CCLV6.js → chunk-WX4S775K.js} +2 -2
- package/dist/chunk-X5B3OS5I.js +34 -0
- package/dist/{chunk-ZHCB4CKR.js → chunk-X5PUFYDJ.js} +18 -3
- package/dist/{chunk-TEDEVD4O.js → chunk-YVE4PXCJ.js} +2 -2
- package/dist/{chunk-A6SOSLUV.js → chunk-YYELAUKP.js} +24 -94
- package/dist/{chunk-DNTPX6HV.js → chunk-ZC664YBJ.js} +3 -3
- package/dist/{chunk-OP6CFVTB.js → chunk-ZZNZX2QW.js} +2 -2
- package/dist/{coordinator-prompt-WOTJQMD5.js → coordinator-prompt-GCITY3Q5.js} +5 -4
- package/dist/{coordinator-prompt-TUHB6ZFA.js → coordinator-prompt-PONGPWIP.js} +5 -4
- package/dist/{cursor-recover-TXVTLAMA.js → cursor-recover-4PQAADAU.js} +3 -28
- package/dist/{global-workspace-V6G2KH2V.js → global-workspace-LIZHU4GM.js} +5 -4
- package/dist/{global-workspace-5UUUNA4A.js → global-workspace-LQZLTGFL.js} +5 -4
- package/dist/index.cjs +681 -385
- package/dist/index.d.cts +96 -5
- package/dist/index.d.ts +96 -5
- package/dist/index.js +52 -19
- package/dist/mcp/run-stdio.cjs +647 -385
- package/dist/mcp/run-stdio.js +12 -11
- package/dist/{orchestrator-4IGHVRAF.js → orchestrator-G5HELCVT.js} +7 -6
- package/dist/{orchestrator-D4AQNF25.js → orchestrator-ZBUXJCII.js} +7 -6
- package/dist/{thread-store-FMWDFAO5.js → thread-store-FCWU7Y3X.js} +2 -1
- package/dist/{thread-store-ESZYZSVC.js → thread-store-KMZRQEPY.js} +2 -1
- package/dist/{workspaces-PZ36M7EQ.js → workspaces-2XW2DMRG.js} +5 -4
- package/dist/{workspaces-CLNANACI.js → workspaces-T6PMQZYQ.js} +5 -4
- package/dist/{worktree-JKTM47K5.js → worktree-2OEMMFRT.js} +4 -3
- package/dist/{worktree-NC4XQNQI.js → worktree-5ZGWKKZ6.js} +4 -3
- package/package.json +1 -1
|
@@ -8,9 +8,7 @@ import {
|
|
|
8
8
|
adjustBrightsyTurnExit,
|
|
9
9
|
allAdapters,
|
|
10
10
|
applyAgentEvent,
|
|
11
|
-
applyTurnUsage,
|
|
12
11
|
clipAgentEventForPaint,
|
|
13
|
-
contextTokens,
|
|
14
12
|
finalizeParts,
|
|
15
13
|
getAdapter,
|
|
16
14
|
isBrightsyNdjsonLine,
|
|
@@ -25,9 +23,8 @@ import {
|
|
|
25
23
|
partsToAssistantText,
|
|
26
24
|
resolveQuotaFallbackAgent,
|
|
27
25
|
stripBrightsyNdjsonNoise,
|
|
28
|
-
sumUsageList,
|
|
29
26
|
toolDescription
|
|
30
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-YYELAUKP.js";
|
|
31
28
|
import {
|
|
32
29
|
SLACK_REPLY_FORMATTING,
|
|
33
30
|
addWorkspace,
|
|
@@ -50,7 +47,7 @@ import {
|
|
|
50
47
|
stageAbsolutePathsAsAttachments,
|
|
51
48
|
stageBuffersAsAttachments,
|
|
52
49
|
syncWorkspacesFromThreads
|
|
53
|
-
} from "./chunk-
|
|
50
|
+
} from "./chunk-3S2LDD2F.js";
|
|
54
51
|
import {
|
|
55
52
|
addPrStackLayer,
|
|
56
53
|
allocateTeamName,
|
|
@@ -100,7 +97,7 @@ import {
|
|
|
100
97
|
worktreeDisplayLabelForGroup,
|
|
101
98
|
worktreeNameFromPath,
|
|
102
99
|
worktreeSlugForTicket
|
|
103
|
-
} from "./chunk-
|
|
100
|
+
} from "./chunk-ZZNZX2QW.js";
|
|
104
101
|
import {
|
|
105
102
|
ATTACHMENTS_DIR,
|
|
106
103
|
DETACHED_JOBS_DIR,
|
|
@@ -134,19 +131,28 @@ import {
|
|
|
134
131
|
turnFailChatText
|
|
135
132
|
} from "./chunk-JZHRZ3DR.js";
|
|
136
133
|
import {
|
|
134
|
+
HISTORY_CLEANUP_INTERVAL_HOURS_DEFAULT,
|
|
135
|
+
applyTurnUsage,
|
|
137
136
|
assertOrchestratorCapableAgent,
|
|
137
|
+
autoCleanupHistoryEnabled,
|
|
138
138
|
childEnvWithAppSettings,
|
|
139
139
|
coerceOrchestratorAgent,
|
|
140
|
+
contextTokens,
|
|
140
141
|
followUpBehavior,
|
|
141
142
|
formatViewerContextDirective,
|
|
142
143
|
formatViewerContextReminder,
|
|
143
144
|
getIssueSource,
|
|
145
|
+
historyMaxCount,
|
|
146
|
+
historyMaxDays,
|
|
147
|
+
historyRetentionStubMessage,
|
|
144
148
|
isAbleTimeConnected,
|
|
145
149
|
isLinearConnected,
|
|
146
150
|
isOrchestratorCapableAgent,
|
|
147
151
|
isSecureFileEncrypted,
|
|
148
152
|
loadAppSettings,
|
|
149
153
|
orchestrationQuotaFallbackAgent,
|
|
154
|
+
planHistoryAgePurge,
|
|
155
|
+
planHistoryRetention,
|
|
150
156
|
readSecureJson,
|
|
151
157
|
resolveEffectiveIssueSource,
|
|
152
158
|
resolveNewThreadOptions,
|
|
@@ -154,10 +160,11 @@ import {
|
|
|
154
160
|
resolveVaultKey,
|
|
155
161
|
resolveViewerProfileForRepo,
|
|
156
162
|
saveAppSettings,
|
|
163
|
+
sumUsageList,
|
|
157
164
|
updateAdvancedSettings,
|
|
158
165
|
usageOnLimit,
|
|
159
166
|
writeSecureJson
|
|
160
|
-
} from "./chunk-
|
|
167
|
+
} from "./chunk-L5CIEBLR.js";
|
|
161
168
|
import {
|
|
162
169
|
stripNestedElectronEnv
|
|
163
170
|
} from "./chunk-4TR3HZFT.js";
|
|
@@ -182,7 +189,7 @@ import {
|
|
|
182
189
|
updateThread,
|
|
183
190
|
withThreadLock,
|
|
184
191
|
writeThread
|
|
185
|
-
} from "./chunk-
|
|
192
|
+
} from "./chunk-FGTPRMPS.js";
|
|
186
193
|
import {
|
|
187
194
|
appDataDir,
|
|
188
195
|
findConventionSetup,
|
|
@@ -476,7 +483,7 @@ async function continueSourceThread(threadId, prompt) {
|
|
|
476
483
|
await continueOnReply(threadId, prompt);
|
|
477
484
|
return;
|
|
478
485
|
}
|
|
479
|
-
const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-
|
|
486
|
+
const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-ZBUXJCII.js");
|
|
480
487
|
await getOrchestrator2().send(threadId, prompt);
|
|
481
488
|
} catch {
|
|
482
489
|
}
|
|
@@ -810,9 +817,9 @@ async function spawnAgentTurn(thread, input, onEvent) {
|
|
|
810
817
|
`Cannot spawn ${thread.agent}: thread ${thread.id} has no worktreePath`
|
|
811
818
|
);
|
|
812
819
|
}
|
|
813
|
-
const { isGlobalThread: isGlobalThread2 } = await import("./global-workspace-
|
|
820
|
+
const { isGlobalThread: isGlobalThread2 } = await import("./global-workspace-LQZLTGFL.js");
|
|
814
821
|
if (isGlobalThread2(thread)) {
|
|
815
|
-
const { ensureGlobalCoordinatorCwd: ensureGlobalCoordinatorCwd2 } = await import("./coordinator-prompt-
|
|
822
|
+
const { ensureGlobalCoordinatorCwd: ensureGlobalCoordinatorCwd2 } = await import("./coordinator-prompt-GCITY3Q5.js");
|
|
816
823
|
ensureGlobalCoordinatorCwd2(
|
|
817
824
|
isOrchestratorThread(thread) ? { orchestratorThreadId: thread.id } : void 0
|
|
818
825
|
);
|
|
@@ -2592,6 +2599,69 @@ function worktreeCleanupSettings() {
|
|
|
2592
2599
|
};
|
|
2593
2600
|
}
|
|
2594
2601
|
|
|
2602
|
+
// src/store/history-cleanup.ts
|
|
2603
|
+
function stripArchivedTranscript(thread) {
|
|
2604
|
+
writeThread(
|
|
2605
|
+
{
|
|
2606
|
+
...thread,
|
|
2607
|
+
attachments: [],
|
|
2608
|
+
pendingTurnAttachments: [],
|
|
2609
|
+
messages: [historyRetentionStubMessage(thread)]
|
|
2610
|
+
},
|
|
2611
|
+
{ touch: false }
|
|
2612
|
+
);
|
|
2613
|
+
}
|
|
2614
|
+
function cleanupArchivedHistory(opts = {}) {
|
|
2615
|
+
const settings = loadAppSettings();
|
|
2616
|
+
if (!opts.force && opts.purgeOlderThanDays == null && !autoCleanupHistoryEnabled(settings)) {
|
|
2617
|
+
return { stripped: [], purged: [] };
|
|
2618
|
+
}
|
|
2619
|
+
const archived = listThreads({ includeArchived: true }).filter((t) => t.status === "archived");
|
|
2620
|
+
const nowMs = opts.nowMs ?? Date.now();
|
|
2621
|
+
const plan = opts.purgeOlderThanDays != null ? { stripIds: [], purgeIds: planHistoryAgePurge(archived, opts.purgeOlderThanDays, nowMs) } : planHistoryRetention(archived, {
|
|
2622
|
+
maxCount: opts.maxCount ?? historyMaxCount(settings),
|
|
2623
|
+
maxDays: opts.maxDays ?? historyMaxDays(settings),
|
|
2624
|
+
nowMs
|
|
2625
|
+
});
|
|
2626
|
+
const stripped = [];
|
|
2627
|
+
const purged = [];
|
|
2628
|
+
if (opts.dryRun) {
|
|
2629
|
+
return { stripped: plan.stripIds, purged: plan.purgeIds };
|
|
2630
|
+
}
|
|
2631
|
+
for (const id of plan.stripIds) {
|
|
2632
|
+
const thread = readThread(id);
|
|
2633
|
+
if (!thread || thread.status !== "archived") continue;
|
|
2634
|
+
try {
|
|
2635
|
+
stripArchivedTranscript(thread);
|
|
2636
|
+
stripped.push(id);
|
|
2637
|
+
} catch {
|
|
2638
|
+
}
|
|
2639
|
+
}
|
|
2640
|
+
for (const id of plan.purgeIds) {
|
|
2641
|
+
const thread = readThread(id);
|
|
2642
|
+
if (!thread || thread.status !== "archived") continue;
|
|
2643
|
+
try {
|
|
2644
|
+
deleteThreadRecord(id);
|
|
2645
|
+
purged.push(id);
|
|
2646
|
+
} catch {
|
|
2647
|
+
}
|
|
2648
|
+
}
|
|
2649
|
+
if (stripped.length > 0 || purged.length > 0) {
|
|
2650
|
+
updateAdvancedSettings({
|
|
2651
|
+
historyLastCleanupAt: new Date(nowMs).toISOString()
|
|
2652
|
+
});
|
|
2653
|
+
}
|
|
2654
|
+
return { stripped, purged };
|
|
2655
|
+
}
|
|
2656
|
+
function shouldRunHistoryCleanup(settings = loadAppSettings()) {
|
|
2657
|
+
if (!autoCleanupHistoryEnabled(settings)) return false;
|
|
2658
|
+
const intervalHours = settings.advanced.historyCleanupIntervalHours ?? HISTORY_CLEANUP_INTERVAL_HOURS_DEFAULT;
|
|
2659
|
+
const last = settings.advanced.historyLastCleanupAt;
|
|
2660
|
+
if (!last) return true;
|
|
2661
|
+
const elapsed = Date.now() - Date.parse(last);
|
|
2662
|
+
return Number.isFinite(elapsed) && elapsed >= intervalHours * 36e5;
|
|
2663
|
+
}
|
|
2664
|
+
|
|
2595
2665
|
// src/git/apply-into-main.ts
|
|
2596
2666
|
import { execa as execa3 } from "execa";
|
|
2597
2667
|
async function applyThreadIntoMain(thread, opts) {
|
|
@@ -3808,7 +3878,7 @@ async function createThread(input, _onSetupLine) {
|
|
|
3808
3878
|
});
|
|
3809
3879
|
await requireAgent(resolved.agent);
|
|
3810
3880
|
if (input.cowboy) {
|
|
3811
|
-
const { cowboyModeEnabled } = await import("./app-settings-
|
|
3881
|
+
const { cowboyModeEnabled } = await import("./app-settings-2TN3WLZV.js");
|
|
3812
3882
|
if (!cowboyModeEnabled()) {
|
|
3813
3883
|
throw new Error(
|
|
3814
3884
|
"Cowboy mode is off. Enable it in Settings \u2192 Advanced."
|
|
@@ -3866,7 +3936,7 @@ async function createThread(input, _onSetupLine) {
|
|
|
3866
3936
|
let sourceIsFork = false;
|
|
3867
3937
|
if (!input.cowboy && sourceType === "branch" && (!sourceRef || sourceRef === "HEAD" || sourceRef === "default")) {
|
|
3868
3938
|
if (isAbleTimeConnected() && getIssueSource() === "abletime") {
|
|
3869
|
-
const { ensureAbleTimeTask, issueAttachmentForAbleTimeTask } = await import("./abletime-
|
|
3939
|
+
const { ensureAbleTimeTask, issueAttachmentForAbleTimeTask } = await import("./abletime-GDZLZRMY.js");
|
|
3870
3940
|
const task = await ensureAbleTimeTask({
|
|
3871
3941
|
title: title?.trim() || "Untitled work",
|
|
3872
3942
|
description: input.prompt?.trim() || void 0
|
|
@@ -3968,7 +4038,7 @@ async function createThread(input, _onSetupLine) {
|
|
|
3968
4038
|
return readThread(thread.id) ?? thread;
|
|
3969
4039
|
}
|
|
3970
4040
|
async function listLinearIssues(agent, repoPath) {
|
|
3971
|
-
const { getAdapter: getAdapter2 } = await import("./agents-
|
|
4041
|
+
const { getAdapter: getAdapter2 } = await import("./agents-IQZUN47D.js");
|
|
3972
4042
|
await requireAgent(agent, { requireLinear: true });
|
|
3973
4043
|
const adapter = getAdapter2(agent);
|
|
3974
4044
|
if (!adapter.listLinearIssues) {
|
|
@@ -4414,7 +4484,7 @@ async function adoptThread(input) {
|
|
|
4414
4484
|
messages: input.messages ?? []
|
|
4415
4485
|
});
|
|
4416
4486
|
writeThread(thread);
|
|
4417
|
-
const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-
|
|
4487
|
+
const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-2XW2DMRG.js");
|
|
4418
4488
|
await ensureWorkspace2(repoPath);
|
|
4419
4489
|
const { ensureWorktreeSideboardIgnored: ensureWorktreeSideboardIgnored2 } = await import("./worktree-exclude-X54WSOXM.js");
|
|
4420
4490
|
await ensureWorktreeSideboardIgnored2(input.worktreePath);
|
|
@@ -7020,7 +7090,7 @@ function formatScheduledPrompt(name, prompt) {
|
|
|
7020
7090
|
${prompt}`;
|
|
7021
7091
|
}
|
|
7022
7092
|
async function defaultDeps() {
|
|
7023
|
-
const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-
|
|
7093
|
+
const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-ZBUXJCII.js");
|
|
7024
7094
|
const orch = getOrchestrator2();
|
|
7025
7095
|
return {
|
|
7026
7096
|
findThread: (id) => findThreadByRef(id),
|
|
@@ -7290,12 +7360,18 @@ var Orchestrator = class {
|
|
|
7290
7360
|
orphans: orphans.map((o) => ({ path: o.path, repoPath: o.repoPath }))
|
|
7291
7361
|
});
|
|
7292
7362
|
}
|
|
7293
|
-
const { autoCleanupOrphansEnabled } = await import("./app-settings-
|
|
7363
|
+
const { autoCleanupOrphansEnabled } = await import("./app-settings-2TN3WLZV.js");
|
|
7294
7364
|
if (autoCleanupOrphansEnabled() && shouldRunWorktreeCleanup() && orphans.length > 0) {
|
|
7295
7365
|
await cleanupOrphanWorktrees({ repoPaths });
|
|
7296
7366
|
}
|
|
7297
7367
|
} catch {
|
|
7298
7368
|
}
|
|
7369
|
+
try {
|
|
7370
|
+
if (shouldRunHistoryCleanup()) {
|
|
7371
|
+
cleanupArchivedHistory();
|
|
7372
|
+
}
|
|
7373
|
+
} catch {
|
|
7374
|
+
}
|
|
7299
7375
|
if (drainQueues) {
|
|
7300
7376
|
this.adoptPersistedQueues();
|
|
7301
7377
|
}
|
|
@@ -7582,7 +7658,7 @@ var Orchestrator = class {
|
|
|
7582
7658
|
}
|
|
7583
7659
|
await setup;
|
|
7584
7660
|
if (skipSetup) return;
|
|
7585
|
-
const { autoRunAfterSetupEnabled } = await import("./app-settings-
|
|
7661
|
+
const { autoRunAfterSetupEnabled } = await import("./app-settings-2TN3WLZV.js");
|
|
7586
7662
|
if (autoRunAfterSetupEnabled()) {
|
|
7587
7663
|
try {
|
|
7588
7664
|
await this.startDev(threadId);
|
|
@@ -7912,7 +7988,7 @@ var Orchestrator = class {
|
|
|
7912
7988
|
}
|
|
7913
7989
|
const isBrightsy = fresh.agent === "brightsy";
|
|
7914
7990
|
const isOrchestration = isOrchestratorThread(fresh);
|
|
7915
|
-
const { autoRenameBranchEnabled, getGithubGitAuthMode, gitBranchPrefixSetting } = await import("./app-settings-
|
|
7991
|
+
const { autoRenameBranchEnabled, getGithubGitAuthMode, gitBranchPrefixSetting } = await import("./app-settings-2TN3WLZV.js");
|
|
7916
7992
|
const gitAuthMode = getGithubGitAuthMode();
|
|
7917
7993
|
const worktreeDirective = isBrightsy || isOrchestration ? null : formatWorktreeDirective(fresh, {
|
|
7918
7994
|
githubSlug: await resolveGithubRepoSlug(fresh.worktreePath).catch(
|
|
@@ -8624,6 +8700,20 @@ var Orchestrator = class {
|
|
|
8624
8700
|
repoPaths
|
|
8625
8701
|
});
|
|
8626
8702
|
}
|
|
8703
|
+
/** Bound Settings → History. After archive always; reconcile is interval-gated. */
|
|
8704
|
+
enforceHistoryRetention() {
|
|
8705
|
+
try {
|
|
8706
|
+
cleanupArchivedHistory();
|
|
8707
|
+
} catch {
|
|
8708
|
+
}
|
|
8709
|
+
}
|
|
8710
|
+
cleanupHistory(opts) {
|
|
8711
|
+
return cleanupArchivedHistory({
|
|
8712
|
+
dryRun: opts?.dryRun,
|
|
8713
|
+
purgeOlderThanDays: opts?.purgeOlderThanDays,
|
|
8714
|
+
force: opts?.force
|
|
8715
|
+
});
|
|
8716
|
+
}
|
|
8627
8717
|
/**
|
|
8628
8718
|
* Best-of-n / fanout: create N threads (one per agent) with the same prompt.
|
|
8629
8719
|
*/
|
|
@@ -8930,7 +9020,7 @@ var Orchestrator = class {
|
|
|
8930
9020
|
if (!titled.userSetTitle && meta.title && titled.title !== meta.title) {
|
|
8931
9021
|
updateThread(thread.id, { title: meta.title });
|
|
8932
9022
|
}
|
|
8933
|
-
const { autoArchiveOnMergeEnabled } = await import("./app-settings-
|
|
9023
|
+
const { autoArchiveOnMergeEnabled } = await import("./app-settings-2TN3WLZV.js");
|
|
8934
9024
|
const latest = this.requireThread(thread.id);
|
|
8935
9025
|
if (!shouldAutoArchiveOnPrMerge({
|
|
8936
9026
|
previousPrState: prevState || null,
|
|
@@ -9184,6 +9274,7 @@ var Orchestrator = class {
|
|
|
9184
9274
|
if (isGlobalThread(thread)) {
|
|
9185
9275
|
const archived2 = setStatus(thread.id, "archived");
|
|
9186
9276
|
this.emit({ type: "status_changed", threadId: archived2.id, status: "archived" });
|
|
9277
|
+
this.enforceHistoryRetention();
|
|
9187
9278
|
return archived2;
|
|
9188
9279
|
}
|
|
9189
9280
|
const siblings = threadsSharingWorktree(thread.worktreePath).filter((t) => t.id !== thread.id);
|
|
@@ -9205,9 +9296,10 @@ var Orchestrator = class {
|
|
|
9205
9296
|
}
|
|
9206
9297
|
const archived = setStatus(thread.id, "archived");
|
|
9207
9298
|
this.emit({ type: "status_changed", threadId: archived.id, status: "archived" });
|
|
9299
|
+
this.enforceHistoryRetention();
|
|
9208
9300
|
if (thread.repoPath && !isGlobalRepoPath(thread.repoPath)) {
|
|
9209
9301
|
try {
|
|
9210
|
-
const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-
|
|
9302
|
+
const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-2XW2DMRG.js");
|
|
9211
9303
|
await ensureWorkspace2(thread.repoPath);
|
|
9212
9304
|
} catch {
|
|
9213
9305
|
}
|
|
@@ -9234,7 +9326,7 @@ var Orchestrator = class {
|
|
|
9234
9326
|
await runArchiveScript(thread.repoPath, thread.worktreePath);
|
|
9235
9327
|
} catch {
|
|
9236
9328
|
}
|
|
9237
|
-
const { deleteBranchOnPurgeEnabled } = await import("./app-settings-
|
|
9329
|
+
const { deleteBranchOnPurgeEnabled } = await import("./app-settings-2TN3WLZV.js");
|
|
9238
9330
|
const deleteBranch = opts?.deleteBranch ?? deleteBranchOnPurgeEnabled();
|
|
9239
9331
|
await removeWorktree(thread.repoPath, thread.worktreePath, {
|
|
9240
9332
|
deleteBranch: deleteBranch ? thread.branchName : void 0
|
|
@@ -9261,7 +9353,7 @@ var Orchestrator = class {
|
|
|
9261
9353
|
`Cowboy checkout missing: ${thread.worktreePath}. Re-add the project folder, then restore.`
|
|
9262
9354
|
);
|
|
9263
9355
|
}
|
|
9264
|
-
const { createThreadWorktree: createThreadWorktree2 } = await import("./worktree-
|
|
9356
|
+
const { createThreadWorktree: createThreadWorktree2 } = await import("./worktree-5ZGWKKZ6.js");
|
|
9265
9357
|
const slug = thread.worktreePath.split("/").pop();
|
|
9266
9358
|
const dest = thread.worktreePath;
|
|
9267
9359
|
await withRepoGitLock(thread.repoPath, async () => {
|
|
@@ -9371,7 +9463,7 @@ async function startOrchestration(opts) {
|
|
|
9371
9463
|
sourceRef: "default",
|
|
9372
9464
|
...createOpts
|
|
9373
9465
|
}).catch(async () => {
|
|
9374
|
-
const { resolveDefaultBranch: resolveDefaultBranch2, resolveRepoRoot: resolveRepoRoot2 } = await import("./worktree-
|
|
9466
|
+
const { resolveDefaultBranch: resolveDefaultBranch2, resolveRepoRoot: resolveRepoRoot2 } = await import("./worktree-5ZGWKKZ6.js");
|
|
9375
9467
|
const repo = await resolveRepoRoot2(repoPath);
|
|
9376
9468
|
const def = await resolveDefaultBranch2(repo);
|
|
9377
9469
|
return orch.createThread({
|
|
@@ -9381,7 +9473,7 @@ async function startOrchestration(opts) {
|
|
|
9381
9473
|
repoPath: repo
|
|
9382
9474
|
});
|
|
9383
9475
|
});
|
|
9384
|
-
const { updateThread: upd } = await import("./thread-store-
|
|
9476
|
+
const { updateThread: upd } = await import("./thread-store-KMZRQEPY.js");
|
|
9385
9477
|
const updated = upd(thread.id, {
|
|
9386
9478
|
sourceType: "orchestration",
|
|
9387
9479
|
sourceRef: goal
|
|
@@ -9540,6 +9632,8 @@ export {
|
|
|
9540
9632
|
cleanupOrphanWorktrees,
|
|
9541
9633
|
shouldRunWorktreeCleanup,
|
|
9542
9634
|
worktreeCleanupSettings,
|
|
9635
|
+
cleanupArchivedHistory,
|
|
9636
|
+
shouldRunHistoryCleanup,
|
|
9543
9637
|
applyThreadIntoMain,
|
|
9544
9638
|
cloneRepoIntoSideboard,
|
|
9545
9639
|
mcpWaitForTurnTimeoutMs,
|
|
@@ -383,6 +383,167 @@ function normalizeVault(raw) {
|
|
|
383
383
|
return out;
|
|
384
384
|
}
|
|
385
385
|
|
|
386
|
+
// src/agents/usage.ts
|
|
387
|
+
function sumOptional(a, b) {
|
|
388
|
+
if (a == null && b == null) return void 0;
|
|
389
|
+
return (a ?? 0) + (b ?? 0);
|
|
390
|
+
}
|
|
391
|
+
function fromInclusiveInputUsage(opts) {
|
|
392
|
+
const totalInput = Number(opts.inputTokens) || 0;
|
|
393
|
+
const outputTokens = Number(opts.outputTokens) || 0;
|
|
394
|
+
const cached = Number(opts.cachedInputTokens) || 0;
|
|
395
|
+
if (!totalInput && !outputTokens) return null;
|
|
396
|
+
const cacheReadTokens = cached > 0 ? Math.min(cached, totalInput) : 0;
|
|
397
|
+
return {
|
|
398
|
+
inputTokens: Math.max(0, totalInput - cacheReadTokens),
|
|
399
|
+
outputTokens,
|
|
400
|
+
cacheReadTokens: cacheReadTokens || void 0
|
|
401
|
+
};
|
|
402
|
+
}
|
|
403
|
+
function requestOccupancy(u) {
|
|
404
|
+
return u.inputTokens + (u.cacheReadTokens ?? 0) + (u.cacheWriteTokens ?? 0);
|
|
405
|
+
}
|
|
406
|
+
function mergeUsage(a, b) {
|
|
407
|
+
return {
|
|
408
|
+
inputTokens: (a?.inputTokens ?? 0) + b.inputTokens,
|
|
409
|
+
outputTokens: (a?.outputTokens ?? 0) + b.outputTokens,
|
|
410
|
+
cacheReadTokens: sumOptional(a?.cacheReadTokens, b.cacheReadTokens),
|
|
411
|
+
cacheWriteTokens: sumOptional(a?.cacheWriteTokens, b.cacheWriteTokens),
|
|
412
|
+
costUsd: sumOptional(a?.costUsd, b.costUsd),
|
|
413
|
+
lastRequestTokens: b.lastRequestTokens ?? a?.lastRequestTokens
|
|
414
|
+
};
|
|
415
|
+
}
|
|
416
|
+
function sumUsageList(list) {
|
|
417
|
+
let acc = null;
|
|
418
|
+
for (const u of list) {
|
|
419
|
+
if (!u) continue;
|
|
420
|
+
acc = mergeUsage(acc, {
|
|
421
|
+
inputTokens: u.inputTokens,
|
|
422
|
+
outputTokens: u.outputTokens,
|
|
423
|
+
cacheReadTokens: u.cacheReadTokens,
|
|
424
|
+
cacheWriteTokens: u.cacheWriteTokens,
|
|
425
|
+
costUsd: u.costUsd
|
|
426
|
+
});
|
|
427
|
+
}
|
|
428
|
+
if (!acc) return null;
|
|
429
|
+
return {
|
|
430
|
+
inputTokens: acc.inputTokens,
|
|
431
|
+
outputTokens: acc.outputTokens,
|
|
432
|
+
...acc.cacheReadTokens != null ? { cacheReadTokens: acc.cacheReadTokens } : {},
|
|
433
|
+
...acc.cacheWriteTokens != null ? { cacheWriteTokens: acc.cacheWriteTokens } : {},
|
|
434
|
+
...acc.costUsd != null ? { costUsd: acc.costUsd } : {}
|
|
435
|
+
};
|
|
436
|
+
}
|
|
437
|
+
function hasBilledTokens(u) {
|
|
438
|
+
return Boolean(
|
|
439
|
+
u.inputTokens || u.outputTokens || u.cacheReadTokens || u.cacheWriteTokens
|
|
440
|
+
);
|
|
441
|
+
}
|
|
442
|
+
function applyTurnUsage(current, incoming, scope = "request") {
|
|
443
|
+
if (scope === "turn") {
|
|
444
|
+
if (!hasBilledTokens(incoming) && current && incoming.costUsd != null) {
|
|
445
|
+
return { ...current, costUsd: incoming.costUsd };
|
|
446
|
+
}
|
|
447
|
+
return {
|
|
448
|
+
...incoming,
|
|
449
|
+
costUsd: incoming.costUsd ?? current?.costUsd,
|
|
450
|
+
lastRequestTokens: current?.lastRequestTokens ?? requestOccupancy(incoming)
|
|
451
|
+
};
|
|
452
|
+
}
|
|
453
|
+
const merged = mergeUsage(current, incoming);
|
|
454
|
+
const occ = incoming.lastRequestTokens != null && incoming.lastRequestTokens > 0 ? incoming.lastRequestTokens : requestOccupancy(incoming);
|
|
455
|
+
return {
|
|
456
|
+
...merged,
|
|
457
|
+
lastRequestTokens: occ > 0 ? occ : current?.lastRequestTokens ?? occ
|
|
458
|
+
};
|
|
459
|
+
}
|
|
460
|
+
function contextTokens(u) {
|
|
461
|
+
if (u.lastRequestTokens != null && u.lastRequestTokens > 0) return u.lastRequestTokens;
|
|
462
|
+
return requestOccupancy(u);
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
// src/store/history-retention.ts
|
|
466
|
+
var HISTORY_MAX_COUNT_DEFAULT = 200;
|
|
467
|
+
var HISTORY_MAX_COUNT_MIN = 1;
|
|
468
|
+
var HISTORY_MAX_COUNT_MAX = 2e3;
|
|
469
|
+
var HISTORY_MAX_DAYS_DEFAULT = 0;
|
|
470
|
+
var HISTORY_MAX_DAYS_MAX = 3650;
|
|
471
|
+
var HISTORY_CLEANUP_INTERVAL_HOURS_DEFAULT = 6;
|
|
472
|
+
var HISTORY_DISCARDED_TEXT = "Transcript discarded by History retention.";
|
|
473
|
+
function clampHistoryMaxCount(value) {
|
|
474
|
+
return Math.max(HISTORY_MAX_COUNT_MIN, Math.min(HISTORY_MAX_COUNT_MAX, Math.floor(value)));
|
|
475
|
+
}
|
|
476
|
+
function clampHistoryMaxDays(value) {
|
|
477
|
+
if (!Number.isFinite(value) || value <= 0) return 0;
|
|
478
|
+
return Math.min(HISTORY_MAX_DAYS_MAX, Math.floor(value));
|
|
479
|
+
}
|
|
480
|
+
function archivedUpdatedMs(thread) {
|
|
481
|
+
const stamped = thread.archivedAt ? Date.parse(thread.archivedAt) : NaN;
|
|
482
|
+
if (Number.isFinite(stamped)) return stamped;
|
|
483
|
+
const updated = Date.parse(thread.updatedAt);
|
|
484
|
+
if (Number.isFinite(updated)) return updated;
|
|
485
|
+
const created = Date.parse(thread.createdAt);
|
|
486
|
+
return Number.isFinite(created) ? created : 0;
|
|
487
|
+
}
|
|
488
|
+
function isHistoryRetentionStub(thread) {
|
|
489
|
+
if ((thread.attachments?.length ?? 0) > 0) return false;
|
|
490
|
+
const messages = thread.messages ?? [];
|
|
491
|
+
if (messages.length === 0) return true;
|
|
492
|
+
if (messages.length > 1) return false;
|
|
493
|
+
const only = messages[0];
|
|
494
|
+
if (only.parts?.length) return false;
|
|
495
|
+
if ((only.attachments?.length ?? 0) > 0) return false;
|
|
496
|
+
const text = (only.text ?? "").trim();
|
|
497
|
+
return text === "" || text === HISTORY_DISCARDED_TEXT;
|
|
498
|
+
}
|
|
499
|
+
function historyRetentionStubMessage(thread) {
|
|
500
|
+
const usage = sumUsageList((thread.messages ?? []).map((m) => m.usage));
|
|
501
|
+
return {
|
|
502
|
+
role: "summary",
|
|
503
|
+
text: HISTORY_DISCARDED_TEXT,
|
|
504
|
+
ts: thread.updatedAt,
|
|
505
|
+
...usage ? { usage } : {}
|
|
506
|
+
};
|
|
507
|
+
}
|
|
508
|
+
function sortArchivedOldestFirst(threads) {
|
|
509
|
+
return [...threads].sort((a, b) => archivedUpdatedMs(a) - archivedUpdatedMs(b));
|
|
510
|
+
}
|
|
511
|
+
function planHistoryRetention(archived, thresholds = {}) {
|
|
512
|
+
const maxCount = clampHistoryMaxCount(thresholds.maxCount ?? HISTORY_MAX_COUNT_DEFAULT);
|
|
513
|
+
const maxDays = clampHistoryMaxDays(thresholds.maxDays ?? HISTORY_MAX_DAYS_DEFAULT);
|
|
514
|
+
const nowMs = thresholds.nowMs ?? Date.now();
|
|
515
|
+
const oldestFirst = sortArchivedOldestFirst(archived);
|
|
516
|
+
const expiredIds = /* @__PURE__ */ new Set();
|
|
517
|
+
if (maxDays > 0) {
|
|
518
|
+
const cutoff = nowMs - maxDays * 864e5;
|
|
519
|
+
for (const thread of oldestFirst) {
|
|
520
|
+
if (archivedUpdatedMs(thread) < cutoff) expiredIds.add(thread.id);
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
const remaining = oldestFirst.filter((t) => !expiredIds.has(t.id));
|
|
524
|
+
const overflow = remaining.length > maxCount ? remaining.slice(0, remaining.length - maxCount) : [];
|
|
525
|
+
const stripIds = [];
|
|
526
|
+
const purgeIds = [...expiredIds];
|
|
527
|
+
const seenPurge = new Set(purgeIds);
|
|
528
|
+
for (const thread of overflow) {
|
|
529
|
+
if (isHistoryRetentionStub(thread)) {
|
|
530
|
+
if (!seenPurge.has(thread.id)) {
|
|
531
|
+
seenPurge.add(thread.id);
|
|
532
|
+
purgeIds.push(thread.id);
|
|
533
|
+
}
|
|
534
|
+
} else {
|
|
535
|
+
stripIds.push(thread.id);
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
return { stripIds, purgeIds };
|
|
539
|
+
}
|
|
540
|
+
function planHistoryAgePurge(archived, olderThanDays, nowMs = Date.now()) {
|
|
541
|
+
const days = clampHistoryMaxDays(olderThanDays);
|
|
542
|
+
if (days <= 0) return [];
|
|
543
|
+
const cutoff = nowMs - days * 864e5;
|
|
544
|
+
return sortArchivedOldestFirst(archived).filter((t) => archivedUpdatedMs(t) < cutoff).map((t) => t.id);
|
|
545
|
+
}
|
|
546
|
+
|
|
386
547
|
// src/store/usage-on-limit.ts
|
|
387
548
|
var USAGE_ON_LIMIT_VALUES = [
|
|
388
549
|
"keep_going",
|
|
@@ -843,6 +1004,24 @@ function normalizeAdvanced(raw) {
|
|
|
843
1004
|
if (typeof source.autoCleanupOrphans === "boolean") {
|
|
844
1005
|
out.autoCleanupOrphans = source.autoCleanupOrphans;
|
|
845
1006
|
}
|
|
1007
|
+
if (typeof source.autoCleanupHistory === "boolean") {
|
|
1008
|
+
out.autoCleanupHistory = source.autoCleanupHistory;
|
|
1009
|
+
}
|
|
1010
|
+
if (typeof source.historyMaxCount === "number" && Number.isFinite(source.historyMaxCount)) {
|
|
1011
|
+
out.historyMaxCount = clampHistoryMaxCount(source.historyMaxCount);
|
|
1012
|
+
}
|
|
1013
|
+
if (typeof source.historyMaxDays === "number" && Number.isFinite(source.historyMaxDays)) {
|
|
1014
|
+
out.historyMaxDays = clampHistoryMaxDays(source.historyMaxDays);
|
|
1015
|
+
}
|
|
1016
|
+
if (typeof source.historyCleanupIntervalHours === "number" && Number.isFinite(source.historyCleanupIntervalHours)) {
|
|
1017
|
+
out.historyCleanupIntervalHours = Math.max(
|
|
1018
|
+
1,
|
|
1019
|
+
Math.min(168, Math.floor(source.historyCleanupIntervalHours))
|
|
1020
|
+
);
|
|
1021
|
+
}
|
|
1022
|
+
if (typeof source.historyLastCleanupAt === "string" && source.historyLastCleanupAt.trim()) {
|
|
1023
|
+
out.historyLastCleanupAt = source.historyLastCleanupAt.trim();
|
|
1024
|
+
}
|
|
846
1025
|
if (source.orchestrationQuotaOnLimit === "switch_agent" || source.orchestrationQuotaOnLimit === "wait_reset") {
|
|
847
1026
|
out.orchestrationQuotaOnLimit = source.orchestrationQuotaOnLimit;
|
|
848
1027
|
}
|
|
@@ -1748,6 +1927,24 @@ function updateAdvancedSettings(patch) {
|
|
|
1748
1927
|
if (typeof patch.autoCleanupOrphans === "boolean") {
|
|
1749
1928
|
advanced.autoCleanupOrphans = patch.autoCleanupOrphans;
|
|
1750
1929
|
}
|
|
1930
|
+
if (typeof patch.autoCleanupHistory === "boolean") {
|
|
1931
|
+
advanced.autoCleanupHistory = patch.autoCleanupHistory;
|
|
1932
|
+
}
|
|
1933
|
+
if (typeof patch.historyMaxCount === "number" && Number.isFinite(patch.historyMaxCount)) {
|
|
1934
|
+
advanced.historyMaxCount = clampHistoryMaxCount(patch.historyMaxCount);
|
|
1935
|
+
}
|
|
1936
|
+
if (typeof patch.historyMaxDays === "number" && Number.isFinite(patch.historyMaxDays)) {
|
|
1937
|
+
advanced.historyMaxDays = clampHistoryMaxDays(patch.historyMaxDays);
|
|
1938
|
+
}
|
|
1939
|
+
if (typeof patch.historyCleanupIntervalHours === "number" && Number.isFinite(patch.historyCleanupIntervalHours)) {
|
|
1940
|
+
advanced.historyCleanupIntervalHours = Math.max(
|
|
1941
|
+
1,
|
|
1942
|
+
Math.min(168, Math.floor(patch.historyCleanupIntervalHours))
|
|
1943
|
+
);
|
|
1944
|
+
}
|
|
1945
|
+
if (typeof patch.historyLastCleanupAt === "string") {
|
|
1946
|
+
advanced.historyLastCleanupAt = patch.historyLastCleanupAt;
|
|
1947
|
+
}
|
|
1751
1948
|
if (patch.orchestrationQuotaOnLimit === "switch_agent" || patch.orchestrationQuotaOnLimit === "wait_reset") {
|
|
1752
1949
|
advanced.orchestrationQuotaOnLimit = patch.orchestrationQuotaOnLimit;
|
|
1753
1950
|
}
|
|
@@ -1798,6 +1995,15 @@ function autoArchiveOnMergeEnabled(settings = loadAppSettings()) {
|
|
|
1798
1995
|
function autoCleanupOrphansEnabled(settings = loadAppSettings()) {
|
|
1799
1996
|
return Boolean(settings.advanced.autoCleanupOrphans);
|
|
1800
1997
|
}
|
|
1998
|
+
function autoCleanupHistoryEnabled(settings = loadAppSettings()) {
|
|
1999
|
+
return settings.advanced.autoCleanupHistory !== false;
|
|
2000
|
+
}
|
|
2001
|
+
function historyMaxCount(settings = loadAppSettings()) {
|
|
2002
|
+
return clampHistoryMaxCount(settings.advanced.historyMaxCount ?? HISTORY_MAX_COUNT_DEFAULT);
|
|
2003
|
+
}
|
|
2004
|
+
function historyMaxDays(settings = loadAppSettings()) {
|
|
2005
|
+
return clampHistoryMaxDays(settings.advanced.historyMaxDays ?? HISTORY_MAX_DAYS_DEFAULT);
|
|
2006
|
+
}
|
|
1801
2007
|
function usageOnLimit(settings = loadAppSettings()) {
|
|
1802
2008
|
return resolveUsageOnLimit(settings.advanced);
|
|
1803
2009
|
}
|
|
@@ -1932,6 +2138,14 @@ export {
|
|
|
1932
2138
|
formatWorkspaceProfileSuffix,
|
|
1933
2139
|
formatViewerContextDirective,
|
|
1934
2140
|
formatViewerContextReminder,
|
|
2141
|
+
fromInclusiveInputUsage,
|
|
2142
|
+
sumUsageList,
|
|
2143
|
+
applyTurnUsage,
|
|
2144
|
+
contextTokens,
|
|
2145
|
+
HISTORY_CLEANUP_INTERVAL_HOURS_DEFAULT,
|
|
2146
|
+
historyRetentionStubMessage,
|
|
2147
|
+
planHistoryRetention,
|
|
2148
|
+
planHistoryAgePurge,
|
|
1935
2149
|
USAGE_ON_LIMIT_VALUES,
|
|
1936
2150
|
isUsageOnLimit,
|
|
1937
2151
|
resolveUsageOnLimit,
|
|
@@ -2001,6 +2215,9 @@ export {
|
|
|
2001
2215
|
confirmClaudeUsageOverLimitEnabled,
|
|
2002
2216
|
autoArchiveOnMergeEnabled,
|
|
2003
2217
|
autoCleanupOrphansEnabled,
|
|
2218
|
+
autoCleanupHistoryEnabled,
|
|
2219
|
+
historyMaxCount,
|
|
2220
|
+
historyMaxDays,
|
|
2004
2221
|
usageOnLimit,
|
|
2005
2222
|
orchestrationQuotaOnLimit,
|
|
2006
2223
|
orchestrationQuotaFallbackAgent,
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import {
|
|
2
|
+
cursorSdkStoreDir
|
|
3
|
+
} from "./chunk-7J72QJOM.js";
|
|
1
4
|
import {
|
|
2
5
|
normalizeThinkingEffort
|
|
3
6
|
} from "./chunk-77WWLBCI.js";
|
|
@@ -13,6 +16,7 @@ import {
|
|
|
13
16
|
existsSync,
|
|
14
17
|
readFileSync,
|
|
15
18
|
renameSync,
|
|
19
|
+
rmSync,
|
|
16
20
|
statSync,
|
|
17
21
|
unlinkSync,
|
|
18
22
|
writeFileSync,
|
|
@@ -52,7 +56,8 @@ function normalizeThread(raw) {
|
|
|
52
56
|
userSetTitle: Boolean(raw.userSetTitle),
|
|
53
57
|
activeRuns: Array.isArray(raw.activeRuns) ? raw.activeRuns : [],
|
|
54
58
|
quotaResumeAt: raw.quotaResumeAt ?? null,
|
|
55
|
-
quotaContinuedFromId: raw.quotaContinuedFromId ?? null
|
|
59
|
+
quotaContinuedFromId: raw.quotaContinuedFromId ?? null,
|
|
60
|
+
archivedAt: typeof raw.archivedAt === "string" && raw.archivedAt.trim() ? raw.archivedAt.trim() : void 0
|
|
56
61
|
};
|
|
57
62
|
}
|
|
58
63
|
function createEmptyThread(partial) {
|
|
@@ -87,6 +92,7 @@ function createEmptyThread(partial) {
|
|
|
87
92
|
pendingTurnAttachments: partial.pendingTurnAttachments ?? [],
|
|
88
93
|
createdAt: ts,
|
|
89
94
|
updatedAt: ts,
|
|
95
|
+
archivedAt: typeof partial.archivedAt === "string" && partial.archivedAt.trim() ? partial.archivedAt.trim() : void 0,
|
|
90
96
|
title: partial.title,
|
|
91
97
|
sourceType: partial.sourceType,
|
|
92
98
|
sourceRef: partial.sourceRef,
|
|
@@ -159,10 +165,10 @@ function readThread(id) {
|
|
|
159
165
|
rememberThread(thread, mtimeMs);
|
|
160
166
|
return thread;
|
|
161
167
|
}
|
|
162
|
-
function writeThread(thread) {
|
|
168
|
+
function writeThread(thread, opts) {
|
|
163
169
|
const path = threadFilePath(idPath(thread.id));
|
|
164
170
|
const tmp = `${path}.${process.pid}.tmp`;
|
|
165
|
-
const next = { ...thread, updatedAt: nowIso() };
|
|
171
|
+
const next = opts?.touch === false ? { ...thread } : { ...thread, updatedAt: nowIso() };
|
|
166
172
|
writeFileSync(tmp, JSON.stringify(next, null, 2), "utf8");
|
|
167
173
|
renameSync(tmp, path);
|
|
168
174
|
rememberThread(next, fileMtimeMs(path) ?? Date.now());
|
|
@@ -207,11 +213,20 @@ function deleteThreadRecord(id) {
|
|
|
207
213
|
} catch {
|
|
208
214
|
}
|
|
209
215
|
}
|
|
216
|
+
try {
|
|
217
|
+
rmSync(cursorSdkStoreDir(id), { recursive: true, force: true });
|
|
218
|
+
} catch {
|
|
219
|
+
}
|
|
210
220
|
}
|
|
211
221
|
function updateThread(id, patch) {
|
|
212
222
|
const current = readThread(id);
|
|
213
223
|
if (!current) throw new Error(`Thread not found: ${id}`);
|
|
214
224
|
const next = { ...current, ...patch, id: current.id, updatedAt: nowIso() };
|
|
225
|
+
if (next.status === "archived") {
|
|
226
|
+
next.archivedAt = typeof next.archivedAt === "string" && next.archivedAt.trim() || current.archivedAt || nowIso();
|
|
227
|
+
} else {
|
|
228
|
+
delete next.archivedAt;
|
|
229
|
+
}
|
|
215
230
|
writeThread(next);
|
|
216
231
|
return next;
|
|
217
232
|
}
|