@fusengine/harness 0.1.4 → 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.
@@ -1,37 +1,5 @@
1
1
  import { r as isDocConsulted, t as formatDocDeny } from "./doc-helpers-Dd_x1-tZ.mjs";
2
2
  import { t as routeReferences } from "./router-Dj3AfgBE.mjs";
3
- import { existsSync } from "node:fs";
4
- import { join } from "node:path";
5
- //#region src/policy/detect-project.ts
6
- /** Keywords that signal a development task (APEX trigger). */
7
- const DEV_KEYWORDS = /\b(implement|create|build|fix|add|refactor|develop|feature|bug|update|modify|change|write|code)\b/i;
8
- /** True when the prompt invokes the /apex command. */
9
- function isApexCommand(prompt) {
10
- return /(?:^|\s)\/apex|\/fuse-ai-pilot:apex/i.test(prompt);
11
- }
12
- /** Detect the project type by scanning config files in `dir`. */
13
- function detectProjectType(dir) {
14
- const has = (f) => existsSync(join(dir, f));
15
- if (has("next.config.js") || has("next.config.ts") || has("next.config.mjs")) return "nextjs";
16
- if (has("nuxt.config.ts") || has("nuxt.config.js")) return "nuxt";
17
- if (has("angular.json")) return "angular";
18
- if (has("svelte.config.js") || has("svelte.config.ts")) return "svelte";
19
- if (has("vite.config.ts") && has("src/App.vue")) return "vue";
20
- if (has("vite.config.ts") || has("vite.config.js")) return "react";
21
- if (has("tailwind.config.js") || has("tailwind.config.ts")) return "tailwind";
22
- if (has("composer.json") && has("artisan")) return "laravel";
23
- if (has("Gemfile") && has("config/routes.rb")) return "rails";
24
- if (has("requirements.txt") || has("pyproject.toml") || has("setup.py")) return has("manage.py") ? "django" : "python";
25
- if (has("go.mod")) return "go";
26
- if (has("Cargo.toml")) return "rust";
27
- if (has("Package.swift")) return "swift";
28
- if (has("pom.xml") || has("build.gradle") || has("build.gradle.kts")) return "java";
29
- if (has("build.sbt")) return "scala";
30
- if (has("mix.exs")) return "elixir";
31
- if (has("Gemfile")) return "ruby";
32
- return "generic";
33
- }
34
- //#endregion
35
3
  //#region src/policy/apex.ts
36
4
  /** Gate: Context7 + Exa must have been consulted this session. */
