@harness-fe/mcp-server 3.0.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/LICENSE +21 -0
- package/README.md +145 -0
- package/dist/auth.d.ts +53 -0
- package/dist/auth.js +212 -0
- package/dist/bridge.d.ts +302 -0
- package/dist/bridge.js +1580 -0
- package/dist/cli.d.ts +18 -0
- package/dist/cli.js +277 -0
- package/dist/daemon.d.ts +98 -0
- package/dist/daemon.js +80 -0
- package/dist/dashboardApi.d.ts +40 -0
- package/dist/dashboardApi.js +142 -0
- package/dist/dashboardSpa.d.ts +18 -0
- package/dist/dashboardSpa.js +180 -0
- package/dist/dashboardUrl.d.ts +13 -0
- package/dist/dashboardUrl.js +18 -0
- package/dist/eventsHandler.d.ts +24 -0
- package/dist/eventsHandler.js +114 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +6 -0
- package/dist/mcp.d.ts +15 -0
- package/dist/mcp.js +923 -0
- package/dist/mcpHttp.d.ts +39 -0
- package/dist/mcpHttp.js +49 -0
- package/dist/openBrowser.d.ts +33 -0
- package/dist/openBrowser.js +63 -0
- package/dist/remoteBridge.d.ts +61 -0
- package/dist/remoteBridge.js +307 -0
- package/dist/replayCreate.d.ts +36 -0
- package/dist/replayCreate.js +156 -0
- package/dist/replayViewer.d.ts +20 -0
- package/dist/replayViewer.js +168 -0
- package/dist/sessionRouter.d.ts +42 -0
- package/dist/sessionRouter.js +88 -0
- package/dist/store/JsonMemoryStore.d.ts +52 -0
- package/dist/store/JsonMemoryStore.js +119 -0
- package/dist/store/JsonTaskStore.d.ts +21 -0
- package/dist/store/JsonTaskStore.js +53 -0
- package/dist/store/JsonlStore.d.ts +128 -0
- package/dist/store/JsonlStore.js +1168 -0
- package/dist/store/MemoryEventStore.d.ts +47 -0
- package/dist/store/MemoryEventStore.js +111 -0
- package/dist/store/WriteQueue.d.ts +51 -0
- package/dist/store/WriteQueue.js +142 -0
- package/dist/store/index.d.ts +6 -0
- package/dist/store/index.js +5 -0
- package/dist/store/types.d.ts +416 -0
- package/dist/store/types.js +19 -0
- package/package.json +63 -0
- package/src/auth.test.ts +90 -0
- package/src/auth.ts +248 -0
- package/src/bridge-auth.test.ts +196 -0
- package/src/bridge.test.ts +1708 -0
- package/src/bridge.ts +1804 -0
- package/src/cli.ts +315 -0
- package/src/daemon.test.ts +123 -0
- package/src/daemon.ts +161 -0
- package/src/dashboardApi.test.ts +235 -0
- package/src/dashboardApi.ts +184 -0
- package/src/dashboardSpa.test.ts +239 -0
- package/src/dashboardSpa.ts +195 -0
- package/src/dashboardUrl.test.ts +46 -0
- package/src/dashboardUrl.ts +28 -0
- package/src/eventsHandler.test.ts +247 -0
- package/src/eventsHandler.ts +136 -0
- package/src/index.ts +26 -0
- package/src/mcp.ts +1407 -0
- package/src/mcpHttp.test.ts +101 -0
- package/src/mcpHttp.ts +88 -0
- package/src/openBrowser.test.ts +103 -0
- package/src/openBrowser.ts +81 -0
- package/src/remoteBridge.test.ts +119 -0
- package/src/remoteBridge.ts +404 -0
- package/src/replay.test.ts +271 -0
- package/src/replayCreate.ts +194 -0
- package/src/replayViewer.ts +173 -0
- package/src/sessionRouter.ts +116 -0
- package/src/store/JsonMemoryStore.test.ts +175 -0
- package/src/store/JsonMemoryStore.ts +128 -0
- package/src/store/JsonTaskStore.test.ts +212 -0
- package/src/store/JsonTaskStore.ts +59 -0
- package/src/store/JsonlStore.test.ts +1538 -0
- package/src/store/JsonlStore.ts +1321 -0
- package/src/store/MemoryEventStore.test.ts +119 -0
- package/src/store/MemoryEventStore.ts +151 -0
- package/src/store/WriteQueue.ts +165 -0
- package/src/store/index.ts +29 -0
- package/src/store/types.ts +517 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JsonTaskStore — JSON-based persistence for annotation tasks.
|
|
3
|
+
*
|
|
4
|
+
* File format: {dataDir}/{sanitizeId(projectId)}/tasks.json
|
|
5
|
+
* ```json
|
|
6
|
+
* { "version": 1, "tasks": Task[] }
|
|
7
|
+
* ```
|
|
8
|
+
*
|
|
9
|
+
* Writes are atomic: write to a .tmp file then rename to the final path.
|
|
10
|
+
* On read failure (missing or corrupt file), returns an empty array.
|
|
11
|
+
* On write failure, logs the error without throwing.
|
|
12
|
+
*/
|
|
13
|
+
import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs';
|
|
14
|
+
import { join } from 'node:path';
|
|
15
|
+
import { sanitizeId } from './JsonlStore.js';
|
|
16
|
+
export class JsonTaskStore {
|
|
17
|
+
dataDir;
|
|
18
|
+
constructor(dataDir) {
|
|
19
|
+
this.dataDir = dataDir;
|
|
20
|
+
}
|
|
21
|
+
tasksPath(projectId) {
|
|
22
|
+
return join(this.dataDir, sanitizeId(projectId), 'tasks.json');
|
|
23
|
+
}
|
|
24
|
+
loadTasks(projectId) {
|
|
25
|
+
const path = this.tasksPath(projectId);
|
|
26
|
+
if (!existsSync(path))
|
|
27
|
+
return [];
|
|
28
|
+
try {
|
|
29
|
+
const raw = readFileSync(path, 'utf-8');
|
|
30
|
+
const parsed = JSON.parse(raw);
|
|
31
|
+
if (!Array.isArray(parsed?.tasks))
|
|
32
|
+
return [];
|
|
33
|
+
return parsed.tasks;
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return [];
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
saveTasks(projectId, tasks) {
|
|
40
|
+
const path = this.tasksPath(projectId);
|
|
41
|
+
const dir = join(this.dataDir, sanitizeId(projectId));
|
|
42
|
+
try {
|
|
43
|
+
mkdirSync(dir, { recursive: true });
|
|
44
|
+
const tmp = `${path}.tmp`;
|
|
45
|
+
const data = { version: 1, tasks };
|
|
46
|
+
writeFileSync(tmp, JSON.stringify(data, null, 2), 'utf-8');
|
|
47
|
+
renameSync(tmp, path);
|
|
48
|
+
}
|
|
49
|
+
catch (err) {
|
|
50
|
+
console.error(`[JsonTaskStore] saveTasks failed for project "${projectId}":`, err);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JsonlStore — JSONL-based persistence layer (v0.4.0 layout).
|
|
3
|
+
*
|
|
4
|
+
* New layout (v0.4.0):
|
|
5
|
+
* {dataDir}/projects/{projectId}/meta.json
|
|
6
|
+
* {dataDir}/projects/{projectId}/notes.jsonl
|
|
7
|
+
* {dataDir}/projects/{projectId}/builds/{buildId}/meta.json
|
|
8
|
+
* {dataDir}/tabs/{tabId}/meta.json
|
|
9
|
+
* {dataDir}/sessions/{sessionId}/meta.json
|
|
10
|
+
* {dataDir}/sessions/{sessionId}/timeline.jsonl
|
|
11
|
+
* {dataDir}/sessions/{sessionId}/recording.jsonl
|
|
12
|
+
* {dataDir}/exports/index.jsonl
|
|
13
|
+
* {dataDir}/exports/{exportId}.rrweb.json
|
|
14
|
+
*
|
|
15
|
+
* Legacy layout (v0.3.x, read-only fallback):
|
|
16
|
+
* {dataDir}/{projectId}/sessions/{buildId}/tabs/{tabId}/...
|
|
17
|
+
* On startup, if legacy dirs are detected a warning is emitted pointing
|
|
18
|
+
* users to `rm -rf ~/.harness/data`.
|
|
19
|
+
*/
|
|
20
|
+
import type { BuildMeta, IStore, ProjectMeta, ProjectTreeNode, PurgeResult, RecordingChunk, RecordingChunkSummary, ReplayExportMeta, RetentionPolicy, SearchOptions, SessionMeta, SessionSummary, StoreEvent, TabMeta, TailOptions, VisitorMeta } from './types.js';
|
|
21
|
+
import type { VisitorEnv } from '@harness-fe/protocol';
|
|
22
|
+
export declare class JsonlStore implements IStore {
|
|
23
|
+
private readonly dataDir;
|
|
24
|
+
private readonly writeQueue;
|
|
25
|
+
/**
|
|
26
|
+
* In-memory index: sessionId → SessionMeta (rebuilt on startup, kept in sync).
|
|
27
|
+
* Enables O(1) session lookup without disk reads.
|
|
28
|
+
*/
|
|
29
|
+
private sessionIndex;
|
|
30
|
+
/**
|
|
31
|
+
* In-memory index: buildId → projectId (from openBuild / upsertBuild).
|
|
32
|
+
* Enables resolving project from buildId for legacy bridge compat.
|
|
33
|
+
*/
|
|
34
|
+
private buildIndex;
|
|
35
|
+
constructor(dataDir?: string);
|
|
36
|
+
/** Scan disk to rebuild in-memory indexes. Mark orphaned sessions (no endedAt). */
|
|
37
|
+
private _rebuildIndexes;
|
|
38
|
+
private projectsDir;
|
|
39
|
+
private projectDir;
|
|
40
|
+
private buildDir;
|
|
41
|
+
private visitorsDir;
|
|
42
|
+
private visitorDir;
|
|
43
|
+
private tabsDir;
|
|
44
|
+
private tabDir;
|
|
45
|
+
private sessionsDir;
|
|
46
|
+
private sessionDir;
|
|
47
|
+
private sessionTimeline;
|
|
48
|
+
private sessionRecording;
|
|
49
|
+
private exportsDir;
|
|
50
|
+
private exportIndex;
|
|
51
|
+
private exportEventsPath;
|
|
52
|
+
openBuild(projectId: string, patch?: Partial<Omit<BuildMeta, 'id' | 'projectId' | 'builtAt'>>): string;
|
|
53
|
+
closeBuild(buildId: string, closedAt?: number): void;
|
|
54
|
+
upsertTab(tabId: string, patch: Partial<Omit<TabMeta, 'id'>>): TabMeta;
|
|
55
|
+
getTab(tabId: string): TabMeta | undefined;
|
|
56
|
+
closeTab(tabId: string, disconnectedAt?: number): void;
|
|
57
|
+
upsertSession(sessionId: string, meta: Partial<Omit<SessionMeta, 'id'>> & {
|
|
58
|
+
tabId: string;
|
|
59
|
+
startedAt: number;
|
|
60
|
+
}): SessionMeta;
|
|
61
|
+
closeSession(sessionId: string, endedAt?: number): void;
|
|
62
|
+
getSession(sessionId: string): SessionMeta | undefined;
|
|
63
|
+
listSessions(opts?: {
|
|
64
|
+
tabId?: string;
|
|
65
|
+
projectId?: string;
|
|
66
|
+
buildId?: string;
|
|
67
|
+
limit?: number;
|
|
68
|
+
}): SessionMeta[];
|
|
69
|
+
appendEvent(sessionId: string, event: StoreEvent): void;
|
|
70
|
+
appendEventBatch(sessionId: string, events: StoreEvent[]): void;
|
|
71
|
+
appendRecording(sessionId: string, chunk: unknown): void;
|
|
72
|
+
writeNote(projectId: string, key: string, value: string): void;
|
|
73
|
+
upsertProject(projectId: string, patch: Partial<Omit<ProjectMeta, 'id' | 'createdAt'>>): ProjectMeta;
|
|
74
|
+
getProject(projectId: string): ProjectMeta | undefined;
|
|
75
|
+
listProjects(): ProjectMeta[];
|
|
76
|
+
upsertVisitor(visitorId: string, patch: {
|
|
77
|
+
userId?: string;
|
|
78
|
+
seenAt?: number;
|
|
79
|
+
incrementSession?: boolean;
|
|
80
|
+
addTabId?: string;
|
|
81
|
+
addProjectId?: string;
|
|
82
|
+
lastEnv?: VisitorEnv;
|
|
83
|
+
}): VisitorMeta;
|
|
84
|
+
getVisitor(visitorId: string): VisitorMeta | undefined;
|
|
85
|
+
listVisitors(opts?: {
|
|
86
|
+
projectId?: string;
|
|
87
|
+
limit?: number;
|
|
88
|
+
}): VisitorMeta[];
|
|
89
|
+
upsertBuild(projectId: string, buildId: string, patch: Partial<Omit<BuildMeta, 'id' | 'projectId'>>): BuildMeta;
|
|
90
|
+
getBuild(projectId: string, buildId: string): BuildMeta | undefined;
|
|
91
|
+
listBuilds(projectId: string, limit?: number): BuildMeta[];
|
|
92
|
+
getProjectTree(rootId?: string): ProjectTreeNode[];
|
|
93
|
+
tail(sessionId: string, opts?: TailOptions): StoreEvent[];
|
|
94
|
+
search(sessionId: string, query: string, opts?: SearchOptions): StoreEvent[];
|
|
95
|
+
listRecordings(sessionId: string): RecordingChunkSummary[];
|
|
96
|
+
sliceRecordings(sessionId: string, since: number, until: number): RecordingChunk[];
|
|
97
|
+
writeExport(input: {
|
|
98
|
+
sessionId: string;
|
|
99
|
+
tabId?: string;
|
|
100
|
+
since: number;
|
|
101
|
+
until: number;
|
|
102
|
+
label?: string;
|
|
103
|
+
events: unknown[];
|
|
104
|
+
startTs: number;
|
|
105
|
+
endTs: number;
|
|
106
|
+
chunkCount: number;
|
|
107
|
+
}): ReplayExportMeta;
|
|
108
|
+
getExport(exportId: string): ReplayExportMeta | undefined;
|
|
109
|
+
readExportEvents(exportId: string): unknown[] | undefined;
|
|
110
|
+
listExports(projectId: string, limit?: number): ReplayExportMeta[];
|
|
111
|
+
summary(sessionId: string): SessionSummary;
|
|
112
|
+
listNotes(projectId: string): Array<{
|
|
113
|
+
key: string;
|
|
114
|
+
value: string;
|
|
115
|
+
ts: number;
|
|
116
|
+
}>;
|
|
117
|
+
purge(policy?: RetentionPolicy): PurgeResult;
|
|
118
|
+
private pruneExports;
|
|
119
|
+
/**
|
|
120
|
+
* Flush all pending WriteQueue entries to disk. Used in tests.
|
|
121
|
+
*/
|
|
122
|
+
flush(): Promise<void>;
|
|
123
|
+
close(): Promise<void>;
|
|
124
|
+
private pruneRecordingFile;
|
|
125
|
+
private readMarkerTimestamps;
|
|
126
|
+
}
|
|
127
|
+
/** Sanitize a string for use as a directory name. */
|
|
128
|
+
export declare function sanitizeId(id: string): string;
|