@aeye/context 0.3.9

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 ADDED
@@ -0,0 +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. |
@@ -0,0 +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
+ }
package/package.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "@aeye/context",
3
+ "version": "0.3.9",
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
+ "type": "module",
6
+ "license": "GPL-3.0",
7
+ "author": "ClickerMonkey",
8
+ "publishConfig": {
9
+ "access": "public"
10
+ },
11
+ "repository": {
12
+ "type": "git",
13
+ "url": "https://github.com/ClickerMonkey/aeye.git",
14
+ "directory": "packages/context"
15
+ },
16
+ "bin": {
17
+ "aeye-context": "bin/aeye-context.mjs"
18
+ },
19
+ "files": [
20
+ "bin",
21
+ "README.md"
22
+ ],
23
+ "keywords": [
24
+ "aeye",
25
+ "context",
26
+ "docs",
27
+ "llm",
28
+ "agent",
29
+ "cli"
30
+ ]
31
+ }