37
5
  const docConsultedGate = (ctx) => isDocConsulted(ctx.authorizations, ctx.sessionId) ? null : {
@@ -76,4 +44,4 @@ function evaluateApex(ctx, gates = APEX_GATES) {
76
44
  return gates.reduce((hit, gate) => hit ?? gate(ctx), null);
77
45
  }
78
46
  //#endregion
79
- export { solidReadGate as a, isApexCommand as c, freshnessGate as i, docConsultedGate as n, DEV_KEYWORDS as o, evaluateApex as r, detectProjectType as s, APEX_GATES as t };
47
+ export { solidReadGate as a, freshnessGate as i, docConsultedGate as n, evaluateApex as r, APEX_GATES as t };
package/dist/index.mjs CHANGED
@@ -3,10 +3,11 @@ import { i as ttlLabel, n as TTL_ENV_KEY, r as resolveTtlSec, t as DEFAULT_TTL_S
3
3
  import { t as compactJson } from "./compact-json-DK2nX-MK.mjs";
4
4
  import { n as projectRoot, r as projectRootOrNull, t as isCodeFile } from "./project-root-C4ks_q1G.mjs";
5
5
  import { n as detectMode, r as modeFor, t as detectHarness } from "./harness-C8Nxxyn_.mjs";
6
- import { a as solidReadGate, c as isApexCommand, i as freshnessGate, n as docConsultedGate, o as DEV_KEYWORDS, r as evaluateApex, s as detectProjectType, t as APEX_GATES } from "./policy-C4zmyZR-.mjs";
6
+ import { n as detectProjectType, r as isApexCommand, t as DEV_KEYWORDS } from "./policy-C_pXmeNB.mjs";
7
7
  import { a as SYSTEM_INSTALL, c as evaluateFileSize, i as PROJECT_INSTALL, l as detectFramework, n as GIT_ASK, o as matchPatterns, r as GIT_BLOCKED, s as countLines, t as evaluate } from "./evaluate-CsYyUucy.mjs";
8
8
  import { i as resolveSessions, n as formatDocSatisfactionStatus, r as isDocConsulted, t as formatDocDeny } from "./doc-helpers-Dd_x1-tZ.mjs";
9
9
  import { i as parseFrontmatter, n as scoreReferences, r as globToRe, t as routeReferences } from "./router-Dj3AfgBE.mjs";
10
+ import { a as solidReadGate, i as freshnessGate, n as docConsultedGate, r as evaluateApex, t as APEX_GATES } from "./apex-gGrHzvM2.mjs";
10
11
  import { t as formatPrompt } from "./types-ernB1Dy3.mjs";
11
12
  import { a as readState, c as throttleMs, i as nowStamp, l as ensureMemoryGitignore, n as readRoots, o as setStateField, r as registryFile, s as stateFileFor, t as addRoot } from "./memory-BVNt4Ary.mjs";
12
13
  import { a as jaccardSimilar, i as compactMarkdown, n as loadIndex, o as queryHash, r as summarizeIndex, t as extractText } from "./cache-DbPSJ9bC.mjs";
@@ -1,3 +1,4 @@
1
- import { a as solidReadGate, c as isApexCommand, i as freshnessGate, n as docConsultedGate, o as DEV_KEYWORDS, r as evaluateApex, s as detectProjectType, t as APEX_GATES } from "../policy-C4zmyZR-.mjs";
1
+ import { n as detectProjectType, r as isApexCommand, t as DEV_KEYWORDS } from "../policy-C_pXmeNB.mjs";
2
2
  import { a as SYSTEM_INSTALL, c as evaluateFileSize, i as PROJECT_INSTALL, l as detectFramework, n as GIT_ASK, o as matchPatterns, r as GIT_BLOCKED, s as countLines, t as evaluate } from "../evaluate-CsYyUucy.mjs";
3
+ import { a as solidReadGate, i as freshnessGate, n as docConsultedGate, r as evaluateApex, t as APEX_GATES } from "../apex-gGrHzvM2.mjs";
3
4
  export { APEX_GATES, DEV_KEYWORDS, GIT_ASK, GIT_BLOCKED, PROJECT_INSTALL, SYSTEM_INSTALL, countLines, detectFramework, detectProjectType, docConsultedGate, evaluate, evaluateApex, evaluateFileSize, freshnessGate, isApexCommand, matchPatterns, solidReadGate };
@@ -0,0 +1,33 @@
1
+ import { existsSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ //#region src/policy/detect-project.ts
4
+ /** Keywords that signal a development task (APEX trigger). */
5
+ const DEV_KEYWORDS = /\b(implement|create|build|fix|add|refactor|develop|feature|bug|update|modify|change|write|code)\b/i;
6
+ /** True when the prompt invokes the /apex command. */
7
+ function isApexCommand(prompt) {
8
+ return /(?:^|\s)\/apex|\/fuse-ai-pilot:apex/i.test(prompt);
9
+ }
10
+ /** Detect the project type by scanning config files in `dir`. */
11
+ function detectProjectType(dir) {
12
+ const has = (f) => existsSync(join(dir, f));
13
+ if (has("next.config.js") || has("next.config.ts") || has("next.config.mjs")) return "nextjs";
14
+ if (has("nuxt.config.ts") || has("nuxt.config.js")) return "nuxt";
15
+ if (has("angular.json")) return "angular";
16
+ if (has("svelte.config.js") || has("svelte.config.ts")) return "svelte";
17
+ if (has("vite.config.ts") && has("src/App.vue")) return "vue";
18
+ if (has("vite.config.ts") || has("vite.config.js")) return "react";
19
+ if (has("tailwind.config.js") || has("tailwind.config.ts")) return "tailwind";
20
+ if (has("composer.json") && has("artisan")) return "laravel";
21
+ if (has("Gemfile") && has("config/routes.rb")) return "rails";
22
+ if (has("requirements.txt") || has("pyproject.toml") || has("setup.py")) return has("manage.py") ? "django" : "python";
23
+ if (has("go.mod")) return "go";
24
+ if (has("Cargo.toml")) return "rust";
25
+ if (has("Package.swift")) return "swift";
26
+ if (has("pom.xml") || has("build.gradle") || has("build.gradle.kts")) return "java";
27
+ if (has("build.sbt")) return "scala";
28
+ if (has("mix.exs")) return "elixir";
29
+ if (has("Gemfile")) return "ruby";
30
+ return "generic";
31
+ }
32
+ //#endregion
33
+ export { detectProjectType as n, isApexCommand as r, DEV_KEYWORDS as t };
@@ -0,0 +1,79 @@
1
+ import { t as Prompt } from "../types-D56jSgD9.mjs";
2
+ import { t as HarnessId } from "../harness-DwJskkz_.mjs";
3
+ import { t as RefMeta } from "../types-CY5qT2X1.mjs";
4
+
5
+ //#region src/runtime/paths.d.ts
6
+ /** Path to a session's track file (under a per-tool base dir). */
7
+ declare function trackFile(sessionId: string, baseDir?: string): string;
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
17
+ //#region src/runtime/record.d.ts
18
+ /** A unit of session activity to record (discriminated union on `kind`). */
19
+ type Activity = {
20
+ kind: "agent";
21
+ name: string;
22
+ ts: number;
23
+ } | {
24
+ kind: "doc";
25
+ framework: string;
26
+ sessionId: string;
27
+ source: string;
28
+ } | {
29
+ kind: "ref";
30
+ path: string;
31
+ };
32
+ /** Apply an activity to a session's track and persist it (PostToolUse path). */
33
+ declare function recordActivity(file: string, activity: Activity): Promise<void>;
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
54
+ //#region src/runtime/gate.d.ts
55
+ /** Prior agents the freshness gate requires before a code edit. */
56
+ declare const REQUIRED_AGENTS: ReadonlyArray<string>;
57
+ /** Default freshness window for {@link REQUIRED_AGENTS} (4 min, the APEX TTL). */
58
+ declare const DEFAULT_WINDOW_MS = 24e4;
59
+ /** A tool-use to gate, plus the session pointers needed for the stateful gates. */
60
+ interface GateInput {
61
+ sessionId: string;
62
+ framework: string;
63
+ tool: string;
64
+ filePath?: string;
65
+ content?: string;
66
+ command?: string;
67
+ refs?: RefMeta[];
68
+ now: number;
69
+ trackFile: string;
70
+ windowMs?: number;
71
+ }
72
+ /**
73
+ * Full gate: the stateless guards (file-size, git) first, then the stateful
74
+ * APEX gates fed from the session track. Returns the first blocking prompt, or
75
+ * null to allow. APEX gates apply only to code edits (a `filePath`).
76
+ */
77
+ declare function gate(input: GateInput): Promise<Prompt | null>;
78
+ //#endregion
79
+ export { Activity, DEFAULT_WINDOW_MS, GateInput, REQUIRED_AGENTS, ToolEvent, activityFor, gate, harnessTrackDir, recordActivity, trackFile };
@@ -0,0 +1,108 @@
1
+ import { t as evaluate } from "../evaluate-CsYyUucy.mjs";
2
+ import { r as evaluateApex } from "../apex-gGrHzvM2.mjs";
3
+ import { a as recordAgent, n as saveTrack, o as recordDoc, r as agentsFresh, s as recordRefRead, t as loadTrack } from "../store-BWvwnnf6.mjs";
4
+ import { join } from "node:path";
5
+ import { tmpdir } from "node:os";
6
+ //#region src/runtime/paths.ts
7
+ /** Path to a session's track file (under a per-tool base dir). */
8
+ function trackFile(sessionId, baseDir = join(tmpdir(), "fuse-harness")) {
9
+ return join(baseDir, `track-${sessionId.replace(/[^A-Za-z0-9_-]/g, "_") || "default"}.json`);
10
+ }
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
30
+ //#region src/runtime/record.ts
31
+ /** Apply an activity to a session's track and persist it (PostToolUse path). */
32
+ async function recordActivity(file, activity) {
33
+ const track = await loadTrack(file);
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));
35
+ }
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
76
+ //#region src/runtime/gate.ts
77
+ /** Prior agents the freshness gate requires before a code edit. */
78
+ const REQUIRED_AGENTS = ["explore-codebase", "research-expert"];
79
+ /** Default freshness window for {@link REQUIRED_AGENTS} (4 min, the APEX TTL). */
80
+ const DEFAULT_WINDOW_MS = 24e4;
81
+ /**
82
+ * Full gate: the stateless guards (file-size, git) first, then the stateful
83
+ * APEX gates fed from the session track. Returns the first blocking prompt, or
84
+ * null to allow. APEX gates apply only to code edits (a `filePath`).
85
+ */
86
+ async function gate(input) {
87
+ const quick = evaluate({
88
+ tool: input.tool,
89
+ filePath: input.filePath,
90
+ content: input.content,
91
+ command: input.command
92
+ });
93
+ if (quick.decision !== "allow" && quick.prompt) return quick.prompt;
94
+ if (!input.filePath) return null;
95
+ const track = await loadTrack(input.trackFile);
96
+ return evaluateApex({
97
+ sessionId: input.sessionId,
98
+ framework: input.framework,
99
+ filePath: input.filePath,
100
+ content: input.content ?? "",
101
+ authorizations: track.authorizations,
102
+ refs: input.refs,
103
+ refsRead: track.refsRead,
104
+ agentsFresh: agentsFresh(track, [...REQUIRED_AGENTS], input.windowMs ?? 24e4, input.now)
105
+ });
106
+ }
107
+ //#endregion
108
+ export { DEFAULT_WINDOW_MS, REQUIRED_AGENTS, activityFor, gate, harnessTrackDir, recordActivity, trackFile };
@@ -0,0 +1,63 @@
1
+ import { n as readJsonFile, r as writeJsonFile } from "./json-io-RH82El2J.mjs";
2
+ //#region src/tracking/session-state.ts
3
+ /** A fresh, empty track. */
4
+ function emptyTrack() {
5
+ return {
6
+ authorizations: {},
7
+ refsRead: [],
8
+ agents: []
9
+ };
10
+ }
11
+ /** Record a doc consultation (Context7/Exa) for a framework in this session. Immutable. */
12
+ function recordDoc(track, framework, sessionId, source) {
13
+ const prev = track.authorizations[framework] ?? {};
14
+ const sessions = new Set(prev.doc_sessions ?? []);
15
+ sessions.add(sessionId);
16
+ const sources = new Set(prev.sources ?? (prev.source ? [prev.source] : []));
17
+ sources.add(source);
18
+ return {
19
+ ...track,
20
+ authorizations: {
21
+ ...track.authorizations,
22
+ [framework]: {
23
+ ...prev,
24
+ doc_sessions: [...sessions],
25
+ sources: [...sources]
26
+ }
27
+ }
28
+ };
29
+ }
30
+ /** Record that a SOLID reference file was read (deduped). Immutable. */
31
+ function recordRefRead(track, path) {
32
+ return track.refsRead.includes(path) ? track : {
33
+ ...track,
34
+ refsRead: [...track.refsRead, path]
35
+ };
36
+ }
37
+ /** Record an agent/tool call with a timestamp. Immutable. */
38
+ function recordAgent(track, name, ts) {
39
+ return {
40
+ ...track,
41
+ agents: [...track.agents, {
42
+ name,
43
+ ts
44
+ }]
45
+ };
46
+ }
47
+ /** True when ALL of `names` were called within `windowMs` before `now`. */
48
+ function agentsFresh(track, names, windowMs, now) {
49
+ const cutoff = now - windowMs;
50
+ return names.every((n) => track.agents.some((a) => a.name === n && a.ts > cutoff));
51
+ }
52
+ //#endregion
53
+ //#region src/tracking/store.ts
54
+ /** Load a session track from a file (an empty track if absent/corrupt). */
55
+ async function loadTrack(file) {
56
+ return await readJsonFile(file) ?? emptyTrack();
57
+ }
58
+ /** Persist a session track. */
59
+ async function saveTrack(file, track) {
60
+ await writeJsonFile(file, track);
61
+ }
62
+ //#endregion
63
+ export { recordAgent as a, emptyTrack as i, saveTrack as n, recordDoc as o, agentsFresh as r, recordRefRead as s, loadTrack as t };
@@ -1,63 +1,2 @@
1
- import { n as readJsonFile, r as writeJsonFile } from "../json-io-RH82El2J.mjs";
2
- //#region src/tracking/session-state.ts
3
- /** A fresh, empty track. */
4
- function emptyTrack() {
5
- return {
6
- authorizations: {},
7
- refsRead: [],
8
- agents: []
9
- };
10
- }
11
- /** Record a doc consultation (Context7/Exa) for a framework in this session. Immutable. */
12
- function recordDoc(track, framework, sessionId, source) {
13
- const prev = track.authorizations[framework] ?? {};
14
- const sessions = new Set(prev.doc_sessions ?? []);
15
- sessions.add(sessionId);
16
- const sources = new Set(prev.sources ?? (prev.source ? [prev.source] : []));
17
- sources.add(source);
18
- return {
19
- ...track,
20
- authorizations: {
21
- ...track.authorizations,
22
- [framework]: {
23
- ...prev,
24
- doc_sessions: [...sessions],
25
- sources: [...sources]
26
- }
27
- }
28
- };
29
- }
30
- /** Record that a SOLID reference file was read (deduped). Immutable. */
31
- function recordRefRead(track, path) {
32
- return track.refsRead.includes(path) ? track : {
33
- ...track,
34
- refsRead: [...track.refsRead, path]
35
- };
36
- }
37
- /** Record an agent/tool call with a timestamp. Immutable. */
38
- function recordAgent(track, name, ts) {
39
- return {
40
- ...track,
41
- agents: [...track.agents, {
42
- name,
43
- ts
44
- }]
45
- };
46
- }
47
- /** True when ALL of `names` were called within `windowMs` before `now`. */
48
- function agentsFresh(track, names, windowMs, now) {
49
- const cutoff = now - windowMs;
50
- return names.every((n) => track.agents.some((a) => a.name === n && a.ts > cutoff));
51
- }
52
- //#endregion
53
- //#region src/tracking/store.ts
54
- /** Load a session track from a file (an empty track if absent/corrupt). */
55
- async function loadTrack(file) {
56
- return await readJsonFile(file) ?? emptyTrack();
57
- }
58
- /** Persist a session track. */
59
- async function saveTrack(file, track) {
60
- await writeJsonFile(file, track);
61
- }
62
- //#endregion
1
+ import { a as recordAgent, i as emptyTrack, n as saveTrack, o as recordDoc, r as agentsFresh, s as recordRefRead, t as loadTrack } from "../store-BWvwnnf6.mjs";
63
2
  export { agentsFresh, emptyTrack, loadTrack, recordAgent, recordDoc, recordRefRead, saveTrack };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fusengine/harness",
3
- "version": "0.1.4",
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",
@@ -24,6 +24,7 @@
24
24
  "./cli": { "bun": "./src/cli/index.ts", "types": "./dist/cli/index.d.mts", "import": "./dist/cli/index.mjs" },
25
25
  "./init": { "bun": "./src/init/index.ts", "types": "./dist/init/index.d.mts", "import": "./dist/init/index.mjs" },
26
26
  "./tracking": { "bun": "./src/tracking/index.ts", "types": "./dist/tracking/index.d.mts", "import": "./dist/tracking/index.mjs" },
27
+ "./runtime": { "bun": "./src/runtime/index.ts", "types": "./dist/runtime/index.d.mts", "import": "./dist/runtime/index.mjs" },
27
28
  "./adapters/claude": { "bun": "./src/adapters/claude/index.ts", "types": "./dist/adapters/claude/index.d.mts", "import": "./dist/adapters/claude/index.mjs" },
28
29
  "./adapters/codex": { "bun": "./src/adapters/codex/index.ts", "types": "./dist/adapters/codex/index.d.mts", "import": "./dist/adapters/codex/index.mjs" },
29
30
  "./adapters/cursor": { "bun": "./src/adapters/cursor/index.ts", "types": "./dist/adapters/cursor/index.d.mts", "import": "./dist/adapters/cursor/index.mjs" },
@@ -36,7 +37,7 @@
36
37
  "scripts": {
37
38
  "test": "bun test",
38
39
  "typecheck": "tsc --noEmit",
39
- "build": "tsdown src/index.ts src/config/index.ts src/util/index.ts src/detect/index.ts src/policy/index.ts src/prompt/index.ts src/memory/index.ts src/cache/index.ts src/freshness/index.ts src/refs/index.ts src/state/index.ts src/statusline/index.ts src/cli/index.ts src/cli/bin.ts src/init/index.ts src/tracking/index.ts src/adapters/claude/index.ts src/adapters/codex/index.ts src/adapters/cursor/index.ts src/adapters/cline/index.ts src/adapters/gemini/index.ts --dts --format esm --clean --out-dir dist",
40
+ "build": "tsdown src/index.ts src/config/index.ts src/util/index.ts src/detect/index.ts src/policy/index.ts src/prompt/index.ts src/memory/index.ts src/cache/index.ts src/freshness/index.ts src/refs/index.ts src/state/index.ts src/statusline/index.ts src/cli/index.ts src/cli/bin.ts src/init/index.ts src/tracking/index.ts src/runtime/index.ts src/adapters/claude/index.ts src/adapters/codex/index.ts src/adapters/cursor/index.ts src/adapters/cline/index.ts src/adapters/gemini/index.ts --dts --format esm --clean --out-dir dist",
40
41
  "prepublishOnly": "bun test && tsc --noEmit && bun run build"
41
42
  },
42
43
  "publishConfig": {