dsh-better-display 0.3.7 → 0.3.9

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.
Files changed (208) hide show
  1. package/CHANGELOG.md +22 -1
  2. package/DESIGN.md +43 -3
  3. package/README.en.md +9 -1
  4. package/README.md +9 -1
  5. package/docs/dependency-update-policy.md +9 -0
  6. package/docs/extension-points.md +172 -0
  7. package/docs/official-rendering-bridge.md +59 -18
  8. package/docs/openapi.yaml +147 -0
  9. package/docs/runbooks/blank-reader.md +39 -0
  10. package/lib/client.js +1629 -586
  11. package/lib/client.js.map +1 -1
  12. package/lib/dsh-better-display.js +535 -57
  13. package/lib/types/client/AssistantNode.d.ts +20 -0
  14. package/lib/types/client/AssistantNode.d.ts.map +1 -0
  15. package/lib/types/client/AssistantNode.js +46 -0
  16. package/lib/types/client/AssistantNode.js.map +1 -0
  17. package/lib/types/client/Blocks.d.ts.map +1 -1
  18. package/lib/types/client/Blocks.js +33 -10
  19. package/lib/types/client/Blocks.js.map +1 -1
  20. package/lib/types/client/ChoreographedFlow.d.ts.map +1 -1
  21. package/lib/types/client/ChoreographedFlow.js +2 -0
  22. package/lib/types/client/ChoreographedFlow.js.map +1 -1
  23. package/lib/types/client/ClosedProcessSummary.d.ts.map +1 -1
  24. package/lib/types/client/ClosedProcessSummary.js +3 -1
  25. package/lib/types/client/ClosedProcessSummary.js.map +1 -1
  26. package/lib/types/client/McpAppFrame.d.ts.map +1 -1
  27. package/lib/types/client/McpAppFrame.js +5 -11
  28. package/lib/types/client/McpAppFrame.js.map +1 -1
  29. package/lib/types/client/OfficialContent.d.ts +17 -3
  30. package/lib/types/client/OfficialContent.d.ts.map +1 -1
  31. package/lib/types/client/OfficialContent.js +33 -7
  32. package/lib/types/client/OfficialContent.js.map +1 -1
  33. package/lib/types/client/Reader.d.ts.map +1 -1
  34. package/lib/types/client/Reader.js +76 -73
  35. package/lib/types/client/Reader.js.map +1 -1
  36. package/lib/types/client/SettingsSection.d.ts.map +1 -1
  37. package/lib/types/client/SettingsSection.js +0 -5
  38. package/lib/types/client/SettingsSection.js.map +1 -1
  39. package/lib/types/client/StickyLane.d.ts +12 -0
  40. package/lib/types/client/StickyLane.d.ts.map +1 -1
  41. package/lib/types/client/StickyLane.js +78 -2
  42. package/lib/types/client/StickyLane.js.map +1 -1
  43. package/lib/types/client/ToolActivity.d.ts.map +1 -1
  44. package/lib/types/client/ToolActivity.js +10 -5
  45. package/lib/types/client/ToolActivity.js.map +1 -1
  46. package/lib/types/client/deliverables.d.ts.map +1 -1
  47. package/lib/types/client/deliverables.js +2 -0
  48. package/lib/types/client/deliverables.js.map +1 -1
  49. package/lib/types/client/index.d.ts +3 -1
  50. package/lib/types/client/index.d.ts.map +1 -1
  51. package/lib/types/client/index.js +15 -1
  52. package/lib/types/client/index.js.map +1 -1
  53. package/lib/types/client/live-turn.d.ts +17 -5
  54. package/lib/types/client/live-turn.d.ts.map +1 -1
  55. package/lib/types/client/live-turn.js +106 -76
  56. package/lib/types/client/live-turn.js.map +1 -1
  57. package/lib/types/client/motion.d.ts +26 -2
  58. package/lib/types/client/motion.d.ts.map +1 -1
  59. package/lib/types/client/motion.js +144 -10
  60. package/lib/types/client/motion.js.map +1 -1
  61. package/lib/types/client/official-slots.d.ts +9 -0
  62. package/lib/types/client/official-slots.d.ts.map +1 -1
  63. package/lib/types/client/official-slots.js +22 -4
  64. package/lib/types/client/official-slots.js.map +1 -1
  65. package/lib/types/client/open-file.d.ts.map +1 -1
  66. package/lib/types/client/open-file.js +1 -6
  67. package/lib/types/client/open-file.js.map +1 -1
  68. package/lib/types/client/projection.d.ts +15 -2
  69. package/lib/types/client/projection.d.ts.map +1 -1
  70. package/lib/types/client/projection.js +16 -4
  71. package/lib/types/client/projection.js.map +1 -1
  72. package/lib/types/client/rewind-cut.d.ts +131 -0
  73. package/lib/types/client/rewind-cut.d.ts.map +1 -0
  74. package/lib/types/client/rewind-cut.js +321 -0
  75. package/lib/types/client/rewind-cut.js.map +1 -0
  76. package/lib/types/client/styles.d.ts +3 -0
  77. package/lib/types/client/styles.d.ts.map +1 -0
  78. package/lib/types/client/styles.js +25 -0
  79. package/lib/types/client/styles.js.map +1 -0
  80. package/lib/types/client/text-transform.d.ts +93 -0
  81. package/lib/types/client/text-transform.d.ts.map +1 -0
  82. package/lib/types/client/text-transform.js +183 -0
  83. package/lib/types/client/text-transform.js.map +1 -0
  84. package/lib/types/client/timeline.d.ts.map +1 -1
  85. package/lib/types/client/timeline.js.map +1 -1
  86. package/lib/types/client/tool-activity.d.ts +11 -4
  87. package/lib/types/client/tool-activity.d.ts.map +1 -1
  88. package/lib/types/client/tool-activity.js +54 -9
  89. package/lib/types/client/tool-activity.js.map +1 -1
  90. package/lib/types/client/turn-slots.d.ts +29 -0
  91. package/lib/types/client/turn-slots.d.ts.map +1 -0
  92. package/lib/types/client/turn-slots.js +62 -0
  93. package/lib/types/client/turn-slots.js.map +1 -0
  94. package/lib/types/client/types.d.ts +18 -0
  95. package/lib/types/client/types.d.ts.map +1 -1
  96. package/lib/types/dsh-better-display.d.ts +4 -1
  97. package/lib/types/dsh-better-display.d.ts.map +1 -1
  98. package/lib/types/dsh-better-display.js +55 -43
  99. package/lib/types/dsh-better-display.js.map +1 -1
  100. package/lib/types/flags.d.ts +7 -0
  101. package/lib/types/flags.d.ts.map +1 -0
  102. package/lib/types/flags.js +37 -0
  103. package/lib/types/flags.js.map +1 -0
  104. package/lib/types/log.d.ts +17 -0
  105. package/lib/types/log.d.ts.map +1 -0
  106. package/lib/types/log.js +122 -0
  107. package/lib/types/log.js.map +1 -0
  108. package/lib/types/metrics.d.ts +18 -0
  109. package/lib/types/metrics.d.ts.map +1 -0
  110. package/lib/types/metrics.js +35 -0
  111. package/lib/types/metrics.js.map +1 -0
  112. package/lib/types/reveal.d.ts +12 -0
  113. package/lib/types/reveal.d.ts.map +1 -0
  114. package/lib/types/reveal.js +147 -0
  115. package/lib/types/reveal.js.map +1 -0
  116. package/lib/types/workspace-path.d.ts +3 -0
  117. package/lib/types/workspace-path.d.ts.map +1 -0
  118. package/lib/types/workspace-path.js +5 -0
  119. package/lib/types/workspace-path.js.map +1 -0
  120. package/package.json +36 -5
  121. package/scripts/changelog.mjs +20 -0
  122. package/scripts/check-agents-md.mjs +67 -0
  123. package/scripts/check-bundle-size.mjs +38 -0
  124. package/scripts/check-dead-flags.mjs +55 -0
  125. package/scripts/check-todo-debt.mjs +69 -0
  126. package/scripts/security-audit-report.mjs +92 -0
  127. package/scripts/verify-commentary-visible.mjs +627 -0
  128. package/src/client/AssistantNode.tsx +72 -0
  129. package/src/client/Blocks.tsx +49 -10
  130. package/src/client/ChoreographedFlow.tsx +3 -1
  131. package/src/client/ClosedProcessSummary.tsx +3 -1
  132. package/src/client/McpAppFrame.tsx +5 -13
  133. package/src/client/OfficialContent.tsx +47 -9
  134. package/src/client/Reader.module.css +103 -21
  135. package/src/client/Reader.tsx +83 -88
  136. package/src/client/SettingsSection.tsx +1 -7
  137. package/src/client/StickyLane.tsx +81 -2
  138. package/src/client/ToolActivity.tsx +10 -6
  139. package/src/client/deliverables.ts +1 -0
  140. package/src/client/index.tsx +18 -2
  141. package/src/client/live-turn.ts +100 -69
  142. package/src/client/motion.tsx +142 -7
  143. package/src/client/official-slots.tsx +23 -4
  144. package/src/client/open-file.ts +2 -8
  145. package/src/client/projection.ts +16 -4
  146. package/src/client/rewind-cut.ts +340 -0
  147. package/src/client/styles.ts +22 -0
  148. package/src/client/text-transform.ts +265 -0
  149. package/src/client/timeline.ts +0 -2
  150. package/src/client/tool-activity.ts +67 -9
  151. package/src/client/turn-slots.ts +80 -0
  152. package/src/client/types.ts +19 -0
  153. package/src/dsh-better-display.ts +57 -42
  154. package/src/flags.ts +40 -0
  155. package/src/log.ts +137 -0
  156. package/src/metrics.ts +50 -0
  157. package/src/reveal.ts +90 -0
  158. package/src/workspace-path.ts +4 -0
  159. package/tests/browser-commentary.tsx +191 -0
  160. package/tests/chat-flow-hook.test.ts +1 -1
  161. package/tests/cloud-gate.test.ts +1 -1
  162. package/tests/context-tool-update.test.ts +1 -1
  163. package/tests/conversation-scroll.test.ts +1 -1
  164. package/tests/deliverables.test.ts +1 -1
  165. package/tests/entry.test.ts +1 -1
  166. package/tests/fixtures/reader-lane-owners.tsx +46 -0
  167. package/tests/fixtures/reader-official-users.tsx +234 -0
  168. package/tests/fixtures/reader-theme-overlap.html +80 -0
  169. package/tests/fixtures/reader-user-bubble.tsx +222 -0
  170. package/tests/flags.test.ts +66 -0
  171. package/tests/fold-choreography.test.ts +32 -8
  172. package/tests/fold-intensity.test.ts +11 -6
  173. package/tests/footer-precedence.test.ts +9 -1
  174. package/tests/history-word-regression.test.ts +1 -1
  175. package/tests/live-turn.test.ts +125 -54
  176. package/tests/log.test.ts +99 -0
  177. package/tests/mcp-apps.test.ts +1 -1
  178. package/tests/message-chrome.test.ts +1 -1
  179. package/tests/metrics.test.ts +52 -0
  180. package/tests/official-slots.test.ts +41 -2
  181. package/tests/open-file.test.ts +1 -1
  182. package/tests/pending-submission.test.ts +12 -1
  183. package/tests/pinned-selection.test.ts +16 -0
  184. package/tests/platform-media.test.ts +1 -1
  185. package/tests/projection.test.ts +66 -3
  186. package/tests/reader-glass-css.test.ts +28 -0
  187. package/tests/reader-official-users.test.ts +91 -0
  188. package/tests/reader-sticky-surface.test.ts +377 -0
  189. package/tests/reader-theme-lanes.test.ts +54 -0
  190. package/tests/reader-theme-overlap.test.ts +151 -0
  191. package/tests/reader-user-bubble.test.ts +137 -0
  192. package/tests/reasoning-follow.test.ts +1 -1
  193. package/tests/retiring-content.test.ts +229 -0
  194. package/tests/reveal.test.ts +128 -0
  195. package/tests/rewind-cut.test.ts +1090 -0
  196. package/tests/settings-copy.test.ts +1 -1
  197. package/tests/skill-status.test.ts +1 -1
  198. package/tests/stock-install.test.ts +9 -1
  199. package/tests/stream-buffer.test.ts +1 -1
  200. package/tests/styles.test.ts +75 -0
  201. package/tests/terminal-input-preview.test.ts +113 -0
  202. package/tests/text-transform.test.ts +272 -0
  203. package/tests/timeline.test.ts +1 -1
  204. package/tests/tool-clock.test.ts +1 -1
  205. package/tests/tool-diff.test.ts +1 -1
  206. package/tests/waiting-clock.test.ts +1 -1
  207. package/tests/word-timeline.test.ts +1 -1
  208. package/tsdown.config.ts +49 -1
