@gmickel/gno 0.7.0 → 0.8.1

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 (209) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +90 -50
  3. package/THIRD_PARTY_NOTICES.md +22 -0
  4. package/assets/screenshots/webui-ask-answer.png +0 -0
  5. package/assets/screenshots/webui-collections.png +0 -0
  6. package/assets/screenshots/webui-editor.png +0 -0
  7. package/assets/screenshots/webui-home.png +0 -0
  8. package/assets/skill/SKILL.md +12 -12
  9. package/assets/skill/cli-reference.md +59 -57
  10. package/assets/skill/examples.md +8 -7
  11. package/assets/skill/mcp-reference.md +8 -4
  12. package/package.json +31 -24
  13. package/src/app/constants.ts +43 -42
  14. package/src/cli/colors.ts +1 -1
  15. package/src/cli/commands/ask.ts +44 -43
  16. package/src/cli/commands/cleanup.ts +9 -8
  17. package/src/cli/commands/collection/add.ts +12 -12
  18. package/src/cli/commands/collection/index.ts +4 -4
  19. package/src/cli/commands/collection/list.ts +26 -25
  20. package/src/cli/commands/collection/remove.ts +10 -10
  21. package/src/cli/commands/collection/rename.ts +10 -10
  22. package/src/cli/commands/context/add.ts +1 -1
  23. package/src/cli/commands/context/check.ts +17 -17
  24. package/src/cli/commands/context/index.ts +4 -4
  25. package/src/cli/commands/context/list.ts +11 -11
  26. package/src/cli/commands/context/rm.ts +1 -1
  27. package/src/cli/commands/doctor.ts +86 -84
  28. package/src/cli/commands/embed.ts +30 -28
  29. package/src/cli/commands/get.ts +27 -26
  30. package/src/cli/commands/index-cmd.ts +9 -9
  31. package/src/cli/commands/index.ts +16 -16
  32. package/src/cli/commands/init.ts +13 -12
  33. package/src/cli/commands/ls.ts +20 -19
  34. package/src/cli/commands/mcp/config.ts +30 -28
  35. package/src/cli/commands/mcp/index.ts +4 -4
  36. package/src/cli/commands/mcp/install.ts +17 -17
  37. package/src/cli/commands/mcp/paths.ts +133 -133
  38. package/src/cli/commands/mcp/status.ts +21 -21
  39. package/src/cli/commands/mcp/uninstall.ts +13 -13
  40. package/src/cli/commands/mcp.ts +2 -2
  41. package/src/cli/commands/models/clear.ts +12 -11
  42. package/src/cli/commands/models/index.ts +5 -5
  43. package/src/cli/commands/models/list.ts +31 -30
  44. package/src/cli/commands/models/path.ts +1 -1
  45. package/src/cli/commands/models/pull.ts +19 -18
  46. package/src/cli/commands/models/use.ts +4 -4
  47. package/src/cli/commands/multi-get.ts +38 -36
  48. package/src/cli/commands/query.ts +21 -20
  49. package/src/cli/commands/ref-parser.ts +10 -10
  50. package/src/cli/commands/reset.ts +40 -39
  51. package/src/cli/commands/search.ts +14 -13
  52. package/src/cli/commands/serve.ts +4 -4
  53. package/src/cli/commands/shared.ts +11 -10
  54. package/src/cli/commands/skill/index.ts +5 -5
  55. package/src/cli/commands/skill/install.ts +18 -17
  56. package/src/cli/commands/skill/paths-cmd.ts +11 -10
  57. package/src/cli/commands/skill/paths.ts +23 -23
  58. package/src/cli/commands/skill/show.ts +13 -12
  59. package/src/cli/commands/skill/uninstall.ts +16 -15
  60. package/src/cli/commands/status.ts +25 -24
  61. package/src/cli/commands/update.ts +3 -3
  62. package/src/cli/commands/vsearch.ts +17 -16
  63. package/src/cli/context.ts +5 -5
  64. package/src/cli/errors.ts +3 -3
  65. package/src/cli/format/search-results.ts +37 -37
  66. package/src/cli/options.ts +43 -43
  67. package/src/cli/program.ts +455 -459
  68. package/src/cli/progress.ts +1 -1
  69. package/src/cli/run.ts +24 -23
  70. package/src/collection/add.ts +9 -8
  71. package/src/collection/index.ts +3 -3
  72. package/src/collection/remove.ts +7 -6
  73. package/src/collection/types.ts +6 -6
  74. package/src/config/defaults.ts +1 -1
  75. package/src/config/index.ts +5 -5
  76. package/src/config/loader.ts +19 -18
  77. package/src/config/paths.ts +9 -8
  78. package/src/config/saver.ts +14 -13
  79. package/src/config/types.ts +53 -52
  80. package/src/converters/adapters/markitdownTs/adapter.ts +21 -19
  81. package/src/converters/adapters/officeparser/adapter.ts +18 -16
  82. package/src/converters/canonicalize.ts +12 -12
  83. package/src/converters/errors.ts +26 -22
  84. package/src/converters/index.ts +8 -8
  85. package/src/converters/mime.ts +25 -25
  86. package/src/converters/native/markdown.ts +10 -9
  87. package/src/converters/native/plaintext.ts +8 -7
  88. package/src/converters/path.ts +2 -2
  89. package/src/converters/pipeline.ts +11 -10
  90. package/src/converters/registry.ts +8 -8
  91. package/src/converters/types.ts +14 -14
  92. package/src/converters/versions.ts +4 -4
  93. package/src/index.ts +4 -4
  94. package/src/ingestion/chunker.ts +10 -9
  95. package/src/ingestion/index.ts +6 -6
  96. package/src/ingestion/language.ts +62 -62
  97. package/src/ingestion/sync.ts +50 -49
  98. package/src/ingestion/types.ts +10 -10
  99. package/src/ingestion/walker.ts +14 -13
  100. package/src/llm/cache.ts +51 -49
  101. package/src/llm/errors.ts +40 -36
  102. package/src/llm/index.ts +9 -9
  103. package/src/llm/lockfile.ts +6 -6
  104. package/src/llm/nodeLlamaCpp/adapter.ts +13 -12
  105. package/src/llm/nodeLlamaCpp/embedding.ts +9 -8
  106. package/src/llm/nodeLlamaCpp/generation.ts +7 -6
  107. package/src/llm/nodeLlamaCpp/lifecycle.ts +11 -10
  108. package/src/llm/nodeLlamaCpp/rerank.ts +6 -5
  109. package/src/llm/policy.ts +5 -5
  110. package/src/llm/registry.ts +6 -5
  111. package/src/llm/types.ts +2 -2
  112. package/src/mcp/resources/index.ts +15 -13
  113. package/src/mcp/server.ts +25 -23
  114. package/src/mcp/tools/get.ts +25 -23
  115. package/src/mcp/tools/index.ts +32 -29
  116. package/src/mcp/tools/multi-get.ts +34 -32
  117. package/src/mcp/tools/query.ts +29 -27
  118. package/src/mcp/tools/search.ts +14 -12
  119. package/src/mcp/tools/status.ts +12 -11
  120. package/src/mcp/tools/vsearch.ts +26 -24
  121. package/src/pipeline/answer.ts +9 -9
  122. package/src/pipeline/chunk-lookup.ts +1 -1
  123. package/src/pipeline/contextual.ts +4 -4
  124. package/src/pipeline/expansion.ts +23 -21
  125. package/src/pipeline/explain.ts +21 -21
  126. package/src/pipeline/fusion.ts +9 -9
  127. package/src/pipeline/hybrid.ts +41 -42
  128. package/src/pipeline/index.ts +10 -10
  129. package/src/pipeline/query-language.ts +39 -39
  130. package/src/pipeline/rerank.ts +8 -7
  131. package/src/pipeline/search.ts +22 -22
  132. package/src/pipeline/types.ts +8 -8
  133. package/src/pipeline/vsearch.ts +21 -24
  134. package/src/serve/CLAUDE.md +21 -15
  135. package/src/serve/config-sync.ts +9 -8
  136. package/src/serve/context.ts +19 -18
  137. package/src/serve/index.ts +1 -1
  138. package/src/serve/jobs.ts +7 -7
  139. package/src/serve/public/app.tsx +79 -25
  140. package/src/serve/public/components/AddCollectionDialog.tsx +382 -0
  141. package/src/serve/public/components/CaptureButton.tsx +60 -0
  142. package/src/serve/public/components/CaptureModal.tsx +365 -0
  143. package/src/serve/public/components/IndexingProgress.tsx +333 -0
  144. package/src/serve/public/components/ShortcutHelpModal.tsx +106 -0
  145. package/src/serve/public/components/ai-elements/code-block.tsx +42 -32
  146. package/src/serve/public/components/ai-elements/conversation.tsx +16 -14
  147. package/src/serve/public/components/ai-elements/inline-citation.tsx +33 -32
  148. package/src/serve/public/components/ai-elements/loader.tsx +5 -4
  149. package/src/serve/public/components/ai-elements/message.tsx +39 -37
  150. package/src/serve/public/components/ai-elements/prompt-input.tsx +97 -95
  151. package/src/serve/public/components/ai-elements/sources.tsx +12 -10
  152. package/src/serve/public/components/ai-elements/suggestion.tsx +10 -9
  153. package/src/serve/public/components/editor/CodeMirrorEditor.tsx +142 -0
  154. package/src/serve/public/components/editor/MarkdownPreview.tsx +311 -0
  155. package/src/serve/public/components/editor/index.ts +6 -0
  156. package/src/serve/public/components/preset-selector.tsx +29 -28
  157. package/src/serve/public/components/ui/badge.tsx +13 -12
  158. package/src/serve/public/components/ui/button-group.tsx +13 -12
  159. package/src/serve/public/components/ui/button.tsx +23 -22
  160. package/src/serve/public/components/ui/card.tsx +16 -16
  161. package/src/serve/public/components/ui/carousel.tsx +36 -35
  162. package/src/serve/public/components/ui/collapsible.tsx +1 -1
  163. package/src/serve/public/components/ui/command.tsx +17 -15
  164. package/src/serve/public/components/ui/dialog.tsx +13 -12
  165. package/src/serve/public/components/ui/dropdown-menu.tsx +13 -12
  166. package/src/serve/public/components/ui/hover-card.tsx +6 -5
  167. package/src/serve/public/components/ui/input-group.tsx +45 -43
  168. package/src/serve/public/components/ui/input.tsx +6 -6
  169. package/src/serve/public/components/ui/progress.tsx +5 -4
  170. package/src/serve/public/components/ui/scroll-area.tsx +11 -10
  171. package/src/serve/public/components/ui/select.tsx +19 -18
  172. package/src/serve/public/components/ui/separator.tsx +6 -5
  173. package/src/serve/public/components/ui/table.tsx +18 -18
  174. package/src/serve/public/components/ui/textarea.tsx +4 -4
  175. package/src/serve/public/components/ui/tooltip.tsx +5 -4
  176. package/src/serve/public/globals.css +27 -4
  177. package/src/serve/public/hooks/use-api.ts +8 -8
  178. package/src/serve/public/hooks/useCaptureModal.tsx +83 -0
  179. package/src/serve/public/hooks/useKeyboardShortcuts.ts +85 -0
  180. package/src/serve/public/index.html +4 -4
  181. package/src/serve/public/lib/utils.ts +6 -0
  182. package/src/serve/public/pages/Ask.tsx +27 -26
  183. package/src/serve/public/pages/Browse.tsx +28 -27
  184. package/src/serve/public/pages/Collections.tsx +439 -0
  185. package/src/serve/public/pages/Dashboard.tsx +166 -40
  186. package/src/serve/public/pages/DocView.tsx +258 -73
  187. package/src/serve/public/pages/DocumentEditor.tsx +510 -0
  188. package/src/serve/public/pages/Search.tsx +80 -58
  189. package/src/serve/routes/api.ts +272 -155
  190. package/src/serve/security.ts +4 -4
  191. package/src/serve/server.ts +66 -48
  192. package/src/store/index.ts +5 -5
  193. package/src/store/migrations/001-initial.ts +24 -23
  194. package/src/store/migrations/002-documents-fts.ts +7 -6
  195. package/src/store/migrations/index.ts +4 -4
  196. package/src/store/migrations/runner.ts +17 -15
  197. package/src/store/sqlite/adapter.ts +123 -121
  198. package/src/store/sqlite/fts5-snowball.ts +24 -23
  199. package/src/store/sqlite/index.ts +1 -1
  200. package/src/store/sqlite/setup.ts +12 -12
  201. package/src/store/sqlite/types.ts +4 -4
  202. package/src/store/types.ts +19 -19
  203. package/src/store/vector/index.ts +3 -3
  204. package/src/store/vector/sqlite-vec.ts +23 -20
  205. package/src/store/vector/stats.ts +10 -8
  206. package/src/store/vector/types.ts +2 -2
  207. package/vendor/fts5-snowball/README.md +6 -6
  208. package/assets/screenshots/webui-ask-answer.jpg +0 -0
  209. package/assets/screenshots/webui-home.jpg +0 -0
