@gmickel/gno 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (131) hide show
  1. package/README.md +256 -0
  2. package/assets/skill/SKILL.md +112 -0
  3. package/assets/skill/cli-reference.md +327 -0
  4. package/assets/skill/examples.md +234 -0
  5. package/assets/skill/mcp-reference.md +159 -0
  6. package/package.json +90 -0
  7. package/src/app/constants.ts +313 -0
  8. package/src/cli/colors.ts +65 -0
  9. package/src/cli/commands/ask.ts +545 -0
  10. package/src/cli/commands/cleanup.ts +105 -0
  11. package/src/cli/commands/collection/add.ts +120 -0
  12. package/src/cli/commands/collection/index.ts +10 -0
  13. package/src/cli/commands/collection/list.ts +108 -0
  14. package/src/cli/commands/collection/remove.ts +64 -0
  15. package/src/cli/commands/collection/rename.ts +95 -0
  16. package/src/cli/commands/context/add.ts +67 -0
  17. package/src/cli/commands/context/check.ts +153 -0
  18. package/src/cli/commands/context/index.ts +10 -0
  19. package/src/cli/commands/context/list.ts +109 -0
  20. package/src/cli/commands/context/rm.ts +52 -0
  21. package/src/cli/commands/doctor.ts +393 -0
  22. package/src/cli/commands/embed.ts +462 -0
  23. package/src/cli/commands/get.ts +356 -0
  24. package/src/cli/commands/index-cmd.ts +119 -0
  25. package/src/cli/commands/index.ts +102 -0
  26. package/src/cli/commands/init.ts +328 -0
  27. package/src/cli/commands/ls.ts +217 -0
  28. package/src/cli/commands/mcp/config.ts +300 -0
  29. package/src/cli/commands/mcp/index.ts +24 -0
  30. package/src/cli/commands/mcp/install.ts +203 -0
  31. package/src/cli/commands/mcp/paths.ts +470 -0
  32. package/src/cli/commands/mcp/status.ts +222 -0
  33. package/src/cli/commands/mcp/uninstall.ts +158 -0
  34. package/src/cli/commands/mcp.ts +20 -0
  35. package/src/cli/commands/models/clear.ts +103 -0
  36. package/src/cli/commands/models/index.ts +32 -0
  37. package/src/cli/commands/models/list.ts +214 -0
  38. package/src/cli/commands/models/path.ts +51 -0
  39. package/src/cli/commands/models/pull.ts +199 -0
  40. package/src/cli/commands/models/use.ts +85 -0
  41. package/src/cli/commands/multi-get.ts +400 -0
  42. package/src/cli/commands/query.ts +220 -0
  43. package/src/cli/commands/ref-parser.ts +108 -0
  44. package/src/cli/commands/reset.ts +191 -0
  45. package/src/cli/commands/search.ts +136 -0
  46. package/src/cli/commands/shared.ts +156 -0
  47. package/src/cli/commands/skill/index.ts +19 -0
  48. package/src/cli/commands/skill/install.ts +197 -0
  49. package/src/cli/commands/skill/paths-cmd.ts +81 -0
  50. package/src/cli/commands/skill/paths.ts +191 -0
  51. package/src/cli/commands/skill/show.ts +73 -0
  52. package/src/cli/commands/skill/uninstall.ts +141 -0
  53. package/src/cli/commands/status.ts +205 -0
  54. package/src/cli/commands/update.ts +68 -0
  55. package/src/cli/commands/vsearch.ts +188 -0
  56. package/src/cli/context.ts +64 -0
  57. package/src/cli/errors.ts +64 -0
  58. package/src/cli/format/search-results.ts +211 -0
  59. package/src/cli/options.ts +183 -0
  60. package/src/cli/program.ts +1330 -0
  61. package/src/cli/run.ts +213 -0
  62. package/src/cli/ui.ts +92 -0
  63. package/src/config/defaults.ts +20 -0
  64. package/src/config/index.ts +55 -0
  65. package/src/config/loader.ts +161 -0
  66. package/src/config/paths.ts +87 -0
  67. package/src/config/saver.ts +153 -0
  68. package/src/config/types.ts +280 -0
  69. package/src/converters/adapters/markitdownTs/adapter.ts +140 -0
  70. package/src/converters/adapters/officeparser/adapter.ts +126 -0
  71. package/src/converters/canonicalize.ts +89 -0
  72. package/src/converters/errors.ts +218 -0
  73. package/src/converters/index.ts +51 -0
  74. package/src/converters/mime.ts +163 -0
  75. package/src/converters/native/markdown.ts +115 -0
  76. package/src/converters/native/plaintext.ts +56 -0
  77. package/src/converters/path.ts +48 -0
  78. package/src/converters/pipeline.ts +159 -0
  79. package/src/converters/registry.ts +74 -0
  80. package/src/converters/types.ts +123 -0
  81. package/src/converters/versions.ts +24 -0
  82. package/src/index.ts +27 -0
  83. package/src/ingestion/chunker.ts +238 -0
  84. package/src/ingestion/index.ts +32 -0
  85. package/src/ingestion/language.ts +276 -0
  86. package/src/ingestion/sync.ts +671 -0
  87. package/src/ingestion/types.ts +219 -0
  88. package/src/ingestion/walker.ts +235 -0
  89. package/src/llm/cache.ts +467 -0
  90. package/src/llm/errors.ts +191 -0
  91. package/src/llm/index.ts +58 -0
  92. package/src/llm/nodeLlamaCpp/adapter.ts +133 -0
  93. package/src/llm/nodeLlamaCpp/embedding.ts +165 -0
  94. package/src/llm/nodeLlamaCpp/generation.ts +88 -0
  95. package/src/llm/nodeLlamaCpp/lifecycle.ts +317 -0
  96. package/src/llm/nodeLlamaCpp/rerank.ts +94 -0
  97. package/src/llm/registry.ts +86 -0
  98. package/src/llm/types.ts +129 -0
  99. package/src/mcp/resources/index.ts +151 -0
  100. package/src/mcp/server.ts +229 -0
  101. package/src/mcp/tools/get.ts +220 -0
  102. package/src/mcp/tools/index.ts +160 -0
  103. package/src/mcp/tools/multi-get.ts +263 -0
  104. package/src/mcp/tools/query.ts +226 -0
  105. package/src/mcp/tools/search.ts +119 -0
  106. package/src/mcp/tools/status.ts +81 -0
  107. package/src/mcp/tools/vsearch.ts +198 -0
  108. package/src/pipeline/chunk-lookup.ts +44 -0
  109. package/src/pipeline/expansion.ts +256 -0
  110. package/src/pipeline/explain.ts +115 -0
  111. package/src/pipeline/fusion.ts +185 -0
  112. package/src/pipeline/hybrid.ts +535 -0
  113. package/src/pipeline/index.ts +64 -0
  114. package/src/pipeline/query-language.ts +118 -0
  115. package/src/pipeline/rerank.ts +223 -0
  116. package/src/pipeline/search.ts +261 -0
  117. package/src/pipeline/types.ts +328 -0
  118. package/src/pipeline/vsearch.ts +348 -0
  119. package/src/store/index.ts +41 -0
  120. package/src/store/migrations/001-initial.ts +196 -0
  121. package/src/store/migrations/index.ts +20 -0
  122. package/src/store/migrations/runner.ts +187 -0
  123. package/src/store/sqlite/adapter.ts +1242 -0
  124. package/src/store/sqlite/index.ts +7 -0
  125. package/src/store/sqlite/setup.ts +129 -0
  126. package/src/store/sqlite/types.ts +28 -0
  127. package/src/store/types.ts +506 -0
  128. package/src/store/vector/index.ts +13 -0
  129. package/src/store/vector/sqlite-vec.ts +373 -0
  130. package/src/store/vector/stats.ts +152 -0
  131. package/src/store/vector/types.ts +115 -0
