lat.md 0.4.0 → 0.4.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.
- package/README.md +10 -1
- package/dist/src/cli/check.js +9 -2
- package/dist/src/cli/index.js +10 -1
- package/dist/src/cli/search.js +11 -4
- package/dist/src/config.d.ts +4 -2
- package/dist/src/config.js +27 -3
- package/dist/src/mcp/server.js +11 -2
- package/package.json +1 -1
- package/templates/AGENTS.md +1 -1
package/README.md
CHANGED
|
@@ -29,7 +29,7 @@ npm install -g lat.md
|
|
|
29
29
|
|
|
30
30
|
Or use directly with `npx lat.md@latest <command>`.
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
After installing, run `lat init` in the repo you want to use lat in.
|
|
33
33
|
|
|
34
34
|
## How it works
|
|
35
35
|
|
|
@@ -58,6 +58,15 @@ npx lat.md search "how do we auth?" # semantic search via embeddings
|
|
|
58
58
|
npx lat.md prompt "fix [[OAuth Flow]]" # expand [[refs]] in a prompt for agents
|
|
59
59
|
```
|
|
60
60
|
|
|
61
|
+
## Configuration
|
|
62
|
+
|
|
63
|
+
Semantic search (`lat search`) requires an OpenAI (`sk-...`) or Vercel AI Gateway (`vck_...`) API key. The key is resolved in order:
|
|
64
|
+
|
|
65
|
+
1. `LAT_LLM_KEY` env var — direct value
|
|
66
|
+
2. `LAT_LLM_KEY_FILE` env var — path to a file containing the key
|
|
67
|
+
3. `LAT_LLM_KEY_HELPER` env var — shell command that prints the key (10s timeout)
|
|
68
|
+
4. Config file — saved by `lat init`. Run `lat config` to see its location.
|
|
69
|
+
|
|
61
70
|
## Development
|
|
62
71
|
|
|
63
72
|
Requires Node.js 22+ and pnpm.
|
package/dist/src/cli/check.js
CHANGED
|
@@ -289,10 +289,17 @@ export async function checkAllCmd(ctx) {
|
|
|
289
289
|
process.exit(1);
|
|
290
290
|
console.log(ctx.chalk.green('All checks passed'));
|
|
291
291
|
const { getLlmKey } = await import('../config.js');
|
|
292
|
-
|
|
292
|
+
let hasKey = false;
|
|
293
|
+
try {
|
|
294
|
+
hasKey = !!getLlmKey();
|
|
295
|
+
}
|
|
296
|
+
catch {
|
|
297
|
+
// key resolution failed (e.g. empty file) — treat as missing
|
|
298
|
+
}
|
|
299
|
+
if (!hasKey) {
|
|
293
300
|
console.log(ctx.chalk.yellow('Warning:') +
|
|
294
301
|
' No LLM key found — semantic search (lat search) will not work.' +
|
|
295
|
-
'
|
|
302
|
+
' Provide a key via LAT_LLM_KEY, LAT_LLM_KEY_FILE, LAT_LLM_KEY_HELPER, or run ' +
|
|
296
303
|
ctx.chalk.cyan('lat init') +
|
|
297
304
|
' to configure.');
|
|
298
305
|
}
|
package/dist/src/cli/index.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
if (!process.argv.includes('--verbose')) {
|
|
4
4
|
process.noDeprecation = true;
|
|
5
5
|
}
|
|
6
|
-
import { readFileSync } from 'node:fs';
|
|
6
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
7
7
|
import { dirname, join } from 'node:path';
|
|
8
8
|
import { fileURLToPath } from 'node:url';
|
|
9
9
|
import { Command } from 'commander';
|
|
@@ -145,4 +145,13 @@ program
|
|
|
145
145
|
const { startMcpServer } = await import('../mcp/server.js');
|
|
146
146
|
await startMcpServer();
|
|
147
147
|
});
|
|
148
|
+
program
|
|
149
|
+
.command('config')
|
|
150
|
+
.description('Show configuration file path')
|
|
151
|
+
.action(async () => {
|
|
152
|
+
const { getConfigPath } = await import('../config.js');
|
|
153
|
+
const configPath = getConfigPath();
|
|
154
|
+
const exists = existsSync(configPath);
|
|
155
|
+
console.log(`Config file: ${configPath}${exists ? '' : ' (not found)'}`);
|
|
156
|
+
});
|
|
148
157
|
await program.parseAsync();
|
package/dist/src/cli/search.js
CHANGED
|
@@ -7,12 +7,19 @@ import { loadAllSections, flattenSections } from '../lattice.js';
|
|
|
7
7
|
import { formatResultList } from '../format.js';
|
|
8
8
|
import { getLlmKey, getConfigPath } from '../config.js';
|
|
9
9
|
export async function searchCmd(ctx, query, opts) {
|
|
10
|
-
|
|
10
|
+
let key;
|
|
11
|
+
try {
|
|
12
|
+
key = getLlmKey();
|
|
13
|
+
}
|
|
14
|
+
catch (err) {
|
|
15
|
+
console.error(chalk.red(err.message));
|
|
16
|
+
process.exit(1);
|
|
17
|
+
}
|
|
11
18
|
if (!key) {
|
|
12
|
-
console.error(chalk.red('
|
|
13
|
-
'
|
|
19
|
+
console.error(chalk.red('No API key configured.') +
|
|
20
|
+
' Provide a key via LAT_LLM_KEY, LAT_LLM_KEY_FILE, LAT_LLM_KEY_HELPER, or run ' +
|
|
14
21
|
chalk.cyan('lat init') +
|
|
15
|
-
' to save
|
|
22
|
+
' to save one in ' +
|
|
16
23
|
chalk.dim(getConfigPath()) +
|
|
17
24
|
'.');
|
|
18
25
|
process.exit(1);
|
package/dist/src/config.d.ts
CHANGED
|
@@ -8,8 +8,10 @@ export declare function writeConfig(config: LatConfig): void;
|
|
|
8
8
|
/**
|
|
9
9
|
* Returns the LLM key from (in priority order):
|
|
10
10
|
* 1. LAT_LLM_KEY environment variable
|
|
11
|
-
* 2.
|
|
11
|
+
* 2. LAT_LLM_KEY_FILE — path to a file containing the key
|
|
12
|
+
* 3. LAT_LLM_KEY_HELPER — shell command that prints the key
|
|
13
|
+
* 4. llm_key field in ~/.config/lat/config.json
|
|
12
14
|
*
|
|
13
|
-
* Returns undefined if
|
|
15
|
+
* Returns undefined if none is set.
|
|
14
16
|
*/
|
|
15
17
|
export declare function getLlmKey(): string | undefined;
|
package/dist/src/config.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { execSync } from 'node:child_process';
|
|
1
2
|
import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';
|
|
2
3
|
import { join } from 'node:path';
|
|
3
4
|
import xdg from '@folder/xdg';
|
|
@@ -28,14 +29,37 @@ export function writeConfig(config) {
|
|
|
28
29
|
/**
|
|
29
30
|
* Returns the LLM key from (in priority order):
|
|
30
31
|
* 1. LAT_LLM_KEY environment variable
|
|
31
|
-
* 2.
|
|
32
|
+
* 2. LAT_LLM_KEY_FILE — path to a file containing the key
|
|
33
|
+
* 3. LAT_LLM_KEY_HELPER — shell command that prints the key
|
|
34
|
+
* 4. llm_key field in ~/.config/lat/config.json
|
|
32
35
|
*
|
|
33
|
-
* Returns undefined if
|
|
36
|
+
* Returns undefined if none is set.
|
|
34
37
|
*/
|
|
35
38
|
export function getLlmKey() {
|
|
36
39
|
const envKey = process.env.LAT_LLM_KEY;
|
|
37
40
|
if (envKey)
|
|
38
41
|
return envKey;
|
|
42
|
+
const file = process.env.LAT_LLM_KEY_FILE;
|
|
43
|
+
if (file) {
|
|
44
|
+
const content = readFileSync(file, 'utf-8').trim();
|
|
45
|
+
if (!content) {
|
|
46
|
+
throw new Error(`LAT_LLM_KEY_FILE (${file}) is empty.`);
|
|
47
|
+
}
|
|
48
|
+
return content;
|
|
49
|
+
}
|
|
50
|
+
const helper = process.env.LAT_LLM_KEY_HELPER;
|
|
51
|
+
if (helper) {
|
|
52
|
+
const result = execSync(helper, {
|
|
53
|
+
encoding: 'utf-8',
|
|
54
|
+
timeout: 10_000,
|
|
55
|
+
}).trim();
|
|
56
|
+
if (!result) {
|
|
57
|
+
throw new Error('LAT_LLM_KEY_HELPER command returned an empty string.');
|
|
58
|
+
}
|
|
59
|
+
return result;
|
|
60
|
+
}
|
|
39
61
|
const config = readConfig();
|
|
40
|
-
|
|
62
|
+
if (config.llm_key)
|
|
63
|
+
return config.llm_key;
|
|
64
|
+
return undefined;
|
|
41
65
|
}
|
package/dist/src/mcp/server.js
CHANGED
|
@@ -70,13 +70,22 @@ export async function startMcpServer() {
|
|
|
70
70
|
.describe('Max results (default 5)'),
|
|
71
71
|
}, async ({ query, limit }) => {
|
|
72
72
|
const { getLlmKey } = await import('../config.js');
|
|
73
|
-
|
|
73
|
+
let key;
|
|
74
|
+
try {
|
|
75
|
+
key = getLlmKey();
|
|
76
|
+
}
|
|
77
|
+
catch (err) {
|
|
78
|
+
return {
|
|
79
|
+
content: [{ type: 'text', text: err.message }],
|
|
80
|
+
isError: true,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
74
83
|
if (!key) {
|
|
75
84
|
return {
|
|
76
85
|
content: [
|
|
77
86
|
{
|
|
78
87
|
type: 'text',
|
|
79
|
-
text: 'No LLM key found.
|
|
88
|
+
text: 'No LLM key found. Provide a key via LAT_LLM_KEY, LAT_LLM_KEY_FILE, LAT_LLM_KEY_HELPER, or run `lat init`.',
|
|
80
89
|
},
|
|
81
90
|
],
|
|
82
91
|
isError: true,
|
package/package.json
CHANGED
package/templates/AGENTS.md
CHANGED
|
@@ -29,7 +29,7 @@ lat check # validate all links and code refs
|
|
|
29
29
|
|
|
30
30
|
Run `lat --help` when in doubt about available commands or options.
|
|
31
31
|
|
|
32
|
-
If `lat search` fails because
|
|
32
|
+
If `lat search` fails because no API key is configured, explain to the user that semantic search requires a key provided via `LAT_LLM_KEY` (direct value), `LAT_LLM_KEY_FILE` (path to key file), or `LAT_LLM_KEY_HELPER` (command that prints the key). Supported key prefixes: `sk-...` (OpenAI) or `vck_...` (Vercel). If the user doesn't want to set it up, use `lat locate` for direct lookups instead.
|
|
33
33
|
|
|
34
34
|
# Syntax primer
|
|
35
35
|
|