@revealui/harnesses 0.1.0 → 0.1.3
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.commercial +2 -3
- package/README.md +3 -0
- package/dist/chunk-DGUM43GV.js +11 -0
- package/dist/{chunk-PG4RAOWS.js → chunk-FJGN6DTH.js} +202 -66
- package/dist/chunk-FJGN6DTH.js.map +1 -0
- package/dist/chunk-HH2PJYQN.js +1158 -0
- package/dist/chunk-HH2PJYQN.js.map +1 -0
- package/dist/chunk-JDI6B2IB.js +2537 -0
- package/dist/chunk-JDI6B2IB.js.map +1 -0
- package/dist/cli.js +367 -24
- package/dist/cli.js.map +1 -1
- package/dist/content/index.d.ts +231 -0
- package/dist/content/index.js +40 -0
- package/dist/content/index.js.map +1 -0
- package/dist/index.d.ts +51 -144
- package/dist/index.js +41 -26
- package/dist/index.js.map +1 -1
- package/dist/types/index.d.ts +151 -0
- package/dist/types/index.js +1 -0
- package/dist/types/index.js.map +1 -0
- package/dist/workboard/index.d.ts +44 -3
- package/dist/workboard/index.js +16 -4
- package/package.json +32 -17
- package/dist/chunk-BDA7D725.js +0 -595
- package/dist/chunk-BDA7D725.js.map +0 -1
- package/dist/chunk-JUNNIQS3.js +0 -1
- package/dist/chunk-PG4RAOWS.js.map +0 -1
- /package/dist/{chunk-JUNNIQS3.js.map → chunk-DGUM43GV.js.map} +0 -0
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core types for the AI harness integration system.
|
|
3
|
+
* Mirrors packages/editors/src/types/core.ts for the harness domain.
|
|
4
|
+
*/
|
|
5
|
+
interface HarnessCapabilities {
|
|
6
|
+
/** Can generate code from a prompt */
|
|
7
|
+
generateCode: boolean;
|
|
8
|
+
/** Can analyze/explain existing code */
|
|
9
|
+
analyzeCode: boolean;
|
|
10
|
+
/** Can apply inline code edits */
|
|
11
|
+
applyEdit: boolean;
|
|
12
|
+
/** Can sync configuration files */
|
|
13
|
+
applyConfig: boolean;
|
|
14
|
+
/** Can query workboard state */
|
|
15
|
+
readWorkboard: boolean;
|
|
16
|
+
/** Can write workboard state */
|
|
17
|
+
writeWorkboard: boolean;
|
|
18
|
+
}
|
|
19
|
+
type ConfigSyncDirection = 'push' | 'pull';
|
|
20
|
+
type HarnessCommand = {
|
|
21
|
+
type: 'generate-code';
|
|
22
|
+
prompt: string;
|
|
23
|
+
context?: string;
|
|
24
|
+
language?: string;
|
|
25
|
+
} | {
|
|
26
|
+
type: 'analyze-code';
|
|
27
|
+
filePath: string;
|
|
28
|
+
question?: string;
|
|
29
|
+
} | {
|
|
30
|
+
type: 'apply-edit';
|
|
31
|
+
filePath: string;
|
|
32
|
+
diff: string;
|
|
33
|
+
} | {
|
|
34
|
+
type: 'apply-config';
|
|
35
|
+
configPath: string;
|
|
36
|
+
content: string;
|
|
37
|
+
} | {
|
|
38
|
+
type: 'get-status';
|
|
39
|
+
} | {
|
|
40
|
+
type: 'get-running-instances';
|
|
41
|
+
} | {
|
|
42
|
+
type: 'sync-config';
|
|
43
|
+
direction: ConfigSyncDirection;
|
|
44
|
+
} | {
|
|
45
|
+
type: 'diff-config';
|
|
46
|
+
} | {
|
|
47
|
+
type: 'read-workboard';
|
|
48
|
+
} | {
|
|
49
|
+
type: 'update-workboard';
|
|
50
|
+
sessionId: string;
|
|
51
|
+
task?: string;
|
|
52
|
+
files?: string[];
|
|
53
|
+
} | {
|
|
54
|
+
type: 'headless-prompt';
|
|
55
|
+
prompt: string;
|
|
56
|
+
maxTurns?: number;
|
|
57
|
+
timeoutMs?: number;
|
|
58
|
+
};
|
|
59
|
+
interface HarnessCommandResult {
|
|
60
|
+
success: boolean;
|
|
61
|
+
command: HarnessCommand['type'];
|
|
62
|
+
message?: string;
|
|
63
|
+
data?: unknown;
|
|
64
|
+
}
|
|
65
|
+
type HarnessEvent = {
|
|
66
|
+
type: 'harness-connected';
|
|
67
|
+
harnessId: string;
|
|
68
|
+
} | {
|
|
69
|
+
type: 'harness-disconnected';
|
|
70
|
+
harnessId: string;
|
|
71
|
+
} | {
|
|
72
|
+
type: 'generation-started';
|
|
73
|
+
taskId: string;
|
|
74
|
+
} | {
|
|
75
|
+
type: 'generation-completed';
|
|
76
|
+
taskId: string;
|
|
77
|
+
output: string;
|
|
78
|
+
} | {
|
|
79
|
+
type: 'error';
|
|
80
|
+
harnessId: string;
|
|
81
|
+
message: string;
|
|
82
|
+
};
|
|
83
|
+
interface HarnessInfo {
|
|
84
|
+
id: string;
|
|
85
|
+
name: string;
|
|
86
|
+
version?: string;
|
|
87
|
+
capabilities: HarnessCapabilities;
|
|
88
|
+
}
|
|
89
|
+
interface HarnessProcessInfo {
|
|
90
|
+
pid: number;
|
|
91
|
+
command: string;
|
|
92
|
+
harnessId: string;
|
|
93
|
+
}
|
|
94
|
+
interface ConfigSyncResult {
|
|
95
|
+
success: boolean;
|
|
96
|
+
harnessId: string;
|
|
97
|
+
direction: ConfigSyncDirection;
|
|
98
|
+
message?: string;
|
|
99
|
+
}
|
|
100
|
+
interface ConfigDiffEntry {
|
|
101
|
+
harnessId: string;
|
|
102
|
+
localExists: boolean;
|
|
103
|
+
ssdExists: boolean;
|
|
104
|
+
identical: boolean;
|
|
105
|
+
}
|
|
106
|
+
interface HealthCheckResult {
|
|
107
|
+
healthy: boolean;
|
|
108
|
+
timestamp: string;
|
|
109
|
+
registeredHarnesses: Array<{
|
|
110
|
+
harnessId: string;
|
|
111
|
+
available: boolean;
|
|
112
|
+
}>;
|
|
113
|
+
workboard: {
|
|
114
|
+
readable: boolean;
|
|
115
|
+
sessionCount: number;
|
|
116
|
+
staleSessionIds: string[];
|
|
117
|
+
};
|
|
118
|
+
diagnostics: string[];
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Contract every AI harness adapter must satisfy.
|
|
123
|
+
* Mirrors EditorAdapter from packages/editors.
|
|
124
|
+
*
|
|
125
|
+
* AI tools are external executables — never linked libraries.
|
|
126
|
+
* Communication is data-only: commands in, results out.
|
|
127
|
+
*/
|
|
128
|
+
interface HarnessAdapter {
|
|
129
|
+
/** Unique stable identifier, e.g. "claude-code", "cursor", "copilot" */
|
|
130
|
+
readonly id: string;
|
|
131
|
+
/** Human-readable display name */
|
|
132
|
+
readonly name: string;
|
|
133
|
+
/** Returns the static capability set for this harness */
|
|
134
|
+
getCapabilities(): HarnessCapabilities;
|
|
135
|
+
/** Returns live info (version, etc.) — may shell out */
|
|
136
|
+
getInfo(): Promise<HarnessInfo>;
|
|
137
|
+
/** True if the harness executable is on PATH and accessible */
|
|
138
|
+
isAvailable(): Promise<boolean>;
|
|
139
|
+
/** Execute a typed command against this harness */
|
|
140
|
+
execute(command: HarnessCommand): Promise<HarnessCommandResult>;
|
|
141
|
+
/** Subscribe to harness events; returns an unsubscribe function */
|
|
142
|
+
onEvent(handler: (event: HarnessEvent) => void): () => void;
|
|
143
|
+
/** Release all resources held by this adapter */
|
|
144
|
+
dispose(): Promise<void>;
|
|
145
|
+
/** Called by the registry after this adapter has been registered. */
|
|
146
|
+
notifyRegistered?(): void;
|
|
147
|
+
/** Called by the registry just before this adapter is unregistered. */
|
|
148
|
+
notifyUnregistering?(): void;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export type { ConfigDiffEntry, ConfigSyncDirection, ConfigSyncResult, HarnessAdapter, HarnessCapabilities, HarnessCommand, HarnessCommandResult, HarnessEvent, HarnessInfo, HarnessProcessInfo, HealthCheckResult };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -67,17 +67,22 @@ interface ConflictResult {
|
|
|
67
67
|
*
|
|
68
68
|
* This class provides programmatic access to the Sessions table and Recent list.
|
|
69
69
|
* Plans, Context, and Plan Reference are treated as opaque strings.
|
|
70
|
+
*
|
|
71
|
+
* All mutating methods use file locking (O_EXCL) to prevent race conditions
|
|
72
|
+
* when multiple harness instances write concurrently. Writes are atomic
|
|
73
|
+
* (tmp file + rename).
|
|
70
74
|
*/
|
|
71
75
|
declare class WorkboardManager {
|
|
72
76
|
private readonly workboardPath;
|
|
77
|
+
private readonly lockPath;
|
|
73
78
|
constructor(workboardPath: string);
|
|
74
79
|
/** Read and parse the workboard. */
|
|
75
80
|
read(): WorkboardState;
|
|
76
|
-
/** Write a workboard state back to disk. */
|
|
81
|
+
/** Write a workboard state back to disk (locked + atomic). */
|
|
77
82
|
write(state: WorkboardState): void;
|
|
78
83
|
/** Read and parse the workboard asynchronously. */
|
|
79
84
|
readAsync(): Promise<WorkboardState>;
|
|
80
|
-
/** Write a workboard state back to disk asynchronously. */
|
|
85
|
+
/** Write a workboard state back to disk asynchronously (locked + atomic). */
|
|
81
86
|
writeAsync(state: WorkboardState): Promise<void>;
|
|
82
87
|
/** Register a new session, replacing any existing row with the same id. */
|
|
83
88
|
registerSession(session: WorkboardSession): void;
|
|
@@ -98,8 +103,44 @@ declare class WorkboardManager {
|
|
|
98
103
|
* Returns a ConflictResult describing any overlaps found.
|
|
99
104
|
*/
|
|
100
105
|
checkConflicts(mySessionId: string, files: string[]): ConflictResult;
|
|
106
|
+
private readUnlocked;
|
|
107
|
+
private writeUnlocked;
|
|
101
108
|
}
|
|
102
109
|
|
|
110
|
+
/**
|
|
111
|
+
* Acquire an exclusive file lock using O_EXCL (kernel-level atomic create).
|
|
112
|
+
* Writes the current PID to the lock file for dead-holder detection.
|
|
113
|
+
*
|
|
114
|
+
* Spins with a 50ms interval until timeout. If the current lock holder
|
|
115
|
+
* is dead (process no longer running), the lock is stolen.
|
|
116
|
+
*
|
|
117
|
+
* @returns true if the lock was acquired, false on timeout
|
|
118
|
+
*/
|
|
119
|
+
declare function acquireLock(lockPath: string, timeoutMs?: number): boolean;
|
|
120
|
+
/**
|
|
121
|
+
* Release a file lock. Swallows ENOENT (already released).
|
|
122
|
+
*/
|
|
123
|
+
declare function releaseLock(lockPath: string): void;
|
|
124
|
+
/**
|
|
125
|
+
* Execute a synchronous function while holding the file lock.
|
|
126
|
+
* The lock is always released, even if fn throws.
|
|
127
|
+
*/
|
|
128
|
+
declare function withLock<T>(lockPath: string, fn: () => T, timeoutMs?: number): T;
|
|
129
|
+
/**
|
|
130
|
+
* Execute an async function while holding the file lock.
|
|
131
|
+
* The lock is always released, even if fn throws.
|
|
132
|
+
*/
|
|
133
|
+
declare function withLockAsync<T>(lockPath: string, fn: () => Promise<T>, timeoutMs?: number): Promise<T>;
|
|
134
|
+
/**
|
|
135
|
+
* Write a file atomically: write to a temporary file, then rename.
|
|
136
|
+
* rename() on the same filesystem is atomic at the kernel level.
|
|
137
|
+
*/
|
|
138
|
+
declare function atomicWriteSync(filePath: string, content: string): void;
|
|
139
|
+
/**
|
|
140
|
+
* Derive a lock path from a workboard path (.md → .lock).
|
|
141
|
+
*/
|
|
142
|
+
declare function lockPathFor(workboardPath: string): string;
|
|
143
|
+
|
|
103
144
|
/** Type of session detected from the runtime environment. */
|
|
104
145
|
type SessionType = 'zed' | 'cursor' | 'terminal';
|
|
105
146
|
/**
|
|
@@ -117,4 +158,4 @@ declare function detectSessionType(): SessionType;
|
|
|
117
158
|
*/
|
|
118
159
|
declare function deriveSessionId(type: SessionType, existingIds: string[]): string;
|
|
119
160
|
|
|
120
|
-
export { type ConflictResult, type SessionType, type WorkboardEntry, WorkboardManager, type WorkboardSession, type WorkboardState, deriveSessionId, detectSessionType };
|
|
161
|
+
export { type ConflictResult, type SessionType, type WorkboardEntry, WorkboardManager, type WorkboardSession, type WorkboardState, acquireLock, atomicWriteSync, deriveSessionId, detectSessionType, lockPathFor, releaseLock, withLock, withLockAsync };
|
package/dist/workboard/index.js
CHANGED
|
@@ -1,12 +1,24 @@
|
|
|
1
|
-
import "../chunk-JUNNIQS3.js";
|
|
2
1
|
import {
|
|
3
2
|
WorkboardManager,
|
|
3
|
+
acquireLock,
|
|
4
|
+
atomicWriteSync,
|
|
4
5
|
deriveSessionId,
|
|
5
|
-
detectSessionType
|
|
6
|
-
|
|
6
|
+
detectSessionType,
|
|
7
|
+
lockPathFor,
|
|
8
|
+
releaseLock,
|
|
9
|
+
withLock,
|
|
10
|
+
withLockAsync
|
|
11
|
+
} from "../chunk-FJGN6DTH.js";
|
|
12
|
+
import "../chunk-DGUM43GV.js";
|
|
7
13
|
export {
|
|
8
14
|
WorkboardManager,
|
|
15
|
+
acquireLock,
|
|
16
|
+
atomicWriteSync,
|
|
9
17
|
deriveSessionId,
|
|
10
|
-
detectSessionType
|
|
18
|
+
detectSessionType,
|
|
19
|
+
lockPathFor,
|
|
20
|
+
releaseLock,
|
|
21
|
+
withLock,
|
|
22
|
+
withLockAsync
|
|
11
23
|
};
|
|
12
24
|
//# sourceMappingURL=index.js.map
|
package/package.json
CHANGED
|
@@ -1,12 +1,27 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@revealui/harnesses",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "AI harness integration system - adapters, daemon, workboard coordination, and JSON-RPC server",
|
|
3
|
+
"version": "0.1.3",
|
|
4
|
+
"description": "[Pro] AI harness integration system - adapters, daemon, workboard coordination, and JSON-RPC server",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "https://github.com/RevealUIStudio/revealui.git",
|
|
8
|
+
"directory": "packages/harnesses"
|
|
9
|
+
},
|
|
5
10
|
"license": "SEE LICENSE IN ../../LICENSE.commercial",
|
|
6
|
-
"type": "module",
|
|
7
11
|
"bin": {
|
|
8
12
|
"revealui-harnesses": "./dist/cli.js"
|
|
9
13
|
},
|
|
14
|
+
"dependencies": {
|
|
15
|
+
"zod": "^4.3.6",
|
|
16
|
+
"@revealui/core": "0.5.0"
|
|
17
|
+
},
|
|
18
|
+
"devDependencies": {
|
|
19
|
+
"@types/node": "^25.3.0",
|
|
20
|
+
"tsup": "^8.5.1",
|
|
21
|
+
"typescript": "^6.0.2",
|
|
22
|
+
"vitest": "^4.0.18",
|
|
23
|
+
"dev": "0.0.1"
|
|
24
|
+
},
|
|
10
25
|
"exports": {
|
|
11
26
|
".": {
|
|
12
27
|
"types": "./dist/index.d.ts",
|
|
@@ -19,35 +34,35 @@
|
|
|
19
34
|
"./workboard": {
|
|
20
35
|
"types": "./dist/workboard/index.d.ts",
|
|
21
36
|
"import": "./dist/workboard/index.js"
|
|
37
|
+
},
|
|
38
|
+
"./content": {
|
|
39
|
+
"types": "./dist/content/index.d.ts",
|
|
40
|
+
"import": "./dist/content/index.js"
|
|
22
41
|
}
|
|
23
42
|
},
|
|
24
43
|
"files": [
|
|
25
44
|
"dist"
|
|
26
45
|
],
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
|
|
30
|
-
"devDependencies": {
|
|
31
|
-
"@types/node": "^25.3.0",
|
|
32
|
-
"tsup": "^8.5.1",
|
|
33
|
-
"typescript": "^5.9.3",
|
|
34
|
-
"vitest": "^4.0.18",
|
|
35
|
-
"dev": "0.0.1"
|
|
46
|
+
"funding": {
|
|
47
|
+
"type": "commercial",
|
|
48
|
+
"url": "https://revealui.com/pro"
|
|
36
49
|
},
|
|
50
|
+
"main": "./dist/index.js",
|
|
37
51
|
"publishConfig": {
|
|
38
|
-
"registry": "https://registry.npmjs.org",
|
|
39
52
|
"access": "public"
|
|
40
53
|
},
|
|
54
|
+
"type": "module",
|
|
55
|
+
"types": "./dist/index.d.ts",
|
|
41
56
|
"scripts": {
|
|
42
57
|
"build": "tsup",
|
|
58
|
+
"clean": "rm -rf dist",
|
|
43
59
|
"dev": "tsup --watch",
|
|
60
|
+
"lint": "biome check .",
|
|
61
|
+
"lint:fix": "biome check --write .",
|
|
44
62
|
"start": "node dist/cli.js",
|
|
45
|
-
"typecheck": "tsc --noEmit",
|
|
46
63
|
"test": "vitest run --passWithNoTests",
|
|
47
64
|
"test:coverage": "vitest run --coverage",
|
|
48
65
|
"test:watch": "vitest",
|
|
49
|
-
"
|
|
50
|
-
"lint:fix": "biome check --write .",
|
|
51
|
-
"clean": "rm -rf dist"
|
|
66
|
+
"typecheck": "tsc --noEmit"
|
|
52
67
|
}
|
|
53
68
|
}
|