@fusengine/harness 0.1.63 → 0.1.64
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/adapters/claude/index.mjs +1 -1
- package/dist/adapters/codex/index.mjs +1 -1
- package/dist/adapters/hermes/index.mjs +1 -1
- package/dist/{claude-C0xGMbeA.mjs → claude-CaBe4eBY.mjs} +17 -5
- package/dist/cli/bin.mjs +29 -10
- package/dist/{handle-CjwRTMOv.mjs → handle-DE-753Mr.mjs} +56 -5
- package/dist/{hermes-C1gt6ooE.mjs → hermes-BdwBBemn.mjs} +1 -1
- package/dist/runtime/index.mjs +1 -1
- package/package.json +4 -1
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as fileSizeGuard, c as readClaudeInput, i as denyResponse, l as systemMessage, n as blockResponse, o as guard, r as contextResponse, s as informResponse, t as attachSystemMessage, u as toClaudeResponse } from "../../claude-
|
|
1
|
+
import { a as fileSizeGuard, c as readClaudeInput, i as denyResponse, l as systemMessage, n as blockResponse, o as guard, r as contextResponse, s as informResponse, t as attachSystemMessage, u as toClaudeResponse } from "../../claude-CaBe4eBY.mjs";
|
|
2
2
|
export { attachSystemMessage, blockResponse, contextResponse, denyResponse, fileSizeGuard, guard, informResponse, readClaudeInput, systemMessage, toClaudeResponse };
|
|
@@ -2,7 +2,7 @@ import { f as countLines } from "../../home-state-D0RLWP8J.mjs";
|
|
|
2
2
|
import { t as evaluate } from "../../evaluate-wDDbojx6.mjs";
|
|
3
3
|
import { t as formatPrompt } from "../../types-ernB1Dy3.mjs";
|
|
4
4
|
import { t as parseApplyPatch } from "../../apply-patch-CIS2EZ_q.mjs";
|
|
5
|
-
import {
|
|
5
|
+
import { c as readClaudeInput, i as denyResponse, r as contextResponse, v as commandToString } from "../../claude-CaBe4eBY.mjs";
|
|
6
6
|
//#region src/adapters/codex/index.ts
|
|
7
7
|
/**
|
|
8
8
|
* OpenAI Codex CLI adapter (hook-mode). Codex's `PreToolUse` hook (since 2026)
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as readHermesInput, r as toHermesResponse, t as guard } from "../../hermes-
|
|
1
|
+
import { n as readHermesInput, r as toHermesResponse, t as guard } from "../../hermes-BdwBBemn.mjs";
|
|
2
2
|
export { guard, readHermesInput, toHermesResponse };
|
|
@@ -81,11 +81,23 @@ function spawnCapture(cmd, args, cwd) {
|
|
|
81
81
|
return "";
|
|
82
82
|
}
|
|
83
83
|
}
|
|
84
|
-
/**
|
|
84
|
+
/**
|
|
85
|
+
* Read the full process stdin as UTF-8 text (works under Node and Bun).
|
|
86
|
+
* Synchronous fd-0 read — never `for await (const c of process.stdin)` —
|
|
87
|
+
* because Bun has a confirmed Linux-only bug where merely adding a new
|
|
88
|
+
* top-level module import shifts stdin's internal init order and makes
|
|
89
|
+
* that async iterator silently yield zero bytes (oven-sh/bun#25320,
|
|
90
|
+
* #27849): exactly what broke every `harness hook` invocation on CI the
|
|
91
|
+
* moment `figures` became this package's first runtime dependency.
|
|
92
|
+
* `readFileSync(0)` bypasses that stream/ownership machinery entirely and
|
|
93
|
+
* is well-supported for piped (non-TTY) stdin under both runtimes.
|
|
94
|
+
*/
|
|
85
95
|
async function readStdin() {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
96
|
+
try {
|
|
97
|
+
return readFileSync(0, "utf8");
|
|
98
|
+
} catch {
|
|
99
|
+
return "";
|
|
100
|
+
}
|
|
89
101
|
}
|
|
90
102
|
/**
|
|
91
103
|
* Recursively collect files under `dir` whose extension is in `exts`, skipping
|
|
@@ -214,4 +226,4 @@ function guard(input) {
|
|
|
214
226
|
/** @deprecated use {@link guard}. Kept for back-compat. */
|
|
215
227
|
const fileSizeGuard = guard;
|
|
216
228
|
//#endregion
|
|
217
|
-
export {
|
|
229
|
+
export { writeText as _, fileSizeGuard as a, readClaudeInput as c, collectFiles as d, pathExists as f, spawnCapture as g, sleep as h, denyResponse as i, systemMessage as l, readText as m, blockResponse as n, guard as o, readStdin as p, contextResponse as r, informResponse as s, attachSystemMessage as t, toClaudeResponse as u, commandToString as v };
|
package/dist/cli/bin.mjs
CHANGED
|
@@ -4,7 +4,8 @@ import { t as detectHarness } from "../harness-Cb9xR8dC.mjs";
|
|
|
4
4
|
import { t as claudeHome } from "../home-state-D0RLWP8J.mjs";
|
|
5
5
|
import { n as stagedContent, r as stagedFiles, t as checkStaged } from "../run-kVHXFVug.mjs";
|
|
6
6
|
import { n as writeInitFile, t as initFor } from "../run-Do2JltgU.mjs";
|
|
7
|
-
import { J as runningVersion, Lt as todayUtc, Y as versionBanner, q as runDoctor, t as handleHook } from "../handle-
|
|
7
|
+
import { J as runningVersion, Lt as todayUtc, Y as versionBanner, q as runDoctor, t as handleHook } from "../handle-DE-753Mr.mjs";
|
|
8
|
+
import { p as readStdin$1 } from "../claude-CaBe4eBY.mjs";
|
|
8
9
|
import { delimiter, join } from "node:path";
|
|
9
10
|
import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
|
|
10
11
|
import { homedir } from "node:os";
|
|
@@ -361,15 +362,19 @@ function discoverRefs(home, cwd, marketplaces) {
|
|
|
361
362
|
* harness hook <id> runtime: read a hook payload on stdin, route to the adapter, print the response
|
|
362
363
|
* harness changelog fetch + diff the Claude Code changelog, print a JSON summary (changelog-watcher)
|
|
363
364
|
*/
|
|
365
|
+
const hookDebug = process.env.FUSE_HARNESS_DEBUG === "1";
|
|
366
|
+
function traceHook(label, data) {
|
|
367
|
+
if (hookDebug) process.stderr.write(`[hook-debug] ${label}: ${typeof data === "string" ? data : JSON.stringify(data)}\n`);
|
|
368
|
+
}
|
|
364
369
|
async function readStdin() {
|
|
365
|
-
const
|
|
366
|
-
|
|
367
|
-
const text = Buffer.concat(chunks).toString("utf8").trim();
|
|
370
|
+
const text = (await readStdin$1()).trim();
|
|
371
|
+
traceHook("stdin-text-length", text.length);
|
|
368
372
|
if (!text) return {};
|
|
369
373
|
try {
|
|
370
374
|
const parsed = JSON.parse(text);
|
|
371
375
|
return typeof parsed === "object" && parsed !== null ? parsed : {};
|
|
372
|
-
} catch {
|
|
376
|
+
} catch (e) {
|
|
377
|
+
traceHook("stdin-parse-error", e instanceof Error ? e.message : String(e));
|
|
373
378
|
return {};
|
|
374
379
|
}
|
|
375
380
|
}
|
|
@@ -399,13 +404,27 @@ if (cmd === "--version" || cmd === "-v") {
|
|
|
399
404
|
])).has(scopeArg) ? scopeArg : "core";
|
|
400
405
|
const marketplaces = (process.env.FUSE_HARNESS_MARKETPLACES ?? "fusengine-plugins").split(",").map((s) => s.trim()).filter(Boolean);
|
|
401
406
|
const refsDir = process.env.FUSE_HARNESS_REFS || discoverRefs(homedir(), process.cwd(), marketplaces) || void 0;
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
cwd: process.cwd(),
|
|
405
|
-
refsDir,
|
|
406
|
-
windowMs: resolveTtlSec(process.env) * 1e3,
|
|
407
|
+
traceHook("args", {
|
|
408
|
+
id,
|
|
407
409
|
scope
|
|
408
410
|
});
|
|
411
|
+
let outcome;
|
|
412
|
+
try {
|
|
413
|
+
outcome = await handleHook(id, await readStdin(), {
|
|
414
|
+
now: Date.now(),
|
|
415
|
+
cwd: process.cwd(),
|
|
416
|
+
refsDir,
|
|
417
|
+
windowMs: resolveTtlSec(process.env) * 1e3,
|
|
418
|
+
scope
|
|
419
|
+
});
|
|
420
|
+
} catch (e) {
|
|
421
|
+
traceHook("handleHook-threw", e instanceof Error ? `${e.message}\n${e.stack}` : String(e));
|
|
422
|
+
throw e;
|
|
423
|
+
}
|
|
424
|
+
traceHook("outcome", {
|
|
425
|
+
stdoutLength: outcome.stdout.length,
|
|
426
|
+
exit: outcome.exit
|
|
427
|
+
});
|
|
409
428
|
if (outcome.stdout) process.stdout.write(outcome.stdout);
|
|
410
429
|
process.exit(outcome.exit);
|
|
411
430
|
} else if (cmd === "init") {
|
|
@@ -14,8 +14,8 @@ import { d as loadIndex, i as cacheLookupMeta, n as webfetchCacheWrite, o as cac
|
|
|
14
14
|
import { t as loadRefs } from "./loader-AGz4nK7d.mjs";
|
|
15
15
|
import { a as writeLastNonce, c as recordAgent, d as recordRefRead, f as recordTarget, h as apexAuthorizationGate, i as verifyTrack, l as recordBrainstormRequired, m as trivialCount, n as saveTrack, o as agentsFresh, p as recordTrivialEdit, r as signTrack, s as emptyTrack, t as loadTrack, u as recordDoc } from "./store-CQ4roWrU.mjs";
|
|
16
16
|
import { t as parseApplyPatch } from "./apply-patch-CIS2EZ_q.mjs";
|
|
17
|
-
import { _ as
|
|
18
|
-
import { r as toHermesResponse } from "./hermes-
|
|
17
|
+
import { _ as writeText, d as collectFiles, f as pathExists, g as spawnCapture, h as sleep, i as denyResponse, l as systemMessage, m as readText, n as blockResponse, r as contextResponse, s as informResponse, t as attachSystemMessage, v as commandToString } from "./claude-CaBe4eBY.mjs";
|
|
18
|
+
import { r as toHermesResponse } from "./hermes-BdwBBemn.mjs";
|
|
19
19
|
import { basename, dirname, extname, join, relative, resolve, sep } from "node:path";
|
|
20
20
|
import { appendFileSync, copyFileSync, existsSync, mkdirSync, readFileSync, readdirSync, renameSync, rmSync, rmdirSync, statSync, unlinkSync, writeFileSync } from "node:fs";
|
|
21
21
|
import { homedir } from "node:os";
|
|
@@ -23,6 +23,7 @@ import { mkdir, rmdir } from "node:fs/promises";
|
|
|
23
23
|
import { createHash } from "node:crypto";
|
|
24
24
|
import { execFileSync, execSync } from "node:child_process";
|
|
25
25
|
import { fileURLToPath } from "node:url";
|
|
26
|
+
import figures from "figures";
|
|
26
27
|
//#region src/runtime/lifecycle/security/skill-state.ts
|
|
27
28
|
/**
|
|
28
29
|
* Shared security-tracker state: per-UTC-day JSON under
|
|
@@ -7053,6 +7054,56 @@ function respond(id, prompt) {
|
|
|
7053
7054
|
}
|
|
7054
7055
|
}
|
|
7055
7056
|
//#endregion
|
|
7057
|
+
//#region src/runtime/deny-notice.ts
|
|
7058
|
+
/**
|
|
7059
|
+
* @module deny-notice
|
|
7060
|
+
* Attach a user-visible notice to a deny/ask hook response — the owner-reported
|
|
7061
|
+
* gap where `permissionDecision: deny/ask` (the agent-only channel) left the
|
|
7062
|
+
* human staring at a silent terminal. Mirrors {@link module:notices}'s
|
|
7063
|
+
* compliance notices but for the BLOCKING outcomes those never covered.
|
|
7064
|
+
* @packageDocumentation
|
|
7065
|
+
*/
|
|
7066
|
+
/**
|
|
7067
|
+
* The human-facing line for a block/ask outcome: the gate's own
|
|
7068
|
+
* {@link Prompt.userMessage} when it set one, else a generic symbol + title —
|
|
7069
|
+
* text-presentation Unicode only (`figures.cross`/`?`), never emoji: terminal-safe,
|
|
7070
|
+
* single-cell width, with the Windows fallbacks `figures` already resolves, matching
|
|
7071
|
+
* the existing notice family (`notices.ts`'s `✓`/`⚠`, left untouched by this module).
|
|
7072
|
+
* Null for `inform` ({@link module:respond}'s own `userMessage` path already
|
|
7073
|
+
* covers it) or when neither applies.
|
|
7074
|
+
*/
|
|
7075
|
+
function denyAskNotice(prompt) {
|
|
7076
|
+
if (prompt.kind === "block") return prompt.userMessage ?? `${figures.cross} ${prompt.title}`;
|
|
7077
|
+
if (prompt.kind === "ask") return prompt.userMessage ?? `? ${prompt.title}`;
|
|
7078
|
+
return null;
|
|
7079
|
+
}
|
|
7080
|
+
/**
|
|
7081
|
+
* Attach {@link denyAskNotice} onto an already-rendered deny/ask `stdout`, for
|
|
7082
|
+
* the harnesses whose human channel is `systemMessage` (claude-code/codex —
|
|
7083
|
+
* `permissionDecision`/`permissionDecisionReason` stay byte-intact, only the
|
|
7084
|
+
* top-level field is added). Every other harness passes `stdout` through
|
|
7085
|
+
* unchanged: Cursor already emits `user_message` natively (respond.ts), Hermes
|
|
7086
|
+
* and cline have no human channel. Deduped via {@link onceExclusive} against
|
|
7087
|
+
* the ~11 sibling-plugin fan-out for one real event (same window as the
|
|
7088
|
+
* sniper reminder / compliance notices).
|
|
7089
|
+
* @param id - Harness id (`ctx.id` from `PreContext`).
|
|
7090
|
+
* @param stdout - The rendered hook response (from {@link module:respond.respond}).
|
|
7091
|
+
* @param prompt - The {@link Prompt} that produced `stdout`.
|
|
7092
|
+
* @param sessionId - Current session id (dedup scope).
|
|
7093
|
+
* @param dir - State-dir for the dedup marker (per-project state dir).
|
|
7094
|
+
* @param now - Event clock (tests pass a fake one).
|
|
7095
|
+
*/
|
|
7096
|
+
function withDenyNotice(id, stdout, prompt, sessionId, dir, now) {
|
|
7097
|
+
if (id !== "claude-code" && id !== "codex") return stdout;
|
|
7098
|
+
const notice = denyAskNotice(prompt);
|
|
7099
|
+
if (!notice) return stdout;
|
|
7100
|
+
if (!onceExclusive(`deny-notice:${sessionId}:${prompt.title}`, 2e3, {
|
|
7101
|
+
now,
|
|
7102
|
+
dir
|
|
7103
|
+
})) return stdout;
|
|
7104
|
+
return attachSystemMessage(stdout, notice);
|
|
7105
|
+
}
|
|
7106
|
+
//#endregion
|
|
7056
7107
|
//#region src/policy/design/content-checks.ts
|
|
7057
7108
|
/** Accessibility warnings: icon buttons need aria-label, images need alt. */
|
|
7058
7109
|
function checkAccessibility(content) {
|
|
@@ -7618,7 +7669,7 @@ async function handlePre(ctx) {
|
|
|
7618
7669
|
}
|
|
7619
7670
|
const designBlock = designGate(payload, event, mcpDir, opts.cwd);
|
|
7620
7671
|
if (designBlock) return {
|
|
7621
|
-
stdout: respond(id, designBlock),
|
|
7672
|
+
stdout: withDenyNotice(id, respond(id, designBlock), designBlock, event.sessionId, dirname(file), opts.now),
|
|
7622
7673
|
exit: 0
|
|
7623
7674
|
};
|
|
7624
7675
|
if (opts.scope === "security") return {
|
|
@@ -7639,7 +7690,7 @@ async function handlePre(ctx) {
|
|
|
7639
7690
|
if (event.files && event.files.length > 0) {
|
|
7640
7691
|
const patchPrompt = applyPatchGate(event.files, opts.cwd);
|
|
7641
7692
|
if (patchPrompt) return {
|
|
7642
|
-
stdout: respond(id, patchPrompt),
|
|
7693
|
+
stdout: withDenyNotice(id, respond(id, patchPrompt), patchPrompt, event.sessionId, dirname(file), opts.now),
|
|
7643
7694
|
exit: 0
|
|
7644
7695
|
};
|
|
7645
7696
|
}
|
|
@@ -7661,7 +7712,7 @@ async function handlePre(ctx) {
|
|
|
7661
7712
|
transcriptPath: typeof payload.transcript_path === "string" ? payload.transcript_path : void 0
|
|
7662
7713
|
});
|
|
7663
7714
|
if (prompt) return {
|
|
7664
|
-
stdout: respond(id, prompt),
|
|
7715
|
+
stdout: withDenyNotice(id, respond(id, prompt), prompt, event.sessionId, dirname(file), opts.now),
|
|
7665
7716
|
exit: 0
|
|
7666
7717
|
};
|
|
7667
7718
|
return allowOutcome(id, event, payload, mcpDir, opts.cwd, {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { t as evaluate } from "./evaluate-wDDbojx6.mjs";
|
|
2
2
|
import { t as formatPrompt } from "./types-ernB1Dy3.mjs";
|
|
3
|
-
import {
|
|
3
|
+
import { c as readClaudeInput, v as commandToString } from "./claude-CaBe4eBY.mjs";
|
|
4
4
|
//#region src/adapters/hermes/index.ts
|
|
5
5
|
/**
|
|
6
6
|
* Hermes Agent adapter (hook-mode). Nous Research's hermes-agent (2026) pipes a
|
package/dist/runtime/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { r as projectLayout } from "../layout-C0jaaCQC.mjs";
|
|
2
2
|
import { a as sanitizeSessionId, c as sessionsDir, i as loadSessionState, n as fuseHarnessHome, o as saveSessionState, r as fusengineCache, s as sessionStatePath, t as claudeHome } from "../home-state-D0RLWP8J.mjs";
|
|
3
|
-
import { $ as postEditTypescript, A as trackSkillRead, At as trackFile, B as isProject, C as seoPostToolUse, Ct as gitContext, D as postTrackingSideEffects, Dt as taskContext, E as securityAdvisory, Et as promptSubmitContext, F as dispatchLessons, Ft as securityStateDir, G as getFileDesc, H as loadEnriched, I as cartoSessionStart, It as securityStatePath, K as listChildren, L as generateEcosystemMap, Lt as todayUtc, M as dispatchLifecycle, Mt as isoUtc, N as aipilotPostToolUse, Nt as loadSecurityState, O as trackWatchResearch, Ot as defaultStateDir, P as dispatchAipilot, Pt as saveSecurityState, Q as lessonsStateFileFor, R as writePluginMap, S as postEditContext, St as devContext, T as dispatchMemory, Tt as claudeMdKey, U as mergeLines, V as writeTree, W as countFiles, X as lessonsArchiveFileFor, Z as lessonsFileFor, _ as preCommitGate, _t as sessionStartCore, a as recordActivity, at as validateTeammateOutput, b as extractSymbols, bt as removeOldFiles, c as MCP_TTL_MS, ct as validateTailwind, d as isMcpTool, dt as countLoc, et as trackSessionChanges, f as queryOf, ft as detectSolidProfile, g as gate, gt as runSessionStartCleanups, h as TRIVIAL_BUDGET, ht as readRules, i as respond, it as logToolFailure, j as trackEnrichment, jt as normalizeEvent, k as trackMcpResearch, kt as projectHash, l as WEBFETCH_TTL_MS, lt as validateSolidGate, m as REQUIRED_AGENTS, mt as injectRules, n as activityFor, nt as cleanupSession, o as mcpPostStore, ot as trackAgentMemory, p as DEFAULT_WINDOW_MS, pt as solidDetectStart, r as handlePre, rt as saveApexState, s as mcpPreIntercept, st as subagentCacheContext, t as handleHook, tt as validateRulesLoaded, u as cacheQueryOf, ut as checkFileSize, v as detectDuplication, vt as pruneEmptyDirs, w as seoPostToolUseResponse, wt as projectContext, x as lifecycleStdout, xt as trimLogFile, y as dryGate, yt as purgeTtlTree, z as generateProjectMap } from "../handle-
|
|
3
|
+
import { $ as postEditTypescript, A as trackSkillRead, At as trackFile, B as isProject, C as seoPostToolUse, Ct as gitContext, D as postTrackingSideEffects, Dt as taskContext, E as securityAdvisory, Et as promptSubmitContext, F as dispatchLessons, Ft as securityStateDir, G as getFileDesc, H as loadEnriched, I as cartoSessionStart, It as securityStatePath, K as listChildren, L as generateEcosystemMap, Lt as todayUtc, M as dispatchLifecycle, Mt as isoUtc, N as aipilotPostToolUse, Nt as loadSecurityState, O as trackWatchResearch, Ot as defaultStateDir, P as dispatchAipilot, Pt as saveSecurityState, Q as lessonsStateFileFor, R as writePluginMap, S as postEditContext, St as devContext, T as dispatchMemory, Tt as claudeMdKey, U as mergeLines, V as writeTree, W as countFiles, X as lessonsArchiveFileFor, Z as lessonsFileFor, _ as preCommitGate, _t as sessionStartCore, a as recordActivity, at as validateTeammateOutput, b as extractSymbols, bt as removeOldFiles, c as MCP_TTL_MS, ct as validateTailwind, d as isMcpTool, dt as countLoc, et as trackSessionChanges, f as queryOf, ft as detectSolidProfile, g as gate, gt as runSessionStartCleanups, h as TRIVIAL_BUDGET, ht as readRules, i as respond, it as logToolFailure, j as trackEnrichment, jt as normalizeEvent, k as trackMcpResearch, kt as projectHash, l as WEBFETCH_TTL_MS, lt as validateSolidGate, m as REQUIRED_AGENTS, mt as injectRules, n as activityFor, nt as cleanupSession, o as mcpPostStore, ot as trackAgentMemory, p as DEFAULT_WINDOW_MS, pt as solidDetectStart, r as handlePre, rt as saveApexState, s as mcpPreIntercept, st as subagentCacheContext, t as handleHook, tt as validateRulesLoaded, u as cacheQueryOf, ut as checkFileSize, v as detectDuplication, vt as pruneEmptyDirs, w as seoPostToolUseResponse, wt as projectContext, x as lifecycleStdout, xt as trimLogFile, y as dryGate, yt as purgeTtlTree, z as generateProjectMap } from "../handle-DE-753Mr.mjs";
|
|
4
4
|
//#region src/runtime/storage.ts
|
|
5
5
|
/**
|
|
6
6
|
* The project's single state dir (`<root>/.harness`) — neutral + harness-agnostic,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fusengine/harness",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.64",
|
|
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",
|
|
@@ -152,5 +152,8 @@
|
|
|
152
152
|
"tsdown": "^0.22.3",
|
|
153
153
|
"typedoc": "^0.28.19",
|
|
154
154
|
"typescript": "^6.0.3"
|
|
155
|
+
},
|
|
156
|
+
"dependencies": {
|
|
157
|
+
"figures": "^6.1.0"
|
|
155
158
|
}
|
|
156
159
|
}
|