@aeye/context 0.3.9 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +42 -42
- package/bin/aeye-context.mjs +116 -116
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,42 +1,42 @@
|
|
|
1
|
-
# @aeye/context
|
|
2
|
-
|
|
3
|
-
Pull **@aeye's agent context** — the flat agent-reference docs — into your repo with one command.
|
|
4
|
-
|
|
5
|
-
Each `@aeye/*` package ships LLM/agent docs as flat markdown: an `aeye-<pkg>.md` reference (some
|
|
6
|
-
packages add topic sub-docs like `aeye-core-tools.md`), cross-linked as flat siblings
|
|
7
|
-
(`./aeye-core-types.md`). Those files ship inside each installed package
|
|
8
|
-
(`node_modules/@aeye/core/aeye-core.md`, …). This CLI copies every installed package's doc into one
|
|
9
|
-
flat folder and generates an `aeye.md` index, so the links actually resolve — on GitHub, in your
|
|
10
|
-
editor, and when you point a coding agent at them.
|
|
11
|
-
|
|
12
|
-
## Usage
|
|
13
|
-
|
|
14
|
-
```bash
|
|
15
|
-
npx @aeye/context # → ./docs
|
|
16
|
-
npx @aeye/context .aeye # → any target directory
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
Run it from your project root (wherever `node_modules/` lives). Re-run after adding or upgrading
|
|
20
|
-
`@aeye/*` packages to resync. To wire it into your project:
|
|
21
|
-
|
|
22
|
-
```jsonc
|
|
23
|
-
// package.json
|
|
24
|
-
"scripts": { "context:sync": "aeye-context" }
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
## What it does
|
|
28
|
-
|
|
29
|
-
1. Scans `node_modules/@aeye/*` (and pnpm's virtual store) for `aeye-*.md` files and copies each,
|
|
30
|
-
flat, into the target folder. Deduped by filename; direct dependencies win.
|
|
31
|
-
2. Writes a generated **`aeye.md`** index — a table linking to every synced doc, labelled by each
|
|
32
|
-
file's title. (Unlike some monorepos, `@aeye` has no hand-written root router, so the index is
|
|
33
|
-
generated from whatever is installed — it never lists docs you don't have.)
|
|
34
|
-
|
|
35
|
-
Only files are written — nothing is deleted from the target.
|
|
36
|
-
|
|
37
|
-
## Options
|
|
38
|
-
|
|
39
|
-
| Arg | Meaning |
|
|
40
|
-
| --- | --- |
|
|
41
|
-
| `[target-dir]` | Where to write the flat docs + index. Default: `docs`. |
|
|
42
|
-
| `--help` | Show usage. |
|
|
1
|
+
# @aeye/context
|
|
2
|
+
|
|
3
|
+
Pull **@aeye's agent context** — the flat agent-reference docs — into your repo with one command.
|
|
4
|
+
|
|
5
|
+
Each `@aeye/*` package ships LLM/agent docs as flat markdown: an `aeye-<pkg>.md` reference (some
|
|
6
|
+
packages add topic sub-docs like `aeye-core-tools.md`), cross-linked as flat siblings
|
|
7
|
+
(`./aeye-core-types.md`). Those files ship inside each installed package
|
|
8
|
+
(`node_modules/@aeye/core/aeye-core.md`, …). This CLI copies every installed package's doc into one
|
|
9
|
+
flat folder and generates an `aeye.md` index, so the links actually resolve — on GitHub, in your
|
|
10
|
+
editor, and when you point a coding agent at them.
|
|
11
|
+
|
|
12
|
+
## Usage
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npx @aeye/context # → ./docs
|
|
16
|
+
npx @aeye/context .aeye # → any target directory
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Run it from your project root (wherever `node_modules/` lives). Re-run after adding or upgrading
|
|
20
|
+
`@aeye/*` packages to resync. To wire it into your project:
|
|
21
|
+
|
|
22
|
+
```jsonc
|
|
23
|
+
// package.json
|
|
24
|
+
"scripts": { "context:sync": "aeye-context" }
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## What it does
|
|
28
|
+
|
|
29
|
+
1. Scans `node_modules/@aeye/*` (and pnpm's virtual store) for `aeye-*.md` files and copies each,
|
|
30
|
+
flat, into the target folder. Deduped by filename; direct dependencies win.
|
|
31
|
+
2. Writes a generated **`aeye.md`** index — a table linking to every synced doc, labelled by each
|
|
32
|
+
file's title. (Unlike some monorepos, `@aeye` has no hand-written root router, so the index is
|
|
33
|
+
generated from whatever is installed — it never lists docs you don't have.)
|
|
34
|
+
|
|
35
|
+
Only files are written — nothing is deleted from the target.
|
|
36
|
+
|
|
37
|
+
## Options
|
|
38
|
+
|
|
39
|
+
| Arg | Meaning |
|
|
40
|
+
| --- | --- |
|
|
41
|
+
| `[target-dir]` | Where to write the flat docs + index. Default: `docs`. |
|
|
42
|
+
| `--help` | Show usage. |
|
package/bin/aeye-context.mjs
CHANGED
|
@@ -1,116 +1,116 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* aeye-context — flatten the @aeye agent-reference docs into your repo.
|
|
4
|
-
*
|
|
5
|
-
* Each `@aeye/*` package ships flat `aeye-<pkg>.md` docs in its package root
|
|
6
|
-
* (`node_modules/@aeye/<pkg>/aeye-<pkg>.md`), and those docs cross-link as flat siblings
|
|
7
|
-
* (`./aeye-core-types.md`). This copies every installed package's doc(s) into one flat folder and
|
|
8
|
-
* writes a generated `aeye.md` index, so the links resolve — on GitHub, in your editor, and when
|
|
9
|
-
* handed to a coding agent.
|
|
10
|
-
*
|
|
11
|
-
* npx @aeye/context # → ./docs
|
|
12
|
-
* npx @aeye/context .aeye # → any target directory
|
|
13
|
-
*
|
|
14
|
-
* Re-run after adding/upgrading @aeye packages to resync.
|
|
15
|
-
*/
|
|
16
|
-
import { readdirSync, mkdirSync, copyFileSync, existsSync, readFileSync, writeFileSync, statSync } from 'node:fs';
|
|
17
|
-
import { join } from 'node:path';
|
|
18
|
-
|
|
19
|
-
const args = process.argv.slice(2);
|
|
20
|
-
if (args.includes('--help') || args.includes('-h')) {
|
|
21
|
-
console.log(`Usage: aeye-context [target-dir]
|
|
22
|
-
|
|
23
|
-
target-dir where to write the flat docs + generated index (default: docs)
|
|
24
|
-
|
|
25
|
-
Scans node_modules for every installed @aeye/* package's aeye-*.md, copies them flat into
|
|
26
|
-
<target-dir>, and writes an aeye.md index linking to them.`);
|
|
27
|
-
process.exit(0);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const target = args.find((a) => !a.startsWith('-')) ?? 'docs';
|
|
31
|
-
const DOC_RE = /^aeye-.*\.md$/;
|
|
32
|
-
|
|
33
|
-
/** Directories that may hold an installed @aeye package. Direct deps first (they win on dedup). */
|
|
34
|
-
function scopeDirs() {
|
|
35
|
-
const dirs = [];
|
|
36
|
-
const scope = join('node_modules', '@aeye');
|
|
37
|
-
if (existsSync(scope)) {
|
|
38
|
-
for (const name of readdirSync(scope)) dirs.push(join(scope, name));
|
|
39
|
-
}
|
|
40
|
-
// pnpm keeps transitive deps only under the virtual store (harmless no-op on npm/yarn).
|
|
41
|
-
const store = join('node_modules', '.pnpm');
|
|
42
|
-
if (existsSync(store)) {
|
|
43
|
-
for (const entry of readdirSync(store)) {
|
|
44
|
-
const nested = join(store, entry, 'node_modules', '@aeye');
|
|
45
|
-
if (existsSync(nested)) {
|
|
46
|
-
for (const name of readdirSync(nested)) dirs.push(join(nested, name));
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
return dirs;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// Collect docs, deduped by filename (first occurrence — a direct dep — wins).
|
|
54
|
-
const found = new Map(); // filename -> absolute source path
|
|
55
|
-
for (const dir of scopeDirs()) {
|
|
56
|
-
let files;
|
|
57
|
-
try {
|
|
58
|
-
if (!statSync(dir).isDirectory()) continue;
|
|
59
|
-
files = readdirSync(dir);
|
|
60
|
-
} catch {
|
|
61
|
-
continue;
|
|
62
|
-
}
|
|
63
|
-
for (const f of files) {
|
|
64
|
-
if (DOC_RE.test(f) && !found.has(f)) found.set(f, join(dir, f));
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
mkdirSync(target, { recursive: true });
|
|
69
|
-
|
|
70
|
-
/** The first `# ` heading of a markdown file, for the index label. */
|
|
71
|
-
const firstHeading = (text) => {
|
|
72
|
-
const m = text.match(/^#\s+(.+)$/m);
|
|
73
|
-
return m ? m[1].trim() : '';
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
// Copy each doc; capture its title for the index.
|
|
77
|
-
const entries = [];
|
|
78
|
-
for (const [name, src] of found) {
|
|
79
|
-
const text = readFileSync(src, 'utf8');
|
|
80
|
-
writeFileSync(join(target, name), text);
|
|
81
|
-
entries.push({ file: name, title: firstHeading(text) });
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
// Sort: group by package, the main doc (aeye-<pkg>.md) before its sub-docs, then alphabetical.
|
|
85
|
-
const keyOf = (file) => {
|
|
86
|
-
const base = file.replace(/^aeye-/, '').replace(/\.md$/, '');
|
|
87
|
-
const pkg = base.split('-')[0];
|
|
88
|
-
return { pkg, isSub: base === pkg ? 0 : 1, base };
|
|
89
|
-
};
|
|
90
|
-
entries.sort((a, b) => {
|
|
91
|
-
const ka = keyOf(a.file);
|
|
92
|
-
const kb = keyOf(b.file);
|
|
93
|
-
return ka.pkg.localeCompare(kb.pkg) || ka.isSub - kb.isSub || ka.base.localeCompare(kb.base);
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
// Generate the index (@aeye has no hand-written root router, so we build one from what's present).
|
|
97
|
-
const rows = entries.map((e) => `| [\`${e.file}\`](./${e.file}) | ${e.title} |`).join('\n');
|
|
98
|
-
const index = `<!-- Generated by @aeye/context — re-run \`npx @aeye/context\` to refresh. Do not edit by hand. -->
|
|
99
|
-
|
|
100
|
-
# @aeye — agent reference
|
|
101
|
-
|
|
102
|
-
Flattened agent docs for the \`@aeye/*\` packages installed in this project. Point your coding agent
|
|
103
|
-
(or your editor) at this folder: the \`./aeye-*.md\` links below — and the cross-links inside each
|
|
104
|
-
doc — resolve here.
|
|
105
|
-
|
|
106
|
-
| Doc | About |
|
|
107
|
-
| --- | --- |
|
|
108
|
-
${rows}
|
|
109
|
-
`;
|
|
110
|
-
writeFileSync(join(target, 'aeye.md'), index);
|
|
111
|
-
|
|
112
|
-
if (found.size === 0) {
|
|
113
|
-
console.warn('aeye-context: no @aeye/* packages found under node_modules — wrote an empty index.');
|
|
114
|
-
} else {
|
|
115
|
-
console.log(`aeye-context: synced ${found.size} doc(s) + aeye.md index → ${target}/`);
|
|
116
|
-
}
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* aeye-context — flatten the @aeye agent-reference docs into your repo.
|
|
4
|
+
*
|
|
5
|
+
* Each `@aeye/*` package ships flat `aeye-<pkg>.md` docs in its package root
|
|
6
|
+
* (`node_modules/@aeye/<pkg>/aeye-<pkg>.md`), and those docs cross-link as flat siblings
|
|
7
|
+
* (`./aeye-core-types.md`). This copies every installed package's doc(s) into one flat folder and
|
|
8
|
+
* writes a generated `aeye.md` index, so the links resolve — on GitHub, in your editor, and when
|
|
9
|
+
* handed to a coding agent.
|
|
10
|
+
*
|
|
11
|
+
* npx @aeye/context # → ./docs
|
|
12
|
+
* npx @aeye/context .aeye # → any target directory
|
|
13
|
+
*
|
|
14
|
+
* Re-run after adding/upgrading @aeye packages to resync.
|
|
15
|
+
*/
|
|
16
|
+
import { readdirSync, mkdirSync, copyFileSync, existsSync, readFileSync, writeFileSync, statSync } from 'node:fs';
|
|
17
|
+
import { join } from 'node:path';
|
|
18
|
+
|
|
19
|
+
const args = process.argv.slice(2);
|
|
20
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
21
|
+
console.log(`Usage: aeye-context [target-dir]
|
|
22
|
+
|
|
23
|
+
target-dir where to write the flat docs + generated index (default: docs)
|
|
24
|
+
|
|
25
|
+
Scans node_modules for every installed @aeye/* package's aeye-*.md, copies them flat into
|
|
26
|
+
<target-dir>, and writes an aeye.md index linking to them.`);
|
|
27
|
+
process.exit(0);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const target = args.find((a) => !a.startsWith('-')) ?? 'docs';
|
|
31
|
+
const DOC_RE = /^aeye-.*\.md$/;
|
|
32
|
+
|
|
33
|
+
/** Directories that may hold an installed @aeye package. Direct deps first (they win on dedup). */
|
|
34
|
+
function scopeDirs() {
|
|
35
|
+
const dirs = [];
|
|
36
|
+
const scope = join('node_modules', '@aeye');
|
|
37
|
+
if (existsSync(scope)) {
|
|
38
|
+
for (const name of readdirSync(scope)) dirs.push(join(scope, name));
|
|
39
|
+
}
|
|
40
|
+
// pnpm keeps transitive deps only under the virtual store (harmless no-op on npm/yarn).
|
|
41
|
+
const store = join('node_modules', '.pnpm');
|
|
42
|
+
if (existsSync(store)) {
|
|
43
|
+
for (const entry of readdirSync(store)) {
|
|
44
|
+
const nested = join(store, entry, 'node_modules', '@aeye');
|
|
45
|
+
if (existsSync(nested)) {
|
|
46
|
+
for (const name of readdirSync(nested)) dirs.push(join(nested, name));
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return dirs;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Collect docs, deduped by filename (first occurrence — a direct dep — wins).
|
|
54
|
+
const found = new Map(); // filename -> absolute source path
|
|
55
|
+
for (const dir of scopeDirs()) {
|
|
56
|
+
let files;
|
|
57
|
+
try {
|
|
58
|
+
if (!statSync(dir).isDirectory()) continue;
|
|
59
|
+
files = readdirSync(dir);
|
|
60
|
+
} catch {
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
for (const f of files) {
|
|
64
|
+
if (DOC_RE.test(f) && !found.has(f)) found.set(f, join(dir, f));
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
mkdirSync(target, { recursive: true });
|
|
69
|
+
|
|
70
|
+
/** The first `# ` heading of a markdown file, for the index label. */
|
|
71
|
+
const firstHeading = (text) => {
|
|
72
|
+
const m = text.match(/^#\s+(.+)$/m);
|
|
73
|
+
return m ? m[1].trim() : '';
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
// Copy each doc; capture its title for the index.
|
|
77
|
+
const entries = [];
|
|
78
|
+
for (const [name, src] of found) {
|
|
79
|
+
const text = readFileSync(src, 'utf8');
|
|
80
|
+
writeFileSync(join(target, name), text);
|
|
81
|
+
entries.push({ file: name, title: firstHeading(text) });
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Sort: group by package, the main doc (aeye-<pkg>.md) before its sub-docs, then alphabetical.
|
|
85
|
+
const keyOf = (file) => {
|
|
86
|
+
const base = file.replace(/^aeye-/, '').replace(/\.md$/, '');
|
|
87
|
+
const pkg = base.split('-')[0];
|
|
88
|
+
return { pkg, isSub: base === pkg ? 0 : 1, base };
|
|
89
|
+
};
|
|
90
|
+
entries.sort((a, b) => {
|
|
91
|
+
const ka = keyOf(a.file);
|
|
92
|
+
const kb = keyOf(b.file);
|
|
93
|
+
return ka.pkg.localeCompare(kb.pkg) || ka.isSub - kb.isSub || ka.base.localeCompare(kb.base);
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
// Generate the index (@aeye has no hand-written root router, so we build one from what's present).
|
|
97
|
+
const rows = entries.map((e) => `| [\`${e.file}\`](./${e.file}) | ${e.title} |`).join('\n');
|
|
98
|
+
const index = `<!-- Generated by @aeye/context — re-run \`npx @aeye/context\` to refresh. Do not edit by hand. -->
|
|
99
|
+
|
|
100
|
+
# @aeye — agent reference
|
|
101
|
+
|
|
102
|
+
Flattened agent docs for the \`@aeye/*\` packages installed in this project. Point your coding agent
|
|
103
|
+
(or your editor) at this folder: the \`./aeye-*.md\` links below — and the cross-links inside each
|
|
104
|
+
doc — resolve here.
|
|
105
|
+
|
|
106
|
+
| Doc | About |
|
|
107
|
+
| --- | --- |
|
|
108
|
+
${rows}
|
|
109
|
+
`;
|
|
110
|
+
writeFileSync(join(target, 'aeye.md'), index);
|
|
111
|
+
|
|
112
|
+
if (found.size === 0) {
|
|
113
|
+
console.warn('aeye-context: no @aeye/* packages found under node_modules — wrote an empty index.');
|
|
114
|
+
} else {
|
|
115
|
+
console.log(`aeye-context: synced ${found.size} doc(s) + aeye.md index → ${target}/`);
|
|
116
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aeye/context",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "Pull @aeye's agent context into your repo — flatten every installed @aeye/* package's aeye-*.md into one folder (with a generated index) to point a coding agent at.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "GPL-3.0",
|