package/package.json CHANGED
@@ -1,40 +1,38 @@
1
1
  {
2
2
  "name": "@gmickel/gno",
3
- "version": "0.7.0",
3
+ "version": "0.8.1",
4
4
  "description": "Local semantic search for your documents. Index Markdown, PDF, and Office files with hybrid BM25 + vector search.",
5
5
  "keywords": [
6
- "search",
7
- "semantic-search",
8
- "rag",
9
- "vector-search",
10
6
  "embeddings",
7
+ "llm",
11
8
  "local-first",
12
9
  "mcp",
13
- "llm"
10
+ "rag",
11
+ "search",
12
+ "semantic-search",
13
+ "vector-search"
14
14
  ],
15
- "author": "Gordon Mickel <gordon@mickel.tech>",
15
+ "homepage": "https://gno.sh",
16
+ "bugs": {
17
+ "url": "https://github.com/gmickel/gno/issues"
18
+ },
16
19
  "license": "MIT",
20
+ "author": "Gordon Mickel <gordon@mickel.tech>",
17
21
  "repository": {
18
22
  "type": "git",
19
23
  "url": "git+https://github.com/gmickel/gno.git"
20
24
  },
21
- "bugs": {
22
- "url": "https://github.com/gmickel/gno/issues"
23
- },
24
- "homepage": "https://gno.sh",
25
- "type": "module",
26
- "module": "src/index.ts",
27
25
  "bin": {
28
26
  "gno": "src/index.ts"
29
27
  },
30
28
  "files": [
31
- "src",
32
29
  "assets",
30
+ "src",
31
+ "THIRD_PARTY_NOTICES.md",
33
32
  "vendor"
34
33
  ],
35
- "engines": {
36
- "bun": ">=1.3.0"
37
- },
34
+ "type": "module",
35
+ "module": "src/index.ts",
38
36
  "publishConfig": {
39
37
  "access": "public"
40
38
  },
@@ -42,15 +40,13 @@
42
40
  "dev": "bun run --hot src/index.ts",
43
41
  "build": "bun build src/index.ts",
44
42
  "start": "bun run src/index.ts",
45
- "lint": "biome check",
46
- "lint:fix": "biome check --write",
43
+ "lint": "oxlint --fix --type-aware --type-check && oxfmt .",
44
+ "lint:check": "oxlint --type-aware --type-check && oxfmt --check .",
47
45
  "test": "bun test",
48
46
  "test:watch": "bun test --watch",
49
47
  "test:coverage": "bun test --coverage",
50
48
  "test:coverage:html": "bun test --coverage --html",
51
49
  "test:fixtures": "bun scripts/generate-test-fixtures.ts",
52
- "typecheck": "tsgo --noEmit",
53
- "lint:typeaware": "bun x oxlint --type-aware",
54
50
  "reset": "bun run src/index.ts reset --confirm",
55
51
  "docs:verify": "bun run scripts/docs-verify.ts",
56
52
  "website:install": "cd website && bundle install",
@@ -62,11 +58,14 @@
62
58
  "version:patch": "npm version patch --no-git-tag-version",
63
59
  "version:minor": "npm version minor --no-git-tag-version",
64
60
  "version:major": "npm version major --no-git-tag-version",
65
- "prerelease": "bun run lint && bun run typecheck && bun test",
61
+ "prerelease": "bun run lint:check && bun test",
66
62
  "release:dry-run": "gh workflow run publish.yml -f publish=false",
67
- "release:trigger": "gh workflow run publish.yml -f publish=true"
63
+ "release:trigger": "gh workflow run publish.yml -f publish=true",
64
+ "prepare": "lefthook install"
68
65
  },
