@oddkin/analyzer 0.0.0-stage → 1.0.0-beta.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 (103) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +40 -2
  3. package/dist/bin.d.ts +3 -0
  4. package/dist/bin.d.ts.map +1 -0
  5. package/dist/bin.js +65 -0
  6. package/dist/bin.js.map +1 -0
  7. package/dist/contracts.d.ts +29 -0
  8. package/dist/contracts.d.ts.map +1 -0
  9. package/dist/contracts.js +57 -0
  10. package/dist/contracts.js.map +1 -0
  11. package/dist/docs.d.ts +34 -0
  12. package/dist/docs.d.ts.map +1 -0
  13. package/dist/docs.js +63 -0
  14. package/dist/docs.js.map +1 -0
  15. package/dist/emit.d.ts +38 -0
  16. package/dist/emit.d.ts.map +1 -0
  17. package/dist/emit.js +406 -0
  18. package/dist/emit.js.map +1 -0
  19. package/dist/examples.d.ts +35 -0
  20. package/dist/examples.d.ts.map +1 -0
  21. package/dist/examples.js +345 -0
  22. package/dist/examples.js.map +1 -0
  23. package/dist/extract.d.ts +208 -0
  24. package/dist/extract.d.ts.map +1 -0
  25. package/dist/extract.js +1570 -0
  26. package/dist/extract.js.map +1 -0
  27. package/dist/foundations.d.ts +36 -0
  28. package/dist/foundations.d.ts.map +1 -0
  29. package/dist/foundations.js +108 -0
  30. package/dist/foundations.js.map +1 -0
  31. package/dist/history.d.ts +10 -0
  32. package/dist/history.d.ts.map +1 -0
  33. package/dist/history.js +62 -0
  34. package/dist/history.js.map +1 -0
  35. package/dist/impact-bin.d.ts +3 -0
  36. package/dist/impact-bin.d.ts.map +1 -0
  37. package/dist/impact-bin.js +7 -0
  38. package/dist/impact-bin.js.map +1 -0
  39. package/dist/impact-cli.d.ts +8 -0
  40. package/dist/impact-cli.d.ts.map +1 -0
  41. package/dist/impact-cli.js +121 -0
  42. package/dist/impact-cli.js.map +1 -0
  43. package/dist/impact.d.ts +282 -0
  44. package/dist/impact.d.ts.map +1 -0
  45. package/dist/impact.js +744 -0
  46. package/dist/impact.js.map +1 -0
  47. package/dist/index.d.ts +82 -0
  48. package/dist/index.d.ts.map +1 -0
  49. package/dist/index.js +228 -0
  50. package/dist/index.js.map +1 -0
  51. package/dist/kit/agents-md.d.ts +10 -0
  52. package/dist/kit/agents-md.d.ts.map +1 -0
  53. package/dist/kit/agents-md.js +64 -0
  54. package/dist/kit/agents-md.js.map +1 -0
  55. package/dist/kit/cli.d.ts +8 -0
  56. package/dist/kit/cli.d.ts.map +1 -0
  57. package/dist/kit/cli.js +214 -0
  58. package/dist/kit/cli.js.map +1 -0
  59. package/dist/kit/context.d.ts +104 -0
  60. package/dist/kit/context.d.ts.map +1 -0
  61. package/dist/kit/context.js +323 -0
  62. package/dist/kit/context.js.map +1 -0
  63. package/dist/kit/index.d.ts +12 -0
  64. package/dist/kit/index.d.ts.map +1 -0
  65. package/dist/kit/index.js +12 -0
  66. package/dist/kit/index.js.map +1 -0
  67. package/dist/kit/kit.d.ts +62 -0
  68. package/dist/kit/kit.d.ts.map +1 -0
  69. package/dist/kit/kit.js +626 -0
  70. package/dist/kit/kit.js.map +1 -0
  71. package/dist/kit/llms.d.ts +22 -0
  72. package/dist/kit/llms.d.ts.map +1 -0
  73. package/dist/kit/llms.js +58 -0
  74. package/dist/kit/llms.js.map +1 -0
  75. package/dist/kit/package-kit.d.ts +18 -0
  76. package/dist/kit/package-kit.d.ts.map +1 -0
  77. package/dist/kit/package-kit.js +224 -0
  78. package/dist/kit/package-kit.js.map +1 -0
  79. package/dist/kit-bin.d.ts +3 -0
  80. package/dist/kit-bin.d.ts.map +1 -0
  81. package/dist/kit-bin.js +7 -0
  82. package/dist/kit-bin.js.map +1 -0
  83. package/dist/published.d.ts +43 -0
  84. package/dist/published.d.ts.map +1 -0
  85. package/dist/published.js +62 -0
  86. package/dist/published.js.map +1 -0
  87. package/dist/references.d.ts +70 -0
  88. package/dist/references.d.ts.map +1 -0
  89. package/dist/references.js +255 -0
  90. package/dist/references.js.map +1 -0
  91. package/dist/style-mappings.d.ts +46 -0
  92. package/dist/style-mappings.d.ts.map +1 -0
  93. package/dist/style-mappings.js +246 -0
  94. package/dist/style-mappings.js.map +1 -0
  95. package/dist/stylesheets.d.ts +56 -0
  96. package/dist/stylesheets.d.ts.map +1 -0
  97. package/dist/stylesheets.js +83 -0
  98. package/dist/stylesheets.js.map +1 -0
  99. package/dist/verification.d.ts +62 -0
  100. package/dist/verification.d.ts.map +1 -0
  101. package/dist/verification.js +115 -0
  102. package/dist/verification.js.map +1 -0
  103. package/package.json +45 -4
