@nessielabs/daemon 0.2.1 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +1 -1
- package/dist/config/store.js +2 -0
- package/dist/sync/loop.js +7 -1
- package/dist/sync/map.js +37 -19
- package/dist/sync/scan.js +1 -0
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -7,7 +7,7 @@ const program = new Command();
|
|
|
7
7
|
program
|
|
8
8
|
.name("nessie-daemon")
|
|
9
9
|
.description("Headless Nessie ingestion daemon for Linux agent machines.")
|
|
10
|
-
.version("0.2.
|
|
10
|
+
.version("0.2.2");
|
|
11
11
|
program
|
|
12
12
|
.command("setup")
|
|
13
13
|
.description("Authenticate, select local sources, and optionally install the user systemd service.")
|
package/dist/config/store.js
CHANGED
|
@@ -22,6 +22,7 @@ export function createInitialState() {
|
|
|
22
22
|
return {
|
|
23
23
|
files: {},
|
|
24
24
|
pushedSourceRootIds: [],
|
|
25
|
+
pushedSessions: {},
|
|
25
26
|
lastSyncAt: null,
|
|
26
27
|
};
|
|
27
28
|
}
|
|
@@ -38,6 +39,7 @@ export async function readState(paths = getDaemonPaths()) {
|
|
|
38
39
|
return {
|
|
39
40
|
files: parsed.files ?? {},
|
|
40
41
|
pushedSourceRootIds: parsed.pushedSourceRootIds ?? [],
|
|
42
|
+
pushedSessions: parsed.pushedSessions ?? {},
|
|
41
43
|
lastSyncAt: parsed.lastSyncAt ?? null,
|
|
42
44
|
};
|
|
43
45
|
}
|
package/dist/sync/loop.js
CHANGED
|
@@ -13,14 +13,19 @@ export async function runSyncOnce() {
|
|
|
13
13
|
const edges = [];
|
|
14
14
|
const previouslyPushedRoots = new Set(state.pushedSourceRootIds);
|
|
15
15
|
const pushedSourceRootIds = new Set(previouslyPushedRoots);
|
|
16
|
+
const pushedSessions = { ...state.pushedSessions };
|
|
16
17
|
for (const source of config.selectedSources) {
|
|
17
18
|
const sessions = scan.sessionsBySourceId.get(source.localId) ?? [];
|
|
18
19
|
const includeRoot = !previouslyPushedRoots.has(source.localId);
|
|
19
|
-
const mapped = mapSessionsToPushItems(source, sessions, {
|
|
20
|
+
const mapped = mapSessionsToPushItems(source, sessions, {
|
|
21
|
+
includeRoot,
|
|
22
|
+
pushedSessions: state.pushedSessions,
|
|
23
|
+
});
|
|
20
24
|
nodes.push(...mapped.nodes);
|
|
21
25
|
edges.push(...mapped.edges);
|
|
22
26
|
if (includeRoot)
|
|
23
27
|
pushedSourceRootIds.add(source.localId);
|
|
28
|
+
Object.assign(pushedSessions, mapped.pushedSessions);
|
|
24
29
|
}
|
|
25
30
|
if (nodes.length > 0 || edges.length > 0) {
|
|
26
31
|
config = await pushSyncPayload(config, { nodes, edges });
|
|
@@ -28,6 +33,7 @@ export async function runSyncOnce() {
|
|
|
28
33
|
await writeState({
|
|
29
34
|
...scan.nextState,
|
|
30
35
|
pushedSourceRootIds: [...pushedSourceRootIds].sort(),
|
|
36
|
+
pushedSessions,
|
|
31
37
|
lastSyncAt: new Date().toISOString(),
|
|
32
38
|
});
|
|
33
39
|
return { nodes: nodes.length, edges: edges.length };
|
package/dist/sync/map.js
CHANGED
|
@@ -1,28 +1,42 @@
|
|
|
1
1
|
import { redactSecrets } from "../redact/secrets.js";
|
|
2
2
|
import { contentHash, stableUuidFromString } from "./ids.js";
|
|
3
3
|
export function mapSessionsToPushItems(source, sessions, options = { includeRoot: true }) {
|
|
4
|
+
const pushedSessions = options.pushedSessions ?? {};
|
|
5
|
+
const nextPushedSessions = {};
|
|
4
6
|
const nodes = options.includeRoot ? [mapRootNode(source)] : [];
|
|
5
7
|
const edges = [];
|
|
6
8
|
for (const session of sessions) {
|
|
7
9
|
const conversationId = stableUuidFromString(`${source.localId}:session:${session.id}`);
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
10
|
+
const stateKey = sessionStateKey(source, session);
|
|
11
|
+
const sessionCursor = pushedSessions[stateKey] ?? {
|
|
12
|
+
conversationPushed: false,
|
|
13
|
+
pushedMessageCount: 0,
|
|
14
|
+
};
|
|
15
|
+
if (!sessionCursor.conversationPushed) {
|
|
16
|
+
nodes.push({
|
|
17
|
+
node: {
|
|
18
|
+
id: conversationId,
|
|
19
|
+
integrationId: source.localId,
|
|
20
|
+
sourceId: session.sourceId,
|
|
21
|
+
name: redactSecrets(session.title),
|
|
22
|
+
kind: session.sourceKind === "codex" ? "codex_chat" : "claude_code_chat",
|
|
23
|
+
originalCreatedAt: session.createdAt,
|
|
24
|
+
originalUpdatedAt: session.updatedAt,
|
|
25
|
+
},
|
|
26
|
+
baseCloudUpdatedAt: null,
|
|
27
|
+
slices: [],
|
|
28
|
+
aiChatMessage: null,
|
|
29
|
+
nessieChatMessage: null,
|
|
30
|
+
});
|
|
31
|
+
edges.push(mapEdge(source.localId, conversationId, "source_of", 0));
|
|
32
|
+
}
|
|
24
33
|
const pushableMessages = session.messages.filter((message) => message.role !== "system");
|
|
25
|
-
|
|
34
|
+
nextPushedSessions[stateKey] = {
|
|
35
|
+
conversationPushed: true,
|
|
36
|
+
pushedMessageCount: pushableMessages.length,
|
|
37
|
+
};
|
|
38
|
+
pushableMessages.slice(sessionCursor.pushedMessageCount).forEach((message, offset) => {
|
|
39
|
+
const index = sessionCursor.pushedMessageCount + offset;
|
|
26
40
|
const messageId = stableUuidFromString(`${conversationId}:message:${index}`);
|
|
27
41
|
const content = redactSecrets(message.content);
|
|
28
42
|
const timestamp = message.timestamp ?? session.updatedAt;
|
|
@@ -54,7 +68,10 @@ export function mapSessionsToPushItems(source, sessions, options = { includeRoot
|
|
|
54
68
|
edges.push(mapEdge(conversationId, messageId, "contains", index));
|
|
55
69
|
});
|
|
56
70
|
}
|
|
57
|
-
return { nodes, edges };
|
|
71
|
+
return { nodes, edges, pushedSessions: nextPushedSessions };
|
|
72
|
+
}
|
|
73
|
+
export function sessionStateKey(source, session) {
|
|
74
|
+
return `${source.localId}:session:${session.id}`;
|
|
58
75
|
}
|
|
59
76
|
function mapRootNode(source) {
|
|
60
77
|
const now = new Date().toISOString();
|
|
@@ -75,9 +92,10 @@ function mapRootNode(source) {
|
|
|
75
92
|
};
|
|
76
93
|
}
|
|
77
94
|
function mapEdge(fromNodeId, toNodeId, type, sortIndex) {
|
|
95
|
+
const id = stableUuidFromString(`${fromNodeId}:${type}:${toNodeId}`);
|
|
78
96
|
return {
|
|
79
97
|
edge: {
|
|
80
|
-
id
|
|
98
|
+
id,
|
|
81
99
|
fromNodeId,
|
|
82
100
|
toNodeId,
|
|
83
101
|
type,
|
package/dist/sync/scan.js
CHANGED
|
@@ -6,6 +6,7 @@ export async function scanSelectedSources(sources, state) {
|
|
|
6
6
|
const nextState = {
|
|
7
7
|
files: { ...state.files },
|
|
8
8
|
pushedSourceRootIds: [...state.pushedSourceRootIds],
|
|
9
|
+
pushedSessions: { ...state.pushedSessions },
|
|
9
10
|
lastSyncAt: state.lastSyncAt,
|
|
10
11
|
};
|
|
11
12
|
const sessionsBySourceId = new Map();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nessielabs/daemon",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "Headless Linux ingestion daemon for Nessie agent traces.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"type": "module",
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"node": ">=20"
|
|
19
19
|
},
|
|
20
20
|
"scripts": {
|
|
21
|
-
"build": "rm -rf dist && tsc -p tsconfig.json",
|
|
21
|
+
"build": "rm -rf dist && tsc -p tsconfig.json && chmod +x dist/cli.js",
|
|
22
22
|
"check": "tsc -p tsconfig.json --noEmit",
|
|
23
23
|
"dev": "tsx src/cli.ts",
|
|
24
24
|
"test": "vitest run"
|