@@ -0,0 +1,7 @@
1
+ /** Startup kill switch loaded from flags.json. This is not the reader glass setting. */
2
+ export interface Flags {
3
+ readonly readerEnabled: boolean;
4
+ }
5
+ export declare const defaultFlags: Flags;
6
+ export declare function loadFlags(source?: string | Flags): Flags;
7
+ //# sourceMappingURL=flags.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flags.d.ts","sourceRoot":"","sources":["../../src/flags.ts"],"names":[],"mappings":"AAIA,wFAAwF;AACxF,MAAM,WAAW,KAAK;IACpB,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;CACjC;AAED,eAAO,MAAM,YAAY,EAAE,KAA+B,CAAC;AAqB3D,wBAAgB,SAAS,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,KAAK,CASxD"}
@@ -0,0 +1,37 @@
1
+ import { existsSync, readFileSync } from 'node:fs';
2
+ import { dirname, resolve } from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+ export const defaultFlags = { readerEnabled: true };
5
+ function locateFlags(start = dirname(fileURLToPath(import.meta.url))) {
6
+ let dir = start;
7
+ for (let depth = 0; depth < 6; depth += 1) {
8
+ const candidate = resolve(dir, 'flags.json');
9
+ if (existsSync(candidate))
10
+ return candidate;
11
+ const parent = dirname(dir);
12
+ if (parent === dir)
13
+ return undefined;
14
+ dir = parent;
15
+ }
16
+ return undefined;
17
+ }
18
+ function normalize(value) {
19
+ const record = value !== null && typeof value === 'object' ? value : {};
20
+ return {
21
+ readerEnabled: typeof record.readerEnabled === 'boolean' ? record.readerEnabled : defaultFlags.readerEnabled,
22
+ };
23
+ }
24
+ export function loadFlags(source) {
25
+ if (source !== undefined && typeof source !== 'string')
26
+ return normalize(source);
27
+ try {
28
+ const path = typeof source === 'string' ? source : locateFlags();
29
+ if (path === undefined || !existsSync(path))
30
+ return { ...defaultFlags };
31
+ return normalize(JSON.parse(readFileSync(path, 'utf8')));
32
+ }
33
+ catch {
34
+ return { ...defaultFlags };
35
+ }
36
+ }
37
+ //# sourceMappingURL=flags.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flags.js","sourceRoot":"","sources":["../../src/flags.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAOzC,MAAM,CAAC,MAAM,YAAY,GAAU,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;AAE3D,SAAS,WAAW,CAAC,KAAK,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAClE,IAAI,GAAG,GAAG,KAAK,CAAC;IAChB,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QAC1C,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;QAC7C,IAAI,UAAU,CAAC,SAAS,CAAC;YAAE,OAAO,SAAS,CAAC;QAC5C,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;QAC5B,IAAI,MAAM,KAAK,GAAG;YAAE,OAAO,SAAS,CAAC;QACrC,GAAG,GAAG,MAAM,CAAC;IACf,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,SAAS,CAAC,KAAc;IAC/B,MAAM,MAAM,GAAG,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAoC,CAAC,CAAC,CAAC,EAAE,CAAC;IACvG,OAAO;QACL,aAAa,EAAE,OAAO,MAAM,CAAC,aAAa,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,YAAY,CAAC,aAAa;KAC7G,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,MAAuB;IAC/C,IAAI,MAAM,KAAK,SAAS,IAAI,OAAO,MAAM,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAC,MAAM,CAAC,CAAC;IACjF,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;QACjE,IAAI,IAAI,KAAK,SAAS,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;YAAE,OAAO,EAAE,GAAG,YAAY,EAAE,CAAC;QACxE,OAAO,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAY,CAAC,CAAC;IACtE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,GAAG,YAAY,EAAE,CAAC;IAC7B,CAAC;AACH,CAAC"}
@@ -0,0 +1,17 @@
1
+ import type { IncomingMessage } from 'node:http';
2
+ export declare const REDACTED = "[REDACTED]";
3
+ export type LogFields = Record<string, unknown>;
4
+ export interface Logger {
5
+ info(msg: string, fields?: LogFields): void;
6
+ warn(msg: string, fields?: LogFields): void;
7
+ error(msg: string, fields?: LogFields): void;
8
+ }
9
+ export interface LoggerOptions {
10
+ readonly write?: (line: string) => void;
11
+ readonly base?: LogFields;
12
+ readonly clock?: () => Date;
13
+ }
14
+ export declare function redact(value: unknown): unknown;
15
+ export declare function createLogger(options?: LoggerOptions): Logger;
16
+ export declare function requestIdOf(req: IncomingMessage): string;
17
+ //# sourceMappingURL=log.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log.d.ts","sourceRoot":"","sources":["../../src/log.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAEjD,eAAO,MAAM,QAAQ,eAAe,CAAC;AAiCrC,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEhD,MAAM,WAAW,MAAM;IACrB,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IAC5C,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IAC5C,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;CAC9C;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,CAAC;IAC1B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,IAAI,CAAC;CAC7B;AA+BD,wBAAgB,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAE9C;AAwBD,wBAAgB,YAAY,CAAC,OAAO,GAAE,aAAkB,GAAG,MAAM,CAwBhE;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,eAAe,GAAG,MAAM,CAKxD"}
@@ -0,0 +1,122 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ export const REDACTED = '[REDACTED]';
3
+ const REQUEST_ID_HEADER = 'x-request-id';
4
+ const REQUEST_ID_PATTERN = /^[A-Za-z0-9._:-]{1,200}$/;
5
+ const SECRET_KEYS = new Set([
6
+ 'authorization',
7
+ 'proxyauthorization',
8
+ 'cookie',
9
+ 'setcookie',
10
+ 'token',
11
+ 'accesstoken',
12
+ 'refreshtoken',
13
+ 'idtoken',
14
+ 'apikey',
15
+ 'apisecret',
16
+ 'secret',
17
+ 'clientsecret',
18
+ 'password',
19
+ 'passwd',
20
+ 'credential',
21
+ 'credentials',
22
+ 'signature',
23
+ 'sig',
24
+ 'jwt',
25
+ 'bearer',
26
+ 'privatekey',
27
+ 'xapikey',
28
+ 'xauthtoken',
29
+ 'xaccesstoken',
30
+ 'auth',
31
+ ]);
32
+ function normalizeKey(key) {
33
+ return key.toLowerCase().replace(/[^a-z0-9]/g, '');
34
+ }
35
+ function isSecretKey(key) {
36
+ const normalized = normalizeKey(key);
37
+ if (SECRET_KEYS.has(normalized))
38
+ return true;
39
+ if (normalized === 'requestid' || normalized === 'xrequestid')
40
+ return false;
41
+ return /(?:^|[^a-z])(?:token|secret|password|api[-_]?key)$/i.test(key);
42
+ }
43
+ function redactString(value) {
44
+ const query = value.replace(/([?&#])([^&#=]+)=([^&#]*)/g, (match, sep, rawKey) => {
45
+ let key;
46
+ try {
47
+ key = decodeURIComponent(rawKey.replace(/\+/g, ' '));
48
+ }
49
+ catch {
50
+ key = rawKey;
51
+ }
52
+ return isSecretKey(key) ? `${sep}${rawKey}=${REDACTED}` : match;
53
+ });
54
+ return query
55
+ .replace(/\b(Bearer|Basic)\s+\S+/gi, `$1 ${REDACTED}`)
56
+ .replace(/\b((?:access[_-]?token|refresh[_-]?token|id[_-]?token|api[_-]?key|client[_-]?secret|password|passwd|authorization|token|secret))(\s*[:=]\s*)([^\s&]+)/gi, `$1$2${REDACTED}`);
57
+ }
58
+ export function redact(value) {
59
+ return redactValue(undefined, value, 0, new WeakSet());
60
+ }
61
+ function redactValue(key, value, depth, seen) {
62
+ if (key !== undefined && isSecretKey(key))
63
+ return REDACTED;
64
+ if (depth > 8)
65
+ return REDACTED;
66
+ if (typeof value === 'string')
67
+ return redactString(value);
68
+ if (typeof value === 'number' || typeof value === 'boolean' || value === null || value === undefined)
69
+ return value;
70
+ if (typeof value !== 'object')
71
+ return REDACTED;
72
+ if (value instanceof Date)
73
+ return value.toISOString();
74
+ if (value instanceof Error) {
75
+ return redactValue(undefined, { name: value.name, message: value.message }, depth + 1, seen);
76
+ }
77
+ if (seen.has(value))
78
+ return REDACTED;
79
+ seen.add(value);
80
+ if (Array.isArray(value)) {
81
+ return value.map(item => redactValue(undefined, item, depth + 1, seen));
82
+ }
83
+ const output = {};
84
+ for (const [childKey, childValue] of Object.entries(value)) {
85
+ output[childKey] = redactValue(childKey, childValue, depth + 1, seen);
86
+ }
87
+ return output;
88
+ }
89
+ export function createLogger(options = {}) {
90
+ const write = options.write ?? ((line) => {
91
+ console.log(line);
92
+ });
93
+ const clock = options.clock ?? (() => new Date());
94
+ const emit = (level, msg, fields) => {
95
+ const details = redact({ ...options.base, ...fields });
96
+ const record = {
97
+ ...(details !== null && typeof details === 'object' ? details : {}),
98
+ time: clock().toISOString(),
99
+ level,
100
+ msg: redactString(msg),
101
+ };
102
+ try {
103
+ write(JSON.stringify(record));
104
+ }
105
+ catch {
106
+ write(JSON.stringify({ time: record.time, level, msg: record.msg, error: 'log record was not serializable' }));
107
+ }
108
+ };
109
+ return {
110
+ info: (msg, fields) => emit('info', msg, fields),
111
+ warn: (msg, fields) => emit('warn', msg, fields),
112
+ error: (msg, fields) => emit('error', msg, fields),
113
+ };
114
+ }
115
+ export function requestIdOf(req) {
116
+ const raw = req.headers[REQUEST_ID_HEADER];
117
+ const value = Array.isArray(raw) ? raw[0] : raw;
118
+ if (typeof value === 'string' && REQUEST_ID_PATTERN.test(value))
119
+ return value;
120
+ return randomUUID();
121
+ }
122
+ //# sourceMappingURL=log.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log.js","sourceRoot":"","sources":["../../src/log.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ export declare const ROUTE_REVEAL = "/better-display/reveal";
2
+ export declare const ROUTE_SKILL_STATUS = "/better-display/skill-status";
3
+ export declare const ROUTE_METRICS = "/better-display/metrics";
4
+ export declare const ROUTE_HITS: readonly ["/better-display/reveal", "/better-display/skill-status", "/better-display/metrics"];
5
+ export interface RouteTiming {
6
+ count: number;
7
+ totalMs: number;
8
+ maxMs: number;
9
+ }
10
+ export declare function recordRouteHit(route: string): number;
11
+ export declare function recordRouteDuration(route: string, elapsedMs: number): RouteTiming;
12
+ export declare function metricsPayload(): {
13
+ counters: {
14
+ dsh_better_display_route_hits_total: Record<string, number>;
15
+ };
16
+ timingsMs: Record<string, RouteTiming>;
17
+ };
18
+ //# sourceMappingURL=metrics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../../src/metrics.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,YAAY,2BAA2B,CAAC;AACrD,eAAO,MAAM,kBAAkB,iCAAiC,CAAC;AACjE,eAAO,MAAM,aAAa,4BAA4B,CAAC;AAEvD,eAAO,MAAM,UAAU,gGAA6D,CAAC;AAErF,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACf;AAaD,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAIpD;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,WAAW,CAUjF;AAED,wBAAgB,cAAc,IAAI;IAChC,QAAQ,EAAE;QAAE,mCAAmC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAE,CAAC;IAC1E,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;CACxC,CAKA"}
@@ -0,0 +1,35 @@
1
+ export const ROUTE_REVEAL = '/better-display/reveal';
2
+ export const ROUTE_SKILL_STATUS = '/better-display/skill-status';
3
+ export const ROUTE_METRICS = '/better-display/metrics';
4
+ export const ROUTE_HITS = [ROUTE_REVEAL, ROUTE_SKILL_STATUS, ROUTE_METRICS];
5
+ const hits = new Map(ROUTE_HITS.map(route => [route, 0]));
6
+ const timings = new Map(ROUTE_HITS.map(route => [route, { count: 0, totalMs: 0, maxMs: 0 }]));
7
+ function snapshotHits() {
8
+ return Object.fromEntries(hits);
9
+ }
10
+ function snapshotTimings() {
11
+ return Object.fromEntries([...timings].map(([route, timing]) => [route, { ...timing }]));
12
+ }
13
+ export function recordRouteHit(route) {
14
+ const next = (hits.get(route) ?? 0) + 1;
15
+ hits.set(route, next);
16
+ return next;
17
+ }
18
+ export function recordRouteDuration(route, elapsedMs) {
19
+ const ms = Number.isFinite(elapsedMs) && elapsedMs > 0 ? Math.round(elapsedMs) : 0;
20
+ const current = timings.get(route) ?? { count: 0, totalMs: 0, maxMs: 0 };
21
+ const next = {
22
+ count: current.count + 1,
23
+ totalMs: current.totalMs + ms,
24
+ maxMs: Math.max(current.maxMs, ms),
25
+ };
26
+ timings.set(route, next);
27
+ return next;
28
+ }
29
+ export function metricsPayload() {
30
+ return {
31
+ counters: { dsh_better_display_route_hits_total: snapshotHits() },
32
+ timingsMs: snapshotTimings(),
33
+ };
34
+ }
35
+ //# sourceMappingURL=metrics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metrics.js","sourceRoot":"","sources":["../../src/metrics.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,YAAY,GAAG,wBAAwB,CAAC;AACrD,MAAM,CAAC,MAAM,kBAAkB,GAAG,8BAA8B,CAAC;AACjE,MAAM,CAAC,MAAM,aAAa,GAAG,yBAAyB,CAAC;AAEvD,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,YAAY,EAAE,kBAAkB,EAAE,aAAa,CAAU,CAAC;AAQrF,MAAM,IAAI,GAAG,IAAI,GAAG,CAAiB,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;AAC1E,MAAM,OAAO,GAAG,IAAI,GAAG,CAAsB,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AAEnH,SAAS,YAAY;IACnB,OAAO,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;AAClC,CAAC;AAED,SAAS,eAAe;IACtB,OAAO,MAAM,CAAC,WAAW,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,EAAE,GAAG,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC;AAC3F,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,KAAa;IAC1C,MAAM,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;IACxC,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IACtB,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,KAAa,EAAE,SAAiB;IAClE,MAAM,EAAE,GAAG,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACnF,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;IACzE,MAAM,IAAI,GAAG;QACX,KAAK,EAAE,OAAO,CAAC,KAAK,GAAG,CAAC;QACxB,OAAO,EAAE,OAAO,CAAC,OAAO,GAAG,EAAE;QAC7B,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC;KACnC,CAAC;IACF,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IACzB,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,cAAc;IAI5B,OAAO;QACL,QAAQ,EAAE,EAAE,mCAAmC,EAAE,YAAY,EAAE,EAAE;QACjE,SAAS,EAAE,eAAe,EAAE;KAC7B,CAAC;AACJ,CAAC"}
@@ -0,0 +1,12 @@
1
+ import { type SpawnOptions } from 'node:child_process';
2
+ import { existsSync } from 'node:fs';
3
+ import type { IncomingMessage, ServerResponse } from 'node:http';
4
+ import type { Context } from '@deepseek-ai/cordis';
5
+ export declare function revealRoots(ctx: Context, sessionId: string | undefined): Promise<readonly string[]>;
6
+ export declare function resolveRevealPath(path: string, roots: readonly string[], exists?: typeof existsSync): string;
7
+ export declare function revealPath(path: string, platform?: NodeJS.Platform, spawnProcess?: (command: string, args: string[], options: SpawnOptions) => unknown): void;
8
+ export declare function createRevealHandler({ roots, reveal }: {
9
+ roots: (sessionId: string | undefined) => Promise<readonly string[]>;
10
+ reveal?: (path: string) => void;
11
+ }): (req: IncomingMessage, res: ServerResponse) => void;
12
+ //# sourceMappingURL=reveal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reveal.d.ts","sourceRoot":"","sources":["../../src/reveal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAEjE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAGnD,wBAAsB,WAAW,CAAC,GAAG,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,SAAS,MAAM,EAAE,CAAC,CAmBzG;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,EAAE,MAAM,oBAAa,GAAG,MAAM,CAarG;AAED,wBAAgB,UAAU,CACxB,IAAI,EAAE,MAAM,EACZ,QAAQ,kBAAmB,EAC3B,YAAY,GAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,YAAY,KAAK,OAAe,GACxF,IAAI,CASN;AAED,wBAAgB,mBAAmB,CAAC,EAAE,KAAK,EAAE,MAAmB,EAAE,EAAE;IAClE,KAAK,EAAE,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,KAAK,OAAO,CAAC,SAAS,MAAM,EAAE,CAAC,CAAC;IACrE,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACjC,GAAG,CAAC,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE,cAAc,KAAK,IAAI,CA4BtD"}
@@ -0,0 +1,147 @@
1
+ var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
2
+ if (value !== null && value !== void 0) {
3
+ if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
4
+ var dispose, inner;
5
+ if (async) {
6
+ if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
7
+ dispose = value[Symbol.asyncDispose];
8
+ }
9
+ if (dispose === void 0) {
10
+ if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
11
+ dispose = value[Symbol.dispose];
12
+ if (async) inner = dispose;
13
+ }
14
+ if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
15
+ if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
16
+ env.stack.push({ value: value, dispose: dispose, async: async });
17
+ }
18
+ else if (async) {
19
+ env.stack.push({ async: true });
20
+ }
21
+ return value;
22
+ };
23
+ var __disposeResources = (this && this.__disposeResources) || (function (SuppressedError) {
24
+ return function (env) {
25
+ function fail(e) {
26
+ env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
27
+ env.hasError = true;
28
+ }
29
+ var r, s = 0;
30
+ function next() {
31
+ while (r = env.stack.pop()) {
32
+ try {
33
+ if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
34
+ if (r.dispose) {
35
+ var result = r.dispose.call(r.value);
36
+ if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
37
+ }
38
+ else s |= 1;
39
+ }
40
+ catch (e) {
41
+ fail(e);
42
+ }
43
+ }
44
+ if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
45
+ if (env.hasError) throw env.error;
46
+ }
47
+ return next();
48
+ };
49
+ })(typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
50
+ var e = new Error(message);
51
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
52
+ });
53
+ import { spawn } from 'node:child_process';
54
+ import { existsSync } from 'node:fs';
55
+ import { posix, win32 } from 'node:path';
56
+ import { isAbsoluteWorkspacePath } from './workspace-path.js';
57
+ export async function revealRoots(ctx, sessionId) {
58
+ if (sessionId !== undefined) {
59
+ const sessions = ctx.get?.('sessions');
60
+ const cwd = sessions?.get(sessionId)?.header.cwd;
61
+ if (cwd)
62
+ return [cwd];
63
+ const query = ctx.get?.('sessionQuery');
64
+ if (query) {
65
+ const env_1 = { stack: [], error: void 0, hasError: false };
66
+ try {
67
+ const observation = __addDisposableResource(env_1, await query.observeSession(sessionId, { projectionMode: 'none' }), false);
68
+ if (observation.header.cwd)
69
+ return [observation.header.cwd];
70
+ }
71
+ catch (e_1) {
72
+ env_1.error = e_1;
73
+ env_1.hasError = true;
74
+ }
75
+ finally {
76
+ __disposeResources(env_1);
77
+ }
78
+ }
79
+ }
80
+ const registry = ctx.get?.('workspaceRegistry');
81
+ return (registry?.list() ?? [])
82
+ .filter(workspace => sessionId === undefined || workspace.sessionIds.includes(sessionId))
83
+ .map(workspace => workspace.path);
84
+ }
85
+ export function resolveRevealPath(path, roots, exists = existsSync) {
86
+ if (isAbsoluteWorkspacePath(path))
87
+ return path;
88
+ // Drive-relative and root-relative Windows paths do not identify a workspace.
89
+ if (/^[A-Za-z]:|^\\/.test(path))
90
+ throw new Error('Path is not workspace-relative');
91
+ const matches = new Set();
92
+ for (const root of roots) {
93
+ if (!isAbsoluteWorkspacePath(root))
94
+ continue;
95
+ const paths = /^[A-Za-z]:[/\\]|^\\\\/.test(root) ? win32 : posix;
96
+ const candidate = paths.resolve(root, path);
97
+ if (exists(candidate))
98
+ matches.add(candidate);
99
+ }
100
+ if (matches.size !== 1)
101
+ throw new Error(matches.size === 0 ? 'Workspace path not found' : 'Workspace path is ambiguous');
102
+ return [...matches][0];
103
+ }
104
+ export function revealPath(path, platform = process.platform, spawnProcess = spawn) {
105
+ const options = { detached: true, stdio: 'ignore' };
106
+ if (platform === 'darwin') {
107
+ spawnProcess('open', ['-R', path], options);
108
+ }
109
+ else if (platform === 'win32') {
110
+ spawnProcess('explorer.exe', [`/select,"${path}"`], { ...options, windowsVerbatimArguments: true });
111
+ }
112
+ else {
113
+ spawnProcess('xdg-open', [path], options);
114
+ }
115
+ }
116
+ export function createRevealHandler({ roots, reveal = revealPath }) {
117
+ return (req, res) => {
118
+ if (req.method !== 'POST') {
119
+ res.statusCode = 405;
120
+ res.end();
121
+ return;
122
+ }
123
+ let body = '';
124
+ req.on('data', chunk => { body += chunk; });
125
+ req.on('end', async () => {
126
+ res.setHeader('Content-Type', 'application/json');
127
+ try {
128
+ const data = JSON.parse(body);
129
+ const path = typeof data === 'object' && data !== null && 'path' in data && typeof data.path === 'string'
130
+ ? data.path.trim() : '';
131
+ if (!path)
132
+ throw new Error('Empty path');
133
+ const sessionId = typeof data === 'object' && data !== null && 'sessionId' in data && typeof data.sessionId === 'string'
134
+ ? data.sessionId : undefined;
135
+ const targetPath = resolveRevealPath(path, isAbsoluteWorkspacePath(path) ? [] : await roots(sessionId));
136
+ reveal(targetPath);
137
+ res.statusCode = 200;
138
+ res.end(JSON.stringify({ ok: true }));
139
+ }
140
+ catch (err) {
141
+ res.statusCode = 400;
142
+ res.end(JSON.stringify({ ok: false, error: String(err) }));
143
+ }
144
+ });
145
+ };
146
+ }
147
+ //# sourceMappingURL=reveal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reveal.js","sourceRoot":"","sources":["../../src/reveal.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ /** Absolute paths accepted by both POSIX and Windows hosts. */
2
+ export declare function isAbsoluteWorkspacePath(path: string): boolean;
3
+ //# sourceMappingURL=workspace-path.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace-path.d.ts","sourceRoot":"","sources":["../../src/workspace-path.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE7D"}
@@ -0,0 +1,5 @@
1
+ /** Absolute paths accepted by both POSIX and Windows hosts. */
2
+ export function isAbsoluteWorkspacePath(path) {
3
+ return /^(?:\/|[A-Za-z]:[/\\]|\\\\)/.test(path);
4
+ }
5
+ //# sourceMappingURL=workspace-path.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace-path.js","sourceRoot":"","sources":["../../src/workspace-path.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,MAAM,UAAU,uBAAuB,CAAC,IAAY;IAClD,OAAO,6BAA6B,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAClD,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-better-display",
3
- "version": "0.3.7",
3
+ "version": "0.3.9",
4
4
  "description": "A calmer reading view for DeepSeek Harness: native process details, live reasoning, and clean final answers.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -38,9 +38,21 @@
