@ai-agent-forge/agent-forge 0.88.4 → 0.88.6

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 (198) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/bundled-plugins/agent-loop-policy/agent-forge.json +1 -1
  3. package/bundled-plugins/agent-loop-policy/plugin.json +1 -1
  4. package/bundled-plugins/alignment/agent-forge.json +19 -0
  5. package/bundled-plugins/alignment/dist/baseline.d.ts +12 -0
  6. package/bundled-plugins/alignment/dist/baseline.d.ts.map +1 -0
  7. package/bundled-plugins/alignment/dist/baseline.js +68 -0
  8. package/bundled-plugins/alignment/dist/baseline.js.map +1 -0
  9. package/bundled-plugins/alignment/dist/engine.d.ts +102 -0
  10. package/bundled-plugins/alignment/dist/engine.d.ts.map +1 -0
  11. package/bundled-plugins/alignment/dist/engine.js +654 -0
  12. package/bundled-plugins/alignment/dist/engine.js.map +1 -0
  13. package/bundled-plugins/alignment/dist/entry.d.ts +14 -0
  14. package/bundled-plugins/alignment/dist/entry.d.ts.map +1 -0
  15. package/bundled-plugins/alignment/dist/entry.js +23 -0
  16. package/bundled-plugins/alignment/dist/entry.js.map +1 -0
  17. package/bundled-plugins/alignment/dist/export.d.ts +15 -0
  18. package/bundled-plugins/alignment/dist/export.d.ts.map +1 -0
  19. package/bundled-plugins/alignment/dist/export.js +122 -0
  20. package/bundled-plugins/alignment/dist/export.js.map +1 -0
  21. package/bundled-plugins/alignment/dist/http-server.d.ts +33 -0
  22. package/bundled-plugins/alignment/dist/http-server.d.ts.map +1 -0
  23. package/bundled-plugins/alignment/dist/http-server.js +119 -0
  24. package/bundled-plugins/alignment/dist/http-server.js.map +1 -0
  25. package/bundled-plugins/alignment/dist/index.d.ts +24 -0
  26. package/bundled-plugins/alignment/dist/index.d.ts.map +1 -0
  27. package/bundled-plugins/alignment/dist/index.js +719 -0
  28. package/bundled-plugins/alignment/dist/index.js.map +1 -0
  29. package/bundled-plugins/alignment/dist/page.d.ts +15 -0
  30. package/bundled-plugins/alignment/dist/page.d.ts.map +1 -0
  31. package/bundled-plugins/alignment/dist/page.js +832 -0
  32. package/bundled-plugins/alignment/dist/page.js.map +1 -0
  33. package/bundled-plugins/alignment/dist/render.d.ts +40 -0
  34. package/bundled-plugins/alignment/dist/render.d.ts.map +1 -0
  35. package/bundled-plugins/alignment/dist/render.js +194 -0
  36. package/bundled-plugins/alignment/dist/render.js.map +1 -0
  37. package/bundled-plugins/alignment/dist/types.d.ts +217 -0
  38. package/bundled-plugins/alignment/dist/types.d.ts.map +1 -0
  39. package/bundled-plugins/alignment/dist/types.js +30 -0
  40. package/bundled-plugins/alignment/dist/types.js.map +1 -0
  41. package/bundled-plugins/alignment/plugin.json +12 -0
  42. package/bundled-plugins/browser-playwright/MANUAL.md +60 -0
  43. package/bundled-plugins/browser-playwright/agent-forge.json +25 -0
  44. package/bundled-plugins/browser-playwright/dist/capability.d.ts +25 -0
  45. package/bundled-plugins/browser-playwright/dist/capability.d.ts.map +1 -0
  46. package/bundled-plugins/browser-playwright/dist/capability.js +612 -0
  47. package/bundled-plugins/browser-playwright/dist/capability.js.map +1 -0
  48. package/bundled-plugins/browser-playwright/dist/entry.d.ts +13 -0
  49. package/bundled-plugins/browser-playwright/dist/entry.d.ts.map +1 -0
  50. package/bundled-plugins/browser-playwright/dist/entry.js +14 -0
  51. package/bundled-plugins/browser-playwright/dist/entry.js.map +1 -0
  52. package/bundled-plugins/browser-playwright/dist/index.d.ts +7 -0
  53. package/bundled-plugins/browser-playwright/dist/index.d.ts.map +1 -0
  54. package/bundled-plugins/browser-playwright/dist/index.js +5 -0
  55. package/bundled-plugins/browser-playwright/dist/index.js.map +1 -0
  56. package/bundled-plugins/browser-playwright/dist/operations.d.ts +69 -0
  57. package/bundled-plugins/browser-playwright/dist/operations.d.ts.map +1 -0
  58. package/bundled-plugins/browser-playwright/dist/operations.js +149 -0
  59. package/bundled-plugins/browser-playwright/dist/operations.js.map +1 -0
  60. package/bundled-plugins/browser-playwright/dist/playwright-driver.d.ts +275 -0
  61. package/bundled-plugins/browser-playwright/dist/playwright-driver.d.ts.map +1 -0
  62. package/bundled-plugins/browser-playwright/dist/playwright-driver.js +953 -0
  63. package/bundled-plugins/browser-playwright/dist/playwright-driver.js.map +1 -0
  64. package/bundled-plugins/browser-playwright/dist/setup.d.ts +88 -0
  65. package/bundled-plugins/browser-playwright/dist/setup.d.ts.map +1 -0
  66. package/bundled-plugins/browser-playwright/dist/setup.js +252 -0
  67. package/bundled-plugins/browser-playwright/dist/setup.js.map +1 -0
  68. package/bundled-plugins/browser-playwright/dist/types.d.ts +270 -0
  69. package/bundled-plugins/browser-playwright/dist/types.d.ts.map +1 -0
  70. package/bundled-plugins/browser-playwright/dist/types.js +2 -0
  71. package/bundled-plugins/browser-playwright/dist/types.js.map +1 -0
  72. package/bundled-plugins/browser-playwright/plugin.json +20 -0
  73. package/bundled-plugins/coding-tools/agent-forge.json +1 -1
  74. package/bundled-plugins/coding-tools/dist/bash.d.ts +2 -7
  75. package/bundled-plugins/coding-tools/dist/bash.d.ts.map +1 -1
  76. package/bundled-plugins/coding-tools/dist/bash.js +2 -34
  77. package/bundled-plugins/coding-tools/dist/bash.js.map +1 -1
  78. package/bundled-plugins/coding-tools/plugin.json +1 -1
  79. package/bundled-plugins/compaction-policy/agent-forge.json +1 -1
  80. package/bundled-plugins/compaction-policy/plugin.json +1 -1
  81. package/bundled-plugins/mcp-http/dist/mcp-http.d.ts.map +1 -1
  82. package/bundled-plugins/mcp-http/dist/mcp-http.js +84 -31
  83. package/bundled-plugins/mcp-http/dist/mcp-http.js.map +1 -1
  84. package/bundled-plugins/overflow-policy/agent-forge.json +1 -1
  85. package/bundled-plugins/overflow-policy/plugin.json +1 -1
  86. package/bundled-plugins/provider-failover/agent-forge.json +1 -1
  87. package/bundled-plugins/provider-failover/plugin.json +1 -1
  88. package/bundled-plugins/retry-policy/agent-forge.json +1 -1
  89. package/bundled-plugins/retry-policy/plugin.json +1 -1
  90. package/dist/bundle/.build-manifest.json +60 -58
  91. package/dist/bundle/chunks/{anthropic-messages-3FJHRAJL.js → anthropic-messages-NL4Y6WPB.js} +1 -1
  92. package/dist/bundle/chunks/{azure-openai-responses-GCL47IDS.js → azure-openai-responses-CPXC42HO.js} +1 -1
  93. package/dist/bundle/chunks/bedrock-converse-stream.js +1 -1
  94. package/dist/bundle/chunks/chunk-5LRQFZFE.js +2 -0
  95. package/dist/bundle/chunks/{chunk-HTEVUY7F.js → chunk-7HSJPQKN.js} +1 -1
  96. package/dist/bundle/chunks/{chunk-AC2FIS4G.js → chunk-EDO7Q6XR.js} +1 -1
  97. package/dist/bundle/chunks/{chunk-755VNWIF.js → chunk-ISLHFRER.js} +6 -6
  98. package/dist/bundle/chunks/{chunk-HV64ASMT.js → chunk-K3S6GTL7.js} +1 -1
  99. package/dist/bundle/chunks/{chunk-HEL6TAWE.js → chunk-POLDAUYA.js} +37 -36
  100. package/dist/bundle/chunks/{chunk-V3ACW7VD.js → chunk-WJSKB3FC.js} +1 -1
  101. package/dist/bundle/chunks/{chunk-32YDZI4J.js → chunk-ZS5JEI76.js} +1 -1
  102. package/dist/bundle/chunks/{google-generative-ai-6BMXWA44.js → google-generative-ai-UMZ53EFA.js} +1 -1
  103. package/dist/bundle/chunks/{google-vertex-6H7NLRTK.js → google-vertex-ZNR5NS6H.js} +1 -1
  104. package/dist/bundle/chunks/image-resize-worker.js +1 -1
  105. package/dist/bundle/chunks/{mistral-conversations-IXUHSFSJ.js → mistral-conversations-IT66WUNN.js} +1 -1
  106. package/dist/bundle/chunks/{openai-codex-responses-YHUAEVCM.js → openai-codex-responses-FOVCVG6I.js} +1 -1
  107. package/dist/bundle/chunks/{openai-completions-ULQCFC72.js → openai-completions-FLQ7CBOL.js} +1 -1
  108. package/dist/bundle/chunks/{openai-responses-NLLAJDPS.js → openai-responses-ABGYHS2T.js} +1 -1
  109. package/dist/bundle/chunks/{pi-messages-EJTI2EJ3.js → pi-messages-6K5W6LUN.js} +1 -1
  110. package/dist/bundle/chunks/{virtual-modules-TQWEGNNZ.js → virtual-modules-2QGILFV7.js} +1 -1
  111. package/dist/bundle/cli.js +1 -1
  112. package/dist/bundle/client.js +1 -1
  113. package/dist/bundle/index.js +1 -1
  114. package/dist/bundle/rpc-entry.js +1 -1
  115. package/dist/client/remote-session.d.ts.map +1 -1
  116. package/dist/client/remote-session.js +65 -6
  117. package/dist/client/remote-session.js.map +1 -1
  118. package/dist/core/agent-session-store.d.ts.map +1 -1
  119. package/dist/core/agent-session-store.js +20 -3
  120. package/dist/core/agent-session-store.js.map +1 -1
  121. package/dist/core/extensions/agent-composition.d.ts.map +1 -1
  122. package/dist/core/extensions/agent-composition.js +20 -1
  123. package/dist/core/extensions/agent-composition.js.map +1 -1
  124. package/dist/core/i18n/locales/zh-cn/core-errors.d.ts.map +1 -1
  125. package/dist/core/i18n/locales/zh-cn/core-errors.js +1 -0
  126. package/dist/core/i18n/locales/zh-cn/core-errors.js.map +1 -1
  127. package/dist/core/i18n/locales/zh-cn/interactive-mode.d.ts.map +1 -1
  128. package/dist/core/i18n/locales/zh-cn/interactive-mode.js +10 -3
  129. package/dist/core/i18n/locales/zh-cn/interactive-mode.js.map +1 -1
  130. package/dist/core/keybindings.d.ts +35 -0
  131. package/dist/core/keybindings.d.ts.map +1 -1
  132. package/dist/core/keybindings.js +34 -0
  133. package/dist/core/keybindings.js.map +1 -1
  134. package/dist/core/sdk.d.ts.map +1 -1
  135. package/dist/core/sdk.js +62 -15
  136. package/dist/core/sdk.js.map +1 -1
  137. package/dist/core/session-manager.d.ts.map +1 -1
  138. package/dist/core/session-manager.js +11 -3
  139. package/dist/core/session-manager.js.map +1 -1
  140. package/dist/core/system-prompt.d.ts.map +1 -1
  141. package/dist/core/system-prompt.js +2 -2
  142. package/dist/core/system-prompt.js.map +1 -1
  143. package/dist/core/tools/capability-mount.d.ts.map +1 -1
  144. package/dist/core/tools/capability-mount.js +4 -21
  145. package/dist/core/tools/capability-mount.js.map +1 -1
  146. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  147. package/dist/modes/interactive/components/assistant-message.js +2 -2
  148. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  149. package/dist/modes/interactive/components/bash-execution.d.ts +2 -0
  150. package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
  151. package/dist/modes/interactive/components/bash-execution.js +25 -0
  152. package/dist/modes/interactive/components/bash-execution.js.map +1 -1
  153. package/dist/modes/interactive/components/changelog-pager.d.ts +53 -0
  154. package/dist/modes/interactive/components/changelog-pager.d.ts.map +1 -0
  155. package/dist/modes/interactive/components/changelog-pager.js +239 -0
  156. package/dist/modes/interactive/components/changelog-pager.js.map +1 -0
  157. package/dist/modes/interactive/components/tool-execution.d.ts +6 -0
  158. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  159. package/dist/modes/interactive/components/tool-execution.js +12 -0
  160. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  161. package/dist/modes/interactive/components/tool-run-group.d.ts +41 -11
  162. package/dist/modes/interactive/components/tool-run-group.d.ts.map +1 -1
  163. package/dist/modes/interactive/components/tool-run-group.js +126 -14
  164. package/dist/modes/interactive/components/tool-run-group.js.map +1 -1
  165. package/dist/modes/interactive/interactive-commands.d.ts.map +1 -1
  166. package/dist/modes/interactive/interactive-commands.js +23 -13
  167. package/dist/modes/interactive/interactive-commands.js.map +1 -1
  168. package/dist/modes/interactive/interactive-events.d.ts +14 -4
  169. package/dist/modes/interactive/interactive-events.d.ts.map +1 -1
  170. package/dist/modes/interactive/interactive-events.js +94 -12
  171. package/dist/modes/interactive/interactive-events.js.map +1 -1
  172. package/dist/modes/interactive/interactive-mode.d.ts +6 -1
  173. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  174. package/dist/modes/interactive/interactive-mode.js +21 -5
  175. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  176. package/dist/plugins/ecosystem/node-local-package-source.d.ts +2 -1
  177. package/dist/plugins/ecosystem/node-local-package-source.d.ts.map +1 -1
  178. package/dist/plugins/ecosystem/node-local-package-source.js +110 -4
  179. package/dist/plugins/ecosystem/node-local-package-source.js.map +1 -1
  180. package/dist/plugins/ecosystem/node-package-install-host.d.ts.map +1 -1
  181. package/dist/plugins/ecosystem/node-package-install-host.js +106 -39
  182. package/dist/plugins/ecosystem/node-package-install-host.js.map +1 -1
  183. package/dist/plugins/ecosystem/node-plugin-bootstrap.d.ts.map +1 -1
  184. package/dist/plugins/ecosystem/node-plugin-bootstrap.js +59 -2
  185. package/dist/plugins/ecosystem/node-plugin-bootstrap.js.map +1 -1
  186. package/dist/suites/builtin-suites.d.ts.map +1 -1
  187. package/dist/suites/builtin-suites.js +2 -2
  188. package/dist/suites/builtin-suites.js.map +1 -1
  189. package/dist/utils/changelog.d.ts +27 -0
  190. package/dist/utils/changelog.d.ts.map +1 -1
  191. package/dist/utils/changelog.js +110 -0
  192. package/dist/utils/changelog.js.map +1 -1
  193. package/docs/keybindings.md +14 -0
  194. package/examples/extensions/with-deps/package-lock.json +2 -2
  195. package/examples/extensions/with-deps/package.json +1 -1
  196. package/examples/extensions/with-deps/plugin.json +1 -1
  197. package/package.json +1 -1
  198. package/dist/bundle/chunks/chunk-A3JYRWB6.js +0 -2