69
66
  "dependencies": {
67
+ "@codemirror/lang-markdown": "^6.5.0",
68
+ "@codemirror/theme-one-dark": "^6.1.3",
70
69
  "@modelcontextprotocol/sdk": "^1.25.1",
71
70
  "@radix-ui/react-collapsible": "^1.1.12",
72
71
  "@radix-ui/react-dialog": "^1.1.15",
@@ -83,6 +82,7 @@
83
82
  "class-variance-authority": "^0.7.1",
84
83
  "clsx": "^2.1.1",
85
84
  "cmdk": "^1.1.1",
85
+ "codemirror": "^6.0.2",
86
86
  "commander": "^14.0.2",
87
87
  "embla-carousel-react": "^8.6.0",
88
88
  "franc": "^6.2.0",
@@ -94,6 +94,9 @@
94
94
  "picocolors": "^1.1.1",
95
95
  "react": "^19.2.3",
96
96
  "react-dom": "^19.2.3",
97
+ "react-markdown": "^10.1.0",
98
+ "rehype-highlight": "^7.0.2",
99
+ "rehype-sanitize": "^6.0.0",
97
100
  "shiki": "^3.20.0",
98
101
  "sqlite-vec": "^0.1.7-alpha.2",
99
102
  "streamdown": "^1.6.10",
@@ -106,13 +109,14 @@
106
109
  "@types/bun": "latest",
107
110
  "@types/react": "^19.2.7",
108
111
  "@types/react-dom": "^19.2.3",
109
- "@typescript/native-preview": "^7.0.0-dev.20251215.1",
110
112
  "ajv": "^8.17.1",
111
113
  "ajv-formats": "^3.0.1",
112
114
  "docx": "^9.5.1",
113
115
  "evalite": "^1.0.0-beta.15",
114
116
  "exceljs": "^4.4.0",
115
117
  "lefthook": "^2.0.13",
118
+ "oxfmt": "^0.21.0",
119
+ "oxlint": "^1.36.0",
116
120
  "oxlint-tsgolint": "^0.10.1",
117
121
  "pdf-lib": "^1.17.1",
118
122
  "pptxgenjs": "^4.0.1",
@@ -121,5 +125,8 @@
121
125
  },