38
38
  "test:official": "node scripts/verify-official-bridge.mjs",
39
39
  "test:auto-fold": "node scripts/verify-auto-fold.mjs",
40
40
  "typecheck": "tsc -p tsconfig.json --noEmit",
41
- "test": "node --import tsx/esm --test tests/*.test.ts",
41
+ "test": "vitest run",
42
42
  "link:harness": "node scripts/link-harness-dependencies.mjs",
43
- "test:flowcell": "node scripts/verify-flowcell.mjs"
43
+ "test:flowcell": "node scripts/verify-flowcell.mjs",
44
+ "lint": "eslint src --max-warnings 0",
45
+ "format:check": "prettier --check .",
46
+ "deadcode": "knip",
47
+ "duplicates": "jscpd src",
48
+ "debt": "node scripts/check-todo-debt.mjs",
49
+ "changelog": "node scripts/changelog.mjs",
50
+ "check:agents": "node scripts/check-agents-md.mjs",
51
+ "check:bundle": "node scripts/check-bundle-size.mjs",
52
+ "security:audit": "node scripts/security-audit-report.mjs",
53
+ "check:flags": "node scripts/check-dead-flags.mjs",
54
+ "test:list": "vitest list",
55
+ "test:coverage": "vitest run --coverage"
44
56
  },
