psadk 1.3.7 → 1.4.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/CHANGELOG.md +52 -0
- package/README.md +150 -0
- package/build/main/lib/PSAI.d.ts +6 -0
- package/build/main/lib/PSAI.js +147 -79
- package/build/main/lib/PSAgent.js +77 -60
- package/build/main/lib/PSAgentConfig.d.ts +3 -0
- package/build/main/lib/PSAgentLogger.js +12 -9
- package/build/main/lib/PSAgentTask.js +4 -1
- package/build/main/lib/PSAgentTool.js +12 -2
- package/build/main/lib/agent-core/agent-loop.d.ts +23 -0
- package/build/main/lib/agent-core/agent-loop.js +479 -0
- package/build/main/lib/agent-core/agent.d.ts +124 -0
- package/build/main/lib/agent-core/agent.js +402 -0
- package/build/main/lib/agent-core/harness/agent-harness.d.ts +84 -0
- package/build/main/lib/agent-core/harness/agent-harness.js +728 -0
- package/build/main/lib/agent-core/harness/compaction/branch-summarization.d.ts +87 -0
- package/build/main/lib/agent-core/harness/compaction/branch-summarization.js +243 -0
- package/build/main/lib/agent-core/harness/compaction/compaction.d.ts +121 -0
- package/build/main/lib/agent-core/harness/compaction/compaction.js +616 -0
- package/build/main/lib/agent-core/harness/compaction/utils.d.ts +37 -0
- package/build/main/lib/agent-core/harness/compaction/utils.js +153 -0
- package/build/main/lib/agent-core/harness/env/nodejs.d.ts +43 -0
- package/build/main/lib/agent-core/harness/env/nodejs.js +348 -0
- package/build/main/lib/agent-core/harness/execution-env.d.ts +3 -0
- package/build/main/lib/agent-core/harness/execution-env.js +3 -0
- package/build/main/lib/agent-core/harness/messages.d.ts +50 -0
- package/build/main/lib/agent-core/harness/messages.js +102 -0
- package/build/main/lib/agent-core/harness/prompt-templates.d.ts +44 -0
- package/build/main/lib/agent-core/harness/prompt-templates.js +200 -0
- package/build/main/lib/agent-core/harness/session/repo/jsonl.d.ts +19 -0
- package/build/main/lib/agent-core/harness/session/repo/jsonl.js +92 -0
- package/build/main/lib/agent-core/harness/session/repo/memory.d.ts +17 -0
- package/build/main/lib/agent-core/harness/session/repo/memory.js +42 -0
- package/build/main/lib/agent-core/harness/session/repo/shared.d.ts +9 -0
- package/build/main/lib/agent-core/harness/session/repo/shared.js +31 -0
- package/build/main/lib/agent-core/harness/session/session.d.ts +31 -0
- package/build/main/lib/agent-core/harness/session/session.js +196 -0
- package/build/main/lib/agent-core/harness/session/storage/jsonl.d.ts +29 -0
- package/build/main/lib/agent-core/harness/session/storage/jsonl.js +170 -0
- package/build/main/lib/agent-core/harness/session/storage/memory.d.ts +25 -0
- package/build/main/lib/agent-core/harness/session/storage/memory.js +90 -0
- package/build/main/lib/agent-core/harness/skills.d.ts +40 -0
- package/build/main/lib/agent-core/harness/skills.js +259 -0
- package/build/main/lib/agent-core/harness/system-prompt.d.ts +2 -0
- package/build/main/lib/agent-core/harness/system-prompt.js +30 -0
- package/build/main/lib/agent-core/harness/types.d.ts +524 -0
- package/build/main/lib/agent-core/harness/types.js +16 -0
- package/build/main/lib/agent-core/harness/utils/shell-output.d.ts +13 -0
- package/build/main/lib/agent-core/harness/utils/shell-output.js +97 -0
- package/build/main/lib/agent-core/harness/utils/truncate.d.ts +69 -0
- package/build/main/lib/agent-core/harness/utils/truncate.js +205 -0
- package/build/main/lib/agent-core/index.d.ts +19 -0
- package/build/main/lib/agent-core/index.js +25 -0
- package/build/main/lib/agent-core/package.json +3 -0
- package/build/main/lib/agent-core/proxy.d.ts +68 -0
- package/build/main/lib/agent-core/proxy.js +278 -0
- package/build/main/lib/agent-core/types.d.ts +385 -0
- package/build/main/lib/agent-core/types.js +2 -0
- package/build/main/lib/skills/constants.js +6 -4
- package/build/main/lib/skills/skillParser.js +2 -2
- package/build/main/lib/skills/utils.js +8 -10
- package/build/main/lib/tools/BraveWebSearchTool.js +4 -3
- package/build/main/lib/tools/PSArtifactTool.js +3 -3
- package/build/main/lib/tools/PSClarifyTool.js +3 -2
- package/build/main/lib/tools/PSCommandLineTool.js +8 -7
- package/build/main/lib/tools/PSMemoryTool.js +9 -7
- package/build/main/lib/tools/PSReadFileTool.js +3 -3
- package/build/main/lib/tools/PSSkillTool.js +6 -4
- package/build/main/lib/tools/PSSubAgentTool.js +4 -5
- package/build/main/lib/tools/PSWriteFileTool.js +3 -3
- package/build/main/lib/tools/TodoTool.js +8 -4
- package/build/main/lib/utils/helpers.js +2 -13
- package/build/module/lib/PSAI.d.ts +6 -0
- package/build/module/lib/PSAI.js +112 -85
- package/build/module/lib/PSAgentConfig.d.ts +3 -0
- package/build/module/lib/agent-core/agent-loop.d.ts +23 -0
- package/build/module/lib/agent-core/agent-loop.js +479 -0
- package/build/module/lib/agent-core/agent.d.ts +124 -0
- package/build/module/lib/agent-core/agent.js +402 -0
- package/build/module/lib/agent-core/harness/agent-harness.d.ts +84 -0
- package/build/module/lib/agent-core/harness/agent-harness.js +728 -0
- package/build/module/lib/agent-core/harness/compaction/branch-summarization.d.ts +87 -0
- package/build/module/lib/agent-core/harness/compaction/branch-summarization.js +243 -0
- package/build/module/lib/agent-core/harness/compaction/compaction.d.ts +121 -0
- package/build/module/lib/agent-core/harness/compaction/compaction.js +616 -0
- package/build/module/lib/agent-core/harness/compaction/utils.d.ts +37 -0
- package/build/module/lib/agent-core/harness/compaction/utils.js +153 -0
- package/build/module/lib/agent-core/harness/env/nodejs.d.ts +43 -0
- package/build/module/lib/agent-core/harness/env/nodejs.js +348 -0
- package/build/module/lib/agent-core/harness/execution-env.d.ts +3 -0
- package/build/module/lib/agent-core/harness/execution-env.js +3 -0
- package/build/module/lib/agent-core/harness/messages.d.ts +50 -0
- package/build/module/lib/agent-core/harness/messages.js +102 -0
- package/build/module/lib/agent-core/harness/prompt-templates.d.ts +44 -0
- package/build/module/lib/agent-core/harness/prompt-templates.js +200 -0
- package/build/module/lib/agent-core/harness/session/repo/jsonl.d.ts +19 -0
- package/build/module/lib/agent-core/harness/session/repo/jsonl.js +92 -0
- package/build/module/lib/agent-core/harness/session/repo/memory.d.ts +17 -0
- package/build/module/lib/agent-core/harness/session/repo/memory.js +42 -0
- package/build/module/lib/agent-core/harness/session/repo/shared.d.ts +9 -0
- package/build/module/lib/agent-core/harness/session/repo/shared.js +31 -0
- package/build/module/lib/agent-core/harness/session/session.d.ts +31 -0
- package/build/module/lib/agent-core/harness/session/session.js +196 -0
- package/build/module/lib/agent-core/harness/session/storage/jsonl.d.ts +29 -0
- package/build/module/lib/agent-core/harness/session/storage/jsonl.js +170 -0
- package/build/module/lib/agent-core/harness/session/storage/memory.d.ts +25 -0
- package/build/module/lib/agent-core/harness/session/storage/memory.js +90 -0
- package/build/module/lib/agent-core/harness/skills.d.ts +40 -0
- package/build/module/lib/agent-core/harness/skills.js +259 -0
- package/build/module/lib/agent-core/harness/system-prompt.d.ts +2 -0
- package/build/module/lib/agent-core/harness/system-prompt.js +30 -0
- package/build/module/lib/agent-core/harness/types.d.ts +524 -0
- package/build/module/lib/agent-core/harness/types.js +16 -0
- package/build/module/lib/agent-core/harness/utils/shell-output.d.ts +13 -0
- package/build/module/lib/agent-core/harness/utils/shell-output.js +97 -0
- package/build/module/lib/agent-core/harness/utils/truncate.d.ts +69 -0
- package/build/module/lib/agent-core/harness/utils/truncate.js +205 -0
- package/build/module/lib/agent-core/index.d.ts +19 -0
- package/build/module/lib/agent-core/index.js +25 -0
- package/build/module/lib/agent-core/proxy.d.ts +68 -0
- package/build/module/lib/agent-core/proxy.js +278 -0
- package/build/module/lib/agent-core/types.d.ts +385 -0
- package/build/module/lib/agent-core/types.js +2 -0
- package/build/module/lib/tools/PSSkillTool.js +1 -1
- package/package.json +20 -3
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { ImageContent, TextContent } from "@earendil-works/pi-ai";
|
|
2
|
+
import type { AgentMessage } from "../../types.js";
|
|
3
|
+
import type { SessionContext, SessionMetadata, SessionStorage, SessionTreeEntry } from "../types.js";
|
|
4
|
+
export declare function buildSessionContext(pathEntries: SessionTreeEntry[]): SessionContext;
|
|
5
|
+
export declare class Session<TMetadata extends SessionMetadata = SessionMetadata> {
|
|
6
|
+
private storage;
|
|
7
|
+
constructor(storage: SessionStorage<TMetadata>);
|
|
8
|
+
getMetadata(): Promise<TMetadata>;
|
|
9
|
+
getStorage(): SessionStorage<TMetadata>;
|
|
10
|
+
getLeafId(): Promise<string | null>;
|
|
11
|
+
getEntry(id: string): Promise<SessionTreeEntry | undefined>;
|
|
12
|
+
getEntries(): Promise<SessionTreeEntry[]>;
|
|
13
|
+
getBranch(fromId?: string): Promise<SessionTreeEntry[]>;
|
|
14
|
+
buildContext(): Promise<SessionContext>;
|
|
15
|
+
getLabel(id: string): Promise<string | undefined>;
|
|
16
|
+
getSessionName(): Promise<string | undefined>;
|
|
17
|
+
private appendTypedEntry;
|
|
18
|
+
appendMessage(message: AgentMessage): Promise<string>;
|
|
19
|
+
appendThinkingLevelChange(thinkingLevel: string): Promise<string>;
|
|
20
|
+
appendModelChange(provider: string, modelId: string): Promise<string>;
|
|
21
|
+
appendCompaction<T = unknown>(summary: string, firstKeptEntryId: string, tokensBefore: number, details?: T, fromHook?: boolean): Promise<string>;
|
|
22
|
+
appendCustomEntry(customType: string, data?: unknown): Promise<string>;
|
|
23
|
+
appendCustomMessageEntry<T = unknown>(customType: string, content: string | (TextContent | ImageContent)[], display: boolean, details?: T): Promise<string>;
|
|
24
|
+
appendLabel(targetId: string, label: string | undefined): Promise<string>;
|
|
25
|
+
appendSessionName(name: string): Promise<string>;
|
|
26
|
+
moveTo(entryId: string | null, summary?: {
|
|
27
|
+
summary: string;
|
|
28
|
+
details?: unknown;
|
|
29
|
+
fromHook?: boolean;
|
|
30
|
+
}): Promise<string | undefined>;
|
|
31
|
+
}
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import { createBranchSummaryMessage, createCompactionSummaryMessage, createCustomMessage } from "../messages.js";
|
|
2
|
+
export function buildSessionContext(pathEntries) {
|
|
3
|
+
let thinkingLevel = "off";
|
|
4
|
+
let model = null;
|
|
5
|
+
let compaction = null;
|
|
6
|
+
for (const entry of pathEntries) {
|
|
7
|
+
if (entry.type === "thinking_level_change") {
|
|
8
|
+
thinkingLevel = entry.thinkingLevel;
|
|
9
|
+
}
|
|
10
|
+
else if (entry.type === "model_change") {
|
|
11
|
+
model = { provider: entry.provider, modelId: entry.modelId };
|
|
12
|
+
}
|
|
13
|
+
else if (entry.type === "message" && entry.message.role === "assistant") {
|
|
14
|
+
model = { provider: entry.message.provider, modelId: entry.message.model };
|
|
15
|
+
}
|
|
16
|
+
else if (entry.type === "compaction") {
|
|
17
|
+
compaction = entry;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
const messages = [];
|
|
21
|
+
const appendMessage = (entry) => {
|
|
22
|
+
if (entry.type === "message") {
|
|
23
|
+
messages.push(entry.message);
|
|
24
|
+
}
|
|
25
|
+
else if (entry.type === "custom_message") {
|
|
26
|
+
messages.push(createCustomMessage(entry.customType, entry.content, entry.display, entry.details, entry.timestamp));
|
|
27
|
+
}
|
|
28
|
+
else if (entry.type === "branch_summary" && entry.summary) {
|
|
29
|
+
messages.push(createBranchSummaryMessage(entry.summary, entry.fromId, entry.timestamp));
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
if (compaction) {
|
|
33
|
+
messages.push(createCompactionSummaryMessage(compaction.summary, compaction.tokensBefore, compaction.timestamp));
|
|
34
|
+
const compactionIdx = pathEntries.findIndex((e) => e.type === "compaction" && e.id === compaction.id);
|
|
35
|
+
let foundFirstKept = false;
|
|
36
|
+
for (let i = 0; i < compactionIdx; i++) {
|
|
37
|
+
const entry = pathEntries[i];
|
|
38
|
+
if (entry.id === compaction.firstKeptEntryId)
|
|
39
|
+
foundFirstKept = true;
|
|
40
|
+
if (foundFirstKept)
|
|
41
|
+
appendMessage(entry);
|
|
42
|
+
}
|
|
43
|
+
for (let i = compactionIdx + 1; i < pathEntries.length; i++) {
|
|
44
|
+
appendMessage(pathEntries[i]);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
for (const entry of pathEntries) {
|
|
49
|
+
appendMessage(entry);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return { messages, thinkingLevel, model };
|
|
53
|
+
}
|
|
54
|
+
export class Session {
|
|
55
|
+
storage;
|
|
56
|
+
constructor(storage) {
|
|
57
|
+
this.storage = storage;
|
|
58
|
+
}
|
|
59
|
+
getMetadata() {
|
|
60
|
+
return this.storage.getMetadata();
|
|
61
|
+
}
|
|
62
|
+
getStorage() {
|
|
63
|
+
return this.storage;
|
|
64
|
+
}
|
|
65
|
+
getLeafId() {
|
|
66
|
+
return this.storage.getLeafId();
|
|
67
|
+
}
|
|
68
|
+
getEntry(id) {
|
|
69
|
+
return this.storage.getEntry(id);
|
|
70
|
+
}
|
|
71
|
+
getEntries() {
|
|
72
|
+
return this.storage.getEntries();
|
|
73
|
+
}
|
|
74
|
+
async getBranch(fromId) {
|
|
75
|
+
const leafId = fromId ?? (await this.storage.getLeafId());
|
|
76
|
+
return this.storage.getPathToRoot(leafId);
|
|
77
|
+
}
|
|
78
|
+
async buildContext() {
|
|
79
|
+
return buildSessionContext(await this.getBranch());
|
|
80
|
+
}
|
|
81
|
+
getLabel(id) {
|
|
82
|
+
return this.storage.getLabel(id);
|
|
83
|
+
}
|
|
84
|
+
async getSessionName() {
|
|
85
|
+
const entries = await this.storage.findEntries("session_info");
|
|
86
|
+
return entries[entries.length - 1]?.name?.trim() || undefined;
|
|
87
|
+
}
|
|
88
|
+
async appendTypedEntry(entry) {
|
|
89
|
+
await this.storage.appendEntry(entry);
|
|
90
|
+
return entry.id;
|
|
91
|
+
}
|
|
92
|
+
async appendMessage(message) {
|
|
93
|
+
return this.appendTypedEntry({
|
|
94
|
+
type: "message",
|
|
95
|
+
id: await this.storage.createEntryId(),
|
|
96
|
+
parentId: await this.storage.getLeafId(),
|
|
97
|
+
timestamp: new Date().toISOString(),
|
|
98
|
+
message,
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
async appendThinkingLevelChange(thinkingLevel) {
|
|
102
|
+
return this.appendTypedEntry({
|
|
103
|
+
type: "thinking_level_change",
|
|
104
|
+
id: await this.storage.createEntryId(),
|
|
105
|
+
parentId: await this.storage.getLeafId(),
|
|
106
|
+
timestamp: new Date().toISOString(),
|
|
107
|
+
thinkingLevel,
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
async appendModelChange(provider, modelId) {
|
|
111
|
+
return this.appendTypedEntry({
|
|
112
|
+
type: "model_change",
|
|
113
|
+
id: await this.storage.createEntryId(),
|
|
114
|
+
parentId: await this.storage.getLeafId(),
|
|
115
|
+
timestamp: new Date().toISOString(),
|
|
116
|
+
provider,
|
|
117
|
+
modelId,
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
async appendCompaction(summary, firstKeptEntryId, tokensBefore, details, fromHook) {
|
|
121
|
+
return this.appendTypedEntry({
|
|
122
|
+
type: "compaction",
|
|
123
|
+
id: await this.storage.createEntryId(),
|
|
124
|
+
parentId: await this.storage.getLeafId(),
|
|
125
|
+
timestamp: new Date().toISOString(),
|
|
126
|
+
summary,
|
|
127
|
+
firstKeptEntryId,
|
|
128
|
+
tokensBefore,
|
|
129
|
+
details,
|
|
130
|
+
fromHook,
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
async appendCustomEntry(customType, data) {
|
|
134
|
+
return this.appendTypedEntry({
|
|
135
|
+
type: "custom",
|
|
136
|
+
id: await this.storage.createEntryId(),
|
|
137
|
+
parentId: await this.storage.getLeafId(),
|
|
138
|
+
timestamp: new Date().toISOString(),
|
|
139
|
+
customType,
|
|
140
|
+
data,
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
async appendCustomMessageEntry(customType, content, display, details) {
|
|
144
|
+
return this.appendTypedEntry({
|
|
145
|
+
type: "custom_message",
|
|
146
|
+
id: await this.storage.createEntryId(),
|
|
147
|
+
parentId: await this.storage.getLeafId(),
|
|
148
|
+
timestamp: new Date().toISOString(),
|
|
149
|
+
customType,
|
|
150
|
+
content,
|
|
151
|
+
display,
|
|
152
|
+
details,
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
async appendLabel(targetId, label) {
|
|
156
|
+
if (!(await this.storage.getEntry(targetId))) {
|
|
157
|
+
throw new Error(`Entry ${targetId} not found`);
|
|
158
|
+
}
|
|
159
|
+
return this.appendTypedEntry({
|
|
160
|
+
type: "label",
|
|
161
|
+
id: await this.storage.createEntryId(),
|
|
162
|
+
parentId: await this.storage.getLeafId(),
|
|
163
|
+
timestamp: new Date().toISOString(),
|
|
164
|
+
targetId,
|
|
165
|
+
label,
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
async appendSessionName(name) {
|
|
169
|
+
return this.appendTypedEntry({
|
|
170
|
+
type: "session_info",
|
|
171
|
+
id: await this.storage.createEntryId(),
|
|
172
|
+
parentId: await this.storage.getLeafId(),
|
|
173
|
+
timestamp: new Date().toISOString(),
|
|
174
|
+
name: name.trim(),
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
async moveTo(entryId, summary) {
|
|
178
|
+
if (entryId !== null && !(await this.storage.getEntry(entryId))) {
|
|
179
|
+
throw new Error(`Entry ${entryId} not found`);
|
|
180
|
+
}
|
|
181
|
+
await this.storage.setLeafId(entryId);
|
|
182
|
+
if (!summary)
|
|
183
|
+
return undefined;
|
|
184
|
+
return this.appendTypedEntry({
|
|
185
|
+
type: "branch_summary",
|
|
186
|
+
id: await this.storage.createEntryId(),
|
|
187
|
+
parentId: entryId,
|
|
188
|
+
timestamp: new Date().toISOString(),
|
|
189
|
+
fromId: entryId ?? "root",
|
|
190
|
+
summary: summary.summary,
|
|
191
|
+
details: summary.details,
|
|
192
|
+
fromHook: summary.fromHook,
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2Vzc2lvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3NyYy9saWIvYWdlbnQtY29yZS9oYXJuZXNzL3Nlc3Npb24vc2Vzc2lvbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFFQSxPQUFPLEVBQUUsMEJBQTBCLEVBQUUsOEJBQThCLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQWlCakgsTUFBTSxVQUFVLG1CQUFtQixDQUFDLFdBQStCO0lBQ2xFLElBQUksYUFBYSxHQUFHLEtBQUssQ0FBQztJQUMxQixJQUFJLEtBQUssR0FBaUQsSUFBSSxDQUFDO0lBQy9ELElBQUksVUFBVSxHQUEyQixJQUFJLENBQUM7SUFFOUMsS0FBSyxNQUFNLEtBQUssSUFBSSxXQUFXLEVBQUUsQ0FBQztRQUNqQyxJQUFJLEtBQUssQ0FBQyxJQUFJLEtBQUssdUJBQXVCLEVBQUUsQ0FBQztZQUM1QyxhQUFhLEdBQUcsS0FBSyxDQUFDLGFBQWEsQ0FBQztRQUNyQyxDQUFDO2FBQU0sSUFBSSxLQUFLLENBQUMsSUFBSSxLQUFLLGNBQWMsRUFBRSxDQUFDO1lBQzFDLEtBQUssR0FBRyxFQUFFLFFBQVEsRUFBRSxLQUFLLENBQUMsUUFBUSxFQUFFLE9BQU8sRUFBRSxLQUFLLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDOUQsQ0FBQzthQUFNLElBQUksS0FBSyxDQUFDLElBQUksS0FBSyxTQUFTLElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxJQUFJLEtBQUssV0FBVyxFQUFFLENBQUM7WUFDM0UsS0FBSyxHQUFHLEVBQUUsUUFBUSxFQUFFLEtBQUssQ0FBQyxPQUFPLENBQUMsUUFBUSxFQUFFLE9BQU8sRUFBRSxLQUFLLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQzVFLENBQUM7YUFBTSxJQUFJLEtBQUssQ0FBQyxJQUFJLEtBQUssWUFBWSxFQUFFLENBQUM7WUFDeEMsVUFBVSxHQUFHLEtBQUssQ0FBQztR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
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { JsonlSessionMetadata, SessionStorage, SessionTreeEntry } from "../../types.js";
|
|
2
|
+
export declare function loadJsonlSessionMetadata(filePath: string): Promise<JsonlSessionMetadata>;
|
|
3
|
+
export declare class JsonlSessionStorage implements SessionStorage<JsonlSessionMetadata> {
|
|
4
|
+
private readonly filePath;
|
|
5
|
+
private readonly metadata;
|
|
6
|
+
private entries;
|
|
7
|
+
private byId;
|
|
8
|
+
private labelsById;
|
|
9
|
+
private currentLeafId;
|
|
10
|
+
private constructor();
|
|
11
|
+
static open(filePath: string): Promise<JsonlSessionStorage>;
|
|
12
|
+
static create(filePath: string, options: {
|
|
13
|
+
cwd: string;
|
|
14
|
+
sessionId: string;
|
|
15
|
+
parentSessionPath?: string;
|
|
16
|
+
}): Promise<JsonlSessionStorage>;
|
|
17
|
+
getMetadata(): Promise<JsonlSessionMetadata>;
|
|
18
|
+
getLeafId(): Promise<string | null>;
|
|
19
|
+
setLeafId(leafId: string | null): Promise<void>;
|
|
20
|
+
createEntryId(): Promise<string>;
|
|
21
|
+
appendEntry(entry: SessionTreeEntry): Promise<void>;
|
|
22
|
+
getEntry(id: string): Promise<SessionTreeEntry | undefined>;
|
|
23
|
+
findEntries<TType extends SessionTreeEntry["type"]>(type: TType): Promise<Array<Extract<SessionTreeEntry, {
|
|
24
|
+
type: TType;
|
|
25
|
+
}>>>;
|
|
26
|
+
getLabel(id: string): Promise<string | undefined>;
|
|
27
|
+
getPathToRoot(leafId: string | null): Promise<SessionTreeEntry[]>;
|
|
28
|
+
getEntries(): Promise<SessionTreeEntry[]>;
|
|
29
|
+
}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { createReadStream } from "node:fs";
|
|
3
|
+
import { appendFile, mkdir, readFile, writeFile } from "node:fs/promises";
|
|
4
|
+
import { dirname, resolve } from "node:path";
|
|
5
|
+
import { createInterface } from "node:readline";
|
|
6
|
+
function updateLabelCache(labelsById, entry) {
|
|
7
|
+
if (entry.type !== "label")
|
|
8
|
+
return;
|
|
9
|
+
const label = entry.label?.trim();
|
|
10
|
+
if (label) {
|
|
11
|
+
labelsById.set(entry.targetId, label);
|
|
12
|
+
}
|
|
13
|
+
else {
|
|
14
|
+
labelsById.delete(entry.targetId);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
function buildLabelsById(entries) {
|
|
18
|
+
const labelsById = new Map();
|
|
19
|
+
for (const entry of entries) {
|
|
20
|
+
updateLabelCache(labelsById, entry);
|
|
21
|
+
}
|
|
22
|
+
return labelsById;
|
|
23
|
+
}
|
|
24
|
+
function generateEntryId(byId) {
|
|
25
|
+
for (let i = 0; i < 100; i++) {
|
|
26
|
+
const id = randomUUID().slice(0, 8);
|
|
27
|
+
if (!byId.has(id))
|
|
28
|
+
return id;
|
|
29
|
+
}
|
|
30
|
+
return randomUUID();
|
|
31
|
+
}
|
|
32
|
+
function headerToSessionMetadata(header, path) {
|
|
33
|
+
return {
|
|
34
|
+
id: header.id,
|
|
35
|
+
createdAt: header.timestamp,
|
|
36
|
+
cwd: header.cwd,
|
|
37
|
+
path,
|
|
38
|
+
parentSessionPath: header.parentSession,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
export async function loadJsonlSessionMetadata(filePath) {
|
|
42
|
+
const stream = createReadStream(filePath, { encoding: "utf8" });
|
|
43
|
+
const lines = createInterface({ input: stream, crlfDelay: Infinity });
|
|
44
|
+
try {
|
|
45
|
+
for await (const line of lines) {
|
|
46
|
+
if (!line.trim())
|
|
47
|
+
break;
|
|
48
|
+
try {
|
|
49
|
+
const header = JSON.parse(line);
|
|
50
|
+
return headerToSessionMetadata(header, resolve(filePath));
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
throw new Error(`Invalid JSONL session file ${filePath}: first line is not a valid session header`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
throw new Error(`Invalid JSONL session file ${filePath}: missing session header`);
|
|
57
|
+
}
|
|
58
|
+
finally {
|
|
59
|
+
lines.close();
|
|
60
|
+
stream.destroy();
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
async function loadJsonlStorage(filePath) {
|
|
64
|
+
const content = await readFile(filePath, "utf8");
|
|
65
|
+
const lines = content.split("\n").filter((line) => line.trim());
|
|
66
|
+
if (lines.length === 0) {
|
|
67
|
+
throw new Error(`Invalid JSONL session file ${filePath}: missing session header`);
|
|
68
|
+
}
|
|
69
|
+
let header;
|
|
70
|
+
try {
|
|
71
|
+
header = JSON.parse(lines[0]);
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
throw new Error(`Invalid JSONL session file ${filePath}: first line is not a valid session header`);
|
|
75
|
+
}
|
|
76
|
+
const entries = [];
|
|
77
|
+
let leafId = null;
|
|
78
|
+
for (const line of lines.slice(1)) {
|
|
79
|
+
try {
|
|
80
|
+
const entry = JSON.parse(line);
|
|
81
|
+
entries.push(entry);
|
|
82
|
+
leafId = entry.id;
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
// ignore malformed entry lines
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return { header, entries, leafId };
|
|
89
|
+
}
|
|
90
|
+
export class JsonlSessionStorage {
|
|
91
|
+
filePath;
|
|
92
|
+
metadata;
|
|
93
|
+
entries;
|
|
94
|
+
byId;
|
|
95
|
+
labelsById;
|
|
96
|
+
currentLeafId;
|
|
97
|
+
constructor(filePath, header, entries, leafId) {
|
|
98
|
+
this.filePath = resolve(filePath);
|
|
99
|
+
this.metadata = headerToSessionMetadata(header, this.filePath);
|
|
100
|
+
this.entries = entries;
|
|
101
|
+
this.byId = new Map(entries.map((entry) => [entry.id, entry]));
|
|
102
|
+
this.labelsById = buildLabelsById(entries);
|
|
103
|
+
this.currentLeafId = leafId;
|
|
104
|
+
}
|
|
105
|
+
static async open(filePath) {
|
|
106
|
+
const resolvedPath = resolve(filePath);
|
|
107
|
+
const loaded = await loadJsonlStorage(resolvedPath);
|
|
108
|
+
return new JsonlSessionStorage(resolvedPath, loaded.header, loaded.entries, loaded.leafId);
|
|
109
|
+
}
|
|
110
|
+
static async create(filePath, options) {
|
|
111
|
+
const resolvedPath = resolve(filePath);
|
|
112
|
+
const header = {
|
|
113
|
+
type: "session",
|
|
114
|
+
version: 3,
|
|
115
|
+
id: options.sessionId,
|
|
116
|
+
timestamp: new Date().toISOString(),
|
|
117
|
+
cwd: options.cwd,
|
|
118
|
+
parentSession: options.parentSessionPath,
|
|
119
|
+
};
|
|
120
|
+
await mkdir(dirname(resolvedPath), { recursive: true });
|
|
121
|
+
await writeFile(resolvedPath, `${JSON.stringify(header)}\n`);
|
|
122
|
+
return new JsonlSessionStorage(resolvedPath, header, [], null);
|
|
123
|
+
}
|
|
124
|
+
async getMetadata() {
|
|
125
|
+
return this.metadata;
|
|
126
|
+
}
|
|
127
|
+
async getLeafId() {
|
|
128
|
+
return this.currentLeafId;
|
|
129
|
+
}
|
|
130
|
+
async setLeafId(leafId) {
|
|
131
|
+
if (leafId !== null && !this.byId.has(leafId)) {
|
|
132
|
+
throw new Error(`Entry ${leafId} not found`);
|
|
133
|
+
}
|
|
134
|
+
this.currentLeafId = leafId;
|
|
135
|
+
}
|
|
136
|
+
async createEntryId() {
|
|
137
|
+
return generateEntryId(this.byId);
|
|
138
|
+
}
|
|
139
|
+
async appendEntry(entry) {
|
|
140
|
+
await appendFile(this.filePath, `${JSON.stringify(entry)}\n`);
|
|
141
|
+
this.entries.push(entry);
|
|
142
|
+
this.byId.set(entry.id, entry);
|
|
143
|
+
updateLabelCache(this.labelsById, entry);
|
|
144
|
+
this.currentLeafId = entry.id;
|
|
145
|
+
}
|
|
146
|
+
async getEntry(id) {
|
|
147
|
+
return this.byId.get(id);
|
|
148
|
+
}
|
|
149
|
+
async findEntries(type) {
|
|
150
|
+
return this.entries.filter((entry) => entry.type === type);
|
|
151
|
+
}
|
|
152
|
+
async getLabel(id) {
|
|
153
|
+
return this.labelsById.get(id);
|
|
154
|
+
}
|
|
155
|
+
async getPathToRoot(leafId) {
|
|
156
|
+
if (leafId === null)
|
|
157
|
+
return [];
|
|
158
|
+
const path = [];
|
|
159
|
+
let current = this.byId.get(leafId);
|
|
160
|
+
while (current) {
|
|
161
|
+
path.unshift(current);
|
|
162
|
+
current = current.parentId ? this.byId.get(current.parentId) : undefined;
|
|
163
|
+
}
|
|
164
|
+
return path;
|
|
165
|
+
}
|
|
166
|
+
async getEntries() {
|
|
167
|
+
return [...this.entries];
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoianNvbmwuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvbGliL2FnZW50LWNvcmUvaGFybmVzcy9zZXNzaW9uL3N0b3JhZ2UvanNvbmwudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUN6QyxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxTQUFTLENBQUM7QUFDM0MsT0FBTyxFQUFFLFVBQVUsRUFBRSxLQUFLLEVBQUUsUUFBUSxFQUFFLFNBQVMsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQzFFLE9BQU8sRUFBRSxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQzdDLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFZaEQsU0FBUyxnQkFBZ0IsQ0FBQyxVQUErQixFQUFFLEtBQXVCO0lBQ2pGLElBQUksS0FBSyxDQUFDLElBQUksS0FBSyxPQUFPO1FBQUUsT0FBTztJQUNuQyxNQUFNLEtBQUssR0FBRyxLQUFLLENBQUMsS0FBSyxFQUFFLElBQUksRUFBRSxDQUFDO0lBQ2xDLElBQUksS0FBSyxFQUFFLENBQUM7UUFDWCxVQUFVLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxRQUFRLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDdkMsQ0FBQztTQUFNLENBQUM7UUFDUCxVQUFVLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUNuQyxDQUFDO0FBQ0YsQ0FBQztBQUVELFNBQVMsZUFBZSxDQUFDLE9BQTJCO0lBQ25ELE1BQU0sVUFBVSxHQUFHLElBQUksR0FBRyxFQUFrQixDQUFDO0lBQzdDLEtBQUssTUFBTSxLQUFLLElBQUksT0FBTyxFQUFFLENBQUM7UUFDN0IsZ0JBQWdCLENBQUMsVUFBVSxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQ3JDLENBQUM7SUFDRCxPQUFPLFVBQVUsQ0FBQztBQUNuQixDQUFDO0FBRUQsU0FBUyxlQUFlLENBQUMsSUFBa0M7SUFDMUQsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEdBQUcsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO1FBQzlCLE1BQU0sRUFBRSxHQUFHLFVBQVUsRUFBRSxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDcEMsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQUUsT0FBTyxFQUFFLENBQUM7SUFDOUIsQ0FBQztJQUNELE9BQU8sVUFBVSxFQUFFLENBQUM7QUFDckIsQ0FBQztBQUVELFNBQVMsdUJBQXVCLENBQUMsTUFBcUIsRUFBRSxJQUFZO0lBQ25FLE9BQU87UUFDTixFQUFFLEVBQUUsTUFBTSxDQUFDLEVBQUU7UUFDYixTQUFTLEVBQUUsTUFBTSxDQUFDLFNBQVM7UUFDM0IsR0FBRyxFQUFFLE1BQU0sQ0FBQyxHQUFHO1FBQ2YsSUFBSTtRQUNKLGlCQUFpQixFQUFFLE1BQU0sQ0FBQyxhQUFhO0tBQ3ZDLENBQUM7QUFDSCxDQUFDO0FBRUQsTUFBTSxDQUFDLEtBQUssVUFBVSx3QkFBd0IsQ0FBQyxRQUFnQjtJQUM5RCxNQUFNLE1BQU0sR0FBRyxnQkFBZ0IsQ0FBQyxRQUFRLEVBQUUsRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFLENBQUMsQ0FBQztJQUNoRSxNQUFNLEtBQUssR0FBRyxlQUFlLENBQUMsRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLFNBQVMsRUFBRSxRQUFRLEVBQUUsQ0FBQyxDQUFDO0lBQ3RFLElBQUksQ0FBQztRQUNKLElBQUksS0FBSyxFQUFFLE1BQU0sSUFBSSxJQUFJLEtBQUssRUFBRSxDQUFDO1lBQ2hDLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFO2dCQUFFLE1BQU07WUFDeEIsSUFBSSxDQUFDO2dCQUNKLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFrQixDQUFDO2dCQUNqRCxPQUFPLHVCQUF1QixDQUFDLE1BQU0sRUFBRSxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQztZQUMzRCxDQUFDO1lBQUMsTUFBTSxDQUFDO2dCQUNSLE1BQU0sSUFBSSxLQUFLLENBQUMsOEJBQThCLFFBQVEsNENBQTRDLENBQUMsQ0FBQztZQUNyRyxDQUFDO1FBQ0YsQ0FBQztRQUNELE1BQU0sSUFBSSxLQUFLLENBQUMsOEJBQThCLFFBQVEsMEJBQTBCLENBQUMsQ0FBQztJQUNuRixDQUFDO1lBQVMsQ0FBQztRQUNWLEtBQUssQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUNkLE1BQU0sQ0FBQyxPQUFPLEVBQUUsQ0FBQztJQUNsQixDQUFDO0FBQ0YsQ0FBQztBQUVELEtBQUssVUFBVSxnQkFBZ0IsQ0FBQyxRQUFnQjtJQUsvQyxNQUFNLE9BQU8sR0FBRyxNQUFNLFFBQVEsQ0FBQyxRQUFRLEVBQUUsTUFBTSxDQUFDLENBQUM7SUFDakQsTUFBTSxLQUFLLEdBQUcsT0FBTyxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDO0lBQ2hFLElBQUksS0FBSyxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUUsQ0FBQztRQUN4QixNQUFNLElBQUksS0FBSyxDQUFDLDhCQUE4QixRQUFRLDBCQUEwQixDQUFDLENBQUM7SUFDbkYsQ0FBQztJQUVELElBQUksTUFBcUIsQ0FBQztJQUMxQixJQUFJLENBQUM7UUFDSixNQUFNLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFFLENBQWtCLENBQUM7SUFDakQsQ0FBQztJQUFDLE1BQU0sQ0FBQztRQUNSLE1BQU0sSUFBSSxLQUFLLENBQUMsOEJBQThCLFFBQVEsNENBQTRDLENBQUMsQ0FBQztJQUNyRyxDQUFDO0lBRUQsTUFBTSxPQUFPLEdBQXVCLEVBQUUsQ0FBQztJQUN2QyxJQUFJLE1BQU0sR0FBa0IsSUFBSSxDQUFDO0lBQ2pDLEtBQUssTUFBTSxJQUFJLElBQUksS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1FBQ25DLElBQUksQ0FBQztZQUNKLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFxQixDQUFDO1lBQ25ELE9BQU8sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDcEIsTUFBTSxHQUFHLEtBQUssQ0FBQyxFQUFFLENBQUM7UUFDbkIsQ0FBQztRQUFDLE1BQU0sQ0FBQztZQUNSLCtCQUErQjtRQUNoQyxDQUFDO0lBQ0YsQ0FBQztJQUNELE9BQU8sRUFBRSxNQUFNLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRSxDQUFDO0FBQ3BDLENBQUM7QUFFRCxNQUFNLE9BQU8sbUJBQW1CO0lBQ2QsUUFBUSxDQUFTO0lBQ2pCLFFBQVEsQ0FBdUI7SUFDeEMsT0FBTyxDQUFxQjtJQUM1QixJQUFJLENBQWdDO0lBQ3BDLFVBQVUsQ0FBc0I7SUFDaEMsYUFBYSxDQUFnQjtJQUVyQyxZQUFvQixRQUFnQixFQUFFLE1BQXFCLEVBQUUsT0FBMkIsRUFBRSxNQUFxQjtRQUM5RyxJQUFJLENBQUMsUUFBUSxHQUFHLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUNsQyxJQUFJLENBQUMsUUFBUSxHQUFHLHVCQUF1QixDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDL0QsSUFBSSxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUM7UUFDdkIsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLEdBQUcsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDLEtBQUssQ0FBQyxFQUFFLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQy9ELElBQUksQ0FBQyxVQUFVLEdBQUcsZUFBZSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQzNDLElBQUksQ0FBQyxhQUFhLEdBQUcsTUFBTSxDQUFDO0lBQzdCLENBQUM7SUFFRCxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxRQUFnQjtRQUNqQyxNQUFNLFlBQVksR0FBRyxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDdkMsTUFBTSxNQUFNLEdBQUcsTUFBTSxnQkFBZ0IsQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUNwRCxPQUFPLElBQUksbUJBQW1CLENBQUMsWUFBWSxFQUFFLE1BQU0sQ0FBQyxNQUFNLEVBQUUsTUFBTSxDQUFDLE9BQU8sRUFBRSxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDNUYsQ0FBQztJQUVELE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUNsQixRQUFnQixFQUNoQixPQUlDO1FBRUQsTUFBTSxZQUFZLEdBQUcsT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ3ZDLE1BQU0sTUFBTSxHQUFrQjtZQUM3QixJQUFJLEVBQUUsU0FBUztZQUNmLE9BQU8sRUFBRSxDQUFDO1lBQ1YsRUFBRSxFQUFFLE9BQU8sQ0FBQyxTQUFTO1lBQ3JCLFNBQVMsRUFBRSxJQUFJLElBQUksRUFBRSxDQUFDLFdBQVcsRUFBRTtZQUNuQyxHQUFHLEVBQUUsT0FBTyxDQUFDLEdBQUc7WUFDaEIsYUFBYSxFQUFFLE9BQU8sQ0FBQyxpQkFBaUI7U0FDeEMsQ0FBQztRQUNGLE1BQU0sS0FBSyxDQUFDLE9BQU8sQ0FBQyxZQUFZLENBQUMsRUFBRSxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO1FBQ3hELE1BQU0sU0FBUyxDQUFDLFlBQVksRUFBRSxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQzdELE9BQU8sSUFBSSxtQkFBbUIsQ0FBQyxZQUFZLEVBQUUsTUFBTSxFQUFFLEVBQUUsRUFBRSxJQUFJLENBQUMsQ0FBQztJQUNoRSxDQUFDO0lBRUQsS0FBSyxDQUFDLFdBQVc7UUFDaEIsT0FBTyxJQUFJLENBQUMsUUFBUSxDQUFDO0lBQ3RCLENBQUM7SUFFRCxLQUFLLENBQUMsU0FBUztRQUNkLE9BQU8sSUFBSSxDQUFDLGFBQWEsQ0FBQztJQUMzQixDQUFDO0lBRUQsS0FBSyxDQUFDLFNBQVMsQ0FBQyxNQUFxQjtRQUNwQyxJQUFJLE1BQU0sS0FBSyxJQUFJLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDO1lBQy9DLE1BQU0sSUFBSSxLQUFLLENBQUMsU0FBUyxNQUFNLFlBQVksQ0FBQyxDQUFDO1FBQzlDLENBQUM7UUFDRCxJQUFJLENBQUMsYUFBYSxHQUFHLE1BQU0sQ0FBQztJQUM3QixDQUFDO0lBRUQsS0FBSyxDQUFDLGFBQWE7UUFDbEIsT0FBTyxlQUFlLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ25DLENBQUM7SUFFRCxLQUFLLENBQUMsV0FBVyxDQUFDLEtBQXVCO1FBQ3hDLE1BQU0sVUFBVSxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUM5RCxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUN6QixJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsRUFBRSxFQUFFLEtBQUssQ0FBQyxDQUFDO1FBQy9CLGdCQUFnQixDQUFDLElBQUksQ0FBQyxVQUFVLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDekMsSUFBSSxDQUFDLGFBQWEsR0FBRyxLQUFLLENBQUMsRUFBRSxDQUFDO0lBQy9CLENBQUM7SUFFRCxLQUFLLENBQUMsUUFBUSxDQUFDLEVBQVU7UUFDeEIsT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUMxQixDQUFDO0lBRUQsS0FBSyxDQUFDLFdBQVcsQ0FDaEIsSUFBVztRQUVYLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQyxLQUFLLEVBQXVELEVBQUUsQ0FBQyxLQUFLLENBQUMsSUFBSSxLQUFLLElBQUksQ0FBQyxDQUFDO0lBQ2pILENBQUM7SUFFRCxLQUFLLENBQUMsUUFBUSxDQUFDLEVBQVU7UUFDeEIsT0FBTyxJQUFJLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUNoQyxDQUFDO0lBRUQsS0FBSyxDQUFDLGFBQWEsQ0FBQyxNQUFxQjtRQUN4QyxJQUFJLE1BQU0sS0FBSyxJQUFJO1lBQUUsT0FBTyxFQUFFLENBQUM7UUFDL0IsTUFBTSxJQUFJLEdBQXVCLEVBQUUsQ0FBQztRQUNwQyxJQUFJLE9BQU8sR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUNwQyxPQUFPLE9BQU8sRUFBRSxDQUFDO1lBQ2hCLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDdEIsT0FBTyxHQUFHLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDO1FBQzFFLENBQUM7UUFDRCxPQUFPLElBQUksQ0FBQztJQUNiLENBQUM7SUFFRCxLQUFLLENBQUMsVUFBVTtRQUNmLE9BQU8sQ0FBQyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUMxQixDQUFDO0NBQ0QifQ==
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { SessionMetadata, SessionStorage, SessionTreeEntry } from "../../types.js";
|
|
2
|
+
export declare class InMemorySessionStorage implements SessionStorage {
|
|
3
|
+
private readonly metadata;
|
|
4
|
+
private entries;
|
|
5
|
+
private byId;
|
|
6
|
+
private labelsById;
|
|
7
|
+
private leafId;
|
|
8
|
+
constructor(options?: {
|
|
9
|
+
entries?: SessionTreeEntry[];
|
|
10
|
+
leafId?: string | null;
|
|
11
|
+
metadata?: SessionMetadata;
|
|
12
|
+
});
|
|
13
|
+
getMetadata(): Promise<SessionMetadata>;
|
|
14
|
+
getLeafId(): Promise<string | null>;
|
|
15
|
+
setLeafId(leafId: string | null): Promise<void>;
|
|
16
|
+
createEntryId(): Promise<string>;
|
|
17
|
+
appendEntry(entry: SessionTreeEntry): Promise<void>;
|
|
18
|
+
getEntry(id: string): Promise<SessionTreeEntry | undefined>;
|
|
19
|
+
findEntries<TType extends SessionTreeEntry["type"]>(type: TType): Promise<Array<Extract<SessionTreeEntry, {
|
|
20
|
+
type: TType;
|
|
21
|
+
}>>>;
|
|
22
|
+
getLabel(id: string): Promise<string | undefined>;
|
|
23
|
+
getPathToRoot(leafId: string | null): Promise<SessionTreeEntry[]>;
|
|
24
|
+
getEntries(): Promise<SessionTreeEntry[]>;
|
|
25
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { v7 as uuidv7 } from "uuid";
|
|
3
|
+
function updateLabelCache(labelsById, entry) {
|
|
4
|
+
if (entry.type !== "label")
|
|
5
|
+
return;
|
|
6
|
+
const label = entry.label?.trim();
|
|
7
|
+
if (label) {
|
|
8
|
+
labelsById.set(entry.targetId, label);
|
|
9
|
+
}
|
|
10
|
+
else {
|
|
11
|
+
labelsById.delete(entry.targetId);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
function buildLabelsById(entries) {
|
|
15
|
+
const labelsById = new Map();
|
|
16
|
+
for (const entry of entries) {
|
|
17
|
+
updateLabelCache(labelsById, entry);
|
|
18
|
+
}
|
|
19
|
+
return labelsById;
|
|
20
|
+
}
|
|
21
|
+
function generateEntryId(byId) {
|
|
22
|
+
for (let i = 0; i < 100; i++) {
|
|
23
|
+
const id = randomUUID().slice(0, 8);
|
|
24
|
+
if (!byId.has(id))
|
|
25
|
+
return id;
|
|
26
|
+
}
|
|
27
|
+
return randomUUID();
|
|
28
|
+
}
|
|
29
|
+
export class InMemorySessionStorage {
|
|
30
|
+
metadata;
|
|
31
|
+
entries;
|
|
32
|
+
byId;
|
|
33
|
+
labelsById;
|
|
34
|
+
leafId;
|
|
35
|
+
constructor(options) {
|
|
36
|
+
this.entries = options?.entries ? [...options.entries] : [];
|
|
37
|
+
this.byId = new Map(this.entries.map((entry) => [entry.id, entry]));
|
|
38
|
+
this.labelsById = buildLabelsById(this.entries);
|
|
39
|
+
this.leafId = options?.leafId ?? this.entries[this.entries.length - 1]?.id ?? null;
|
|
40
|
+
if (this.leafId !== null && !this.byId.has(this.leafId)) {
|
|
41
|
+
throw new Error(`Entry ${this.leafId} not found`);
|
|
42
|
+
}
|
|
43
|
+
this.metadata = options?.metadata ?? { id: uuidv7(), createdAt: new Date().toISOString() };
|
|
44
|
+
}
|
|
45
|
+
async getMetadata() {
|
|
46
|
+
return this.metadata;
|
|
47
|
+
}
|
|
48
|
+
async getLeafId() {
|
|
49
|
+
return this.leafId;
|
|
50
|
+
}
|
|
51
|
+
async setLeafId(leafId) {
|
|
52
|
+
if (leafId !== null && !this.byId.has(leafId)) {
|
|
53
|
+
throw new Error(`Entry ${leafId} not found`);
|
|
54
|
+
}
|
|
55
|
+
this.leafId = leafId;
|
|
56
|
+
}
|
|
57
|
+
async createEntryId() {
|
|
58
|
+
return generateEntryId(this.byId);
|
|
59
|
+
}
|
|
60
|
+
async appendEntry(entry) {
|
|
61
|
+
this.entries.push(entry);
|
|
62
|
+
this.byId.set(entry.id, entry);
|
|
63
|
+
updateLabelCache(this.labelsById, entry);
|
|
64
|
+
this.leafId = entry.id;
|
|
65
|
+
}
|
|
66
|
+
async getEntry(id) {
|
|
67
|
+
return this.byId.get(id);
|
|
68
|
+
}
|
|
69
|
+
async findEntries(type) {
|
|
70
|
+
return this.entries.filter((entry) => entry.type === type);
|
|
71
|
+
}
|
|
72
|
+
async getLabel(id) {
|
|
73
|
+
return this.labelsById.get(id);
|
|
74
|
+
}
|
|
75
|
+
async getPathToRoot(leafId) {
|
|
76
|
+
if (leafId === null)
|
|
77
|
+
return [];
|
|
78
|
+
const path = [];
|
|
79
|
+
let current = this.byId.get(leafId);
|
|
80
|
+
while (current) {
|
|
81
|
+
path.unshift(current);
|
|
82
|
+
current = current.parentId ? this.byId.get(current.parentId) : undefined;
|
|
83
|
+
}
|
|
84
|
+
return path;
|
|
85
|
+
}
|
|
86
|
+
async getEntries() {
|
|
87
|
+
return [...this.entries];
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWVtb3J5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2xpYi9hZ2VudC1jb3JlL2hhcm5lc3Mvc2Vzc2lvbi9zdG9yYWdlL21lbW9yeS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQ3pDLE9BQU8sRUFBRSxFQUFFLElBQUksTUFBTSxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBR3BDLFNBQVMsZ0JBQWdCLENBQUMsVUFBK0IsRUFBRSxLQUF1QjtJQUNqRixJQUFJLEtBQUssQ0FBQyxJQUFJLEtBQUssT0FBTztRQUFFLE9BQU87SUFDbkMsTUFBTSxLQUFLLEdBQUcsS0FBSyxDQUFDLEtBQUssRUFBRSxJQUFJLEVBQUUsQ0FBQztJQUNsQyxJQUFJLEtBQUssRUFBRSxDQUFDO1FBQ1gsVUFBVSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsUUFBUSxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQ3ZDLENBQUM7U0FBTSxDQUFDO1FBQ1AsVUFBVSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDbkMsQ0FBQztBQUNGLENBQUM7QUFFRCxTQUFTLGVBQWUsQ0FBQyxPQUEyQjtJQUNuRCxNQUFNLFVBQVUsR0FBRyxJQUFJLEdBQUcsRUFBa0IsQ0FBQztJQUM3QyxLQUFLLE1BQU0sS0FBSyxJQUFJLE9BQU8sRUFBRSxDQUFDO1FBQzdCLGdCQUFnQixDQUFDLFVBQVUsRUFBRSxLQUFLLENBQUMsQ0FBQztJQUNyQyxDQUFDO0lBQ0QsT0FBTyxVQUFVLENBQUM7QUFDbkIsQ0FBQztBQUVELFNBQVMsZUFBZSxDQUFDLElBQWtDO0lBQzFELEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxHQUFHLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztRQUM5QixNQUFNLEVBQUUsR0FBRyxVQUFVLEVBQUUsQ0FB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
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { ExecutionEnv, Skill } from "./types.js";
|
|
2
|
+
/** Warning produced while loading skills. */
|
|
3
|
+
export interface SkillDiagnostic {
|
|
4
|
+
/** Diagnostic severity. Currently only warnings are emitted. */
|
|
5
|
+
type: "warning";
|
|
6
|
+
/** Human-readable diagnostic message. */
|
|
7
|
+
message: string;
|
|
8
|
+
/** Path associated with the diagnostic. */
|
|
9
|
+
path: string;
|
|
10
|
+
}
|
|
11
|
+
/** Format a skill invocation prompt, optionally appending additional user instructions. */
|
|
12
|
+
export declare function formatSkillInvocation(skill: Skill, additionalInstructions?: string): string;
|
|
13
|
+
/**
|
|
14
|
+
* Load skills from one or more directories.
|
|
15
|
+
*
|
|
16
|
+
* Traverses directories recursively, loads `SKILL.md` files, loads direct root `.md` files as skills, honors ignore files,
|
|
17
|
+
* and returns diagnostics for invalid skill files. Missing input directories are skipped.
|
|
18
|
+
*/
|
|
19
|
+
export declare function loadSkills(env: ExecutionEnv, dirs: string | string[]): Promise<{
|
|
20
|
+
skills: Skill[];
|
|
21
|
+
diagnostics: SkillDiagnostic[];
|
|
22
|
+
}>;
|
|
23
|
+
/**
|
|
24
|
+
* Load skills from source-tagged directories.
|
|
25
|
+
*
|
|
26
|
+
* Source values are preserved exactly and attached to every loaded skill and diagnostic. The agent package does not
|
|
27
|
+
* interpret source values; applications define their own provenance shape.
|
|
28
|
+
*/
|
|
29
|
+
export declare function loadSourcedSkills<TSource, TSkill extends Skill = Skill>(env: ExecutionEnv, inputs: Array<{
|
|
30
|
+
path: string;
|
|
31
|
+
source: TSource;
|
|
32
|
+
}>, mapSkill?: (skill: Skill, source: TSource) => TSkill): Promise<{
|
|
33
|
+
skills: Array<{
|
|
34
|
+
skill: TSkill;
|
|
35
|
+
source: TSource;
|
|
36
|
+
}>;
|
|
37
|
+
diagnostics: Array<SkillDiagnostic & {
|
|
38
|
+
source: TSource;
|
|
39
|
+
}>;
|
|
40
|
+
}>;
|