skill-distill 1.0.0 → 1.0.1

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/cli.js CHANGED
@@ -46,94 +46,128 @@ var ClaudeSessionLoader = class extends SessionLoader {
46
46
  super(options);
47
47
  }
48
48
  getDefaultBasePath() {
49
- return join(homedir(), ".claude", "projects");
49
+ return join(homedir(), ".claude", "transcripts");
50
50
  }
51
51
  async listSessions() {
52
52
  const sessions = [];
53
53
  try {
54
- const projectDirs = await fs.readdir(this.basePath);
55
- for (const projectDir of projectDirs) {
56
- const projectPath = join(this.basePath, projectDir);
57
- const stat = await fs.stat(projectPath);
58
- if (!stat.isDirectory()) continue;
59
- const sessionsPath = join(projectPath, "sessions");
60
- try {
61
- const sessionFiles = await fs.readdir(sessionsPath);
62
- for (const file of sessionFiles) {
63
- if (!file.endsWith(".json")) continue;
64
- const sessionPath = join(sessionsPath, file);
65
- const sessionData = await this.readSessionFile(sessionPath);
66
- if (sessionData) {
67
- sessions.push({
68
- id: sessionData.id,
69
- projectPath: projectDir,
70
- startTime: sessionData.createdAt,
71
- endTime: sessionData.updatedAt,
72
- messageCount: sessionData.messages.length,
73
- summary: this.extractSummary(sessionData.messages)
74
- });
75
- }
76
- }
77
- } catch {
78
- continue;
79
- }
54
+ const files = await fs.readdir(this.basePath);
55
+ for (const file of files) {
56
+ if (!file.endsWith(".jsonl") || !file.startsWith("ses_")) continue;
57
+ const filePath = join(this.basePath, file);
58
+ const stat = await fs.stat(filePath);
59
+ const sessionId = file.replace(".jsonl", "");
60
+ const entries = await this.readTranscriptFile(filePath);
61
+ if (entries.length === 0) continue;
62
+ const userMessages = entries.filter((e) => e.type === "user");
63
+ const firstEntry = entries[0];
64
+ const lastEntry = entries[entries.length - 1];
65
+ sessions.push({
66
+ id: sessionId,
67
+ projectPath: "",
68
+ startTime: firstEntry.timestamp,
69
+ endTime: lastEntry.timestamp,
70
+ messageCount: userMessages.length,
71
+ summary: this.extractSummary(entries)
72
+ });
80
73
  }
81
74
  } catch (error) {
82
75
  throw new Error(`Failed to list sessions: ${error}`);
83
76
  }
84
- return sessions;
77
+ return sessions.sort(
78
+ (a, b) => new Date(b.startTime).getTime() - new Date(a.startTime).getTime()
79
+ );
85
80
  }
86
81
  async getSession(id) {
87
- const sessions = await this.listSessions();
88
- const sessionInfo = sessions.find((s) => s.id === id);
89
- if (!sessionInfo) {
82
+ const filePath = join(this.basePath, `${id}.jsonl`);
83
+ try {
84
+ await fs.access(filePath);
85
+ } catch {
90
86
  throw new Error(`Session not found: ${id}`);
91
87
  }
92
- const sessionPath = join(this.basePath, sessionInfo.projectPath, "sessions", `${id}.json`);
93
- const data = await this.readSessionFile(sessionPath);
94
- if (!data) {
95
- throw new Error(`Failed to read session: ${id}`);
88
+ const entries = await this.readTranscriptFile(filePath);
89
+ if (entries.length === 0) {
90
+ throw new Error(`Empty session: ${id}`);
96
91
  }
97
- return this.transformSession(data, sessionInfo.projectPath);
92
+ return this.transformSession(id, entries);
98
93
  }
99
- async readSessionFile(path) {
94
+ async readTranscriptFile(path) {
100
95
  try {
101
96
  const content = await fs.readFile(path, "utf-8");
102
- return JSON.parse(content);
97
+ const lines = content.trim().split("\n").filter(Boolean);
98
+ return lines.map((line) => JSON.parse(line));
103
99
  } catch {
104
- return null;
100
+ return [];
105
101
  }
106
102
  }
107
- transformSession(data, projectPath) {
108
- return {
109
- id: data.id,
110
- projectPath,
111
- startTime: data.createdAt,
112
- endTime: data.updatedAt,
113
- messages: data.messages.map((msg) => this.transformMessage(msg))
114
- };
115
- }
116
- transformMessage(msg) {
103
+ transformSession(id, entries) {
104
+ const messages = [];
105
+ let currentAssistantContent = "";
106
+ let currentToolCalls = [];
107
+ let currentToolResults = [];
108
+ let lastTimestamp = "";
109
+ for (const entry of entries) {
110
+ if (entry.type === "user") {
111
+ if (currentAssistantContent || currentToolCalls?.length) {
112
+ messages.push({
113
+ role: "assistant",
114
+ content: currentAssistantContent,
115
+ timestamp: lastTimestamp,
116
+ toolCalls: currentToolCalls.length > 0 ? currentToolCalls : void 0,
117
+ toolResults: currentToolResults.length > 0 ? currentToolResults : void 0
118
+ });
119
+ currentAssistantContent = "";
120
+ currentToolCalls = [];
121
+ currentToolResults = [];
122
+ }
123
+ messages.push({
124
+ role: "user",
125
+ content: entry.content ?? "",
126
+ timestamp: entry.timestamp
127
+ });
128
+ } else if (entry.type === "assistant") {
129
+ currentAssistantContent += (entry.content ?? "") + "\n";
130
+ lastTimestamp = entry.timestamp;
131
+ } else if (entry.type === "tool_use") {
132
+ currentToolCalls.push({
133
+ name: entry.tool_name ?? "unknown",
134
+ input: entry.tool_input ?? {}
135
+ });
136
+ lastTimestamp = entry.timestamp;
137
+ } else if (entry.type === "tool_result") {
138
+ currentToolResults.push({
139
+ name: entry.tool_name ?? "unknown",
140
+ output: entry.tool_output?.preview ?? "",
141
+ success: true
142
+ });
143
+ lastTimestamp = entry.timestamp;
144
+ }
145
+ }
146
+ if (currentAssistantContent || currentToolCalls?.length) {
147
+ messages.push({
148
+ role: "assistant",
149
+ content: currentAssistantContent.trim(),
150
+ timestamp: lastTimestamp,
151
+ toolCalls: currentToolCalls.length > 0 ? currentToolCalls : void 0,
152
+ toolResults: currentToolResults.length > 0 ? currentToolResults : void 0
153
+ });
154
+ }
155
+ const firstEntry = entries[0];
156
+ const lastEntry = entries[entries.length - 1];
117
157
  return {
118
- role: msg.role === "human" ? "user" : "assistant",
119
- content: msg.content,
120
- timestamp: msg.createdAt,
121
- toolCalls: msg.toolUseBlocks?.map((t) => ({
122
- name: t.name,
123
- input: t.input
124
- })),
125
- toolResults: msg.toolResultBlocks?.map((t) => ({
126
- name: t.toolUseId,
127
- output: t.content,
128
- success: !t.isError
129
- }))
158
+ id,
159
+ projectPath: "",
160
+ startTime: firstEntry.timestamp,
161
+ endTime: lastEntry.timestamp,
162
+ messages
130
163
  };
131
164
  }
132
- extractSummary(messages) {
133
- const firstUserMessage = messages.find((m) => m.role === "human");
134
- if (!firstUserMessage) return "";
135
- const content = firstUserMessage.content;
136
- return content.length > 100 ? content.slice(0, 100) + "..." : content;
165
+ extractSummary(entries) {
166
+ const firstUserEntry = entries.find((e) => e.type === "user");
167
+ if (!firstUserEntry?.content) return "";
168
+ const content = firstUserEntry.content;
169
+ const firstLine = content.split("\n")[0];
170
+ return firstLine.length > 80 ? firstLine.slice(0, 80) + "..." : firstLine;
137
171
  }
138
172
  };
139
173