45
57
  "peerDependencies": {
46
58
  "@deepseek-ai/cordis": "~4.0.4",
@@ -70,7 +82,17 @@
70
82
  "tsdown": "^0.22.2",
71
83
  "tsx": "^4.22.4",
72
84
  "typescript": "^6.0.3",
73
- "semver": "^7.7.2"
85
+ "semver": "^7.7.2",
86
+ "@eslint/js": "^10.0.1",
87
+ "eslint": "^10.13.0",
88
+ "typescript-eslint": "^8.72.0",
89
+ "prettier": "^3.9.10",
90
+ "husky": "^9.1.7",
91
+ "lint-staged": "^17.6.0",
92
+ "knip": "^6.42.1",
93
+ "jscpd": "^5.4.1",
94
+ "@vitest/coverage-v8": "5.0.5",
95
+ "vitest": "5.0.5"
74
96
  },
75
97
  "dependencies": {
76
98
  "clsx": "^2.0.0",
@@ -128,5 +150,14 @@
128
150
  "reasoning",
129
151
  "streaming",
130
152
  "accessibility"
131
- ]
153
+ ],
154
+ "lint-staged": {
155
+ "*.{ts,tsx}": [
156
+ "eslint --fix",
157
+ "prettier --write"
158
+ ],
159
+ "*.{mjs,cjs,js,json,md,yml,yaml,css}": [
160
+ "prettier --write"
161
+ ]
162
+ }
132
163
  }