122
126
  "peerDependencies": {
123
127
  "typescript": "^5"
128
+ },
129
+ "engines": {
130
+ "bun": ">=1.3.0"
124
131
  }
125
132
  }
@@ -5,26 +5,27 @@
5
5
  * @module src/app/constants
6
6
  */
7
7
 
8
- import { homedir, platform } from 'node:os';
9
- import { join } from 'node:path';
8
+ import { homedir, platform } from "node:os";
9
+ import { join } from "node:path";
10
+
10
11
  // Bun supports JSON imports natively - version single source of truth
11
- import pkg from '../../package.json';
12
+ import pkg from "../../package.json";
12
13
 
13
14
  // ─────────────────────────────────────────────────────────────────────────────
14
15
  // Brand / Product Identity
15
16
  // ─────────────────────────────────────────────────────────────────────────────
16
17
 
17
18
  /** Product name (display) */
18
- export const PRODUCT_NAME = 'GNO';
19
+ export const PRODUCT_NAME = "GNO";
19
20
 
20
21
  /** CLI binary name */
21
- export const CLI_NAME = 'gno';
22
+ export const CLI_NAME = "gno";
22
23
 
23
24
  /** Version from package.json (single source of truth) */
24
25
  export const VERSION = pkg.version;
25
26
 
26
27
  /** Virtual URI scheme for document references */
27
- export const URI_SCHEME = 'gno';
28
+ export const URI_SCHEME = "gno";
28
29
 
29
30
  /** Full URI prefix including :// */
30
31
  export const URI_PREFIX = `${URI_SCHEME}://`;
@@ -34,56 +35,56 @@ export const URI_PREFIX = `${URI_SCHEME}://`;
34
35
  // ─────────────────────────────────────────────────────────────────────────────
35
36
 
36
37
  /** MCP server name */
37
- export const MCP_SERVER_NAME = 'gno';
38
+ export const MCP_SERVER_NAME = "gno";
38
39
 
39
40
  /** MCP tool namespace prefix (tools are gno.search, gno.query, etc.) */
40
- export const MCP_TOOL_PREFIX = 'gno';
41
+ export const MCP_TOOL_PREFIX = "gno";
41
42
 
42
43
  // ─────────────────────────────────────────────────────────────────────────────
43
44
  // Documentation & Support
