@este.systems/dsc 0.1.0
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/LICENSE +21 -0
- package/README.md +408 -0
- package/bin/dsc.mjs +29 -0
- package/dist/agent.js +259 -0
- package/dist/agent.js.map +1 -0
- package/dist/api.js +333 -0
- package/dist/api.js.map +1 -0
- package/dist/approval.js +79 -0
- package/dist/approval.js.map +1 -0
- package/dist/audit.js +26 -0
- package/dist/audit.js.map +1 -0
- package/dist/compact.js +100 -0
- package/dist/compact.js.map +1 -0
- package/dist/history.js +212 -0
- package/dist/history.js.map +1 -0
- package/dist/index.js +830 -0
- package/dist/index.js.map +1 -0
- package/dist/markdown.js +543 -0
- package/dist/markdown.js.map +1 -0
- package/dist/prompt.js +44 -0
- package/dist/prompt.js.map +1 -0
- package/dist/repl_history.js +55 -0
- package/dist/repl_history.js.map +1 -0
- package/dist/search.js +215 -0
- package/dist/search.js.map +1 -0
- package/dist/tools.js +670 -0
- package/dist/tools.js.map +1 -0
- package/dist/ui.js +165 -0
- package/dist/ui.js.map +1 -0
- package/package.json +57 -0
package/dist/approval.js
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import * as readline from "node:readline/promises";
|
|
2
|
+
import { stdin as input, stdout as output } from "node:process";
|
|
3
|
+
import { createPatch } from "diff";
|
|
4
|
+
const RESET = "\x1b[0m";
|
|
5
|
+
const DIM = "\x1b[2m";
|
|
6
|
+
const RED = "\x1b[31m";
|
|
7
|
+
const GREEN = "\x1b[32m";
|
|
8
|
+
const YELLOW = "\x1b[33m";
|
|
9
|
+
const CYAN = "\x1b[36m";
|
|
10
|
+
const BOLD = "\x1b[1m";
|
|
11
|
+
function colorize(diffText) {
|
|
12
|
+
return diffText
|
|
13
|
+
.split("\n")
|
|
14
|
+
.map((line) => {
|
|
15
|
+
if (line.startsWith("+++") || line.startsWith("---"))
|
|
16
|
+
return BOLD + line + RESET;
|
|
17
|
+
if (line.startsWith("@@"))
|
|
18
|
+
return CYAN + line + RESET;
|
|
19
|
+
if (line.startsWith("+"))
|
|
20
|
+
return GREEN + line + RESET;
|
|
21
|
+
if (line.startsWith("-"))
|
|
22
|
+
return RED + line + RESET;
|
|
23
|
+
return line;
|
|
24
|
+
})
|
|
25
|
+
.join("\n");
|
|
26
|
+
}
|
|
27
|
+
let activeAsker = null;
|
|
28
|
+
export function setAsker(fn) {
|
|
29
|
+
activeAsker = fn;
|
|
30
|
+
}
|
|
31
|
+
async function ask(question) {
|
|
32
|
+
let answer;
|
|
33
|
+
if (activeAsker) {
|
|
34
|
+
answer = (await activeAsker(question)).trim().toLowerCase();
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
const rl = readline.createInterface({ input, output });
|
|
38
|
+
try {
|
|
39
|
+
answer = (await rl.question(question)).trim().toLowerCase();
|
|
40
|
+
}
|
|
41
|
+
finally {
|
|
42
|
+
rl.close();
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return answer === "y" || answer === "yes";
|
|
46
|
+
}
|
|
47
|
+
export async function confirmWrite(path, oldContent, newContent, existed) {
|
|
48
|
+
const verb = existed ? "Overwrite" : "Create";
|
|
49
|
+
process.stdout.write(`\n${YELLOW}${verb} ${path}${RESET}\n`);
|
|
50
|
+
if (existed) {
|
|
51
|
+
const patch = createPatch(path, oldContent, newContent, "", "", { context: 3 });
|
|
52
|
+
process.stdout.write(colorize(patch) + "\n");
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
const preview = newContent.length > 4000 ? newContent.slice(0, 4000) + "\n…(truncated)" : newContent;
|
|
56
|
+
process.stdout.write(`${DIM}--- proposed content (${newContent.length} chars) ---${RESET}\n`);
|
|
57
|
+
process.stdout.write(preview + "\n");
|
|
58
|
+
}
|
|
59
|
+
return ask(`Apply? [y/N] `);
|
|
60
|
+
}
|
|
61
|
+
export async function confirmEdit(path, oldContent, newContent) {
|
|
62
|
+
process.stdout.write(`\n${YELLOW}Edit ${path}${RESET}\n`);
|
|
63
|
+
const patch = createPatch(path, oldContent, newContent, "", "", { context: 3 });
|
|
64
|
+
process.stdout.write(colorize(patch) + "\n");
|
|
65
|
+
return ask(`Apply? [y/N] `);
|
|
66
|
+
}
|
|
67
|
+
export async function confirmBash(command, description) {
|
|
68
|
+
process.stdout.write(`\n${YELLOW}Run shell command${RESET}\n`);
|
|
69
|
+
if (description)
|
|
70
|
+
process.stdout.write(`${DIM}${description}${RESET}\n`);
|
|
71
|
+
process.stdout.write(` $ ${command}\n`);
|
|
72
|
+
return ask(`Run? [y/N] `);
|
|
73
|
+
}
|
|
74
|
+
export async function confirmFetch(url) {
|
|
75
|
+
process.stdout.write(`\n${YELLOW}Fetch URL${RESET}\n`);
|
|
76
|
+
process.stdout.write(` ${url}\n`);
|
|
77
|
+
return ask(`Fetch? [y/N] `);
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=approval.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"approval.js","sourceRoot":"","sources":["../src/approval.ts"],"names":[],"mappings":"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"}
|
package/dist/audit.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { promises as fs } from "node:fs";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
export function auditLogPath() {
|
|
5
|
+
const xdg = process.env.XDG_STATE_HOME;
|
|
6
|
+
const base = xdg && xdg.length ? xdg : path.join(homedir(), ".local", "state");
|
|
7
|
+
return path.join(base, "dsc", "audit.log");
|
|
8
|
+
}
|
|
9
|
+
let _dirEnsured = false;
|
|
10
|
+
export async function record(entry) {
|
|
11
|
+
if (process.env.DSC_NO_AUDIT === "1")
|
|
12
|
+
return;
|
|
13
|
+
const file = auditLogPath();
|
|
14
|
+
try {
|
|
15
|
+
if (!_dirEnsured) {
|
|
16
|
+
await fs.mkdir(path.dirname(file), { recursive: true });
|
|
17
|
+
_dirEnsured = true;
|
|
18
|
+
}
|
|
19
|
+
const line = JSON.stringify({ ts: new Date().toISOString(), ...entry }) + "\n";
|
|
20
|
+
await fs.appendFile(file, line, "utf8");
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
// best-effort; never fail a tool call because of audit log issues
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=audit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit.js","sourceRoot":"","sources":["../src/audit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAElC,MAAM,UAAU,YAAY;IAC1B,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;IACvC,MAAM,IAAI,GAAG,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC/E,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,WAAW,CAAC,CAAC;AAC7C,CAAC;AAED,IAAI,WAAW,GAAG,KAAK,CAAC;AAExB,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,KAA8B;IACzD,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY,KAAK,GAAG;QAAE,OAAO;IAC7C,MAAM,IAAI,GAAG,YAAY,EAAE,CAAC;IAC5B,IAAI,CAAC;QACH,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YACxD,WAAW,GAAG,IAAI,CAAC;QACrB,CAAC;QACD,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,GAAG,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC;QAC/E,MAAM,EAAE,CAAC,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;IAC1C,CAAC;IAAC,MAAM,CAAC;QACP,kEAAkE;IACpE,CAAC;AACH,CAAC"}
|
package/dist/compact.js
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { chat } from "./api.js";
|
|
2
|
+
const MAX_INPUT_CHARS = 80_000; // hard cap on what we send to the summarizer
|
|
3
|
+
const SUMMARIZER_SYSTEM = `You are summarizing an ongoing CLI coding-assistant session for compaction. Produce a concise, plain-prose summary covering: the user's overall goal, key decisions and trade-offs, files touched, the current state of partial work, and any pending tasks. Keep it under ~800 tokens. The summary will be shown to the assistant on future turns; write it as factual session notes, not a story. Do not invent details that aren't in the conversation.`;
|
|
4
|
+
/**
|
|
5
|
+
* Pick the index in `messages` where we start KEEPING messages (everything at
|
|
6
|
+
* or after the index is preserved verbatim). We keep the last `keepUserTurns`
|
|
7
|
+
* user-initiated turns and any assistant/tool messages that follow them.
|
|
8
|
+
*
|
|
9
|
+
* Returns -1 when there's nothing worth compacting (fewer user turns than the
|
|
10
|
+
* keep threshold).
|
|
11
|
+
*/
|
|
12
|
+
export function pickCutpoint(messages, keepUserTurns) {
|
|
13
|
+
const userIdxs = [];
|
|
14
|
+
for (let i = 0; i < messages.length; i++) {
|
|
15
|
+
if (messages[i].role === "user")
|
|
16
|
+
userIdxs.push(i);
|
|
17
|
+
}
|
|
18
|
+
if (userIdxs.length <= keepUserTurns)
|
|
19
|
+
return -1;
|
|
20
|
+
if (keepUserTurns <= 0)
|
|
21
|
+
return messages.length;
|
|
22
|
+
return userIdxs[userIdxs.length - keepUserTurns];
|
|
23
|
+
}
|
|
24
|
+
function messageToText(m) {
|
|
25
|
+
const role = m.role;
|
|
26
|
+
const content = typeof m.content === "string" ? m.content : "";
|
|
27
|
+
if (role === "tool") {
|
|
28
|
+
return `[tool result for ${m.tool_call_id ?? "?"}]: ${truncate(content, 600)}`;
|
|
29
|
+
}
|
|
30
|
+
if (role === "assistant") {
|
|
31
|
+
let out = `[assistant]: ${content || "(no content)"}`;
|
|
32
|
+
if (m.tool_calls && m.tool_calls.length) {
|
|
33
|
+
const calls = m.tool_calls
|
|
34
|
+
.map((t) => `${t.function.name}(${truncate(t.function.arguments, 120)})`)
|
|
35
|
+
.join(", ");
|
|
36
|
+
out += `\n → called ${calls}`;
|
|
37
|
+
}
|
|
38
|
+
return out;
|
|
39
|
+
}
|
|
40
|
+
if (role === "user")
|
|
41
|
+
return `[user]: ${content}`;
|
|
42
|
+
return `[${role}]: ${content}`;
|
|
43
|
+
}
|
|
44
|
+
function truncate(s, n) {
|
|
45
|
+
return s.length <= n ? s : s.slice(0, n) + "…";
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Summarize all messages older than the cutpoint and return the new state.
|
|
49
|
+
* Folds any prior /compact summary into the new one so successive compactions
|
|
50
|
+
* accumulate rather than forget history.
|
|
51
|
+
*/
|
|
52
|
+
export async function compactSession(state, keepUserTurns, modelOverride, signal) {
|
|
53
|
+
const cutAt = pickCutpoint(state.messages, keepUserTurns);
|
|
54
|
+
if (cutAt < 0)
|
|
55
|
+
return null;
|
|
56
|
+
const toSummarize = state.messages.slice(0, cutAt);
|
|
57
|
+
const remainingMessages = state.messages.slice(cutAt);
|
|
58
|
+
if (toSummarize.length === 0)
|
|
59
|
+
return null;
|
|
60
|
+
const priorSummary = state.compaction?.summary ?? null;
|
|
61
|
+
const conversationText = toSummarize.map(messageToText).join("\n\n");
|
|
62
|
+
const trimmedConversation = conversationText.length > MAX_INPUT_CHARS
|
|
63
|
+
? conversationText.slice(-MAX_INPUT_CHARS)
|
|
64
|
+
: conversationText;
|
|
65
|
+
const userPrompt = (priorSummary
|
|
66
|
+
? `Previous summary of even older turns (fold this in):\n${priorSummary}\n\n`
|
|
67
|
+
: "") +
|
|
68
|
+
`Conversation to summarize:\n${trimmedConversation}\n\n` +
|
|
69
|
+
`Now produce the updated summary.`;
|
|
70
|
+
const resp = await chat({
|
|
71
|
+
model: modelOverride ?? state.model,
|
|
72
|
+
messages: [
|
|
73
|
+
{ role: "system", content: SUMMARIZER_SYSTEM },
|
|
74
|
+
{ role: "user", content: userPrompt },
|
|
75
|
+
],
|
|
76
|
+
signal,
|
|
77
|
+
});
|
|
78
|
+
const content = resp.choices[0]?.message?.content?.trim() ?? "";
|
|
79
|
+
if (!content)
|
|
80
|
+
return null;
|
|
81
|
+
const compaction = {
|
|
82
|
+
summary: content,
|
|
83
|
+
compacted_at: Date.now(),
|
|
84
|
+
turns_removed: (state.compaction?.turns_removed ?? 0) + countUserTurns(toSummarize),
|
|
85
|
+
};
|
|
86
|
+
return {
|
|
87
|
+
summary: content,
|
|
88
|
+
turnsRemoved: countUserTurns(toSummarize),
|
|
89
|
+
remainingMessages,
|
|
90
|
+
droppedMessages: toSummarize,
|
|
91
|
+
usage: resp.usage,
|
|
92
|
+
};
|
|
93
|
+
// Note: caller is responsible for assigning state.compaction = {...} since
|
|
94
|
+
// we don't mutate `state` here. The above CompactionState is just to keep
|
|
95
|
+
// the contract clear if we ever want to return it directly.
|
|
96
|
+
}
|
|
97
|
+
function countUserTurns(messages) {
|
|
98
|
+
return messages.filter((m) => m.role === "user").length;
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=compact.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compact.js","sourceRoot":"","sources":["../src/compact.ts"],"names":[],"mappings":"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"}
|
package/dist/history.js
ADDED
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import { promises as fs } from "node:fs";
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
3
|
+
import * as path from "node:path";
|
|
4
|
+
import { homedir } from "node:os";
|
|
5
|
+
import { randomBytes } from "node:crypto";
|
|
6
|
+
import { AVAILABLE_MODELS, DEFAULT_MODEL, newStats, } from "./api.js";
|
|
7
|
+
export const LEGACY_HISTORY_FILE = ".dsc-history.json";
|
|
8
|
+
export function sessionsDir() {
|
|
9
|
+
const xdg = process.env.XDG_DATA_HOME;
|
|
10
|
+
const base = xdg && xdg.length ? xdg : path.join(homedir(), ".local", "share");
|
|
11
|
+
return path.join(base, "dsc", "sessions");
|
|
12
|
+
}
|
|
13
|
+
function newSessionId() {
|
|
14
|
+
return `${Date.now()}-${randomBytes(2).toString("hex")}`;
|
|
15
|
+
}
|
|
16
|
+
function statsFromPersisted(s) {
|
|
17
|
+
const stats = newStats();
|
|
18
|
+
if (!s)
|
|
19
|
+
return stats;
|
|
20
|
+
stats.prompts = s.prompts ?? 0;
|
|
21
|
+
stats.responses = s.responses ?? 0;
|
|
22
|
+
stats.prompt_tokens = s.prompt_tokens ?? 0;
|
|
23
|
+
stats.completion_tokens = s.completion_tokens ?? 0;
|
|
24
|
+
stats.total_tokens = s.total_tokens ?? 0;
|
|
25
|
+
stats.cache_hit_tokens = s.cache_hit_tokens ?? 0;
|
|
26
|
+
stats.cache_miss_tokens = s.cache_miss_tokens ?? 0;
|
|
27
|
+
stats.tool_calls_total = s.tool_calls_total ?? 0;
|
|
28
|
+
stats.tool_calls_by_name = { ...(s.tool_calls_by_name ?? {}) };
|
|
29
|
+
stats.files_touched = new Set(Array.isArray(s.files_touched) ? s.files_touched : []);
|
|
30
|
+
return stats;
|
|
31
|
+
}
|
|
32
|
+
function statsToPersisted(stats) {
|
|
33
|
+
return {
|
|
34
|
+
prompts: stats.prompts,
|
|
35
|
+
responses: stats.responses,
|
|
36
|
+
prompt_tokens: stats.prompt_tokens,
|
|
37
|
+
completion_tokens: stats.completion_tokens,
|
|
38
|
+
total_tokens: stats.total_tokens,
|
|
39
|
+
cache_hit_tokens: stats.cache_hit_tokens,
|
|
40
|
+
cache_miss_tokens: stats.cache_miss_tokens,
|
|
41
|
+
tool_calls_total: stats.tool_calls_total,
|
|
42
|
+
tool_calls_by_name: { ...stats.tool_calls_by_name },
|
|
43
|
+
files_touched: Array.from(stats.files_touched),
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
export function newSession(cwd, model) {
|
|
47
|
+
return {
|
|
48
|
+
id: newSessionId(),
|
|
49
|
+
cwd,
|
|
50
|
+
model,
|
|
51
|
+
messages: [],
|
|
52
|
+
stats: newStats(),
|
|
53
|
+
created_at: Date.now(),
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
export async function saveSession(state) {
|
|
57
|
+
const dir = sessionsDir();
|
|
58
|
+
await fs.mkdir(dir, { recursive: true });
|
|
59
|
+
const file = path.join(dir, `${state.id}.json`);
|
|
60
|
+
const data = {
|
|
61
|
+
version: 2,
|
|
62
|
+
id: state.id,
|
|
63
|
+
cwd: state.cwd,
|
|
64
|
+
model: state.model,
|
|
65
|
+
created_at: state.created_at,
|
|
66
|
+
updated_at: Date.now(),
|
|
67
|
+
messages: state.messages,
|
|
68
|
+
stats: statsToPersisted(state.stats),
|
|
69
|
+
...(state.compaction ? { compaction: state.compaction } : {}),
|
|
70
|
+
...(state.archivedMessages?.length
|
|
71
|
+
? { archivedMessages: state.archivedMessages }
|
|
72
|
+
: {}),
|
|
73
|
+
...(state.name ? { name: state.name } : {}),
|
|
74
|
+
...(state.assistantLabel ? { assistantLabel: state.assistantLabel } : {}),
|
|
75
|
+
};
|
|
76
|
+
const tmp = file + ".tmp";
|
|
77
|
+
await fs.writeFile(tmp, JSON.stringify(data, null, 2), "utf8");
|
|
78
|
+
await fs.rename(tmp, file);
|
|
79
|
+
}
|
|
80
|
+
export async function loadSession(id) {
|
|
81
|
+
const file = path.join(sessionsDir(), `${id}.json`);
|
|
82
|
+
let text;
|
|
83
|
+
try {
|
|
84
|
+
text = await fs.readFile(file, "utf8");
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
let data;
|
|
90
|
+
try {
|
|
91
|
+
data = JSON.parse(text);
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
if (!data || data.version !== 2 || !Array.isArray(data.messages))
|
|
97
|
+
return null;
|
|
98
|
+
const model = AVAILABLE_MODELS.includes(data.model) ? data.model : DEFAULT_MODEL;
|
|
99
|
+
return {
|
|
100
|
+
id: data.id,
|
|
101
|
+
cwd: data.cwd,
|
|
102
|
+
model,
|
|
103
|
+
messages: data.messages,
|
|
104
|
+
stats: statsFromPersisted(data.stats),
|
|
105
|
+
created_at: data.created_at,
|
|
106
|
+
compaction: data.compaction,
|
|
107
|
+
archivedMessages: data.archivedMessages,
|
|
108
|
+
name: data.name,
|
|
109
|
+
assistantLabel: data.assistantLabel,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
export async function listSessions(cwd) {
|
|
113
|
+
const dir = sessionsDir();
|
|
114
|
+
let entries;
|
|
115
|
+
try {
|
|
116
|
+
entries = await fs.readdir(dir);
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
return [];
|
|
120
|
+
}
|
|
121
|
+
const out = [];
|
|
122
|
+
for (const name of entries) {
|
|
123
|
+
if (!name.endsWith(".json"))
|
|
124
|
+
continue;
|
|
125
|
+
let text;
|
|
126
|
+
try {
|
|
127
|
+
text = await fs.readFile(path.join(dir, name), "utf8");
|
|
128
|
+
}
|
|
129
|
+
catch {
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
let data;
|
|
133
|
+
try {
|
|
134
|
+
data = JSON.parse(text);
|
|
135
|
+
}
|
|
136
|
+
catch {
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
if (!data || data.version !== 2)
|
|
140
|
+
continue;
|
|
141
|
+
if (cwd && data.cwd !== cwd)
|
|
142
|
+
continue;
|
|
143
|
+
const firstUser = data.messages.find((m) => m.role === "user");
|
|
144
|
+
out.push({
|
|
145
|
+
id: data.id,
|
|
146
|
+
cwd: data.cwd,
|
|
147
|
+
model: data.model,
|
|
148
|
+
created_at: data.created_at,
|
|
149
|
+
updated_at: data.updated_at,
|
|
150
|
+
message_count: data.messages.filter((m) => m.role === "user" || m.role === "assistant").length,
|
|
151
|
+
first_user_message: typeof firstUser?.content === "string" ? firstUser.content.slice(0, 80) : "",
|
|
152
|
+
name: data.name,
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
out.sort((a, b) => b.updated_at - a.updated_at);
|
|
156
|
+
return out;
|
|
157
|
+
}
|
|
158
|
+
export async function mostRecentForCwd(cwd) {
|
|
159
|
+
const all = await listSessions(cwd);
|
|
160
|
+
return all[0] ?? null;
|
|
161
|
+
}
|
|
162
|
+
export async function deleteSession(id) {
|
|
163
|
+
try {
|
|
164
|
+
await fs.unlink(path.join(sessionsDir(), `${id}.json`));
|
|
165
|
+
}
|
|
166
|
+
catch {
|
|
167
|
+
// ignore
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
// Migrate ./.dsc-history.json (v1) into the new sessions dir on startup.
|
|
171
|
+
// Returns the new session id if a migration happened.
|
|
172
|
+
export async function migrateLegacyIfPresent(cwd, model) {
|
|
173
|
+
const legacy = path.join(cwd, LEGACY_HISTORY_FILE);
|
|
174
|
+
if (!existsSync(legacy))
|
|
175
|
+
return null;
|
|
176
|
+
let text;
|
|
177
|
+
try {
|
|
178
|
+
text = await fs.readFile(legacy, "utf8");
|
|
179
|
+
}
|
|
180
|
+
catch {
|
|
181
|
+
return null;
|
|
182
|
+
}
|
|
183
|
+
let data;
|
|
184
|
+
try {
|
|
185
|
+
data = JSON.parse(text);
|
|
186
|
+
}
|
|
187
|
+
catch {
|
|
188
|
+
return null;
|
|
189
|
+
}
|
|
190
|
+
if (!data || !Array.isArray(data.messages))
|
|
191
|
+
return null;
|
|
192
|
+
const stats = statsFromPersisted(data.stats);
|
|
193
|
+
const sessionModel = AVAILABLE_MODELS.includes(data.model) ? data.model : model;
|
|
194
|
+
const session = {
|
|
195
|
+
id: newSessionId(),
|
|
196
|
+
cwd,
|
|
197
|
+
model: sessionModel,
|
|
198
|
+
messages: data.messages,
|
|
199
|
+
stats,
|
|
200
|
+
created_at: Date.now(),
|
|
201
|
+
};
|
|
202
|
+
await saveSession(session);
|
|
203
|
+
// Best-effort delete of the legacy file
|
|
204
|
+
try {
|
|
205
|
+
await fs.unlink(legacy);
|
|
206
|
+
}
|
|
207
|
+
catch {
|
|
208
|
+
// ignore
|
|
209
|
+
}
|
|
210
|
+
return session.id;
|
|
211
|
+
}
|
|
212
|
+
//# sourceMappingURL=history.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"history.js","sourceRoot":"","sources":["../src/history.ts"],"names":[],"mappings":"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"}
|