@inerrata-corporation/errata 2.0.19 → 2.0.20-dev.3682

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.
@@ -0,0 +1,63 @@
1
+ import { spawn } from 'node:child_process'
2
+ import { openSync, closeSync } from 'node:fs'
3
+ import { mkdir, readFile } from 'node:fs/promises'
4
+ import { join, resolve } from 'node:path'
5
+ import { fileURLToPath } from 'node:url'
6
+ import { parseArgs } from 'node:util'
7
+ import { setTimeout } from 'node:timers/promises'
8
+
9
+ const { values } = parseArgs({ options: { root: { type: 'string' }, session: { type: 'string' } } })
10
+ const root = resolve(values.root ?? process.cwd())
11
+ const session = values.session ?? process.env.CODEX_THREAD_ID
12
+ if (session && !/^[\w-]{1,100}$/.test(session)) throw new Error('Invalid task id')
13
+ const output = join(root, '.errata', 'context-preview')
14
+ const metadata = join(output, (session ?? 'workspace') + '.json')
15
+ async function running() {
16
+ try {
17
+ const info = JSON.parse(await readFile(metadata, 'utf8'))
18
+ const url = new URL(info.url)
19
+ if (
20
+ url.protocol !== 'http:' ||
21
+ url.hostname !== '127.0.0.1' ||
22
+ info.root !== root ||
23
+ info.sessionId !== (session ?? null)
24
+ )
25
+ return null
26
+ const response = await fetch(new URL('health', url), { signal: AbortSignal.timeout(700) })
27
+ const health = await response.json()
28
+ return health.ok &&
29
+ health.root === root &&
30
+ health.sessionId === (session ?? null) &&
31
+ health.pid === info.pid
32
+ ? info
33
+ : null
34
+ } catch {
35
+ return null
36
+ }
37
+ }
38
+ let info = await running()
39
+ if (!info) {
40
+ await mkdir(output, { recursive: true })
41
+ const log = openSync(join(output, (session ?? 'workspace') + '.log'), 'a')
42
+ const args = [fileURLToPath(new URL('dist/server.mjs', import.meta.url)), '--root', root]
43
+ if (session) args.push('--session', session)
44
+ let error
45
+ const child = spawn(process.execPath, args, {
46
+ detached: true,
47
+ windowsHide: true,
48
+ stdio: ['ignore', log, log],
49
+ cwd: root,
50
+ })
51
+ child.on('error', (e) => {
52
+ error = e
53
+ })
54
+ child.unref()
55
+ closeSync(log)
56
+ for (let i = 0; i < 50 && !info; i++) {
57
+ if (error) throw error
58
+ await setTimeout(200)
59
+ info = await running()
60
+ }
61
+ }
62
+ if (!info) throw new Error('Preview did not start. See the task log in ' + output)
63
+ console.log(JSON.stringify(info))
@@ -0,0 +1,37 @@
1
+ ---
2
+ name: context-graph
3
+ description: Open a minimal live 3D graph of the Errata priors loaded into the current Codex task and its recent bursts. Use when the user asks to see context, priors, or graph activity in a side panel.
4
+ ---
5
+
6
+ # Errata context graph
7
+
8
+ Use the plugin's `open_context_graph` MCP tool. Supply the absolute current
9
+ workspace as `workspace` and the current `CODEX_THREAD_ID` as `sessionId`.
10
+ Read that environment variable through the shell if it is not already available.
11
+ Do not guess the task id or select whichever transcript was modified most recently.
12
+
13
+ Once the user has a context panel open for this task, keep that panel as the
14
+ visual surface. Do not call `open_context_graph` again for normal refreshes or
15
+ post additional graph cards or screenshots into chat. Reopen only when the user
16
+ asks or the current panel cannot recover. The panel follows updates itself.
17
+
18
+ This tool declares the native conversation-panel entrypoint. The UI reads its own
19
+ updates through `read_context_graph`; no automation, repeated model calls, or
20
+ additional graph bursts are needed to keep it live. Do not print the entire graph
21
+ payload into the conversation. Do not add a dashboard, header, counts, or node list.
22
+
23
+ The graph follows the latest task-specific Errata injection and uses the workspace
24
+ snapshot only while task context is unavailable. It turns toward real successful
25
+ burst results. New bursts animate a seed pulse, recorded traversal hops, and a
26
+ settle on the results. This replays recorded paths after completion; do not
27
+ describe it as every internal search step. Dragging pauses camera following;
28
+ double-click, Home, or Escape resumes. Hover or select a node for its label.
29
+ Click a burst in the tiny log to replay it. Reduced motion shows results directly.
30
+
31
+ If the host cannot render MCP Apps, use the bundled fallback only as needed:
32
+ run `node <plugin-root>/launch.mjs --root <workspace> --session <task-id>` and open
33
+ the returned local URL in the right-hand browser panel. Explain that it is a browser
34
+ fallback. Do not claim the native panel was opened unless the host actually renders it.
35
+
36
+ All graph and transcript reads are local and read-only. Only rendered prior lines
37
+ and completed burst results are sent to the panel, never the full conversation.