@@ -1 +1 @@
1
- {"version":3,"file":"changelog.d.ts","sourceRoot":"","sources":["../../src/utils/changelog.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,cAAc;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CAChB;AA2FD,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,cAAc,GAAG,MAAM,CAKlG;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,aAAa,EAAE,MAAM,GAAG,cAAc,EAAE,CAyDtE;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,EAAE,EAAE,cAAc,EAAE,EAAE,EAAE,cAAc,GAAG,MAAM,CAI9E;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,cAAc,EAAE,EAAE,WAAW,EAAE,MAAM,GAAG,cAAc,EAAE,CAW9F;AAGD,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC","sourcesContent":["import path from \"node:path\";\nimport { existsSync, readFileSync } from \"fs\";\n\nexport interface ChangelogEntry {\n\tmajor: number;\n\tminor: number;\n\tpatch: number;\n\tcontent: string;\n}\n\nconst GITHUB_REPO = process.env.AGENT_FORGE_GITHUB_REPO || \"agent-forge/agent-forge\";\nconst CHANGELOG_LINK_BASE_PATH = \"packages/agent-forge\";\nconst LEGACY_REPO_RE = /^https:\\/\\/github\\.com\\/(?:badlogic|earendil-works)\\/(?:pi-mono|pi)(?=\\/|$)/;\nconst URL_SCHEME_RE = /^[a-z][a-z0-9+.-]*:/i;\nconst INLINE_MARKDOWN_LINK_RE = /(!?\\[[^\\]\\n]+\\]\\()([^\\s)]+)((?:\\s+[^)]*)?\\))/g;\n\nfunction entryVersion(entry: ChangelogEntry): string {\n\treturn `${entry.major}.${entry.minor}.${entry.patch}`;\n}\n\nfunction normalizeTag(version: string | ChangelogEntry): string {\n\tconst versionString = typeof version === \"string\" ? version : entryVersion(version);\n\treturn versionString.startsWith(\"v\") ? versionString : `v${versionString}`;\n}\n\nfunction splitLocalTarget(target: string): { fragment: string; pathPart: string; query: string } {\n\tconst hashIndex = target.indexOf(\"#\");\n\tconst beforeHash = hashIndex === -1 ? target : target.slice(0, hashIndex);\n\tconst fragment = hashIndex === -1 ? \"\" : target.slice(hashIndex);\n\tconst queryIndex = beforeHash.indexOf(\"?\");\n\n\tif (queryIndex === -1) {\n\t\treturn { fragment, pathPart: beforeHash, query: \"\" };\n\t}\n\n\treturn {\n\t\tfragment,\n\t\tpathPart: beforeHash.slice(0, queryIndex),\n\t\tquery: beforeHash.slice(queryIndex),\n\t};\n}\n\nfunction normalizePathPart(value: string): string {\n\treturn value.replaceAll(\"\\\\\", \"/\");\n}\n\nfunction resolveRepositoryPath(targetPath: string): string | undefined {\n\tconst normalizedTarget = normalizePathPart(targetPath);\n\tconst joined = normalizedTarget.startsWith(\"/\")\n\t\t? path.posix.normalize(normalizedTarget.replace(/^\\/+/, \"\"))\n\t\t: path.posix.normalize(path.posix.join(CHANGELOG_LINK_BASE_PATH, normalizedTarget));\n\n\tif (joined === \".\" || joined.startsWith(\"../\") || joined === \"..\") {\n\t\treturn undefined;\n\t}\n\n\treturn joined;\n}\n\nfunction isDirectoryTarget(originalPath: string, repositoryPath: string): boolean {\n\tif (originalPath.endsWith(\"/\")) {\n\t\treturn true;\n\t}\n\n\tconst basename = path.posix.basename(repositoryPath);\n\treturn !basename.includes(\".\");\n}\n\nfunction normalizeChangelogLinkTarget(target: string, tag: string): string {\n\tlet canonicalTarget = target.replace(LEGACY_REPO_RE, `https://github.com/${GITHUB_REPO}`);\n\tconst repoUrl = `https://github.com/${GITHUB_REPO}`;\n\n\tfor (const route of [\"blob\", \"tree\"]) {\n\t\tfor (const branch of [\"main\", \"master\"]) {\n\t\t\tconst floatingRefPrefix = `${repoUrl}/${route}/${branch}/`;\n\t\t\tif (canonicalTarget.startsWith(floatingRefPrefix)) {\n\t\t\t\tcanonicalTarget = `${repoUrl}/${route}/${tag}/${canonicalTarget.slice(floatingRefPrefix.length)}`;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (canonicalTarget.startsWith(\"#\") || canonicalTarget.startsWith(\"//\") || URL_SCHEME_RE.test(canonicalTarget)) {\n\t\treturn canonicalTarget;\n\t}\n\n\tconst { fragment, pathPart, query } = splitLocalTarget(canonicalTarget);\n\tif (!pathPart) {\n\t\treturn canonicalTarget;\n\t}\n\n\tconst repositoryPath = resolveRepositoryPath(pathPart);\n\tif (!repositoryPath) {\n\t\treturn canonicalTarget;\n\t}\n\n\tconst route = isDirectoryTarget(pathPart, repositoryPath) ? \"tree\" : \"blob\";\n\treturn `https://github.com/${GITHUB_REPO}/${route}/${tag}/${encodeURI(repositoryPath)}${query}${fragment}`;\n}\n\nexport function normalizeChangelogLinks(markdown: string, version: string | ChangelogEntry): string {\n\tconst tag = normalizeTag(version);\n\treturn markdown.replace(INLINE_MARKDOWN_LINK_RE, (_match, prefix, target, suffix) => {\n\t\treturn `${prefix}${normalizeChangelogLinkTarget(target, tag)}${suffix}`;\n\t});\n}\n\n/**\n * Parse changelog entries from CHANGELOG.md\n * Scans for ## lines and collects content until next ## or EOF\n */\nexport function parseChangelog(changelogPath: string): ChangelogEntry[] {\n\tif (!existsSync(changelogPath)) {\n\t\treturn [];\n\t}\n\n\ttry {\n\t\tconst content = readFileSync(changelogPath, \"utf-8\");\n\t\tconst lines = content.split(\"\\n\");\n\t\tconst entries: ChangelogEntry[] = [];\n\n\t\tlet currentLines: string[] = [];\n\t\tlet currentVersion: { major: number; minor: number; patch: number } | null = null;\n\n\t\tfor (const line of lines) {\n\t\t\t// Check if this is a version header (## [x.y.z] ...)\n\t\t\tif (line.startsWith(\"## \")) {\n\t\t\t\t// Save previous entry if exists\n\t\t\t\tif (currentVersion && currentLines.length > 0) {\n\t\t\t\t\tentries.push({\n\t\t\t\t\t\t...currentVersion,\n\t\t\t\t\t\tcontent: currentLines.join(\"\\n\").trim(),\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\t// Try to parse version from this line\n\t\t\t\tconst versionMatch = line.match(/##\\s+\\[?(\\d+)\\.(\\d+)\\.(\\d+)\\]?/);\n\t\t\t\tif (versionMatch) {\n\t\t\t\t\tcurrentVersion = {\n\t\t\t\t\t\tmajor: Number.parseInt(versionMatch[1], 10),\n\t\t\t\t\t\tminor: Number.parseInt(versionMatch[2], 10),\n\t\t\t\t\t\tpatch: Number.parseInt(versionMatch[3], 10),\n\t\t\t\t\t};\n\t\t\t\t\tcurrentLines = [line];\n\t\t\t\t} else {\n\t\t\t\t\t// Reset if we can't parse version\n\t\t\t\t\tcurrentVersion = null;\n\t\t\t\t\tcurrentLines = [];\n\t\t\t\t}\n\t\t\t} else if (currentVersion) {\n\t\t\t\t// Collect lines for current version\n\t\t\t\tcurrentLines.push(line);\n\t\t\t}\n\t\t}\n\n\t\t// Save last entry\n\t\tif (currentVersion && currentLines.length > 0) {\n\t\t\tentries.push({\n\t\t\t\t...currentVersion,\n\t\t\t\tcontent: currentLines.join(\"\\n\").trim(),\n\t\t\t});\n\t\t}\n\n\t\treturn entries;\n\t} catch (error) {\n\t\tconsole.error(`Warning: Could not parse changelog: ${error}`);\n\t\treturn [];\n\t}\n}\n\n/**\n * Compare versions. Returns: -1 if v1 < v2, 0 if v1 === v2, 1 if v1 > v2\n */\nexport function compareVersions(v1: ChangelogEntry, v2: ChangelogEntry): number {\n\tif (v1.major !== v2.major) return v1.major - v2.major;\n\tif (v1.minor !== v2.minor) return v1.minor - v2.minor;\n\treturn v1.patch - v2.patch;\n}\n\n/**\n * Get entries newer than lastVersion\n */\nexport function getNewEntries(entries: ChangelogEntry[], lastVersion: string): ChangelogEntry[] {\n\t// Parse lastVersion\n\tconst parts = lastVersion.split(\".\").map(Number);\n\tconst last: ChangelogEntry = {\n\t\tmajor: parts[0] || 0,\n\t\tminor: parts[1] || 0,\n\t\tpatch: parts[2] || 0,\n\t\tcontent: \"\",\n\t};\n\n\treturn entries.filter((entry) => compareVersions(entry, last) > 0);\n}\n\n// Re-export getChangelogPath from paths.ts for convenience\nexport { getChangelogPath } from \"../config.ts\";\n"]}
1
+ {"version":3,"file":"changelog.d.ts","sourceRoot":"","sources":["../../src/utils/changelog.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,cAAc;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CAChB;AA2FD,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,cAAc,GAAG,MAAM,CAKlG;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,aAAa,EAAE,MAAM,GAAG,cAAc,EAAE,CAyDtE;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,EAAE,EAAE,cAAc,EAAE,EAAE,EAAE,cAAc,GAAG,MAAM,CAI9E;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,cAAc,EAAE,EAAE,WAAW,EAAE,MAAM,GAAG,cAAc,EAAE,CAW9F;AAGD,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAQhD,MAAM,WAAW,wBAAwB;IACxC,2EAA2E;IAC3E,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,yEAAyE;IACzE,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,4EAA4E;IAC5E,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,iEAAiE;IACjE,QAAQ,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;CAC7C;AAED,eAAO,MAAM,mCAAmC,EAAE,wBAKjD,CAAC;AAwBF;;;;GAIG;AACH,wBAAgB,0BAA0B,CACzC,OAAO,EAAE,SAAS,cAAc,EAAE,EAClC,OAAO,GAAE,wBAA8D,GACrE,MAAM,CAoCR;AAED,MAAM,WAAW,qBAAqB;IACrC,QAAQ,CAAC,IAAI,EAAE,gBAAgB,GAAG,UAAU,CAAC;IAC7C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC1B;AAED;;;;GAIG;AACH,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,SAAS,cAAc,EAAE,GAAG,SAAS,qBAAqB,EAAE,CA2BhH","sourcesContent":["import path from \"node:path\";\nimport { existsSync, readFileSync } from \"fs\";\n\nexport interface ChangelogEntry {\n\tmajor: number;\n\tminor: number;\n\tpatch: number;\n\tcontent: string;\n}\n\nconst GITHUB_REPO = process.env.AGENT_FORGE_GITHUB_REPO || \"agent-forge/agent-forge\";\nconst CHANGELOG_LINK_BASE_PATH = \"packages/agent-forge\";\nconst LEGACY_REPO_RE = /^https:\\/\\/github\\.com\\/(?:badlogic|earendil-works)\\/(?:pi-mono|pi)(?=\\/|$)/;\nconst URL_SCHEME_RE = /^[a-z][a-z0-9+.-]*:/i;\nconst INLINE_MARKDOWN_LINK_RE = /(!?\\[[^\\]\\n]+\\]\\()([^\\s)]+)((?:\\s+[^)]*)?\\))/g;\n\nfunction entryVersion(entry: ChangelogEntry): string {\n\treturn `${entry.major}.${entry.minor}.${entry.patch}`;\n}\n\nfunction normalizeTag(version: string | ChangelogEntry): string {\n\tconst versionString = typeof version === \"string\" ? version : entryVersion(version);\n\treturn versionString.startsWith(\"v\") ? versionString : `v${versionString}`;\n}\n\nfunction splitLocalTarget(target: string): { fragment: string; pathPart: string; query: string } {\n\tconst hashIndex = target.indexOf(\"#\");\n\tconst beforeHash = hashIndex === -1 ? target : target.slice(0, hashIndex);\n\tconst fragment = hashIndex === -1 ? \"\" : target.slice(hashIndex);\n\tconst queryIndex = beforeHash.indexOf(\"?\");\n\n\tif (queryIndex === -1) {\n\t\treturn { fragment, pathPart: beforeHash, query: \"\" };\n\t}\n\n\treturn {\n\t\tfragment,\n\t\tpathPart: beforeHash.slice(0, queryIndex),\n\t\tquery: beforeHash.slice(queryIndex),\n\t};\n}\n\nfunction normalizePathPart(value: string): string {\n\treturn value.replaceAll(\"\\\\\", \"/\");\n}\n\nfunction resolveRepositoryPath(targetPath: string): string | undefined {\n\tconst normalizedTarget = normalizePathPart(targetPath);\n\tconst joined = normalizedTarget.startsWith(\"/\")\n\t\t? path.posix.normalize(normalizedTarget.replace(/^\\/+/, \"\"))\n\t\t: path.posix.normalize(path.posix.join(CHANGELOG_LINK_BASE_PATH, normalizedTarget));\n\n\tif (joined === \".\" || joined.startsWith(\"../\") || joined === \"..\") {\n\t\treturn undefined;\n\t}\n\n\treturn joined;\n}\n\nfunction isDirectoryTarget(originalPath: string, repositoryPath: string): boolean {\n\tif (originalPath.endsWith(\"/\")) {\n\t\treturn true;\n\t}\n\n\tconst basename = path.posix.basename(repositoryPath);\n\treturn !basename.includes(\".\");\n}\n\nfunction normalizeChangelogLinkTarget(target: string, tag: string): string {\n\tlet canonicalTarget = target.replace(LEGACY_REPO_RE, `https://github.com/${GITHUB_REPO}`);\n\tconst repoUrl = `https://github.com/${GITHUB_REPO}`;\n\n\tfor (const route of [\"blob\", \"tree\"]) {\n\t\tfor (const branch of [\"main\", \"master\"]) {\n\t\t\tconst floatingRefPrefix = `${repoUrl}/${route}/${branch}/`;\n\t\t\tif (canonicalTarget.startsWith(floatingRefPrefix)) {\n\t\t\t\tcanonicalTarget = `${repoUrl}/${route}/${tag}/${canonicalTarget.slice(floatingRefPrefix.length)}`;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (canonicalTarget.startsWith(\"#\") || canonicalTarget.startsWith(\"//\") || URL_SCHEME_RE.test(canonicalTarget)) {\n\t\treturn canonicalTarget;\n\t}\n\n\tconst { fragment, pathPart, query } = splitLocalTarget(canonicalTarget);\n\tif (!pathPart) {\n\t\treturn canonicalTarget;\n\t}\n\n\tconst repositoryPath = resolveRepositoryPath(pathPart);\n\tif (!repositoryPath) {\n\t\treturn canonicalTarget;\n\t}\n\n\tconst route = isDirectoryTarget(pathPart, repositoryPath) ? \"tree\" : \"blob\";\n\treturn `https://github.com/${GITHUB_REPO}/${route}/${tag}/${encodeURI(repositoryPath)}${query}${fragment}`;\n}\n\nexport function normalizeChangelogLinks(markdown: string, version: string | ChangelogEntry): string {\n\tconst tag = normalizeTag(version);\n\treturn markdown.replace(INLINE_MARKDOWN_LINK_RE, (_match, prefix, target, suffix) => {\n\t\treturn `${prefix}${normalizeChangelogLinkTarget(target, tag)}${suffix}`;\n\t});\n}\n\n/**\n * Parse changelog entries from CHANGELOG.md\n * Scans for ## lines and collects content until next ## or EOF\n */\nexport function parseChangelog(changelogPath: string): ChangelogEntry[] {\n\tif (!existsSync(changelogPath)) {\n\t\treturn [];\n\t}\n\n\ttry {\n\t\tconst content = readFileSync(changelogPath, \"utf-8\");\n\t\tconst lines = content.split(\"\\n\");\n\t\tconst entries: ChangelogEntry[] = [];\n\n\t\tlet currentLines: string[] = [];\n\t\tlet currentVersion: { major: number; minor: number; patch: number } | null = null;\n\n\t\tfor (const line of lines) {\n\t\t\t// Check if this is a version header (## [x.y.z] ...)\n\t\t\tif (line.startsWith(\"## \")) {\n\t\t\t\t// Save previous entry if exists\n\t\t\t\tif (currentVersion && currentLines.length > 0) {\n\t\t\t\t\tentries.push({\n\t\t\t\t\t\t...currentVersion,\n\t\t\t\t\t\tcontent: currentLines.join(\"\\n\").trim(),\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\t// Try to parse version from this line\n\t\t\t\tconst versionMatch = line.match(/##\\s+\\[?(\\d+)\\.(\\d+)\\.(\\d+)\\]?/);\n\t\t\t\tif (versionMatch) {\n\t\t\t\t\tcurrentVersion = {\n\t\t\t\t\t\tmajor: Number.parseInt(versionMatch[1], 10),\n\t\t\t\t\t\tminor: Number.parseInt(versionMatch[2], 10),\n\t\t\t\t\t\tpatch: Number.parseInt(versionMatch[3], 10),\n\t\t\t\t\t};\n\t\t\t\t\tcurrentLines = [line];\n\t\t\t\t} else {\n\t\t\t\t\t// Reset if we can't parse version\n\t\t\t\t\tcurrentVersion = null;\n\t\t\t\t\tcurrentLines = [];\n\t\t\t\t}\n\t\t\t} else if (currentVersion) {\n\t\t\t\t// Collect lines for current version\n\t\t\t\tcurrentLines.push(line);\n\t\t\t}\n\t\t}\n\n\t\t// Save last entry\n\t\tif (currentVersion && currentLines.length > 0) {\n\t\t\tentries.push({\n\t\t\t\t...currentVersion,\n\t\t\t\tcontent: currentLines.join(\"\\n\").trim(),\n\t\t\t});\n\t\t}\n\n\t\treturn entries;\n\t} catch (error) {\n\t\tconsole.error(`Warning: Could not parse changelog: ${error}`);\n\t\treturn [];\n\t}\n}\n\n/**\n * Compare versions. Returns: -1 if v1 < v2, 0 if v1 === v2, 1 if v1 > v2\n */\nexport function compareVersions(v1: ChangelogEntry, v2: ChangelogEntry): number {\n\tif (v1.major !== v2.major) return v1.major - v2.major;\n\tif (v1.minor !== v2.minor) return v1.minor - v2.minor;\n\treturn v1.patch - v2.patch;\n}\n\n/**\n * Get entries newer than lastVersion\n */\nexport function getNewEntries(entries: ChangelogEntry[], lastVersion: string): ChangelogEntry[] {\n\t// Parse lastVersion\n\tconst parts = lastVersion.split(\".\").map(Number);\n\tconst last: ChangelogEntry = {\n\t\tmajor: parts[0] || 0,\n\t\tminor: parts[1] || 0,\n\t\tpatch: parts[2] || 0,\n\t\tcontent: \"\",\n\t};\n\n\treturn entries.filter((entry) => compareVersions(entry, last) > 0);\n}\n\n// Re-export getChangelogPath from paths.ts for convenience\nexport { getChangelogPath } from \"../config.ts\";\n\n// ---------------------------------------------------------------------------\n// Startup digest + pager blocks (设计 docs/design/版本新特性面板与Changelog分页.md).\n// The changelog files stay the authoritative record; these functions only shape\n// what the TUI renders so a wall-of-text entry cannot flood the scrollback.\n// ---------------------------------------------------------------------------\n\nexport interface ChangelogDigestOptionsV1 {\n\t/** Max condensed body lines per version (subsection headers + bullets). */\n\treadonly maxLinesPerVersion: number;\n\t/** Max characters per bullet before hard truncation with an ellipsis. */\n\treadonly maxBulletChars: number;\n\t/** Max versions rendered; older new entries collapse into one hint line. */\n\treadonly maxVersions: number;\n\t/** Renders the hint line for versions omitted by maxVersions. */\n\treadonly moreHint: (count: number) => string;\n}\n\nexport const DEFAULT_CHANGELOG_DIGEST_OPTIONS_V1: ChangelogDigestOptionsV1 = {\n\tmaxLinesPerVersion: 12,\n\tmaxBulletChars: 160,\n\tmaxVersions: 5,\n\tmoreHint: (count) => `… ${count} more version(s) — use /changelog for the full history.`,\n};\n\n/**\n * End-of-sentence cut: `.!?` only when followed by a capital/backtick/markup\n * start (so \"e.g. memory's\" does not cut) or at end of text; CJK terminators\n * always cut.\n */\nconst SENTENCE_END_RE = /(?:[.!?](?=\\s+[A-Z`*[\\d])|[.!?](?=$)|[。!?])/;\n\nfunction firstSentence(text: string, maxChars: number): string {\n\tconst match = SENTENCE_END_RE.exec(text);\n\tif (match !== null) {\n\t\tconst sentence = text.slice(0, match.index + match[0].length);\n\t\tif (sentence.length <= maxChars) return sentence;\n\t}\n\tif (text.length <= maxChars) return text;\n\treturn `${text.slice(0, maxChars - 1).trimEnd()}…`;\n}\n\nfunction isFillerLine(line: string): boolean {\n\tconst trimmed = line.trim();\n\treturn trimmed === \"\" || trimmed.startsWith(\"## \");\n}\n\n/**\n * Condense parsed entries into the startup What's-New markdown: empty version\n * sections are dropped, bullets reduce to their first sentence, and per-version\n * / total-version caps keep the panel bounded regardless of entry size.\n */\nexport function condenseChangelogEntriesV1(\n\tentries: readonly ChangelogEntry[],\n\toptions: ChangelogDigestOptionsV1 = DEFAULT_CHANGELOG_DIGEST_OPTIONS_V1,\n): string {\n\tconst parts: string[] = [];\n\tlet renderedVersions = 0;\n\tfor (const entry of entries.slice(0, options.maxVersions)) {\n\t\tconst lines = entry.content.split(\"\\n\");\n\t\tconst header = lines[0]?.trim() || `## [${entryVersion(entry)}]`;\n\t\tconst body: string[] = [];\n\t\tfor (const rawLine of lines.slice(1)) {\n\t\t\tconst trimmed = rawLine.trim();\n\t\t\tif (isFillerLine(rawLine)) continue;\n\t\t\tconst text = trimmed.startsWith(\"- \") ? trimmed.slice(2) : trimmed;\n\t\t\tif (text === \"\") continue;\n\t\t\tif (trimmed.startsWith(\"### \")) {\n\t\t\t\tif (body.length > 0) body.push(\"\");\n\t\t\t\tbody.push(trimmed);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (body.length >= options.maxLinesPerVersion) {\n\t\t\t\tbody.push(\"…\");\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tbody.push(`- ${firstSentence(text, options.maxBulletChars)}`);\n\t\t}\n\t\t// A version whose body never leaves the header is an empty release\n\t\t// section (v0.88.5); a bare version header carries no information.\n\t\tif (body.length === 0) continue;\n\t\tif (renderedVersions > 0) parts.push(\"\");\n\t\tparts.push(header, ...body);\n\t\trenderedVersions++;\n\t}\n\tconst omitted = Math.max(0, entries.length - options.maxVersions);\n\tif (omitted > 0) {\n\t\tif (parts.length > 0) parts.push(\"\");\n\t\tparts.push(options.moreHint(omitted));\n\t}\n\treturn parts.join(\"\\n\");\n}\n\nexport interface ChangelogPagerBlockV1 {\n\treadonly kind: \"version-header\" | \"markdown\";\n\treadonly markdown: string;\n}\n\n/**\n * Split entries into pager blocks: one header block per version plus one\n * markdown block per subsection (`### …` to the next subsection), so the pager\n * renders lazily block by block instead of the whole history at once.\n */\nexport function splitChangelogPagerBlocksV1(entries: readonly ChangelogEntry[]): readonly ChangelogPagerBlockV1[] {\n\tconst blocks: ChangelogPagerBlockV1[] = [];\n\tfor (const entry of entries) {\n\t\tconst lines = entry.content.split(\"\\n\");\n\t\tconst rest = lines.slice(1);\n\t\tif (rest.every((line) => line.trim() === \"\")) continue;\n\t\tconst header = lines[0]?.trim();\n\t\tif (header !== undefined && header !== \"\") {\n\t\t\tblocks.push({ kind: \"version-header\", markdown: header });\n\t\t}\n\t\tlet current: string[] = [];\n\t\tconst flush = (): void => {\n\t\t\tconst markdown = current.join(\"\\n\").trim();\n\t\t\tcurrent = [];\n\t\t\tif (markdown !== \"\") blocks.push({ kind: \"markdown\", markdown });\n\t\t};\n\t\tfor (const line of rest) {\n\t\t\tif (line.trimStart().startsWith(\"### \")) {\n\t\t\t\tflush();\n\t\t\t\tcurrent.push(line);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tcurrent.push(line);\n\t\t}\n\t\tflush();\n\t}\n\treturn blocks;\n}\n"]}
@@ -162,4 +162,114 @@ export function getNewEntries(entries, lastVersion) {
162
162
  }
163
163
  // Re-export getChangelogPath from paths.ts for convenience
164
164
  export { getChangelogPath } from "../config.js";
165
+ export const DEFAULT_CHANGELOG_DIGEST_OPTIONS_V1 = {
166
+ maxLinesPerVersion: 12,
167
+ maxBulletChars: 160,
168
+ maxVersions: 5,
169
+ moreHint: (count) => `… ${count} more version(s) — use /changelog for the full history.`,
170
+ };
171
+ /**
172
+ * End-of-sentence cut: `.!?` only when followed by a capital/backtick/markup
173
+ * start (so "e.g. memory's" does not cut) or at end of text; CJK terminators
174
+ * always cut.
175
+ */
176
+ const SENTENCE_END_RE = /(?:[.!?](?=\s+[A-Z`*[\d])|[.!?](?=$)|[。!?])/;
177
+ function firstSentence(text, maxChars) {
178
+ const match = SENTENCE_END_RE.exec(text);
179
+ if (match !== null) {
180
+ const sentence = text.slice(0, match.index + match[0].length);
181
+ if (sentence.length <= maxChars)
182
+ return sentence;
183
+ }
184
+ if (text.length <= maxChars)
185
+ return text;
186
+ return `${text.slice(0, maxChars - 1).trimEnd()}…`;
187
+ }
188
+ function isFillerLine(line) {
189
+ const trimmed = line.trim();
190
+ return trimmed === "" || trimmed.startsWith("## ");
191
+ }
192
+ /**
193
+ * Condense parsed entries into the startup What's-New markdown: empty version
194
+ * sections are dropped, bullets reduce to their first sentence, and per-version
195
+ * / total-version caps keep the panel bounded regardless of entry size.
196
+ */
197
+ export function condenseChangelogEntriesV1(entries, options = DEFAULT_CHANGELOG_DIGEST_OPTIONS_V1) {
198
+ const parts = [];
199
+ let renderedVersions = 0;
200
+ for (const entry of entries.slice(0, options.maxVersions)) {
201
+ const lines = entry.content.split("\n");
202
+ const header = lines[0]?.trim() || `## [${entryVersion(entry)}]`;
203
+ const body = [];
204
+ for (const rawLine of lines.slice(1)) {
205
+ const trimmed = rawLine.trim();
206
+ if (isFillerLine(rawLine))
207
+ continue;
208
+ const text = trimmed.startsWith("- ") ? trimmed.slice(2) : trimmed;
209
+ if (text === "")
210
+ continue;
211
+ if (trimmed.startsWith("### ")) {
212
+ if (body.length > 0)
213
+ body.push("");
214
+ body.push(trimmed);
215
+ continue;
216
+ }
217
+ if (body.length >= options.maxLinesPerVersion) {
218
+ body.push("…");
219
+ break;
220
+ }
221
+ body.push(`- ${firstSentence(text, options.maxBulletChars)}`);
222
+ }
223
+ // A version whose body never leaves the header is an empty release
224
+ // section (v0.88.5); a bare version header carries no information.
225
+ if (body.length === 0)
226
+ continue;
227
+ if (renderedVersions > 0)
228
+ parts.push("");
229
+ parts.push(header, ...body);
230
+ renderedVersions++;
231
+ }
232
+ const omitted = Math.max(0, entries.length - options.maxVersions);
233
+ if (omitted > 0) {
234
+ if (parts.length > 0)
235
+ parts.push("");
236
+ parts.push(options.moreHint(omitted));
237
+ }
238
+ return parts.join("\n");
239
+ }
240
+ /**
241
+ * Split entries into pager blocks: one header block per version plus one
242
+ * markdown block per subsection (`### …` to the next subsection), so the pager
243
+ * renders lazily block by block instead of the whole history at once.
244
+ */
245
+ export function splitChangelogPagerBlocksV1(entries) {
246
+ const blocks = [];
247
+ for (const entry of entries) {
248
+ const lines = entry.content.split("\n");
249
+ const rest = lines.slice(1);
250
+ if (rest.every((line) => line.trim() === ""))
251
+ continue;
252
+ const header = lines[0]?.trim();
253
+ if (header !== undefined && header !== "") {
254
+ blocks.push({ kind: "version-header", markdown: header });
255
+ }
256
+ let current = [];
257
+ const flush = () => {
258
+ const markdown = current.join("\n").trim();
259
+ current = [];
260
+ if (markdown !== "")
261
+ blocks.push({ kind: "markdown", markdown });
262
+ };
263
+ for (const line of rest) {
264
+ if (line.trimStart().startsWith("### ")) {
265
+ flush();
266
+ current.push(line);
267
+ continue;
268
+ }
269
+ current.push(line);
270
+ }
271
+ flush();
272
+ }
273
+ return blocks;
274
+ }
165
275
  //# sourceMappingURL=changelog.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"changelog.js","sourceRoot":"","sources":["../../src/utils/changelog.ts"],"names":[],"mappings":"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","sourcesContent":["import path from \"node:path\";\nimport { existsSync, readFileSync } from \"fs\";\n\nexport interface ChangelogEntry {\n\tmajor: number;\n\tminor: number;\n\tpatch: number;\n\tcontent: string;\n}\n\nconst GITHUB_REPO = process.env.AGENT_FORGE_GITHUB_REPO || \"agent-forge/agent-forge\";\nconst CHANGELOG_LINK_BASE_PATH = \"packages/agent-forge\";\nconst LEGACY_REPO_RE = /^https:\\/\\/github\\.com\\/(?:badlogic|earendil-works)\\/(?:pi-mono|pi)(?=\\/|$)/;\nconst URL_SCHEME_RE = /^[a-z][a-z0-9+.-]*:/i;\nconst INLINE_MARKDOWN_LINK_RE = /(!?\\[[^\\]\\n]+\\]\\()([^\\s)]+)((?:\\s+[^)]*)?\\))/g;\n\nfunction entryVersion(entry: ChangelogEntry): string {\n\treturn `${entry.major}.${entry.minor}.${entry.patch}`;\n}\n\nfunction normalizeTag(version: string | ChangelogEntry): string {\n\tconst versionString = typeof version === \"string\" ? version : entryVersion(version);\n\treturn versionString.startsWith(\"v\") ? versionString : `v${versionString}`;\n}\n\nfunction splitLocalTarget(target: string): { fragment: string; pathPart: string; query: string } {\n\tconst hashIndex = target.indexOf(\"#\");\n\tconst beforeHash = hashIndex === -1 ? target : target.slice(0, hashIndex);\n\tconst fragment = hashIndex === -1 ? \"\" : target.slice(hashIndex);\n\tconst queryIndex = beforeHash.indexOf(\"?\");\n\n\tif (queryIndex === -1) {\n\t\treturn { fragment, pathPart: beforeHash, query: \"\" };\n\t}\n\n\treturn {\n\t\tfragment,\n\t\tpathPart: beforeHash.slice(0, queryIndex),\n\t\tquery: beforeHash.slice(queryIndex),\n\t};\n}\n\nfunction normalizePathPart(value: string): string {\n\treturn value.replaceAll(\"\\\\\", \"/\");\n}\n\nfunction resolveRepositoryPath(targetPath: string): string | undefined {\n\tconst normalizedTarget = normalizePathPart(targetPath);\n\tconst joined = normalizedTarget.startsWith(\"/\")\n\t\t? path.posix.normalize(normalizedTarget.replace(/^\\/+/, \"\"))\n\t\t: path.posix.normalize(path.posix.join(CHANGELOG_LINK_BASE_PATH, normalizedTarget));\n\n\tif (joined === \".\" || joined.startsWith(\"../\") || joined === \"..\") {\n\t\treturn undefined;\n\t}\n\n\treturn joined;\n}\n\nfunction isDirectoryTarget(originalPath: string, repositoryPath: string): boolean {\n\tif (originalPath.endsWith(\"/\")) {\n\t\treturn true;\n\t}\n\n\tconst basename = path.posix.basename(repositoryPath);\n\treturn !basename.includes(\".\");\n}\n\nfunction normalizeChangelogLinkTarget(target: string, tag: string): string {\n\tlet canonicalTarget = target.replace(LEGACY_REPO_RE, `https://github.com/${GITHUB_REPO}`);\n\tconst repoUrl = `https://github.com/${GITHUB_REPO}`;\n\n\tfor (const route of [\"blob\", \"tree\"]) {\n\t\tfor (const branch of [\"main\", \"master\"]) {\n\t\t\tconst floatingRefPrefix = `${repoUrl}/${route}/${branch}/`;\n\t\t\tif (canonicalTarget.startsWith(floatingRefPrefix)) {\n\t\t\t\tcanonicalTarget = `${repoUrl}/${route}/${tag}/${canonicalTarget.slice(floatingRefPrefix.length)}`;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (canonicalTarget.startsWith(\"#\") || canonicalTarget.startsWith(\"//\") || URL_SCHEME_RE.test(canonicalTarget)) {\n\t\treturn canonicalTarget;\n\t}\n\n\tconst { fragment, pathPart, query } = splitLocalTarget(canonicalTarget);\n\tif (!pathPart) {\n\t\treturn canonicalTarget;\n\t}\n\n\tconst repositoryPath = resolveRepositoryPath(pathPart);\n\tif (!repositoryPath) {\n\t\treturn canonicalTarget;\n\t}\n\n\tconst route = isDirectoryTarget(pathPart, repositoryPath) ? \"tree\" : \"blob\";\n\treturn `https://github.com/${GITHUB_REPO}/${route}/${tag}/${encodeURI(repositoryPath)}${query}${fragment}`;\n}\n\nexport function normalizeChangelogLinks(markdown: string, version: string | ChangelogEntry): string {\n\tconst tag = normalizeTag(version);\n\treturn markdown.replace(INLINE_MARKDOWN_LINK_RE, (_match, prefix, target, suffix) => {\n\t\treturn `${prefix}${normalizeChangelogLinkTarget(target, tag)}${suffix}`;\n\t});\n}\n\n/**\n * Parse changelog entries from CHANGELOG.md\n * Scans for ## lines and collects content until next ## or EOF\n */\nexport function parseChangelog(changelogPath: string): ChangelogEntry[] {\n\tif (!existsSync(changelogPath)) {\n\t\treturn [];\n\t}\n\n\ttry {\n\t\tconst content = readFileSync(changelogPath, \"utf-8\");\n\t\tconst lines = content.split(\"\\n\");\n\t\tconst entries: ChangelogEntry[] = [];\n\n\t\tlet currentLines: string[] = [];\n\t\tlet currentVersion: { major: number; minor: number; patch: number } | null = null;\n\n\t\tfor (const line of lines) {\n\t\t\t// Check if this is a version header (## [x.y.z] ...)\n\t\t\tif (line.startsWith(\"## \")) {\n\t\t\t\t// Save previous entry if exists\n\t\t\t\tif (currentVersion && currentLines.length > 0) {\n\t\t\t\t\tentries.push({\n\t\t\t\t\t\t...currentVersion,\n\t\t\t\t\t\tcontent: currentLines.join(\"\\n\").trim(),\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\t// Try to parse version from this line\n\t\t\t\tconst versionMatch = line.match(/##\\s+\\[?(\\d+)\\.(\\d+)\\.(\\d+)\\]?/);\n\t\t\t\tif (versionMatch) {\n\t\t\t\t\tcurrentVersion = {\n\t\t\t\t\t\tmajor: Number.parseInt(versionMatch[1], 10),\n\t\t\t\t\t\tminor: Number.parseInt(versionMatch[2], 10),\n\t\t\t\t\t\tpatch: Number.parseInt(versionMatch[3], 10),\n\t\t\t\t\t};\n\t\t\t\t\tcurrentLines = [line];\n\t\t\t\t} else {\n\t\t\t\t\t// Reset if we can't parse version\n\t\t\t\t\tcurrentVersion = null;\n\t\t\t\t\tcurrentLines = [];\n\t\t\t\t}\n\t\t\t} else if (currentVersion) {\n\t\t\t\t// Collect lines for current version\n\t\t\t\tcurrentLines.push(line);\n\t\t\t}\n\t\t}\n\n\t\t// Save last entry\n\t\tif (currentVersion && currentLines.length > 0) {\n\t\t\tentries.push({\n\t\t\t\t...currentVersion,\n\t\t\t\tcontent: currentLines.join(\"\\n\").trim(),\n\t\t\t});\n\t\t}\n\n\t\treturn entries;\n\t} catch (error) {\n\t\tconsole.error(`Warning: Could not parse changelog: ${error}`);\n\t\treturn [];\n\t}\n}\n\n/**\n * Compare versions. Returns: -1 if v1 < v2, 0 if v1 === v2, 1 if v1 > v2\n */\nexport function compareVersions(v1: ChangelogEntry, v2: ChangelogEntry): number {\n\tif (v1.major !== v2.major) return v1.major - v2.major;\n\tif (v1.minor !== v2.minor) return v1.minor - v2.minor;\n\treturn v1.patch - v2.patch;\n}\n\n/**\n * Get entries newer than lastVersion\n */\nexport function getNewEntries(entries: ChangelogEntry[], lastVersion: string): ChangelogEntry[] {\n\t// Parse lastVersion\n\tconst parts = lastVersion.split(\".\").map(Number);\n\tconst last: ChangelogEntry = {\n\t\tmajor: parts[0] || 0,\n\t\tminor: parts[1] || 0,\n\t\tpatch: parts[2] || 0,\n\t\tcontent: \"\",\n\t};\n\n\treturn entries.filter((entry) => compareVersions(entry, last) > 0);\n}\n\n// Re-export getChangelogPath from paths.ts for convenience\nexport { getChangelogPath } from \"../config.ts\";\n"]}
1
+ {"version":3,"file":"changelog.js","sourceRoot":"","sources":["../../src/utils/changelog.ts"],"names":[],"mappings":"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","sourcesContent":["import path from \"node:path\";\nimport { existsSync, readFileSync } from \"fs\";\n\nexport interface ChangelogEntry {\n\tmajor: number;\n\tminor: number;\n\tpatch: number;\n\tcontent: string;\n}\n\nconst GITHUB_REPO = process.env.AGENT_FORGE_GITHUB_REPO || \"agent-forge/agent-forge\";\nconst CHANGELOG_LINK_BASE_PATH = \"packages/agent-forge\";\nconst LEGACY_REPO_RE = /^https:\\/\\/github\\.com\\/(?:badlogic|earendil-works)\\/(?:pi-mono|pi)(?=\\/|$)/;\nconst URL_SCHEME_RE = /^[a-z][a-z0-9+.-]*:/i;\nconst INLINE_MARKDOWN_LINK_RE = /(!?\\[[^\\]\\n]+\\]\\()([^\\s)]+)((?:\\s+[^)]*)?\\))/g;\n\nfunction entryVersion(entry: ChangelogEntry): string {\n\treturn `${entry.major}.${entry.minor}.${entry.patch}`;\n}\n\nfunction normalizeTag(version: string | ChangelogEntry): string {\n\tconst versionString = typeof version === \"string\" ? version : entryVersion(version);\n\treturn versionString.startsWith(\"v\") ? versionString : `v${versionString}`;\n}\n\nfunction splitLocalTarget(target: string): { fragment: string; pathPart: string; query: string } {\n\tconst hashIndex = target.indexOf(\"#\");\n\tconst beforeHash = hashIndex === -1 ? target : target.slice(0, hashIndex);\n\tconst fragment = hashIndex === -1 ? \"\" : target.slice(hashIndex);\n\tconst queryIndex = beforeHash.indexOf(\"?\");\n\n\tif (queryIndex === -1) {\n\t\treturn { fragment, pathPart: beforeHash, query: \"\" };\n\t}\n\n\treturn {\n\t\tfragment,\n\t\tpathPart: beforeHash.slice(0, queryIndex),\n\t\tquery: beforeHash.slice(queryIndex),\n\t};\n}\n\nfunction normalizePathPart(value: string): string {\n\treturn value.replaceAll(\"\\\\\", \"/\");\n}\n\nfunction resolveRepositoryPath(targetPath: string): string | undefined {\n\tconst normalizedTarget = normalizePathPart(targetPath);\n\tconst joined = normalizedTarget.startsWith(\"/\")\n\t\t? path.posix.normalize(normalizedTarget.replace(/^\\/+/, \"\"))\n\t\t: path.posix.normalize(path.posix.join(CHANGELOG_LINK_BASE_PATH, normalizedTarget));\n\n\tif (joined === \".\" || joined.startsWith(\"../\") || joined === \"..\") {\n\t\treturn undefined;\n\t}\n\n\treturn joined;\n}\n\nfunction isDirectoryTarget(originalPath: string, repositoryPath: string): boolean {\n\tif (originalPath.endsWith(\"/\")) {\n\t\treturn true;\n\t}\n\n\tconst basename = path.posix.basename(repositoryPath);\n\treturn !basename.includes(\".\");\n}\n\nfunction normalizeChangelogLinkTarget(target: string, tag: string): string {\n\tlet canonicalTarget = target.replace(LEGACY_REPO_RE, `https://github.com/${GITHUB_REPO}`);\n\tconst repoUrl = `https://github.com/${GITHUB_REPO}`;\n\n\tfor (const route of [\"blob\", \"tree\"]) {\n\t\tfor (const branch of [\"main\", \"master\"]) {\n\t\t\tconst floatingRefPrefix = `${repoUrl}/${route}/${branch}/`;\n\t\t\tif (canonicalTarget.startsWith(floatingRefPrefix)) {\n\t\t\t\tcanonicalTarget = `${repoUrl}/${route}/${tag}/${canonicalTarget.slice(floatingRefPrefix.length)}`;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (canonicalTarget.startsWith(\"#\") || canonicalTarget.startsWith(\"//\") || URL_SCHEME_RE.test(canonicalTarget)) {\n\t\treturn canonicalTarget;\n\t}\n\n\tconst { fragment, pathPart, query } = splitLocalTarget(canonicalTarget);\n\tif (!pathPart) {\n\t\treturn canonicalTarget;\n\t}\n\n\tconst repositoryPath = resolveRepositoryPath(pathPart);\n\tif (!repositoryPath) {\n\t\treturn canonicalTarget;\n\t}\n\n\tconst route = isDirectoryTarget(pathPart, repositoryPath) ? \"tree\" : \"blob\";\n\treturn `https://github.com/${GITHUB_REPO}/${route}/${tag}/${encodeURI(repositoryPath)}${query}${fragment}`;\n}\n\nexport function normalizeChangelogLinks(markdown: string, version: string | ChangelogEntry): string {\n\tconst tag = normalizeTag(version);\n\treturn markdown.replace(INLINE_MARKDOWN_LINK_RE, (_match, prefix, target, suffix) => {\n\t\treturn `${prefix}${normalizeChangelogLinkTarget(target, tag)}${suffix}`;\n\t});\n}\n\n/**\n * Parse changelog entries from CHANGELOG.md\n * Scans for ## lines and collects content until next ## or EOF\n */\nexport function parseChangelog(changelogPath: string): ChangelogEntry[] {\n\tif (!existsSync(changelogPath)) {\n\t\treturn [];\n\t}\n\n\ttry {\n\t\tconst content = readFileSync(changelogPath, \"utf-8\");\n\t\tconst lines = content.split(\"\\n\");\n\t\tconst entries: ChangelogEntry[] = [];\n\n\t\tlet currentLines: string[] = [];\n\t\tlet currentVersion: { major: number; minor: number; patch: number } | null = null;\n\n\t\tfor (const line of lines) {\n\t\t\t// Check if this is a version header (## [x.y.z] ...)\n\t\t\tif (line.startsWith(\"## \")) {\n\t\t\t\t// Save previous entry if exists\n\t\t\t\tif (currentVersion && currentLines.length > 0) {\n\t\t\t\t\tentries.push({\n\t\t\t\t\t\t...currentVersion,\n\t\t\t\t\t\tcontent: currentLines.join(\"\\n\").trim(),\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\t// Try to parse version from this line\n\t\t\t\tconst versionMatch = line.match(/##\\s+\\[?(\\d+)\\.(\\d+)\\.(\\d+)\\]?/);\n\t\t\t\tif (versionMatch) {\n\t\t\t\t\tcurrentVersion = {\n\t\t\t\t\t\tmajor: Number.parseInt(versionMatch[1], 10),\n\t\t\t\t\t\tminor: Number.parseInt(versionMatch[2], 10),\n\t\t\t\t\t\tpatch: Number.parseInt(versionMatch[3], 10),\n\t\t\t\t\t};\n\t\t\t\t\tcurrentLines = [line];\n\t\t\t\t} else {\n\t\t\t\t\t// Reset if we can't parse version\n\t\t\t\t\tcurrentVersion = null;\n\t\t\t\t\tcurrentLines = [];\n\t\t\t\t}\n\t\t\t} else if (currentVersion) {\n\t\t\t\t// Collect lines for current version\n\t\t\t\tcurrentLines.push(line);\n\t\t\t}\n\t\t}\n\n\t\t// Save last entry\n\t\tif (currentVersion && currentLines.length > 0) {\n\t\t\tentries.push({\n\t\t\t\t...currentVersion,\n\t\t\t\tcontent: currentLines.join(\"\\n\").trim(),\n\t\t\t});\n\t\t}\n\n\t\treturn entries;\n\t} catch (error) {\n\t\tconsole.error(`Warning: Could not parse changelog: ${error}`);\n\t\treturn [];\n\t}\n}\n\n/**\n * Compare versions. Returns: -1 if v1 < v2, 0 if v1 === v2, 1 if v1 > v2\n */\nexport function compareVersions(v1: ChangelogEntry, v2: ChangelogEntry): number {\n\tif (v1.major !== v2.major) return v1.major - v2.major;\n\tif (v1.minor !== v2.minor) return v1.minor - v2.minor;\n\treturn v1.patch - v2.patch;\n}\n\n/**\n * Get entries newer than lastVersion\n */\nexport function getNewEntries(entries: ChangelogEntry[], lastVersion: string): ChangelogEntry[] {\n\t// Parse lastVersion\n\tconst parts = lastVersion.split(\".\").map(Number);\n\tconst last: ChangelogEntry = {\n\t\tmajor: parts[0] || 0,\n\t\tminor: parts[1] || 0,\n\t\tpatch: parts[2] || 0,\n\t\tcontent: \"\",\n\t};\n\n\treturn entries.filter((entry) => compareVersions(entry, last) > 0);\n}\n\n// Re-export getChangelogPath from paths.ts for convenience\nexport { getChangelogPath } from \"../config.ts\";\n\n// ---------------------------------------------------------------------------\n// Startup digest + pager blocks (设计 docs/design/版本新特性面板与Changelog分页.md).\n// The changelog files stay the authoritative record; these functions only shape\n// what the TUI renders so a wall-of-text entry cannot flood the scrollback.\n// ---------------------------------------------------------------------------\n\nexport interface ChangelogDigestOptionsV1 {\n\t/** Max condensed body lines per version (subsection headers + bullets). */\n\treadonly maxLinesPerVersion: number;\n\t/** Max characters per bullet before hard truncation with an ellipsis. */\n\treadonly maxBulletChars: number;\n\t/** Max versions rendered; older new entries collapse into one hint line. */\n\treadonly maxVersions: number;\n\t/** Renders the hint line for versions omitted by maxVersions. */\n\treadonly moreHint: (count: number) => string;\n}\n\nexport const DEFAULT_CHANGELOG_DIGEST_OPTIONS_V1: ChangelogDigestOptionsV1 = {\n\tmaxLinesPerVersion: 12,\n\tmaxBulletChars: 160,\n\tmaxVersions: 5,\n\tmoreHint: (count) => `… ${count} more version(s) — use /changelog for the full history.`,\n};\n\n/**\n * End-of-sentence cut: `.!?` only when followed by a capital/backtick/markup\n * start (so \"e.g. memory's\" does not cut) or at end of text; CJK terminators\n * always cut.\n */\nconst SENTENCE_END_RE = /(?:[.!?](?=\\s+[A-Z`*[\\d])|[.!?](?=$)|[。!?])/;\n\nfunction firstSentence(text: string, maxChars: number): string {\n\tconst match = SENTENCE_END_RE.exec(text);\n\tif (match !== null) {\n\t\tconst sentence = text.slice(0, match.index + match[0].length);\n\t\tif (sentence.length <= maxChars) return sentence;\n\t}\n\tif (text.length <= maxChars) return text;\n\treturn `${text.slice(0, maxChars - 1).trimEnd()}…`;\n}\n\nfunction isFillerLine(line: string): boolean {\n\tconst trimmed = line.trim();\n\treturn trimmed === \"\" || trimmed.startsWith(\"## \");\n}\n\n/**\n * Condense parsed entries into the startup What's-New markdown: empty version\n * sections are dropped, bullets reduce to their first sentence, and per-version\n * / total-version caps keep the panel bounded regardless of entry size.\n */\nexport function condenseChangelogEntriesV1(\n\tentries: readonly ChangelogEntry[],\n\toptions: ChangelogDigestOptionsV1 = DEFAULT_CHANGELOG_DIGEST_OPTIONS_V1,\n): string {\n\tconst parts: string[] = [];\n\tlet renderedVersions = 0;\n\tfor (const entry of entries.slice(0, options.maxVersions)) {\n\t\tconst lines = entry.content.split(\"\\n\");\n\t\tconst header = lines[0]?.trim() || `## [${entryVersion(entry)}]`;\n\t\tconst body: string[] = [];\n\t\tfor (const rawLine of lines.slice(1)) {\n\t\t\tconst trimmed = rawLine.trim();\n\t\t\tif (isFillerLine(rawLine)) continue;\n\t\t\tconst text = trimmed.startsWith(\"- \") ? trimmed.slice(2) : trimmed;\n\t\t\tif (text === \"\") continue;\n\t\t\tif (trimmed.startsWith(\"### \")) {\n\t\t\t\tif (body.length > 0) body.push(\"\");\n\t\t\t\tbody.push(trimmed);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (body.length >= options.maxLinesPerVersion) {\n\t\t\t\tbody.push(\"…\");\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tbody.push(`- ${firstSentence(text, options.maxBulletChars)}`);\n\t\t}\n\t\t// A version whose body never leaves the header is an empty release\n\t\t// section (v0.88.5); a bare version header carries no information.\n\t\tif (body.length === 0) continue;\n\t\tif (renderedVersions > 0) parts.push(\"\");\n\t\tparts.push(header, ...body);\n\t\trenderedVersions++;\n\t}\n\tconst omitted = Math.max(0, entries.length - options.maxVersions);\n\tif (omitted > 0) {\n\t\tif (parts.length > 0) parts.push(\"\");\n\t\tparts.push(options.moreHint(omitted));\n\t}\n\treturn parts.join(\"\\n\");\n}\n\nexport interface ChangelogPagerBlockV1 {\n\treadonly kind: \"version-header\" | \"markdown\";\n\treadonly markdown: string;\n}\n\n/**\n * Split entries into pager blocks: one header block per version plus one\n * markdown block per subsection (`### …` to the next subsection), so the pager\n * renders lazily block by block instead of the whole history at once.\n */\nexport function splitChangelogPagerBlocksV1(entries: readonly ChangelogEntry[]): readonly ChangelogPagerBlockV1[] {\n\tconst blocks: ChangelogPagerBlockV1[] = [];\n\tfor (const entry of entries) {\n\t\tconst lines = entry.content.split(\"\\n\");\n\t\tconst rest = lines.slice(1);\n\t\tif (rest.every((line) => line.trim() === \"\")) continue;\n\t\tconst header = lines[0]?.trim();\n\t\tif (header !== undefined && header !== \"\") {\n\t\t\tblocks.push({ kind: \"version-header\", markdown: header });\n\t\t}\n\t\tlet current: string[] = [];\n\t\tconst flush = (): void => {\n\t\t\tconst markdown = current.join(\"\\n\").trim();\n\t\t\tcurrent = [];\n\t\t\tif (markdown !== \"\") blocks.push({ kind: \"markdown\", markdown });\n\t\t};\n\t\tfor (const line of rest) {\n\t\t\tif (line.trimStart().startsWith(\"### \")) {\n\t\t\t\tflush();\n\t\t\t\tcurrent.push(line);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tcurrent.push(line);\n\t\t}\n\t\tflush();\n\t}\n\treturn blocks;\n}\n"]}
@@ -173,6 +173,20 @@ This routing remains configurable through the ordinary action bindings. For exam
173
173
  | `app.queue.moveDown` | `alt+down` | Move the selected queued message down in `/queue-list` (in-component key of the queue manager, not a feature trigger) |
174
174
  | `app.queue.remove` | `delete` | Delete the selected queued message in `/queue-list` (in-component key of the queue manager, not a feature trigger) |
175
175
 
176
+ ### Changelog Pager
177
+
178
+ In-component keys of the `/changelog` preview overlay (not feature triggers). Search rides the existing `tui.altScreen.search` / `searchNext` / `searchPrevious` bindings (`ctrl+f` opens the search prompt, `enter`/`ctrl+g` jumps to the next match, `shift+enter`/`ctrl+shift+g` to the previous match while a search is active).
179
+
180
+ | Keybinding id | Default | Description |
181
+ |--------|---------|-------------|
182
+ | `app.changelogPager.close` | `escape`, `q` | Close the changelog pager |
183
+ | `app.changelogPager.up` | `up` | Scroll one line up |
184
+ | `app.changelogPager.down` | `down` | Scroll one line down |
185
+ | `app.changelogPager.pageUp` | `pageUp` | Scroll one page up |
186
+ | `app.changelogPager.pageDown` | `pageDown` | Scroll one page down |
187
+ | `app.changelogPager.top` | `home` | Scroll to the top |
188
+ | `app.changelogPager.bottom` | `end` | Scroll to the bottom |
189
+
176
190
  ### Tree Navigation
177
191
 
178
192
  | Keybinding id | Default | Description |
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "agent-forge-extension-with-deps",
3
- "version": "0.88.4",
3
+ "version": "0.88.6",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "agent-forge-extension-with-deps",
9
- "version": "0.88.4",
9
+ "version": "0.88.6",
10
10
  "dependencies": {
11
11
  "ms": "^2.1.3"
12
12
  },
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "agent-forge-extension-with-deps",
3
3
  "private": true,
4
- "version": "0.88.4",
4
+ "version": "0.88.6",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "clean": "echo 'nothing to clean'",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "id": "agent-forge.example.with-deps",
3
- "version": "0.88.4",
3
+ "version": "0.88.6",
4
4
  "hostVersion": ">=0.84.0",
5
5
  "apiVersion": "1-draft",
6
6
  "entry": "./index.ts",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-agent-forge/agent-forge",
3
- "version": "0.88.4",
3
+ "version": "0.88.6",
4
4
  "description": "Coding agent CLI with read, bash, edit, write tools and session management",
5
5
  "type": "module",
6
6
  "agentForgeConfig": {
@@ -1,2 +0,0 @@
1
- import { createRequire as __piCreateRequire } from "node:module"; const require = __piCreateRequire(import.meta.url);
2
- var FifoQueue=class{incoming=[];outgoing=[];get length(){return this.incoming.length+this.outgoing.length}enqueue(value){this.incoming.push(value)}dequeue(){if(this.outgoing.length===0)for(;this.incoming.length>0;)this.outgoing.push(this.incoming.pop());return this.outgoing.pop()}},EventStream=class{queue=new FifoQueue;waiting=new FifoQueue;done=!1;finalResultPromise;resolveFinalResult;isComplete;extractResult;constructor(isComplete,extractResult){this.isComplete=isComplete,this.extractResult=extractResult,this.finalResultPromise=new Promise(resolve=>{this.resolveFinalResult=resolve})}push(event){if(this.done)return;this.isComplete(event)&&(this.done=!0,this.resolveFinalResult(this.extractResult(event)));let waiter=this.waiting.dequeue();waiter?waiter({value:event,done:!1}):this.queue.enqueue(event)}end(result){for(this.done=!0,result!==void 0&&this.resolveFinalResult(result);this.waiting.length>0;)this.waiting.dequeue()({value:void 0,done:!0})}async*[Symbol.asyncIterator](){for(;;)if(this.queue.length>0)yield this.queue.dequeue();else{if(this.done)return;{let result=await new Promise(resolve=>this.waiting.enqueue(resolve));if(result.done)return;yield result.value}}}result(){return this.finalResultPromise}},AssistantMessageEventStream=class extends EventStream{constructor(){super(event=>event.type==="done"||event.type==="error",event=>{if(event.type==="done")return event.message;if(event.type==="error")return event.error;throw new Error("Unexpected event type for final result")})}};function createAssistantMessageEventStream(){return new AssistantMessageEventStream}function formatThrownValue(value){return value instanceof Error?value.message||value.name:typeof value=="string"?value:String(value)}function extractDiagnosticError(error){if(!(error instanceof Error))return{name:"ThrownValue",message:formatThrownValue(error)};let code=error.code;return{name:error.name||void 0,message:error.message||error.name,stack:error.stack,code:typeof code=="string"||typeof code=="number"?code:void 0}}function createAssistantMessageDiagnostic(type,error,details){return{type,timestamp:Date.now(),error:extractDiagnosticError(error),details}}function appendAssistantMessageDiagnostic(message,diagnostic){message.diagnostics=[...message.diagnostics??[],diagnostic]}export{EventStream,AssistantMessageEventStream,createAssistantMessageEventStream,formatThrownValue,extractDiagnosticError,createAssistantMessageDiagnostic,appendAssistantMessageDiagnostic};