@code-yeongyu/senpi-agent-core 2026.8.12 → 2026.8.13
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 +13 -7
- package/dist/agent-loop.js +5 -1
- package/dist/agent-loop.js.map +1 -1
- package/dist/agent.d.ts +3 -1
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +8 -0
- package/dist/agent.js.map +1 -1
- package/dist/harness/agent-harness.d.ts +452 -96
- package/dist/harness/agent-harness.d.ts.map +1 -1
- package/dist/harness/agent-harness.js +162 -1005
- package/dist/harness/agent-harness.js.map +1 -1
- package/dist/harness/compaction/branch-summarization.d.ts +13 -6
- package/dist/harness/compaction/branch-summarization.d.ts.map +1 -1
- package/dist/harness/compaction/branch-summarization.js +10 -14
- package/dist/harness/compaction/branch-summarization.js.map +1 -1
- package/dist/harness/compaction/compaction.d.ts +14 -17
- package/dist/harness/compaction/compaction.d.ts.map +1 -1
- package/dist/harness/compaction/compaction.js +23 -36
- package/dist/harness/compaction/compaction.js.map +1 -1
- package/dist/harness/env/nodejs.d.ts +1 -0
- package/dist/harness/env/nodejs.d.ts.map +1 -1
- package/dist/harness/env/nodejs.js +23 -7
- package/dist/harness/env/nodejs.js.map +1 -1
- package/dist/harness/messages.d.ts +3 -3
- package/dist/harness/messages.d.ts.map +1 -1
- package/dist/harness/messages.js +3 -3
- package/dist/harness/messages.js.map +1 -1
- package/dist/harness/prompt-templates.d.ts.map +1 -1
- package/dist/harness/prompt-templates.js +4 -9
- package/dist/harness/prompt-templates.js.map +1 -1
- package/dist/harness/reducer.d.ts +100 -0
- package/dist/harness/reducer.d.ts.map +1 -0
- package/dist/harness/reducer.js +414 -0
- package/dist/harness/reducer.js.map +1 -0
- package/dist/harness/result.d.ts +40 -0
- package/dist/harness/result.d.ts.map +1 -0
- package/dist/harness/result.js +41 -0
- package/dist/harness/result.js.map +1 -0
- package/dist/harness/session/context.d.ts +22 -0
- package/dist/harness/session/context.d.ts.map +1 -0
- package/dist/harness/session/context.js +67 -0
- package/dist/harness/session/context.js.map +1 -0
- package/dist/harness/session/index.d.ts +7 -0
- package/dist/harness/session/index.d.ts.map +1 -0
- package/dist/harness/session/index.js +6 -0
- package/dist/harness/session/index.js.map +1 -0
- package/dist/harness/session/jsonl/codec.d.ts +8 -0
- package/dist/harness/session/jsonl/codec.d.ts.map +1 -0
- package/dist/harness/session/jsonl/codec.js +190 -0
- package/dist/harness/session/jsonl/codec.js.map +1 -0
- package/dist/harness/session/jsonl/errors.d.ts +5 -0
- package/dist/harness/session/jsonl/errors.d.ts.map +1 -0
- package/dist/harness/session/jsonl/errors.js +11 -0
- package/dist/harness/session/jsonl/errors.js.map +1 -0
- package/dist/harness/session/jsonl/repo.d.ts +23 -0
- package/dist/harness/session/jsonl/repo.d.ts.map +1 -0
- package/dist/harness/session/jsonl/repo.js +129 -0
- package/dist/harness/session/jsonl/repo.js.map +1 -0
- package/dist/harness/session/jsonl/storage.d.ts +43 -0
- package/dist/harness/session/jsonl/storage.d.ts.map +1 -0
- package/dist/harness/session/jsonl/storage.js +206 -0
- package/dist/harness/session/jsonl/storage.js.map +1 -0
- package/dist/harness/session/jsonl/types.d.ts +38 -0
- package/dist/harness/session/jsonl/types.d.ts.map +1 -0
- package/dist/harness/session/jsonl/types.js +2 -0
- package/dist/harness/session/jsonl/types.js.map +1 -0
- package/dist/harness/session/jsonl.d.ts +3 -0
- package/dist/harness/session/jsonl.d.ts.map +1 -0
- package/dist/harness/session/jsonl.js +2 -0
- package/dist/harness/session/jsonl.js.map +1 -0
- package/dist/harness/session/memory.d.ts +44 -0
- package/dist/harness/session/memory.d.ts.map +1 -0
- package/dist/harness/session/memory.js +142 -0
- package/dist/harness/session/memory.js.map +1 -0
- package/dist/harness/session/search.d.ts +19 -0
- package/dist/harness/session/search.d.ts.map +1 -0
- package/dist/harness/session/search.js +41 -0
- package/dist/harness/session/search.js.map +1 -0
- package/dist/harness/session/session.d.ts +43 -38
- package/dist/harness/session/session.d.ts.map +1 -1
- package/dist/harness/session/session.js +186 -304
- package/dist/harness/session/session.js.map +1 -1
- package/dist/harness/session/state.d.ts +65 -0
- package/dist/harness/session/state.d.ts.map +1 -0
- package/dist/harness/session/state.js +320 -0
- package/dist/harness/session/state.js.map +1 -0
- package/dist/harness/session/testing/conformance.d.ts +4 -0
- package/dist/harness/session/testing/conformance.d.ts.map +1 -0
- package/dist/harness/session/testing/conformance.js +743 -0
- package/dist/harness/session/testing/conformance.js.map +1 -0
- package/dist/harness/session/testing/index.d.ts +3 -0
- package/dist/harness/session/testing/index.d.ts.map +1 -0
- package/dist/harness/session/testing/index.js +2 -0
- package/dist/harness/session/testing/index.js.map +1 -0
- package/dist/harness/session/testing/types.d.ts +14 -0
- package/dist/harness/session/testing/types.d.ts.map +1 -0
- package/dist/harness/session/testing/types.js +2 -0
- package/dist/harness/session/testing/types.js.map +1 -0
- package/dist/harness/session/types.d.ts +333 -0
- package/dist/harness/session/types.d.ts.map +1 -0
- package/dist/harness/session/types.js +9 -0
- package/dist/harness/session/types.js.map +1 -0
- package/dist/harness/skills.js +21 -19
- package/dist/harness/skills.js.map +1 -1
- package/dist/harness/telemetry.d.ts +1221 -0
- package/dist/harness/telemetry.d.ts.map +1 -0
- package/dist/harness/telemetry.js +508 -0
- package/dist/harness/telemetry.js.map +1 -0
- package/dist/harness/types.d.ts +8 -485
- package/dist/harness/types.d.ts.map +1 -1
- package/dist/harness/types.js +4 -16
- package/dist/harness/types.js.map +1 -1
- package/dist/harness/utils/truncate.js.map +1 -1
- package/dist/index.d.ts +10 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -8
- package/dist/index.js.map +1 -1
- package/dist/proxy.d.ts +1 -1
- package/dist/proxy.d.ts.map +1 -1
- package/dist/proxy.js +1 -0
- package/dist/proxy.js.map +1 -1
- package/dist/types.d.ts +6 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +9 -2
- package/dist/harness/session/array-session-reader.d.ts +0 -3
- package/dist/harness/session/array-session-reader.d.ts.map +0 -1
- package/dist/harness/session/array-session-reader.js +0 -70
- package/dist/harness/session/array-session-reader.js.map +0 -1
- package/dist/harness/session/fork.d.ts +0 -4
- package/dist/harness/session/fork.d.ts.map +0 -1
- package/dist/harness/session/fork.js +0 -22
- package/dist/harness/session/fork.js.map +0 -1
- package/dist/harness/session/jsonl-store.d.ts +0 -13
- package/dist/harness/session/jsonl-store.d.ts.map +0 -1
- package/dist/harness/session/jsonl-store.js +0 -304
- package/dist/harness/session/jsonl-store.js.map +0 -1
- package/dist/harness/session/keyed-operation-queue.d.ts +0 -17
- package/dist/harness/session/keyed-operation-queue.d.ts.map +0 -1
- package/dist/harness/session/keyed-operation-queue.js +0 -60
- package/dist/harness/session/keyed-operation-queue.js.map +0 -1
- package/dist/harness/session/memory-store.d.ts +0 -6
- package/dist/harness/session/memory-store.d.ts.map +0 -1
- package/dist/harness/session/memory-store.js +0 -107
- package/dist/harness/session/memory-store.js.map +0 -1
- package/dist/harness/session/repository.d.ts +0 -28
- package/dist/harness/session/repository.d.ts.map +0 -1
- package/dist/harness/session/repository.js +0 -61
- package/dist/harness/session/repository.js.map +0 -1
- package/dist/harness/session/search-backend.d.ts +0 -8
- package/dist/harness/session/search-backend.d.ts.map +0 -1
- package/dist/harness/session/search-backend.js +0 -22
- package/dist/harness/session/search-backend.js.map +0 -1
|
@@ -1,45 +1,50 @@
|
|
|
1
|
-
import { type ImageContent, type TextContent, type Usage } from "@earendil-works/pi-ai";
|
|
2
1
|
import type { AgentMessage } from "../../types.ts";
|
|
3
|
-
import type {
|
|
4
|
-
export
|
|
5
|
-
export
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
}
|
|
12
|
-
export declare function defaultContextEntryTransform(pathEntries: readonly SessionTreeEntry[]): SessionTreeEntry[];
|
|
13
|
-
export declare function buildContextEntries(pathEntries: readonly SessionTreeEntry[], options?: SessionContextBuildOptions): SessionTreeEntry[];
|
|
14
|
-
export declare function sessionEntryToContextMessages(entry: SessionTreeEntry, index: number, entries: readonly SessionTreeEntry[], options?: SessionContextBuildOptions): AgentMessage[];
|
|
15
|
-
export declare function buildSessionContext(pathEntries: readonly SessionTreeEntry[], options?: SessionContextBuildOptions): SessionContext;
|
|
16
|
-
export interface Session<TMetadata extends SessionMetadata = SessionMetadata> {
|
|
2
|
+
import type { BranchBounds, Entry, EntryQuery, IdGenerator, LanePointer, LaneRecord, LogItem, LogOptions, NewRecord, OperationStartedRecord, ProvisionedEntry, RecordBase, RecordQuery, SessionMetadata, SessionStats, SessionStorage, SessionTree } from "./types.ts";
|
|
3
|
+
export declare function assertJsonSerializable(value: unknown): void;
|
|
4
|
+
export declare class Session<TMetadata extends SessionMetadata = SessionMetadata> implements SessionTree {
|
|
5
|
+
private readonly storage;
|
|
6
|
+
readonly idGenerator: IdGenerator;
|
|
7
|
+
constructor(storage: SessionStorage<TMetadata>, options?: {
|
|
8
|
+
idGenerator?: IdGenerator;
|
|
9
|
+
});
|
|
17
10
|
getMetadata(): Promise<TMetadata>;
|
|
11
|
+
view(lane: string): SessionTree;
|
|
18
12
|
getLeafId(): Promise<string | null>;
|
|
19
|
-
getEntry(id: string): Promise<
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
13
|
+
getEntry(id: string): Promise<Entry | undefined>;
|
|
14
|
+
getStats(): Promise<SessionStats>;
|
|
15
|
+
getName(): Promise<string | undefined>;
|
|
16
|
+
setName(name: string): Promise<void>;
|
|
17
|
+
getLabel(targetId: string): Promise<string | undefined>;
|
|
18
|
+
setLabel(targetId: string, label: string | undefined): Promise<void>;
|
|
19
|
+
findEntries(query?: EntryQuery): Promise<Entry[]>;
|
|
20
|
+
findEntry(query?: EntryQuery): Promise<Entry | undefined>;
|
|
21
|
+
findEntriesOnBranch(query?: EntryQuery & BranchBounds): Promise<Entry[]>;
|
|
22
|
+
findEntryOnBranch(query?: EntryQuery & BranchBounds): Promise<Entry | undefined>;
|
|
27
23
|
appendMessage(message: AgentMessage): Promise<string>;
|
|
28
|
-
appendThinkingLevelChange(thinkingLevel: string): Promise<string>;
|
|
29
|
-
appendModelChange(provider: string, modelId: string): Promise<string>;
|
|
30
|
-
appendActiveToolsChange(activeToolNames: string[]): Promise<string>;
|
|
31
|
-
appendCompaction<T = unknown>(summary: string, firstKeptEntryId: string | undefined, tokensBefore: number, details?: T, fromHook?: boolean, usage?: Usage, retainedTail?: AgentMessage[]): Promise<string>;
|
|
32
24
|
appendCustomEntry(customType: string, data?: unknown): Promise<string>;
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
25
|
+
getLanes(): Promise<LanePointer[]>;
|
|
26
|
+
createLane(lane: string, at: string | null): Promise<void>;
|
|
27
|
+
moveLane(lane: string, to: string | null): Promise<void>;
|
|
28
|
+
appendEntry<TEntry extends Entry>(entry: ProvisionedEntry<TEntry>, lane: string): Promise<TEntry>;
|
|
29
|
+
appendRecord<TNewRecord extends NewRecord>(record: TNewRecord): Promise<TNewRecord & Pick<RecordBase, "seq" | "timestamp">>;
|
|
30
|
+
findRecords<K extends LaneRecord["type"]>(query: RecordQuery & {
|
|
31
|
+
type: K;
|
|
32
|
+
}): Promise<Extract<LaneRecord, {
|
|
33
|
+
type: K;
|
|
34
|
+
}>[]>;
|
|
35
|
+
findRecords(query?: RecordQuery): Promise<LaneRecord[]>;
|
|
36
|
+
findOpenOperations(lane: string, options?: {
|
|
37
|
+
limit?: number;
|
|
38
|
+
}): Promise<OperationStartedRecord[]>;
|
|
39
|
+
getLog(options?: LogOptions): Promise<LogItem[]>;
|
|
40
|
+
private getLeafIdForLane;
|
|
41
|
+
private queryEntries;
|
|
42
|
+
private queryBranchEntries;
|
|
43
|
+
private queryRecords;
|
|
44
|
+
private queryLog;
|
|
45
|
+
private appendMessageToLane;
|
|
46
|
+
private appendCustomEntryToLane;
|
|
47
|
+
private commitEntry;
|
|
48
|
+
private commitRecord;
|
|
42
49
|
}
|
|
43
|
-
/** @internal Construct sessions only through SessionRepository. */
|
|
44
|
-
export declare function createSessionFromReader<TMetadata extends SessionMetadata>(store: Pick<SessionStore<TMetadata>, "appendEntry">, reader: SessionReader<TMetadata>, contextBuildOptions?: SessionContextBuildOptions): Promise<Session<TMetadata>>;
|
|
45
50
|
//# sourceMappingURL=session.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../../src/harness/session/session.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../../src/harness/session/session.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,338 +1,220 @@
|
|
|
1
1
|
import { uuidv7 } from "@earendil-works/pi-ai";
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
2
|
+
import { SessionError } from "./types.js";
|
|
3
|
+
function invalidPayload(reason) {
|
|
4
|
+
throw new SessionError("invalid_payload", `Durable payload ${reason}`);
|
|
5
|
+
}
|
|
6
|
+
function assertValidLimit(limit) {
|
|
7
|
+
if (limit !== undefined && (!Number.isInteger(limit) || limit <= 0)) {
|
|
8
|
+
throw new SessionError("invalid_query", "limit must be a positive integer");
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
function assertValidCursor(afterSeq) {
|
|
12
|
+
if (afterSeq !== undefined && (!Number.isInteger(afterSeq) || afterSeq < 0)) {
|
|
13
|
+
throw new SessionError("invalid_query", "cursor sequence must be a non-negative integer");
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
export function assertJsonSerializable(value) {
|
|
17
|
+
const active = new WeakSet();
|
|
18
|
+
const stack = [{ value }];
|
|
19
|
+
while (stack.length > 0) {
|
|
20
|
+
const frame = stack.pop();
|
|
21
|
+
if ("exit" in frame) {
|
|
22
|
+
active.delete(frame.exit);
|
|
23
|
+
continue;
|
|
11
24
|
}
|
|
12
|
-
|
|
13
|
-
|
|
25
|
+
const candidate = frame.value;
|
|
26
|
+
if (candidate === null || typeof candidate === "string" || typeof candidate === "boolean") {
|
|
27
|
+
continue;
|
|
14
28
|
}
|
|
15
|
-
|
|
16
|
-
|
|
29
|
+
if (typeof candidate === "number") {
|
|
30
|
+
if (!Number.isFinite(candidate))
|
|
31
|
+
invalidPayload("contains a non-finite number");
|
|
32
|
+
continue;
|
|
17
33
|
}
|
|
18
|
-
|
|
19
|
-
|
|
34
|
+
if (typeof candidate !== "object")
|
|
35
|
+
invalidPayload(`contains ${typeof candidate}`);
|
|
36
|
+
if (active.has(candidate))
|
|
37
|
+
invalidPayload("contains a cycle");
|
|
38
|
+
active.add(candidate);
|
|
39
|
+
stack.push({ exit: candidate });
|
|
40
|
+
if (Array.isArray(candidate)) {
|
|
41
|
+
if (Object.getPrototypeOf(candidate) !== Array.prototype) {
|
|
42
|
+
invalidPayload("contains a non-standard array");
|
|
43
|
+
}
|
|
44
|
+
if (Object.getOwnPropertySymbols(candidate).length > 0 ||
|
|
45
|
+
Object.getOwnPropertyNames(candidate).length !== candidate.length + 1) {
|
|
46
|
+
invalidPayload("contains an array with unsupported properties");
|
|
47
|
+
}
|
|
48
|
+
for (let index = candidate.length - 1; index >= 0; index--) {
|
|
49
|
+
if (!Object.hasOwn(candidate, index))
|
|
50
|
+
invalidPayload("contains a sparse array");
|
|
51
|
+
const descriptor = Object.getOwnPropertyDescriptor(candidate, index);
|
|
52
|
+
if (!("value" in descriptor))
|
|
53
|
+
invalidPayload("contains an array accessor");
|
|
54
|
+
stack.push({ value: descriptor.value });
|
|
55
|
+
}
|
|
56
|
+
continue;
|
|
20
57
|
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
export function defaultContextEntryTransform(pathEntries) {
|
|
25
|
-
let compaction = null;
|
|
26
|
-
for (const entry of pathEntries) {
|
|
27
|
-
if (entry.type === "compaction") {
|
|
28
|
-
compaction = entry;
|
|
58
|
+
const prototype = Object.getPrototypeOf(candidate);
|
|
59
|
+
if (prototype !== Object.prototype && prototype !== null) {
|
|
60
|
+
invalidPayload("contains a non-plain object");
|
|
29
61
|
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
return [...pathEntries];
|
|
33
|
-
}
|
|
34
|
-
const entries = [compaction];
|
|
35
|
-
const compactionIdx = pathEntries.findIndex((entry) => entry.type === "compaction" && entry.id === compaction.id);
|
|
36
|
-
if (compaction.retainedTail) {
|
|
37
|
-
for (let i = compactionIdx + 1; i < pathEntries.length; i++) {
|
|
38
|
-
entries.push(pathEntries[i]);
|
|
62
|
+
if (Object.getOwnPropertySymbols(candidate).length > 0) {
|
|
63
|
+
invalidPayload("contains a symbol-keyed property");
|
|
39
64
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
let foundFirstKept = false;
|
|
44
|
-
for (let i = 0; i < compactionIdx; i++) {
|
|
45
|
-
const entry = pathEntries[i];
|
|
46
|
-
if (entry.id === compaction.firstKeptEntryId)
|
|
47
|
-
foundFirstKept = true;
|
|
48
|
-
if (foundFirstKept)
|
|
49
|
-
entries.push(entry);
|
|
65
|
+
const keys = Object.keys(candidate);
|
|
66
|
+
if (Object.getOwnPropertyNames(candidate).length !== keys.length) {
|
|
67
|
+
invalidPayload("contains a non-enumerable property");
|
|
50
68
|
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}
|
|
57
|
-
export function buildContextEntries(pathEntries, options = {}) {
|
|
58
|
-
let entries = defaultContextEntryTransform(pathEntries);
|
|
59
|
-
for (const transform of options.entryTransforms ?? []) {
|
|
60
|
-
entries = [...transform(entries)];
|
|
61
|
-
}
|
|
62
|
-
return entries;
|
|
63
|
-
}
|
|
64
|
-
export function sessionEntryToContextMessages(entry, index, entries, options = {}) {
|
|
65
|
-
if (entry.type === "message") {
|
|
66
|
-
return [entry.message];
|
|
67
|
-
}
|
|
68
|
-
if (entry.type === "custom_message") {
|
|
69
|
-
return [
|
|
70
|
-
createCustomMessage(entry.customType, entry.content, entry.display, entry.details, entry.timestamp),
|
|
71
|
-
];
|
|
72
|
-
}
|
|
73
|
-
if (entry.type === "compaction") {
|
|
74
|
-
return [
|
|
75
|
-
createCompactionSummaryMessage(entry.summary, entry.tokensBefore, entry.timestamp),
|
|
76
|
-
...(entry.retainedTail ?? []),
|
|
77
|
-
];
|
|
78
|
-
}
|
|
79
|
-
if (entry.type === "branch_summary" && entry.summary) {
|
|
80
|
-
return [createBranchSummaryMessage(entry.summary, entry.fromId, entry.timestamp)];
|
|
81
|
-
}
|
|
82
|
-
if (entry.type === "custom") {
|
|
83
|
-
return [...(options.entryProjectors?.[entry.customType]?.(entry, index, entries) ?? [])];
|
|
84
|
-
}
|
|
85
|
-
return [];
|
|
86
|
-
}
|
|
87
|
-
export function buildSessionContext(pathEntries, options = {}) {
|
|
88
|
-
const state = deriveSessionContextState(pathEntries);
|
|
89
|
-
const contextEntries = buildContextEntries(pathEntries, options);
|
|
90
|
-
const messages = contextEntries.flatMap((entry, index) => sessionEntryToContextMessages(entry, index, contextEntries, options));
|
|
91
|
-
return { ...state, messages };
|
|
92
|
-
}
|
|
93
|
-
class HydratedSessionState {
|
|
94
|
-
constructor(entries) {
|
|
95
|
-
this.labelsById = new Map();
|
|
96
|
-
this.entries = [...entries];
|
|
97
|
-
for (const entry of this.entries)
|
|
98
|
-
this.applyProjection(entry);
|
|
99
|
-
}
|
|
100
|
-
getLabel(id) {
|
|
101
|
-
return this.labelsById.get(id);
|
|
102
|
-
}
|
|
103
|
-
getSessionName() {
|
|
104
|
-
for (let i = this.entries.length - 1; i >= 0; i--) {
|
|
105
|
-
const entry = this.entries[i];
|
|
106
|
-
if (entry.type === "session_info")
|
|
107
|
-
return entry.name?.trim() || undefined;
|
|
108
|
-
}
|
|
109
|
-
return undefined;
|
|
110
|
-
}
|
|
111
|
-
getSessionStats() {
|
|
112
|
-
let messageCount = 0;
|
|
113
|
-
let cachedTokens = 0;
|
|
114
|
-
let uncachedTokens = 0;
|
|
115
|
-
let totalTokens = 0;
|
|
116
|
-
let costTotal = 0;
|
|
117
|
-
for (const entry of this.entries) {
|
|
118
|
-
if (entry.type === "message")
|
|
119
|
-
messageCount += 1;
|
|
120
|
-
const usage = entry.type === "message"
|
|
121
|
-
? entry.message.role === "assistant"
|
|
122
|
-
? entry.message.usage
|
|
123
|
-
: undefined
|
|
124
|
-
: entry.type === "compaction" || entry.type === "branch_summary"
|
|
125
|
-
? entry.usage
|
|
126
|
-
: undefined;
|
|
127
|
-
if (!usage ||
|
|
128
|
-
typeof usage.input !== "number" ||
|
|
129
|
-
typeof usage.output !== "number" ||
|
|
130
|
-
typeof usage.cacheRead !== "number" ||
|
|
131
|
-
typeof usage.cacheWrite !== "number" ||
|
|
132
|
-
typeof usage.cost?.total !== "number")
|
|
133
|
-
continue;
|
|
134
|
-
cachedTokens += usage.cacheRead;
|
|
135
|
-
uncachedTokens += usage.input + usage.cacheWrite;
|
|
136
|
-
totalTokens += usage.input + usage.output + usage.cacheRead + usage.cacheWrite;
|
|
137
|
-
costTotal += usage.cost.total;
|
|
69
|
+
for (let index = keys.length - 1; index >= 0; index--) {
|
|
70
|
+
const descriptor = Object.getOwnPropertyDescriptor(candidate, keys[index]);
|
|
71
|
+
if (!("value" in descriptor))
|
|
72
|
+
invalidPayload("contains an accessor");
|
|
73
|
+
stack.push({ value: descriptor.value });
|
|
138
74
|
}
|
|
139
|
-
return { messageCount, cachedTokens, uncachedTokens, totalTokens, costTotal };
|
|
140
|
-
}
|
|
141
|
-
applyProjection(entry) {
|
|
142
|
-
if (entry.type !== "label")
|
|
143
|
-
return;
|
|
144
|
-
const label = entry.label?.trim();
|
|
145
|
-
if (label)
|
|
146
|
-
this.labelsById.set(entry.targetId, label);
|
|
147
|
-
else
|
|
148
|
-
this.labelsById.delete(entry.targetId);
|
|
149
75
|
}
|
|
150
76
|
}
|
|
151
|
-
class
|
|
152
|
-
constructor(
|
|
153
|
-
this.
|
|
154
|
-
this.
|
|
155
|
-
this.reader = reader;
|
|
156
|
-
this.metadata = reader.metadata;
|
|
157
|
-
this.leafId = leafId;
|
|
158
|
-
this.contextBuildOptions = contextBuildOptions;
|
|
77
|
+
export class Session {
|
|
78
|
+
constructor(storage, options = {}) {
|
|
79
|
+
this.storage = storage;
|
|
80
|
+
this.idGenerator = options.idGenerator ?? { next: () => uuidv7() };
|
|
159
81
|
}
|
|
160
82
|
async getMetadata() {
|
|
161
|
-
return this.
|
|
83
|
+
return this.storage.getMetadata();
|
|
84
|
+
}
|
|
85
|
+
view(lane) {
|
|
86
|
+
if (lane === "main")
|
|
87
|
+
return this;
|
|
88
|
+
return {
|
|
89
|
+
getLeafId: () => this.getLeafIdForLane(lane),
|
|
90
|
+
getEntry: (id) => this.getEntry(id),
|
|
91
|
+
getStats: () => this.getStats(),
|
|
92
|
+
getName: () => this.getName(),
|
|
93
|
+
setName: (name) => this.setName(name),
|
|
94
|
+
getLabel: (targetId) => this.getLabel(targetId),
|
|
95
|
+
setLabel: (targetId, label) => this.setLabel(targetId, label),
|
|
96
|
+
findEntries: (query) => this.queryEntries(query),
|
|
97
|
+
findEntry: async (query = {}) => (await this.queryEntries(query, 1))[0],
|
|
98
|
+
findEntriesOnBranch: (query) => this.queryBranchEntries(lane, query),
|
|
99
|
+
findEntryOnBranch: async (query = {}) => (await this.queryBranchEntries(lane, query, 1))[0],
|
|
100
|
+
appendMessage: (message) => this.appendMessageToLane(lane, message),
|
|
101
|
+
appendCustomEntry: (customType, data) => this.appendCustomEntryToLane(lane, customType, data),
|
|
102
|
+
};
|
|
162
103
|
}
|
|
163
104
|
async getLeafId() {
|
|
164
|
-
return this.
|
|
105
|
+
return this.getLeafIdForLane("main");
|
|
165
106
|
}
|
|
166
107
|
async getEntry(id) {
|
|
167
|
-
return this.
|
|
108
|
+
return this.storage.getEntry(id);
|
|
168
109
|
}
|
|
169
|
-
async
|
|
170
|
-
return
|
|
110
|
+
async getStats() {
|
|
111
|
+
return this.storage.getStats();
|
|
171
112
|
}
|
|
172
|
-
async
|
|
173
|
-
return
|
|
113
|
+
async getName() {
|
|
114
|
+
return this.storage.getName();
|
|
174
115
|
}
|
|
175
|
-
async
|
|
176
|
-
|
|
116
|
+
async setName(name) {
|
|
117
|
+
await this.storage.setName(name);
|
|
177
118
|
}
|
|
178
|
-
async
|
|
179
|
-
return
|
|
119
|
+
async getLabel(targetId) {
|
|
120
|
+
return this.storage.getLabel(targetId);
|
|
180
121
|
}
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
entryTransforms: [...(this.contextBuildOptions.entryTransforms ?? []), ...(options.entryTransforms ?? [])],
|
|
184
|
-
entryProjectors: {
|
|
185
|
-
...(this.contextBuildOptions.entryProjectors ?? {}),
|
|
186
|
-
...(options.entryProjectors ?? {}),
|
|
187
|
-
},
|
|
188
|
-
};
|
|
122
|
+
async setLabel(targetId, label) {
|
|
123
|
+
await this.storage.setLabel(targetId, label);
|
|
189
124
|
}
|
|
190
|
-
async
|
|
191
|
-
return
|
|
125
|
+
async findEntries(query) {
|
|
126
|
+
return this.queryEntries(query);
|
|
192
127
|
}
|
|
193
|
-
async
|
|
194
|
-
return (await this.
|
|
128
|
+
async findEntry(query = {}) {
|
|
129
|
+
return (await this.queryEntries(query, 1))[0];
|
|
195
130
|
}
|
|
196
|
-
async
|
|
197
|
-
return
|
|
131
|
+
async findEntriesOnBranch(query) {
|
|
132
|
+
return this.queryBranchEntries("main", query);
|
|
198
133
|
}
|
|
199
|
-
async
|
|
200
|
-
|
|
201
|
-
return this.hydratedStatePromise;
|
|
202
|
-
}
|
|
203
|
-
async createEntryId() {
|
|
204
|
-
for (let i = 0; i < 100; i++) {
|
|
205
|
-
const id = uuidv7().slice(-8);
|
|
206
|
-
if (!(await this.getEntry(id)))
|
|
207
|
-
return id;
|
|
208
|
-
}
|
|
209
|
-
return uuidv7();
|
|
210
|
-
}
|
|
211
|
-
enqueueAppend(createEntry) {
|
|
212
|
-
const operation = this.appendTail.then(async () => {
|
|
213
|
-
const entry = createEntry({
|
|
214
|
-
id: await this.createEntryId(),
|
|
215
|
-
parentId: this.leafId,
|
|
216
|
-
timestamp: new Date().toISOString(),
|
|
217
|
-
});
|
|
218
|
-
await this.store.appendEntry(this.metadata, entry);
|
|
219
|
-
this.leafId = entry.type === "leaf" ? entry.targetId : entry.id;
|
|
220
|
-
this.hydratedStatePromise = undefined;
|
|
221
|
-
return entry;
|
|
222
|
-
});
|
|
223
|
-
this.appendTail = operation.then(() => undefined, () => undefined);
|
|
224
|
-
return operation;
|
|
225
|
-
}
|
|
226
|
-
async setLeafId(leafId) {
|
|
227
|
-
if (leafId !== null && !(await this.getEntry(leafId))) {
|
|
228
|
-
throw new SessionError("not_found", `Entry ${leafId} not found`);
|
|
229
|
-
}
|
|
230
|
-
return this.enqueueAppend((base) => {
|
|
231
|
-
return { ...base, type: "leaf", targetId: leafId };
|
|
232
|
-
});
|
|
233
|
-
}
|
|
234
|
-
async appendTypedEntry(createEntry) {
|
|
235
|
-
return (await this.enqueueAppend(createEntry)).id;
|
|
134
|
+
async findEntryOnBranch(query = {}) {
|
|
135
|
+
return (await this.queryBranchEntries("main", query, 1))[0];
|
|
236
136
|
}
|
|
237
137
|
async appendMessage(message) {
|
|
238
|
-
return this.
|
|
239
|
-
...base,
|
|
240
|
-
type: "message",
|
|
241
|
-
message,
|
|
242
|
-
}));
|
|
243
|
-
}
|
|
244
|
-
async appendThinkingLevelChange(thinkingLevel) {
|
|
245
|
-
return this.appendTypedEntry((base) => ({
|
|
246
|
-
...base,
|
|
247
|
-
type: "thinking_level_change",
|
|
248
|
-
thinkingLevel,
|
|
249
|
-
}));
|
|
250
|
-
}
|
|
251
|
-
async appendModelChange(provider, modelId) {
|
|
252
|
-
return this.appendTypedEntry((base) => ({
|
|
253
|
-
...base,
|
|
254
|
-
type: "model_change",
|
|
255
|
-
provider,
|
|
256
|
-
modelId,
|
|
257
|
-
}));
|
|
258
|
-
}
|
|
259
|
-
async appendActiveToolsChange(activeToolNames) {
|
|
260
|
-
return this.appendTypedEntry((base) => ({
|
|
261
|
-
...base,
|
|
262
|
-
type: "active_tools_change",
|
|
263
|
-
activeToolNames: [...activeToolNames],
|
|
264
|
-
}));
|
|
265
|
-
}
|
|
266
|
-
async appendCompaction(summary, firstKeptEntryId, tokensBefore, details, fromHook, usage, retainedTail) {
|
|
267
|
-
return this.appendTypedEntry((base) => ({
|
|
268
|
-
...base,
|
|
269
|
-
type: "compaction",
|
|
270
|
-
summary,
|
|
271
|
-
firstKeptEntryId,
|
|
272
|
-
tokensBefore,
|
|
273
|
-
retainedTail,
|
|
274
|
-
details,
|
|
275
|
-
usage,
|
|
276
|
-
fromHook,
|
|
277
|
-
}));
|
|
138
|
+
return this.appendMessageToLane("main", message);
|
|
278
139
|
}
|
|
279
140
|
async appendCustomEntry(customType, data) {
|
|
280
|
-
return this.
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
}
|
|
297
|
-
async
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
141
|
+
return this.appendCustomEntryToLane("main", customType, data);
|
|
142
|
+
}
|
|
143
|
+
async getLanes() {
|
|
144
|
+
return this.storage.getLanes();
|
|
145
|
+
}
|
|
146
|
+
async createLane(lane, at) {
|
|
147
|
+
await this.storage.createLane(lane, at);
|
|
148
|
+
}
|
|
149
|
+
async moveLane(lane, to) {
|
|
150
|
+
await this.storage.moveLane(lane, to);
|
|
151
|
+
}
|
|
152
|
+
async appendEntry(entry, lane) {
|
|
153
|
+
return this.commitEntry(entry, lane);
|
|
154
|
+
}
|
|
155
|
+
async appendRecord(record) {
|
|
156
|
+
return this.commitRecord(record);
|
|
157
|
+
}
|
|
158
|
+
async findRecords(query) {
|
|
159
|
+
return this.queryRecords(query);
|
|
160
|
+
}
|
|
161
|
+
async findOpenOperations(lane, options) {
|
|
162
|
+
assertValidLimit(options?.limit);
|
|
163
|
+
return this.storage.findOpenOperations(lane, options);
|
|
164
|
+
}
|
|
165
|
+
async getLog(options) {
|
|
166
|
+
return this.queryLog(options);
|
|
167
|
+
}
|
|
168
|
+
async getLeafIdForLane(lane) {
|
|
169
|
+
const pointer = (await this.getLanes()).find((candidate) => candidate.lane === lane);
|
|
170
|
+
if (!pointer)
|
|
171
|
+
throw new SessionError("invalid_lane", `Lane not found: ${lane}`);
|
|
172
|
+
return pointer.leafId;
|
|
173
|
+
}
|
|
174
|
+
async queryEntries(query = {}, resultLimit = query.limit) {
|
|
175
|
+
assertValidLimit(query.limit);
|
|
176
|
+
assertValidCursor(query.cursor?.afterSeq);
|
|
177
|
+
return this.storage.findEntries(resultLimit === query.limit ? query : { ...query, limit: resultLimit });
|
|
178
|
+
}
|
|
179
|
+
async queryBranchEntries(lane, query = {}, resultLimit = query.limit) {
|
|
180
|
+
assertValidLimit(query.limit);
|
|
181
|
+
assertValidCursor(query.cursor?.afterSeq);
|
|
182
|
+
const start = query.start ?? (await this.getLeafIdForLane(lane));
|
|
183
|
+
if (start === null)
|
|
184
|
+
return [];
|
|
185
|
+
const storageQuery = resultLimit === query.limit ? query : { ...query, limit: resultLimit };
|
|
186
|
+
return this.storage.findEntriesOnBranch({ ...storageQuery, start });
|
|
187
|
+
}
|
|
188
|
+
async queryRecords(query = {}) {
|
|
189
|
+
assertValidLimit(query.limit);
|
|
190
|
+
assertValidCursor(query.afterSeq);
|
|
191
|
+
if (query.operationKind !== undefined && query.type !== "operation_started") {
|
|
192
|
+
throw new SessionError("invalid_query", 'operationKind requires type "operation_started"');
|
|
319
193
|
}
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
194
|
+
return this.storage.findRecords(query);
|
|
195
|
+
}
|
|
196
|
+
async queryLog(options = {}) {
|
|
197
|
+
assertValidLimit(options.limit);
|
|
198
|
+
assertValidCursor(options.afterSeq);
|
|
199
|
+
return this.storage.getLog(options);
|
|
200
|
+
}
|
|
201
|
+
async appendMessageToLane(lane, message) {
|
|
202
|
+
const entry = await this.commitEntry({ type: "message", id: this.idGenerator.next(), message }, lane);
|
|
203
|
+
return entry.id;
|
|
204
|
+
}
|
|
205
|
+
async appendCustomEntryToLane(lane, customType, data) {
|
|
206
|
+
const entry = await this.commitEntry(data === undefined
|
|
207
|
+
? { type: "custom", id: this.idGenerator.next(), customType }
|
|
208
|
+
: { type: "custom", id: this.idGenerator.next(), customType, data }, lane);
|
|
209
|
+
return entry.id;
|
|
210
|
+
}
|
|
211
|
+
async commitEntry(entry, lane) {
|
|
212
|
+
assertJsonSerializable(entry);
|
|
213
|
+
return this.storage.appendEntry(entry, lane);
|
|
214
|
+
}
|
|
215
|
+
async commitRecord(record) {
|
|
216
|
+
assertJsonSerializable(record);
|
|
217
|
+
return this.storage.appendRecord(record);
|
|
332
218
|
}
|
|
333
|
-
}
|
|
334
|
-
/** @internal Construct sessions only through SessionRepository. */
|
|
335
|
-
export async function createSessionFromReader(store, reader, contextBuildOptions = {}) {
|
|
336
|
-
return new StoreSession(store, reader, (await reader.readHead()).leafId, contextBuildOptions);
|
|
337
219
|
}
|
|
338
220
|
//# sourceMappingURL=session.js.map
|