@xmoon76/dsh-pi-tui 0.3.0 → 0.3.2
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/builtins.mjs +1 -1
- package/dist/extension/advanced.d.mts +1 -1
- package/dist/extension/unstable.d.mts +1 -1
- package/dist/extensions.d.mts +1 -1
- package/dist/extensions.mjs +1 -1
- package/dist/index.d.mts +114 -12
- package/dist/index.mjs +2 -2
- package/dist/{public-types-2omeXG8d.d.mts → public-types-CZz5_arj.d.mts} +3 -0
- package/dist/{src-ClAKiW0z.mjs → src-oZjot5jQ.mjs} +2925 -191
- package/dist/startup.d.mts +41 -1
- package/dist/startup.mjs +99 -2
- package/package.json +1 -1
- package/scripts/bench.mts +6 -0
- package/scripts/preview-prompt.mts +62 -0
- package/scripts/preview-role-styles.mts +97 -0
- package/scripts/tarball-smoke.mjs +6 -2
package/dist/startup.d.mts
CHANGED
|
@@ -5,6 +5,46 @@ import { Context } from "@deepseek-ai/cordis";
|
|
|
5
5
|
declare const name = "tui-startup";
|
|
6
6
|
/** Services required before the flags can be resolved. */
|
|
7
7
|
declare const inject: string[];
|
|
8
|
+
/** One incompatible dsh harness range and the guidance it deserves. Add a
|
|
9
|
+
* new entry here whenever a future bundle release stops supporting an
|
|
10
|
+
* older (or newer) harness line; entries are checked in ORDER and the
|
|
11
|
+
* first whose range covers the installed dsh version wins.
|
|
12
|
+
*
|
|
13
|
+
* Range semantics: `min` is inclusive, `max` is EXCLUSIVE. An entry with
|
|
14
|
+
* only `max` covers everything below it (the common "too old" case); an
|
|
15
|
+
* entry with only `min` covers everything at or above it ("too new" —
|
|
16
|
+
* e.g. a harness that removed a seam we still use).
|
|
17
|
+
*
|
|
18
|
+
* `since` names the bundle release line that FIRST imposed the constraint:
|
|
19
|
+
* it is shown as the fallback version label (`>= <since>`) when the
|
|
20
|
+
* bundle's own version cannot be read, so the message stays truthful.
|
|
21
|
+
*/
|
|
22
|
+
interface HarnessCompatEntry {
|
|
23
|
+
/** Inclusive lower bound of the incompatible range; absent = unbounded below. */
|
|
24
|
+
min?: string;
|
|
25
|
+
/** Exclusive upper bound of the incompatible range; absent = unbounded above. */
|
|
26
|
+
max?: string;
|
|
27
|
+
/** The bundle release line that first required this constraint. */
|
|
28
|
+
since: string;
|
|
29
|
+
/** Human-readable requirement, e.g. `DeepSeek Harness 0.1.1-rc.1 or later`. */
|
|
30
|
+
requires: string;
|
|
31
|
+
/** What the user must do; placeholders are NOT needed — the message
|
|
32
|
+
* builder fills in the requirement and the installed version. */
|
|
33
|
+
guidance: string;
|
|
34
|
+
}
|
|
35
|
+
/** The compatibility table. */
|
|
36
|
+
declare const HARNESS_COMPAT: readonly HarnessCompatEntry[];
|
|
37
|
+
/** The compat entry covering the installed dsh version, or undefined when
|
|
38
|
+
* the harness is supported. */
|
|
39
|
+
declare function harnessCompatEntryFor(installed: string): HarnessCompatEntry | undefined;
|
|
40
|
+
/** The bundle's own version label for the gate message, read from
|
|
41
|
+
* package.json at runtime (never hardcoded). Falls back to the release
|
|
42
|
+
* line that first imposed the requirement when unreadable. */
|
|
43
|
+
declare function bundleVersionLabel(since: string): string;
|
|
44
|
+
/** The actionable message printed before the loader's raw failure when the
|
|
45
|
+
* installed harness falls in an incompatible range. `entry` MUST be the
|
|
46
|
+
* entry {@link harnessCompatEntryFor} matched for `installed`. */
|
|
47
|
+
declare function incompatibleHarnessMessage(installed: string, entry: HarnessCompatEntry): string;
|
|
8
48
|
/** Service provided by this plugin and injected by the TUI runner row. */
|
|
9
49
|
declare const TUI_STARTUP_SERVICE = "tuiStartup";
|
|
10
50
|
/** What the runner row reads from {@link TUI_STARTUP_SERVICE}. */
|
|
@@ -29,4 +69,4 @@ interface TuiStartupValues {
|
|
|
29
69
|
*/
|
|
30
70
|
declare function apply(ctx: Context): void;
|
|
31
71
|
//#endregion
|
|
32
|
-
export { TUI_STARTUP_SERVICE, TuiStartupValues, apply, inject, name };
|
|
72
|
+
export { HARNESS_COMPAT, HarnessCompatEntry, TUI_STARTUP_SERVICE, TuiStartupValues, apply, bundleVersionLabel, harnessCompatEntryFor, incompatibleHarnessMessage, inject, name };
|
package/dist/startup.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { readFileSync, realpathSync } from "node:fs";
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
2
3
|
import { Command } from "commander";
|
|
3
4
|
import { parseCmdline } from "@deepseek-ai/dsh-cmdline";
|
|
4
5
|
//#region src/startup.ts
|
|
@@ -9,10 +10,97 @@ import { parseCmdline } from "@deepseek-ai/dsh-cmdline";
|
|
|
9
10
|
* `cmdlineArgs`, providing a service that flag-configured rows inject.
|
|
10
11
|
* @module @xmoon76/dsh-pi-tui/startup
|
|
11
12
|
*/
|
|
13
|
+
/** The installed dsh version, resolved from the launcher's real path. */
|
|
14
|
+
function installedDshVersion() {
|
|
15
|
+
const bin = process.argv[1];
|
|
16
|
+
if (bin === void 0) return void 0;
|
|
17
|
+
try {
|
|
18
|
+
let dir = dirname(realpathSync(bin));
|
|
19
|
+
for (let depth = 0; depth < 8; depth += 1) {
|
|
20
|
+
try {
|
|
21
|
+
const pkg = JSON.parse(readFileSync(join(dir, "package.json"), "utf8"));
|
|
22
|
+
if (pkg.name === "@deepseek-ai/dsh" && typeof pkg.version === "string") return pkg.version;
|
|
23
|
+
} catch {}
|
|
24
|
+
const parent = dirname(dir);
|
|
25
|
+
if (parent === dir) return void 0;
|
|
26
|
+
dir = parent;
|
|
27
|
+
}
|
|
28
|
+
} catch {}
|
|
29
|
+
}
|
|
30
|
+
/** Prerelease-aware `a >= b` (semver ordering; mirrors src/dsh-version.ts). */
|
|
31
|
+
function versionAtLeast(version, minimum) {
|
|
32
|
+
const parse = (value) => {
|
|
33
|
+
const [core, prerelease = ""] = value.split("-");
|
|
34
|
+
return {
|
|
35
|
+
nums: core.split(".").map(Number),
|
|
36
|
+
pre: prerelease === "" ? [] : prerelease.split(".")
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
const a = parse(version);
|
|
40
|
+
const b = parse(minimum);
|
|
41
|
+
for (let i = 0; i < 3; i += 1) {
|
|
42
|
+
const pa = a.nums[i] ?? 0;
|
|
43
|
+
const pb = b.nums[i] ?? 0;
|
|
44
|
+
if (pa !== pb) return pa > pb;
|
|
45
|
+
}
|
|
46
|
+
if (a.pre.length === 0) return true;
|
|
47
|
+
if (b.pre.length === 0) return false;
|
|
48
|
+
const length = Math.max(a.pre.length, b.pre.length);
|
|
49
|
+
for (let i = 0; i < length; i += 1) {
|
|
50
|
+
const pa = a.pre[i];
|
|
51
|
+
const pb = b.pre[i];
|
|
52
|
+
if (pa === void 0) return false;
|
|
53
|
+
if (pb === void 0) return true;
|
|
54
|
+
if (pa === pb) continue;
|
|
55
|
+
const na = Number(pa);
|
|
56
|
+
const nb = Number(pb);
|
|
57
|
+
const naNumeric = !Number.isNaN(na);
|
|
58
|
+
const nbNumeric = !Number.isNaN(nb);
|
|
59
|
+
if (naNumeric && nbNumeric) return na > nb;
|
|
60
|
+
if (naNumeric !== nbNumeric) return !naNumeric;
|
|
61
|
+
return pa > pb;
|
|
62
|
+
}
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
12
65
|
/** Stable Cordis plugin name. */
|
|
13
66
|
const name = "tui-startup";
|
|
14
67
|
/** Services required before the flags can be resolved. */
|
|
15
68
|
const inject = ["cmdlineArgs"];
|
|
69
|
+
/** The compatibility table. */
|
|
70
|
+
const HARNESS_COMPAT = [{
|
|
71
|
+
max: "0.1.1-rc.1",
|
|
72
|
+
since: "0.3.0",
|
|
73
|
+
requires: "DeepSeek Harness 0.1.1-rc.1 or later",
|
|
74
|
+
guidance: "Upgrade dsh first, e.g.: npm install -g @deepseek-ai/dsh@0.1.1-rc.1"
|
|
75
|
+
}];
|
|
76
|
+
/** The compat entry covering the installed dsh version, or undefined when
|
|
77
|
+
* the harness is supported. */
|
|
78
|
+
function harnessCompatEntryFor(installed) {
|
|
79
|
+
return HARNESS_COMPAT.find((entry) => (entry.min === void 0 || versionAtLeast(installed, entry.min)) && (entry.max === void 0 || !versionAtLeast(installed, entry.max)));
|
|
80
|
+
}
|
|
81
|
+
/** The bundle's own version label for the gate message, read from
|
|
82
|
+
* package.json at runtime (never hardcoded). Falls back to the release
|
|
83
|
+
* line that first imposed the requirement when unreadable. */
|
|
84
|
+
function bundleVersionLabel(since) {
|
|
85
|
+
try {
|
|
86
|
+
const pkg = JSON.parse(readFileSync(join(import.meta.dirname, "..", "package.json"), "utf8"));
|
|
87
|
+
return pkg.version === void 0 || pkg.version === "" ? `>= ${since}` : `v${pkg.version}`;
|
|
88
|
+
} catch {
|
|
89
|
+
return `>= ${since}`;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
/** The actionable message printed before the loader's raw failure when the
|
|
93
|
+
* installed harness falls in an incompatible range. `entry` MUST be the
|
|
94
|
+
* entry {@link harnessCompatEntryFor} matched for `installed`. */
|
|
95
|
+
function incompatibleHarnessMessage(installed, entry) {
|
|
96
|
+
return [
|
|
97
|
+
`dsh-pi-tui ${bundleVersionLabel(entry.since)} requires ${entry.requires},`,
|
|
98
|
+
`but this installation is running dsh ${installed}.`,
|
|
99
|
+
"",
|
|
100
|
+
`${entry.guidance}`,
|
|
101
|
+
"Then re-run: dsh --profile pi-tui"
|
|
102
|
+
].join("\n");
|
|
103
|
+
}
|
|
16
104
|
/** Service provided by this plugin and injected by the TUI runner row. */
|
|
17
105
|
const TUI_STARTUP_SERVICE = "tuiStartup";
|
|
18
106
|
/** This app's command: its flags, its description, and its help text. */
|
|
@@ -33,6 +121,15 @@ Examples:
|
|
|
33
121
|
function apply(ctx) {
|
|
34
122
|
const program = tuiCommand();
|
|
35
123
|
program.action(() => {
|
|
124
|
+
const installed = installedDshVersion();
|
|
125
|
+
if (installed !== void 0) {
|
|
126
|
+
const entry = harnessCompatEntryFor(installed);
|
|
127
|
+
if (entry !== void 0) {
|
|
128
|
+
const message = incompatibleHarnessMessage(installed, entry);
|
|
129
|
+
process.stderr.write(`\n${message}\n\n`);
|
|
130
|
+
throw new Error(message);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
36
133
|
const options = program.opts();
|
|
37
134
|
ctx.provide(TUI_STARTUP_SERVICE, {
|
|
38
135
|
...options.session !== void 0 ? { sessionId: options.session } : {},
|
|
@@ -43,4 +140,4 @@ function apply(ctx) {
|
|
|
43
140
|
parseCmdline(ctx, program);
|
|
44
141
|
}
|
|
45
142
|
//#endregion
|
|
46
|
-
export { TUI_STARTUP_SERVICE, apply, inject, name };
|
|
143
|
+
export { HARNESS_COMPAT, TUI_STARTUP_SERVICE, apply, bundleVersionLabel, harnessCompatEntryFor, incompatibleHarnessMessage, inject, name };
|
package/package.json
CHANGED
package/scripts/bench.mts
CHANGED
|
@@ -52,6 +52,12 @@ class BenchTerminal {
|
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
// --- synthetic session content ---------------------------------------------
|
|
55
|
+
// NOTE: the CJK strings below are FUNCTIONAL benchmark fixtures, not
|
|
56
|
+
// user-facing copy: the wide-grapheme samples exercise the CJK width
|
|
57
|
+
// paths (get-east-asian-width, wrap + emoji) whose cost this script
|
|
58
|
+
// measures. The English-only rule applies to user-facing strings and
|
|
59
|
+
// comments; these samples are deliberately CJK — an English-only fixture
|
|
60
|
+
// would silently drop the wide-character code path from the benchmark.
|
|
55
61
|
|
|
56
62
|
const MARKDOWN_BLOCKS = [
|
|
57
63
|
'## Findings\n\nThe **cache** now hits for unchanged messages, so `markdown` is not re-parsed every frame.\n\n```ts\nconst hit = cached.text === message.text\n```\n\n- one\n- two\n- three',
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Visual preview of the editor `❯` prompt + the transcript user-role
|
|
3
|
+
* styling — run inside a real TTY (tmux):
|
|
4
|
+
*
|
|
5
|
+
* env -u NO_COLOR node --import tsx/esm scripts/preview-prompt.mts
|
|
6
|
+
*
|
|
7
|
+
* Shows a transcript mixing user / assistant / thinking / system rows and
|
|
8
|
+
* alternates the editor between an EMPTY draft (the `❯ ` prompt with the
|
|
9
|
+
* cursor block) and a multi-line draft (the prompt leads the first line,
|
|
10
|
+
* continuation lines indent under it, exactly like the transcript rows).
|
|
11
|
+
* `PREVIEW_HOLD_MS` controls how long it stays up (default 30s); Ctrl+C
|
|
12
|
+
* also exits.
|
|
13
|
+
* @module @xmoon76/dsh-pi-tui/preview-prompt
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { ProcessTerminal } from '@xmoon76/pi-tui'
|
|
17
|
+
import { TuiApp } from '../src/tui-app.ts'
|
|
18
|
+
|
|
19
|
+
const holdMs = Number(process.env.PREVIEW_HOLD_MS ?? 30000)
|
|
20
|
+
|
|
21
|
+
const terminal = new ProcessTerminal()
|
|
22
|
+
const app = new TuiApp(terminal, {
|
|
23
|
+
onSubmit: () => {},
|
|
24
|
+
onExit: () => {
|
|
25
|
+
app.stop()
|
|
26
|
+
process.exit(0)
|
|
27
|
+
},
|
|
28
|
+
})
|
|
29
|
+
app.start()
|
|
30
|
+
|
|
31
|
+
// Transcript contrast: the user row is a brand-blue bubble (whole-row
|
|
32
|
+
// background + blue ❯), everything else (assistant / thinking / system)
|
|
33
|
+
// keeps its own distinct style.
|
|
34
|
+
app.setTranscript([
|
|
35
|
+
{
|
|
36
|
+
kind: 'user',
|
|
37
|
+
turn: 0,
|
|
38
|
+
// Long enough to wrap: the continuation must indent under the ❯.
|
|
39
|
+
text: 'The startup fails with ENOTFOUND near line 42 of src/app.ts — I suspect an environment variable is missing, so please check the config load order and compare it against the .env.example keys and the docs.',
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
kind: 'assistant',
|
|
43
|
+
turn: 0,
|
|
44
|
+
text: 'Let me check. **Config load order**:\n\n1. `.env` file\n2. Environment overrides\n3. Default fallbacks\n\n`ENOTFOUND` usually means DNS resolution failed — confirm whether you reach an internal registry or the public one.',
|
|
45
|
+
},
|
|
46
|
+
{ kind: 'thinking', turn: 0, text: 'ENOTFOUND is a DNS issue; verify the config source before concluding.', running: false },
|
|
47
|
+
{ kind: 'system', turn: 0, label: 'AGENTS.md', text: 'Repo config conventions live in docs/config.md; env keys come from the preset.', summary: 'context rules' },
|
|
48
|
+
])
|
|
49
|
+
|
|
50
|
+
// Alternate the draft so both the empty prompt and the multi-line prompt
|
|
51
|
+
// (continuation indent) are visible without touching the keyboard.
|
|
52
|
+
let draftVisible = false
|
|
53
|
+
const flip = setInterval(() => {
|
|
54
|
+
draftVisible = !draftVisible
|
|
55
|
+
app.setDraft(draftVisible ? 'git status\npnpm test -- --filter @xmoon76/pi-tui' : '')
|
|
56
|
+
}, 6000)
|
|
57
|
+
|
|
58
|
+
setTimeout(() => {
|
|
59
|
+
clearInterval(flip)
|
|
60
|
+
app.stop()
|
|
61
|
+
process.exit(0)
|
|
62
|
+
}, holdMs)
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Side-by-side preview of user-role visual schemes — repo code untouched,
|
|
3
|
+
* pure display. Run in a real TTY (tmux):
|
|
4
|
+
*
|
|
5
|
+
* env -u NO_COLOR node --import tsx/esm scripts/preview-role-styles.mts
|
|
6
|
+
*
|
|
7
|
+
* Shows the chosen scheme — background bubble with a brand-blue ❯ (dsh-web
|
|
8
|
+
* parity) — in both the dark palette and the light palette, next to the
|
|
9
|
+
* old kimi-style amber text for contrast, plus the editor-prompt colours.
|
|
10
|
+
* Ctrl+C exits.
|
|
11
|
+
* @module @xmoon76/dsh-pi-tui/preview-role-styles
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { Chalk } from 'chalk'
|
|
15
|
+
import {
|
|
16
|
+
ProcessTerminal, Text, TuiMainScreen, matchesKey,
|
|
17
|
+
visibleWidth, wrapTextWithAnsi, type TuiInputListenerResult,
|
|
18
|
+
} from '@xmoon76/pi-tui'
|
|
19
|
+
|
|
20
|
+
const chalk = new Chalk({ level: 3 })
|
|
21
|
+
const dim = (s: string): string => chalk.hex('#888888')(s)
|
|
22
|
+
const darkBlue = (s: string): string => chalk.bold.hex('#679EFE')(s)
|
|
23
|
+
const darkBubbleBg = (s: string): string => chalk.bgHex('#2C2C2F')(s)
|
|
24
|
+
const lightBlue = (s: string): string => chalk.bold.hex('#4177E6')(s)
|
|
25
|
+
const lightBubbleBg = (s: string): string => chalk.bgHex('#E4EDFD')(s)
|
|
26
|
+
const amber = (s: string): string => chalk.bold.hex('#FFCB6B')(s)
|
|
27
|
+
const border = (s: string): string => chalk.hex('#5A5A5A')(s)
|
|
28
|
+
|
|
29
|
+
const W = 100
|
|
30
|
+
const MSG_ONE = 'Check the config load order — ENOTFOUND at src/app.ts:42, likely a missing env var.'
|
|
31
|
+
const MSG_TWO = 'Also verify the .env.example keys against the docs, since the preset loader reads them in sequence.'
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Wrap `text` to `width - 2` cells. The first row carries the plain `❯ `
|
|
35
|
+
* marker, continuation rows indent 2 cells under it; every row is padded
|
|
36
|
+
* to the full inner width so a background paint covers the whole row.
|
|
37
|
+
*/
|
|
38
|
+
function wrapped(width: number, text: string): string[] {
|
|
39
|
+
const inner = Math.max(1, width - 2)
|
|
40
|
+
return wrapTextWithAnsi(text, inner).map((line, index) => {
|
|
41
|
+
const prefix = index === 0 ? '❯ ' : ' '
|
|
42
|
+
return prefix + line + ' '.repeat(Math.max(0, inner - visibleWidth(line)))
|
|
43
|
+
})
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** Bubble rows: full-row background, coloured ❯, body in the terminal default. */
|
|
47
|
+
function bubble(width: number, text: string, bg: (s: string) => string, bullet: (s: string) => string): string[] {
|
|
48
|
+
return wrapped(width, text).map((row, index) => {
|
|
49
|
+
if (index === 0 && row.startsWith('❯ ')) {
|
|
50
|
+
return bg(bullet('❯') + ' ' + row.slice(2))
|
|
51
|
+
}
|
|
52
|
+
return bg(row)
|
|
53
|
+
})
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/** Old kimi look: the whole row (❯ + body + padding) in one amber paint. */
|
|
57
|
+
function amberRows(width: number, text: string): string[] {
|
|
58
|
+
return wrapped(width, text).map(amber)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const blocks: string[] = [
|
|
62
|
+
dim('dsh-pi-tui · user-role style preview (repo untouched) — Ctrl+C to exit'),
|
|
63
|
+
'',
|
|
64
|
+
dim('dark · bubble + brand-blue ❯ (chosen scheme)'),
|
|
65
|
+
...bubble(W, MSG_ONE, darkBubbleBg, darkBlue),
|
|
66
|
+
...bubble(W, MSG_TWO, darkBubbleBg, darkBlue),
|
|
67
|
+
'',
|
|
68
|
+
dim('light · bubble + deep brand-blue ❯ (light palette)'),
|
|
69
|
+
...bubble(W, MSG_ONE, lightBubbleBg, lightBlue),
|
|
70
|
+
...bubble(W, MSG_TWO, lightBubbleBg, lightBlue),
|
|
71
|
+
'',
|
|
72
|
+
dim('kimi amber text (rejected — kept for contrast)'),
|
|
73
|
+
...amberRows(W, MSG_ONE),
|
|
74
|
+
...amberRows(W, MSG_TWO),
|
|
75
|
+
'',
|
|
76
|
+
dim('editor prompt candidates:'),
|
|
77
|
+
border('─'.repeat(W)),
|
|
78
|
+
` ${darkBlue('❯')} git status ${lightBlue('❯')} git status ${amber('❯')} git status`,
|
|
79
|
+
border('─'.repeat(W)),
|
|
80
|
+
]
|
|
81
|
+
|
|
82
|
+
// Pad every line to the exact width so nothing wraps.
|
|
83
|
+
const preview = blocks
|
|
84
|
+
.map(line => line + ' '.repeat(Math.max(0, W - visibleWidth(line))))
|
|
85
|
+
.join('\n')
|
|
86
|
+
|
|
87
|
+
const terminal = new ProcessTerminal()
|
|
88
|
+
const tui = new TuiMainScreen(terminal)
|
|
89
|
+
tui.addChild(new Text(preview, 0, 0))
|
|
90
|
+
tui.addInputListener((data): TuiInputListenerResult => {
|
|
91
|
+
if (matchesKey(data, 'ctrl+c')) {
|
|
92
|
+
tui.stop()
|
|
93
|
+
process.exit(0)
|
|
94
|
+
}
|
|
95
|
+
return undefined
|
|
96
|
+
})
|
|
97
|
+
tui.start()
|
|
@@ -254,13 +254,17 @@ function main() {
|
|
|
254
254
|
// legitimately inlines the TuiApp implementation (src/tui-app.d.ts)
|
|
255
255
|
// for the Loader row — it is NOT a third-party SDK entry. Its region
|
|
256
256
|
// is exempted; everything else (chunks, extensions, builtins) must
|
|
257
|
-
// name only the public modules below.
|
|
257
|
+
// name only the public modules below. The image modules
|
|
258
|
+
// (src/image/admission.d.ts, src/image/types.d.ts) are also
|
|
259
|
+
// legitimately inlined into the root entry: the public
|
|
260
|
+
// `commandRejectsImages` signature references `DraftImageStoreLike`,
|
|
261
|
+
// which pulls in the draft vocabulary (and the recalled-ref shape).
|
|
258
262
|
const isRoot = name === 'dist/index.d.mts'
|
|
259
263
|
for (const line of lines) {
|
|
260
264
|
const match = /\/\/#region\s+(\S+)/.exec(line)
|
|
261
265
|
if (match) {
|
|
262
266
|
const regionPath = match[1]
|
|
263
|
-
const allowed = /^src\/(builtins|commands|diag|extension\/advanced|extension\/advanced-types|extension\/public-types|extension\/service|extension\/slot-map|extension\/unstable|extension\/unstable-types|extensions|index|skill-catalog|startup|surface-catalog)\.d\.ts$/.test(regionPath)
|
|
267
|
+
const allowed = /^src\/(builtins|commands|diag|extension\/advanced|extension\/advanced-types|extension\/public-types|extension\/service|extension\/slot-map|extension\/unstable|extension\/unstable-types|extensions|image\/admission|image\/types|index|skill-catalog|startup|surface-catalog)\.d\.ts$/.test(regionPath)
|
|
264
268
|
const rootAllowed = isRoot && /^src\/tui-app\.d\.ts$/.test(regionPath)
|
|
265
269
|
if (!allowed && !rootAllowed) dtsLeaks.push(`${name}: region ${regionPath}`)
|
|
266
270
|
}
|