@@ -0,0 +1,214 @@
1
+ /**
2
+ * `oddkin-kit` commands, kept free of a shebang so tests can import them.
3
+ *
4
+ * oddkin-kit [--root <dir>] [--package <name>]... [--out <dir>] [--theme-config <file>] [--check]
5
+ * oddkin-kit package [--root <dir>] [--package <name>]... [--check]
6
+ * oddkin-kit agents-md [--root <dir>] [--write | --check]
7
+ * oddkin-kit llms --base <url> --out <dir> [--root <dir>] [--package <name>]... [--title <text>]
8
+ * [--summary <text>]
9
+ *
10
+ * Exit codes: 0 success; 1 a stale, missing, or over-budget kit, or a stale AGENTS.md section;
11
+ * 2 usage error.
12
+ */
13
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
14
+ import { join, relative, resolve } from 'node:path';
15
+ import { parseArgs } from 'node:util';
16
+ import { lineDiff, renderSection, updateAgentsMd } from './agents-md.js';
17
+ import { resolveProjectContext } from './context.js';
18
+ import { checkKit, generateKit, kitDirName, refreshCommand, writeKit } from './kit.js';
19
+ import { siteLlmsText } from './llms.js';
20
+ import { packageKit } from './package-kit.js';
21
+ export const USAGE = `Usage:
22
+ oddkin-kit [--root <dir>] [--package <name>]... [--out <dir>] [--theme-config <file>] [--check]
23
+ Write each library's agent kit into <out>/<name>/ (default .oddkin/agent-kit): the
24
+ workspace's own libraries, or those named with --package. --check reports stale or
25
+ missing kits instead.
26
+ oddkin-kit package [--root <dir>] [--package <name>]... [--check]
27
+ Write the kit each component package ships into <package>/agent/: the workspace's own
28
+ packages, or those named with --package. --check regenerates each kit and compares it
29
+ with the files there, installed packages included.
30
+ oddkin-kit agents-md [--root <dir>] [--write | --check]
31
+ Show, write, or check the managed section of the workspace's AGENTS.md.
32
+ oddkin-kit llms --base <url> --out <dir> [--root <dir>] [--package <name>]... [--title <text>] [--summary <text>]
33
+ Write a documentation site's llms.txt into <dir>: an index of the packages' kits, linked
34
+ under <url>, and the kit files it links, in <dir>/agent/<name>/.`;
35
+ const COMMANDS = new Set(['package', 'agents-md', 'llms']);
36
+ /** Run one command; resolves with the exit code. */
37
+ export async function main(argv, io) {
38
+ const [first, ...rest] = argv;
39
+ const command = first !== undefined && COMMANDS.has(first) ? first : 'kit';
40
+ const args = command === 'kit' ? [...argv] : rest;
41
+ let values;
42
+ try {
43
+ ({ values } = parseArgs({
44
+ args,
45
+ options: {
46
+ root: { type: 'string', default: '.' },
47
+ package: { type: 'string', multiple: true },
48
+ out: { type: 'string', default: '.oddkin/agent-kit' },
49
+ 'theme-config': { type: 'string' },
50
+ check: { type: 'boolean', default: false },
51
+ write: { type: 'boolean', default: false },
52
+ base: { type: 'string' },
53
+ title: { type: 'string' },
54
+ summary: { type: 'string' },
55
+ help: { type: 'boolean', short: 'h', default: false },
56
+ },
57
+ }));
58
+ }
59
+ catch (error) {
60
+ io.err(`${error instanceof Error ? error.message : String(error)}\n${USAGE}`);
61
+ return 2;
62
+ }
63
+ if (values.help) {
64
+ io.out(USAGE);
65
+ return 0;
66
+ }
67
+ let base;
68
+ if (command === 'llms') {
69
+ try {
70
+ base = new URL(values.base ?? '');
71
+ }
72
+ catch {
73
+ base = undefined;
74
+ }
75
+ const out = args.some((arg) => arg === '--out' || arg.startsWith('--out='));
76
+ if (!base || !/^https?:$/.test(base.protocol) || !out) {
77
+ io.err(`llms needs --base <absolute http(s) URL> and --out <dir>.\n${USAGE}`);
78
+ return 2;
79
+ }
80
+ if (!base.pathname.endsWith('/'))
81
+ base.pathname += '/';
82
+ }
83
+ if (command === 'agents-md') {
84
+ if (values.write && values.check) {
85
+ io.err(USAGE);
86
+ return 2;
87
+ }
88
+ return agentsMd(values.root, values.check, values.write, io);
89
+ }
90
+ const project = resolveProjectContext(values.root, {
91
+ ...(values['theme-config'] ? { themeConfig: values['theme-config'] } : {}),
92
+ });
93
+ for (const d of project.diagnostics)
94
+ io.err(`${d.severity} ${d.code}: ${d.message}`);
95
+ const names = values.package ?? project.libraries.filter((l) => l.owned).map((l) => l.name);
96
+ if (!names.length) {
97
+ io.err('No package of this workspace publishes oddkin.metadata.json; name installed ones with --package.');
98
+ return 1;
99
+ }
100
+ for (const name of names)
101
+ if (!project.libraries.some((l) => l.name === name)) {
102
+ io.err(`error agent.kit.unknownPackage: ${name} publishes no oddkin.metadata.json here.`);
103
+ return 1;
104
+ }
105
+ if (command === 'llms' && base) {
106
+ const title = values.title ??
107
+ JSON.parse(readFileSync(join(project.root, 'package.json'), 'utf8'))
108
+ .name ??
109
+ 'Agent kits';
110
+ return llms(project, names, resolve(values.root, values.out), base, title, values.summary, io);
111
+ }
112
+ return command === 'package'
113
+ ? packaged(project, names, values.check, io)
114
+ : kits(project, names, values.root, values.out, values.check, io);
115
+ }
116
+ async function llms(project, names, out, base, title, summary, io) {
117
+ const site = [];
118
+ for (const name of names) {
119
+ const library = project.libraries.find((l) => l.name === name);
120
+ const { files, manifest } = await packageKit(project, library);
121
+ const path = `agent/${kitDirName(name)}/`;
122
+ writeKit(join(out, path), files);
123
+ site.push({ library, manifest, url: new URL(path, base).href });
124
+ }
125
+ mkdirSync(out, { recursive: true });
126
+ writeFileSync(join(out, 'llms.txt'), siteLlmsText({ title, ...(summary ? { summary } : {}), kits: site }));
127
+ io.out(`llms.txt and ${site.length} kits in ${out}, linked under ${base.href}`);
128
+ return 0;
129
+ }
130
+ function kits(project, names, root, out, check, io) {
131
+ let failed = false;
132
+ for (const name of names) {
133
+ const dir = resolve(root, out, kitDirName(name));
134
+ if (check) {
135
+ const { status, changed } = checkKit(dir, project, name);
136
+ if (status === 'current')
137
+ io.out(`${name}: current (${dir})`);
138
+ else {
139
+ failed = true;
140
+ io.err(`${status === 'stale' ? 'error agent.kit.stale' : 'error agent.kit.missing'}: ${name} at ${dir}${changed.length ? `\n ${changed.join('\n ')}` : ''}\n → ${refreshCommand(name, out)}`);
141
+ }
142
+ continue;
143
+ }
144
+ const { files, manifest } = generateKit(project, name);
145
+ writeKit(dir, files);
146
+ io.out(`${name}: ${files.size} files in ${dir}; GUIDE.md ${manifest.guide.bytes} of ${manifest.guide.budgetBytes} bytes`);
147
+ if (manifest.guide.bytes > manifest.guide.budgetBytes) {
148
+ failed = true;
149
+ io.err(`error agent.kit.guideBudget: ${name}'s GUIDE.md exceeds its budget.`);
150
+ }
151
+ }
152
+ return failed ? 1 : 0;
153
+ }
154
+ async function packaged(project, names, check, io) {
155
+ let failed = false;
156
+ for (const name of names) {
157
+ const library = project.libraries.find((l) => l.name === name);
158
+ const { dir, files, manifest } = await packageKit(project, library);
159
+ const where = relative(project.root, dir).split('\\').join('/');
160
+ if (manifest.guide.bytes > manifest.guide.budgetBytes) {
161
+ failed = true;
162
+ io.err(`error agent.kit.guideBudget: ${name}'s GUIDE.md exceeds its budget.`);
163
+ }
164
+ if (check) {
165
+ const stale = [...files].filter(([path, text]) => !existsSync(join(dir, path)) || readFileSync(join(dir, path), 'utf8') !== text);
166
+ if (!stale.length) {
167
+ io.out(`${name}: current (${where})`);
168
+ continue;
169
+ }
170
+ failed = true;
171
+ const shipped = existsSync(join(dir, 'kit.json'))
172
+ ? JSON.parse(readFileSync(join(dir, 'kit.json'), 'utf8'))
173
+ : undefined;
174
+ const generator = shipped?.fingerprint?.generator?.version;
175
+ io.err(`error agent.kit.stale: ${where} (${stale.length} of ${files.size} files differ: ${stale
176
+ .slice(0, 5)
177
+ .map(([path]) => path)
178
+ .join(', ')}${stale.length > 5 ? ', …' : ''})${generator && generator !== manifest.fingerprint.generator.version
179
+ ? `\n generated by ${generator}; this is ${manifest.fingerprint.generator.version}`
180
+ : ''}${library.owned ? '\n → oddkin-kit package' : ''}`);
181
+ continue;
182
+ }
183
+ if (!library.owned) {
184
+ failed = true;
185
+ io.err(`error agent.kit.installed: ${name} is installed, not part of this workspace; its kit ships with it (use --check).`);
186
+ continue;
187
+ }
188
+ writeKit(dir, files);
189
+ io.out(`${name}: ${files.size} files in ${where}; GUIDE.md ${manifest.guide.bytes} of ${manifest.guide.budgetBytes} bytes`);
190
+ }
191
+ return failed ? 1 : 0;
192
+ }
193
+ function agentsMd(root, check, write, io) {
194
+ const file = join(resolve(root), 'AGENTS.md');
195
+ const before = existsSync(file) ? readFileSync(file, 'utf8') : '';
196
+ const after = updateAgentsMd(before, renderSection(resolveProjectContext(root)));
197
+ if (after === before) {
198
+ io.out('AGENTS.md: managed section current.');
199
+ return 0;
200
+ }
201
+ io.out(`AGENTS.md${before ? '' : ' (new file)'}:\n${lineDiff(before, after).join('\n')}`);
202
+ if (check) {
203
+ io.err('error agent.agentsMd.stale: run oddkin-kit agents-md --write');
204
+ return 1;
205
+ }
206
+ if (write) {
207
+ writeFileSync(file, after);
208
+ io.out('AGENTS.md written.');
209
+ }
210
+ else
211
+ io.out('Dry run: add --write to apply.');
212
+ return 0;
213
+ }
214
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/kit/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,104 @@
1
+ export declare const CONTEXT_SCHEMA = "https://oddkin.dev/schemas/project-context/v1.json";
2
+ /**
3
+ * The generator: this package and a hash of the kit modules themselves, so a generator change
4
+ * makes kits stale. The built modules are the same bytes in the workspace that builds the package
5
+ * and in every project that installs it.
6
+ */
7
+ export declare const GENERATOR: {
8
+ readonly name: string;
9
+ readonly version: string;
10
+ };
11
+ export interface Fingerprint {
12
+ generator: {
13
+ name: string;
14
+ version: string;
15
+ };
16
+ schemaVersion: number;
17
+ packages?: Record<string, string>;
18
+ inputs: string;
19
+ }
20
+ export interface ProjectContext {
21
+ schema: string;
22
+ packages: Array<{
23
+ name: string;
24
+ version: string;
25
+ peerRanges?: Record<string, string>;
26
+ exports?: string[];
27
+ registrations?: Record<string, string>;
28
+ metadata?: string;
29
+ }>;
30
+ components?: Array<{
31
+ tag: string;
32
+ source: string;
33
+ extends?: string;
34
+ dependencies?: string[];
35
+ }>;
36
+ theme?: {
37
+ config?: string;
38
+ themes?: string[];
39
+ modes?: string[];
40
+ densities?: string[];
41
+ profiles?: string[];
42
+ products?: string[];
43
+ };
44
+ recipes: string[];
45
+ stylesheets: string[];
46
+ examples: string[];
47
+ conventions: {
48
+ componentLayout: 'folders' | 'colocated' | 'mixed' | 'unknown';
49
+ };
50
+ commands: Record<string, string>;
51
+ capabilityPaths: Array<'core-authoring' | 'tokens-only' | 'components-without-state' | 'application-services'>;
52
+ fingerprint: Fingerprint;
53
+ freshness: 'current' | 'stale' | 'unknown';
54
+ }
55
+ export interface Library {
56
+ name: string;
57
+ version: string;
58
+ dir: string;
59
+ manifest: Record<string, any>;
60
+ metadata: Record<string, any>;
61
+ cem?: Record<string, any>;
62
+ owned: boolean;
63
+ }
64
+ export interface ContextDiagnostic {
65
+ code: string;
66
+ severity: 'error' | 'warning';
67
+ message: string;
68
+ }
69
+ /** Where a theme's token inspection comes from: a package export. */
70
+ export interface InspectionSource {
71
+ package: string;
72
+ export: string;
73
+ }
74
+ export interface Project {
75
+ root: string;
76
+ context: ProjectContext;
77
+ diagnostics: ContextDiagnostic[];
78
+ /** Input path (relative to the root) → SHA-256 of its content. */
79
+ inputs: Map<string, string>;
80
+ libraries: Library[];
81
+ inspection?: {
82
+ file: string;
83
+ data: Record<string, any>;
84
+ source?: InspectionSource;
85
+ };
86
+ workspace: Array<{
87
+ name: string;
88
+ dir: string;
89
+ }>;
90
+ }
91
+ /** The file a package exports at `subpath` (development build first, as the analyzer reads). */
92
+ export declare function exportTarget(manifest: Record<string, any>, subpath: string): string | undefined;
93
+ /**
94
+ * Resolve a workspace's project context (project-context.v1). `options.themeConfig` names the
95
+ * theme configuration file; the token inspection is the one the libraries' foundations
96
+ * reference, or `options.inspection`.
97
+ */
98
+ export declare function resolveProjectContext(rootDir: string, options?: {
99
+ themeConfig?: string;
100
+ inspection?: string;
101
+ }): Project;
102
+ /** `sha256-…` over every input's path and content hash, in path order. */
103
+ export declare function inputsHash(inputs: Map<string, string>): string;
104
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/kit/context.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,323 @@
1
+ /**
2
+ * Agent kits, the project context (agent-tooling.md §4): what a workspace actually installs and
3
+ * publishes, read from package manifests, published metadata, token inspection, and example files
4
+ * only. Nothing is executed or inferred from names; unknown stays absent.
5
+ */
6
+ import { createHash } from 'node:crypto';
7
+ import { existsSync, readdirSync, readFileSync, realpathSync } from 'node:fs';
8
+ import { dirname, extname, join, relative, resolve, sep } from 'node:path';
9
+ import { fileURLToPath } from 'node:url';
10
+ export const CONTEXT_SCHEMA = 'https://oddkin.dev/schemas/project-context/v1.json';
11
+ const sha256 = (text) => createHash('sha256').update(text).digest('hex');
12
+ const posix = (path) => path.split(sep).join('/');
13
+ const here = dirname(fileURLToPath(import.meta.url));
14
+ /**
15
+ * The generator: this package and a hash of the kit modules themselves, so a generator change
16
+ * makes kits stale. The built modules are the same bytes in the workspace that builds the package
17
+ * and in every project that installs it.
18
+ */
19
+ export const GENERATOR = (() => {
20
+ const manifest = JSON.parse(readFileSync(join(here, '..', '..', 'package.json'), 'utf8'));
21
+ const own = extname(fileURLToPath(import.meta.url));
22
+ const sources = readdirSync(here)
23
+ .filter((file) => extname(file) === own && !file.endsWith(`.d${own}`))
24
+ .sort()
25
+ .map((file) => `${file}\0${sha256(readFileSync(join(here, file)))}`)
26
+ .join('\n');
27
+ return {
28
+ name: `${manifest.name}/kit`,
29
+ version: `${manifest.version}+${sha256(sources).slice(0, 12)}`,
30
+ };
31
+ })();
32
+ const COMMANDS = [
33
+ ['build', ['build']],
34
+ ['typecheck', ['typecheck']],
35
+ ['test', ['test']],
36
+ ['browser', ['test:browser']],
37
+ ['e2e', ['test:e2e', 'e2e']],
38
+ ['lint', ['lint']],
39
+ ['verify', ['verify']],
40
+ ['metadata', ['verify:metadata', 'metadata']],
41
+ ];
42
+ /** The file a package exports at `subpath` (development build first, as the analyzer reads). */
43
+ export function exportTarget(manifest, subpath) {
44
+ const target = manifest['exports']?.[subpath];
45
+ const file = typeof target === 'string'
46
+ ? target
47
+ : (target?.development ?? target?.import ?? target?.default ?? undefined);
48
+ return typeof file === 'string' ? file.replace(/^\.\//, '') : undefined;
49
+ }
50
+ /** Node's lookup of an installed package from `from`, through symlinks. */
51
+ function findPackage(name, from) {
52
+ for (let dir = from;; dir = dirname(dir)) {
53
+ const candidate = join(dir, 'node_modules', ...name.split('/'), 'package.json');
54
+ if (existsSync(candidate))
55
+ return dirname(realpathSync(candidate));
56
+ if (dirname(dir) === dir)
57
+ return undefined;
58
+ }
59
+ }
60
+ function workspaceDirs(root, manifest, diagnostics) {
61
+ const workspaces = manifest['workspaces'];
62
+ const patterns = Array.isArray(workspaces) ? workspaces : (workspaces?.packages ?? []);
63
+ const dirs = [];
64
+ for (const pattern of patterns) {
65
+ if (/^[^*]+\/\*$/.test(pattern)) {
66
+ const base = join(root, pattern.slice(0, -2));
67
+ if (!existsSync(base))
68
+ continue;
69
+ for (const name of readdirSync(base).sort())
70
+ if (existsSync(join(base, name, 'package.json')))
71
+ dirs.push(join(base, name));
72
+ }
73
+ else if (!pattern.includes('*')) {
74
+ if (existsSync(join(root, pattern, 'package.json')))
75
+ dirs.push(join(root, pattern));
76
+ }
77
+ else
78
+ diagnostics.push({
79
+ code: 'agent.context.workspacePattern',
80
+ severity: 'warning',
81
+ message: `Workspace pattern "${pattern}" is not read (only "dir" and "dir/*"); its packages are missing from the context.`,
82
+ });
83
+ }
84
+ return dirs;
85
+ }
86
+ /** The authored source of a built module, from its source map; the module itself without one. */
87
+ function sourceOf(packageDir, module) {
88
+ const built = join(packageDir, module);
89
+ const map = `${built}.map`;
90
+ if (existsSync(map)) {
91
+ const { sources, sourceRoot = '' } = JSON.parse(readFileSync(map, 'utf8'));
92
+ if (sources?.length === 1)
93
+ return resolve(dirname(built), sourceRoot, sources[0]);
94
+ }
95
+ return built;
96
+ }
97
+ /** `folders` when a component's template is its own module beside the class, as compose() needs. */
98
+ function layoutOf(component) {
99
+ const template = component.definition?.template?.module;
100
+ if (!template || component.definition.template.package)
101
+ return 'colocated';
102
+ return template !== component.cem.module && dirname(template) === dirname(component.cem.module)
103
+ ? 'folders'
104
+ : 'colocated';
105
+ }
106
+ const themeAxes = (inspection) => {
107
+ const values = (attribute) => [
108
+ ...new Set(inspection['scopes']
109
+ .map((s) => new RegExp(`\\[data-odd-${attribute}~?="([^"]+)"\\]`).exec(s.selector)?.[1])
110
+ .filter((value) => Boolean(value))),
111
+ ].sort();
112
+ return {
113
+ themes: [...new Set([inspection['theme'], ...values('theme')])].sort(),
114
+ modes: [...inspection['modes']],
115
+ densities: values('density'),
116
+ profiles: values('profile'),
117
+ products: values('product'),
118
+ };
119
+ };
120
+ /**
121
+ * Resolve a workspace's project context (project-context.v1). `options.themeConfig` names the
122
+ * theme configuration file; the token inspection is the one the libraries' foundations
123
+ * reference, or `options.inspection`.
124
+ */
125
+ export function resolveProjectContext(rootDir, options = {}) {
126
+ const root = resolve(rootDir);
127
+ const rel = (file) => posix(relative(root, file));
128
+ const inputs = new Map();
129
+ const diagnostics = [];
130
+ const readInput = (file) => {
131
+ const text = readFileSync(file, 'utf8');
132
+ inputs.set(rel(file), sha256(text));
133
+ return text;
134
+ };
135
+ const readJson = (file) => JSON.parse(readInput(file));
136
+ const rootManifest = readJson(join(root, 'package.json'));
137
+ const installed = new Map();
138
+ for (const dir of workspaceDirs(root, rootManifest, diagnostics)) {
139
+ const manifest = JSON.parse(readFileSync(join(dir, 'package.json'), 'utf8'));
140
+ installed.set(manifest.name, { dir, manifest, owned: true });
141
+ }
142
+ const declared = (manifest) => [
143
+ ...Object.keys(manifest['dependencies'] ?? {}),
144
+ ...Object.keys(manifest['devDependencies'] ?? {}),
145
+ ...Object.keys(manifest['peerDependencies'] ?? {}),
146
+ ];
147
+ const wanted = new Set([rootManifest, ...[...installed.values()].map((p) => p.manifest)].flatMap(declared));
148
+ for (const name of [...wanted].sort()) {
149
+ if (installed.has(name))
150
+ continue;
151
+ const dir = findPackage(name, root);
152
+ if (!dir) {
153
+ if (name.startsWith('@oddkin/'))
154
+ diagnostics.push({
155
+ code: 'agent.context.notInstalled',
156
+ severity: 'warning',
157
+ message: `${name} is declared but not installed; run the package manager's install.`,
158
+ });
159
+ continue;
160
+ }
161
+ const manifest = JSON.parse(readFileSync(join(dir, 'package.json'), 'utf8'));
162
+ installed.set(name, { dir, manifest, owned: false });
163
+ }
164
+ const packages = [];
165
+ const libraries = [];
166
+ for (const [name, { dir, manifest, owned }] of [...installed].sort(([a], [b]) => a < b ? -1 : 1)) {
167
+ if (!manifest['exports'] || !(name.startsWith('@oddkin/') || manifest['customElements']))
168
+ continue;
169
+ readInput(join(dir, 'package.json'));
170
+ const record = {
171
+ name,
172
+ version: manifest['version'] ?? '0.0.0',
173
+ };
174
+ if (manifest['peerDependencies'])
175
+ record.peerRanges = { ...manifest['peerDependencies'] };
176
+ record.exports = Object.keys(manifest['exports'])
177
+ .filter((subpath) => subpath !== './package.json')
178
+ .map((subpath) => (subpath === '.' ? name : `${name}${subpath.slice(1)}`));
179
+ const metadataFile = exportTarget(manifest, './oddkin.metadata.json');
180
+ if (metadataFile && existsSync(join(dir, metadataFile))) {
181
+ const metadata = readJson(join(dir, metadataFile));
182
+ const cemFile = manifest['customElements']?.replace(/^\.\//, '');
183
+ const cem = cemFile && existsSync(join(dir, cemFile)) ? readJson(join(dir, cemFile)) : undefined;
184
+ record.registrations = Object.fromEntries(Object.values(metadata['components'] ?? {}).map((c) => [c.tag, c.registration]));
185
+ record.metadata = rel(join(dir, metadataFile));
186
+ for (const example of Object.values(metadata['examples'] ?? {}))
187
+ if (existsSync(join(dir, example.file)))
188
+ readInput(join(dir, example.file));
189
+ libraries.push({
190
+ name,
191
+ version: record.version,
192
+ dir,
193
+ manifest,
194
+ metadata,
195
+ ...(cem ? { cem } : {}),
196
+ owned,
197
+ });
198
+ }
199
+ packages.push(record);
200
+ }
201
+ const components = libraries
202
+ .filter((library) => library.owned)
203
+ .flatMap((library) => Object.values(library.metadata['components'] ?? {}).map((c) => ({
204
+ tag: c.tag,
205
+ source: rel(sourceOf(library.dir, c.definition?.ref?.module ?? c.cem.module)),
206
+ ...(c.definition?.extends ? { extends: c.definition.extends } : {}),
207
+ ...(c.definition?.dependencies
208
+ ? {
209
+ dependencies: [...new Set(Object.values(c.definition.dependencies))].sort(),
210
+ }
211
+ : {}),
212
+ })))
213
+ .sort((a, b) => (a.tag < b.tag ? -1 : 1));
214
+ // The token inspection the libraries' foundations were generated from.
215
+ const sources = [
216
+ ...new Set(libraries.flatMap((l) => Object.values(l.metadata['foundations'] ?? {}).map((f) => JSON.stringify(f.generation?.value?.source ?? null)))),
217
+ ]
218
+ .map((s) => JSON.parse(s))
219
+ .filter((s) => Boolean(s));
220
+ const first = sources[0];
221
+ if (sources.length > 1 && first)
222
+ diagnostics.push({
223
+ code: 'agent.context.themes',
224
+ severity: 'warning',
225
+ message: `Foundations reference ${sources.length} token inspections; the first (${first.package} ${first.export}) describes the theme.`,
226
+ });
227
+ const inspectionFile = options.inspection ??
228
+ (first &&
229
+ (() => {
230
+ const owner = installed.get(first.package);
231
+ const dir = owner?.dir ?? findPackage(first.package, root);
232
+ const manifest = dir && JSON.parse(readFileSync(join(dir, 'package.json'), 'utf8'));
233
+ const file = manifest && exportTarget(manifest, first.export);
234
+ return dir && file ? join(dir, file) : undefined;
235
+ })());
236
+ let inspection;
237
+ if (inspectionFile && existsSync(inspectionFile))
238
+ inspection = {
239
+ file: inspectionFile,
240
+ data: readJson(inspectionFile),
241
+ ...(first && !options.inspection ? { source: first } : {}),
242
+ };
243
+ if (options.themeConfig)
244
+ readInput(resolve(root, options.themeConfig));
245
+ for (const name of readdirSync(root).filter((f) => /^oddkin\.docs\.(ts|mts|js|mjs|json)$/.test(f)))
246
+ readInput(join(root, name));
247
+ const scripts = rootManifest['scripts'] ?? {};
248
+ const commands = Object.fromEntries(COMMANDS.flatMap(([key, names]) => {
249
+ const script = names.find((n) => scripts[n]);
250
+ return script ? [[key, script === 'test' ? 'npm test' : `npm run ${script}`]] : [];
251
+ }));
252
+ const names = new Set(packages.map((p) => p.name));
253
+ const hasServices = names.has('@oddkin/state') || names.has('@oddkin/app');
254
+ const hasComponents = libraries.length > 0;
255
+ const capabilityPaths = [
256
+ ...(hasServices ? ['application-services'] : []),
257
+ ...(hasComponents && !hasServices ? ['components-without-state'] : []),
258
+ ...(components.length ? ['core-authoring'] : []),
259
+ ...(names.has('@oddkin/tokens') && !hasComponents && !components.length
260
+ ? ['tokens-only']
261
+ : []),
262
+ ].sort();
263
+ const layouts = new Set(libraries
264
+ .filter((l) => l.owned)
265
+ .flatMap((l) => Object.values(l.metadata['components'] ?? {}).map(layoutOf)));
266
+ const fingerprint = {
267
+ generator: { ...GENERATOR },
268
+ schemaVersion: 1,
269
+ packages: Object.fromEntries(packages.map((p) => [p.name, p.version])),
270
+ inputs: inputsHash(inputs),
271
+ };
272
+ const context = {
273
+ schema: CONTEXT_SCHEMA,
274
+ packages,
275
+ ...(components.length ? { components } : {}),
276
+ ...(inspection || options.themeConfig
277
+ ? {
278
+ theme: {
279
+ ...(options.themeConfig ? { config: rel(resolve(root, options.themeConfig)) } : {}),
280
+ ...(inspection ? themeAxes(inspection.data) : {}),
281
+ },
282
+ }
283
+ : {}),
284
+ recipes: [
285
+ ...new Set(libraries.flatMap((l) => Object.keys(l.metadata['recipes'] ?? {}))),
286
+ ].sort(),
287
+ stylesheets: [
288
+ ...new Set(libraries.flatMap((l) => Object.keys(l.metadata['stylesheets'] ?? {}))),
289
+ ].sort(),
290
+ examples: libraries
291
+ .flatMap((l) => Object.entries(l.metadata['examples'] ?? {})
292
+ .filter(([, e]) => !e.incorrect)
293
+ .map(([id]) => id))
294
+ .sort(),
295
+ conventions: {
296
+ componentLayout: layouts.size === 0 ? 'unknown' : layouts.size > 1 ? 'mixed' : [...layouts][0],
297
+ },
298
+ commands,
299
+ capabilityPaths,
300
+ fingerprint,
301
+ freshness: 'current',
302
+ };
303
+ return {
304
+ root,
305
+ context,
306
+ diagnostics,
307
+ inputs,
308
+ libraries,
309
+ ...(inspection ? { inspection } : {}),
310
+ workspace: [...installed]
311
+ .filter(([, p]) => p.owned)
312
+ .map(([name, p]) => ({ name, dir: rel(p.dir) }))
313
+ .sort((a, b) => (a.dir < b.dir ? -1 : 1)),
314
+ };
315
+ }
316
+ /** `sha256-…` over every input's path and content hash, in path order. */
317
+ export function inputsHash(inputs) {
318
+ return `sha256-${sha256([...inputs]
319
+ .sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))
320
+ .map(([path, hash]) => `${path}\0${hash}`)
321
+ .join('\n'))}`;
322
+ }
323
+ //# sourceMappingURL=context.js.map