@@ -0,0 +1,158 @@
1
+ /**
2
+ * Uninstall gno MCP server from client configurations.
3
+ *
4
+ * @module src/cli/commands/mcp/uninstall
5
+ */
6
+
7
+ import { CliError } from '../../errors.js';
8
+ import { getGlobals } from '../../program.js';
9
+ import {
10
+ type AnyMcpConfig,
11
+ isYamlFormat,
12
+ readMcpConfig,
13
+ removeServerEntry,
14
+ writeMcpConfig,
15
+ } from './config.js';
16
+ import {
17
+ getTargetDisplayName,
18
+ MCP_SERVER_NAME,
19
+ type McpScope,
20
+ type McpTarget,
21
+ resolveMcpConfigPath,
22
+ TARGETS_WITH_PROJECT_SCOPE,
23
+ } from './paths.js';
24
+
25
+ // ─────────────────────────────────────────────────────────────────────────────
26
+ // Types
27
+ // ─────────────────────────────────────────────────────────────────────────────
28
+
29
+ export interface UninstallOptions {
30
+ target?: McpTarget;
31
+ scope?: McpScope;
32
+ /** Override cwd (testing) */
33
+ cwd?: string;
34
+ /** Override home dir (testing) */
35
+ homeDir?: string;
36
+ /** JSON output */
37
+ json?: boolean;
38
+ /** Quiet mode */
39
+ quiet?: boolean;
40
+ }
41
+
42
+ interface UninstallResult {
43
+ target: McpTarget;
44
+ scope: McpScope;
45
+ configPath: string;
46
+ action: 'removed' | 'not_found';
47
+ }
48
+
49
+ // ─────────────────────────────────────────────────────────────────────────────
50
+ // Uninstall Logic
51
+ // ─────────────────────────────────────────────────────────────────────────────
52
+
53
+ /**
54
+ * Uninstall gno from a single target.
55
+ */
56
+ async function uninstallFromTarget(
57
+ target: McpTarget,
58
+ scope: McpScope,
59
+ options: { cwd?: string; homeDir?: string }
60
+ ): Promise<UninstallResult> {
61
+ const { cwd, homeDir } = options;
62
+
63
+ const { configPath, configFormat } = resolveMcpConfigPath({
64
+ target,
65
+ scope,
66
+ cwd,
67
+ homeDir,
68
+ });
69
+
70
+ const useYaml = isYamlFormat(configFormat);
71
+ const config = await readMcpConfig(configPath, {
72
+ returnNullOnMissing: true,
73
+ yaml: useYaml,
74
+ });
75
+
76
+ // File doesn't exist
77
+ if (config === null) {
78
+ return { target, scope, configPath, action: 'not_found' };
79
+ }
80
+
81
+ // Try to remove entry using format-aware helper
82
+ const removed = removeServerEntry(
83
+ config as AnyMcpConfig,
84
+ MCP_SERVER_NAME,
85
+ configFormat
86
+ );
87
+
88
+ if (!removed) {
89
+ return { target, scope, configPath, action: 'not_found' };
90
+ }
91
+
92
+ // Write back
93
+ await writeMcpConfig(configPath, config as AnyMcpConfig, { yaml: useYaml });
94
+
95
+ return { target, scope, configPath, action: 'removed' };
96
+ }
97
+
98
+ /**
99
+ * Get globals safely.
100
+ */
101
+ function safeGetGlobals(): { json: boolean; quiet: boolean } {
102
+ try {
103
+ return getGlobals();
104
+ } catch {
105
+ return { json: false, quiet: false };
106
+ }
107
+ }
108
+
109
+ /**
110
+ * Uninstall gno MCP server.
111
+ */
112
+ export async function uninstallMcp(opts: UninstallOptions = {}): Promise<void> {
113
+ const target = opts.target ?? 'claude-desktop';
114
+ const scope = opts.scope ?? 'user';
115
+ const globals = safeGetGlobals();
116
+ const json = opts.json ?? globals.json;
117
+ const quiet = opts.quiet ?? globals.quiet;
118
+
119
+ // Validate scope - only some targets support project scope
120
+ if (scope === 'project' && !TARGETS_WITH_PROJECT_SCOPE.includes(target)) {
121
+ throw new CliError(
122
+ 'VALIDATION',
123
+ `${getTargetDisplayName(target)} does not support project scope.`
124
+ );
125
+ }
126
+
127
+ const result = await uninstallFromTarget(target, scope, {
128
+ cwd: opts.cwd,
129
+ homeDir: opts.homeDir,
130
+ });
131
+
132
+ // Output
133
+ if (json) {
134
+ process.stdout.write(
135
+ `${JSON.stringify({ uninstalled: result }, null, 2)}\n`
136
+ );
137
+ return;
138
+ }
139
+
140
+ if (quiet) {
141
+ return;
142
+ }
143
+
144
+ if (result.action === 'not_found') {
145
+ process.stdout.write(
146
+ `gno is not configured in ${getTargetDisplayName(target)}.\n`
147
+ );
148
+ return;
149
+ }
150
+
151
+ process.stdout.write(
152
+ `Removed gno MCP server from ${getTargetDisplayName(target)}.\n`
153
+ );
154
+ process.stdout.write(` Config: ${result.configPath}\n\n`);
155
+ process.stdout.write(
156
+ `Restart ${getTargetDisplayName(target)} to apply changes.\n`
157
+ );
158
+ }
@@ -0,0 +1,20 @@
1
+ /**
2
+ * MCP command - starts MCP server on stdio transport.
3
+ *
4
+ * @module src/cli/commands/mcp
5
+ */
6
+
7
+ import type { GlobalOptions } from '../context';
8
+
9
+ /**
10
+ * Start the MCP server.
11
+ * Reads global options for --index and --config flags.
12
+ */
13
+ export async function mcpCommand(options: GlobalOptions): Promise<void> {
14
+ const { startMcpServer } = await import('../../mcp/server.js');
15
+ await startMcpServer({
16
+ indexName: options.index,
17
+ configPath: options.config,
18
+ verbose: options.verbose,
19
+ });
20
+ }
@@ -0,0 +1,103 @@
1
+ /**
2
+ * gno models clear command implementation.
3
+ * Remove cached models.
4
+ *
5
+ * @module src/cli/commands/models/clear
6
+ */
7
+
8
+ import { getModelsCachePath } from '../../../app/constants';
9
+ import { ModelCache } from '../../../llm/cache';
10
+ import type { ModelType } from '../../../llm/types';
11
+
12
+ // ─────────────────────────────────────────────────────────────────────────────
13
+ // Types
14
+ // ─────────────────────────────────────────────────────────────────────────────
15
+
16
+ export interface ModelsClearOptions {
17
+ /** Clear all models */
18
+ all?: boolean;
19
+ /** Clear embedding model */
20
+ embed?: boolean;
21
+ /** Clear reranker model */
22
+ rerank?: boolean;
23
+ /** Clear generation model */
24
+ gen?: boolean;
25
+ /** Skip confirmation */
26
+ yes?: boolean;
27
+ }
28
+
29
+ export interface ModelsClearResult {
30
+ cleared: ModelType[];
31
+ sizeBefore: number;
32
+ sizeAfter: number;
33
+ }
34
+
35
+ // ─────────────────────────────────────────────────────────────────────────────
36
+ // Implementation
37
+ // ─────────────────────────────────────────────────────────────────────────────
38
+
39
+ /**
40
+ * Execute gno models clear command.
41
+ */
42
+ export async function modelsClear(
43
+ options: ModelsClearOptions = {}
44
+ ): Promise<ModelsClearResult> {
45
+ const cache = new ModelCache(getModelsCachePath());
46
+
47
+ // Determine which models to clear
48
+ let types: ModelType[] | undefined;
49
+
50
+ if (options.all) {
51
+ types = undefined; // Clear all
52
+ } else if (options.embed || options.rerank || options.gen) {
53
+ types = [];
54
+ if (options.embed) {
55
+ types.push('embed');
56
+ }
57
+ if (options.rerank) {
58
+ types.push('rerank');
59
+ }
60
+ if (options.gen) {
61
+ types.push('gen');
62
+ }
63
+ } else {
64
+ // Default: clear all
65
+ types = undefined;
66
+ }
67
+
68
+ const sizeBefore = await cache.totalSize();
69
+ await cache.clear(types);
70
+ const sizeAfter = await cache.totalSize();
71
+
72
+ return {
73
+ cleared: types ?? ['embed', 'rerank', 'gen'],
74
+ sizeBefore,
75
+ sizeAfter,
76
+ };
77
+ }
78
+
79
+ // ─────────────────────────────────────────────────────────────────────────────
80
+ // Formatting
81
+ // ─────────────────────────────────────────────────────────────────────────────
82
+
83
+ function formatBytes(bytes: number): string {
84
+ if (bytes === 0) {
85
+ return '0 B';
86
+ }
87
+ const k = 1024;
88
+ const sizes = ['B', 'KB', 'MB', 'GB'];
89
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
90
+ return `${(bytes / k ** i).toFixed(1)} ${sizes[i]}`;
91
+ }
92
+
93
+ /**
94
+ * Format models clear result for output.
95
+ */
96
+ export function formatModelsClear(result: ModelsClearResult): string {
97
+ const lines: string[] = [];
98
+
99
+ lines.push(`Cleared: ${result.cleared.join(', ')}`);
100
+ lines.push(`Freed: ${formatBytes(result.sizeBefore - result.sizeAfter)}`);
101
+
102
+ return lines.join('\n');
103
+ }
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Models commands public API.
3
+ *
4
+ * @module src/cli/commands/models
5
+ */
6
+
7
+ export {
8
+ formatModelsClear,
9
+ type ModelsClearOptions,
10
+ type ModelsClearResult,
11
+ modelsClear,
12
+ } from './clear';
13
+ export {
14
+ formatModelsList,
15
+ type ModelsListOptions,
16
+ type ModelsListResult,
17
+ modelsList,
18
+ } from './list';
19
+ export {
20
+ formatModelsPath,
21
+ type ModelsPathOptions,
22
+ type ModelsPathResult,
23
+ modelsPath,
24
+ } from './path';
25
+ export {
26
+ createProgressRenderer,
27
+ formatModelsPull,
28
+ type ModelPullResult,
29
+ type ModelsPullOptions,
30
+ type ModelsPullResult,
31
+ modelsPull,
32
+ } from './pull';
@@ -0,0 +1,214 @@
1
+ /**
2
+ * gno models list command implementation.
3
+ * List configured and available models.
4
+ *
5
+ * @module src/cli/commands/models/list
6
+ */
7
+
8
+ import { getModelsCachePath } from '../../../app/constants';
9
+ import { loadConfig } from '../../../config';
10
+ import { ModelCache } from '../../../llm/cache';
11
+ import { getActivePreset } from '../../../llm/registry';
12
+ import type { ModelStatus } from '../../../llm/types';
13
+
14
+ // ─────────────────────────────────────────────────────────────────────────────
15
+ // Types
16
+ // ─────────────────────────────────────────────────────────────────────────────
17
+
18
+ export interface ModelsListOptions {
19
+ /** Override config path */
20
+ configPath?: string;
21
+ /** Output as JSON */
22
+ json?: boolean;
23
+ /** Output as Markdown */
24
+ md?: boolean;
25
+ }
26
+
27
+ export interface PresetInfo {
28
+ id: string;
29
+ name: string;
30
+ active: boolean;
31
+ }
32
+
33
+ export interface ModelsListResult {
34
+ activePreset: string;
35
+ presets: PresetInfo[];
36
+ embed: ModelStatus;
37
+ rerank: ModelStatus;
38
+ gen: ModelStatus;
39
+ cacheDir: string;
40
+ totalSize: number;
41
+ }
42
+
43
+ // ─────────────────────────────────────────────────────────────────────────────
44
+ // Implementation
45
+ // ─────────────────────────────────────────────────────────────────────────────
46
+
47
+ async function getModelStatus(
48
+ cache: ModelCache,
49
+ uri: string
50
+ ): Promise<ModelStatus> {
51
+ const cached = await cache.getCachedPath(uri);
52
+ if (cached) {
53
+ const entries = await cache.list();
54
+ const entry = entries.find((e) => e.uri === uri);
55
+ return {
56
+ uri,
57
+ cached: true,
58
+ path: cached,
59
+ size: entry?.size,
60
+ };
61
+ }
62
+ return {
63
+ uri,
64
+ cached: false,
65
+ path: null,
66
+ };
67
+ }
68
+
69
+ /**
70
+ * Execute gno models list command.
71
+ */
72
+ export async function modelsList(
73
+ options: ModelsListOptions = {}
74
+ ): Promise<ModelsListResult> {
75
+ // Load config (use defaults if not initialized)
76
+ const { createDefaultConfig } = await import('../../../config');
77
+ const { getModelConfig, listPresets } = await import('../../../llm/registry');
78
+ const configResult = await loadConfig(options.configPath);
79
+ const config = configResult.ok ? configResult.value : createDefaultConfig();
80
+
81
+ const modelConfig = getModelConfig(config);
82
+ const allPresets = listPresets(config);
83
+ const preset = getActivePreset(config);
84
+ const cache = new ModelCache(getModelsCachePath());
85
+
86
+ const [embed, rerank, gen] = await Promise.all([
87
+ getModelStatus(cache, preset.embed),
88
+ getModelStatus(cache, preset.rerank),
89
+ getModelStatus(cache, preset.gen),
90
+ ]);
91
+
92
+ return {
93
+ activePreset: modelConfig.activePreset,
94
+ presets: allPresets.map((p) => ({
95
+ id: p.id,
96
+ name: p.name,
97
+ active: p.id === modelConfig.activePreset,
98
+ })),
99
+ embed,
100
+ rerank,
101
+ gen,
102
+ cacheDir: cache.dir,
103
+ totalSize: await cache.totalSize(),
104
+ };
105
+ }
106
+
107
+ // ─────────────────────────────────────────────────────────────────────────────
108
+ // Formatting
109
+ // ─────────────────────────────────────────────────────────────────────────────
110
+
111
+ function formatBytes(bytes: number): string {
112
+ if (bytes === 0) {
113
+ return '0 B';
114
+ }
115
+ const k = 1024;
116
+ const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
117
+ const i = Math.min(
118
+ Math.floor(Math.log(bytes) / Math.log(k)),
119
+ sizes.length - 1
120
+ );
121
+ return `${(bytes / k ** i).toFixed(1)} ${sizes[i]}`;
122
+ }
123
+
124
+ function formatTerminal(result: ModelsListResult): string {
125
+ const lines: string[] = [];
126
+
127
+ // Show presets
128
+ lines.push('Presets:');
129
+ for (const p of result.presets) {
130
+ const marker = p.active ? '>' : ' ';
131
+ lines.push(` ${marker} ${p.id}: ${p.name}`);
132
+ }
133
+ lines.push('');
134
+
135
+ // Show models for active preset
136
+ lines.push(`Models (${result.activePreset}):`);
137
+
138
+ const statusIcon = (s: ModelStatus) => (s.cached ? '✓' : '✗');
139
+
140
+ lines.push(
141
+ ` embed: ${statusIcon(result.embed)} ${result.embed.uri}` +
142
+ (result.embed.size ? ` (${formatBytes(result.embed.size)})` : '')
143
+ );
144
+ lines.push(
145
+ ` rerank: ${statusIcon(result.rerank)} ${result.rerank.uri}` +
146
+ (result.rerank.size ? ` (${formatBytes(result.rerank.size)})` : '')
147
+ );
148
+ lines.push(
149
+ ` gen: ${statusIcon(result.gen)} ${result.gen.uri}` +
150
+ (result.gen.size ? ` (${formatBytes(result.gen.size)})` : '')
151
+ );
152
+
153
+ lines.push('');
154
+ lines.push(`Cache: ${result.cacheDir}`);
155
+ lines.push(`Total size: ${formatBytes(result.totalSize)}`);
156
+
157
+ const allCached =
158
+ result.embed.cached && result.rerank.cached && result.gen.cached;
159
+ if (!allCached) {
160
+ lines.push('');
161
+ lines.push('Run: gno models pull --all');
162
+ }
163
+
164
+ lines.push('');
165
+ lines.push('Switch preset: gno models use <preset>');
166
+
167
+ return lines.join('\n');
168
+ }
169
+
170
+ function formatMarkdown(result: ModelsListResult): string {
171
+ const lines: string[] = [];
172
+
173
+ lines.push('# Models');
174
+ lines.push('');
175
+ lines.push('| Type | URI | Cached | Size |');
176
+ lines.push('|------|-----|--------|------|');
177
+
178
+ const status = (s: ModelStatus) => (s.cached ? '✓' : '✗');
179
+ const size = (s: ModelStatus) => (s.size ? formatBytes(s.size) : '-');
180
+
181
+ lines.push(
182
+ `| embed | ${result.embed.uri} | ${status(result.embed)} | ${size(result.embed)} |`
183
+ );
184
+ lines.push(
185
+ `| rerank | ${result.rerank.uri} | ${status(result.rerank)} | ${size(result.rerank)} |`
186
+ );
187
+ lines.push(
188
+ `| gen | ${result.gen.uri} | ${status(result.gen)} | ${size(result.gen)} |`
189
+ );
190
+
191
+ lines.push('');
192
+ lines.push(`**Cache**: ${result.cacheDir}`);
193
+ lines.push(`**Total size**: ${formatBytes(result.totalSize)}`);
194
+
195
+ return lines.join('\n');
196
+ }
197
+
198
+ /**
199
+ * Format models list result for output.
200
+ */
201
+ export function formatModelsList(
202
+ result: ModelsListResult,
203
+ options: ModelsListOptions
204
+ ): string {
205
+ if (options.json) {
206
+ return JSON.stringify(result, null, 2);
207
+ }
208
+
209
+ if (options.md) {
210
+ return formatMarkdown(result);
211
+ }
212
+
213
+ return formatTerminal(result);
214
+ }
@@ -0,0 +1,51 @@
1
+ /**
2
+ * gno models path command implementation.
3
+ * Print model cache directory.
4
+ *
5
+ * @module src/cli/commands/models/path
6
+ */
7
+
8
+ import { getModelsCachePath } from '../../../app/constants';
9
+
10
+ // ─────────────────────────────────────────────────────────────────────────────
11
+ // Types
12
+ // ─────────────────────────────────────────────────────────────────────────────
13
+
14
+ export interface ModelsPathOptions {
15
+ /** Output as JSON */
16
+ json?: boolean;
17
+ }
18
+
19
+ export interface ModelsPathResult {
20
+ path: string;
21
+ }
22
+
23
+ // ─────────────────────────────────────────────────────────────────────────────
24
+ // Implementation
25
+ // ─────────────────────────────────────────────────────────────────────────────
26
+
27
+ /**
28
+ * Execute gno models path command.
29
+ */
30
+ export function modelsPath(): ModelsPathResult {
31
+ return {
32
+ path: getModelsCachePath(),
33
+ };
34
+ }
35
+
36
+ // ─────────────────────────────────────────────────────────────────────────────
37
+ // Formatting
38
+ // ─────────────────────────────────────────────────────────────────────────────
39
+
40
+ /**
41
+ * Format models path result for output.
42
+ */
43
+ export function formatModelsPath(
44
+ result: ModelsPathResult,
45
+ options: ModelsPathOptions
46
+ ): string {
47
+ if (options.json) {
48
+ return JSON.stringify(result, null, 2);
49
+ }
50
+ return result.path;
51
+ }