aihand 0.0.1 → 0.1.0

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 (113) hide show
  1. package/README.md +136 -2
  2. package/dist/chunk-2NTK7H4W.js +10 -0
  3. package/dist/chunk-3X4FTHLC.cjs +369 -0
  4. package/dist/chunk-BXVNR4E2.js +399 -0
  5. package/dist/chunk-C7DGE6MY.cjs +1456 -0
  6. package/dist/chunk-DUUCVLC3.cjs +254 -0
  7. package/dist/chunk-FAHI53KO.cjs +125 -0
  8. package/dist/chunk-G7KVJ7NF.js +369 -0
  9. package/dist/chunk-GNEUSRGP.js +52 -0
  10. package/dist/chunk-IGNEAOLT.cjs +130 -0
  11. package/dist/chunk-IS5XFUDB.js +125 -0
  12. package/dist/chunk-JLYC76XL.js +2448 -0
  13. package/dist/chunk-KQOABC2O.cjs +52 -0
  14. package/dist/chunk-OVMK33AC.cjs +104 -0
  15. package/dist/chunk-OWYK2IGV.js +250 -0
  16. package/dist/chunk-PQSQN4CN.js +126 -0
  17. package/dist/chunk-QF6AG3M5.cjs +410 -0
  18. package/dist/chunk-QSAMLXML.js +1456 -0
  19. package/dist/chunk-VEKYRKPF.cjs +399 -0
  20. package/dist/chunk-Y6H7W7PI.cjs +2451 -0
  21. package/dist/chunk-YKSYW77R.js +410 -0
  22. package/dist/chunk-Z2Y65YOY.cjs +7 -0
  23. package/dist/chunk-ZJQRNIK7.js +104 -0
  24. package/dist/cli-FDS2C2CZ.cjs +651 -0
  25. package/dist/cli-HHRGYPSM.js +649 -0
  26. package/dist/cli-JQEIE7RQ.js +120 -0
  27. package/dist/cli-K3OS2QQH.cjs +122 -0
  28. package/dist/cli-OSYG6LJD.cjs +89 -0
  29. package/dist/cli-TXRW5PG6.js +89 -0
  30. package/dist/cli.cjs +81 -0
  31. package/dist/cli.js +81 -0
  32. package/dist/config-5KEQLN6L.cjs +13 -0
  33. package/dist/config-PJPYKDLQ.js +13 -0
  34. package/dist/graph-IH56SCPK.js +8 -0
  35. package/dist/graph-ZUXXCJ5A.cjs +8 -0
  36. package/dist/index.cjs +481 -0
  37. package/dist/index.d.cts +461 -0
  38. package/dist/index.d.ts +461 -0
  39. package/dist/index.js +479 -0
  40. package/dist/locate-5XFSXJ5J.cjs +15 -0
  41. package/dist/locate-NKSUGL3A.js +15 -0
  42. package/dist/refactor-5FWSZIBN.cjs +19 -0
  43. package/dist/refactor-BOB3SZSA.js +19 -0
  44. package/dist/scan-4R7GQG2W.cjs +9 -0
  45. package/dist/scan-VF54GAAX.js +9 -0
  46. package/dist/ui/probe/server.cjs +505 -0
  47. package/dist/ui/probe/server.js +507 -0
  48. package/dist/vite.cjs +12 -0
  49. package/dist/vite.d.cts +12 -0
  50. package/dist/vite.d.ts +12 -0
  51. package/dist/vite.js +12 -0
  52. package/package.json +82 -9
  53. package/src/cli.ts +107 -0
  54. package/src/index.ts +54 -0
  55. package/src/read/cli.ts +650 -0
  56. package/src/read/compact.ts +286 -0
  57. package/src/read/config.ts +62 -0
  58. package/src/read/graph.ts +182 -0
  59. package/src/read/index.ts +12 -0
  60. package/src/read/inject.ts +121 -0
  61. package/src/read/locate.ts +104 -0
  62. package/src/read/panel.ts +335 -0
  63. package/src/read/pipeline.ts +78 -0
  64. package/src/read/refactor.ts +576 -0
  65. package/src/read/render.ts +1118 -0
  66. package/src/read/scan.ts +61 -0
  67. package/src/read/seam.ts +0 -0
  68. package/src/read/security.ts +171 -0
  69. package/src/read/signals.ts +333 -0
  70. package/src/read/state.ts +71 -0
  71. package/src/read/stategraph.ts +205 -0
  72. package/src/read/types.ts +162 -0
  73. package/src/read/vite.ts +77 -0
  74. package/src/ui/babel/line-profiler.ts +197 -0
  75. package/src/ui/babel/source-loc.ts +68 -0
  76. package/src/ui/bridge/cdp-bridge.ts +138 -0
  77. package/src/ui/bridge/compile-probe.ts +80 -0
  78. package/src/ui/bridge/transport.ts +26 -0
  79. package/src/ui/bridge/vite-bridge.ts +116 -0
  80. package/src/ui/client/client-patch.ts +899 -0
  81. package/src/ui/client/client.ts +2562 -0
  82. package/src/ui/core/action.ts +747 -0
  83. package/src/ui/core/candidates.ts +348 -0
  84. package/src/ui/core/canvas.ts +305 -0
  85. package/src/ui/core/check.ts +34 -0
  86. package/src/ui/core/compact.ts +314 -0
  87. package/src/ui/core/detail.ts +244 -0
  88. package/src/ui/core/diff.ts +253 -0
  89. package/src/ui/core/emit.ts +198 -0
  90. package/src/ui/core/knob-exec.ts +137 -0
  91. package/src/ui/core/perf.ts +254 -0
  92. package/src/ui/core/types.ts +164 -0
  93. package/src/ui/core/util.ts +221 -0
  94. package/src/ui/index.ts +5 -0
  95. package/src/ui/probe/cli.ts +139 -0
  96. package/src/ui/probe/server.ts +468 -0
  97. package/src/ui/self/act.ts +47 -0
  98. package/src/ui/self/discover.ts +101 -0
  99. package/src/ui/self/grow.ts +121 -0
  100. package/src/ui/self/install.ts +100 -0
  101. package/src/ui/self/probe.ts +105 -0
  102. package/src/ui/self/screen-hook.ts +44 -0
  103. package/src/ui/self/self.ts +48 -0
  104. package/src/ui/self/store-refs.ts +123 -0
  105. package/src/ui/self/store-schema.ts +65 -0
  106. package/src/ui/self/synth.ts +37 -0
  107. package/src/ui/server/cli.ts +102 -0
  108. package/src/ui/server/dispatch.ts +276 -0
  109. package/src/ui/server/help-text.ts +237 -0
  110. package/src/ui/server/knob-schema.ts +87 -0
  111. package/src/ui/server/plugin.ts +1151 -0
  112. package/src/vite.ts +39 -0
  113. package/index.js +0 -2
