@fusengine/harness 0.1.5 → 0.1.6
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/runtime/index.d.mts +29 -1
- package/dist/runtime/index.mjs +58 -1
- package/package.json +1 -1
package/dist/runtime/index.d.mts
CHANGED
|
@@ -1,10 +1,19 @@
|
|
|
1
1
|
import { t as Prompt } from "../types-D56jSgD9.mjs";
|
|
2
|
+
import { t as HarnessId } from "../harness-DwJskkz_.mjs";
|
|
2
3
|
import { t as RefMeta } from "../types-CY5qT2X1.mjs";
|
|
3
4
|
|
|
4
5
|
//#region src/runtime/paths.d.ts
|
|
5
6
|
/** Path to a session's track file (under a per-tool base dir). */
|
|
6
7
|
declare function trackFile(sessionId: string, baseDir?: string): string;
|
|
7
8
|
//#endregion
|
|
9
|
+
//#region src/runtime/storage.d.ts
|
|
10
|
+
/**
|
|
11
|
+
* Directory where a harness's fuse-harness track files live — under that
|
|
12
|
+
* harness's own config dir (`.claude`, `.codex`, …) so state sits next to its
|
|
13
|
+
* hooks. Falls back to `.fuse-harness` for harnesses without a known config dir.
|
|
14
|
+
*/
|
|
15
|
+
declare function harnessTrackDir(id: HarnessId, projectRoot: string): string;
|
|
16
|
+
//#endregion
|
|
8
17
|
//#region src/runtime/record.d.ts
|
|
9
18
|
/** A unit of session activity to record (discriminated union on `kind`). */
|
|
10
19
|
type Activity = {
|
|
@@ -23,6 +32,25 @@ type Activity = {
|
|
|
23
32
|
/** Apply an activity to a session's track and persist it (PostToolUse path). */
|
|
24
33
|
declare function recordActivity(file: string, activity: Activity): Promise<void>;
|
|
25
34
|
//#endregion
|
|
35
|
+
//#region src/runtime/activity.d.ts
|
|
36
|
+
/** A live tool-use, already normalized to `tool` + `input` by the adapter. */
|
|
37
|
+
interface ToolEvent {
|
|
38
|
+
/** The harness's `tool_name` (Cline: `preToolUse.toolName`), as a plain string. */
|
|
39
|
+
tool: string;
|
|
40
|
+
input?: Record<string, unknown>;
|
|
41
|
+
sessionId: string;
|
|
42
|
+
framework: string;
|
|
43
|
+
now: number;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Map a live tool-use to the activity to record, or null when nothing is
|
|
47
|
+
* tracked. Works across harnesses — tool names are globally distinct:
|
|
48
|
+
* - MCP doc calls (`context7` / `exa`, any separator) → `doc`
|
|
49
|
+
* - `Task` + `subagent_type` (Claude/Cursor) → `agent` (bare agent name)
|
|
50
|
+
* - a read tool opening a `.md` reference → `ref`
|
|
51
|
+
*/
|
|
52
|
+
declare function activityFor(event: ToolEvent): Activity | null;
|
|
53
|
+
//#endregion
|
|
26
54
|
//#region src/runtime/gate.d.ts
|
|
27
55
|
/** Prior agents the freshness gate requires before a code edit. */
|
|
28
56
|
declare const REQUIRED_AGENTS: ReadonlyArray<string>;
|
|
@@ -48,4 +76,4 @@ interface GateInput {
|
|
|
48
76
|
*/
|
|
49
77
|
declare function gate(input: GateInput): Promise<Prompt | null>;
|
|
50
78
|
//#endregion
|
|
51
|
-
export { Activity, DEFAULT_WINDOW_MS, GateInput, REQUIRED_AGENTS, gate, recordActivity, trackFile };
|
|
79
|
+
export { Activity, DEFAULT_WINDOW_MS, GateInput, REQUIRED_AGENTS, ToolEvent, activityFor, gate, harnessTrackDir, recordActivity, trackFile };
|
package/dist/runtime/index.mjs
CHANGED
|
@@ -9,6 +9,24 @@ function trackFile(sessionId, baseDir = join(tmpdir(), "fuse-harness")) {
|
|
|
9
9
|
return join(baseDir, `track-${sessionId.replace(/[^A-Za-z0-9_-]/g, "_") || "default"}.json`);
|
|
10
10
|
}
|
|
11
11
|
//#endregion
|
|
12
|
+
//#region src/runtime/storage.ts
|
|
13
|
+
/** Per-harness config dir (relative to the project root) where state lives. */
|
|
14
|
+
const STATE_DIR = {
|
|
15
|
+
"claude-code": ".claude",
|
|
16
|
+
codex: ".codex",
|
|
17
|
+
cursor: ".cursor",
|
|
18
|
+
"gemini-cli": ".gemini",
|
|
19
|
+
cline: ".clinerules"
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Directory where a harness's fuse-harness track files live — under that
|
|
23
|
+
* harness's own config dir (`.claude`, `.codex`, …) so state sits next to its
|
|
24
|
+
* hooks. Falls back to `.fuse-harness` for harnesses without a known config dir.
|
|
25
|
+
*/
|
|
26
|
+
function harnessTrackDir(id, projectRoot) {
|
|
27
|
+
return join(projectRoot, STATE_DIR[id] ?? ".fuse-harness", "harness");
|
|
28
|
+
}
|
|
29
|
+
//#endregion
|
|
12
30
|
//#region src/runtime/record.ts
|
|
13
31
|
/** Apply an activity to a session's track and persist it (PostToolUse path). */
|
|
14
32
|
async function recordActivity(file, activity) {
|
|
@@ -16,6 +34,45 @@ async function recordActivity(file, activity) {
|
|
|
16
34
|
await saveTrack(file, activity.kind === "agent" ? recordAgent(track, activity.name, activity.ts) : activity.kind === "doc" ? recordDoc(track, activity.framework, activity.sessionId, activity.source) : recordRefRead(track, activity.path));
|
|
17
35
|
}
|
|
18
36
|
//#endregion
|
|
37
|
+
//#region src/runtime/activity.ts
|
|
38
|
+
/** Read tools across harnesses (Claude `Read`, Gemini/Cline `read_file`, …). */
|
|
39
|
+
const READ_TOOLS = /* @__PURE__ */ new Set([
|
|
40
|
+
"Read",
|
|
41
|
+
"read_file",
|
|
42
|
+
"read_many_files"
|
|
43
|
+
]);
|
|
44
|
+
/**
|
|
45
|
+
* Map a live tool-use to the activity to record, or null when nothing is
|
|
46
|
+
* tracked. Works across harnesses — tool names are globally distinct:
|
|
47
|
+
* - MCP doc calls (`context7` / `exa`, any separator) → `doc`
|
|
48
|
+
* - `Task` + `subagent_type` (Claude/Cursor) → `agent` (bare agent name)
|
|
49
|
+
* - a read tool opening a `.md` reference → `ref`
|
|
50
|
+
*/
|
|
51
|
+
function activityFor(event) {
|
|
52
|
+
if (/context7|exa/i.test(event.tool)) return {
|
|
53
|
+
kind: "doc",
|
|
54
|
+
framework: event.framework,
|
|
55
|
+
sessionId: event.sessionId,
|
|
56
|
+
source: /exa/i.test(event.tool) ? "exa" : "context7"
|
|
57
|
+
};
|
|
58
|
+
if (event.tool === "Task") {
|
|
59
|
+
const name = String(event.input?.subagent_type ?? "").split(":").pop() ?? "";
|
|
60
|
+
return name ? {
|
|
61
|
+
kind: "agent",
|
|
62
|
+
name,
|
|
63
|
+
ts: event.now
|
|
64
|
+
} : null;
|
|
65
|
+
}
|
|
66
|
+
if (READ_TOOLS.has(event.tool)) {
|
|
67
|
+
const path = String(event.input?.file_path ?? event.input?.path ?? "");
|
|
68
|
+
if (path.endsWith(".md")) return {
|
|
69
|
+
kind: "ref",
|
|
70
|
+
path
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
//#endregion
|
|
19
76
|
//#region src/runtime/gate.ts
|
|
20
77
|
/** Prior agents the freshness gate requires before a code edit. */
|
|
21
78
|
const REQUIRED_AGENTS = ["explore-codebase", "research-expert"];
|
|
@@ -48,4 +105,4 @@ async function gate(input) {
|
|
|
48
105
|
});
|
|
49
106
|
}
|
|
50
107
|
//#endregion
|
|
51
|
-
export { DEFAULT_WINDOW_MS, REQUIRED_AGENTS, gate, recordActivity, trackFile };
|
|
108
|
+
export { DEFAULT_WINDOW_MS, REQUIRED_AGENTS, activityFor, gate, harnessTrackDir, recordActivity, trackFile };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fusengine/harness",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"description": "Harness-agnostic toolkit for AI coding agents: runtime harness detection (Claude Code, Codex, Cursor, Cline, Gemini, Aider...), pure policy core (env config, project/framework detection, SOLID/file-size limits, APEX freshness, guard patterns, portable prompts), cache, project memory, ref routing, state/locks, statusline, per-harness adapters (Claude/Cursor/Cline/Gemini) and a cli-mode harness-check binary. Bun-native, with a built dist for Node + bundlers.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "src/index.ts",
|