@hassangameryt/freeflow 0.5.0 → 0.7.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 (301) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +2 -2
  3. package/.codex-plugin/plugin.json +4 -5
  4. package/README.md +141 -163
  5. package/capabilities/cognitive-routing/SKILL.md +387 -0
  6. package/capabilities/context-virtualization/SKILL.md +103 -0
  7. package/capabilities/conversation-history/SKILL.md +53 -0
  8. package/command-surface.json +6 -37
  9. package/hooks/freeflow-runtime-context.mjs +50 -541
  10. package/hooks/hooks.json +1 -26
  11. package/hooks/tests/check-runtime-context-hook.sh +114 -308
  12. package/package.json +27 -17
  13. package/pi-extension/dist/cognitive-routing/commands.js +96 -0
  14. package/pi-extension/dist/cognitive-routing/config.js +232 -0
  15. package/pi-extension/dist/cognitive-routing/controller.js +1292 -0
  16. package/pi-extension/dist/cognitive-routing/history.js +451 -0
  17. package/pi-extension/dist/cognitive-routing/host.js +188 -0
  18. package/pi-extension/dist/cognitive-routing/pi-routing-session.js +414 -0
  19. package/pi-extension/dist/cognitive-routing/pi-session-control.js +320 -0
  20. package/pi-extension/dist/cognitive-routing/runtime.js +43 -0
  21. package/pi-extension/dist/cognitive-routing/tool.js +212 -0
  22. package/pi-extension/dist/cognitive-routing/types.js +6 -0
  23. package/pi-extension/dist/context-virtualization/commands.js +89 -0
  24. package/pi-extension/dist/context-virtualization/projector.js +42 -0
  25. package/pi-extension/dist/context-virtualization/runtime.js +356 -0
  26. package/pi-extension/dist/context-virtualization/state.js +57 -0
  27. package/pi-extension/dist/context-virtualization/types.js +10 -0
  28. package/pi-extension/dist/conversation-history/passages.js +66 -0
  29. package/pi-extension/dist/conversation-history/ranking.js +105 -0
  30. package/pi-extension/dist/conversation-history/runtime.js +226 -0
  31. package/pi-extension/dist/conversation-history/search.js +56 -0
  32. package/pi-extension/dist/conversation-history/types.js +1 -0
  33. package/pi-extension/dist/freeflow-context/resolver.js +120 -0
  34. package/pi-extension/dist/freeflow-context/runtime.js +80 -0
  35. package/pi-extension/dist/freeflow-context/source-projector.js +95 -0
  36. package/pi-extension/dist/freeflow-context/tool.js +308 -0
  37. package/pi-extension/dist/freeflow-context/types.js +12 -0
  38. package/pi-extension/dist/freeflow-context/visibility.js +28 -0
  39. package/pi-extension/dist/index.js +564 -129
  40. package/pi-extension/dist/runtime/runtime-context.js +357 -470
  41. package/pi-extension/dist/runtime/runtime-identity.js +5 -0
  42. package/pi-extension/dist/settings/settings-tui.js +78 -0
  43. package/pi-extension/dist/settings/settings-ui.js +572 -826
  44. package/pi-extension/dist/ui/text-component.js +57 -0
  45. package/pi-extension/src/cognitive-routing/commands.ts +129 -0
  46. package/pi-extension/src/cognitive-routing/config.ts +303 -0
  47. package/pi-extension/src/cognitive-routing/controller.ts +1628 -0
  48. package/pi-extension/src/cognitive-routing/history.ts +650 -0
  49. package/pi-extension/src/cognitive-routing/host.ts +266 -0
  50. package/pi-extension/src/cognitive-routing/pi-routing-session.ts +538 -0
  51. package/pi-extension/src/cognitive-routing/pi-session-control.ts +444 -0
  52. package/pi-extension/src/cognitive-routing/runtime.ts +57 -0
  53. package/pi-extension/src/cognitive-routing/tool.ts +273 -0
  54. package/pi-extension/src/cognitive-routing/types.ts +89 -0
  55. package/pi-extension/src/context-virtualization/commands.ts +111 -0
  56. package/pi-extension/src/context-virtualization/projector.ts +62 -0
  57. package/pi-extension/src/context-virtualization/runtime.ts +406 -0
  58. package/pi-extension/src/context-virtualization/state.ts +79 -0
  59. package/pi-extension/src/context-virtualization/types.ts +92 -0
  60. package/pi-extension/src/conversation-history/passages.ts +81 -0
  61. package/pi-extension/src/conversation-history/ranking.ts +155 -0
  62. package/pi-extension/src/conversation-history/runtime.ts +250 -0
  63. package/pi-extension/src/conversation-history/search.ts +79 -0
  64. package/pi-extension/src/conversation-history/types.ts +31 -0
  65. package/pi-extension/src/freeflow-context/resolver.ts +139 -0
  66. package/pi-extension/src/freeflow-context/runtime.ts +100 -0
  67. package/pi-extension/src/freeflow-context/source-projector.ts +106 -0
  68. package/pi-extension/src/freeflow-context/tool.ts +360 -0
  69. package/pi-extension/src/freeflow-context/types.ts +70 -0
  70. package/pi-extension/src/freeflow-context/visibility.ts +53 -0
  71. package/pi-extension/src/index.ts +597 -135
  72. package/pi-extension/src/runtime/runtime-context.ts +373 -491
  73. package/pi-extension/src/runtime/runtime-identity.ts +8 -0
  74. package/pi-extension/src/settings/settings-tui.ts +93 -0
  75. package/pi-extension/src/settings/settings-ui.ts +679 -910
  76. package/pi-extension/src/ui/text-component.ts +66 -0
  77. package/pi-extension/tests/cognitive-routing/commands.test.js +134 -0
  78. package/pi-extension/tests/cognitive-routing/controller.test.js +1128 -0
  79. package/pi-extension/tests/cognitive-routing/extension-lifecycle.test.js +1142 -0
  80. package/pi-extension/tests/cognitive-routing/history.test.js +274 -0
  81. package/pi-extension/tests/cognitive-routing/host-fixture.js +4 -0
  82. package/pi-extension/tests/cognitive-routing/host-identity.test.js +63 -0
  83. package/pi-extension/tests/cognitive-routing/pi-normal-lifecycle.test.js +434 -0
  84. package/pi-extension/tests/cognitive-routing/pi-session-control.test.js +174 -0
  85. package/pi-extension/tests/cognitive-routing/pi-session-history.test.js +91 -0
  86. package/pi-extension/tests/cognitive-routing/profile-resolution.test.js +279 -0
  87. package/pi-extension/tests/cognitive-routing/tool.test.js +230 -0
  88. package/pi-extension/tests/context-virtualization/extension.test.js +749 -0
  89. package/pi-extension/tests/context-virtualization/projector.test.js +110 -0
  90. package/pi-extension/tests/context-virtualization/runtime.test.js +216 -0
  91. package/pi-extension/tests/conversation-history/runtime.test.js +98 -0
  92. package/pi-extension/tests/conversation-history/search.test.js +97 -0
  93. package/pi-extension/tests/integration/mode-free-core.test.js +218 -0
  94. package/pi-extension/tests/integration/pi-extension.test.js +532 -3701
  95. package/pi-extension/tests/integration/prompt-architecture.test.js +350 -0
  96. package/pi-extension/tests/integration/unaffected-regressions.test.js +411 -0
  97. package/runtime/prompts/cognitive-routing.md +10 -0
  98. package/runtime/prompts/context-virtualization.md +3 -0
  99. package/runtime/prompts/conversation-history.md +3 -0
  100. package/runtime/prompts/core.md +84 -0
  101. package/runtime/prompts/interaction-contract.md +11 -0
  102. package/skills/action-selection/SKILL.md +140 -0
  103. package/skills/action-selection/references/trajectory-stalls.md +71 -0
  104. package/skills/bypass/SKILL.md +109 -38
  105. package/skills/commit-work/SKILL.md +94 -55
  106. package/skills/commit-work/references/git-state-edges.md +94 -0
  107. package/skills/commit-work/references/simple-push.md +92 -0
  108. package/skills/commit-work/references/staging-decisions.md +79 -46
  109. package/skills/decision-gate/SKILL.md +80 -22
  110. package/skills/design-for-depth/SKILL.md +206 -60
  111. package/skills/design-for-depth/references/design-pressure-signals.md +108 -240
  112. package/skills/design-for-depth/references/interface-design-loop.md +77 -97
  113. package/skills/design-for-depth/references/module-and-dependency-design.md +147 -0
  114. package/skills/design-for-depth/references/software-design-philosophy.md +128 -174
  115. package/skills/design-for-depth/references/state-and-failure-boundaries.md +136 -0
  116. package/skills/diagnose-failure/SKILL.md +200 -48
  117. package/skills/diagnose-failure/references/diagnostic-loop-catalog.md +18 -6
  118. package/skills/diagnose-failure/references/{flaky-and-performance.md → flaky-and-performance-diagnosis.md} +13 -5
  119. package/skills/discuss/SKILL.md +119 -65
  120. package/skills/discuss/references/discussion-continuity.md +123 -0
  121. package/skills/evaluate-skill/SKILL.md +166 -52
  122. package/skills/evaluate-skill/references/{definition-schema.md → evaluation-definition-schema.md} +43 -3
  123. package/skills/evaluate-skill/references/evaluation-design.md +56 -30
  124. package/skills/evaluate-skill/references/execution-and-evidence.md +8 -3
  125. package/skills/evaluate-skill/references/review-and-revision.md +62 -21
  126. package/skills/evaluate-skill/scripts/lib/definitions.mjs +114 -3
  127. package/skills/evaluate-skill/scripts/lib/grade-interaction.mjs +156 -1
  128. package/skills/evaluate-skill/scripts/lib/grade.mjs +9 -1
  129. package/skills/evaluate-skill/scripts/lib/pi.mjs +147 -32
  130. package/skills/evaluate-skill/scripts/lib/rpc.mjs +4 -4
  131. package/skills/evaluate-skill/scripts/lib/runner.mjs +36 -14
  132. package/skills/evaluate-skill/scripts/lib/sandbox.mjs +92 -0
  133. package/skills/evaluate-skill/scripts/pi-guard.mjs +1 -1
  134. package/skills/evaluate-skill/scripts/pi-observer.mjs +66 -0
  135. package/skills/evaluate-skill/scripts/skill-eval.mjs +6 -5
  136. package/skills/execute-work/SKILL.md +99 -57
  137. package/skills/execute-work/references/code-practices.md +4 -4
  138. package/skills/execute-work/references/execute-work-edges.md +62 -0
  139. package/skills/finish-branch/SKILL.md +2 -2
  140. package/skills/finish-branch/references/integration-options.md +1 -1
  141. package/skills/handoff/SKILL.md +3 -3
  142. package/skills/launch-work/SKILL.md +1 -1
  143. package/skills/launch-work/references/launch-readiness.md +2 -2
  144. package/skills/migration-work/SKILL.md +2 -2
  145. package/skills/migration-work/references/migration-lifecycle.md +1 -1
  146. package/skills/release-work/SKILL.md +1 -1
  147. package/skills/release-work/references/release-evidence.md +1 -1
  148. package/skills/review-artifact/SKILL.md +129 -66
  149. package/skills/review-artifact/references/adjudicate-artifact-review.md +101 -0
  150. package/skills/review-artifact/references/independent-artifact-reviewer-contract.md +159 -0
  151. package/skills/review-work/SKILL.md +113 -68
  152. package/skills/review-work/references/adjudicate-work-review.md +97 -0
  153. package/skills/review-work/references/independent-work-reviewer-contract.md +139 -0
  154. package/skills/review-work/references/security-risk-lens.md +18 -16
  155. package/skills/setup-freeflow/SKILL.md +16 -17
  156. package/skills/setup-freeflow/references/activation-contract.md +24 -30
  157. package/skills/setup-freeflow/references/host-setup.md +6 -7
  158. package/skills/simplify-code/SKILL.md +97 -39
  159. package/skills/simplify-code/references/simplification-patterns.md +1 -1
  160. package/skills/tdd/SKILL.md +100 -53
  161. package/skills/tdd/references/test-design.md +3 -3
  162. package/skills/track-work/SKILL.md +195 -58
  163. package/skills/track-work/references/working-record-format.md +515 -0
  164. package/skills/track-work/scripts/lib/document.mjs +713 -0
  165. package/skills/track-work/scripts/lib/format.mjs +166 -0
  166. package/skills/track-work/scripts/lib/store.mjs +233 -0
  167. package/skills/track-work/scripts/lib/transitions.mjs +790 -0
  168. package/skills/track-work/scripts/lib/views.mjs +40 -0
  169. package/skills/track-work/scripts/working-record.mjs +316 -0
  170. package/skills/verify-work/SKILL.md +57 -19
  171. package/skills/verify-work/references/browser-runtime-evidence.md +2 -2
  172. package/skills/verify-work/references/integration-evidence.md +1 -7
  173. package/skills/verify-work/references/performance-evidence.md +2 -2
  174. package/skills/workflow/SKILL.md +137 -55
  175. package/skills/workflow/references/domain-skill-composition.md +26 -40
  176. package/skills/write-plan/SKILL.md +1 -1
  177. package/skills/write-skill/SKILL.md +218 -61
  178. package/skills/write-skill/references/activation-boundaries.md +63 -21
  179. package/skills/write-skill/references/agent-first-instructions.md +61 -27
  180. package/skills/write-skill/references/progressive-disclosure.md +97 -33
  181. package/skills/write-skill/references/skill-dependency-graphs.md +190 -0
  182. package/capabilities/output-router/SKILL.md +0 -206
  183. package/capabilities/output-router/references/safety-policy.md +0 -40
  184. package/capabilities/output-router/references/setup.md +0 -110
  185. package/pi-extension/dist/output-router/host-producer-identification.js +0 -232
  186. package/pi-extension/dist/output-router/native-safety-net.js +0 -216
  187. package/pi-extension/dist/output-router/observed-tool-routing.js +0 -122
  188. package/pi-extension/dist/output-router/renderers.js +0 -1023
  189. package/pi-extension/dist/output-router/router-tools.js +0 -554
  190. package/pi-extension/dist/output-router/schemas.js +0 -383
  191. package/pi-extension/dist/output-router/status.js +0 -744
  192. package/pi-extension/dist/output-router/utils.js +0 -502
  193. package/pi-extension/src/output-router/host-producer-identification.ts +0 -256
  194. package/pi-extension/src/output-router/native-safety-net.ts +0 -248
  195. package/pi-extension/src/output-router/observed-tool-routing.ts +0 -134
  196. package/pi-extension/src/output-router/renderers.ts +0 -1108
  197. package/pi-extension/src/output-router/router-tools.ts +0 -579
  198. package/pi-extension/src/output-router/schemas.ts +0 -387
  199. package/pi-extension/src/output-router/status.ts +0 -791
  200. package/pi-extension/src/output-router/utils.ts +0 -554
  201. package/pi-extension/tests/output-router/observed-producers.test.js +0 -132
  202. package/pi-extension/tests/output-router/search.test.js +0 -722
  203. package/router/dist/benchmarks/benchmark-harness.d.ts +0 -35
  204. package/router/dist/benchmarks/benchmark-harness.js +0 -92
  205. package/router/dist/benchmarks/benchmarks.d.ts +0 -109
  206. package/router/dist/benchmarks/benchmarks.js +0 -979
  207. package/router/dist/benchmarks/codex-qa-benchmarks.d.ts +0 -95
  208. package/router/dist/benchmarks/codex-qa-benchmarks.js +0 -500
  209. package/router/dist/benchmarks/command-benchmarks.d.ts +0 -143
  210. package/router/dist/benchmarks/command-benchmarks.js +0 -698
  211. package/router/dist/benchmarks/context-mode-normalized-benchmarks.d.ts +0 -82
  212. package/router/dist/benchmarks/context-mode-normalized-benchmarks.js +0 -773
  213. package/router/dist/benchmarks/context-mode-real-deep-benchmark.d.ts +0 -132
  214. package/router/dist/benchmarks/context-mode-real-deep-benchmark.js +0 -1380
  215. package/router/dist/benchmarks/context-saving-baseline.d.ts +0 -60
  216. package/router/dist/benchmarks/context-saving-baseline.js +0 -470
  217. package/router/dist/benchmarks/index-benchmarks.d.ts +0 -103
  218. package/router/dist/benchmarks/index-benchmarks.js +0 -862
  219. package/router/dist/benchmarks/storage-policy-benchmarks.d.ts +0 -101
  220. package/router/dist/benchmarks/storage-policy-benchmarks.js +0 -618
  221. package/router/dist/benchmarks/vault-index-benchmarks.d.ts +0 -56
  222. package/router/dist/benchmarks/vault-index-benchmarks.js +0 -322
  223. package/router/dist/config/config.d.ts +0 -103
  224. package/router/dist/config/config.js +0 -632
  225. package/router/dist/config/router-contract.d.ts +0 -10
  226. package/router/dist/config/router-contract.js +0 -54
  227. package/router/dist/config/schema.d.ts +0 -27
  228. package/router/dist/config/schema.js +0 -648
  229. package/router/dist/config/types.d.ts +0 -573
  230. package/router/dist/config/types.js +0 -41
  231. package/router/dist/evidence/bounded-evidence.d.ts +0 -40
  232. package/router/dist/evidence/bounded-evidence.js +0 -323
  233. package/router/dist/evidence/evidence-range-selector.d.ts +0 -24
  234. package/router/dist/evidence/evidence-range-selector.js +0 -232
  235. package/router/dist/evidence/evidence-search.d.ts +0 -27
  236. package/router/dist/evidence/evidence-search.js +0 -490
  237. package/router/dist/evidence/evidence.d.ts +0 -38
  238. package/router/dist/evidence/evidence.js +0 -200
  239. package/router/dist/evidence/failure-contracts.d.ts +0 -37
  240. package/router/dist/evidence/failure-contracts.js +0 -166
  241. package/router/dist/evidence/line-ranges.d.ts +0 -24
  242. package/router/dist/evidence/line-ranges.js +0 -22
  243. package/router/dist/experiments/local-index.d.ts +0 -64
  244. package/router/dist/experiments/local-index.js +0 -581
  245. package/router/dist/index.d.ts +0 -30
  246. package/router/dist/index.js +0 -32
  247. package/router/dist/local/local-traversal.d.ts +0 -18
  248. package/router/dist/local/local-traversal.js +0 -334
  249. package/router/dist/processing/engine.d.ts +0 -132
  250. package/router/dist/processing/engine.js +0 -533
  251. package/router/dist/processing/reducers.d.ts +0 -280
  252. package/router/dist/processing/reducers.js +0 -1673
  253. package/router/dist/processing/renderers.d.ts +0 -31
  254. package/router/dist/processing/renderers.js +0 -195
  255. package/router/dist/processing/scripts.d.ts +0 -91
  256. package/router/dist/processing/scripts.js +0 -386
  257. package/router/dist/repo/repo-traversal.d.ts +0 -18
  258. package/router/dist/repo/repo-traversal.js +0 -245
  259. package/router/dist/routing/observed-reducers.d.ts +0 -41
  260. package/router/dist/routing/observed-reducers.js +0 -661
  261. package/router/dist/routing/observed-routing.d.ts +0 -26
  262. package/router/dist/routing/observed-routing.js +0 -378
  263. package/router/dist/routing/parsers.d.ts +0 -16
  264. package/router/dist/routing/parsers.js +0 -521
  265. package/router/dist/routing/run-filters.d.ts +0 -60
  266. package/router/dist/routing/run-filters.js +0 -238
  267. package/router/dist/routing/run-reducers.d.ts +0 -49
  268. package/router/dist/routing/run-reducers.js +0 -122
  269. package/router/dist/sandbox/adapter-roots.d.ts +0 -46
  270. package/router/dist/sandbox/adapter-roots.js +0 -66
  271. package/router/dist/sandbox/eryx-python-adapter.d.ts +0 -13
  272. package/router/dist/sandbox/eryx-python-adapter.js +0 -868
  273. package/router/dist/sandbox/jq-wasm-adapter.d.ts +0 -9
  274. package/router/dist/sandbox/jq-wasm-adapter.js +0 -429
  275. package/router/dist/sandbox/quickjs-wasi-adapter.d.ts +0 -13
  276. package/router/dist/sandbox/quickjs-wasi-adapter.js +0 -384
  277. package/router/dist/sandbox/script-sandbox.d.ts +0 -134
  278. package/router/dist/sandbox/script-sandbox.js +0 -337
  279. package/router/dist/setup/script-transform-adapters.d.ts +0 -32
  280. package/router/dist/setup/script-transform-adapters.js +0 -278
  281. package/router/dist/tools/batch.d.ts +0 -33
  282. package/router/dist/tools/batch.js +0 -586
  283. package/router/dist/tools/run.d.ts +0 -62
  284. package/router/dist/tools/run.js +0 -1304
  285. package/router/dist/tools/search.d.ts +0 -66
  286. package/router/dist/tools/search.js +0 -1364
  287. package/router/dist/transform/engine.d.ts +0 -168
  288. package/router/dist/transform/engine.js +0 -2072
  289. package/router/dist/vault/vault-index.d.ts +0 -125
  290. package/router/dist/vault/vault-index.js +0 -416
  291. package/router/dist/vault/vault.d.ts +0 -138
  292. package/router/dist/vault/vault.js +0 -630
  293. package/runtime/interaction-contract.md +0 -16
  294. package/skills/discuss/references/checkpoints.md +0 -66
  295. package/skills/execute-work/references/execution-loop.md +0 -77
  296. package/skills/mode-contract/SKILL.md +0 -104
  297. package/skills/review-artifact/references/reviewer-prompt.md +0 -148
  298. package/skills/review-work/references/reviewer-prompt.md +0 -134
  299. package/skills/track-work/references/working-record-schema.md +0 -378
  300. package/skills/workflow/references/workflow-loop.md +0 -92
  301. /package/skills/handoff/references/{templates.md → handoff-templates.md} +0 -0