@@ -0,0 +1,20 @@
1
+ import { execFileSync } from 'node:child_process';
2
+ import { fileURLToPath } from 'node:url';
3
+
4
+ const root = fileURLToPath(new URL('..', import.meta.url));
5
+ const count = process.argv.includes('--self-test') ? '5' : '30';
6
+ const log = execFileSync(
7
+ 'git',
8
+ ['log', '--no-merges', '-n', count, '--date=short', '--pretty=format:%h %ad %s'],
9
+ { encoding: 'utf8', cwd: root },
10
+ );
11
+
12
+ console.log('# Notes from git log');
13
+ console.log('');
14
+ console.log('This prints history only. It does not rewrite CHANGELOG.md.');
15
+ console.log('');
16
+ if (!log.trim()) {
17
+ console.log('(no commits)');
18
+ } else {
19
+ for (const line of log.split('\n')) console.log(`- ${line}`);
20
+ }
@@ -0,0 +1,67 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { resolve } from 'node:path';
3
+
4
+ const BUILTINS = new Set([
5
+ 'ci', 'install', 'uninstall', 'update', 'outdated', 'ping', 'config', 'cache',
6
+ 'explore', 'exec', 'x', 'dlx', 'init', 'create', 'pack', 'publish', 'login',
7
+ 'logout', 'whoami', 'view', 'search', 'access', 'audit', 'fund', 'explain',
8
+ 'prefix', 'root', 'bin', 'ls', 'version', 'help', 'doctor', 'diff', 'pkg',
9
+ 'sbom', 'rebuild', 'link', 'unlink', 'prune', 'dedupe', 'install-test',
10
+ ]);
11
+
12
+ /** Script names referenced by fenced npm commands, or null when the command is a builtin. */
13
+ export function npmScriptName(rest) {
14
+ if (rest.startsWith('run ')) {
15
+ const name = rest.slice(4).trim().split(/\s+/)[0];
16
+ return name && !name.startsWith('-') ? name : '';
17
+ }
18
+ const head = rest.split(/\s+/)[0];
19
+ if (head === 'test' || head === 'start') return head;
20
+ if (BUILTINS.has(head)) return null;
21
+ return '';
22
+ }
23
+
24
+ export function missingNpmScripts(markdown, scriptNames) {
25
+ const missing = new Set();
26
+ for (const match of markdown.matchAll(/```[^\n]*\n([\s\S]*?)```/g)) {
27
+ for (const rawLine of match[1].split('\n')) {
28
+ for (const piece of rawLine.split(/&&|\|\||;/)) {
29
+ let command = piece.trim().replace(/^(?:[A-Za-z_][A-Za-z0-9_]*=\S*\s+)+/, '');
30
+ if (command.startsWith('$ ')) command = command.slice(2).trim();
31
+ if (!command.startsWith('npm ') && command !== 'npm') continue;
32
+ const name = npmScriptName(command.slice(3).trim());
33
+ if (name === null) continue;
34
+ if (!name || !scriptNames.has(name)) missing.add(name || command);
35
+ }
36
+ }
37
+ }
38
+ return [...missing];
39
+ }
40
+
41
+ function selfTest() {
42
+ const scripts = new Set(['build', 'test', 'typecheck']);
43
+ const ok = missingNpmScripts('```sh\nnpm ci\nnpm run build\nnpm test\n```\n', scripts);
44
+ const bad = missingNpmScripts('```sh\nnpm run nope\n```\nSee `npm run nope` outside.\n', scripts);
45
+ const unfenced = missingNpmScripts('Run npm run nope in prose.\n', scripts);
46
+ if (ok.length !== 0 || bad.join() !== 'nope' || unfenced.length !== 0) {
47
+ console.error('check-agents-md self-test failed', { ok, bad, unfenced });
48
+ process.exit(1);
49
+ }
50
+ console.log('check-agents-md self-test passed');
51
+ }
52
+
53
+ if (process.argv.includes('--self-test')) selfTest();
54
+
55
+ const root = resolve(import.meta.dirname, '..');
56
+ const markdown = readFileSync(resolve(root, 'AGENTS.md'), 'utf8');
57
+ if (!markdown.trim()) {
58
+ console.error('AGENTS.md is empty');
59
+ process.exit(1);
60
+ }
61
+ const pkg = JSON.parse(readFileSync(resolve(root, 'package.json'), 'utf8'));
62
+ const missing = missingNpmScripts(markdown, new Set(Object.keys(pkg.scripts ?? {})));
63
+ if (missing.length > 0) {
64
+ console.error(`AGENTS.md fenced npm commands are not package.json scripts: ${missing.join(', ')}`);
65
+ process.exit(1);
66
+ }
67
+ console.log('AGENTS.md fenced npm commands match package.json scripts');