@aexol/spectral 0.9.166 → 0.9.167
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/sdk/coding-agent/core/agent-session.d.ts +21 -1
- package/dist/sdk/coding-agent/core/agent-session.d.ts.map +1 -1
- package/dist/sdk/coding-agent/core/agent-session.js +377 -75
- package/dist/sdk/coding-agent/core/compaction/llm-compaction.d.ts +42 -0
- package/dist/sdk/coding-agent/core/compaction/llm-compaction.d.ts.map +1 -0
- package/dist/sdk/coding-agent/core/compaction/llm-compaction.js +83 -0
- package/dist/sdk/coding-agent/core/resource-loader.d.ts.map +1 -1
- package/dist/sdk/coding-agent/core/resource-loader.js +23 -1
- package/dist/sdk/coding-agent/core/session-manager.d.ts +50 -1
- package/dist/sdk/coding-agent/core/session-manager.d.ts.map +1 -1
- package/dist/sdk/coding-agent/core/session-manager.js +222 -26
- package/dist/sdk/coding-agent/core/settings-manager.d.ts +15 -0
- package/dist/sdk/coding-agent/core/settings-manager.d.ts.map +1 -1
- package/dist/sdk/coding-agent/core/settings-manager.js +11 -0
- package/package.json +1 -1
|
@@ -3,10 +3,11 @@ import { randomUUID } from "crypto";
|
|
|
3
3
|
import { appendFileSync, closeSync, existsSync, mkdirSync, openSync, readdirSync, readFileSync, readSync, statSync, writeFileSync, } from "fs";
|
|
4
4
|
import { readdir, readFile, stat } from "fs/promises";
|
|
5
5
|
import { join, resolve } from "path";
|
|
6
|
-
import { getAgentDir as getDefaultAgentDir, getSessionsDir } from "../config.js";
|
|
6
|
+
import { getAgentDir as getDefaultAgentDir, getSessionsDir, } from "../config.js";
|
|
7
7
|
import { normalizePath, resolvePath } from "../utils/paths.js";
|
|
8
8
|
import { createBranchSummaryMessage, createCompactionSummaryMessage, createCustomMessage, } from "./messages.js";
|
|
9
9
|
export const CURRENT_SESSION_VERSION = 3;
|
|
10
|
+
const REQUEST_TIME_JOB_ENTRY = "spectral.request-time-compaction";
|
|
10
11
|
function createSessionId() {
|
|
11
12
|
return uuidv7();
|
|
12
13
|
}
|
|
@@ -20,6 +21,40 @@ function generateId(byId) {
|
|
|
20
21
|
// Fallback to full UUID if somehow we have collisions
|
|
21
22
|
return randomUUID();
|
|
22
23
|
}
|
|
24
|
+
function isRecord(value) {
|
|
25
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
26
|
+
}
|
|
27
|
+
function hasCompletedToolBoundary(entries) {
|
|
28
|
+
const pending = new Set();
|
|
29
|
+
const completed = new Set();
|
|
30
|
+
let sawAssistant = false;
|
|
31
|
+
let lastAssistant;
|
|
32
|
+
for (const entry of entries) {
|
|
33
|
+
if (entry.type !== "message")
|
|
34
|
+
continue;
|
|
35
|
+
const message = entry.message;
|
|
36
|
+
if (message.role === "assistant" && Array.isArray(message.content)) {
|
|
37
|
+
sawAssistant = true;
|
|
38
|
+
lastAssistant = entry.message;
|
|
39
|
+
for (const block of message.content) {
|
|
40
|
+
if (isRecord(block) && block.type === "toolCall" && typeof block.id === "string") {
|
|
41
|
+
if (pending.has(block.id) || completed.has(block.id))
|
|
42
|
+
return false;
|
|
43
|
+
pending.add(block.id);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
if (message.role === "toolResult" && typeof message.toolCallId === "string") {
|
|
48
|
+
if (!pending.delete(message.toolCallId))
|
|
49
|
+
return false;
|
|
50
|
+
completed.add(message.toolCallId);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
if (!sawAssistant || pending.size !== 0 || !lastAssistant)
|
|
54
|
+
return false;
|
|
55
|
+
const stopReason = lastAssistant.stopReason;
|
|
56
|
+
return stopReason !== "aborted" && stopReason !== "error";
|
|
57
|
+
}
|
|
23
58
|
/** Migrate v1 → v2: add id/parentId tree structure. Mutates in place. */
|
|
24
59
|
function migrateV1ToV2(entries) {
|
|
25
60
|
const ids = new Set();
|
|
@@ -55,7 +90,8 @@ function migrateV2ToV3(entries) {
|
|
|
55
90
|
// Update message entries with hookMessage role
|
|
56
91
|
if (entry.type === "message") {
|
|
57
92
|
const msgEntry = entry;
|
|
58
|
-
if (msgEntry.message &&
|
|
93
|
+
if (msgEntry.message &&
|
|
94
|
+
msgEntry.message.role === "hookMessage") {
|
|
59
95
|
msgEntry.message.role = "custom";
|
|
60
96
|
}
|
|
61
97
|
}
|
|
@@ -153,7 +189,10 @@ export function buildSessionContext(entries, leafId, byId) {
|
|
|
153
189
|
model = { provider: entry.provider, modelId: entry.modelId };
|
|
154
190
|
}
|
|
155
191
|
else if (entry.type === "message" && entry.message.role === "assistant") {
|
|
156
|
-
model = {
|
|
192
|
+
model = {
|
|
193
|
+
provider: entry.message.provider,
|
|
194
|
+
modelId: entry.message.model,
|
|
195
|
+
};
|
|
157
196
|
}
|
|
158
197
|
else if (entry.type === "compaction") {
|
|
159
198
|
compaction = entry;
|
|
@@ -181,15 +220,43 @@ export function buildSessionContext(entries, leafId, byId) {
|
|
|
181
220
|
messages.push(createCompactionSummaryMessage(compaction.summary, compaction.tokensBefore, compaction.timestamp));
|
|
182
221
|
// Find compaction index in path
|
|
183
222
|
const compactionIdx = path.findIndex((e) => e.type === "compaction" && e.id === compaction.id);
|
|
184
|
-
//
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
223
|
+
// Request-time overlays are appended after the snapshot boundary. They
|
|
224
|
+
// must not retain the snapshot's raw messages; only descendants created
|
|
225
|
+
// after targetTurnId belong in the tail.
|
|
226
|
+
const snapshotTarget = compaction.snapshot?.targetTurnId;
|
|
227
|
+
const snapshotTargetIdx = snapshotTarget
|
|
228
|
+
? path.findIndex((entry) => entry.id === snapshotTarget)
|
|
229
|
+
: -1;
|
|
230
|
+
if (snapshotTargetIdx >= 0) {
|
|
231
|
+
// Keep the provider tail selected by the compaction result from the
|
|
232
|
+
// immutable snapshot. The snapshot target is the completed-turn
|
|
233
|
+
// boundary, not the beginning of the tail; omitting this range would
|
|
234
|
+
// leave request-time context with only the summary when the job was
|
|
235
|
+
// scheduled at the current leaf.
|
|
236
|
+
let firstKeptIdx = path.findIndex((entry) => entry.id === compaction.firstKeptEntryId);
|
|
237
|
+
if (firstKeptIdx < 0 || firstKeptIdx > snapshotTargetIdx) {
|
|
238
|
+
firstKeptIdx = snapshotTargetIdx;
|
|
239
|
+
}
|
|
240
|
+
for (let i = firstKeptIdx; i <= snapshotTargetIdx; i++) {
|
|
241
|
+
appendMessage(path[i]);
|
|
190
242
|
}
|
|
191
|
-
|
|
192
|
-
|
|
243
|
+
// Include descendants created after the snapshot while the async job
|
|
244
|
+
// was running, but never re-add the snapshot's compacted prefix.
|
|
245
|
+
for (let i = snapshotTargetIdx + 1; i < compactionIdx; i++) {
|
|
246
|
+
appendMessage(path[i]);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
else {
|
|
250
|
+
// Emit kept messages (before compaction, starting from firstKeptEntryId)
|
|
251
|
+
let foundFirstKept = false;
|
|
252
|
+
for (let i = 0; i < compactionIdx; i++) {
|
|
253
|
+
const entry = path[i];
|
|
254
|
+
if (entry.id === compaction.firstKeptEntryId) {
|
|
255
|
+
foundFirstKept = true;
|
|
256
|
+
}
|
|
257
|
+
if (foundFirstKept) {
|
|
258
|
+
appendMessage(entry);
|
|
259
|
+
}
|
|
193
260
|
}
|
|
194
261
|
}
|
|
195
262
|
// Emit messages after compaction
|
|
@@ -323,7 +390,9 @@ function getSessionModifiedDate(entries, header, statsMtime) {
|
|
|
323
390
|
if (typeof lastActivityTime === "number" && lastActivityTime > 0) {
|
|
324
391
|
return new Date(lastActivityTime);
|
|
325
392
|
}
|
|
326
|
-
const headerTime = typeof header.timestamp === "string"
|
|
393
|
+
const headerTime = typeof header.timestamp === "string"
|
|
394
|
+
? new Date(header.timestamp).getTime()
|
|
395
|
+
: NaN;
|
|
327
396
|
return !Number.isNaN(headerTime) ? new Date(headerTime) : statsMtime;
|
|
328
397
|
}
|
|
329
398
|
async function buildSessionInfo(filePath) {
|
|
@@ -373,7 +442,9 @@ async function buildSessionInfo(filePath) {
|
|
|
373
442
|
firstMessage = textContent;
|
|
374
443
|
}
|
|
375
444
|
}
|
|
376
|
-
const cwd = typeof header.cwd === "string"
|
|
445
|
+
const cwd = typeof header.cwd === "string"
|
|
446
|
+
? header.cwd
|
|
447
|
+
: "";
|
|
377
448
|
const parentSessionPath = header.parentSession;
|
|
378
449
|
const modified = getSessionModifiedDate(entries, header, stats.mtime);
|
|
379
450
|
return {
|
|
@@ -418,7 +489,8 @@ async function buildSessionInfosWithConcurrency(files, onLoaded) {
|
|
|
418
489
|
inFlight.add(task);
|
|
419
490
|
};
|
|
420
491
|
while (nextIndex < files.length || inFlight.size > 0) {
|
|
421
|
-
while (nextIndex < files.length &&
|
|
492
|
+
while (nextIndex < files.length &&
|
|
493
|
+
inFlight.size < MAX_CONCURRENT_SESSION_INFO_LOADS) {
|
|
422
494
|
startNext();
|
|
423
495
|
}
|
|
424
496
|
if (inFlight.size > 0) {
|
|
@@ -434,7 +506,9 @@ async function listSessionsFromDir(dir, onProgress, progressOffset = 0, progress
|
|
|
434
506
|
}
|
|
435
507
|
try {
|
|
436
508
|
const dirEntries = await readdir(dir);
|
|
437
|
-
const files = dirEntries
|
|
509
|
+
const files = dirEntries
|
|
510
|
+
.filter((f) => f.endsWith(".jsonl"))
|
|
511
|
+
.map((f) => join(dir, f));
|
|
438
512
|
const total = progressTotal ?? files.length;
|
|
439
513
|
let loaded = 0;
|
|
440
514
|
const results = await buildSessionInfosWithConcurrency(files, () => {
|
|
@@ -475,6 +549,8 @@ export class SessionManager {
|
|
|
475
549
|
labelsById = new Map();
|
|
476
550
|
labelTimestampsById = new Map();
|
|
477
551
|
leafId = null;
|
|
552
|
+
/** Monotonic in-memory CAS revision; compaction ordinal is deliberately unrelated. */
|
|
553
|
+
revision = 0;
|
|
478
554
|
constructor(cwd, sessionDir, sessionFile, persist) {
|
|
479
555
|
this.cwd = resolvePath(cwd);
|
|
480
556
|
this.sessionDir = normalizePath(sessionDir);
|
|
@@ -533,6 +609,7 @@ export class SessionManager {
|
|
|
533
609
|
this.byId.clear();
|
|
534
610
|
this.labelsById.clear();
|
|
535
611
|
this.leafId = null;
|
|
612
|
+
this.revision = 0;
|
|
536
613
|
this.flushed = false;
|
|
537
614
|
if (this.persist) {
|
|
538
615
|
const fileTimestamp = timestamp.replace(/[:.]/g, "-");
|
|
@@ -545,11 +622,13 @@ export class SessionManager {
|
|
|
545
622
|
this.labelsById.clear();
|
|
546
623
|
this.labelTimestampsById.clear();
|
|
547
624
|
this.leafId = null;
|
|
625
|
+
this.revision = 0;
|
|
548
626
|
for (const entry of this.fileEntries) {
|
|
549
627
|
if (entry.type === "session")
|
|
550
628
|
continue;
|
|
551
629
|
this.byId.set(entry.id, entry);
|
|
552
630
|
this.leafId = entry.id;
|
|
631
|
+
this.revision++;
|
|
553
632
|
if (entry.type === "label") {
|
|
554
633
|
if (entry.label) {
|
|
555
634
|
this.labelsById.set(entry.targetId, entry.label);
|
|
@@ -606,6 +685,7 @@ export class SessionManager {
|
|
|
606
685
|
this.fileEntries.push(entry);
|
|
607
686
|
this.byId.set(entry.id, entry);
|
|
608
687
|
this.leafId = entry.id;
|
|
688
|
+
this.revision++;
|
|
609
689
|
this._persist(entry);
|
|
610
690
|
}
|
|
611
691
|
/** Append a message as child of current leaf, then advance leaf. Returns entry id.
|
|
@@ -651,7 +731,7 @@ export class SessionManager {
|
|
|
651
731
|
return entry.id;
|
|
652
732
|
}
|
|
653
733
|
/** Append a compaction summary as child of current leaf, then advance leaf. Returns entry id. */
|
|
654
|
-
appendCompaction(summary, firstKeptEntryId, tokensBefore, details, fromHook) {
|
|
734
|
+
appendCompaction(summary, firstKeptEntryId, tokensBefore, details, fromHook, snapshot) {
|
|
655
735
|
const entry = {
|
|
656
736
|
type: "compaction",
|
|
657
737
|
id: generateId(this.byId),
|
|
@@ -662,10 +742,102 @@ export class SessionManager {
|
|
|
662
742
|
tokensBefore,
|
|
663
743
|
details,
|
|
664
744
|
fromHook,
|
|
745
|
+
snapshot,
|
|
665
746
|
};
|
|
666
747
|
this._appendEntry(entry);
|
|
667
748
|
return entry.id;
|
|
668
749
|
}
|
|
750
|
+
getRevision() {
|
|
751
|
+
return this.revision;
|
|
752
|
+
}
|
|
753
|
+
/** Request-time jobs are journaled as ignored custom entries so old JSONL
|
|
754
|
+
* sessions remain readable and an interrupted worker can be recovered. */
|
|
755
|
+
getRequestTimeCompactionJobs() {
|
|
756
|
+
const jobs = new Map();
|
|
757
|
+
for (const entry of this.fileEntries) {
|
|
758
|
+
if (entry.type !== "custom" || entry.customType !== REQUEST_TIME_JOB_ENTRY)
|
|
759
|
+
continue;
|
|
760
|
+
const data = entry.data;
|
|
761
|
+
if (!isRecord(data) || !isRecord(data.snapshot) || typeof data.status !== "string")
|
|
762
|
+
continue;
|
|
763
|
+
const snapshot = data.snapshot;
|
|
764
|
+
if (typeof snapshot.compactionId !== "string" || !Array.isArray(snapshot.entries))
|
|
765
|
+
continue;
|
|
766
|
+
const status = data.status;
|
|
767
|
+
jobs.set(snapshot.compactionId, { snapshot, status });
|
|
768
|
+
}
|
|
769
|
+
return [...jobs.values()].filter((job) => job.status === "pending" || job.status === "running");
|
|
770
|
+
}
|
|
771
|
+
persistRequestTimeCompactionJob(job) {
|
|
772
|
+
this.appendCustomEntry(REQUEST_TIME_JOB_ENTRY, job);
|
|
773
|
+
// Job state must survive even before the first assistant message (the
|
|
774
|
+
// normal session journal intentionally delays those writes).
|
|
775
|
+
if (this.persist && this.sessionFile && !this.flushed) {
|
|
776
|
+
this._rewriteFile();
|
|
777
|
+
this.flushed = true;
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
/** Stable identity for the current tree branch (root entry). */
|
|
781
|
+
getBranchId(leafId = this.leafId) {
|
|
782
|
+
const branch = this.getBranch(leafId ?? undefined);
|
|
783
|
+
return branch[0]?.id ?? "root";
|
|
784
|
+
}
|
|
785
|
+
/** Capture only the already-completed path through targetTurnId. */
|
|
786
|
+
createRequestTimeSnapshot(targetTurnId = this.leafId ?? "") {
|
|
787
|
+
if (!targetTurnId)
|
|
788
|
+
throw new Error("Cannot snapshot an empty session");
|
|
789
|
+
const entries = this.getBranch(targetTurnId);
|
|
790
|
+
if (entries.length === 0 || !this.byId.has(targetTurnId))
|
|
791
|
+
throw new Error(`Entry ${targetTurnId} not found`);
|
|
792
|
+
if (!hasCompletedToolBoundary(entries)) {
|
|
793
|
+
throw new Error("Request-time compaction requires a completed tool-call turn");
|
|
794
|
+
}
|
|
795
|
+
return Object.freeze({
|
|
796
|
+
compactionId: randomUUID(),
|
|
797
|
+
branchId: this.getBranchId(targetTurnId),
|
|
798
|
+
leafId: targetTurnId,
|
|
799
|
+
baseRevision: this.revision,
|
|
800
|
+
targetTurnId,
|
|
801
|
+
entries: Object.freeze(entries.map((entry) => structuredClone(entry))),
|
|
802
|
+
});
|
|
803
|
+
}
|
|
804
|
+
/** Append an already-generated overlay iff its snapshot still belongs to this branch. */
|
|
805
|
+
commitRequestTimeCompaction(snapshot, result) {
|
|
806
|
+
const existing = this.getEntries().find((entry) => entry.type === "compaction" &&
|
|
807
|
+
(entry.snapshot?.compactionId === snapshot.compactionId ||
|
|
808
|
+
(isRecord(entry.details) &&
|
|
809
|
+
entry.details.compactionId ===
|
|
810
|
+
snapshot.compactionId)));
|
|
811
|
+
if (existing)
|
|
812
|
+
return { status: "idempotent", entryId: existing.id };
|
|
813
|
+
const currentBranch = this.getBranch();
|
|
814
|
+
const targetIndex = currentBranch.findIndex((entry) => entry.id === snapshot.targetTurnId);
|
|
815
|
+
const snapshotIds = snapshot.entries.map((entry) => entry.id);
|
|
816
|
+
const currentPrefix = currentBranch
|
|
817
|
+
.filter((entry) => !(entry.type === "custom" && entry.customType === REQUEST_TIME_JOB_ENTRY))
|
|
818
|
+
.slice(0, snapshotIds.length)
|
|
819
|
+
.map((entry) => entry.id);
|
|
820
|
+
// New descendants after the snapshot are safe, but a fork before the
|
|
821
|
+
// target changes the ancestor chain and must not receive the overlay.
|
|
822
|
+
if (targetIndex < 0 ||
|
|
823
|
+
this.getBranchId() !== snapshot.branchId ||
|
|
824
|
+
currentPrefix.length !== snapshotIds.length ||
|
|
825
|
+
currentPrefix.some((id, index) => id !== snapshotIds[index]))
|
|
826
|
+
return { status: "stale" };
|
|
827
|
+
const details = {
|
|
828
|
+
...(isRecord(result.details) ? result.details : {}),
|
|
829
|
+
snapshot,
|
|
830
|
+
};
|
|
831
|
+
const entryId = this.appendCompaction(result.summary, result.firstKeptEntryId, result.tokensBefore, details, false, {
|
|
832
|
+
compactionId: snapshot.compactionId,
|
|
833
|
+
branchId: snapshot.branchId,
|
|
834
|
+
leafId: snapshot.leafId,
|
|
835
|
+
baseRevision: snapshot.baseRevision,
|
|
836
|
+
targetTurnId: snapshot.targetTurnId,
|
|
837
|
+
mode: "request_time",
|
|
838
|
+
});
|
|
839
|
+
return { status: "committed", entryId };
|
|
840
|
+
}
|
|
669
841
|
/** Append a custom entry (for extensions) as child of current leaf, then advance leaf. Returns entry id. */
|
|
670
842
|
appendCustomEntry(customType, data) {
|
|
671
843
|
const entry = {
|
|
@@ -821,6 +993,13 @@ export class SessionManager {
|
|
|
821
993
|
getEntries() {
|
|
822
994
|
return this.fileEntries.filter((e) => e.type !== "session");
|
|
823
995
|
}
|
|
996
|
+
/** Full append-only history for UI/landing; never the provider-resolved context. */
|
|
997
|
+
getFullHistory() {
|
|
998
|
+
return this.getEntries().map((entry) => structuredClone(entry));
|
|
999
|
+
}
|
|
1000
|
+
getDisplayHistory() {
|
|
1001
|
+
return this.getFullHistory();
|
|
1002
|
+
}
|
|
824
1003
|
/**
|
|
825
1004
|
* Get the session as a tree structure. Returns a shallow defensive copy of all entries.
|
|
826
1005
|
* A well-formed session has exactly one root (first entry with parentId === null).
|
|
@@ -858,7 +1037,8 @@ export class SessionManager {
|
|
|
858
1037
|
const stack = [...roots];
|
|
859
1038
|
while (stack.length > 0) {
|
|
860
1039
|
const node = stack.pop();
|
|
861
|
-
node.children.sort((a, b) => new Date(a.entry.timestamp).getTime() -
|
|
1040
|
+
node.children.sort((a, b) => new Date(a.entry.timestamp).getTime() -
|
|
1041
|
+
new Date(b.entry.timestamp).getTime());
|
|
862
1042
|
stack.push(...node.children);
|
|
863
1043
|
}
|
|
864
1044
|
return roots;
|
|
@@ -939,7 +1119,11 @@ export class SessionManager {
|
|
|
939
1119
|
const labelsToWrite = [];
|
|
940
1120
|
for (const [targetId, label] of this.labelsById) {
|
|
941
1121
|
if (pathEntryIds.has(targetId)) {
|
|
942
|
-
labelsToWrite.push({
|
|
1122
|
+
labelsToWrite.push({
|
|
1123
|
+
targetId,
|
|
1124
|
+
label,
|
|
1125
|
+
timestamp: this.labelTimestampsById.get(targetId),
|
|
1126
|
+
});
|
|
943
1127
|
}
|
|
944
1128
|
}
|
|
945
1129
|
if (this.persist) {
|
|
@@ -947,7 +1131,7 @@ export class SessionManager {
|
|
|
947
1131
|
const lastEntryId = pathWithoutLabels[pathWithoutLabels.length - 1]?.id || null;
|
|
948
1132
|
let parentId = lastEntryId;
|
|
949
1133
|
const labelEntries = [];
|
|
950
|
-
for (const { targetId, label, timestamp: labelTimestamp } of labelsToWrite) {
|
|
1134
|
+
for (const { targetId, label, timestamp: labelTimestamp, } of labelsToWrite) {
|
|
951
1135
|
const labelEntry = {
|
|
952
1136
|
type: "label",
|
|
953
1137
|
id: generateId(new Set(pathEntryIds)),
|
|
@@ -982,7 +1166,7 @@ export class SessionManager {
|
|
|
982
1166
|
// In-memory mode: replace current session with the path + labels
|
|
983
1167
|
const labelEntries = [];
|
|
984
1168
|
let parentId = pathWithoutLabels[pathWithoutLabels.length - 1]?.id || null;
|
|
985
|
-
for (const { targetId, label, timestamp: labelTimestamp } of labelsToWrite) {
|
|
1169
|
+
for (const { targetId, label, timestamp: labelTimestamp, } of labelsToWrite) {
|
|
986
1170
|
const labelEntry = {
|
|
987
1171
|
type: "label",
|
|
988
1172
|
id: generateId(new Set([...pathEntryIds, ...labelEntries.map((e) => e.id)])),
|
|
@@ -1005,7 +1189,9 @@ export class SessionManager {
|
|
|
1005
1189
|
* @param sessionDir Optional session directory. If omitted, uses default (~/.spectral/agent/sessions/<encoded-cwd>/).
|
|
1006
1190
|
*/
|
|
1007
1191
|
static create(cwd, sessionDir) {
|
|
1008
|
-
const dir = sessionDir
|
|
1192
|
+
const dir = sessionDir
|
|
1193
|
+
? normalizePath(sessionDir)
|
|
1194
|
+
: getDefaultSessionDir(cwd);
|
|
1009
1195
|
return new SessionManager(cwd, dir, undefined, true);
|
|
1010
1196
|
}
|
|
1011
1197
|
/**
|
|
@@ -1021,7 +1207,9 @@ export class SessionManager {
|
|
|
1021
1207
|
const header = entries.find((e) => e.type === "session");
|
|
1022
1208
|
const cwd = cwdOverride ?? header?.cwd ?? process.cwd();
|
|
1023
1209
|
// If no sessionDir provided, derive from file's parent directory
|
|
1024
|
-
const dir = sessionDir
|
|
1210
|
+
const dir = sessionDir
|
|
1211
|
+
? normalizePath(sessionDir)
|
|
1212
|
+
: resolve(resolvedPath, "..");
|
|
1025
1213
|
return new SessionManager(cwd, dir, resolvedPath, true);
|
|
1026
1214
|
}
|
|
1027
1215
|
/**
|
|
@@ -1030,7 +1218,9 @@ export class SessionManager {
|
|
|
1030
1218
|
* @param sessionDir Optional session directory. If omitted, uses default (~/.spectral/agent/sessions/<encoded-cwd>/).
|
|
1031
1219
|
*/
|
|
1032
1220
|
static continueRecent(cwd, sessionDir) {
|
|
1033
|
-
const dir = sessionDir
|
|
1221
|
+
const dir = sessionDir
|
|
1222
|
+
? normalizePath(sessionDir)
|
|
1223
|
+
: getDefaultSessionDir(cwd);
|
|
1034
1224
|
const mostRecent = findMostRecentSession(dir);
|
|
1035
1225
|
if (mostRecent) {
|
|
1036
1226
|
return new SessionManager(cwd, dir, mostRecent, true);
|
|
@@ -1059,7 +1249,9 @@ export class SessionManager {
|
|
|
1059
1249
|
if (!sourceHeader) {
|
|
1060
1250
|
throw new Error(`Cannot fork: source session has no header: ${resolvedSourcePath}`);
|
|
1061
1251
|
}
|
|
1062
|
-
const dir = sessionDir
|
|
1252
|
+
const dir = sessionDir
|
|
1253
|
+
? normalizePath(sessionDir)
|
|
1254
|
+
: getDefaultSessionDir(resolvedTargetCwd);
|
|
1063
1255
|
if (!existsSync(dir)) {
|
|
1064
1256
|
mkdirSync(dir, { recursive: true });
|
|
1065
1257
|
}
|
|
@@ -1093,7 +1285,9 @@ export class SessionManager {
|
|
|
1093
1285
|
* @param onProgress Optional callback for progress updates (loaded, total)
|
|
1094
1286
|
*/
|
|
1095
1287
|
static async list(cwd, sessionDir, onProgress) {
|
|
1096
|
-
const dir = sessionDir
|
|
1288
|
+
const dir = sessionDir
|
|
1289
|
+
? normalizePath(sessionDir)
|
|
1290
|
+
: getDefaultSessionDir(cwd);
|
|
1097
1291
|
const sessions = await listSessionsFromDir(dir, onProgress);
|
|
1098
1292
|
sessions.sort((a, b) => b.modified.getTime() - a.modified.getTime());
|
|
1099
1293
|
return sessions;
|
|
@@ -1109,7 +1303,9 @@ export class SessionManager {
|
|
|
1109
1303
|
return [];
|
|
1110
1304
|
}
|
|
1111
1305
|
const entries = await readdir(sessionsDir, { withFileTypes: true });
|
|
1112
|
-
const dirs = entries
|
|
1306
|
+
const dirs = entries
|
|
1307
|
+
.filter((e) => e.isDirectory())
|
|
1308
|
+
.map((e) => join(sessionsDir, e.name));
|
|
1113
1309
|
// Count total files first for accurate progress
|
|
1114
1310
|
let totalFiles = 0;
|
|
1115
1311
|
const dirFiles = [];
|
|
@@ -31,6 +31,13 @@ export interface PromptMutationSettings {
|
|
|
31
31
|
provider?: string;
|
|
32
32
|
modelId?: string;
|
|
33
33
|
}
|
|
34
|
+
export interface LlmCompactionSettings {
|
|
35
|
+
enabled?: boolean;
|
|
36
|
+
provider?: string;
|
|
37
|
+
modelId?: string;
|
|
38
|
+
timeoutMs?: number;
|
|
39
|
+
maxResponseChars?: number;
|
|
40
|
+
}
|
|
34
41
|
export type TransportSetting = Transport;
|
|
35
42
|
/**
|
|
36
43
|
* Package source for npm/git packages.
|
|
@@ -73,6 +80,7 @@ export interface Settings {
|
|
|
73
80
|
disabledNativeExtensions?: string[];
|
|
74
81
|
enabledNativeExtensions?: string[];
|
|
75
82
|
promptMutation?: PromptMutationSettings;
|
|
83
|
+
llmCompaction?: LlmCompactionSettings;
|
|
76
84
|
}
|
|
77
85
|
export type SettingsScope = "global" | "project";
|
|
78
86
|
export interface SettingsStorage {
|
|
@@ -163,6 +171,13 @@ export declare class SettingsManager {
|
|
|
163
171
|
getCompactionKeepRecentTokens(): number;
|
|
164
172
|
getCompactionPolicy(): CompactionPolicy;
|
|
165
173
|
getCompactionSettings(): CompactionPolicy["conversation"];
|
|
174
|
+
getLlmCompactionSettings(): {
|
|
175
|
+
enabled: boolean;
|
|
176
|
+
provider?: string;
|
|
177
|
+
modelId?: string;
|
|
178
|
+
timeoutMs: number;
|
|
179
|
+
maxResponseChars: number;
|
|
180
|
+
};
|
|
166
181
|
getBranchSummarySettings(): {
|
|
167
182
|
reserveTokens: number;
|
|
168
183
|
skipPrompt: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settings-manager.d.ts","sourceRoot":"","sources":["../../../../src/sdk/coding-agent/core/settings-manager.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"settings-manager.d.ts","sourceRoot":"","sources":["../../../../src/sdk/coding-agent/core/settings-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -472,6 +472,17 @@ export class SettingsManager {
|
|
|
472
472
|
getCompactionSettings() {
|
|
473
473
|
return this.getCompactionPolicy().conversation;
|
|
474
474
|
}
|
|
475
|
+
getLlmCompactionSettings() {
|
|
476
|
+
const timeoutMs = this.settings.llmCompaction?.timeoutMs;
|
|
477
|
+
const maxResponseChars = this.settings.llmCompaction?.maxResponseChars;
|
|
478
|
+
return {
|
|
479
|
+
enabled: this.settings.llmCompaction?.enabled === true,
|
|
480
|
+
provider: this.settings.llmCompaction?.provider,
|
|
481
|
+
modelId: this.settings.llmCompaction?.modelId,
|
|
482
|
+
timeoutMs: typeof timeoutMs === "number" && Number.isFinite(timeoutMs) && timeoutMs > 0 ? Math.floor(timeoutMs) : 15_000,
|
|
483
|
+
maxResponseChars: typeof maxResponseChars === "number" && Number.isFinite(maxResponseChars) && maxResponseChars > 0 ? Math.min(Math.floor(maxResponseChars), 50_000) : 20_000,
|
|
484
|
+
};
|
|
485
|
+
}
|
|
475
486
|
getBranchSummarySettings() {
|
|
476
487
|
return {
|
|
477
488
|
reserveTokens: this.settings.branchSummary?.reserveTokens ?? 16384,
|