@@ -0,0 +1,1456 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
2
+
3
+
4
+
5
+ var _chunk3X4FTHLCcjs = require('./chunk-3X4FTHLC.cjs');
6
+
7
+
8
+
9
+
10
+ var _chunkDUUCVLC3cjs = require('./chunk-DUUCVLC3.cjs');
11
+
12
+ // src/read/inject.ts
13
+ var _fs = require('fs');
14
+ var _path = require('path');
15
+ var START_TAG = "<!-- AIDEV:START -->";
16
+ var END_TAG = "<!-- AIDEV:END -->";
17
+ function ensureMarkers(filePath) {
18
+ if (!_fs.existsSync.call(void 0, filePath)) {
19
+ const dir = _path.dirname.call(void 0, filePath);
20
+ if (!_fs.existsSync.call(void 0, dir))
21
+ _fs.mkdirSync.call(void 0, dir, { recursive: true });
22
+ _fs.writeFileSync.call(void 0, filePath, `${START_TAG}
23
+ ${END_TAG}
24
+ `);
25
+ return "created";
26
+ }
27
+ const content = _fs.readFileSync.call(void 0, filePath, "utf-8");
28
+ if (content.includes(START_TAG))
29
+ return "skipped";
30
+ const sep = content.endsWith("\n") ? "" : "\n";
31
+ _fs.writeFileSync.call(void 0, filePath, `${content}${sep}
32
+ ${START_TAG}
33
+ ${END_TAG}
34
+ `);
35
+ return "marked";
36
+ }
37
+ var DEV_TOOL_HINT = "> Before changing code: `aihand` is this repo's read\xB7ui\xB7refactor tool (read the control panel / reverse-locate, drive the running page, AST refactor). Run `aihand --help` to expand.";
38
+ var CODEMAP_HINT = [
39
+ "> **Locate code** (on demand, don't pull the whole map first):",
40
+ "> \xB7 change a UI behavior \u2192 `aihand read panel` (knob \xD7 store morphism: one line per control, which field it writes)",
41
+ "> \xB7 where files live / the layout \u2192 `aihand read tree`",
42
+ "> \xB7 runtime coord \u2192 static symbol \u2192 `aihand read source <file:line>` (with callers/callees)",
43
+ "> \xB7 the full map at once \u2192 `aihand read --stdout`"
44
+ ].join("\n");
45
+ var DEFAULT_INJECT_FILES = ["CLAUDE.md", "AGENTS.md"];
46
+ function renderSections(config, data) {
47
+ const sections = [];
48
+ if (data.overview)
49
+ sections.push(`# Overview
50
+
51
+ ${data.overview}`);
52
+ if (config.read.injectCodemap) {
53
+ if (data.panel)
54
+ sections.push(`# Control Panel \u2014 \u7CFB\u7EDF\u7684\u63A7\u5236\u8BBA\u6A21\u578B
55
+
56
+ \u8FD9\u662F\u6700\u9AD8\u62BD\u8C61\u5C42\uFF1A\u4E00\u4E2A\u6D17\u8863\u673A\u9762\u677F\u3002\u7CFB\u7EDF\u65E0\u8BBA\u5185\u90E8\u591A\u590D\u6742\uFF08\u51E0\u5343\u7EC4\u4EF6\uFF09\uFF0C\u5176\u672C\u8D28 = **(\u65CB\u94AE \xD7 \u72B6\u6001) \u2192 \u72B6\u6001\u8F6C\u79FB**\u3002\u65CB\u94AE\u662F\u5B8C\u6574\u63A5\u53E3\uFF0C\u62E8\u4EFB\u4E00\u65CB\u94AE\u6574\u4E2A App \u8FDB\u5165\u65B0\u72B6\u6001\uFF1B\u4E0B\u9762\u7684\u72B6\u6001\u663E\u793A\u662F\u8F93\u51FA\u7AEF/\u53EF\u89C2\u6D4B\u91CF\u3002\u4E0B\u9762\u7684\u51E0\u5343\u7EC4\u4EF6\u5168\u662F\u8FD9\u5341\u51E0\u4E2A\u63A7\u5236\u91CF\u7684\u5C55\u5F00\u3002\u8BFB\u5B83\u5373\u77E5"\u8FD9 App \u80FD\u5E72\u4EC0\u4E48\u3001\u7531\u54EA\u4E9B\u72B6\u6001\u9A71\u52A8\u3001\u6539\u67D0\u4E2A UI \u53BB\u54EA\u4E2A store \u5B57\u6BB5"\u3002\u6539 UI \u884C\u4E3A\u524D\u5148\u5728\u8FD9\u91CC\u5B9A\u4F4D\uFF0C\u518D \`aihand read source\` \u5C55\u5F00\u3002
57
+
58
+ ## \u65CB\u94AE\uFF08\u8F93\u5165\u7AEF\uFF09
59
+
60
+ \u4E00\u884C\u4E00\u4E2A\u65CB\u94AE\uFF1A\`\u300C\u540D\u5B57\u300D \u4E8B\u4EF6 \u2192 store.{ \u5B57\u6BB5=\u76EE\u6807\u503C } :\u884C\u53F7\`\u2014\u2014\u62E8\u5B83\u628A\u54EA\u4E2A store \u72B6\u6001\u63A8\u5411\u4EC0\u4E48\u503C\u3002
61
+
62
+ \`\`\`
63
+ ${data.panel}
64
+ \`\`\``);
65
+ if (data.state)
66
+ sections.push(`## \u72B6\u6001\u663E\u793A\uFF08\u8F93\u51FA\u7AEF / \u53EF\u89C2\u6D4B\u91CF\uFF09
67
+
68
+ \u7CFB\u7EDF\u7531\u54EA\u4E9B\u72B6\u6001\u91CF\u6784\u6210\u3001\u5404\u81EA\u521D\u503C\u3001\u5404\u81EA\u503C\u57DF\uFF08\`{a|b|c}\` = \u53EF\u679A\u4E3E\u7684\u79BB\u6563\u6001\uFF0C\u5373\u9762\u677F\u80FD\u663E\u793A\u7684\u72B6\u6001\u673A\uFF1B\u65E0\u6807\u6CE8 = boolean/\u5BF9\u8C61\u7B49\u975E\u679A\u4E3E\u6001\uFF09\u3002\u65CB\u94AE\u62E8\u52A8\u7684\u5C31\u662F\u8FD9\u4E9B\u91CF\u3002
69
+
70
+ \`\`\`
71
+ ${data.state}
72
+ \`\`\``);
73
+ if (data.tree)
74
+ sections.push(`# File Tree
75
+
76
+ ${data.tree}`);
77
+ if (data.signatures)
78
+ sections.push(`# Signatures
79
+
80
+ \`\`\`
81
+ ${data.signatures}
82
+ \`\`\``);
83
+ if (data.full)
84
+ sections.push(`# Full Source
85
+
86
+ \`\`\`
87
+ ${data.full}
88
+ \`\`\``);
89
+ } else {
90
+ sections.push(CODEMAP_HINT);
91
+ }
92
+ if (config.read.injectDevToolInstructions)
93
+ sections.push(DEV_TOOL_HINT);
94
+ return sections.join("\n\n");
95
+ }
96
+ function computeInjection(content, config, data) {
97
+ const si = content.indexOf(START_TAG);
98
+ const ei = content.indexOf(END_TAG);
99
+ if (si === -1 || ei === -1)
100
+ return null;
101
+ const oldBody = content.slice(si + START_TAG.length, ei);
102
+ const newBody = `
103
+
104
+ ${renderSections(config, data)}
105
+ `;
106
+ if (oldBody === newBody)
107
+ return null;
108
+ const before = content.slice(0, si + START_TAG.length);
109
+ const after = content.slice(ei);
110
+ return `${before}${newBody}${after}`;
111
+ }
112
+ function injectFile(config, data, filePath) {
113
+ if (!_fs.existsSync.call(void 0, filePath))
114
+ return false;
115
+ const next = computeInjection(_fs.readFileSync.call(void 0, filePath, "utf-8"), config, data);
116
+ if (next === null)
117
+ return false;
118
+ _fs.writeFileSync.call(void 0, filePath, next);
119
+ return true;
120
+ }
121
+ function injectAll(config, data, files = DEFAULT_INJECT_FILES) {
122
+ const injected = [];
123
+ for (const f of files) {
124
+ if (injectFile(config, data, f))
125
+ injected.push(f);
126
+ }
127
+ return injected;
128
+ }
129
+
130
+ // src/read/state.ts
131
+
132
+ var _process = require('process'); var _process2 = _interopRequireDefault(_process);
133
+ var toStateField = (f) => ({
134
+ name: f.name,
135
+ init: f.init,
136
+ domain: f.domain.length ? f.domain : null
137
+ });
138
+ async function buildState(paths, marker = "_loading") {
139
+ const cwd = _process2.default.cwd();
140
+ const project = await _chunk3X4FTHLCcjs.openProject.call(void 0, cwd);
141
+ const inScope = paths ? new Set(paths) : null;
142
+ const { nodes } = _chunk3X4FTHLCcjs.buildStateGraph.call(void 0, project, (abs) => _path.relative.call(void 0, cwd, abs), marker);
143
+ const states = [];
144
+ for (const n of nodes) {
145
+ const filePath = n.anchor.slice(0, n.anchor.lastIndexOf(":"));
146
+ if (inScope && !inScope.has(filePath))
147
+ continue;
148
+ const decl = _optionalChain([project, 'access', _ => _.getSourceFile, 'call', _2 => _2(_path.resolve.call(void 0, cwd, filePath)), 'optionalAccess', _3 => _3.getVariableDeclarations, 'call', _4 => _4(), 'access', _5 => _5.find, 'call', _6 => _6((v) => v.getName() === n.store)]);
149
+ if (!decl)
150
+ continue;
151
+ const fields = _chunk3X4FTHLCcjs.extractStoreFields.call(void 0, decl, marker);
152
+ if (fields.length)
153
+ states.push({ store: n.store, filePath, fields: fields.map(toStateField) });
154
+ }
155
+ return states;
156
+ }
157
+ function formatState(states) {
158
+ const lines = [];
159
+ for (const s of states) {
160
+ lines.push(`${s.store} (${s.filePath})`);
161
+ for (const f of s.fields) {
162
+ const dom = f.domain ? ` {${f.domain.join("|")}}` : "";
163
+ lines.push(` ${f.name} = ${f.init}${dom}`);
164
+ }
165
+ }
166
+ return lines.join("\n");
167
+ }
168
+
169
+ // src/read/render.ts
170
+
171
+ var _ignore = require('ignore'); var _ignore2 = _interopRequireDefault(_ignore);
172
+ var _mdastutilfrommarkdown = require('mdast-util-from-markdown');
173
+ var _nodehtmlparser = require('node-html-parser');
174
+ var _postcss = require('postcss'); var _postcss2 = _interopRequireDefault(_postcss);
175
+ var _postcssless = require('postcss-less'); var _postcssless2 = _interopRequireDefault(_postcssless);
176
+ var _postcssscss = require('postcss-scss'); var _postcssscss2 = _interopRequireDefault(_postcssscss);
177
+ var _webtreesitter = require('web-tree-sitter');
178
+ var _yaml = require('yaml');
179
+ function buildClassifier(detail, defaultLevel = "compact") {
180
+ const matchers = [];
181
+ for (const level of ["tree", "full", "compact"]) {
182
+ const globs = Object.keys(detail).filter((p) => detail[p] === level);
183
+ if (globs.length)
184
+ matchers.push({ level, ig: _ignore2.default.call(void 0, ).add(globs) });
185
+ }
186
+ return (path) => _nullishCoalesce(_optionalChain([matchers, 'access', _7 => _7.find, 'call', _8 => _8((m) => m.ig.ignores(path)), 'optionalAccess', _9 => _9.level]), () => ( defaultLevel));
187
+ }
188
+ var STACK_INCLUDE = /* @__PURE__ */ new Set([
189
+ // Platform
190
+ "electron",
191
+ "react-native",
192
+ "@tauri-apps/api",
193
+ "@capacitor/core",
194
+ // Meta-framework
195
+ "next",
196
+ "nuxt",
197
+ "@remix-run/react",
198
+ "astro",
199
+ "gatsby",
200
+ "@sveltejs/kit",
201
+ // UI framework
202
+ "react",
203
+ "vue",
204
+ "svelte",
205
+ "solid-js",
206
+ "@angular/core",
207
+ // Build
208
+ "vite",
209
+ "webpack",
210
+ "esbuild",
211
+ "@rspack/core",
212
+ "turbopack",
213
+ // Monorepo
214
+ "turbo",
215
+ "nx",
216
+ // Language
217
+ "typescript",
218
+ // Styling
219
+ "tailwindcss",
220
+ "unocss",
221
+ "styled-components",
222
+ "@emotion/css",
223
+ "@emotion/react",
224
+ "@vanilla-extract/css",
225
+ // Component lib
226
+ "class-variance-authority",
227
+ "@mui/material",
228
+ "antd",
229
+ "@chakra-ui/react",
230
+ "@mantine/core",
231
+ "@headlessui/react",
232
+ "element-plus",
233
+ "@arco-design/web-react",
234
+ "@arco-design/mobile-react",
235
+ "naive-ui",
236
+ "vuetify",
237
+ // Icons
238
+ "lucide-react",
239
+ "@heroicons/react",
240
+ // Routing
241
+ "react-router-dom",
242
+ "@tanstack/react-router",
243
+ "vue-router",
244
+ // State
245
+ "mobx",
246
+ "zustand",
247
+ "redux",
248
+ "@reduxjs/toolkit",
249
+ "@tanstack/react-query",
250
+ "jotai",
251
+ "pinia",
252
+ "valtio",
253
+ "xstate",
254
+ "swr",
255
+ "@apollo/client",
256
+ // Forms
257
+ "react-hook-form",
258
+ // Animation
259
+ "framer-motion",
260
+ "@react-spring/web",
261
+ // Rich text / Editor
262
+ "@tiptap/react",
263
+ "@monaco-editor/react",
264
+ // DnD
265
+ "@dnd-kit/core",
266
+ // Virtualization
267
+ "@tanstack/react-virtual",
268
+ // Charts
269
+ "recharts",
270
+ "@nivo/core",
271
+ "d3",
272
+ // Canvas / Visual
273
+ "@xyflow/react",
274
+ "three",
275
+ "@react-three/fiber",
276
+ // Testing
277
+ "vitest",
278
+ "jest",
279
+ "@playwright/test",
280
+ "cypress",
281
+ // Backend
282
+ "express",
283
+ "fastify",
284
+ "hono",
285
+ "@nestjs/core",
286
+ // ORM / DB
287
+ "drizzle-orm",
288
+ "prisma",
289
+ "@prisma/client",
290
+ "mongoose",
291
+ // BaaS
292
+ "@supabase/supabase-js",
293
+ "firebase",
294
+ // AI
295
+ "ai",
296
+ "@langchain/core",
297
+ // API
298
+ "@trpc/server",
299
+ "graphql",
300
+ // Storage
301
+ "dexie"
302
+ ]);
303
+ var STACK_COLLAPSE = [
304
+ { prefix: "@dnd-kit/", label: "dnd-kit" },
305
+ { prefix: "@tiptap/", label: "tiptap" },
306
+ { prefix: "@tanstack/react-query", label: "tanstack-query" },
307
+ { prefix: "@tanstack/react-router", label: "tanstack-router" },
308
+ { prefix: "@tanstack/react-virtual", label: "tanstack-virtual" },
309
+ { prefix: "@emotion/", label: "emotion" },
310
+ { prefix: "@mui/", label: "mui" },
311
+ { prefix: "@chakra-ui/", label: "chakra" },
312
+ { prefix: "@mantine/", label: "mantine" },
313
+ { prefix: "@headlessui/", label: "headless-ui" },
314
+ { prefix: "@heroicons/", label: "heroicons" },
315
+ { prefix: "@arco-design/", label: "arco-design" },
316
+ { prefix: "@nestjs/", label: "nestjs" },
317
+ { prefix: "@supabase/", label: "supabase" },
318
+ { prefix: "@langchain/", label: "langchain" },
319
+ { prefix: "@trpc/", label: "trpc" },
320
+ { prefix: "@prisma/", label: "prisma" },
321
+ { prefix: "@remix-run/", label: "remix" },
322
+ { prefix: "@sveltejs/kit", label: "sveltekit" },
323
+ { prefix: "@angular/", label: "angular" },
324
+ { prefix: "@tauri-apps/", label: "tauri" },
325
+ { prefix: "@capacitor/", label: "capacitor" },
326
+ { prefix: "@xyflow/", label: "react-flow" },
327
+ { prefix: "@react-three/", label: "r3f" },
328
+ { prefix: "@react-spring/", label: "react-spring" },
329
+ { prefix: "@reduxjs/", label: "redux" },
330
+ { prefix: "@playwright/", label: "playwright" },
331
+ { prefix: "@rspack/", label: "rspack" },
332
+ { prefix: "@monaco-editor/", label: "monaco" },
333
+ { prefix: "@apollo/", label: "apollo" },
334
+ { prefix: "@nivo/", label: "nivo" },
335
+ { prefix: "@vanilla-extract/", label: "vanilla-extract" }
336
+ ];
337
+ var STACK_RENAME = {
338
+ "typescript": "ts",
339
+ "tailwindcss": "tailwind",
340
+ "class-variance-authority": "shadcn/ui",
341
+ "ai": "vercel-ai",
342
+ "solid-js": "solid",
343
+ "drizzle-orm": "drizzle",
344
+ "lucide-react": "lucide"
345
+ };
346
+ var STACK_PRIORITY = {
347
+ // Platform / runtime
348
+ "electron": 0,
349
+ "react-native": 0,
350
+ "tauri": 0,
351
+ "capacitor": 0,
352
+ // Meta-framework
353
+ "next": 1,
354
+ "nuxt": 1,
355
+ "remix": 1,
356
+ "astro": 1,
357
+ "gatsby": 1,
358
+ "sveltekit": 1,
359
+ // UI framework
360
+ "react": 2,
361
+ "vue": 2,
362
+ "svelte": 2,
363
+ "solid": 2,
364
+ "angular": 2,
365
+ // Bundler + lang
366
+ "vite": 3,
367
+ "webpack": 3,
368
+ "esbuild": 3,
369
+ "rspack": 3,
370
+ "turbopack": 3,
371
+ "ts": 3,
372
+ // Monorepo
373
+ "turbo": 4,
374
+ "nx": 4,
375
+ // State
376
+ "mobx": 5,
377
+ "zustand": 5,
378
+ "redux": 5,
379
+ "jotai": 5,
380
+ "pinia": 5,
381
+ "valtio": 5,
382
+ "xstate": 5,
383
+ // Styling
384
+ "tailwind": 5,
385
+ "unocss": 5,
386
+ "styled-components": 5,
387
+ "emotion": 5,
388
+ "vanilla-extract": 5,
389
+ // Component library
390
+ "shadcn/ui": 6,
391
+ "mui": 6,
392
+ "antd": 6,
393
+ "chakra": 6,
394
+ "mantine": 6,
395
+ "headless-ui": 6,
396
+ "element-plus": 6,
397
+ "arco-design": 6,
398
+ "naive-ui": 6,
399
+ "vuetify": 6,
400
+ // Data / network
401
+ "vercel-ai": 7,
402
+ "langchain": 7,
403
+ "tanstack-query": 7,
404
+ "swr": 7,
405
+ "apollo": 7,
406
+ "trpc": 7,
407
+ "graphql": 7,
408
+ "drizzle": 7,
409
+ "prisma": 7,
410
+ "mongoose": 7,
411
+ "supabase": 7,
412
+ "firebase": 7,
413
+ "dexie": 7,
414
+ // Testing
415
+ "vitest": 8,
416
+ "jest": 8,
417
+ "playwright": 8,
418
+ "cypress": 8,
419
+ // Package manager (detected separately, always first)
420
+ "bun": -1,
421
+ "pnpm": -1,
422
+ "yarn": -1
423
+ };
424
+ function detectStack(pkg, packageManager) {
425
+ const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
426
+ const keys = Object.keys(allDeps);
427
+ const result = [];
428
+ if (packageManager)
429
+ result.push(packageManager);
430
+ for (const dep of keys) {
431
+ if (!STACK_INCLUDE.has(dep))
432
+ continue;
433
+ const collapse = STACK_COLLAPSE.find((c) => dep.startsWith(c.prefix));
434
+ const label = collapse ? collapse.label : _nullishCoalesce(STACK_RENAME[dep], () => ( dep));
435
+ if (!result.includes(label))
436
+ result.push(label);
437
+ }
438
+ return result.sort((a, b) => (_nullishCoalesce(STACK_PRIORITY[a], () => ( 7))) - (_nullishCoalesce(STACK_PRIORITY[b], () => ( 7))));
439
+ }
440
+ function detectPackageManager(filePath) {
441
+ const dir = filePath.includes("/") ? filePath.slice(0, filePath.lastIndexOf("/") + 1) : "./";
442
+ if (_fs.existsSync.call(void 0, `${dir}bun.lock`))
443
+ return "bun";
444
+ if (_fs.existsSync.call(void 0, `${dir}pnpm-lock.yaml`))
445
+ return "pnpm";
446
+ if (_fs.existsSync.call(void 0, `${dir}yarn.lock`))
447
+ return "yarn";
448
+ return "";
449
+ }
450
+ function compactPackageJson(content, filePath, packageManager = detectPackageManager(filePath)) {
451
+ try {
452
+ const pkg = JSON.parse(content);
453
+ const parts = [];
454
+ const stack = detectStack(pkg, packageManager);
455
+ if (stack.length)
456
+ parts.push(`stack: ${stack.join(", ")}`);
457
+ if (pkg.scripts)
458
+ parts.push(`scripts: ${Object.keys(pkg.scripts).join(", ")}`);
459
+ const meta = [];
460
+ if (pkg.type)
461
+ meta.push(`type: ${pkg.type}`);
462
+ if (pkg.main)
463
+ meta.push(`main: ${pkg.main}`);
464
+ if (pkg.workspaces) {
465
+ const ws = Array.isArray(pkg.workspaces) ? pkg.workspaces : _nullishCoalesce(pkg.workspaces.packages, () => ( []));
466
+ if (ws.length)
467
+ meta.push(`workspaces: ${ws.join(", ")}`);
468
+ }
469
+ if (meta.length)
470
+ parts.splice(1, 0, meta.join(", "));
471
+ return parts.join("\n") || "";
472
+ } catch (e2) {
473
+ return "";
474
+ }
475
+ }
476
+ function stripJsonComments(src) {
477
+ let out = "";
478
+ for (let i = 0; i < src.length; i++) {
479
+ if (src[i] === "/" && src[i + 1] === "/") {
480
+ i += 2;
481
+ while (i < src.length && src[i] !== "\n") i++;
482
+ i--;
483
+ } else if (src[i] === "/" && src[i + 1] === "*") {
484
+ i += 2;
485
+ while (i < src.length && !(src[i] === "*" && src[i + 1] === "/")) i++;
486
+ i++;
487
+ } else {
488
+ out += src[i];
489
+ }
490
+ }
491
+ return out;
492
+ }
493
+ function compactTsconfig(content) {
494
+ try {
495
+ const stripped = stripJsonComments(content);
496
+ const cfg = JSON.parse(stripped);
497
+ const co = _nullishCoalesce(cfg.compilerOptions, () => ( {}));
498
+ const parts = [];
499
+ if (co.target)
500
+ parts.push(`target: ${co.target}`);
501
+ if (co.jsx)
502
+ parts.push(`jsx: ${co.jsx}`);
503
+ if (co.paths) {
504
+ const aliases = Object.entries(co.paths).map(([k, v]) => `"${k}": "${_nullishCoalesce(v[0], () => ( ""))}"`).join(", ");
505
+ parts.push(`paths: { ${aliases} }`);
506
+ }
507
+ if (cfg.extends)
508
+ parts.push(`extends: ${cfg.extends}`);
509
+ if (cfg.include)
510
+ parts.push(`include: ${cfg.include.join(", ")}`);
511
+ return parts.join(", ") || "";
512
+ } catch (e3) {
513
+ return "";
514
+ }
515
+ }
516
+ function compactYaml(content) {
517
+ let doc;
518
+ try {
519
+ doc = _yaml.parse.call(void 0, content);
520
+ } catch (e4) {
521
+ return "";
522
+ }
523
+ if (!doc || typeof doc !== "object" || Array.isArray(doc))
524
+ return "";
525
+ const result = [];
526
+ for (const [key, val] of Object.entries(doc)) {
527
+ if (val && typeof val === "object" && !Array.isArray(val)) {
528
+ const sub = Object.keys(val).slice(0, 12).join(", ");
529
+ result.push(sub ? `${key}: ${sub}` : key);
530
+ } else if (Array.isArray(val)) {
531
+ result.push(`${key}: ${val.slice(0, 8).join(", ")}`);
532
+ } else if (val != null) {
533
+ result.push(`${key}: ${val}`);
534
+ } else {
535
+ result.push(key);
536
+ }
537
+ }
538
+ return result.join("\n");
539
+ }
540
+ function compactDockerfile(content) {
541
+ const KEEP = /* @__PURE__ */ new Set(["FROM", "WORKDIR", "EXPOSE", "CMD", "ENTRYPOINT", "ARG"]);
542
+ const parts = [];
543
+ let buf = "";
544
+ for (const raw of content.split("\n")) {
545
+ const line = raw.trim();
546
+ if (!line || line.startsWith("#"))
547
+ continue;
548
+ if (line.endsWith("\\")) {
549
+ buf += `${line.slice(0, -1)} `;
550
+ continue;
551
+ }
552
+ const full = (buf + line).trim();
553
+ buf = "";
554
+ const spaceIdx = full.indexOf(" ");
555
+ if (spaceIdx === -1)
556
+ continue;
557
+ const cmd = full.slice(0, spaceIdx).toUpperCase();
558
+ const arg = full.slice(spaceIdx + 1).trim();
559
+ if (!KEEP.has(cmd))
560
+ continue;
561
+ const val = cmd === "ARG" ? arg.slice(0, arg.includes("=") ? arg.indexOf("=") : void 0) : arg;
562
+ parts.push(`${cmd} ${val}`);
563
+ }
564
+ return parts.join("\n");
565
+ }
566
+ function compactCss(content, filename) {
567
+ const syntax = filename.endsWith(".scss") ? _postcssscss2.default : filename.endsWith(".less") ? _postcssless2.default : void 0;
568
+ try {
569
+ const root = syntax ? _postcss2.default.call(void 0, ).process(content, { syntax }).root : _postcss2.default.parse(content);
570
+ const seen = /* @__PURE__ */ new Set();
571
+ root.walkDecls((decl) => {
572
+ if (decl.prop.startsWith("--"))
573
+ seen.add(decl.prop);
574
+ });
575
+ return [...seen].join(", ");
576
+ } catch (e5) {
577
+ return "";
578
+ }
579
+ }
580
+ function compactEnv(content) {
581
+ const keys = content.split("\n").map((l) => l.trim()).filter((l) => l && !l.startsWith("#") && l.includes("=")).map((l) => l.slice(0, l.indexOf("=")));
582
+ return keys.length ? keys.join(", ") : "";
583
+ }
584
+ function compactHtml(content) {
585
+ const root = _nodehtmlparser.parse.call(void 0, content);
586
+ const parts = [];
587
+ const title = root.querySelector("title");
588
+ if (_optionalChain([title, 'optionalAccess', _10 => _10.text, 'access', _11 => _11.trim, 'call', _12 => _12()]))
589
+ parts.push(`title: ${title.text.trim()}`);
590
+ const SCRIPT_EXTS = [".tsx", ".ts", ".jsx", ".js", ".mjs"];
591
+ const entry = root.querySelectorAll("script[src]").map((n) => n.getAttribute("src")).find((src) => SCRIPT_EXTS.some((ext) => src.endsWith(ext)));
592
+ if (entry)
593
+ parts.push(`entry: ${entry}`);
594
+ return parts.join(", ") || "";
595
+ }
596
+ function compactMarkdown(content) {
597
+ const tree = _mdastutilfrommarkdown.fromMarkdown.call(void 0, content);
598
+ return tree.children.filter((n) => n.type === "heading" && n.depth <= 3).map((n) => {
599
+ const text = n.children.map((c) => "value" in c ? c.value : "").join("");
600
+ return `${"#".repeat(n.depth)} ${text}`;
601
+ }).join("\n");
602
+ }
603
+ var NON_CODE_COMPRESSORS = [
604
+ { match: (f) => f === "package.json", compress: compactPackageJson },
605
+ { match: (f) => f.startsWith("tsconfig") && f.endsWith(".json"), compress: (c) => compactTsconfig(c) },
606
+ { match: (f) => f === ".env" || f.startsWith(".env."), compress: (c) => compactEnv(c) },
607
+ { match: (f) => f.endsWith(".html"), compress: (c) => compactHtml(c) },
608
+ { match: (f) => f.endsWith(".yml") || f.endsWith(".yaml"), compress: (c) => compactYaml(c) },
609
+ { match: (f) => f === "Dockerfile" || f.startsWith("Dockerfile."), compress: (c) => compactDockerfile(c) },
610
+ { match: (f) => f.endsWith(".css") || f.endsWith(".scss") || f.endsWith(".less"), compress: (c, p) => compactCss(c, p.slice(p.lastIndexOf("/") + 1)) },
611
+ { match: (f) => f.endsWith(".md"), compress: (c) => compactMarkdown(c) }
612
+ ];
613
+ var isWs = (c) => c === " " || c === " " || c === "\n" || c === "\r" || c === "\f" || c === "\v";
614
+ var isDigit = (c) => c >= "0" && c <= "9";
615
+ function extractPort(src) {
616
+ let from = 0;
617
+ for (; ; ) {
618
+ const idx = src.indexOf("port", from);
619
+ if (idx === -1)
620
+ return "";
621
+ from = idx + 4;
622
+ let i = from;
623
+ while (i < src.length && isWs(src[i])) i++;
624
+ if (src[i] !== ":")
625
+ continue;
626
+ i++;
627
+ while (i < src.length && isWs(src[i])) i++;
628
+ let n = 0;
629
+ while (i + n < src.length && isDigit(src[i + n])) n++;
630
+ if (n)
631
+ return src.slice(i, i + n);
632
+ }
633
+ }
634
+ function extractAliasKeys(src) {
635
+ let from = 0;
636
+ for (; ; ) {
637
+ const idx = src.indexOf("alias", from);
638
+ if (idx === -1)
639
+ return [];
640
+ from = idx + 5;
641
+ let i = from;
642
+ while (i < src.length && isWs(src[i])) i++;
643
+ if (src[i] !== ":")
644
+ continue;
645
+ i++;
646
+ while (i < src.length && isWs(src[i])) i++;
647
+ if (src[i] !== "{")
648
+ continue;
649
+ const close = src.indexOf("}", i);
650
+ if (close === -1)
651
+ continue;
652
+ return extractQuotedKeys(src.slice(i + 1, close));
653
+ }
654
+ }
655
+ function extractQuotedKeys(body) {
656
+ const keys = [];
657
+ for (let i = 0; i < body.length; i++) {
658
+ const q = body[i];
659
+ if (q !== "'" && q !== '"')
660
+ continue;
661
+ const end = body.indexOf(q, i + 1);
662
+ if (end === -1)
663
+ break;
664
+ const key = body.slice(i + 1, end);
665
+ let j = end + 1;
666
+ while (j < body.length && isWs(body[j])) j++;
667
+ if (body[j] === ":")
668
+ keys.push(key);
669
+ i = end;
670
+ }
671
+ return keys;
672
+ }
673
+ async function buildBlocks(paths, config, wasmDir, classifyFn, contents) {
674
+ await _webtreesitter.Parser.init();
675
+ const parser = new (0, _webtreesitter.Parser)();
676
+ const classifyPath = _nullishCoalesce(classifyFn, () => ( buildClassifier(config.read.fileDetailLevel)));
677
+ const blocks = [];
678
+ let currentLang = null;
679
+ for (const path of paths) {
680
+ const level = classifyPath(path);
681
+ if (level === "tree") {
682
+ blocks.push({ path, level, content: "" });
683
+ continue;
684
+ }
685
+ const raw = _nullishCoalesce(_optionalChain([contents, 'optionalAccess', _13 => _13.get, 'call', _14 => _14(path)]), () => ( _fs.readFileSync.call(void 0, path, "utf-8")));
686
+ if (!raw.trim())
687
+ continue;
688
+ if (level === "full") {
689
+ blocks.push({ path, level, content: raw });
690
+ continue;
691
+ }
692
+ const ext = path.slice(path.lastIndexOf("."));
693
+ const lang = await _chunkDUUCVLC3cjs.getLang.call(void 0, ext, wasmDir);
694
+ if (lang && lang !== currentLang) {
695
+ parser.setLanguage(lang);
696
+ currentLang = lang;
697
+ }
698
+ let tree;
699
+ if (lang) {
700
+ tree = _nullishCoalesce(parser.parse(raw), () => ( void 0));
701
+ }
702
+ const imports = lang ? _chunkDUUCVLC3cjs.extractImports.call(void 0, raw, parser, lang, tree) : void 0;
703
+ const filename = path.slice(path.lastIndexOf("/") + 1);
704
+ let content;
705
+ if (filename.startsWith("vite.config.") && lang) {
706
+ const plugins = (_nullishCoalesce(imports, () => ( []))).filter((p) => !p.startsWith("node:") && !p.startsWith(".") && (p.includes("plugin") || p.startsWith("@vitejs/")));
707
+ const info = [];
708
+ if (plugins.length)
709
+ info.push(`plugins: ${plugins.join(", ")}`);
710
+ const port = extractPort(raw);
711
+ if (port)
712
+ info.push(`port: ${port}`);
713
+ const aliasKeys = extractAliasKeys(raw);
714
+ if (aliasKeys.length)
715
+ info.push(`alias: ${aliasKeys.join(", ")}`);
716
+ content = info.join(", ");
717
+ } else if (lang) {
718
+ content = _chunkDUUCVLC3cjs.compact.call(void 0, raw, parser, lang, {
719
+ skipNoParamFn: !config.read.showNoParamFn
720
+ }, tree);
721
+ } else {
722
+ const c = NON_CODE_COMPRESSORS.find((c2) => c2.match(filename));
723
+ content = c ? c.compress(raw, path) : "";
724
+ }
725
+ _optionalChain([tree, 'optionalAccess', _15 => _15.delete, 'call', _16 => _16()]);
726
+ if (content.trim())
727
+ blocks.push({ path, level, content, imports });
728
+ }
729
+ parser.delete();
730
+ return blocks;
731
+ }
732
+ var CODE_EXTS = /* @__PURE__ */ new Set([
733
+ ".ts",
734
+ ".tsx",
735
+ ".js",
736
+ ".jsx",
737
+ ".mjs",
738
+ ".cjs",
739
+ ".vue",
740
+ ".svelte",
741
+ ".py",
742
+ ".rb",
743
+ ".go",
744
+ ".rs",
745
+ ".java",
746
+ ".c",
747
+ ".cpp",
748
+ ".cs",
749
+ ".swift",
750
+ ".kt"
751
+ ]);
752
+ function getExt(name) {
753
+ return name.includes(".") ? name.slice(name.lastIndexOf(".")) : "(no ext)";
754
+ }
755
+ var isHex = (c) => c >= "0" && c <= "9" || c >= "a" && c <= "f" || c >= "A" && c <= "F";
756
+ var isAlpha = (c) => c >= "a" && c <= "z" || c >= "A" && c <= "Z";
757
+ function classSeq(stem) {
758
+ let out = "";
759
+ let prev = "";
760
+ for (const c of stem) {
761
+ const cls = isHex(c) ? "H" : isAlpha(c) ? "A" : c === "-" || c === "_" || c === "." ? "S" : "X";
762
+ if (cls !== prev) {
763
+ out += cls;
764
+ prev = cls;
765
+ }
766
+ }
767
+ return out;
768
+ }
769
+ var HOMOGENEOUS_FOLD_MIN = 3;
770
+ function formatTree(paths, foldThreshold = 8, opts = {}) {
771
+ const { skeletonOnly = false, kept, collapsedDirs, starred } = opts;
772
+ const star = (fullPath) => _optionalChain([starred, 'optionalAccess', _17 => _17.has, 'call', _18 => _18(fullPath)]) ? " \u2605" : "";
773
+ const root = { children: /* @__PURE__ */ new Map() };
774
+ for (const path of paths) {
775
+ const parts = path.split("/");
776
+ let node = root;
777
+ for (let i = 0; i < parts.length - 1; i++) {
778
+ if (!node.children.has(parts[i]))
779
+ node.children.set(parts[i], { children: /* @__PURE__ */ new Map() });
780
+ node = node.children.get(parts[i]);
781
+ }
782
+ node.children.set(parts[parts.length - 1], { children: /* @__PURE__ */ new Map(), file: true });
783
+ }
784
+ function mergeExt(exts, ext, incoming) {
785
+ const existing = exts.get(ext);
786
+ if (!existing) {
787
+ exts.set(ext, { ...incoming });
788
+ return;
789
+ }
790
+ const count = existing.count + incoming.count;
791
+ exts.set(ext, { count });
792
+ }
793
+ function annotate(node) {
794
+ const exts = /* @__PURE__ */ new Map();
795
+ let count = 0;
796
+ let dirCount = 0;
797
+ let hasCode = false;
798
+ for (const [name, child] of node.children) {
799
+ if (child.file) {
800
+ const ext = getExt(name);
801
+ mergeExt(exts, ext, { count: 1, name });
802
+ count++;
803
+ if (CODE_EXTS.has(ext))
804
+ hasCode = true;
805
+ } else {
806
+ annotate(child);
807
+ count += _nullishCoalesce(child.subtreeCount, () => ( 0));
808
+ dirCount += 1 + (_nullishCoalesce(child.subtreeDirCount, () => ( 0)));
809
+ if (child.hasCode)
810
+ hasCode = true;
811
+ for (const [ext, entry] of _nullishCoalesce(child.subtreeExts, () => ( [])))
812
+ mergeExt(exts, ext, entry);
813
+ }
814
+ }
815
+ node.hasCode = hasCode;
816
+ node.subtreeExts = exts;
817
+ node.subtreeCount = count;
818
+ node.subtreeDirCount = dirCount;
819
+ }
820
+ annotate(root);
821
+ const lines = [];
822
+ const FOLD_DIRS = /* @__PURE__ */ new Set(["ui", "icons"]);
823
+ const leafFileNames = (n) => {
824
+ const names = [];
825
+ for (const [name, c] of n.children) {
826
+ if (!c.file)
827
+ return null;
828
+ names.push(name);
829
+ }
830
+ return names;
831
+ };
832
+ function foldSiblingDirs(dirEntries) {
833
+ const groups = /* @__PURE__ */ new Map();
834
+ const rest = [];
835
+ for (const [name, c] of dirEntries) {
836
+ const names = leafFileNames(c);
837
+ if (!names || !names.length) {
838
+ rest.push([name, c]);
839
+ continue;
840
+ }
841
+ const sorted = [...names].sort();
842
+ const sig = `N:${sorted.join("|")}`;
843
+ groups.set(sig, [..._nullishCoalesce(groups.get(sig), () => ( [])), { entry: [name, c], names: sorted }]);
844
+ }
845
+ const extGroups = /* @__PURE__ */ new Map();
846
+ for (const [sig, arr] of [...groups]) {
847
+ if (arr.length >= HOMOGENEOUS_FOLD_MIN)
848
+ continue;
849
+ groups.delete(sig);
850
+ for (const item of arr) {
851
+ const extSig = `E:${item.names.map(getExt).sort().join("|")}`;
852
+ extGroups.set(extSig, [..._nullishCoalesce(extGroups.get(extSig), () => ( [])), item]);
853
+ }
854
+ }
855
+ const folded = [];
856
+ const emit = (arr, byName) => {
857
+ const sample = arr[0].names;
858
+ const body = byName ? sample.join(", ") : [...new Set(sample.map(getExt))].map((e) => {
859
+ const n = sample.filter((name) => getExt(name) === e).length;
860
+ return n > 1 ? `${e} \xD7${n}` : e;
861
+ }).join(", ");
862
+ folded.push(`[name]/ (${body}) \xD7${arr.length}`);
863
+ };
864
+ for (const arr of groups.values()) {
865
+ if (arr.length >= HOMOGENEOUS_FOLD_MIN)
866
+ emit(arr, true);
867
+ else arr.forEach((i) => rest.push(i.entry));
868
+ }
869
+ for (const arr of extGroups.values()) {
870
+ if (arr.length >= HOMOGENEOUS_FOLD_MIN)
871
+ emit(arr, false);
872
+ else arr.forEach((i) => rest.push(i.entry));
873
+ }
874
+ return { folded, rest };
875
+ }
876
+ function foldHomogeneousFiles(fileEntries) {
877
+ const stemOf = (name) => {
878
+ const ext = getExt(name);
879
+ return ext === "(no ext)" ? name : name.slice(0, name.length - ext.length);
880
+ };
881
+ const isPureId = (stem) => stem.length > 0 && [...stem].every((c) => isHex(c) || c === "-" || c === "_");
882
+ const groups = /* @__PURE__ */ new Map();
883
+ const rest = [];
884
+ for (const [name, c] of fileEntries) {
885
+ const stem = stemOf(name);
886
+ if (!isPureId(stem)) {
887
+ rest.push([name, c]);
888
+ continue;
889
+ }
890
+ const key = `${classSeq(stem)}|${getExt(name)}`;
891
+ groups.set(key, [..._nullishCoalesce(groups.get(key), () => ( [])), [name, c]]);
892
+ }
893
+ const folded = [];
894
+ for (const entries of groups.values()) {
895
+ if (entries.length >= HOMOGENEOUS_FOLD_MIN) {
896
+ const ext = getExt(entries[0][0]);
897
+ folded.push(`[id]${ext === "(no ext)" ? "" : ext} \xD7${entries.length}`);
898
+ } else {
899
+ rest.push(...entries);
900
+ }
901
+ }
902
+ return { folded, rest };
903
+ }
904
+ function walk(node, prefix, dirName, dirPath = "") {
905
+ let rawEntries = Array.from(node.children.entries());
906
+ const unkeptExtLines = [];
907
+ if (_optionalChain([kept, 'optionalAccess', _19 => _19.size])) {
908
+ const unkept = rawEntries.filter(([name, c]) => c.file && !kept.has(dirPath ? `${dirPath}/${name}` : name));
909
+ if (unkept.length) {
910
+ rawEntries = rawEntries.filter(([name, c]) => !(c.file && !kept.has(dirPath ? `${dirPath}/${name}` : name)));
911
+ const extCounts = /* @__PURE__ */ new Map();
912
+ for (const [name] of unkept) extCounts.set(getExt(name), (_nullishCoalesce(extCounts.get(getExt(name)), () => ( 0))) + 1);
913
+ for (const [ext, n] of [...extCounts.entries()].sort((a, b) => b[1] - a[1]))
914
+ unkeptExtLines.push(`${ext} \xD7${n}`);
915
+ }
916
+ }
917
+ const codeItems = rawEntries.filter(([name, c]) => c.file ? CODE_EXTS.has(getExt(name)) : !!c.hasCode);
918
+ const nonCodeItems = rawEntries.filter(([name, c]) => c.file ? !CODE_EXTS.has(getExt(name)) : !c.hasCode);
919
+ const nonCodeItemCount = nonCodeItems.length;
920
+ const items = [];
921
+ if (skeletonOnly) {
922
+ const dirs = rawEntries.filter(([, c]) => !c.file);
923
+ const fileCount = rawEntries.length - dirs.length;
924
+ const branchDirs = dirs.filter(([, c]) => [...c.children.values()].some((ch) => !ch.file));
925
+ const leafDirs = dirs.filter(([, c]) => ![...c.children.values()].some((ch) => !ch.file));
926
+ const { folded, rest } = foldSiblingDirs(leafDirs);
927
+ for (const [name, c] of rest)
928
+ items.push({ display: `${name}/ ${c.children.size} file${c.children.size > 1 ? "s" : ""}` });
929
+ for (const d of folded) items.push({ display: d });
930
+ for (const [name, c] of branchDirs) items.push({ display: name, child: c });
931
+ if (fileCount > 0)
932
+ items.push({ display: `${fileCount} file${fileCount > 1 ? "s" : ""}` });
933
+ return emitItems(items, prefix);
934
+ }
935
+ const codeFiles = codeItems.filter(([, c]) => c.file);
936
+ const codeDirs = codeItems.filter(([, c]) => !c.file);
937
+ if (dirName && FOLD_DIRS.has(dirName) && codeFiles.length > 1 && codeDirs.length === 0) {
938
+ const ext = getExt(codeFiles[0][0]);
939
+ const allSameExt = codeFiles.every(([name]) => getExt(name) === ext);
940
+ if (allSameExt) {
941
+ items.push({ display: `${ext} \xD7${codeFiles.length}` });
942
+ } else {
943
+ const extCounts = /* @__PURE__ */ new Map();
944
+ for (const [name] of codeFiles) {
945
+ const e = getExt(name);
946
+ extCounts.set(e, (_nullishCoalesce(extCounts.get(e), () => ( 0))) + 1);
947
+ }
948
+ for (const [ext2, count] of [...extCounts.entries()].sort((a, b) => b[1] - a[1]))
949
+ items.push({ display: `${ext2} \xD7${count}` });
950
+ }
951
+ } else {
952
+ const { folded: foldedDirs, rest: restDirs } = foldSiblingDirs(codeDirs);
953
+ const { folded: foldedFiles, rest: restFiles } = foldHomogeneousFiles(codeFiles);
954
+ for (const [name] of restFiles)
955
+ items.push({ display: name, child: void 0 });
956
+ for (const [name, c] of restDirs)
957
+ items.push({ display: name, child: c });
958
+ for (const d of foldedFiles) items.push({ display: d });
959
+ for (const d of foldedDirs) items.push({ display: d });
960
+ }
961
+ if (nonCodeItemCount > foldThreshold) {
962
+ const extCounts = /* @__PURE__ */ new Map();
963
+ for (const [name, c] of nonCodeItems) {
964
+ if (c.file) {
965
+ mergeExt(extCounts, getExt(name), { count: 1, name });
966
+ } else {
967
+ for (const [ext, entry] of _nullishCoalesce(c.subtreeExts, () => ( []))) mergeExt(extCounts, ext, entry);
968
+ }
969
+ }
970
+ for (const [ext, entry] of [...extCounts.entries()].sort((a, b) => b[1].count - a[1].count))
971
+ items.push({ display: entry.count === 1 && entry.name ? entry.name : `${ext} \xD7${entry.count}` });
972
+ } else {
973
+ const ncDirs = nonCodeItems.filter(([, c]) => !c.file);
974
+ const ncFiles = nonCodeItems.filter(([, c]) => c.file);
975
+ const { folded: foldedDirs, rest: restDirs } = foldSiblingDirs(ncDirs);
976
+ const { folded: foldedFiles, rest: restFiles } = foldHomogeneousFiles(ncFiles);
977
+ for (const [name] of restFiles)
978
+ items.push({ display: name, child: void 0 });
979
+ for (const [name, c] of restDirs)
980
+ items.push({ display: name, child: c });
981
+ for (const d of foldedFiles) items.push({ display: d });
982
+ for (const d of foldedDirs) items.push({ display: d });
983
+ }
984
+ for (const line of unkeptExtLines)
985
+ items.push({ display: line });
986
+ return emitItems(items, prefix, dirPath);
987
+ }
988
+ function emitItems(items, prefix, dirPath = "") {
989
+ for (const { display, child } of items) {
990
+ if (child) {
991
+ const childPath = dirPath ? `${dirPath}/${display}` : display;
992
+ if (_optionalChain([collapsedDirs, 'optionalAccess', _20 => _20.has, 'call', _21 => _21(childPath)])) {
993
+ const files = _nullishCoalesce(child.subtreeCount, () => ( 0));
994
+ const dirs = _nullishCoalesce(child.subtreeDirCount, () => ( 0));
995
+ lines.push(`${prefix}${display}/ (${files} file${files === 1 ? "" : "s"}, ${dirs} dir${dirs === 1 ? "" : "s"})`);
996
+ continue;
997
+ }
998
+ let label = display;
999
+ let cur = child;
1000
+ let fileLeaf = false;
1001
+ while (cur.children.size === 1) {
1002
+ const [onlyName, onlyChild] = [...cur.children][0];
1003
+ label += `/${onlyName}`;
1004
+ if (onlyChild.file) {
1005
+ lines.push(`${prefix}${label}${star(dirPath ? `${dirPath}/${label}` : label)}`);
1006
+ fileLeaf = true;
1007
+ break;
1008
+ }
1009
+ cur = onlyChild;
1010
+ }
1011
+ if (fileLeaf)
1012
+ continue;
1013
+ lines.push(`${prefix}${label}/`);
1014
+ walk(cur, `${prefix} `, label.slice(label.lastIndexOf("/") + 1), dirPath ? `${dirPath}/${label}` : label);
1015
+ } else {
1016
+ lines.push(`${prefix}${display}${star(dirPath ? `${dirPath}/${display}` : display)}`);
1017
+ }
1018
+ }
1019
+ }
1020
+ walk(root, "");
1021
+ return lines.join("\n");
1022
+ }
1023
+ function formatStarredTree(paths, starred) {
1024
+ const root = { children: /* @__PURE__ */ new Map() };
1025
+ for (const path of paths) {
1026
+ const parts = path.split("/");
1027
+ let node = root;
1028
+ for (let i = 0; i < parts.length; i++) {
1029
+ const isLeaf = i === parts.length - 1;
1030
+ if (!node.children.has(parts[i]))
1031
+ node.children.set(parts[i], { children: /* @__PURE__ */ new Map() });
1032
+ node = node.children.get(parts[i]);
1033
+ if (isLeaf) {
1034
+ node.file = true;
1035
+ node.fullPath = path;
1036
+ }
1037
+ }
1038
+ }
1039
+ const hasStar = (n) => {
1040
+ if (n.file) return !!(n.fullPath && starred.has(n.fullPath));
1041
+ for (const c of n.children.values()) if (hasStar(c)) return true;
1042
+ return false;
1043
+ };
1044
+ const countNonStar = (n) => {
1045
+ if (n.file) return n.fullPath && starred.has(n.fullPath) ? 0 : 1;
1046
+ let s = 0;
1047
+ for (const c of n.children.values()) s += countNonStar(c);
1048
+ return s;
1049
+ };
1050
+ const lines = [];
1051
+ const walk = (node, prefix) => {
1052
+ const entries = [...node.children.entries()];
1053
+ const starDirs = entries.filter(([, c]) => !c.file && hasStar(c));
1054
+ const starFiles = entries.filter(([, c]) => c.file && hasStar(c));
1055
+ let hidden = 0;
1056
+ for (const [, c] of entries)
1057
+ if (!hasStar(c)) hidden += countNonStar(c);
1058
+ for (const [name, c] of starFiles)
1059
+ lines.push(`${prefix}${name} \u2605`);
1060
+ for (const [name, c] of starDirs) {
1061
+ lines.push(`${prefix}${name}/`);
1062
+ walk(c, `${prefix} `);
1063
+ }
1064
+ if (hidden > 0)
1065
+ lines.push(`${prefix}\u2026 ${hidden} more`);
1066
+ };
1067
+ walk(root, "");
1068
+ return lines.join("\n");
1069
+ }
1070
+ function formatXml(blocks, levels) {
1071
+ return blocks.filter((b) => {
1072
+ if (levels && !levels.has(b.path))
1073
+ return false;
1074
+ const level = _nullishCoalesce(_optionalChain([levels, 'optionalAccess', _22 => _22.get, 'call', _23 => _23(b.path)]), () => ( b.level));
1075
+ return level !== "tree" && b.content.trim();
1076
+ }).map((b) => `<file path="${b.path}">
1077
+ ${b.content}
1078
+ </file>`).join("\n\n");
1079
+ }
1080
+
1081
+ // src/read/security.ts
1082
+ var isDigit2 = (c) => c >= "0" && c <= "9";
1083
+ var isUpper = (c) => c >= "A" && c <= "Z";
1084
+ var isLower = (c) => c >= "a" && c <= "z";
1085
+ var isAlpha2 = (c) => isUpper(c) || isLower(c);
1086
+ var isAlphaNum = (c) => isAlpha2(c) || isDigit2(c);
1087
+ var isWord = (c) => isAlphaNum(c) || c === "_";
1088
+ var isSpace = (c) => c === " " || c === " " || c === "\f" || c === "\v";
1089
+ var isBearerChar = (c) => isWord(c) || c === "-" || c === "." || c === "~" || c === "+" || c === "/";
1090
+ function runLen(line, i, pred) {
1091
+ let n = 0;
1092
+ while (i + n < line.length && pred(line[i + n]))
1093
+ n++;
1094
+ return n;
1095
+ }
1096
+ function hasAwsKey(line) {
1097
+ for (let i = 0; i + 4 <= line.length; i++) {
1098
+ if (line.startsWith("AKIA", i)) {
1099
+ const run = runLen(line, i + 4, (c) => isDigit2(c) || isUpper(c));
1100
+ if (run >= 16)
1101
+ return true;
1102
+ }
1103
+ }
1104
+ return false;
1105
+ }
1106
+ var SECRET_KEYWORDS = ["secret", "password", "passwd", "token", "api_key", "apikey", "api-key", "auth"];
1107
+ function hasGenericSecret(line) {
1108
+ const lower = line.toLowerCase();
1109
+ for (const kw of SECRET_KEYWORDS) {
1110
+ let from = 0;
1111
+ for (; ; ) {
1112
+ const idx = lower.indexOf(kw, from);
1113
+ if (idx === -1)
1114
+ break;
1115
+ from = idx + 1;
1116
+ let j = idx + kw.length;
1117
+ while (j < line.length && isSpace(line[j])) j++;
1118
+ if (line[j] !== "=" && line[j] !== ":")
1119
+ continue;
1120
+ j++;
1121
+ while (j < line.length && isSpace(line[j])) j++;
1122
+ const quote = line[j];
1123
+ if (quote !== "'" && quote !== '"')
1124
+ continue;
1125
+ j++;
1126
+ const valStart = j;
1127
+ while (j < line.length && line[j] !== quote && line[j] !== " " && line[j] !== " " && line[j] !== "\f" && line[j] !== "\v" && line[j] !== "'" && line[j] !== '"')
1128
+ j++;
1129
+ if (j - valStart >= 8 && line[j] === quote)
1130
+ return true;
1131
+ }
1132
+ }
1133
+ return false;
1134
+ }
1135
+ function hasPrivateKey(line) {
1136
+ const i = line.indexOf("-----BEGIN ");
1137
+ if (i === -1)
1138
+ return false;
1139
+ let rest = line.slice(i + "-----BEGIN ".length);
1140
+ for (const prefix of ["RSA ", "EC ", "DSA "]) {
1141
+ if (rest.startsWith(prefix)) {
1142
+ rest = rest.slice(prefix.length);
1143
+ break;
1144
+ }
1145
+ }
1146
+ return rest.startsWith("PRIVATE KEY-----");
1147
+ }
1148
+ function hasBearerToken(line) {
1149
+ const lower = line.toLowerCase();
1150
+ let from = 0;
1151
+ for (; ; ) {
1152
+ const idx = lower.indexOf("bearer", from);
1153
+ if (idx === -1)
1154
+ return false;
1155
+ from = idx + 1;
1156
+ let j = idx + "bearer".length;
1157
+ const spaces = runLen(line, j, isSpace);
1158
+ if (spaces === 0)
1159
+ continue;
1160
+ j += spaces;
1161
+ if (runLen(line, j, isBearerChar) >= 20)
1162
+ return true;
1163
+ }
1164
+ }
1165
+ function hasGitHubToken(line) {
1166
+ for (let i = 0; i + 4 <= line.length; i++) {
1167
+ if (line[i] === "g" && line[i + 1] === "h" && (line[i + 2] === "p" || line[i + 2] === "s") && line[i + 3] === "_") {
1168
+ if (runLen(line, i + 4, isWord) >= 36)
1169
+ return true;
1170
+ }
1171
+ }
1172
+ return false;
1173
+ }
1174
+ var SLACK_KINDS = "bpors";
1175
+ function hasSlackToken(line) {
1176
+ for (let i = 0; i + 5 <= line.length; i++) {
1177
+ if (line.startsWith("xox", i) && SLACK_KINDS.includes(line[i + 3]) && line[i + 4] === "-") {
1178
+ if (runLen(line, i + 5, (c) => isAlphaNum(c) || c === "-") >= 10)
1179
+ return true;
1180
+ }
1181
+ }
1182
+ return false;
1183
+ }
1184
+ var API_PREFIXES = ["sk", "pk", "key"];
1185
+ function hasGenericApiKey(line) {
1186
+ for (const prefix of API_PREFIXES) {
1187
+ let from = 0;
1188
+ for (; ; ) {
1189
+ const idx = line.indexOf(`${prefix}-`, from);
1190
+ if (idx === -1)
1191
+ break;
1192
+ from = idx + 1;
1193
+ if (runLen(line, idx + prefix.length + 1, isAlphaNum) >= 20)
1194
+ return true;
1195
+ }
1196
+ }
1197
+ return false;
1198
+ }
1199
+ var SECRET_PATTERNS = [
1200
+ { name: "AWS Key", match: hasAwsKey },
1201
+ { name: "Generic Secret", match: hasGenericSecret },
1202
+ { name: "Private Key", match: hasPrivateKey },
1203
+ { name: "Bearer Token", match: hasBearerToken },
1204
+ { name: "GitHub Token", match: hasGitHubToken },
1205
+ { name: "Slack Token", match: hasSlackToken },
1206
+ { name: "Generic API Key", match: hasGenericApiKey }
1207
+ ];
1208
+ function scanSecrets(blocks) {
1209
+ const matches = [];
1210
+ for (const block of blocks) {
1211
+ if (!block.content)
1212
+ continue;
1213
+ const lines = block.content.split("\n");
1214
+ for (let i = 0; i < lines.length; i++) {
1215
+ for (const { name, match } of SECRET_PATTERNS) {
1216
+ if (match(lines[i])) {
1217
+ matches.push({ path: block.path, line: i + 1, pattern: name });
1218
+ }
1219
+ }
1220
+ }
1221
+ }
1222
+ return matches;
1223
+ }
1224
+
1225
+ // src/read/signals.ts
1226
+ var _child_process = require('child_process');
1227
+
1228
+
1229
+
1230
+ var estimateTokens = (s) => Math.ceil(s.length / 4);
1231
+ function parseRecency(gitLogOutput, files, cwdFromRoot) {
1232
+ const scores = new Map(files.map((f) => [f, 0]));
1233
+ const commits = [];
1234
+ let block = [];
1235
+ for (const raw of gitLogOutput.split("\n")) {
1236
+ const l = raw.trim();
1237
+ if (l) {
1238
+ block.push(l);
1239
+ } else if (block.length) {
1240
+ commits.push(block);
1241
+ block = [];
1242
+ }
1243
+ }
1244
+ if (block.length)
1245
+ commits.push(block);
1246
+ const firstSeen = /* @__PURE__ */ new Map();
1247
+ for (const [i, commitFiles] of commits.entries()) {
1248
+ for (const f of commitFiles) {
1249
+ if (!firstSeen.has(f))
1250
+ firstSeen.set(f, i);
1251
+ }
1252
+ }
1253
+ for (const [gitPath, commitIdx] of firstSeen) {
1254
+ const cwdPath = cwdFromRoot ? _path.relative.call(void 0, cwdFromRoot, gitPath) : gitPath;
1255
+ if (scores.has(cwdPath))
1256
+ scores.set(cwdPath, commitIdx < 5 ? 2 : commitIdx < 20 ? 1 : 0);
1257
+ }
1258
+ return scores;
1259
+ }
1260
+ function computeRecency(files, cwd = _process2.default.cwd()) {
1261
+ try {
1262
+ const gitRoot = _child_process.execSync.call(void 0, "git rev-parse --show-toplevel", { cwd, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
1263
+ const out = _child_process.execSync.call(void 0, "git log --name-only --pretty=format: -n 50", { cwd, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] });
1264
+ return parseRecency(out, files, _path.relative.call(void 0, gitRoot, _path.resolve.call(void 0, cwd)));
1265
+ } catch (e6) {
1266
+ return new Map(files.map((f) => [f, 0]));
1267
+ }
1268
+ }
1269
+ var EXTENSIONS = [".ts", ".tsx", ".js", ".jsx"];
1270
+ function loadPathAliases(cwd) {
1271
+ for (const name of ["tsconfig.app.json", "tsconfig.json"]) {
1272
+ const p = _path.join.call(void 0, cwd, name);
1273
+ if (!_fs.existsSync.call(void 0, p))
1274
+ continue;
1275
+ try {
1276
+ const stripped = stripJsonComments(_fs.readFileSync.call(void 0, p, "utf-8"));
1277
+ const paths = _nullishCoalesce(_optionalChain([JSON, 'access', _24 => _24.parse, 'call', _25 => _25(stripped), 'optionalAccess', _26 => _26.compilerOptions, 'optionalAccess', _27 => _27.paths]), () => ( {}));
1278
+ const noStar = (s) => s.endsWith("*") ? s.slice(0, -1) : s;
1279
+ return Object.entries(paths).map(([key, vals]) => {
1280
+ const target = noStar(vals[0]);
1281
+ return {
1282
+ prefix: noStar(key),
1283
+ // "@/*" → "@/"
1284
+ target: target.startsWith("./") ? target.slice(2) : target
1285
+ // "./src/" → "src/"
1286
+ };
1287
+ });
1288
+ } catch (e7) {
1289
+ continue;
1290
+ }
1291
+ }
1292
+ return [];
1293
+ }
1294
+ function resolveImport(fromFile, specifier, aliases, diskCache, fileExists) {
1295
+ let base;
1296
+ const alias = aliases.find((a) => specifier.startsWith(a.prefix));
1297
+ if (alias) {
1298
+ base = alias.target + specifier.slice(alias.prefix.length);
1299
+ } else if (specifier.startsWith(".")) {
1300
+ const dir = _path.dirname.call(void 0, fromFile);
1301
+ base = _path.join.call(void 0, dir, specifier);
1302
+ } else {
1303
+ return null;
1304
+ }
1305
+ const cached = diskCache.get(base);
1306
+ if (cached !== void 0)
1307
+ return cached;
1308
+ for (const ext of EXTENSIONS) {
1309
+ if (fileExists(base + ext)) {
1310
+ diskCache.set(base, base + ext);
1311
+ return base + ext;
1312
+ }
1313
+ const idx = _path.join.call(void 0, base, `index${ext}`);
1314
+ if (fileExists(idx)) {
1315
+ diskCache.set(base, idx);
1316
+ return idx;
1317
+ }
1318
+ }
1319
+ diskCache.set(base, null);
1320
+ return null;
1321
+ }
1322
+ function buildImportGraphPure(blocks, aliases, fileExists) {
1323
+ const diskCache = /* @__PURE__ */ new Map();
1324
+ const graph = /* @__PURE__ */ new Map();
1325
+ for (const block of blocks) {
1326
+ if (!_optionalChain([block, 'access', _28 => _28.imports, 'optionalAccess', _29 => _29.length]))
1327
+ continue;
1328
+ for (const specifier of block.imports) {
1329
+ const resolved = resolveImport(block.path, specifier, aliases, diskCache, fileExists);
1330
+ if (!resolved)
1331
+ continue;
1332
+ if (!graph.has(resolved))
1333
+ graph.set(resolved, /* @__PURE__ */ new Set());
1334
+ graph.get(resolved).add(block.path);
1335
+ }
1336
+ }
1337
+ return graph;
1338
+ }
1339
+ function buildImportGraph(blocks, cwd = _process2.default.cwd()) {
1340
+ return buildImportGraphPure(blocks, loadPathAliases(cwd), _fs.existsSync);
1341
+ }
1342
+ function computeCentrality(files, graph) {
1343
+ return new Map(files.map((f) => {
1344
+ const count = _nullishCoalesce(_optionalChain([graph, 'access', _30 => _30.get, 'call', _31 => _31(f), 'optionalAccess', _32 => _32.size]), () => ( 0));
1345
+ return [f, count >= 20 ? 2 : count >= 5 ? 1 : 0];
1346
+ }));
1347
+ }
1348
+ function expandByBudget(paths, scores, contentTokens, budget, treeEntryTokens = 8) {
1349
+ const root = { path: "", isFile: false, score: -1, cost: 0, children: [] };
1350
+ const byPath = /* @__PURE__ */ new Map([["", root]]);
1351
+ for (const path of paths) {
1352
+ const parts = path.split("/");
1353
+ let prefix = "";
1354
+ let parent = root;
1355
+ for (let i = 0; i < parts.length; i++) {
1356
+ prefix = prefix ? `${prefix}/${parts[i]}` : parts[i];
1357
+ let node = byPath.get(prefix);
1358
+ if (!node) {
1359
+ const isFile = i === parts.length - 1;
1360
+ node = {
1361
+ path: prefix,
1362
+ isFile,
1363
+ score: isFile ? _nullishCoalesce(scores.get(path), () => ( 0)) : -1,
1364
+ cost: isFile ? (_nullishCoalesce(contentTokens.get(path), () => ( 0))) + treeEntryTokens : treeEntryTokens,
1365
+ children: []
1366
+ };
1367
+ byPath.set(prefix, node);
1368
+ parent.children.push(node);
1369
+ }
1370
+ parent = node;
1371
+ }
1372
+ }
1373
+ const aggregate = (node) => {
1374
+ if (node.isFile)
1375
+ return node.score;
1376
+ node.score = node.children.reduce((m, c) => Math.max(m, aggregate(c)), node.score);
1377
+ return node.score;
1378
+ };
1379
+ aggregate(root);
1380
+ const kept = /* @__PURE__ */ new Set();
1381
+ const collapsedDirs = /* @__PURE__ */ new Set();
1382
+ const frontier = [...root.children];
1383
+ let spent = 0;
1384
+ while (frontier.length) {
1385
+ let bestIdx = 0;
1386
+ for (let i = 1; i < frontier.length; i++) {
1387
+ if (frontier[i].score > frontier[bestIdx].score)
1388
+ bestIdx = i;
1389
+ }
1390
+ const node = frontier.splice(bestIdx, 1)[0];
1391
+ if (spent + node.cost > budget) {
1392
+ if (!node.isFile)
1393
+ collapsedDirs.add(node.path);
1394
+ continue;
1395
+ }
1396
+ spent += node.cost;
1397
+ kept.add(node.path);
1398
+ if (!node.isFile)
1399
+ frontier.push(...node.children);
1400
+ }
1401
+ return { kept, collapsedDirs };
1402
+ }
1403
+ var TREE_ENTRY_TOKENS = 8;
1404
+ function allocate(blocks, recency, centrality, budget, pinned, isTreeDisplay) {
1405
+ const levels = new Map(blocks.map((b) => [b.path, b.level]));
1406
+ const contentTokens = new Map(blocks.map((b) => [
1407
+ b.path,
1408
+ _optionalChain([isTreeDisplay, 'optionalCall', _33 => _33(b.path)]) ? 0 : estimateTokens(b.content) + estimateTokens(`<file path="${b.path}">
1409
+
1410
+ </file>
1411
+
1412
+ `)
1413
+ ]));
1414
+ const scores = new Map(
1415
+ blocks.map((b) => [b.path, (_nullishCoalesce(recency.get(b.path), () => ( 0))) + (_nullishCoalesce(centrality.get(b.path), () => ( 0)))])
1416
+ );
1417
+ let total = blocks.reduce((sum, b) => sum + (_nullishCoalesce(contentTokens.get(b.path), () => ( 0))) + TREE_ENTRY_TOKENS, 0);
1418
+ const totalBefore = total;
1419
+ let downgraded = 0;
1420
+ const done = () => ({ levels, totalBefore, totalAfter: total, downgraded, deficit: Math.max(0, total - budget), scores, contentTokens, treeEntryTokens: TREE_ENTRY_TOKENS });
1421
+ if (total <= budget)
1422
+ return done();
1423
+ const sorted = [...blocks].sort((a, b) => (_nullishCoalesce(scores.get(a.path), () => ( 0))) - (_nullishCoalesce(scores.get(b.path), () => ( 0))));
1424
+ for (const block of sorted) {
1425
+ if (total <= budget)
1426
+ break;
1427
+ if (_optionalChain([pinned, 'optionalAccess', _34 => _34.has, 'call', _35 => _35(block.path)]))
1428
+ continue;
1429
+ if (levels.get(block.path) === "compact") {
1430
+ total -= _nullishCoalesce(contentTokens.get(block.path), () => ( 0));
1431
+ levels.set(block.path, "tree");
1432
+ downgraded++;
1433
+ }
1434
+ }
1435
+ return done();
1436
+ }
1437
+
1438
+
1439
+
1440
+
1441
+
1442
+
1443
+
1444
+
1445
+
1446
+
1447
+
1448
+
1449
+
1450
+
1451
+
1452
+
1453
+
1454
+
1455
+
1456
+ exports.ensureMarkers = ensureMarkers; exports.renderSections = renderSections; exports.injectFile = injectFile; exports.injectAll = injectAll; exports.buildState = buildState; exports.formatState = formatState; exports.buildClassifier = buildClassifier; exports.buildBlocks = buildBlocks; exports.formatTree = formatTree; exports.formatStarredTree = formatStarredTree; exports.formatXml = formatXml; exports.scanSecrets = scanSecrets; exports.computeRecency = computeRecency; exports.buildImportGraph = buildImportGraph; exports.computeCentrality = computeCentrality; exports.expandByBudget = expandByBudget; exports.allocate = allocate;