@elaraai/east-plugin 0.0.0-stage → 1.0.87

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 (133) hide show
  1. package/LICENSE.md +682 -0
  2. package/README.md +104 -2
  3. package/dist/daemon/east-py-lsp.d.ts +2 -0
  4. package/dist/daemon/east-py-lsp.d.ts.map +1 -0
  5. package/dist/daemon/east-py-lsp.js +9 -0
  6. package/dist/daemon/east-py-lsp.js.map +1 -0
  7. package/dist/daemon/lsp.d.ts +2 -0
  8. package/dist/daemon/lsp.d.ts.map +1 -0
  9. package/dist/daemon/lsp.js +7 -0
  10. package/dist/daemon/lsp.js.map +1 -0
  11. package/dist/daemon/server.d.ts +2 -0
  12. package/dist/daemon/server.d.ts.map +1 -0
  13. package/dist/daemon/server.js +71 -0
  14. package/dist/daemon/server.js.map +1 -0
  15. package/dist/hooks/diagnose-bash.d.ts +2 -0
  16. package/dist/hooks/diagnose-bash.d.ts.map +1 -0
  17. package/dist/hooks/diagnose-bash.js +28 -0
  18. package/dist/hooks/diagnose-bash.js.map +1 -0
  19. package/dist/hooks/diagnose.d.ts +2 -0
  20. package/dist/hooks/diagnose.d.ts.map +1 -0
  21. package/dist/hooks/diagnose.js +33 -0
  22. package/dist/hooks/diagnose.js.map +1 -0
  23. package/dist/hooks/pre-read.d.ts +2 -0
  24. package/dist/hooks/pre-read.d.ts.map +1 -0
  25. package/dist/hooks/pre-read.js +11 -0
  26. package/dist/hooks/pre-read.js.map +1 -0
  27. package/dist/hooks/pre-write.d.ts +2 -0
  28. package/dist/hooks/pre-write.d.ts.map +1 -0
  29. package/dist/hooks/pre-write.js +11 -0
  30. package/dist/hooks/pre-write.js.map +1 -0
  31. package/dist/hooks/session-start.d.ts +2 -0
  32. package/dist/hooks/session-start.d.ts.map +1 -0
  33. package/dist/hooks/session-start.js +34 -0
  34. package/dist/hooks/session-start.js.map +1 -0
  35. package/dist/hooks/subagent-start.d.ts +2 -0
  36. package/dist/hooks/subagent-start.d.ts.map +1 -0
  37. package/dist/hooks/subagent-start.js +29 -0
  38. package/dist/hooks/subagent-start.js.map +1 -0
  39. package/dist/lib/bash-writes.d.ts +11 -0
  40. package/dist/lib/bash-writes.d.ts.map +1 -0
  41. package/dist/lib/bash-writes.js +74 -0
  42. package/dist/lib/bash-writes.js.map +1 -0
  43. package/dist/lib/codex-hook.d.ts +64 -0
  44. package/dist/lib/codex-hook.d.ts.map +1 -0
  45. package/dist/lib/codex-hook.js +94 -0
  46. package/dist/lib/codex-hook.js.map +1 -0
  47. package/dist/lib/codex-skills.d.ts +38 -0
  48. package/dist/lib/codex-skills.d.ts.map +1 -0
  49. package/dist/lib/codex-skills.js +80 -0
  50. package/dist/lib/codex-skills.js.map +1 -0
  51. package/dist/lib/codex-tools.d.ts +11 -0
  52. package/dist/lib/codex-tools.d.ts.map +1 -0
  53. package/dist/lib/codex-tools.js +41 -0
  54. package/dist/lib/codex-tools.js.map +1 -0
  55. package/dist/lib/diagnostics-client.d.ts +9 -0
  56. package/dist/lib/diagnostics-client.d.ts.map +1 -0
  57. package/dist/lib/diagnostics-client.js +123 -0
  58. package/dist/lib/diagnostics-client.js.map +1 -0
  59. package/dist/lib/east-index.d.ts +3 -0
  60. package/dist/lib/east-index.d.ts.map +1 -0
  61. package/dist/lib/east-index.js +9 -0
  62. package/dist/lib/east-index.js.map +1 -0
  63. package/dist/lib/east-project.d.ts +49 -0
  64. package/dist/lib/east-project.d.ts.map +1 -0
  65. package/dist/lib/east-project.js +121 -0
  66. package/dist/lib/east-project.js.map +1 -0
  67. package/dist/lib/east-py-lint.d.ts +7 -0
  68. package/dist/lib/east-py-lint.d.ts.map +1 -0
  69. package/dist/lib/east-py-lint.js +22 -0
  70. package/dist/lib/east-py-lint.js.map +1 -0
  71. package/dist/lib/east-rules-context.d.ts +7 -0
  72. package/dist/lib/east-rules-context.d.ts.map +1 -0
  73. package/dist/lib/east-rules-context.js +91 -0
  74. package/dist/lib/east-rules-context.js.map +1 -0
  75. package/dist/lib/hook-io.d.ts +30 -0
  76. package/dist/lib/hook-io.d.ts.map +1 -0
  77. package/dist/lib/hook-io.js +29 -0
  78. package/dist/lib/hook-io.js.map +1 -0
  79. package/dist/lib/host.d.ts +3 -0
  80. package/dist/lib/host.d.ts.map +1 -0
  81. package/dist/lib/host.js +9 -0
  82. package/dist/lib/host.js.map +1 -0
  83. package/dist/lib/lsp-client.d.ts +34 -0
  84. package/dist/lib/lsp-client.d.ts.map +1 -0
  85. package/dist/lib/lsp-client.js +200 -0
  86. package/dist/lib/lsp-client.js.map +1 -0
  87. package/dist/lib/plugin-status.d.ts +9 -0
  88. package/dist/lib/plugin-status.d.ts.map +1 -0
  89. package/dist/lib/plugin-status.js +164 -0
  90. package/dist/lib/plugin-status.js.map +1 -0
  91. package/dist/lib/review.d.ts +16 -0
  92. package/dist/lib/review.d.ts.map +1 -0
  93. package/dist/lib/review.js +74 -0
  94. package/dist/lib/review.js.map +1 -0
  95. package/dist/lib/search-guidance.d.ts +44 -0
  96. package/dist/lib/search-guidance.d.ts.map +1 -0
  97. package/dist/lib/search-guidance.js +73 -0
  98. package/dist/lib/search-guidance.js.map +1 -0
  99. package/dist/lib/search-hooks.d.ts +75 -0
  100. package/dist/lib/search-hooks.d.ts.map +1 -0
  101. package/dist/lib/search-hooks.js +117 -0
  102. package/dist/lib/search-hooks.js.map +1 -0
  103. package/dist/lib/search.d.ts +121 -0
  104. package/dist/lib/search.d.ts.map +1 -0
  105. package/dist/lib/search.js +181 -0
  106. package/dist/lib/search.js.map +1 -0
  107. package/dist/lib/transcript.d.ts +29 -0
  108. package/dist/lib/transcript.d.ts.map +1 -0
  109. package/dist/lib/transcript.js +109 -0
  110. package/dist/lib/transcript.js.map +1 -0
  111. package/dist/mcp/example-tools.d.ts +33 -0
  112. package/dist/mcp/example-tools.d.ts.map +1 -0
  113. package/dist/mcp/example-tools.js +97 -0
  114. package/dist/mcp/example-tools.js.map +1 -0
  115. package/dist/mcp/server.d.ts +2 -0
  116. package/dist/mcp/server.d.ts.map +1 -0
  117. package/dist/mcp/server.js +52 -0
  118. package/dist/mcp/server.js.map +1 -0
  119. package/dist/scripts/examples-file.d.ts +38 -0
  120. package/dist/scripts/examples-file.d.ts.map +1 -0
  121. package/dist/scripts/examples-file.js +224 -0
  122. package/dist/scripts/examples-file.js.map +1 -0
  123. package/dist/scripts/generate-index.d.ts +127 -0
  124. package/dist/scripts/generate-index.d.ts.map +1 -0
  125. package/dist/scripts/generate-index.js +315 -0
  126. package/dist/scripts/generate-index.js.map +1 -0
  127. package/dist/status/report.d.ts +2 -0
  128. package/dist/status/report.d.ts.map +1 -0
  129. package/dist/status/report.js +9 -0
  130. package/dist/status/report.js.map +1 -0
  131. package/index.json +44926 -0
  132. package/package.json +65 -3
  133. package/scripts/render-python.py +67 -0
