@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,64 @@
1
+ import type { HookInput } from "./hook-io.js";
2
+ import { type PatchFile } from "./codex-tools.js";
3
+ import type { SearchHookReply } from "./search-hooks.js";
4
+ /** What a Codex tool call touches: the files it writes or reads, and the command or patch it runs. */
5
+ export interface CodexToolCall {
6
+ /** The tool's name. */
7
+ tool: string;
8
+ /** The shell command or the patch, as the tool's input holds it. */
9
+ command: string;
10
+ /** Whether the tool runs a shell command. */
11
+ shell: boolean;
12
+ /** The files a patch adds, updates, moves or deletes. */
13
+ patches: PatchFile[];
14
+ /** The file a file tool names, resolved against the working directory. */
15
+ filePath: string | undefined;
16
+ /** Every file the call writes or reads, each once (a deleted file excluded). */
17
+ paths: string[];
18
+ }
19
+ /**
20
+ * What a Codex tool call touches.
21
+ *
22
+ * @param event - The hook's event
23
+ * @returns The files, command and patch of the call
24
+ */
25
+ export declare function codexToolCall(event: HookInput): CodexToolCall;
26
+ /** The Codex search gate's configuration. */
27
+ export interface CodexSearchGateOptions {
28
+ /** The tools whose call in a transcript counts as a search. */
29
+ searchTools: readonly string[];
30
+ /** Matches a search or fetch tool's MCP name, whatever server name Codex gives it. */
31
+ searchToolName: RegExp;
32
+ /** The instruction a write of corpus code with no search on record meets (`gateText(...)`). */
33
+ gateText: string;
34
+ /** The reminder a read of the corpus gets (`readText(...)`). */
35
+ readText: string;
36
+ /** Whether a file tool reaches for the corpus (`corpusReadFor(scope)`). */
37
+ isCorpusRead(tool: string, input: Record<string, unknown>): boolean;
38
+ /** Matches a shell command that reaches for the corpus. */
39
+ shellSweep: RegExp;
40
+ /** Matches the corpus's code in a file's text, before or after the write. */
41
+ corpusCode: RegExp;
42
+ /** The prefix of the per-session marker in the temporary directory that records a search seen. */
43
+ markerPrefix: string;
44
+ /** The environment variable that makes the gate refuse the write when it is `deny`. */
45
+ requireSearchEnv: string;
46
+ }
47
+ /** East's Codex gate. */
48
+ export declare const EAST_CODEX_SEARCH_GATE: CodexSearchGateOptions;
49
+ /**
50
+ * The search-first gate for a Codex tool call. After a successful search or
51
+ * fetch it records the search (`"recorded"`) — the stable hook event, not the
52
+ * transcript's undocumented wire format. Before a call, it reminds a read of
53
+ * the corpus, and gives a write of corpus code with no search on record the
54
+ * instruction to search first: a reminder, or a refusal when the options'
55
+ * environment variable is `deny`.
56
+ *
57
+ * @param event - The hook's event
58
+ * @param options - The gate's configuration
59
+ * @param call - What the call touches, when the hook has read it already for
60
+ * its own use, so the patch or the command is parsed once
61
+ * @returns The reply before a call, `"recorded"` after a search, else null
62
+ */
63
+ export declare function codexSearchGate(event: HookInput, options: CodexSearchGateOptions, call?: CodexToolCall): Promise<SearchHookReply | "recorded" | null>;
64
+ //# sourceMappingURL=codex-hook.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codex-hook.d.ts","sourceRoot":"","sources":["../../lib/codex-hook.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAA8B,KAAK,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAI9E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAOzD,sGAAsG;AACtG,MAAM,WAAW,aAAa;IAC5B,uBAAuB;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,oEAAoE;IACpE,OAAO,EAAE,MAAM,CAAC;IAChB,6CAA6C;IAC7C,KAAK,EAAE,OAAO,CAAC;IACf,yDAAyD;IACzD,OAAO,EAAE,SAAS,EAAE,CAAC;IACrB,0EAA0E;IAC1E,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,gFAAgF;IAChF,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,SAAS,GAAG,aAAa,CAc7D;AAED,6CAA6C;AAC7C,MAAM,WAAW,sBAAsB;IACrC,+DAA+D;IAC/D,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,sFAAsF;IACtF,cAAc,EAAE,MAAM,CAAC;IACvB,+FAA+F;IAC/F,QAAQ,EAAE,MAAM,CAAC;IACjB,gEAAgE;IAChE,QAAQ,EAAE,MAAM,CAAC;IACjB,2EAA2E;IAC3E,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC;IACpE,2DAA2D;IAC3D,UAAU,EAAE,MAAM,CAAC;IACnB,6EAA6E;IAC7E,UAAU,EAAE,MAAM,CAAC;IACnB,kGAAkG;IAClG,YAAY,EAAE,MAAM,CAAC;IACrB,uFAAuF;IACvF,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,yBAAyB;AACzB,eAAO,MAAM,sBAAsB,EAAE,sBAUpC,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,wBAAsB,eAAe,CACnC,KAAK,EAAE,SAAS,EAChB,OAAO,EAAE,sBAAsB,EAC/B,IAAI,GAAE,aAAoC,GACzC,OAAO,CAAC,eAAe,GAAG,UAAU,GAAG,IAAI,CAAC,CA6B9C"}
@@ -0,0 +1,94 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { existsSync, writeFileSync } from "node:fs";
3
+ import { createHash } from "node:crypto";
4
+ import { tmpdir } from "node:os";
5
+ import { join, resolve } from "node:path";
6
+ import { patchFiles, shellReadPaths } from "./codex-tools.js";
7
+ import { writtenPaths } from "./bash-writes.js";
8
+ import { SEARCH_TOOLS, searchedInTranscript } from "./transcript.js";
9
+ import { GATE_TEXT, READ_TEXT, isExampleCorpusRead } from "./search-guidance.js";
10
+ /**
11
+ * What a Codex tool call touches.
12
+ *
13
+ * @param event - The hook's event
14
+ * @returns The files, command and patch of the call
15
+ */
16
+ export function codexToolCall(event) {
17
+ const cwd = event.cwd || process.cwd();
18
+ const input = event.tool_input ?? {};
19
+ const command = typeof input.command === 'string' ? input.command : typeof input['cmd'] === 'string' ? input['cmd'] : '';
20
+ const tool = event.tool_name ?? '';
21
+ const patches = tool === 'apply_patch' ? patchFiles(command, cwd) : [];
22
+ const shell = ['Bash', 'exec_command', 'shell_command'].includes(tool);
23
+ const filePath = typeof input.file_path === 'string' ? resolve(cwd, input.file_path) : undefined;
24
+ const paths = [...new Set([
25
+ ...patches.filter(p => !p.deleted).map(p => p.path),
26
+ ...(shell ? [...writtenPaths(command, cwd), ...shellReadPaths(command, cwd)] : []),
27
+ ...(filePath ? [filePath] : []),
28
+ ])];
29
+ return { tool, command, shell, patches, filePath, paths };
30
+ }
31
+ /** East's Codex gate. */
32
+ export const EAST_CODEX_SEARCH_GATE = {
33
+ searchTools: SEARCH_TOOLS,
34
+ searchToolName: /__(?:search_east_examples|get_east_example)$/,
35
+ gateText: GATE_TEXT,
36
+ readText: READ_TEXT,
37
+ isCorpusRead: isExampleCorpusRead,
38
+ shellSweep: /node_modules\/@elaraai(?:\/|\b)|\.examples\.tsx?/,
39
+ corpusCode: /@elaraai\/east|(?:from|import)\s+east\b/,
40
+ markerPrefix: "east-codex-search-",
41
+ requireSearchEnv: "EAST_REQUIRE_SEARCH",
42
+ };
43
+ /**
44
+ * The search-first gate for a Codex tool call. After a successful search or
45
+ * fetch it records the search (`"recorded"`) — the stable hook event, not the
46
+ * transcript's undocumented wire format. Before a call, it reminds a read of
47
+ * the corpus, and gives a write of corpus code with no search on record the
48
+ * instruction to search first: a reminder, or a refusal when the options'
49
+ * environment variable is `deny`.
50
+ *
51
+ * @param event - The hook's event
52
+ * @param options - The gate's configuration
53
+ * @param call - What the call touches, when the hook has read it already for
54
+ * its own use, so the patch or the command is parsed once
55
+ * @returns The reply before a call, `"recorded"` after a search, else null
56
+ */
57
+ export async function codexSearchGate(event, options, call = codexToolCall(event)) {
58
+ const input = event.tool_input ?? {};
59
+ const marker = join(tmpdir(), options.markerPrefix + createHash('sha256').update(event.session_id ?? '').digest('hex'));
60
+ if (event.hook_event_name === 'PostToolUse') {
61
+ if (call.tool.startsWith('mcp__') && options.searchToolName.test(call.tool)) {
62
+ if (event.tool_response?.['isError'] !== true)
63
+ writeFileSync(marker, 'searched');
64
+ return 'recorded';
65
+ }
66
+ return null;
67
+ }
68
+ const context = [];
69
+ if (options.isCorpusRead(call.tool, input) || (call.shell && options.shellSweep.test(call.command))) {
70
+ context.push(options.readText);
71
+ }
72
+ const writes = call.tool === 'apply_patch' ? call.patches.filter(p => !p.deleted) :
73
+ call.shell ? writtenPaths(call.command, event.cwd || process.cwd()).map(path => ({ path, originalPath: path, code: call.command })) :
74
+ call.filePath && ['Edit', 'Write'].includes(call.tool) ? [{ path: call.filePath, originalPath: call.filePath, code: input.content ?? input.new_string ?? '' }] : [];
75
+ let corpusWrite = false;
76
+ for (const file of writes) {
77
+ if (!/\.(tsx?|js|py)$/.test(file.path))
78
+ continue;
79
+ let old = '';
80
+ try {
81
+ old = await readFile(file.originalPath, 'utf8');
82
+ }
83
+ catch { /* new file */ }
84
+ if (options.corpusCode.test(old + '\n' + file.code))
85
+ corpusWrite = true;
86
+ }
87
+ if (corpusWrite && !existsSync(marker) && !(event.transcript_path && await searchedInTranscript(event.transcript_path, options.searchTools))) {
88
+ if (process.env[options.requireSearchEnv] === 'deny')
89
+ return { decision: 'deny', text: options.gateText };
90
+ context.push(options.gateText);
91
+ }
92
+ return context.length > 0 ? { decision: 'context', text: context.join('\n\n') } : null;
93
+ }
94
+ //# sourceMappingURL=codex-hook.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codex-hook.js","sourceRoot":"","sources":["../../lib/codex-hook.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ /** The names a skill is adapted between. */
2
+ export interface SkillNames {
3
+ /** The Claude Code MCP prefix of the plugin's tools, which Codex drops (`mcp__plugin_east_east__`). */
4
+ claudeToolPrefix: string;
5
+ /** How Claude Code names the plugin's skills (`/east:`). */
6
+ claudeSkillPrefix: string;
7
+ /** How Codex names them (`$east-codex-plugin:`). */
8
+ codexSkillPrefix: string;
9
+ /** The Claude Code plugin's name (`east-claude-plugin`). */
10
+ claudePlugin: string;
11
+ /** The Codex plugin's name (`east-codex-plugin`). */
12
+ codexPlugin: string;
13
+ }
14
+ /** East's names. */
15
+ export declare const EAST_SKILL_NAMES: SkillNames;
16
+ /**
17
+ * A skill's text adapted for Codex: the names, the words, and a description
18
+ * Codex takes — at most 1024 characters with no angle brackets, the whole of
19
+ * a longer or bracketed one kept in the body.
20
+ *
21
+ * @param text - The SKILL.md as written for Claude Code
22
+ * @param names - The names it is adapted between (default East's)
23
+ * @returns The SKILL.md for Codex
24
+ * @throws {Error} When the skill has no frontmatter
25
+ */
26
+ export declare function adaptSkill(text: string, names?: SkillNames): string;
27
+ /**
28
+ * Writes a Codex plugin's skills as real files: every skill directory under
29
+ * `sources`, its Markdown adapted and every other file copied through any
30
+ * symlink.
31
+ *
32
+ * @param sources - The directory of skill directories, as written for Claude Code
33
+ * @param target - The Codex plugin's `skills` directory
34
+ * @param names - The names they are adapted between (default East's)
35
+ * @returns The skills written, by directory name
36
+ */
37
+ export declare function materializeSkills(sources: string, target: string, names?: SkillNames): Promise<string[]>;
38
+ //# sourceMappingURL=codex-skills.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codex-skills.d.ts","sourceRoot":"","sources":["../../lib/codex-skills.ts"],"names":[],"mappings":"AASA,4CAA4C;AAC5C,MAAM,WAAW,UAAU;IACzB,uGAAuG;IACvG,gBAAgB,EAAE,MAAM,CAAC;IACzB,4DAA4D;IAC5D,iBAAiB,EAAE,MAAM,CAAC;IAC1B,oDAAoD;IACpD,gBAAgB,EAAE,MAAM,CAAC;IACzB,4DAA4D;IAC5D,YAAY,EAAE,MAAM,CAAC;IACrB,qDAAqD;IACrD,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,oBAAoB;AACpB,eAAO,MAAM,gBAAgB,EAAE,UAM9B,CAAC;AAEF;;;;;;;;;GASG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,GAAE,UAA6B,GAAG,MAAM,CA0BrF;AAED;;;;;;;;;GASG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,GAAE,UAA6B,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAgBhI"}
@@ -0,0 +1,80 @@
1
+ import { readdir, readFile, mkdir, writeFile, cp } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ /** East's names. */
4
+ export const EAST_SKILL_NAMES = {
5
+ claudeToolPrefix: "mcp__plugin_east_east__",
6
+ claudeSkillPrefix: "/east:",
7
+ codexSkillPrefix: "$east-codex-plugin:",
8
+ claudePlugin: "east-claude-plugin",
9
+ codexPlugin: "east-codex-plugin",
10
+ };
11
+ /**
12
+ * A skill's text adapted for Codex: the names, the words, and a description
13
+ * Codex takes — at most 1024 characters with no angle brackets, the whole of
14
+ * a longer or bracketed one kept in the body.
15
+ *
16
+ * @param text - The SKILL.md as written for Claude Code
17
+ * @param names - The names it is adapted between (default East's)
18
+ * @returns The SKILL.md for Codex
19
+ * @throws {Error} When the skill has no frontmatter
20
+ */
21
+ export function adaptSkill(text, names = EAST_SKILL_NAMES) {
22
+ text = text.replaceAll(names.claudeToolPrefix, '')
23
+ .replaceAll(names.claudeSkillPrefix, names.codexSkillPrefix)
24
+ .replaceAll(names.claudePlugin, names.codexPlugin)
25
+ .replaceAll('Claude Code', 'Codex')
26
+ .replaceAll("the Claude plugin's language server", "the Codex plugin's LSP bridge and hooks")
27
+ .replaceAll('the Claude plugin LSP', 'the Codex plugin diagnostic hooks and LSP bridge')
28
+ .replaceAll('Claude plugin', 'Codex plugin')
29
+ .replaceAll('Generated-with-Claude-Code', 'Generated-with-Codex')
30
+ .replace(/End every commit with the trailer:\n\s*`Co-Authored-By: Claude[^`]+`/, 'Use the repository attribution policy for the actual contributing agent.')
31
+ .replaceAll('${CLAUDE_PLUGIN_ROOT}', '${PLUGIN_ROOT}');
32
+ const frontmatter = /^(---\r?\n)([\s\S]*?)(\r?\n---\r?\n)/.exec(text);
33
+ if (!frontmatter)
34
+ throw new Error('Missing skill frontmatter');
35
+ let details = '';
36
+ const metadata = frontmatter[2].replace(/^description: (.+)$/m, (_line, value) => {
37
+ // The shared skill catalog uses JSON-compatible double-quoted YAML strings.
38
+ const original = JSON.parse(value);
39
+ let description = original.replaceAll('<', '(').replaceAll('>', ')');
40
+ if (description.length > 1024) {
41
+ description = description.slice(0, 940).replace(/\s+\S*$/, '') + '… See the detailed scope below.';
42
+ }
43
+ if (description !== original)
44
+ details = `\n## Detailed skill scope\n\n${original}\n`;
45
+ return 'description: ' + JSON.stringify(description);
46
+ });
47
+ // Preserve all discovery detail in the body, including text too long for metadata.
48
+ return frontmatter[1] + metadata + frontmatter[3] + details + text.slice(frontmatter[0].length);
49
+ }
50
+ /**
51
+ * Writes a Codex plugin's skills as real files: every skill directory under
52
+ * `sources`, its Markdown adapted and every other file copied through any
53
+ * symlink.
54
+ *
55
+ * @param sources - The directory of skill directories, as written for Claude Code
56
+ * @param target - The Codex plugin's `skills` directory
57
+ * @param names - The names they are adapted between (default East's)
58
+ * @returns The skills written, by directory name
59
+ */
60
+ export async function materializeSkills(sources, target, names = EAST_SKILL_NAMES) {
61
+ const written = [];
62
+ for (const entry of await readdir(sources, { withFileTypes: true })) {
63
+ if (!entry.isDirectory())
64
+ continue;
65
+ const source = join(sources, entry.name);
66
+ const skill = join(target, entry.name);
67
+ await mkdir(skill, { recursive: true });
68
+ for (const file of await readdir(source, { withFileTypes: true })) {
69
+ const input = join(source, file.name);
70
+ const output = join(skill, file.name);
71
+ if (file.name.endsWith('.md'))
72
+ await writeFile(output, adaptSkill(await readFile(input, 'utf8'), names));
73
+ else
74
+ await cp(input, output, { recursive: true, dereference: true });
75
+ }
76
+ written.push(entry.name);
77
+ }
78
+ return written;
79
+ }
80
+ //# sourceMappingURL=codex-skills.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codex-skills.js","sourceRoot":"","sources":["../../lib/codex-skills.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ export interface PatchFile {
2
+ path: string;
3
+ code: string;
4
+ deleted: boolean;
5
+ originalPath: string;
6
+ }
7
+ /** Extract file boundaries and added/context text from Codex's apply_patch input. */
8
+ export declare function patchFiles(command: string, cwd: string): PatchFile[];
9
+ /** Concrete source paths in ordinary shell reads. No glob expansion or shell execution. */
10
+ export declare function shellReadPaths(command: string, cwd: string): string[];
11
+ //# sourceMappingURL=codex-tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codex-tools.d.ts","sourceRoot":"","sources":["../../lib/codex-tools.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,SAAS;IAAG,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE;AACjG,qFAAqF;AACrF,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,SAAS,EAAE,CAgBpE;AAED,2FAA2F;AAC3F,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAYrE"}
@@ -0,0 +1,41 @@
1
+ import { resolve } from "node:path";
2
+ /** Extract file boundaries and added/context text from Codex's apply_patch input. */
3
+ export function patchFiles(command, cwd) {
4
+ const files = [];
5
+ let current;
6
+ for (const line of command.split(/\r?\n/)) {
7
+ const header = /^\*\*\* (Add|Update|Delete) File: (.+)$/.exec(line);
8
+ if (header) {
9
+ const path = resolve(cwd, header[2]);
10
+ current = { path, originalPath: path, code: "", deleted: header[1] === "Delete" };
11
+ files.push(current);
12
+ }
13
+ else if (line.startsWith('*** Move to: ') && current) {
14
+ current.path = resolve(cwd, line.slice(13));
15
+ }
16
+ else if (current && (line.startsWith('+') || line.startsWith(' '))) {
17
+ current.code += line.slice(1) + '\n';
18
+ }
19
+ }
20
+ return files;
21
+ }
22
+ /** Concrete source paths in ordinary shell reads. No glob expansion or shell execution. */
23
+ export function shellReadPaths(command, cwd) {
24
+ const paths = new Set();
25
+ let dir = cwd;
26
+ for (const segment of command.split(/&&|;|\n|\|/)) {
27
+ const tokens = [...segment.matchAll(/"([^"\n]*)"|'([^'\n]*)'|([^\s]+)/g)].map(m => m[1] ?? m[2] ?? m[3]);
28
+ if (tokens[0] === 'cd' && tokens[1]) {
29
+ dir = resolve(dir, tokens[1]);
30
+ continue;
31
+ }
32
+ if (!['cat', 'head', 'tail', 'sed', 'rg', 'grep', 'less', 'more'].includes(tokens[0] ?? ''))
33
+ continue;
34
+ for (const token of tokens.slice(1)) {
35
+ if (!token.startsWith('-') && !/[*?$`]/.test(token) && /\.(tsx?|js|py)$/.test(token))
36
+ paths.add(resolve(dir, token));
37
+ }
38
+ }
39
+ return [...paths];
40
+ }
41
+ //# sourceMappingURL=codex-tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codex-tools.js","sourceRoot":"","sources":["../../lib/codex-tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,qFAAqF;AACrF,MAAM,UAAU,UAAU,CAAC,OAAe,EAAE,GAAW;IACrD,MAAM,KAAK,GAAgB,EAAE,CAAC;IAC9B,IAAI,OAA8B,CAAC;IACnC,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;QAC1C,MAAM,MAAM,GAAG,yCAAyC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACpE,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAE,CAAC,CAAC;YACtC,OAAO,GAAG,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,QAAQ,EAAE,CAAC;YAClF,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACtB,CAAC;aAAM,IAAI,IAAI,CAAC,UAAU,CAAC,eAAe,CAAC,IAAI,OAAO,EAAE,CAAC;YACvD,OAAO,CAAC,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;QAC9C,CAAC;aAAM,IAAI,OAAO,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;YACrE,OAAO,CAAC,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;QACvC,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,2FAA2F;AAC3F,MAAM,UAAU,cAAc,CAAC,OAAe,EAAE,GAAW;IACzD,MAAM,KAAK,GAAG,IAAI,GAAG,EAAU,CAAC;IAChC,IAAI,GAAG,GAAG,GAAG,CAAC;IACd,KAAK,MAAM,OAAO,IAAI,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC,EAAE,CAAC;QAClD,MAAM,MAAM,GAAG,CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC,mCAAmC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAE,CAAC,CAAC;QAC1G,IAAI,MAAM,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;YAAC,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;YAAC,SAAS;QAAC,CAAC;QACjF,IAAI,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;YAAE,SAAS;QACtG,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;YACpC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC;gBAAE,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC;QACvH,CAAC;IACH,CAAC;IACD,OAAO,CAAC,GAAG,KAAK,CAAC,CAAC;AACpB,CAAC"}
@@ -0,0 +1,9 @@
1
+ /** Fire-and-forget: ensure a daemon is running for this workspace so the first
2
+ * edit doesn't pay process-spawn latency. Probes the socket and only spawns if
3
+ * nothing is listening (so a live daemon is never disrupted). */
4
+ export declare function warmDaemon(workspace: string): void;
5
+ /** Get the `<east-code-review>` text for `file` from the daemon (lazily
6
+ * spawning it if absent). Returns `""` when clean and `null` when the daemon
7
+ * could not be reached within `budgetMs` — callers degrade to a silent no-op. */
8
+ export declare function getDiagnosticsText(workspace: string, file: string, budgetMs?: number): Promise<string | null>;
9
+ //# sourceMappingURL=diagnostics-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diagnostics-client.d.ts","sourceRoot":"","sources":["../../lib/diagnostics-client.ts"],"names":[],"mappings":"AA8EA;;iEAEiE;AACjE,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAiBlD;AAED;;iFAEiF;AACjF,wBAAsB,kBAAkB,CACtC,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,EACZ,QAAQ,SAAO,GACd,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAwBxB"}
@@ -0,0 +1,123 @@
1
+ import { createConnection } from "node:net";
2
+ import { spawn } from "node:child_process";
3
+ import { createHash } from "node:crypto";
4
+ import { tmpdir } from "node:os";
5
+ import { existsSync, unlinkSync } from "node:fs";
6
+ import { dirname, join, resolve } from "node:path";
7
+ import { fileURLToPath } from "node:url";
8
+ // One resident daemon per installed plugin version, keyed on the bundled daemon
9
+ // path (which lives under the versioned plugin cache dir) — NOT the workspace.
10
+ // It serves every project: createDiagnosticsService caches a LanguageService per
11
+ // tsconfig, so each project cold-loads once and then stays warm. This avoids
12
+ // per-directory daemon churn, and a new plugin version spawns a fresh daemon
13
+ // instead of reusing a stale one.
14
+ function daemonSocket() {
15
+ const hash = createHash("sha1").update(daemonEntry()).digest("hex").slice(0, 16);
16
+ return join(tmpdir(), `east-diag-${hash}.sock`);
17
+ }
18
+ // Inlined by esbuild into .build/hooks/diagnose.js, so import.meta.url is that
19
+ // path: .build/hooks → up one to .build, then daemon/server.js.
20
+ function daemonEntry() {
21
+ return resolve(dirname(fileURLToPath(import.meta.url)), "..", "daemon", "server.js");
22
+ }
23
+ function tryRequest(socketPath, file, timeoutMs) {
24
+ return new Promise((resolveResult) => {
25
+ const conn = createConnection(socketPath);
26
+ let buffer = "";
27
+ let settled = false;
28
+ const settle = (result) => {
29
+ if (settled)
30
+ return;
31
+ settled = true;
32
+ clearTimeout(timer);
33
+ conn.destroy();
34
+ resolveResult(result);
35
+ };
36
+ const timer = setTimeout(() => settle({ kind: "timeout" }), timeoutMs);
37
+ timer.unref();
38
+ conn.on("connect", () => conn.write(`${JSON.stringify({ file })}\n`));
39
+ conn.on("data", (chunk) => {
40
+ buffer += chunk.toString("utf8");
41
+ const newline = buffer.indexOf("\n");
42
+ if (newline < 0)
43
+ return;
44
+ try {
45
+ const response = JSON.parse(buffer.slice(0, newline));
46
+ settle(response.ok === true ? { kind: "text", text: response.text ?? "" } : { kind: "error" });
47
+ }
48
+ catch {
49
+ settle({ kind: "error" });
50
+ }
51
+ });
52
+ conn.on("error", (err) => {
53
+ settle(err.code === "ECONNREFUSED" || err.code === "ENOENT" ? { kind: "refused" } : { kind: "error" });
54
+ });
55
+ });
56
+ }
57
+ function spawnDaemon(socketPath, workspace) {
58
+ const entry = daemonEntry();
59
+ if (!existsSync(entry))
60
+ return;
61
+ try {
62
+ spawn(process.execPath, [entry], {
63
+ detached: true,
64
+ stdio: "ignore",
65
+ env: { ...process.env, EAST_DIAG_SOCKET: socketPath, EAST_DIAG_CWD: workspace },
66
+ }).unref();
67
+ }
68
+ catch {
69
+ /* ignore */
70
+ }
71
+ }
72
+ /** Fire-and-forget: ensure a daemon is running for this workspace so the first
73
+ * edit doesn't pay process-spawn latency. Probes the socket and only spawns if
74
+ * nothing is listening (so a live daemon is never disrupted). */
75
+ export function warmDaemon(workspace) {
76
+ const socketPath = daemonSocket();
77
+ const conn = createConnection(socketPath);
78
+ conn.on("connect", () => conn.destroy());
79
+ conn.on("error", (err) => {
80
+ conn.destroy();
81
+ if (err.code === "ECONNREFUSED" || err.code === "ENOENT") {
82
+ if (existsSync(socketPath)) {
83
+ try {
84
+ unlinkSync(socketPath);
85
+ }
86
+ catch {
87
+ /* ignore */
88
+ }
89
+ }
90
+ spawnDaemon(socketPath, workspace);
91
+ }
92
+ });
93
+ }
94
+ /** Get the `<east-code-review>` text for `file` from the daemon (lazily
95
+ * spawning it if absent). Returns `""` when clean and `null` when the daemon
96
+ * could not be reached within `budgetMs` — callers degrade to a silent no-op. */
97
+ export async function getDiagnosticsText(workspace, file, budgetMs = 4000) {
98
+ const socketPath = daemonSocket();
99
+ const deadline = Date.now() + budgetMs;
100
+ let spawned = false;
101
+ while (Date.now() < deadline) {
102
+ const attempt = await tryRequest(socketPath, file, Math.min(1500, deadline - Date.now()));
103
+ if (attempt.kind === "text")
104
+ return attempt.text;
105
+ if (attempt.kind === "refused" && !spawned) {
106
+ // No live daemon: clear any stale socket file, then spawn one.
107
+ if (existsSync(socketPath)) {
108
+ try {
109
+ unlinkSync(socketPath);
110
+ }
111
+ catch {
112
+ /* ignore */
113
+ }
114
+ }
115
+ spawnDaemon(socketPath, workspace);
116
+ spawned = true;
117
+ }
118
+ // refused-after-spawn (still starting) or timeout (warming): wait and retry.
119
+ await new Promise((r) => setTimeout(r, 200));
120
+ }
121
+ return null;
122
+ }
123
+ //# sourceMappingURL=diagnostics-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diagnostics-client.js","sourceRoot":"","sources":["../../lib/diagnostics-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAQzC,gFAAgF;AAChF,+EAA+E;AAC/E,iFAAiF;AACjF,6EAA6E;AAC7E,6EAA6E;AAC7E,kCAAkC;AAClC,SAAS,YAAY;IACnB,MAAM,IAAI,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACjF,OAAO,IAAI,CAAC,MAAM,EAAE,EAAE,aAAa,IAAI,OAAO,CAAC,CAAC;AAClD,CAAC;AAED,+EAA+E;AAC/E,gEAAgE;AAChE,SAAS,WAAW;IAClB,OAAO,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC;AACvF,CAAC;AAED,SAAS,UAAU,CAAC,UAAkB,EAAE,IAAY,EAAE,SAAiB;IACrE,OAAO,IAAI,OAAO,CAAC,CAAC,aAAa,EAAE,EAAE;QACnC,MAAM,IAAI,GAAG,gBAAgB,CAAC,UAAU,CAAC,CAAC;QAC1C,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,IAAI,OAAO,GAAG,KAAK,CAAC;QACpB,MAAM,MAAM,GAAG,CAAC,MAAqB,EAAQ,EAAE;YAC7C,IAAI,OAAO;gBAAE,OAAO;YACpB,OAAO,GAAG,IAAI,CAAC;YACf,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,IAAI,CAAC,OAAO,EAAE,CAAC;YACf,aAAa,CAAC,MAAM,CAAC,CAAC;QACxB,CAAC,CAAC;QACF,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,CAAC,CAAC;QACvE,KAAK,CAAC,KAAK,EAAE,CAAC;QAEd,IAAI,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;QACtE,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE;YAChC,MAAM,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;YACjC,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YACrC,IAAI,OAAO,GAAG,CAAC;gBAAE,OAAO;YACxB,IAAI,CAAC;gBACH,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC,CAAoC,CAAC;gBACzF,MAAM,CAAC,QAAQ,CAAC,EAAE,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;YACjG,CAAC;YAAC,MAAM,CAAC;gBACP,MAAM,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;YAC5B,CAAC;QACH,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAA0B,EAAE,EAAE;YAC9C,MAAM,CAAC,GAAG,CAAC,IAAI,KAAK,cAAc,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;QACzG,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,WAAW,CAAC,UAAkB,EAAE,SAAiB;IACxD,MAAM,KAAK,GAAG,WAAW,EAAE,CAAC;IAC5B,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC;QAAE,OAAO;IAC/B,IAAI,CAAC;QACH,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,EAAE;YAC/B,QAAQ,EAAE,IAAI;YACd,KAAK,EAAE,QAAQ;YACf,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,gBAAgB,EAAE,UAAU,EAAE,aAAa,EAAE,SAAS,EAAE;SAChF,CAAC,CAAC,KAAK,EAAE,CAAC;IACb,CAAC;IAAC,MAAM,CAAC;QACP,YAAY;IACd,CAAC;AACH,CAAC;AAED;;iEAEiE;AACjE,MAAM,UAAU,UAAU,CAAC,SAAiB;IAC1C,MAAM,UAAU,GAAG,YAAY,EAAE,CAAC;IAClC,MAAM,IAAI,GAAG,gBAAgB,CAAC,UAAU,CAAC,CAAC;IAC1C,IAAI,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;IACzC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAA0B,EAAE,EAAE;QAC9C,IAAI,CAAC,OAAO,EAAE,CAAC;QACf,IAAI,GAAG,CAAC,IAAI,KAAK,cAAc,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACzD,IAAI,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;gBAC3B,IAAI,CAAC;oBACH,UAAU,CAAC,UAAU,CAAC,CAAC;gBACzB,CAAC;gBAAC,MAAM,CAAC;oBACP,YAAY;gBACd,CAAC;YACH,CAAC;YACD,WAAW,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;QACrC,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;iFAEiF;AACjF,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,SAAiB,EACjB,IAAY,EACZ,QAAQ,GAAG,IAAI;IAEf,MAAM,UAAU,GAAG,YAAY,EAAE,CAAC;IAClC,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,CAAC;IACvC,IAAI,OAAO,GAAG,KAAK,CAAC;IAEpB,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,EAAE,CAAC;QAC7B,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC,UAAU,EAAE,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QAC1F,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM;YAAE,OAAO,OAAO,CAAC,IAAI,CAAC;QACjD,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS,IAAI,CAAC,OAAO,EAAE,CAAC;YAC3C,+DAA+D;YAC/D,IAAI,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;gBAC3B,IAAI,CAAC;oBACH,UAAU,CAAC,UAAU,CAAC,CAAC;gBACzB,CAAC;gBAAC,MAAM,CAAC;oBACP,YAAY;gBACd,CAAC;YACH,CAAC;YACD,WAAW,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;YACnC,OAAO,GAAG,IAAI,CAAC;QACjB,CAAC;QACD,6EAA6E;QAC7E,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;IAC/C,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,3 @@
1
+ /** The path of East's `index.json` in the installed `@elaraai/east-plugin`. */
2
+ export declare const EAST_INDEX_PATH: string;
3
+ //# sourceMappingURL=east-index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"east-index.d.ts","sourceRoot":"","sources":["../../lib/east-index.ts"],"names":[],"mappings":"AAQA,+EAA+E;AAC/E,eAAO,MAAM,eAAe,EAAE,MAAoE,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { fileURLToPath } from "node:url";
2
+ // East's own example index as the published package ships it: `index.json` at
3
+ // the package root, two directories above this module's `dist/lib/`. A plugin
4
+ // that builds on East's serves it beside its own corpus (`loadIndexes`), or
5
+ // copies it into its bundle at build time, as East's plugins do — a bundled
6
+ // module no longer sits where this path is reckoned from.
7
+ /** The path of East's `index.json` in the installed `@elaraai/east-plugin`. */
8
+ export const EAST_INDEX_PATH = fileURLToPath(new URL("../../index.json", import.meta.url));
9
+ //# sourceMappingURL=east-index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"east-index.js","sourceRoot":"","sources":["../../lib/east-index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,8EAA8E;AAC9E,8EAA8E;AAC9E,4EAA4E;AAC5E,4EAA4E;AAC5E,0DAA0D;AAE1D,+EAA+E;AAC/E,MAAM,CAAC,MAAM,eAAe,GAAW,aAAa,CAAC,IAAI,GAAG,CAAC,kBAAkB,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC"}
@@ -0,0 +1,49 @@
1
+ /** Which language(s) an East project is authored in. A project may be both. */
2
+ export type EastLanguage = "typescript" | "python";
3
+ interface PackageJson {
4
+ dependencies?: Record<string, string>;
5
+ devDependencies?: Record<string, string>;
6
+ }
7
+ export declare function findPackageJson(startDir: string): Promise<PackageJson | null>;
8
+ /**
9
+ * The `pyproject.toml` that governs `startDir`, as text: the nearest one at
10
+ * or above it that depends on an east-py distribution, else the nearest one
11
+ * at all. A uv workspace member has its own pyproject — that is what makes it
12
+ * a member — and it usually says nothing about East, so stopping at the first
13
+ * file found would call every member a non-East project while the root
14
+ * declares otherwise; the walk continues past a pyproject that does not
15
+ * mention east-py (the same rule `east.diagnostics.config` applies).
16
+ *
17
+ * `uv.lock` is deliberately NOT read. This runs on a hot path — every session
18
+ * start, every subagent start, every gated write, and every reviewed file — and
19
+ * a lockfile is large (~1 MB in this repo), so reading one per call to
20
+ * substring-match it was real work repeated constantly. It was also wrong:
21
+ * a lockfile lists TRANSITIVE resolutions, so a TypeScript-only project that
22
+ * merely resolved an East distribution somewhere in its graph was reported as
23
+ * a python East project and handed the python cheat-sheet. A project that
24
+ * authors East in python declares it in a `pyproject.toml` of its own.
25
+ */
26
+ export declare function findPyProject(startDir: string): Promise<string | null>;
27
+ export declare function detectEastSkills(pkg: PackageJson | null): string[];
28
+ /** The east-py skills a pyproject.toml text depends on. */
29
+ export declare function detectPythonSkills(pyproject: string | null): string[];
30
+ export interface EastProjectInfo {
31
+ isEast: boolean;
32
+ skills: string[];
33
+ /** The language(s) detected — drives which rule cheat-sheet an agent is given. */
34
+ languages: EastLanguage[];
35
+ pkg: PackageJson | null;
36
+ }
37
+ /**
38
+ * What kind of East project `cwd` sits in.
39
+ *
40
+ * Both ecosystems count. A project whose East dependency is declared only in
41
+ * `pyproject.toml` — no package.json anywhere — is an East project, and used
42
+ * to report `isEast: false`, so the session and subagent hooks injected
43
+ * nothing at all for it: no skill list, no rule cheat-sheet. (The diagnose and
44
+ * pre-write hooks never consulted this, gating on an `import east` instead,
45
+ * which is why diagnostics worked there while orientation did not.)
46
+ */
47
+ export declare function getEastProjectInfo(cwd: string): Promise<EastProjectInfo>;
48
+ export {};
49
+ //# sourceMappingURL=east-project.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"east-project.d.ts","sourceRoot":"","sources":["../../lib/east-project.ts"],"names":[],"mappings":"AAGA,+EAA+E;AAC/E,MAAM,MAAM,YAAY,GAAG,YAAY,GAAG,QAAQ,CAAC;AAsBnD,UAAU,WAAW;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC1C;AAED,wBAAsB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAYnF;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAe5E;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,WAAW,GAAG,IAAI,GAAG,MAAM,EAAE,CAalE;AAED,2DAA2D;AAC3D,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,EAAE,CAOrE;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,kFAAkF;IAClF,SAAS,EAAE,YAAY,EAAE,CAAC;IAC1B,GAAG,EAAE,WAAW,GAAG,IAAI,CAAC;CACzB;AAED;;;;;;;;;GASG;AACH,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAS9E"}