@anureo/adapter-claude 0.2.0 → 0.3.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/README.md +107 -12
- package/package.json +23 -23
- package/src/adapter.d.ts +253 -0
- package/src/adapter.js +1328 -0
- package/src/catalog.d.ts +26 -0
- package/src/catalog.js +168 -0
- package/src/file-changes.d.ts +22 -0
- package/src/file-changes.js +124 -0
- package/src/index.d.ts +4 -0
- package/src/index.js +4 -0
- package/src/options.d.ts +47 -0
- package/src/options.js +0 -0
- package/src/output-schema.d.ts +17 -0
- package/src/output-schema.js +23 -0
- package/src/store.d.ts +71 -0
- package/src/store.js +223 -0
- package/src/turn-error.d.ts +11 -0
- package/src/turn-error.js +74 -0
- package/dist/catalog.d.ts +0 -8
- package/dist/catalog.js +0 -1087
- package/dist/file-changes.d.ts +0 -6
- package/dist/index.d.ts +0 -88
- package/dist/index.js +0 -1000
- package/dist/store.d.ts +0 -23
- package/dist/store.js +0 -141
package/dist/store.d.ts
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import type { SessionKey, SessionStore, SessionStoreEntry } from "@anthropic-ai/claude-agent-sdk";
|
|
2
|
-
/** Uses the official opaque SessionStore contract; never parses Claude's private transcript files. */
|
|
3
|
-
export declare class FileSessionStore implements SessionStore {
|
|
4
|
-
readonly directory: string;
|
|
5
|
-
constructor(directory: string);
|
|
6
|
-
private file;
|
|
7
|
-
private read;
|
|
8
|
-
append(key: SessionKey, entries: SessionStoreEntry[]): Promise<void>;
|
|
9
|
-
load(key: SessionKey): Promise<SessionStoreEntry[] | null>;
|
|
10
|
-
private all;
|
|
11
|
-
listSessions(projectKey: string): Promise<Array<{
|
|
12
|
-
sessionId: string;
|
|
13
|
-
mtime: number;
|
|
14
|
-
}>>;
|
|
15
|
-
listSubkeys(key: {
|
|
16
|
-
projectKey: string;
|
|
17
|
-
sessionId: string;
|
|
18
|
-
}): Promise<string[]>;
|
|
19
|
-
delete(key: SessionKey): Promise<void>;
|
|
20
|
-
private turnMapPath;
|
|
21
|
-
loadTurnMap(sessionId: string): Promise<Record<string, string>>;
|
|
22
|
-
saveTurnMap(sessionId: string, turns: Record<string, string>): Promise<void>;
|
|
23
|
-
}
|
package/dist/store.js
DELETED
|
@@ -1,141 +0,0 @@
|
|
|
1
|
-
// packages/claude/src/store.ts
|
|
2
|
-
import { createHash, randomUUID } from "node:crypto";
|
|
3
|
-
import { mkdir, open, readFile, readdir, rename, rm } from "node:fs/promises";
|
|
4
|
-
import { join } from "node:path";
|
|
5
|
-
import { HarnessSdkError } from "@anureo/sdk";
|
|
6
|
-
|
|
7
|
-
class FileSessionStore {
|
|
8
|
-
directory;
|
|
9
|
-
constructor(directory) {
|
|
10
|
-
this.directory = directory;
|
|
11
|
-
}
|
|
12
|
-
file(key) {
|
|
13
|
-
return join(this.directory, `${createHash("sha256").update(JSON.stringify([key.projectKey, key.sessionId, key.subpath ?? null])).digest("hex")}.json`);
|
|
14
|
-
}
|
|
15
|
-
async read(file) {
|
|
16
|
-
try {
|
|
17
|
-
const value = JSON.parse(await readFile(file, "utf8"));
|
|
18
|
-
if (!value || !value.key || !Array.isArray(value.entries))
|
|
19
|
-
throw new HarnessSdkError("SESSION_STORE_INVALID");
|
|
20
|
-
return value;
|
|
21
|
-
} catch (cause) {
|
|
22
|
-
if (cause.code === "ENOENT")
|
|
23
|
-
return null;
|
|
24
|
-
throw cause;
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
async append(key, entries) {
|
|
28
|
-
await mkdir(this.directory, { recursive: true, mode: 448 });
|
|
29
|
-
const file = this.file(key);
|
|
30
|
-
const lockPath = `${file}.lock`;
|
|
31
|
-
const expires = Date.now() + 1e4;
|
|
32
|
-
let lock;
|
|
33
|
-
while (!lock) {
|
|
34
|
-
try {
|
|
35
|
-
lock = await open(lockPath, "wx", 384);
|
|
36
|
-
await lock.writeFile(String(process.pid));
|
|
37
|
-
} catch (cause) {
|
|
38
|
-
if (cause.code !== "EEXIST")
|
|
39
|
-
throw cause;
|
|
40
|
-
const pid = Number(await readFile(lockPath, "utf8").catch(() => ""));
|
|
41
|
-
let alive = true;
|
|
42
|
-
if (Number.isSafeInteger(pid) && pid > 0) {
|
|
43
|
-
try {
|
|
44
|
-
process.kill(pid, 0);
|
|
45
|
-
} catch (error) {
|
|
46
|
-
alive = error.code !== "ESRCH";
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
if (!alive) {
|
|
50
|
-
await rm(lockPath, { force: true });
|
|
51
|
-
continue;
|
|
52
|
-
}
|
|
53
|
-
if (Date.now() >= expires)
|
|
54
|
-
throw new HarnessSdkError("SESSION_STORE_BUSY");
|
|
55
|
-
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
const temporary = `${file}.${randomUUID()}.tmp`;
|
|
59
|
-
try {
|
|
60
|
-
const stored = await this.read(file) ?? { key: structuredClone(key), entries: [], mtime: 0 };
|
|
61
|
-
const byId = new Map(stored.entries.flatMap((entry, index) => entry.uuid ? [[entry.uuid, index]] : []));
|
|
62
|
-
for (const entry of entries) {
|
|
63
|
-
const previous = entry.uuid ? byId.get(entry.uuid) : undefined;
|
|
64
|
-
if (previous !== undefined)
|
|
65
|
-
stored.entries[previous] = structuredClone(entry);
|
|
66
|
-
else {
|
|
67
|
-
if (entry.uuid)
|
|
68
|
-
byId.set(entry.uuid, stored.entries.length);
|
|
69
|
-
stored.entries.push(structuredClone(entry));
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
stored.mtime = Math.max(Date.now(), stored.mtime + 1);
|
|
73
|
-
const target = await open(temporary, "wx", 384);
|
|
74
|
-
try {
|
|
75
|
-
await target.writeFile(JSON.stringify(stored));
|
|
76
|
-
await target.sync();
|
|
77
|
-
} finally {
|
|
78
|
-
await target.close();
|
|
79
|
-
}
|
|
80
|
-
await rename(temporary, file);
|
|
81
|
-
} finally {
|
|
82
|
-
await rm(temporary, { force: true });
|
|
83
|
-
await lock.close();
|
|
84
|
-
await rm(lockPath, { force: true });
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
async load(key) {
|
|
88
|
-
const value = await this.read(this.file(key));
|
|
89
|
-
return value ? structuredClone(value.entries) : null;
|
|
90
|
-
}
|
|
91
|
-
async all() {
|
|
92
|
-
const names = await readdir(this.directory).catch((cause) => {
|
|
93
|
-
if (cause.code === "ENOENT")
|
|
94
|
-
return [];
|
|
95
|
-
throw cause;
|
|
96
|
-
});
|
|
97
|
-
const entries = await Promise.all(names.filter((name) => /^[a-f0-9]{64}\.json$/.test(name)).map((name) => this.read(join(this.directory, name))));
|
|
98
|
-
return entries.filter((entry) => entry !== null);
|
|
99
|
-
}
|
|
100
|
-
async listSessions(projectKey) {
|
|
101
|
-
return (await this.all()).filter((entry) => entry.key.projectKey === projectKey && !entry.key.subpath).map(({ key, mtime }) => ({ sessionId: key.sessionId, mtime }));
|
|
102
|
-
}
|
|
103
|
-
async listSubkeys(key) {
|
|
104
|
-
return (await this.all()).filter((entry) => entry.key.projectKey === key.projectKey && entry.key.sessionId === key.sessionId && entry.key.subpath).map((entry) => entry.key.subpath);
|
|
105
|
-
}
|
|
106
|
-
async delete(key) {
|
|
107
|
-
await rm(this.file(key), { force: true });
|
|
108
|
-
}
|
|
109
|
-
turnMapPath(sessionId) {
|
|
110
|
-
return join(this.directory, `${createHash("sha256").update(`turns:${sessionId}`).digest("hex")}.turns.json`);
|
|
111
|
-
}
|
|
112
|
-
async loadTurnMap(sessionId) {
|
|
113
|
-
try {
|
|
114
|
-
return JSON.parse(await readFile(this.turnMapPath(sessionId), "utf8"));
|
|
115
|
-
} catch (cause) {
|
|
116
|
-
if (cause.code === "ENOENT")
|
|
117
|
-
return {};
|
|
118
|
-
throw cause;
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
async saveTurnMap(sessionId, turns) {
|
|
122
|
-
await mkdir(this.directory, { recursive: true, mode: 448 });
|
|
123
|
-
const path = this.turnMapPath(sessionId);
|
|
124
|
-
const temporary = `${path}.${randomUUID()}.tmp`;
|
|
125
|
-
try {
|
|
126
|
-
const file = await open(temporary, "wx", 384);
|
|
127
|
-
try {
|
|
128
|
-
await file.writeFile(JSON.stringify(turns));
|
|
129
|
-
await file.sync();
|
|
130
|
-
} finally {
|
|
131
|
-
await file.close();
|
|
132
|
-
}
|
|
133
|
-
await rename(temporary, path);
|
|
134
|
-
} finally {
|
|
135
|
-
await rm(temporary, { force: true });
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
export {
|
|
140
|
-
FileSessionStore
|
|
141
|
-
};
|