dsh-plugin-sessiongraph-service 0.1.21 → 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/lib/index.d.ts +3 -2
- package/lib/index.js +2 -1
- package/lib/panel.d.ts +26 -0
- package/lib/panel.js +26 -0
- package/lib/schema.d.ts +5 -1
- package/lib/schema.js +6 -1
- package/lib/types.d.ts +176 -6
- package/lib/types.js +20 -2
- package/package.json +1 -1
package/lib/index.d.ts
CHANGED
|
@@ -19,10 +19,11 @@ import type { SessiongraphIndexer, SessiongraphIndexOptions, SessiongraphIndexRe
|
|
|
19
19
|
export { assertNever } from './assert.ts';
|
|
20
20
|
export { SessiongraphIndexerId, SessiongraphSessionId, SessiongraphStoreId } from './brand.ts';
|
|
21
21
|
export { ENTRY_FTS_TABLE, ENTRY_TABLE, INDEX_RELATIVE_PATH, META_DISCOVERED, META_FAILED, META_INDEXED_AT, META_SCHEMA_VERSION, SCHEMA_STATEMENTS, SCHEMA_VERSION, SESSION_TABLE, } from './schema.ts';
|
|
22
|
+
export { PANEL_CODEX_SYNC_KEY, PANEL_FILE_NAME } from './panel.ts';
|
|
22
23
|
export { highlightTerms, isCjk, matchExpression, tokenize } from './tokenize.ts';
|
|
23
24
|
export { SessiongraphError } from './types.ts';
|
|
24
|
-
export type { SessiongraphEntry, SessiongraphEntryKind, SessiongraphErrorCode, SessiongraphHit, SessiongraphIndexer, SessiongraphIndexOptions, SessiongraphIndexReport, SessiongraphOperation, SessiongraphRequest, SessiongraphRequestBase, SessiongraphResult, SessiongraphResultFor, SessiongraphSearchRequest, SessiongraphSearchResult, SessiongraphService, SessiongraphSessionRequest, SessiongraphSessionResult, SessiongraphSessionSummary, SessiongraphStatusRequest, SessiongraphStatusResult, SessiongraphStoreProvider, SessiongraphTimelineRequest, SessiongraphTimelineResult, SessiongraphWorkspaceStat, SessiongraphWorkspacesRequest, SessiongraphWorkspacesResult, } from './types.ts';
|
|
25
|
-
export { SESSIONGRAPH_ENTRY_KINDS, SESSIONGRAPH_OPERATIONS } from './types.ts';
|
|
25
|
+
export type { SessiongraphEntry, SessiongraphEntryKind, SessiongraphErrorCode, SessiongraphEventRequest, SessiongraphEventResult, SessiongraphEventTraceResult, SessiongraphHit, SessiongraphIndexer, SessiongraphIndexOptions, SessiongraphIndexReport, SessiongraphOperation, SessiongraphRawEvent, SessiongraphRawEventSummary, SessiongraphRequest, SessiongraphRequestBase, SessiongraphResult, SessiongraphResultFor, SessiongraphSearchRequest, SessiongraphSearchResult, SessiongraphService, SessiongraphSessionRequest, SessiongraphSessionResult, SessiongraphSessionSummary, SessiongraphSessionTraceResult, SessiongraphSource, SessiongraphStatusRequest, SessiongraphStatusResult, SessiongraphStoreProvider, SessiongraphTimelineRequest, SessiongraphTimelineResult, SessiongraphTraceNode, SessiongraphTraceRequest, SessiongraphTraceResult, SessiongraphWorkspaceStat, SessiongraphWorkspacesRequest, SessiongraphWorkspacesResult, } from './types.ts';
|
|
26
|
+
export { SESSIONGRAPH_ENTRY_KINDS, SESSIONGRAPH_OPERATIONS, SESSIONGRAPH_SOURCES } from './types.ts';
|
|
26
27
|
/**
|
|
27
28
|
* `ctx.sessiongraph`. Holds the store and indexer reservations; selection reads them per call so a
|
|
28
29
|
* provider that unloads mid-session stops serving without leaving a stale route behind.
|
package/lib/index.js
CHANGED
|
@@ -21,9 +21,10 @@ import { SessiongraphError } from "./types.js";
|
|
|
21
21
|
export { assertNever } from "./assert.js";
|
|
22
22
|
export { SessiongraphIndexerId, SessiongraphSessionId, SessiongraphStoreId } from "./brand.js";
|
|
23
23
|
export { ENTRY_FTS_TABLE, ENTRY_TABLE, INDEX_RELATIVE_PATH, META_DISCOVERED, META_FAILED, META_INDEXED_AT, META_SCHEMA_VERSION, SCHEMA_STATEMENTS, SCHEMA_VERSION, SESSION_TABLE, } from "./schema.js";
|
|
24
|
+
export { PANEL_CODEX_SYNC_KEY, PANEL_FILE_NAME } from "./panel.js";
|
|
24
25
|
export { highlightTerms, isCjk, matchExpression, tokenize } from "./tokenize.js";
|
|
25
26
|
export { SessiongraphError } from "./types.js";
|
|
26
|
-
export { SESSIONGRAPH_ENTRY_KINDS, SESSIONGRAPH_OPERATIONS } from "./types.js";
|
|
27
|
+
export { SESSIONGRAPH_ENTRY_KINDS, SESSIONGRAPH_OPERATIONS, SESSIONGRAPH_SOURCES } from "./types.js";
|
|
27
28
|
/**
|
|
28
29
|
* `ctx.sessiongraph`. Holds the store and indexer reservations; selection reads them per call so a
|
|
29
30
|
* provider that unloads mid-session stops serving without leaving a stale route behind.
|
package/lib/panel.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one file the settings panel and the indexer both know about.
|
|
3
|
+
*
|
|
4
|
+
* `panel.json` lives inside an index root and holds choices a human made in the settings page. It is
|
|
5
|
+
* **not** an index artifact: nothing in it describes indexed data, it is rewritten whole on every
|
|
6
|
+
* save, and a missing or unreadable file means "use the configured value" rather than an error — a
|
|
7
|
+
* broken panel must never stop an index run.
|
|
8
|
+
*
|
|
9
|
+
* Two packages read it for different members, which is why the name lives here rather than in either
|
|
10
|
+
* of them: `tool` owns the HTTP surface and writes the document, while `sessions` reads
|
|
11
|
+
* `codexSync` on every run because that choice decides whether Codex history is part of the corpus.
|
|
12
|
+
* A second spelling of the filename would let the panel save a choice the indexer never sees.
|
|
13
|
+
* @module dsh-plugin-sessiongraph-service/panel
|
|
14
|
+
*/
|
|
15
|
+
/** Name of the settings document inside an index root. */
|
|
16
|
+
export declare const PANEL_FILE_NAME = "panel.json";
|
|
17
|
+
/**
|
|
18
|
+
* The member of `panel.json` that decides whether Codex history is indexed.
|
|
19
|
+
*
|
|
20
|
+
* Absent means "whatever the plugin configuration says": a user who never opened the panel keeps the
|
|
21
|
+
* configured default, and only an explicit save stores a value. Deliberately a bare optional boolean
|
|
22
|
+
* rather than a tri-state — the configuration already owns "default", so the file only ever records
|
|
23
|
+
* a human's deviation from it.
|
|
24
|
+
*/
|
|
25
|
+
export declare const PANEL_CODEX_SYNC_KEY = "codexSync";
|
|
26
|
+
//# sourceMappingURL=panel.d.ts.map
|
package/lib/panel.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one file the settings panel and the indexer both know about.
|
|
3
|
+
*
|
|
4
|
+
* `panel.json` lives inside an index root and holds choices a human made in the settings page. It is
|
|
5
|
+
* **not** an index artifact: nothing in it describes indexed data, it is rewritten whole on every
|
|
6
|
+
* save, and a missing or unreadable file means "use the configured value" rather than an error — a
|
|
7
|
+
* broken panel must never stop an index run.
|
|
8
|
+
*
|
|
9
|
+
* Two packages read it for different members, which is why the name lives here rather than in either
|
|
10
|
+
* of them: `tool` owns the HTTP surface and writes the document, while `sessions` reads
|
|
11
|
+
* `codexSync` on every run because that choice decides whether Codex history is part of the corpus.
|
|
12
|
+
* A second spelling of the filename would let the panel save a choice the indexer never sees.
|
|
13
|
+
* @module dsh-plugin-sessiongraph-service/panel
|
|
14
|
+
*/
|
|
15
|
+
/** Name of the settings document inside an index root. */
|
|
16
|
+
export const PANEL_FILE_NAME = 'panel.json';
|
|
17
|
+
/**
|
|
18
|
+
* The member of `panel.json` that decides whether Codex history is indexed.
|
|
19
|
+
*
|
|
20
|
+
* Absent means "whatever the plugin configuration says": a user who never opened the panel keeps the
|
|
21
|
+
* configured default, and only an explicit save stores a value. Deliberately a bare optional boolean
|
|
22
|
+
* rather than a tri-state — the configuration already owns "default", so the file only ever records
|
|
23
|
+
* a human's deviation from it.
|
|
24
|
+
*/
|
|
25
|
+
export const PANEL_CODEX_SYNC_KEY = 'codexSync';
|
|
26
|
+
//# sourceMappingURL=panel.js.map
|
package/lib/schema.d.ts
CHANGED
|
@@ -14,8 +14,12 @@
|
|
|
14
14
|
* v2 stores the FTS index contentless (`content=''`): FTS5's default build keeps a copy of every
|
|
15
15
|
* indexed column in a `_content` shadow table, which on a real corpus was 67MB of a 174MB file
|
|
16
16
|
* holding a token stream that can always be recomputed from `entry.text`.
|
|
17
|
+
*
|
|
18
|
+
* v3 records which harness wrote a session (`session.source`). The first version indexed only DSH's
|
|
19
|
+
* own logs, so the column is absent rather than defaulted; a v3 row carries `'dsh'` or `'codex'` and
|
|
20
|
+
* a store that cannot name the origin refuses the file instead of labelling every hit "dsh".
|
|
17
21
|
*/
|
|
18
|
-
export declare const SCHEMA_VERSION =
|
|
22
|
+
export declare const SCHEMA_VERSION = 3;
|
|
19
23
|
/** Relative path of the index file inside an index root. */
|
|
20
24
|
export declare const INDEX_RELATIVE_PATH = "index.db";
|
|
21
25
|
/** One session, keyed by its harness session id. */
|
package/lib/schema.js
CHANGED
|
@@ -14,8 +14,12 @@
|
|
|
14
14
|
* v2 stores the FTS index contentless (`content=''`): FTS5's default build keeps a copy of every
|
|
15
15
|
* indexed column in a `_content` shadow table, which on a real corpus was 67MB of a 174MB file
|
|
16
16
|
* holding a token stream that can always be recomputed from `entry.text`.
|
|
17
|
+
*
|
|
18
|
+
* v3 records which harness wrote a session (`session.source`). The first version indexed only DSH's
|
|
19
|
+
* own logs, so the column is absent rather than defaulted; a v3 row carries `'dsh'` or `'codex'` and
|
|
20
|
+
* a store that cannot name the origin refuses the file instead of labelling every hit "dsh".
|
|
17
21
|
*/
|
|
18
|
-
export const SCHEMA_VERSION =
|
|
22
|
+
export const SCHEMA_VERSION = 3;
|
|
19
23
|
/** Relative path of the index file inside an index root. */
|
|
20
24
|
export const INDEX_RELATIVE_PATH = 'index.db';
|
|
21
25
|
/** One session, keyed by its harness session id. */
|
|
@@ -43,6 +47,7 @@ export const SCHEMA_STATEMENTS = [
|
|
|
43
47
|
)`,
|
|
44
48
|
`CREATE TABLE IF NOT EXISTS ${SESSION_TABLE} (
|
|
45
49
|
id TEXT PRIMARY KEY,
|
|
50
|
+
source TEXT NOT NULL,
|
|
46
51
|
workspace TEXT NOT NULL,
|
|
47
52
|
title TEXT,
|
|
48
53
|
created_at INTEGER NOT NULL,
|
package/lib/types.d.ts
CHANGED
|
@@ -9,8 +9,16 @@
|
|
|
9
9
|
* @module dsh-plugin-sessiongraph-service/types
|
|
10
10
|
*/
|
|
11
11
|
import type { SessiongraphIndexerId, SessiongraphSessionId, SessiongraphStoreId } from './brand.ts';
|
|
12
|
-
/**
|
|
13
|
-
|
|
12
|
+
/**
|
|
13
|
+
* Every query operation the seam answers.
|
|
14
|
+
*
|
|
15
|
+
* `event` and `trace` were added when the model-facing surface collapsed from two tools into one:
|
|
16
|
+
* the built-in session tools could read a single unabridged event and follow replacement/citation
|
|
17
|
+
* relationships, and a replacement that dropped those answers would be a downgrade rather than a
|
|
18
|
+
* swap. An index run is deliberately **not** here — it writes, so the tool routes it through
|
|
19
|
+
* `Sessiongraph.index()` instead of pretending a query provider can build an index.
|
|
20
|
+
*/
|
|
21
|
+
export declare const SESSIONGRAPH_OPERATIONS: readonly ["search", "session", "event", "trace", "timeline", "workspaces", "status"];
|
|
14
22
|
/** One query operation. */
|
|
15
23
|
export type SessiongraphOperation = (typeof SESSIONGRAPH_OPERATIONS)[number];
|
|
16
24
|
/**
|
|
@@ -23,6 +31,18 @@ export type SessiongraphOperation = (typeof SESSIONGRAPH_OPERATIONS)[number];
|
|
|
23
31
|
export declare const SESSIONGRAPH_ENTRY_KINDS: readonly ["user", "assistant", "tool", "title"];
|
|
24
32
|
/** One entry kind. */
|
|
25
33
|
export type SessiongraphEntryKind = (typeof SESSIONGRAPH_ENTRY_KINDS)[number];
|
|
34
|
+
/**
|
|
35
|
+
* Which agent harness wrote a session log.
|
|
36
|
+
*
|
|
37
|
+
* `dsh` is this host's own store under `~/.dsh/sessions`; `codex` is OpenAI Codex's rollout log
|
|
38
|
+
* under `~/.codex`. The value is stored per session, not per index, because one index deliberately
|
|
39
|
+
* holds both and a hit that cannot say where it came from makes a caller read the wrong file. It is
|
|
40
|
+
* a closed set rather than a free-form string: an unknown origin is a bug in the indexer, and
|
|
41
|
+
* widening this list is how a new harness becomes queryable.
|
|
42
|
+
*/
|
|
43
|
+
export declare const SESSIONGRAPH_SOURCES: readonly ["dsh", "codex"];
|
|
44
|
+
/** One session source. */
|
|
45
|
+
export type SessiongraphSource = (typeof SESSIONGRAPH_SOURCES)[number];
|
|
26
46
|
/** Error codes the seam raises, so a consumer can distinguish "no index" from "bad request". */
|
|
27
47
|
export type SessiongraphErrorCode = 'SESSIONGRAPH_UNAVAILABLE' | 'SESSIONGRAPH_CONFLICT' | 'SESSIONGRAPH_INVALID_PROVIDER' | 'SESSIONGRAPH_INVALID_REQUEST' | 'SESSIONGRAPH_NOT_FOUND' | 'SESSIONGRAPH_CORRUPT' | 'SESSIONGRAPH_IO';
|
|
28
48
|
/** The single error type crossing the seam. */
|
|
@@ -46,12 +66,36 @@ export interface SessiongraphSearchRequest extends SessiongraphRequestBase {
|
|
|
46
66
|
query: string;
|
|
47
67
|
/** Restrict to one workspace (exact `cwd`), or a path prefix when it ends without a trailing slash. */
|
|
48
68
|
workspace?: string;
|
|
69
|
+
/**
|
|
70
|
+
* Restrict to sessions one harness wrote.
|
|
71
|
+
*
|
|
72
|
+
* An index holds DSH's own logs and Codex's rollout logs side by side, and the two answer different
|
|
73
|
+
* questions: "what did I ask DSH about this repo" and "what did I ask Codex about it". Absent means
|
|
74
|
+
* every source, which is the right default for a cross-harness sweep.
|
|
75
|
+
*/
|
|
76
|
+
source?: SessiongraphSource;
|
|
49
77
|
/** Only entries at or after this epoch-millisecond timestamp. */
|
|
50
78
|
after?: number;
|
|
51
79
|
/** Only entries at or before this epoch-millisecond timestamp. */
|
|
52
80
|
before?: number;
|
|
53
81
|
/** Restrict to these entry kinds. Absent means every kind. */
|
|
54
82
|
kinds?: readonly SessiongraphEntryKind[];
|
|
83
|
+
/**
|
|
84
|
+
* Restrict the search to one session: a full id, or a prefix long enough to identify exactly one.
|
|
85
|
+
*
|
|
86
|
+
* A prefix that matches several sessions raises `SESSIONGRAPH_INVALID_REQUEST` rather than
|
|
87
|
+
* guessing — a search silently answered from the wrong conversation is worse than a refusal. This
|
|
88
|
+
* is what replaces the built-in `session_event_search`, which needed its own tool for it.
|
|
89
|
+
*/
|
|
90
|
+
sessionId?: string;
|
|
91
|
+
/**
|
|
92
|
+
* Return at most one hit per session (the strongest), default `true`.
|
|
93
|
+
*
|
|
94
|
+
* The built-in cross-session search answered one hit per session, and a caller paging through a
|
|
95
|
+
* verbatim log usually wants breadth across conversations, not ten matches from one. Callers that
|
|
96
|
+
* want every entry (a single-session sweep) turn it off.
|
|
97
|
+
*/
|
|
98
|
+
dedupeBySession?: boolean;
|
|
55
99
|
/** Maximum hits to return. */
|
|
56
100
|
limit: number;
|
|
57
101
|
/** Hits to skip, for paging. */
|
|
@@ -60,6 +104,8 @@ export interface SessiongraphSearchRequest extends SessiongraphRequestBase {
|
|
|
60
104
|
/** One matched entry, with enough context to recognize it without a second query. */
|
|
61
105
|
export interface SessiongraphHit {
|
|
62
106
|
sessionId: SessiongraphSessionId;
|
|
107
|
+
/** Which harness wrote the session this hit belongs to. */
|
|
108
|
+
source: SessiongraphSource;
|
|
63
109
|
/** Session title, when the session ever produced one. */
|
|
64
110
|
title: string | undefined;
|
|
65
111
|
/** The session's working directory. */
|
|
@@ -81,7 +127,13 @@ export interface SessiongraphHit {
|
|
|
81
127
|
export interface SessiongraphSearchResult {
|
|
82
128
|
operation: 'search';
|
|
83
129
|
hits: SessiongraphHit[];
|
|
84
|
-
/**
|
|
130
|
+
/**
|
|
131
|
+
* How many results matched before `limit`/`offset` — counted in the same unit the hits use.
|
|
132
|
+
*
|
|
133
|
+
* With `dedupeBySession` on (the default) that is **sessions**, because the hits are one per
|
|
134
|
+
* session; counting entries there would make `truncated` permanently true and paging incoherent.
|
|
135
|
+
* With it off, it is entries.
|
|
136
|
+
*/
|
|
85
137
|
total: number;
|
|
86
138
|
/** True when `total` exceeded `limit + offset`, or when a snippet was clipped. */
|
|
87
139
|
truncated: boolean;
|
|
@@ -89,6 +141,8 @@ export interface SessiongraphSearchResult {
|
|
|
89
141
|
/** A session's metadata, as the timeline and session operations report it. */
|
|
90
142
|
export interface SessiongraphSessionSummary {
|
|
91
143
|
sessionId: SessiongraphSessionId;
|
|
144
|
+
/** Which harness wrote this session's log. */
|
|
145
|
+
source: SessiongraphSource;
|
|
92
146
|
title: string | undefined;
|
|
93
147
|
workspace: string;
|
|
94
148
|
/** Epoch milliseconds of the session's first event. */
|
|
@@ -142,12 +196,16 @@ export interface SessiongraphTimelineRequest extends SessiongraphRequestBase {
|
|
|
142
196
|
operation: 'timeline';
|
|
143
197
|
/** Restrict to one workspace, or a path prefix when it ends without a trailing slash. */
|
|
144
198
|
workspace?: string;
|
|
199
|
+
/** Restrict to one harness's sessions. Absent means every source. */
|
|
200
|
+
source?: SessiongraphSource;
|
|
145
201
|
/** Only sessions whose last event is at or after this epoch-millisecond timestamp. */
|
|
146
202
|
after?: number;
|
|
147
203
|
/** Only sessions whose first event is at or before this epoch-millisecond timestamp. */
|
|
148
204
|
before?: number;
|
|
149
205
|
/** Maximum sessions to return, newest first. */
|
|
150
206
|
limit: number;
|
|
207
|
+
/** Sessions to skip, for paging; follows the timeline's newest-first order. */
|
|
208
|
+
offset?: number;
|
|
151
209
|
}
|
|
152
210
|
/** Answer to a timeline request. */
|
|
153
211
|
export interface SessiongraphTimelineResult {
|
|
@@ -159,8 +217,12 @@ export interface SessiongraphTimelineResult {
|
|
|
159
217
|
/** Enumerate the workspaces the index covers. */
|
|
160
218
|
export interface SessiongraphWorkspacesRequest extends SessiongraphRequestBase {
|
|
161
219
|
operation: 'workspaces';
|
|
220
|
+
/** Restrict the census to one harness's sessions. Absent means every source. */
|
|
221
|
+
source?: SessiongraphSource;
|
|
162
222
|
/** Maximum workspaces to return, most recently active first. */
|
|
163
223
|
limit: number;
|
|
224
|
+
/** Workspaces to skip, for paging; follows the most-recently-active-first order. */
|
|
225
|
+
offset?: number;
|
|
164
226
|
}
|
|
165
227
|
/** One workspace's coverage. */
|
|
166
228
|
export interface SessiongraphWorkspaceStat {
|
|
@@ -208,12 +270,120 @@ export interface SessiongraphStatusResult {
|
|
|
208
270
|
/** Bytes the index file occupies on disk. */
|
|
209
271
|
bytes: number;
|
|
210
272
|
}
|
|
273
|
+
/**
|
|
274
|
+
* One raw event, reduced to the fields that let a reader orient around a target.
|
|
275
|
+
*
|
|
276
|
+
* The window around an event is answered as summaries rather than full payloads: a caller asking
|
|
277
|
+
* "what came before this" wants the shape of the conversation, not megabytes of tool output.
|
|
278
|
+
*/
|
|
279
|
+
export interface SessiongraphRawEventSummary {
|
|
280
|
+
/** Event sequence number inside its session. */
|
|
281
|
+
seq: number;
|
|
282
|
+
/** Event timestamp, epoch milliseconds. */
|
|
283
|
+
time: number;
|
|
284
|
+
/** Event type as the log records it (`tool/call`, `assistant/message`, …). */
|
|
285
|
+
type: string;
|
|
286
|
+
}
|
|
287
|
+
/** One event exactly as the session log holds it, with no clipping applied. */
|
|
288
|
+
export interface SessiongraphRawEvent {
|
|
289
|
+
/** Event sequence number inside its session. */
|
|
290
|
+
seq: number;
|
|
291
|
+
/** Event timestamp, epoch milliseconds. */
|
|
292
|
+
time: number;
|
|
293
|
+
/** Event type as the log records it. */
|
|
294
|
+
type: string;
|
|
295
|
+
/**
|
|
296
|
+
* The event's own `data` payload, verbatim. Opaque to this seam on purpose: the log's event
|
|
297
|
+
* vocabulary belongs to `dsh-session`, and re-declaring it here would drift.
|
|
298
|
+
*/
|
|
299
|
+
data: unknown;
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Read one unabridged event, plus an optional window of neighbouring events.
|
|
303
|
+
*
|
|
304
|
+
* This is what replaces the built-in `session_event_read`. It reads the source log directly rather
|
|
305
|
+
* than the index, because the index stores semantic text clipped to a per-entry cap and this answer
|
|
306
|
+
* must be the original bytes.
|
|
307
|
+
*/
|
|
308
|
+
export interface SessiongraphEventRequest extends SessiongraphRequestBase {
|
|
309
|
+
operation: 'event';
|
|
310
|
+
/** Full session id, or a prefix long enough to identify exactly one session. */
|
|
311
|
+
sessionId: string;
|
|
312
|
+
/** Sequence number of the target event. */
|
|
313
|
+
seq: number;
|
|
314
|
+
/** Raw events to include immediately before the target. Omitted means none. */
|
|
315
|
+
windowBefore?: number;
|
|
316
|
+
/** Raw events to include immediately after the target. Omitted means none. */
|
|
317
|
+
windowAfter?: number;
|
|
318
|
+
}
|
|
319
|
+
/** Answer to an event request. */
|
|
320
|
+
export interface SessiongraphEventResult {
|
|
321
|
+
operation: 'event';
|
|
322
|
+
session: SessiongraphSessionSummary;
|
|
323
|
+
/** The target event, unabridged. */
|
|
324
|
+
event: SessiongraphRawEvent;
|
|
325
|
+
/** Neighbours before the target, oldest first. */
|
|
326
|
+
before: SessiongraphRawEventSummary[];
|
|
327
|
+
/** Neighbours after the target, oldest first. */
|
|
328
|
+
after: SessiongraphRawEventSummary[];
|
|
329
|
+
}
|
|
330
|
+
/** One node of a recursive descendant tree. */
|
|
331
|
+
export interface SessiongraphTraceNode {
|
|
332
|
+
session: SessiongraphSessionSummary;
|
|
333
|
+
descendants: SessiongraphTraceNode[];
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* Follow session lineage, or one event's replacement and citation relationships.
|
|
337
|
+
*
|
|
338
|
+
* `seq` selects the shape: present means "trace this event", absent means "trace this session".
|
|
339
|
+
* Both live in one operation because they share the only other input (`sessionId`) and because a
|
|
340
|
+
* second tool would cost permanent schema tokens for a question asked rarely.
|
|
341
|
+
*/
|
|
342
|
+
export interface SessiongraphTraceRequest extends SessiongraphRequestBase {
|
|
343
|
+
operation: 'trace';
|
|
344
|
+
/** Full session id, or a prefix long enough to identify exactly one session. */
|
|
345
|
+
sessionId: string;
|
|
346
|
+
/** Given → trace one event inside the session; omitted → trace the session's lineage. */
|
|
347
|
+
seq?: number;
|
|
348
|
+
/** Maximum descendant depth to walk. Omitted means the whole tree. */
|
|
349
|
+
depth?: number;
|
|
350
|
+
}
|
|
351
|
+
/** A session's ancestor chain and descendant tree. */
|
|
352
|
+
export interface SessiongraphSessionTraceResult {
|
|
353
|
+
operation: 'trace';
|
|
354
|
+
kind: 'session';
|
|
355
|
+
target: SessiongraphSessionSummary;
|
|
356
|
+
/** Ancestors, nearest first. */
|
|
357
|
+
ancestors: SessiongraphSessionSummary[];
|
|
358
|
+
descendants: SessiongraphTraceNode[];
|
|
359
|
+
/**
|
|
360
|
+
* False when the walk stopped early — a depth limit was hit, or a parent the index does not hold.
|
|
361
|
+
* A caller must be able to tell "this is the root" from "I gave up looking".
|
|
362
|
+
*/
|
|
363
|
+
complete: boolean;
|
|
364
|
+
}
|
|
365
|
+
/** One event's positional replacements and the source events it cites. */
|
|
366
|
+
export interface SessiongraphEventTraceResult {
|
|
367
|
+
operation: 'trace';
|
|
368
|
+
kind: 'event';
|
|
369
|
+
session: SessiongraphSessionSummary;
|
|
370
|
+
/** The target event, reduced to its identity. */
|
|
371
|
+
event: SessiongraphRawEventSummary;
|
|
372
|
+
/** Sequence numbers that replaced this event, following the chain outward. */
|
|
373
|
+
replacedBy: number[];
|
|
374
|
+
/** Sequence numbers this event shadowed. */
|
|
375
|
+
shadowedSeqs: number[];
|
|
376
|
+
/** Sequence numbers this event cites as sources (a tool result citing its call, for instance). */
|
|
377
|
+
sourceEventSeqs: number[];
|
|
378
|
+
}
|
|
379
|
+
/** Either trace shape, discriminated on `kind`. */
|
|
380
|
+
export type SessiongraphTraceResult = SessiongraphSessionTraceResult | SessiongraphEventTraceResult;
|
|
211
381
|
/** Every request the seam accepts, discriminated on `operation`. */
|
|
212
|
-
export type SessiongraphRequest = SessiongraphSearchRequest | SessiongraphSessionRequest | SessiongraphTimelineRequest | SessiongraphWorkspacesRequest | SessiongraphStatusRequest;
|
|
382
|
+
export type SessiongraphRequest = SessiongraphSearchRequest | SessiongraphSessionRequest | SessiongraphEventRequest | SessiongraphTraceRequest | SessiongraphTimelineRequest | SessiongraphWorkspacesRequest | SessiongraphStatusRequest;
|
|
213
383
|
/** The result type a given request produces. */
|
|
214
|
-
export type SessiongraphResultFor<R extends SessiongraphRequest> = R extends SessiongraphSearchRequest ? SessiongraphSearchResult : R extends SessiongraphSessionRequest ? SessiongraphSessionResult : R extends SessiongraphTimelineRequest ? SessiongraphTimelineResult : R extends SessiongraphWorkspacesRequest ? SessiongraphWorkspacesResult : R extends SessiongraphStatusRequest ? SessiongraphStatusResult : never;
|
|
384
|
+
export type SessiongraphResultFor<R extends SessiongraphRequest> = R extends SessiongraphSearchRequest ? SessiongraphSearchResult : R extends SessiongraphSessionRequest ? SessiongraphSessionResult : R extends SessiongraphEventRequest ? SessiongraphEventResult : R extends SessiongraphTraceRequest ? SessiongraphTraceResult : R extends SessiongraphTimelineRequest ? SessiongraphTimelineResult : R extends SessiongraphWorkspacesRequest ? SessiongraphWorkspacesResult : R extends SessiongraphStatusRequest ? SessiongraphStatusResult : never;
|
|
215
385
|
/** Every result the seam produces. */
|
|
216
|
-
export type SessiongraphResult = SessiongraphSearchResult | SessiongraphSessionResult | SessiongraphTimelineResult | SessiongraphWorkspacesResult | SessiongraphStatusResult;
|
|
386
|
+
export type SessiongraphResult = SessiongraphSearchResult | SessiongraphSessionResult | SessiongraphEventResult | SessiongraphTraceResult | SessiongraphTimelineResult | SessiongraphWorkspacesResult | SessiongraphStatusResult;
|
|
217
387
|
/**
|
|
218
388
|
* A read provider: answers queries from an index it claims.
|
|
219
389
|
*
|
package/lib/types.js
CHANGED
|
@@ -8,8 +8,16 @@
|
|
|
8
8
|
* never exposes a path to a table — only sessions, entries, and search hits.
|
|
9
9
|
* @module dsh-plugin-sessiongraph-service/types
|
|
10
10
|
*/
|
|
11
|
-
/**
|
|
12
|
-
|
|
11
|
+
/**
|
|
12
|
+
* Every query operation the seam answers.
|
|
13
|
+
*
|
|
14
|
+
* `event` and `trace` were added when the model-facing surface collapsed from two tools into one:
|
|
15
|
+
* the built-in session tools could read a single unabridged event and follow replacement/citation
|
|
16
|
+
* relationships, and a replacement that dropped those answers would be a downgrade rather than a
|
|
17
|
+
* swap. An index run is deliberately **not** here — it writes, so the tool routes it through
|
|
18
|
+
* `Sessiongraph.index()` instead of pretending a query provider can build an index.
|
|
19
|
+
*/
|
|
20
|
+
export const SESSIONGRAPH_OPERATIONS = ['search', 'session', 'event', 'trace', 'timeline', 'workspaces', 'status'];
|
|
13
21
|
/**
|
|
14
22
|
* What a searchable entry is, from the reader's point of view.
|
|
15
23
|
*
|
|
@@ -18,6 +26,16 @@ export const SESSIONGRAPH_OPERATIONS = ['search', 'session', 'timeline', 'worksp
|
|
|
18
26
|
* is a session title, kept as its own kind so a title match is recognizable in the hit list.
|
|
19
27
|
*/
|
|
20
28
|
export const SESSIONGRAPH_ENTRY_KINDS = ['user', 'assistant', 'tool', 'title'];
|
|
29
|
+
/**
|
|
30
|
+
* Which agent harness wrote a session log.
|
|
31
|
+
*
|
|
32
|
+
* `dsh` is this host's own store under `~/.dsh/sessions`; `codex` is OpenAI Codex's rollout log
|
|
33
|
+
* under `~/.codex`. The value is stored per session, not per index, because one index deliberately
|
|
34
|
+
* holds both and a hit that cannot say where it came from makes a caller read the wrong file. It is
|
|
35
|
+
* a closed set rather than a free-form string: an unknown origin is a bug in the indexer, and
|
|
36
|
+
* widening this list is how a new harness becomes queryable.
|
|
37
|
+
*/
|
|
38
|
+
export const SESSIONGRAPH_SOURCES = ['dsh', 'codex'];
|
|
21
39
|
/** The single error type crossing the seam. */
|
|
22
40
|
export class SessiongraphError extends Error {
|
|
23
41
|
code;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-plugin-sessiongraph-service",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Service definition for the DeepSeek Harness session-graph seam (ctx.sessiongraph) — a store-provider and indexer-provider registry over local conversation history, plus the normalized query vocabulary the model-facing tool speaks",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"dsh",
|