@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.
- package/LICENSE.md +682 -0
- package/README.md +104 -2
- package/dist/daemon/east-py-lsp.d.ts +2 -0
- package/dist/daemon/east-py-lsp.d.ts.map +1 -0
- package/dist/daemon/east-py-lsp.js +9 -0
- package/dist/daemon/east-py-lsp.js.map +1 -0
- package/dist/daemon/lsp.d.ts +2 -0
- package/dist/daemon/lsp.d.ts.map +1 -0
- package/dist/daemon/lsp.js +7 -0
- package/dist/daemon/lsp.js.map +1 -0
- package/dist/daemon/server.d.ts +2 -0
- package/dist/daemon/server.d.ts.map +1 -0
- package/dist/daemon/server.js +71 -0
- package/dist/daemon/server.js.map +1 -0
- package/dist/hooks/diagnose-bash.d.ts +2 -0
- package/dist/hooks/diagnose-bash.d.ts.map +1 -0
- package/dist/hooks/diagnose-bash.js +28 -0
- package/dist/hooks/diagnose-bash.js.map +1 -0
- package/dist/hooks/diagnose.d.ts +2 -0
- package/dist/hooks/diagnose.d.ts.map +1 -0
- package/dist/hooks/diagnose.js +33 -0
- package/dist/hooks/diagnose.js.map +1 -0
- package/dist/hooks/pre-read.d.ts +2 -0
- package/dist/hooks/pre-read.d.ts.map +1 -0
- package/dist/hooks/pre-read.js +11 -0
- package/dist/hooks/pre-read.js.map +1 -0
- package/dist/hooks/pre-write.d.ts +2 -0
- package/dist/hooks/pre-write.d.ts.map +1 -0
- package/dist/hooks/pre-write.js +11 -0
- package/dist/hooks/pre-write.js.map +1 -0
- package/dist/hooks/session-start.d.ts +2 -0
- package/dist/hooks/session-start.d.ts.map +1 -0
- package/dist/hooks/session-start.js +34 -0
- package/dist/hooks/session-start.js.map +1 -0
- package/dist/hooks/subagent-start.d.ts +2 -0
- package/dist/hooks/subagent-start.d.ts.map +1 -0
- package/dist/hooks/subagent-start.js +29 -0
- package/dist/hooks/subagent-start.js.map +1 -0
- package/dist/lib/bash-writes.d.ts +11 -0
- package/dist/lib/bash-writes.d.ts.map +1 -0
- package/dist/lib/bash-writes.js +74 -0
- package/dist/lib/bash-writes.js.map +1 -0
- package/dist/lib/codex-hook.d.ts +64 -0
- package/dist/lib/codex-hook.d.ts.map +1 -0
- package/dist/lib/codex-hook.js +94 -0
- package/dist/lib/codex-hook.js.map +1 -0
- package/dist/lib/codex-skills.d.ts +38 -0
- package/dist/lib/codex-skills.d.ts.map +1 -0
- package/dist/lib/codex-skills.js +80 -0
- package/dist/lib/codex-skills.js.map +1 -0
- package/dist/lib/codex-tools.d.ts +11 -0
- package/dist/lib/codex-tools.d.ts.map +1 -0
- package/dist/lib/codex-tools.js +41 -0
- package/dist/lib/codex-tools.js.map +1 -0
- package/dist/lib/diagnostics-client.d.ts +9 -0
- package/dist/lib/diagnostics-client.d.ts.map +1 -0
- package/dist/lib/diagnostics-client.js +123 -0
- package/dist/lib/diagnostics-client.js.map +1 -0
- package/dist/lib/east-index.d.ts +3 -0
- package/dist/lib/east-index.d.ts.map +1 -0
- package/dist/lib/east-index.js +9 -0
- package/dist/lib/east-index.js.map +1 -0
- package/dist/lib/east-project.d.ts +49 -0
- package/dist/lib/east-project.d.ts.map +1 -0
- package/dist/lib/east-project.js +121 -0
- package/dist/lib/east-project.js.map +1 -0
- package/dist/lib/east-py-lint.d.ts +7 -0
- package/dist/lib/east-py-lint.d.ts.map +1 -0
- package/dist/lib/east-py-lint.js +22 -0
- package/dist/lib/east-py-lint.js.map +1 -0
- package/dist/lib/east-rules-context.d.ts +7 -0
- package/dist/lib/east-rules-context.d.ts.map +1 -0
- package/dist/lib/east-rules-context.js +91 -0
- package/dist/lib/east-rules-context.js.map +1 -0
- package/dist/lib/hook-io.d.ts +30 -0
- package/dist/lib/hook-io.d.ts.map +1 -0
- package/dist/lib/hook-io.js +29 -0
- package/dist/lib/hook-io.js.map +1 -0
- package/dist/lib/host.d.ts +3 -0
- package/dist/lib/host.d.ts.map +1 -0
- package/dist/lib/host.js +9 -0
- package/dist/lib/host.js.map +1 -0
- package/dist/lib/lsp-client.d.ts +34 -0
- package/dist/lib/lsp-client.d.ts.map +1 -0
- package/dist/lib/lsp-client.js +200 -0
- package/dist/lib/lsp-client.js.map +1 -0
- package/dist/lib/plugin-status.d.ts +9 -0
- package/dist/lib/plugin-status.d.ts.map +1 -0
- package/dist/lib/plugin-status.js +164 -0
- package/dist/lib/plugin-status.js.map +1 -0
- package/dist/lib/review.d.ts +16 -0
- package/dist/lib/review.d.ts.map +1 -0
- package/dist/lib/review.js +74 -0
- package/dist/lib/review.js.map +1 -0
- package/dist/lib/search-guidance.d.ts +44 -0
- package/dist/lib/search-guidance.d.ts.map +1 -0
- package/dist/lib/search-guidance.js +73 -0
- package/dist/lib/search-guidance.js.map +1 -0
- package/dist/lib/search-hooks.d.ts +75 -0
- package/dist/lib/search-hooks.d.ts.map +1 -0
- package/dist/lib/search-hooks.js +117 -0
- package/dist/lib/search-hooks.js.map +1 -0
- package/dist/lib/search.d.ts +121 -0
- package/dist/lib/search.d.ts.map +1 -0
- package/dist/lib/search.js +181 -0
- package/dist/lib/search.js.map +1 -0
- package/dist/lib/transcript.d.ts +29 -0
- package/dist/lib/transcript.d.ts.map +1 -0
- package/dist/lib/transcript.js +109 -0
- package/dist/lib/transcript.js.map +1 -0
- package/dist/mcp/example-tools.d.ts +33 -0
- package/dist/mcp/example-tools.d.ts.map +1 -0
- package/dist/mcp/example-tools.js +97 -0
- package/dist/mcp/example-tools.js.map +1 -0
- package/dist/mcp/server.d.ts +2 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +52 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/scripts/examples-file.d.ts +38 -0
- package/dist/scripts/examples-file.d.ts.map +1 -0
- package/dist/scripts/examples-file.js +224 -0
- package/dist/scripts/examples-file.js.map +1 -0
- package/dist/scripts/generate-index.d.ts +127 -0
- package/dist/scripts/generate-index.d.ts.map +1 -0
- package/dist/scripts/generate-index.js +315 -0
- package/dist/scripts/generate-index.js.map +1 -0
- package/dist/status/report.d.ts +2 -0
- package/dist/status/report.d.ts.map +1 -0
- package/dist/status/report.js +9 -0
- package/dist/status/report.js.map +1 -0
- package/index.json +44926 -0
- package/package.json +65 -3
- 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":"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"}
|
|
@@ -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"}
|