@@ -0,0 +1,52 @@
1
+ import { EastLspPool } from "../lib/lsp-client.js";
2
+ import { join, dirname } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
5
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
6
+ import { z } from "zod";
7
+ import { registerExampleTools } from "./example-tools.js";
8
+ import { checkPluginStatus, formatStatus } from "../lib/plugin-status.js";
9
+ const __dirname = dirname(fileURLToPath(import.meta.url));
10
+ // Two levels up from .build/mcp/ to project root
11
+ const INDEX_PATH = join(__dirname, "..", "..", "index.json");
12
+ const server = new McpServer({
13
+ name: "east",
14
+ version: "1.0.0",
15
+ });
16
+ // The example search and fetch, over East's index, loaded once before the
17
+ // server connects: an index that does not load fails it at startup, naming why.
18
+ await registerExampleTools(server, { index: [INDEX_PATH] });
19
+ server.tool("east_status", "Report whether the East plugin's features are installed and working: bundled hooks, the example-search index, the PostToolUse diagnostics daemon, skills, and East project detection. Use when asked to check or confirm the East plugin's status or health.", {
20
+ directory: z
21
+ .string()
22
+ .optional()
23
+ .describe("Project directory to check for diagnostics readiness (defaults to the current working directory)"),
24
+ }, async ({ directory }) => {
25
+ const checks = await checkPluginStatus(join(__dirname, "..", ".."), directory ?? process.cwd());
26
+ return { content: [{ type: "text", text: formatStatus(checks) }] };
27
+ });
28
+ const lsp = new EastLspPool();
29
+ server.tool("east_lsp_diagnostics", "Run the bundled real TypeScript/TSX or Python language server on a source file. Connections stay warm. Returns the next diagnostic publication; Python's build tier may publish later. Use refresh: false to read the latest publication after waiting. No publication means unavailable or still pending, never a clean bill of health.", {
30
+ file: z.string().describe("Absolute source file path (.ts, .tsx, .py)"),
31
+ timeout_ms: z.number().int().min(100).max(30000).default(15000),
32
+ refresh: z.boolean().default(true),
33
+ }, async ({ file, timeout_ms, refresh }) => {
34
+ try {
35
+ const publication = await lsp.diagnostics(file, timeout_ms, refresh);
36
+ return { content: [{ type: "text", text: publication === null
37
+ ? "No diagnostic publication available. The server may still be computing, or this project may lack its language runtime. This does not mean the file is clean."
38
+ : JSON.stringify({ ...publication, scope: "East-aware diagnostics only. Empty diagnostics can also mean the file is outside the server scope; check east_status for runtime readiness. Python build-tier updates may arrive later; poll with refresh: false." }, null, 2) }] };
39
+ }
40
+ catch (error) {
41
+ return { isError: true, content: [{ type: "text", text: String(error) }] };
42
+ }
43
+ });
44
+ server.server.onclose = () => lsp.close();
45
+ // The stdio transport never reports end of input: a client that closes stdin
46
+ // has gone, and the language servers' pipes must not keep this process alive.
47
+ process.stdin.once("end", () => lsp.close());
48
+ for (const signal of ["SIGINT", "SIGTERM"])
49
+ process.on(signal, () => { lsp.close(); process.exit(0); });
50
+ const transport = new StdioServerTransport();
51
+ await server.connect(transport);
52
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../mcp/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * examples-file.ts
3
+ *
4
+ * Reads one examples file (`*.examples.ts` / `*.examples.tsx`) for the search
5
+ * index: every `export const NAME = example({ … })` with its suite, keywords,
6
+ * description and `fn` source, the module-scope declarations that `fn`
7
+ * reaches, and the file's imports.
8
+ *
9
+ * The TypeScript parser reads the file — as TSX when it is one. A text scan
10
+ * cannot bound an example in a `.tsx` file, where JSX text is not code: an
11
+ * apostrophe in it ("a task's seam") read as an unclosed string literal, and
12
+ * the example was dropped from the index with only a warning (#846). Every
13
+ * field comes off the syntax tree, so a description keeps its apostrophes too.
14
+ */
15
+ /** One `example()` export of a file. */
16
+ export interface ParsedExample {
17
+ exportName: string;
18
+ suiteName: string;
19
+ description: string;
20
+ keywords: string[];
21
+ source: string;
22
+ imports: string[];
23
+ }
24
+ /**
25
+ * Read an examples file's `example()` exports, in file order.
26
+ *
27
+ * Each carries the suite of the section divider above it
28
+ * (`// ---\n// Name\n// ---`), its keywords and description, and its source:
29
+ * a comment line with the description and one with the `inputs` / `returns`
30
+ * source when the example declares them, then the module-scope declarations
31
+ * its `fn` reaches as written (each under its doc comment, a blank line after
32
+ * each), then the `fn` initializer as written.
33
+ *
34
+ * @param filePath - The examples file
35
+ * @returns The file's examples; an export without an `fn` is skipped with a warning
36
+ */
37
+ export declare function parseExamplesFile(filePath: string): ParsedExample[];
38
+ //# sourceMappingURL=examples-file.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"examples-file.d.ts","sourceRoot":"","sources":["../../scripts/examples-file.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAKH,wCAAwC;AACxC,MAAM,WAAW,aAAa;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,EAAE,CAAC;CACrB;AAkID;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,aAAa,EAAE,CA0FnE"}
@@ -0,0 +1,224 @@
1
+ /**
2
+ * examples-file.ts
3
+ *
4
+ * Reads one examples file (`*.examples.ts` / `*.examples.tsx`) for the search
5
+ * index: every `export const NAME = example({ … })` with its suite, keywords,
6
+ * description and `fn` source, the module-scope declarations that `fn`
7
+ * reaches, and the file's imports.
8
+ *
9
+ * The TypeScript parser reads the file — as TSX when it is one. A text scan
10
+ * cannot bound an example in a `.tsx` file, where JSX text is not code: an
11
+ * apostrophe in it ("a task's seam") read as an unclosed string literal, and
12
+ * the example was dropped from the index with only a warning (#846). Every
13
+ * field comes off the syntax tree, so a description keeps its apostrophes too.
14
+ */
15
+ import * as fs from "node:fs";
16
+ import * as ts from "typescript";
17
+ // ---------------------------------------------------------------------------
18
+ // Extract imports (stop at first export or section divider)
19
+ // ---------------------------------------------------------------------------
20
+ function extractImports(lines) {
21
+ const imports = [];
22
+ for (const line of lines) {
23
+ if (/^\s*export\s+const\s/.test(line) || /^\/\/ -{3,}/.test(line)) {
24
+ break;
25
+ }
26
+ if (/^\s*import\s/.test(line)) {
27
+ imports.push(line.trimEnd());
28
+ }
29
+ }
30
+ return imports;
31
+ }
32
+ // ---------------------------------------------------------------------------
33
+ // The example declarations
34
+ // ---------------------------------------------------------------------------
35
+ /** The initializer of an object literal's `key: …` property, if it has one. */
36
+ function propertyOf(obj, key) {
37
+ return obj.properties.find((p) => ts.isPropertyAssignment(p) && ts.isIdentifier(p.name) && p.name.text === key)?.initializer;
38
+ }
39
+ /** Each `NAME = example({ … })` a top-level `export const` statement declares, with its object literal. */
40
+ function examplesOf(statement) {
41
+ if (!ts.isVariableStatement(statement))
42
+ return [];
43
+ if (!statement.modifiers?.some((m) => m.kind === ts.SyntaxKind.ExportKeyword))
44
+ return [];
45
+ if ((statement.declarationList.flags & ts.NodeFlags.Const) === 0)
46
+ return [];
47
+ const out = [];
48
+ for (const decl of statement.declarationList.declarations) {
49
+ const call = decl.initializer;
50
+ if (call === undefined || !ts.isCallExpression(call))
51
+ continue;
52
+ if (!ts.isIdentifier(call.expression) || call.expression.text !== "example")
53
+ continue;
54
+ const obj = call.arguments[0];
55
+ if (!ts.isIdentifier(decl.name) || obj === undefined || !ts.isObjectLiteralExpression(obj))
56
+ continue;
57
+ out.push({ name: decl.name.text, obj });
58
+ }
59
+ return out;
60
+ }
61
+ /** Identifier texts referenced anywhere in a subtree — never a property
62
+ * access's member, a qualified type's right side, an object literal's key or
63
+ * a JSX attribute's name, so a field cannot stand for a declaration of the
64
+ * same name. */
65
+ function refsOf(node) {
66
+ const out = new Set();
67
+ const walk = (n) => {
68
+ if (ts.isIdentifier(n)
69
+ && !(ts.isPropertyAccessExpression(n.parent) && n.parent.name === n)
70
+ && !(ts.isQualifiedName(n.parent) && n.parent.right === n)
71
+ && !(ts.isPropertyAssignment(n.parent) && n.parent.name === n)
72
+ && !(ts.isJsxAttribute(n.parent) && n.parent.name === n)) {
73
+ out.add(n.text);
74
+ }
75
+ ts.forEachChild(n, walk);
76
+ };
77
+ walk(node);
78
+ return out;
79
+ }
80
+ /** The names a top-level statement declares. */
81
+ function namesOf(statement) {
82
+ if (ts.isVariableStatement(statement)) {
83
+ return statement.declarationList.declarations
84
+ .flatMap((d) => ts.isIdentifier(d.name) ? [d.name.text] : []);
85
+ }
86
+ if ((ts.isTypeAliasDeclaration(statement) || ts.isInterfaceDeclaration(statement)
87
+ || ts.isEnumDeclaration(statement) || ts.isFunctionDeclaration(statement)
88
+ || ts.isClassDeclaration(statement)) && statement.name !== undefined) {
89
+ return [statement.name.text];
90
+ }
91
+ return [];
92
+ }
93
+ /** The doc comment directly above a statement — its own JSDoc block — if it
94
+ * has one. A section divider or the file's prose above it is not the
95
+ * statement's, and stays behind. */
96
+ function docOf(content, statement) {
97
+ const ranges = ts.getLeadingCommentRanges(content, statement.getFullStart()) ?? [];
98
+ const own = ranges[ranges.length - 1];
99
+ if (own === undefined || own.kind !== ts.SyntaxKind.MultiLineCommentTrivia)
100
+ return undefined;
101
+ const text = content.slice(own.pos, own.end);
102
+ return text.startsWith("/**") ? text : undefined;
103
+ }
104
+ /**
105
+ * The module-scope declarations an example reaches: the closure of the
106
+ * identifiers its `fn` references over the file's other top-level
107
+ * statements, in source order, each under its doc comment. An e3-ui example
108
+ * binds datasets declared beside it (`e3.input`, `e3.record`, `e3.task`),
109
+ * built from types and functions declared there too; without them the
110
+ * indexed `fn` would name what it never shows.
111
+ */
112
+ function dependenciesOf(fn, declarations, byName) {
113
+ const needed = new Set();
114
+ const queue = [...refsOf(fn)].flatMap((ref) => byName.get(ref) ?? []);
115
+ while (queue.length > 0) {
116
+ const i = queue.pop();
117
+ if (needed.has(i))
118
+ continue;
119
+ needed.add(i);
120
+ for (const ref of declarations[i].refs) {
121
+ const next = byName.get(ref);
122
+ if (next !== undefined && !needed.has(next))
123
+ queue.push(next);
124
+ }
125
+ }
126
+ return declarations.filter((_, i) => needed.has(i)).map((d) => d.text);
127
+ }
128
+ // ---------------------------------------------------------------------------
129
+ // Parse a single examples file (*.examples.ts / *.examples.tsx)
130
+ // ---------------------------------------------------------------------------
131
+ /**
132
+ * Read an examples file's `example()` exports, in file order.
133
+ *
134
+ * Each carries the suite of the section divider above it
135
+ * (`// ---\n// Name\n// ---`), its keywords and description, and its source:
136
+ * a comment line with the description and one with the `inputs` / `returns`
137
+ * source when the example declares them, then the module-scope declarations
138
+ * its `fn` reaches as written (each under its doc comment, a blank line after
139
+ * each), then the `fn` initializer as written.
140
+ *
141
+ * @param filePath - The examples file
142
+ * @returns The file's examples; an export without an `fn` is skipped with a warning
143
+ */
144
+ export function parseExamplesFile(filePath) {
145
+ // Normalise CRLF/CR to LF so the extracted source (and the index built from
146
+ // it) is byte-identical regardless of the checkout's line-ending settings.
147
+ const content = fs.readFileSync(filePath, "utf-8").replace(/\r\n?/g, "\n");
148
+ const lines = content.split("\n");
149
+ const imports = extractImports(lines);
150
+ const results = [];
151
+ // Extract section names from comment dividers
152
+ const sectionRe = /^\/\/ -{3,}\s*\n\/\/ (.+)\n\/\/ -{3,}/gm;
153
+ const sections = [];
154
+ let sectionMatch;
155
+ while ((sectionMatch = sectionRe.exec(content)) !== null) {
156
+ sections.push({ name: sectionMatch[1].trim(), index: sectionMatch.index });
157
+ }
158
+ const sf = ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true, filePath.endsWith(".tsx") ? ts.ScriptKind.TSX : ts.ScriptKind.TS);
159
+ // The top-level statements an example may reach: every one but the
160
+ // imports and the examples themselves.
161
+ const declarations = sf.statements
162
+ .filter((s) => !ts.isImportDeclaration(s) && !ts.isExportDeclaration(s) && examplesOf(s).length === 0)
163
+ .map((s) => {
164
+ const doc = docOf(content, s);
165
+ const body = s.getText(sf);
166
+ return { names: namesOf(s), refs: refsOf(s), text: doc === undefined ? body : `${doc}\n${body}` };
167
+ });
168
+ const byName = new Map();
169
+ declarations.forEach((d, i) => d.names.forEach((name) => byName.set(name, i)));
170
+ for (const statement of sf.statements) {
171
+ const exportIndex = statement.getStart(sf);
172
+ for (const { name: exportName, obj } of examplesOf(statement)) {
173
+ // Determine which section this export belongs to
174
+ let currentSuite = "";
175
+ for (const section of sections) {
176
+ if (section.index < exportIndex) {
177
+ currentSuite = section.name;
178
+ }
179
+ else {
180
+ break;
181
+ }
182
+ }
183
+ const keywordsExpr = propertyOf(obj, "keywords");
184
+ const keywords = keywordsExpr !== undefined && ts.isArrayLiteralExpression(keywordsExpr)
185
+ ? keywordsExpr.elements.filter(ts.isStringLiteralLike).map((e) => e.text)
186
+ : [];
187
+ const descriptionExpr = propertyOf(obj, "description");
188
+ const description = descriptionExpr !== undefined && ts.isStringLiteralLike(descriptionExpr) ? descriptionExpr.text : "";
189
+ const fnExpr = propertyOf(obj, "fn");
190
+ if (fnExpr === undefined) {
191
+ console.warn(` Warning: Could not extract fn for example "${exportName}" in ${filePath}`);
192
+ continue;
193
+ }
194
+ const fnValue = fnExpr.getText(sf);
195
+ const inputsRaw = propertyOf(obj, "inputs")?.getText(sf) ?? null;
196
+ const returnsRaw = propertyOf(obj, "returns")?.getText(sf) ?? null;
197
+ // Compose annotated source: prepend description + inputs/returns as comments
198
+ const commentLines = [];
199
+ if (description) {
200
+ commentLines.push(`// ${description}`);
201
+ }
202
+ if (inputsRaw != null || returnsRaw != null) {
203
+ const parts = [];
204
+ if (inputsRaw != null)
205
+ parts.push(`inputs: ${inputsRaw}`);
206
+ if (returnsRaw != null)
207
+ parts.push(`returns: ${returnsRaw}`);
208
+ commentLines.push(`// ${parts.join(" ")}`);
209
+ }
210
+ const dependencies = dependenciesOf(fnExpr, declarations, byName);
211
+ const source = [...commentLines, ...dependencies.flatMap((d) => [d, ""]), fnValue].join("\n");
212
+ results.push({
213
+ exportName,
214
+ suiteName: currentSuite,
215
+ description,
216
+ keywords,
217
+ source,
218
+ imports,
219
+ });
220
+ }
221
+ }
222
+ return results;
223
+ }
224
+ //# sourceMappingURL=examples-file.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"examples-file.js","sourceRoot":"","sources":["../../scripts/examples-file.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,127 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * generate-index.ts
4
+ *
5
+ * Builds the example search index (index.json) the plugin's MCP search tool
6
+ * serves (#654) — East's, or a plugin's that builds on East's: the sources,
7
+ * the libraries and the hand-written entries are the caller's.
8
+ *
9
+ * Usage: east-plugin-generate-index --base-dir <dir> [--config <index.config.json>]
10
+ * [--static <index.static.json>] [--out <index.json>]
11
+ *
12
+ * Each path defaults to this package's own (East's index). From code, call
13
+ * `generateIndex` with the config and entries themselves.
14
+ *
15
+ * Two kinds of source, declared in index.config.json:
16
+ *
17
+ * - `ir: true` — a package whose `*.examples.ts` are East programs (east,
18
+ * east-node-std, east-node-io, east-py-datascience). Each `example()` export
19
+ * is imported from the package's BUILT test modules (`distTest`) and stored
20
+ * as its IR — the example itself, loc_ids zeroed — with its declared types,
21
+ * inputs, expected return, the builtins and platform functions it calls,
22
+ * and the TypeScript printed from that IR by `East.toSource` — with the
23
+ * `libraries` of the config imported and given to the printer, so a
24
+ * platform call prints as the library exports it (`Compression.Tar.create`)
25
+ * rather than as a hoisted declaration. The python rendering is added by
26
+ * `scripts/render-python.py` (the python printer), which fills the
27
+ * `python` field this script leaves null. No authored source text is
28
+ * stored: both languages are printings of the IR.
29
+ * - otherwise — a package whose examples are not printable programs (UI
30
+ * components authored as JSX, hand-written CLI stubs): the authored
31
+ * TypeScript source is extracted from the file text, as before.
32
+ *
33
+ * Each example uses the `example()` pattern:
34
+ * export const name = example({ keywords, description, fn, inputs, returns })
35
+ *
36
+ * Section comments (// ---\n// Name\n// ---) provide suite grouping. Each
37
+ * file is read by `examples-file.ts`, through the TypeScript parser.
38
+ */
39
+ /** One package whose examples are indexed. */
40
+ export interface SourceConfig {
41
+ package: string;
42
+ skill: string;
43
+ testDir: string;
44
+ pattern: string | string[];
45
+ /** The examples are East programs: store their IR (see the module notes). */
46
+ ir?: boolean;
47
+ /** The package's build output (mirrors the package layout: `test/x.examples.ts` → `dist/test/x.examples.js`); default `<testDir>/dist`. */
48
+ dist?: string;
49
+ }
50
+ /** What an index holds: `index.config.json`'s shape. */
51
+ export interface IndexConfig {
52
+ sources: SourceConfig[];
53
+ /** Library modules whose exported declarations spell platform calls in the printed TypeScript: specifier → built entry, relative to the base dir. */
54
+ libraries?: Record<string, string>;
55
+ }
56
+ /** One example. A program entry carries `ir` / `ts` / `python` / `signature` / `inputs` / `returns` / `builtins`; a source entry carries `source`. */
57
+ export interface IndexEntry {
58
+ id: string;
59
+ skill: string;
60
+ package: string;
61
+ file: string;
62
+ suite: string;
63
+ test: string;
64
+ keywords: string[];
65
+ imports: string[];
66
+ /**
67
+ * What the entry can be shown as: `["typescript", "python"]` for a program
68
+ * (both printed from its IR), `["tsx"]` for a JSX-authored UI example,
69
+ * `["typescript"]` for authored TypeScript that is not a printable program.
70
+ * Derived from the package and the file, never declared per example.
71
+ */
72
+ languages: Array<"typescript" | "python" | "tsx">;
73
+ /** Authored TypeScript (UI and static entries only). */
74
+ source?: string;
75
+ /** The example's IR as JSON, loc_ids zeroed (program entries). */
76
+ ir?: string;
77
+ /** The TypeScript printed from `ir` (program entries). */
78
+ ts?: string;
79
+ /** The python printed from `ir`; null until `render-python.py` runs (program entries). */
80
+ python?: string | null;
81
+ /** The declared function type, as TypeScript type constructors (program entries). */
82
+ signature?: {
83
+ inputs: string[];
84
+ output: string;
85
+ async: boolean;
86
+ };
87
+ /** The example inputs and expected return as JSON (program entries; null when they are expressions). */
88
+ inputs?: string | null;
89
+ returns?: string | null;
90
+ /** The builtins and platform functions the IR calls, sorted (program entries). */
91
+ builtins?: string[];
92
+ }
93
+ /** How many entries and files an index holds, by package. */
94
+ export interface IndexStats {
95
+ totalEntries: number;
96
+ totalFiles: number;
97
+ packages: Record<string, number>;
98
+ }
99
+ /** An index: `index.json`'s shape. */
100
+ export interface IndexOutput {
101
+ version: number;
102
+ stats: IndexStats;
103
+ entries: IndexEntry[];
104
+ }
105
+ /** What `generateIndex` indexes. */
106
+ export interface GenerateIndexOptions {
107
+ /** The directory the config's `testDir`, `dist` and library paths are relative to. */
108
+ baseDir: string;
109
+ /** The packages whose examples are indexed, and the libraries their printed TypeScript imports. */
110
+ config: IndexConfig;
111
+ /** Hand-written entries merged in (`index.static.json`'s `entries`), e.g. a CLI's. */
112
+ staticEntries?: readonly IndexEntry[];
113
+ /** Progress lines (default `console.log`). */
114
+ log?: (line: string) => void;
115
+ }
116
+ /**
117
+ * Builds an index: every `example()` of each source's examples files, a
118
+ * program's as its IR and the TypeScript printed from it, any other's as its
119
+ * authored source, then the hand-written entries. The python printings are
120
+ * `scripts/render-python.py`'s, run over the written index.
121
+ *
122
+ * @param options - The base directory, the config and the hand-written entries
123
+ * @returns The index, ready to write as `index.json`
124
+ * @throws {Error} When a program package or a library is not built, or an export is not an `example()`
125
+ */
126
+ export declare function generateIndex(options: GenerateIndexOptions): Promise<IndexOutput>;
127
+ //# sourceMappingURL=generate-index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-index.d.ts","sourceRoot":"","sources":["../../scripts/generate-index.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAYH,8CAA8C;AAC9C,MAAM,WAAW,YAAY;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC3B,6EAA6E;IAC7E,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,2IAA2I;IAC3I,IAAI,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wDAAwD;AACxD,MAAM,WAAW,WAAW;IACxB,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,qJAAqJ;IACrJ,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACtC;AAED,sJAAsJ;AACtJ,MAAM,WAAW,UAAU;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB;;;;;OAKG;IACH,SAAS,EAAE,KAAK,CAAC,YAAY,GAAG,QAAQ,GAAG,KAAK,CAAC,CAAC;IAClD,wDAAwD;IACxD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kEAAkE;IAClE,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,0DAA0D;IAC1D,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,0FAA0F;IAC1F,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,qFAAqF;IACrF,SAAS,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,EAAE,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC;IACjE,wGAAwG;IACxG,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,kFAAkF;IAClF,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,6DAA6D;AAC7D,MAAM,WAAW,UAAU;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACpC;AAED,sCAAsC;AACtC,MAAM,WAAW,WAAW;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,UAAU,CAAC;IAClB,OAAO,EAAE,UAAU,EAAE,CAAC;CACzB;AAqHD,oCAAoC;AACpC,MAAM,WAAW,oBAAoB;IACjC,sFAAsF;IACtF,OAAO,EAAE,MAAM,CAAC;IAChB,mGAAmG;IACnG,MAAM,EAAE,WAAW,CAAC;IACpB,sFAAsF;IACtF,aAAa,CAAC,EAAE,SAAS,UAAU,EAAE,CAAC;IACtC,8CAA8C;IAC9C,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAChC;AAED;;;;;;;;;GASG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,WAAW,CAAC,CAyGvF"}