@@ -1,323 +0,0 @@
1
- const TRUNCATION_SUFFIX = " … [truncated; expand or retrieve exact lines for recovery]";
2
- const TRUNCATION_PREFIX = "[truncated head; expand or retrieve exact lines for recovery] … ";
3
- export function buildBoundedEdgeChunks(options) {
4
- return overCapEdgeRanges(options.lines, options.range, options.caps).map((range) => {
5
- const excerpt =
6
- range.edge === "tail"
7
- ? truncateTailToUtf8Bytes(linesForRange(options.lines, range), options.caps.exactChunkMaxBytes)
8
- : truncateToUtf8Bytes(linesForRange(options.lines, range), options.caps.exactChunkMaxBytes);
9
- return {
10
- range: { start: range.start, end: range.end },
11
- linesLabel: `${range.start}-${range.end}`,
12
- edge: range.edge,
13
- excerpt,
14
- };
15
- });
16
- }
17
- export function buildBoundedExcerpt(options) {
18
- const capped = capLineRangeForWindow(options.range, options.window, options.caps);
19
- const selected = options.lines.slice(capped.range.start - 1, capped.range.end);
20
- const maxBytes = maxExcerptBytesForWindow(options.window, options.caps);
21
- if (maxBytes !== null && options.exactNormalizedPhrase !== undefined) {
22
- const exactExcerpt = excerptAroundNormalizedPhrase(selected.join("\n"), options.exactNormalizedPhrase, maxBytes);
23
- if (exactExcerpt !== null) {
24
- return {
25
- range: capped.range,
26
- linesLabel: `${capped.range.start}-${capped.range.end}`,
27
- excerpt: exactExcerpt,
28
- truncatedByLineCap: capped.truncated,
29
- truncatedByByteCap: byteLength(selected.join("\n")) > maxBytes,
30
- };
31
- }
32
- }
33
- const previewedLines =
34
- maxBytes !== null
35
- ? selected.map((line) =>
36
- truncateLinePreview(line, options.caps.linePreviewMaxBytes, options.exactNormalizedPhrase),
37
- )
38
- : selected;
39
- const uncappedExcerpt = previewedLines.join("\n");
40
- const excerpt = maxBytes === null ? uncappedExcerpt : truncateToUtf8Bytes(uncappedExcerpt, maxBytes);
41
- return {
42
- range: capped.range,
43
- linesLabel: `${capped.range.start}-${capped.range.end}`,
44
- excerpt,
45
- truncatedByLineCap: capped.truncated,
46
- truncatedByByteCap: maxBytes !== null && byteLength(uncappedExcerpt) > maxBytes,
47
- };
48
- }
49
- function overCapEdgeRanges(lines, range, caps) {
50
- const lineCount = range.end - range.start + 1;
51
- const chunkLineCount = Math.min(10, Math.max(1, Math.floor(lineCount / 2)));
52
- const headRange = shrinkRangeToMaxBytes(
53
- lines,
54
- { start: range.start, end: Math.min(range.end, range.start + chunkLineCount - 1) },
55
- "head",
56
- caps,
57
- );
58
- const tailRange = shrinkRangeToMaxBytes(
59
- lines,
60
- { start: Math.max(range.start, range.end - chunkLineCount + 1), end: range.end },
61
- "tail",
62
- caps,
63
- );
64
- const head = { ...headRange, edge: "head" };
65
- const tail = { ...tailRange, edge: "tail" };
66
- if (tail.start <= head.end) {
67
- return byteLength(linesForRange(lines, head)) > caps.exactChunkMaxBytes ? [head, tail] : [head];
68
- }
69
- return [head, tail];
70
- }
71
- function shrinkRangeToMaxBytes(lines, range, edge, caps) {
72
- let current = range;
73
- while (current.end > current.start && byteLength(linesForRange(lines, current)) > caps.exactChunkMaxBytes) {
74
- current =
75
- edge === "head" ? { start: current.start, end: current.end - 1 } : { start: current.start + 1, end: current.end };
76
- }
77
- return current;
78
- }
79
- function linesForRange(lines, range) {
80
- return lines.slice(range.start - 1, range.end).join("\n");
81
- }
82
- function capLineRangeForWindow(range, window, caps) {
83
- const maxLines = maxLinesForWindow(window, caps);
84
- const lineCount = range.end - range.start + 1;
85
- if (maxLines === null || lineCount <= maxLines) {
86
- return { range, truncated: false };
87
- }
88
- return {
89
- range: { start: range.start, end: range.start + maxLines - 1 },
90
- truncated: true,
91
- };
92
- }
93
- function maxLinesForWindow(window, caps) {
94
- if (window === "lines_30") {
95
- return caps.expandLines30MaxLines;
96
- }
97
- if (window === "lines_80") {
98
- return caps.expandLines80MaxLines;
99
- }
100
- return null;
101
- }
102
- function maxExcerptBytesForWindow(window, caps) {
103
- if (window === "small" || window === "section") {
104
- return caps.queryExcerptMaxBytes;
105
- }
106
- if (window === "lines_30") {
107
- return caps.expandLines30MaxBytes;
108
- }
109
- if (window === "lines_80") {
110
- return caps.expandLines80MaxBytes;
111
- }
112
- return null;
113
- }
114
- function excerptAroundNormalizedPhrase(text, exactNormalizedPhrase, maxBytes) {
115
- const span = normalizedPhraseRawSpan(text, exactNormalizedPhrase);
116
- if (span === null) {
117
- return null;
118
- }
119
- return truncateToUtf8BytesAroundSpan(text, span, maxBytes);
120
- }
121
- function truncateLinePreview(text, maxBytes, exactNormalizedPhrase) {
122
- if (exactNormalizedPhrase === undefined || byteLength(text) <= maxBytes) {
123
- return truncateToUtf8Bytes(text, maxBytes);
124
- }
125
- const span = normalizedPhraseRawSpan(text, exactNormalizedPhrase);
126
- if (span === null) {
127
- return truncateToUtf8Bytes(text, maxBytes);
128
- }
129
- return truncateToUtf8BytesAroundSpan(text, span, maxBytes);
130
- }
131
- function truncateToUtf8Bytes(text, maxBytes) {
132
- if (byteLength(text) <= maxBytes) {
133
- return text;
134
- }
135
- const suffixBytes = byteLength(TRUNCATION_SUFFIX);
136
- const contentBytes = Math.max(0, maxBytes - suffixBytes);
137
- return `${truncateHeadToUtf8Bytes(text, contentBytes)}${TRUNCATION_SUFFIX}`;
138
- }
139
- function truncateToUtf8BytesAroundSpan(text, span, maxBytes) {
140
- if (byteLength(text) <= maxBytes) {
141
- return text;
142
- }
143
- const prefix = span.start > 0 ? TRUNCATION_PREFIX : "";
144
- const suffix = span.end < text.length ? TRUNCATION_SUFFIX : "";
145
- const budget = maxBytes - byteLength(prefix) - byteLength(suffix);
146
- const phrase = text.slice(span.start, span.end);
147
- const phraseBytes = byteLength(phrase);
148
- if (budget <= 0 || phraseBytes >= budget) {
149
- return truncateToUtf8Bytes(text.slice(span.start), maxBytes);
150
- }
151
- const contextBudget = budget - phraseBytes;
152
- const beforeBudget = Math.floor(contextBudget / 2);
153
- const afterBudget = contextBudget - beforeBudget;
154
- let start = span.start;
155
- while (start > 0 && byteLength(text.slice(start - 1, span.start)) <= beforeBudget) {
156
- start -= 1;
157
- }
158
- if (byteLength(text.slice(start, span.start)) > beforeBudget) {
159
- start += 1;
160
- }
161
- let end = span.end;
162
- while (end < text.length && byteLength(text.slice(span.end, end + 1)) <= afterBudget) {
163
- end += 1;
164
- }
165
- if (byteLength(text.slice(span.end, end)) > afterBudget) {
166
- end -= 1;
167
- }
168
- start = moveToCodePointStartBoundary(text, start);
169
- end = moveToCodePointEndBoundary(text, end);
170
- const actualPrefix = start > 0 ? prefix : "";
171
- const actualSuffix = end < text.length ? suffix : "";
172
- return `${actualPrefix}${text.slice(start, end)}${actualSuffix}`;
173
- }
174
- function normalizedPhraseRawSpan(text, normalizedPhrase) {
175
- const phraseTokens = normalizedPhrase.split(/\s+/).filter(Boolean);
176
- if (phraseTokens.length === 0) {
177
- return null;
178
- }
179
- const spans = tokenSpansForPhrase(text);
180
- for (let startIndex = 0; startIndex <= spans.length - phraseTokens.length; startIndex += 1) {
181
- let matched = true;
182
- for (let offset = 0; offset < phraseTokens.length; offset += 1) {
183
- if (spans[startIndex + offset]?.token !== phraseTokens[offset]) {
184
- matched = false;
185
- break;
186
- }
187
- }
188
- if (matched) {
189
- const first = spans[startIndex];
190
- const last = spans[startIndex + phraseTokens.length - 1];
191
- if (first !== undefined && last !== undefined) {
192
- return { start: first.start, end: last.end };
193
- }
194
- }
195
- }
196
- return null;
197
- }
198
- function tokenSpansForPhrase(text) {
199
- const spans = [];
200
- for (const match of text.matchAll(/[A-Za-z0-9_./-]+/g)) {
201
- const rawToken = match[0];
202
- const start = match.index ?? 0;
203
- const end = start + rawToken.length;
204
- for (const token of expandedIdentifierTokens(rawToken)) {
205
- if (token.length >= 2) {
206
- spans.push({ token, start, end });
207
- }
208
- }
209
- }
210
- return spans;
211
- }
212
- function expandedIdentifierTokens(token) {
213
- if (!token) {
214
- return [];
215
- }
216
- const lower = token.toLowerCase();
217
- if (!needsIdentifierSplit(token)) {
218
- return [lower];
219
- }
220
- const variants = new Set();
221
- addTokenVariant(variants, lower);
222
- for (const part of splitIdentifierToken(token)) {
223
- addTokenVariant(variants, part.toLowerCase());
224
- }
225
- return Array.from(variants);
226
- }
227
- function addTokenVariant(variants, token) {
228
- if (token) {
229
- variants.add(token);
230
- }
231
- }
232
- function needsIdentifierSplit(token) {
233
- if (/[._/-]/.test(token)) {
234
- return true;
235
- }
236
- for (let index = 1; index < token.length; index += 1) {
237
- const previous = token.charCodeAt(index - 1);
238
- const current = token.charCodeAt(index);
239
- const next = index + 1 < token.length ? token.charCodeAt(index + 1) : 0;
240
- const previousIsLowerOrDigit = (previous >= 97 && previous <= 122) || (previous >= 48 && previous <= 57);
241
- const previousIsUpper = previous >= 65 && previous <= 90;
242
- const currentIsUpper = current >= 65 && current <= 90;
243
- const nextIsLower = next >= 97 && next <= 122;
244
- if ((previousIsLowerOrDigit && currentIsUpper) || (previousIsUpper && currentIsUpper && nextIsLower)) {
245
- return true;
246
- }
247
- }
248
- return false;
249
- }
250
- function splitIdentifierToken(token) {
251
- const separated = token
252
- .replace(/[._/-]+/g, " ")
253
- .replace(/([a-z0-9])([A-Z])/g, "$1 $2")
254
- .replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2");
255
- return separated.split(/\s+/).filter(Boolean);
256
- }
257
- function truncateTailToUtf8Bytes(text, maxBytes) {
258
- if (byteLength(text) <= maxBytes) {
259
- return text;
260
- }
261
- const prefixBytes = byteLength(TRUNCATION_PREFIX);
262
- const contentBytes = Math.max(0, maxBytes - prefixBytes);
263
- return `${TRUNCATION_PREFIX}${truncateTailToUtf8BytesContent(text, contentBytes)}`;
264
- }
265
- function truncateHeadToUtf8Bytes(text, maxBytes) {
266
- if (maxBytes <= 0) {
267
- return "";
268
- }
269
- if (byteLength(text) <= maxBytes) {
270
- return text;
271
- }
272
- let low = 0;
273
- let high = text.length;
274
- while (low < high) {
275
- const mid = Math.ceil((low + high) / 2);
276
- if (byteLength(text.slice(0, mid)) <= maxBytes) {
277
- low = mid;
278
- } else {
279
- high = mid - 1;
280
- }
281
- }
282
- return text.slice(0, moveToCodePointEndBoundary(text, low));
283
- }
284
- function truncateTailToUtf8BytesContent(text, maxBytes) {
285
- if (maxBytes <= 0) {
286
- return "";
287
- }
288
- if (byteLength(text) <= maxBytes) {
289
- return text;
290
- }
291
- let low = 0;
292
- let high = text.length;
293
- while (low < high) {
294
- const mid = Math.floor((low + high) / 2);
295
- if (byteLength(text.slice(mid)) <= maxBytes) {
296
- high = mid;
297
- } else {
298
- low = mid + 1;
299
- }
300
- }
301
- return text.slice(moveToCodePointStartBoundary(text, low));
302
- }
303
- function moveToCodePointStartBoundary(text, index) {
304
- if (index > 0 && index < text.length && isLowSurrogate(text.charCodeAt(index))) {
305
- return index + 1;
306
- }
307
- return index;
308
- }
309
- function moveToCodePointEndBoundary(text, index) {
310
- if (index > 0 && isHighSurrogate(text.charCodeAt(index - 1))) {
311
- return index - 1;
312
- }
313
- return index;
314
- }
315
- function isHighSurrogate(code) {
316
- return code >= 0xd800 && code <= 0xdbff;
317
- }
318
- function isLowSurrogate(code) {
319
- return code >= 0xdc00 && code <= 0xdfff;
320
- }
321
- function byteLength(text) {
322
- return Buffer.byteLength(text, "utf8");
323
- }
@@ -1,24 +0,0 @@
1
- export interface LineRange {
2
- start: number;
3
- end: number;
4
- }
5
- export type EvidenceChunkKind = "section" | "symbol" | "window";
6
- export type EvidenceRangeMatchKind = "exact-phrase" | "coverage" | "best-line";
7
- export interface SelectEvidenceRangeForChunkOptions {
8
- lines: readonly string[];
9
- chunkRange: LineRange;
10
- chunkKind: EvidenceChunkKind;
11
- queryTokens: readonly string[];
12
- normalizedQueryPhrase: string;
13
- chunkHasExactPhrase: boolean;
14
- defaultContextLines: number;
15
- queryCoverageMaxLines: number;
16
- }
17
- export interface EvidenceRangeSelection {
18
- range: LineRange;
19
- anchorLine: number;
20
- matchKind: EvidenceRangeMatchKind;
21
- }
22
- export declare function selectEvidenceRangeForChunk(
23
- options: SelectEvidenceRangeForChunkOptions,
24
- ): EvidenceRangeSelection;
@@ -1,232 +0,0 @@
1
- export function selectEvidenceRangeForChunk(options) {
2
- const exactRange = options.chunkHasExactPhrase ? exactPhraseRangeForChunk(options) : null;
3
- const chunkLength = options.chunkRange.end - options.chunkRange.start + 1;
4
- const anchorLineIndex = exactRange ? exactRange.start - 1 : bestLineIndexInChunk(options);
5
- if (exactRange) {
6
- const range = expandSectionRangeToNearbyFencedCodeBlocks(options, {
7
- start: Math.max(options.chunkRange.start, exactRange.start - options.defaultContextLines),
8
- end: Math.min(options.chunkRange.end, exactRange.end + options.defaultContextLines),
9
- });
10
- return {
11
- range,
12
- anchorLine: exactRange.start,
13
- matchKind: "exact-phrase",
14
- };
15
- }
16
- if (options.chunkKind === "symbol" || chunkLength <= options.defaultContextLines * 2 + 4) {
17
- return {
18
- range: options.chunkRange,
19
- anchorLine: anchorLineIndex + 1,
20
- matchKind: exactRange ? "exact-phrase" : "best-line",
21
- };
22
- }
23
- const coverageRange = queryCoverageRangeForChunk(options);
24
- if (coverageRange) {
25
- return {
26
- range: expandSectionRangeToNearbyFencedCodeBlocks(options, coverageRange),
27
- anchorLine: coverageRange.start,
28
- matchKind: "coverage",
29
- };
30
- }
31
- const range = expandSectionRangeToNearbyFencedCodeBlocks(options, {
32
- start: Math.max(options.chunkRange.start, anchorLineIndex + 1 - options.defaultContextLines),
33
- end: Math.min(options.chunkRange.end, anchorLineIndex + 1 + options.defaultContextLines),
34
- });
35
- return {
36
- range,
37
- anchorLine: anchorLineIndex + 1,
38
- matchKind: "best-line",
39
- };
40
- }
41
- function exactPhraseRangeForChunk(options) {
42
- if (options.normalizedQueryPhrase === "") {
43
- return null;
44
- }
45
- for (let lineIndex = options.chunkRange.start - 1; lineIndex < options.chunkRange.end; lineIndex += 1) {
46
- const line = options.lines[lineIndex] ?? "";
47
- if (hasExactNormalizedPhrase(line, options.normalizedQueryPhrase)) {
48
- return { start: lineIndex + 1, end: lineIndex + 1 };
49
- }
50
- }
51
- for (let startIndex = options.chunkRange.start - 1; startIndex < options.chunkRange.end; startIndex += 1) {
52
- let text = "";
53
- for (let endIndex = startIndex; endIndex < options.chunkRange.end; endIndex += 1) {
54
- const line = options.lines[endIndex] ?? "";
55
- text = text === "" ? line : `${text}\n${line}`;
56
- if (hasExactNormalizedPhrase(text, options.normalizedQueryPhrase)) {
57
- return { start: startIndex + 1, end: endIndex + 1 };
58
- }
59
- }
60
- }
61
- return null;
62
- }
63
- function bestLineIndexInChunk(options) {
64
- let bestIndex = options.chunkRange.start - 1;
65
- let bestScore = 0;
66
- for (let lineIndex = options.chunkRange.start - 1; lineIndex < options.chunkRange.end; lineIndex += 1) {
67
- const line = options.lines[lineIndex] ?? "";
68
- const score = scoreText(line, options.queryTokens) * 4 + (line.trimStart().startsWith("#") ? 2 : 0);
69
- if (score > bestScore) {
70
- bestIndex = lineIndex;
71
- bestScore = score;
72
- }
73
- }
74
- return bestIndex;
75
- }
76
- function queryCoverageRangeForChunk(options) {
77
- if (options.chunkKind !== "section" || options.queryTokens.length < 2) {
78
- return null;
79
- }
80
- const remainingTokens = new Set(options.queryTokens);
81
- const matchingLines = [];
82
- for (let lineIndex = options.chunkRange.start - 1; lineIndex < options.chunkRange.end; lineIndex += 1) {
83
- const line = options.lines[lineIndex] ?? "";
84
- const lineTokens = new Set(tokenizeForSearch(line));
85
- let matchedLine = false;
86
- for (const token of options.queryTokens) {
87
- if (lineTokens.has(token)) {
88
- remainingTokens.delete(token);
89
- matchedLine = true;
90
- }
91
- }
92
- if (matchedLine) {
93
- matchingLines.push(lineIndex + 1);
94
- }
95
- if (remainingTokens.size === 0) {
96
- break;
97
- }
98
- }
99
- if (remainingTokens.size > 0 || matchingLines.length === 0) {
100
- return null;
101
- }
102
- return boundedCoverageRange(options, matchingLines);
103
- }
104
- function boundedCoverageRange(options, matchingLines) {
105
- const firstMatch = Math.min(...matchingLines);
106
- const lastMatch = Math.max(...matchingLines);
107
- const start = Math.max(options.chunkRange.start, firstMatch - options.defaultContextLines);
108
- const end = Math.min(options.chunkRange.end, lastMatch + options.defaultContextLines);
109
- if (end - start + 1 <= options.queryCoverageMaxLines) {
110
- return { start, end };
111
- }
112
- const cappedStart = start;
113
- const cappedEnd = Math.min(options.chunkRange.end, cappedStart + options.queryCoverageMaxLines - 1);
114
- return { start: cappedStart, end: cappedEnd };
115
- }
116
- function expandSectionRangeToNearbyFencedCodeBlocks(options, range) {
117
- if (options.chunkKind !== "section") {
118
- return range;
119
- }
120
- let expanded = range;
121
- for (const block of fencedCodeBlocksInChunk(options)) {
122
- const adjacentOrOverlapping =
123
- block.start <= expanded.end + options.defaultContextLines &&
124
- block.end >= expanded.start - options.defaultContextLines;
125
- if (!adjacentOrOverlapping) {
126
- continue;
127
- }
128
- const candidate = {
129
- start: Math.min(expanded.start, block.start),
130
- end: Math.max(expanded.end, block.end),
131
- };
132
- if (candidate.end - candidate.start + 1 <= options.queryCoverageMaxLines) {
133
- expanded = candidate;
134
- }
135
- }
136
- return expanded;
137
- }
138
- function fencedCodeBlocksInChunk(options) {
139
- const blocks = [];
140
- let openStart = null;
141
- for (let lineIndex = options.chunkRange.start - 1; lineIndex < options.chunkRange.end; lineIndex += 1) {
142
- const lineNumber = lineIndex + 1;
143
- const line = options.lines[lineIndex] ?? "";
144
- if (!/^\s*```/.test(line)) {
145
- continue;
146
- }
147
- if (openStart === null) {
148
- openStart = lineNumber;
149
- } else {
150
- blocks.push({ start: openStart, end: lineNumber });
151
- openStart = null;
152
- }
153
- }
154
- if (openStart !== null) {
155
- blocks.push({ start: openStart, end: options.chunkRange.end });
156
- }
157
- return blocks;
158
- }
159
- function hasExactNormalizedPhrase(text, normalizedQueryPhrase) {
160
- return normalizedQueryPhrase !== "" && normalizePhraseSequence(text).includes(normalizedQueryPhrase);
161
- }
162
- function normalizePhraseSequence(text) {
163
- const tokens = tokenizeForPhrase(text);
164
- return tokens.length >= 2 ? tokens.join(" ") : "";
165
- }
166
- function tokenizeForSearch(text) {
167
- return text
168
- .split(/[^A-Za-z0-9_./-]+/)
169
- .flatMap((token) => expandedIdentifierTokens(token.trim()))
170
- .filter((token) => token.length >= 2);
171
- }
172
- function tokenizeForPhrase(text) {
173
- return tokenizeForSearch(text);
174
- }
175
- function scoreText(text, tokens) {
176
- const lower = text.toLowerCase();
177
- return tokens.reduce((score, token) => score + countOccurrences(lower, token), 0);
178
- }
179
- function countOccurrences(text, token) {
180
- let count = 0;
181
- let index = text.indexOf(token);
182
- while (index !== -1) {
183
- count += 1;
184
- index = text.indexOf(token, index + token.length);
185
- }
186
- return count;
187
- }
188
- function expandedIdentifierTokens(token) {
189
- if (!token) {
190
- return [];
191
- }
192
- const lower = token.toLowerCase();
193
- if (!needsIdentifierSplit(token)) {
194
- return [lower];
195
- }
196
- const variants = new Set();
197
- addTokenVariant(variants, lower);
198
- for (const part of splitIdentifierToken(token)) {
199
- addTokenVariant(variants, part.toLowerCase());
200
- }
201
- return Array.from(variants);
202
- }
203
- function addTokenVariant(variants, token) {
204
- if (token) {
205
- variants.add(token);
206
- }
207
- }
208
- function needsIdentifierSplit(token) {
209
- if (/[._/-]/.test(token)) {
210
- return true;
211
- }
212
- for (let index = 1; index < token.length; index += 1) {
213
- const previous = token.charCodeAt(index - 1);
214
- const current = token.charCodeAt(index);
215
- const next = index + 1 < token.length ? token.charCodeAt(index + 1) : 0;
216
- const previousIsLowerOrDigit = (previous >= 97 && previous <= 122) || (previous >= 48 && previous <= 57);
217
- const previousIsUpper = previous >= 65 && previous <= 90;
218
- const currentIsUpper = current >= 65 && current <= 90;
219
- const nextIsLower = next >= 97 && next <= 122;
220
- if ((previousIsLowerOrDigit && currentIsUpper) || (previousIsUpper && currentIsUpper && nextIsLower)) {
221
- return true;
222
- }
223
- }
224
- return false;
225
- }
226
- function splitIdentifierToken(token) {
227
- return token
228
- .replace(/([a-z0-9])([A-Z])/g, "$1 $2")
229
- .replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2")
230
- .split(/[._/\-\s]+/)
231
- .filter((part) => part.length > 0);
232
- }
@@ -1,27 +0,0 @@
1
- export interface EvidenceSearchLineRange {
2
- start: number;
3
- end: number;
4
- }
5
- export interface EvidenceSearchFile {
6
- path: string;
7
- lines: readonly string[];
8
- }
9
- export interface EvidenceSearchCandidate<TFile extends EvidenceSearchFile = EvidenceSearchFile> {
10
- file: TFile;
11
- lineIndex: number;
12
- score: number;
13
- reason: string;
14
- range?: EvidenceSearchLineRange;
15
- exactNormalizedPhrase?: string;
16
- }
17
- export interface SearchRepoEvidenceCandidatesOptions<TFile extends EvidenceSearchFile = EvidenceSearchFile> {
18
- files: readonly TFile[];
19
- query: string;
20
- topK: number;
21
- defaultContextLines?: number;
22
- queryCoverageMaxLines?: number;
23
- }
24
- export declare function searchRepoEvidenceCandidates<TFile extends EvidenceSearchFile>(
25
- options: SearchRepoEvidenceCandidatesOptions<TFile>,
26
- ): EvidenceSearchCandidate<TFile>[];
27
- export declare function findBestLineForQuery(lines: readonly string[], query: string): number | null;