44
45
  // ─────────────────────────────────────────────────────────────────────────────
45
46
 
46
47
  /** Documentation URL */
47
- export const DOCS_URL = 'https://github.com/gmickel/gno#readme';
48
+ export const DOCS_URL = "https://github.com/gmickel/gno#readme";
48
49
 
49
50
  /** Issue tracker URL */
50
- export const ISSUES_URL = 'https://github.com/gmickel/gno/issues';
51
+ export const ISSUES_URL = "https://github.com/gmickel/gno/issues";
51
52
 
52
53
  // ─────────────────────────────────────────────────────────────────────────────
53
54
  // Environment Variable Names (for directory overrides)
54
55
  // ─────────────────────────────────────────────────────────────────────────────
55
56
 
56
57
  /** Env var to override config directory */
57
- export const ENV_CONFIG_DIR = 'GNO_CONFIG_DIR';
58
+ export const ENV_CONFIG_DIR = "GNO_CONFIG_DIR";
58
59
 
59
60
  /** Env var to override data directory */
60
- export const ENV_DATA_DIR = 'GNO_DATA_DIR';
61
+ export const ENV_DATA_DIR = "GNO_DATA_DIR";
61
62
 
62
63
  /** Env var to override cache directory */
63
- export const ENV_CACHE_DIR = 'GNO_CACHE_DIR';
64
+ export const ENV_CACHE_DIR = "GNO_CACHE_DIR";
64
65
 
65
66
  // ─────────────────────────────────────────────────────────────────────────────
66
67
  // Directory Names
67
68
  // ─────────────────────────────────────────────────────────────────────────────
68
69
 
69
70
  /** Directory name used within platform-specific locations */
70
- export const DIR_NAME = 'gno';
71
+ export const DIR_NAME = "gno";
71
72
 
72
73
  // ─────────────────────────────────────────────────────────────────────────────
73
74
  // Index Defaults
74
75
  // ─────────────────────────────────────────────────────────────────────────────
75
76
 
76
77
  /** Default index name when not specified via --index */
77
- export const DEFAULT_INDEX_NAME = 'default';
78
+ export const DEFAULT_INDEX_NAME = "default";
78
79
 
79
80
  /** Config filename */
80
- export const CONFIG_FILENAME = 'index.yml';
81
+ export const CONFIG_FILENAME = "index.yml";
81
82
 
82
83
  // ─────────────────────────────────────────────────────────────────────────────
83
84
  // Platform Detection
84
85
  // ─────────────────────────────────────────────────────────────────────────────
85
86
 
86
- export type Platform = 'darwin' | 'win32' | 'linux';
87
+ export type Platform = "darwin" | "win32" | "linux";
87
88
 
88
89
  /**
89
90
  * Get current platform, normalized to supported types.
@@ -91,13 +92,13 @@ export type Platform = 'darwin' | 'win32' | 'linux';
91
92
  */
92
93
  export function getPlatform(): Platform {
93
94
  const p = platform();
94
- if (p === 'darwin') {
95
- return 'darwin';
95
+ if (p === "darwin") {
96
+ return "darwin";
96
97
  }
97
- if (p === 'win32') {
98
- return 'win32';
98
+ if (p === "win32") {
99
+ return "win32";
99
100
  }
100
- return 'linux';
101
+ return "linux";
101
102
  }
102
103
 
103
104
  // ─────────────────────────────────────────────────────────────────────────────
@@ -132,9 +133,9 @@ interface PlatformPaths {
132
133
 
133
134
  function getLinuxPaths(): PlatformPaths {
134
135
  const home = homedir();
135
- const xdgConfig = process.env.XDG_CONFIG_HOME ?? join(home, '.config');
136
- const xdgData = process.env.XDG_DATA_HOME ?? join(home, '.local', 'share');
137
- const xdgCache = process.env.XDG_CACHE_HOME ?? join(home, '.cache');
136
+ const xdgConfig = process.env.XDG_CONFIG_HOME ?? join(home, ".config");
137
+ const xdgData = process.env.XDG_DATA_HOME ?? join(home, ".local", "share");
138
+ const xdgCache = process.env.XDG_CACHE_HOME ?? join(home, ".cache");
138
139
 
139
140
  return {
140
141
  config: join(xdgConfig, DIR_NAME),
@@ -145,24 +146,24 @@ function getLinuxPaths(): PlatformPaths {
145
146
 
146
147
  function getDarwinPaths(): PlatformPaths {
147
148
  const home = homedir();
148
- const appSupport = join(home, 'Library', 'Application Support', DIR_NAME);
149
+ const appSupport = join(home, "Library", "Application Support", DIR_NAME);
149
150
 
150
151
  return {
151
- config: join(appSupport, 'config'),
152
- data: join(appSupport, 'data'),
153
- cache: join(home, 'Library', 'Caches', DIR_NAME),
152
+ config: join(appSupport, "config"),
153
+ data: join(appSupport, "data"),
154
+ cache: join(home, "Library", "Caches", DIR_NAME),
154
155
  };
155
156
  }
156
157
 
157
158
  function getWin32Paths(): PlatformPaths {
158
- const appData = process.env.APPDATA ?? join(homedir(), 'AppData', 'Roaming');
159
+ const appData = process.env.APPDATA ?? join(homedir(), "AppData", "Roaming");
159
160
  const localAppData =
160
- process.env.LOCALAPPDATA ?? join(homedir(), 'AppData', 'Local');
161
+ process.env.LOCALAPPDATA ?? join(homedir(), "AppData", "Local");
161
162
 
162
163
  return {
163
- config: join(appData, DIR_NAME, 'config'),
164
- data: join(localAppData, DIR_NAME, 'data'),
165
- cache: join(localAppData, DIR_NAME, 'cache'),
164
+ config: join(appData, DIR_NAME, "config"),
165
+ data: join(localAppData, DIR_NAME, "data"),
166
+ cache: join(localAppData, DIR_NAME, "cache"),
166
167
  };
167
168
  }
168
169
 
@@ -171,9 +172,9 @@ function getWin32Paths(): PlatformPaths {
171
172
  */
172
173
  export function getPlatformPaths(p: Platform = getPlatform()): PlatformPaths {
173
174
  switch (p) {
174
- case 'darwin':
175
+ case "darwin":
175
176
  return getDarwinPaths();
176
- case 'win32':
177
+ case "win32":
177
178
  return getWin32Paths();
178
179
  default:
179
180
  return getLinuxPaths();
@@ -231,7 +232,7 @@ export function getConfigPath(dirs: ResolvedDirs = resolveDirs()): string {
231
232
  * Get path to models cache directory.
232
233
  */
233
234
  export function getModelsCachePath(dirs: ResolvedDirs = resolveDirs()): string {
234
- return join(dirs.cache, 'models');
235
+ return join(dirs.cache, "models");
235
236
  }
236
237
 
237
238
  // ─────────────────────────────────────────────────────────────────────────────
@@ -244,9 +245,9 @@ export function getModelsCachePath(dirs: ResolvedDirs = resolveDirs()): string {
244
245
  export function buildUri(collection: string, relativePath: string): string {
245
246
  // URL-encode special chars in path segments but preserve slashes
246
247
  const encodedPath = relativePath
247
- .split('/')
248
+ .split("/")
248
249
  .map((segment) => encodeURIComponent(segment))
249
- .join('/');
250
+ .join("/");
250
251
  return `${URI_PREFIX}${collection}/${encodedPath}`;
251
252
  }
252
253
 
@@ -262,11 +263,11 @@ export function parseUri(
262
263
  }
263
264
 
264
265
  const rest = uri.slice(URI_PREFIX.length);
265
- const slashIndex = rest.indexOf('/');
266
+ const slashIndex = rest.indexOf("/");
266
267
 
267
268
  if (slashIndex === -1) {
268
269
  // gno://collection (no path)
269
- return { collection: rest, path: '' };
270
+ return { collection: rest, path: "" };
270
271
  }
271
272
 
272
273
  const collection = rest.slice(0, slashIndex);
@@ -285,7 +286,7 @@ export function parseUri(
285
286
  // ─────────────────────────────────────────────────────────────────────────────
286
287
 
287
288
  /** docid prefix */
288
- export const DOCID_PREFIX = '#';
289
+ export const DOCID_PREFIX = "#";
289
290
 
290
291
  /** docid hex length (8 chars = 32 bits, ~4B unique values) */
291
292
  export const DOCID_LENGTH = 8;
package/src/cli/colors.ts CHANGED
@@ -4,7 +4,7 @@
4
4
  * @module src/cli/colors
5
5
  */
6
6
 
7
- import pc from 'picocolors';
7
+ import pc from "picocolors";
8
8
 
9
9
  // Track whether colors are enabled (global state for CLI lifetime)
10
10
  let colorsEnabled = true;
@@ -5,30 +5,31 @@
5
5
  * @module src/cli/commands/ask
6
6
  */
7
7
 
8
- import { LlmAdapter } from '../../llm/nodeLlamaCpp/adapter';
9
- import { resolveDownloadPolicy } from '../../llm/policy';
10
- import { getActivePreset } from '../../llm/registry';
11
8
  import type {
12
9
  EmbeddingPort,
13
10
  GenerationPort,
14
11
  RerankPort,
15
- } from '../../llm/types';
12
+ } from "../../llm/types";
13
+ import type { AskOptions, AskResult, Citation } from "../../pipeline/types";
14
+
15
+ import { LlmAdapter } from "../../llm/nodeLlamaCpp/adapter";
16
+ import { resolveDownloadPolicy } from "../../llm/policy";
17
+ import { getActivePreset } from "../../llm/registry";
16
18
  import {
17
19
  generateGroundedAnswer,
18
20
  processAnswerResult,
19
- } from '../../pipeline/answer';
20
- import { type HybridSearchDeps, searchHybrid } from '../../pipeline/hybrid';
21
- import type { AskOptions, AskResult, Citation } from '../../pipeline/types';
21
+ } from "../../pipeline/answer";
22
+ import { type HybridSearchDeps, searchHybrid } from "../../pipeline/hybrid";
22
23
  import {
23
24
  createVectorIndexPort,
24
25
  type VectorIndexPort,
25
- } from '../../store/vector';
26
- import { getGlobals } from '../program';
26
+ } from "../../store/vector";
27
+ import { getGlobals } from "../program";
27
28
  import {
28
29
  createProgressRenderer,
29
30
  createThrottledProgressRenderer,
30
- } from '../progress';
31
- import { initStore } from './shared';
31
+ } from "../progress";
32
+ import { initStore } from "./shared";
32
33
 
33
34
  // ─────────────────────────────────────────────────────────────────────────────
34
35
  // Types
@@ -62,7 +63,7 @@ export type AskCommandResult =
62
63
  /**
63
64
  * Execute gno ask command.
64
65
  */
65
- // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: CLI orchestration with multiple output formats
66
+ // oxlint-disable-next-line max-lines-per-function -- CLI orchestration with multiple output formats
66
67
  export async function ask(
67
68
  query: string,
68
69
  options: AskCommandOptions = {}
@@ -105,7 +106,7 @@ export async function ask(
105
106
  const embedResult = await llm.createEmbeddingPort(embedUri, {
106
107
  policy,
107
108
  onProgress: downloadProgress
108
- ? (progress) => downloadProgress('embed', progress)
109
+ ? (progress) => downloadProgress("embed", progress)
109
110
  : undefined,
110
111
  });
111
112
  if (embedResult.ok) {
@@ -120,7 +121,7 @@ export async function ask(
120
121
  const genResult = await llm.createGenerationPort(genUri, {
121
122
  policy,
122
123
  onProgress: downloadProgress
123
- ? (progress) => downloadProgress('gen', progress)
124
+ ? (progress) => downloadProgress("gen", progress)
124
125
  : undefined,
125
126
  });
126
127
  if (genResult.ok) {
@@ -134,7 +135,7 @@ export async function ask(
134
135
  const rerankResult = await llm.createRerankPort(rerankUri, {
135
136
  policy,
136
137
  onProgress: downloadProgress
137
- ? (progress) => downloadProgress('rerank', progress)
138
+ ? (progress) => downloadProgress("rerank", progress)
138
139
  : undefined,
139
140
  });
140
141
  if (rerankResult.ok) {
@@ -144,7 +145,7 @@ export async function ask(
144
145
 
145
146
  // Clear progress line if shown
146
147
  if (showProgress && downloadProgress) {
147
- process.stderr.write('\n');
148
+ process.stderr.write("\n");
148
149
  }
149
150
 
150
151
  // Create vector index
@@ -181,8 +182,8 @@ export async function ask(
181
182
  return {
182
183
  success: false,
183
184
  error:
184
- 'Answer generation requested but no generation model available. ' +
185
- 'Run `gno models pull --gen` to download a model, or configure a preset.',
185
+ "Answer generation requested but no generation model available. " +
186
+ "Run `gno models pull --gen` to download a model, or configure a preset.",
186
187
  };
187
188
  }
188
189
 
@@ -227,7 +228,7 @@ export async function ask(
227
228
  return {
228
229
  success: false,
229
230
  error:
230
- 'Answer generation failed. The generation model may have encountered an error.',
231
+ "Answer generation failed. The generation model may have encountered an error.",
231
232
  };
232
233
  }
233
234
 
@@ -240,8 +241,8 @@ export async function ask(
240
241
 
241
242
  const askResult: AskResult = {
242
243
  query,
243
- mode: searchResult.value.meta.vectorsUsed ? 'hybrid' : 'bm25_only',
244
- queryLanguage: searchResult.value.meta.queryLanguage ?? 'und',
244
+ mode: searchResult.value.meta.vectorsUsed ? "hybrid" : "bm25_only",
245
+ queryLanguage: searchResult.value.meta.queryLanguage ?? "und",
245
246
  answer,
246
247
  citations,
247
248
  results,
@@ -277,28 +278,28 @@ interface FormatOptions {
277
278
  showSources?: boolean;
278
279
  }
279
280
 
280
- // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: terminal formatting with conditional sections
281
+ // oxlint-disable-next-line max-lines-per-function -- terminal formatting with conditional sections
281
282
  function formatTerminal(data: AskResult, opts: FormatOptions = {}): string {
282
283
  const lines: string[] = [];
283
284
  const hasAnswer = Boolean(data.answer);
284
285
 
285
286
  // Show answer if present
286
287
  if (data.answer) {
287
- lines.push('Answer:');
288
+ lines.push("Answer:");
288
289
  lines.push(data.answer);
289
- lines.push('');
290
+ lines.push("");
290
291
  }
291
292
 
292
293
  // Show cited sources (only sources actually referenced in answer)
293
294
  if (data.citations && data.citations.length > 0) {
294
- lines.push('Cited Sources:');
295
+ lines.push("Cited Sources:");
295
296
  for (let i = 0; i < data.citations.length; i++) {
296
297
  const c = data.citations[i];
297
298
  if (c) {
298
299
  lines.push(` [${i + 1}] ${c.uri}`);
299
300
  }
300
301
  }
301
- lines.push('');
302
+ lines.push("");
302
303
  }
303
304
 
304
305
  // Show all retrieved sources if:
@@ -306,7 +307,7 @@ function formatTerminal(data: AskResult, opts: FormatOptions = {}): string {
306
307
  // - User explicitly requested with --show-sources
307
308
  const showAllSources = !hasAnswer || opts.showSources;
308
309
  if (showAllSources && data.results.length > 0) {
309
- lines.push(hasAnswer ? 'All Retrieved Sources:' : 'Sources:');
310
+ lines.push(hasAnswer ? "All Retrieved Sources:" : "Sources:");
310
311
  for (const r of data.results) {
311
312
  lines.push(` [${r.docid}] ${r.uri}`);
312
313
  if (r.title) {
@@ -324,10 +325,10 @@ function formatTerminal(data: AskResult, opts: FormatOptions = {}): string {
324
325
  }
325
326
 
326
327
  if (!data.answer && data.results.length === 0) {
327
- lines.push('No relevant sources found.');
328
+ lines.push("No relevant sources found.");
328
329
  }
329
330
 
330
- return lines.join('\n');
331
+ return lines.join("\n");
331
332
  }
332
333
 
333
334
  function formatMarkdown(data: AskResult, opts: FormatOptions = {}): string {
@@ -335,33 +336,33 @@ function formatMarkdown(data: AskResult, opts: FormatOptions = {}): string {
335
336
  const hasAnswer = Boolean(data.answer);
336
337
 
337
338
  lines.push(`# Question: ${data.query}`);
338
- lines.push('');
339
+ lines.push("");
339
340
 
340
341
  if (data.answer) {
341
- lines.push('## Answer');
342
- lines.push('');
342
+ lines.push("## Answer");
343
+ lines.push("");
343
344
  lines.push(data.answer);
344
- lines.push('');
345
+ lines.push("");
345
346
  }
346
347
 
347
348
  // Show cited sources (only sources actually referenced in answer)
348
349
  if (data.citations && data.citations.length > 0) {
349
- lines.push('## Cited Sources');
350
- lines.push('');
350
+ lines.push("## Cited Sources");
351
+ lines.push("");
351
352
  for (let i = 0; i < data.citations.length; i++) {
352
353
  const c = data.citations[i];
353
354
  if (c) {
354
355
  lines.push(`**[${i + 1}]** \`${c.uri}\``);
355
356
  }
356
357
  }
357
- lines.push('');
358
+ lines.push("");
358
359
  }
359
360
 
360
361
  // Show all retrieved sources if no answer or --show-sources
361
362
  const showAllSources = !hasAnswer || opts.showSources;
362
363
  if (showAllSources) {
363
- lines.push(hasAnswer ? '## All Retrieved Sources' : '## Sources');
364
- lines.push('');
364
+ lines.push(hasAnswer ? "## All Retrieved Sources" : "## Sources");
365
+ lines.push("");
365
366
 
366
367
  for (let i = 0; i < data.results.length; i++) {
367
368
  const r = data.results[i];
@@ -374,17 +375,17 @@ function formatMarkdown(data: AskResult, opts: FormatOptions = {}): string {
374
375
  }
375
376
 
376
377
  if (data.results.length === 0) {
377
- lines.push('*No relevant sources found.*');
378
+ lines.push("*No relevant sources found.*");
378
379
  }
379
380
  }
380
381
 
381
- lines.push('');
382
- lines.push('---');
382
+ lines.push("");
383
+ lines.push("---");
383
384
  lines.push(
384
385
  `*Mode: ${data.mode} | Expanded: ${data.meta.expanded} | Reranked: ${data.meta.reranked}*`
385
386
  );
386
387
 
387
- return lines.join('\n');
388
+ return lines.join("\n");
388
389
  }
389
390
 
390
391
  /**
@@ -397,7 +398,7 @@ export function formatAsk(
397
398
  if (!result.success) {
398
399
  return options.json
399
400
  ? JSON.stringify({
400
- error: { code: 'ASK_FAILED', message: result.error },
401
+ error: { code: "ASK_FAILED", message: result.error },
401
402
  })
402
403
  : `Error: ${result.error}`;
403
404
  }
@@ -5,10 +5,11 @@
5
5
  * @module src/cli/commands/cleanup
6
6
  */
7
7
 
8
- import { getIndexDbPath } from '../../app/constants';
9
- import { isInitialized, loadConfig } from '../../config';
10
- import { SqliteAdapter } from '../../store/sqlite/adapter';
11
- import type { CleanupStats } from '../../store/types';
8
+ import type { CleanupStats } from "../../store/types";
9
+
10
+ import { getIndexDbPath } from "../../app/constants";
11
+ import { isInitialized, loadConfig } from "../../config";
12
+ import { SqliteAdapter } from "../../store/sqlite/adapter";
12
13
 
13
14
  /**
14
15
  * Options for cleanup command.
@@ -34,7 +35,7 @@ export async function cleanup(
34
35
  // Check if initialized
35
36
  const initialized = await isInitialized(options.configPath);
36
37
  if (!initialized) {
37
- return { success: false, error: 'GNO not initialized. Run: gno init' };
38
+ return { success: false, error: "GNO not initialized. Run: gno init" };
38
39
  }
39
40
 
40
41
  // Load config
@@ -81,10 +82,10 @@ export function formatCleanup(result: CleanupResult): string {
81
82
  stats.expiredCache;
82
83
 
83
84
  if (total === 0) {
84
- return 'No orphans found. Index is clean.';
85
+ return "No orphans found. Index is clean.";
85
86
  }
86
87
 
87
- const lines: string[] = ['Cleanup complete:'];
88
+ const lines: string[] = ["Cleanup complete:"];
88
89
 
89
90
  if (stats.orphanedContent > 0) {
90
91
  lines.push(` Orphaned content: ${stats.orphanedContent}`);
@@ -101,5 +102,5 @@ export function formatCleanup(result: CleanupResult): string {
101
102
 
102
103
  lines.push(`Total removed: ${total}`);
103
104
 
104
- return lines.join('\n');
105
+ return lines.join("\n");
105
106
  }