@textjs/app 0.0.0-stage → 1.0.2
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/README.md +34 -2
- package/bin/text.js +29 -0
- package/bin/text.ts +13 -0
- package/dist/.tsbuildinfo +1 -0
- package/dist/cli/build.d.ts +39 -0
- package/dist/cli/build.d.ts.map +1 -0
- package/dist/cli/build.js +157 -0
- package/dist/cli/build.js.map +1 -0
- package/dist/cli/config.d.ts +22 -0
- package/dist/cli/config.d.ts.map +1 -0
- package/dist/cli/config.js +73 -0
- package/dist/cli/config.js.map +1 -0
- package/dist/cli/dev.d.ts +12 -0
- package/dist/cli/dev.d.ts.map +1 -0
- package/dist/cli/dev.js +49 -0
- package/dist/cli/dev.js.map +1 -0
- package/dist/cli/index.d.ts +26 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +192 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/run.d.ts +31 -0
- package/dist/cli/run.d.ts.map +1 -0
- package/dist/cli/run.js +111 -0
- package/dist/cli/run.js.map +1 -0
- package/dist/cli/start.d.ts +14 -0
- package/dist/cli/start.d.ts.map +1 -0
- package/dist/cli/start.js +183 -0
- package/dist/cli/start.js.map +1 -0
- package/dist/cli/ui.d.ts +35 -0
- package/dist/cli/ui.d.ts.map +1 -0
- package/dist/cli/ui.js +73 -0
- package/dist/cli/ui.js.map +1 -0
- package/dist/client.d.ts +34 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +93 -0
- package/dist/client.js.map +1 -0
- package/dist/config.d.ts +143 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +28 -0
- package/dist/config.js.map +1 -0
- package/dist/context.d.ts +44 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +26 -0
- package/dist/context.js.map +1 -0
- package/dist/dev-errors.d.ts +68 -0
- package/dist/dev-errors.d.ts.map +1 -0
- package/dist/dev-errors.js +121 -0
- package/dist/dev-errors.js.map +1 -0
- package/dist/devtools.d.ts +64 -0
- package/dist/devtools.d.ts.map +1 -0
- package/dist/devtools.js +186 -0
- package/dist/devtools.js.map +1 -0
- package/dist/frame-mirror.d.ts +19 -0
- package/dist/frame-mirror.d.ts.map +1 -0
- package/dist/frame-mirror.js +141 -0
- package/dist/frame-mirror.js.map +1 -0
- package/dist/frame-protocol.d.ts +175 -0
- package/dist/frame-protocol.d.ts.map +1 -0
- package/dist/frame-protocol.js +369 -0
- package/dist/frame-protocol.js.map +1 -0
- package/dist/history.d.ts +54 -0
- package/dist/history.d.ts.map +1 -0
- package/dist/history.js +152 -0
- package/dist/history.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/link.d.ts +32 -0
- package/dist/link.d.ts.map +1 -0
- package/dist/link.js +54 -0
- package/dist/link.js.map +1 -0
- package/dist/live-player.d.ts +83 -0
- package/dist/live-player.d.ts.map +1 -0
- package/dist/live-player.js +413 -0
- package/dist/live-player.js.map +1 -0
- package/dist/live-protocol.d.ts +132 -0
- package/dist/live-protocol.d.ts.map +1 -0
- package/dist/live-protocol.js +278 -0
- package/dist/live-protocol.js.map +1 -0
- package/dist/live-stub.d.ts +10 -0
- package/dist/live-stub.d.ts.map +1 -0
- package/dist/live-stub.js +32 -0
- package/dist/live-stub.js.map +1 -0
- package/dist/mcp/cli.d.ts +22 -0
- package/dist/mcp/cli.d.ts.map +1 -0
- package/dist/mcp/cli.js +177 -0
- package/dist/mcp/cli.js.map +1 -0
- package/dist/mcp/frame.d.ts +58 -0
- package/dist/mcp/frame.d.ts.map +1 -0
- package/dist/mcp/frame.js +169 -0
- package/dist/mcp/frame.js.map +1 -0
- package/dist/mcp/index.d.ts +15 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/mcp/index.js +15 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/inspect.d.ts +95 -0
- package/dist/mcp/inspect.d.ts.map +1 -0
- package/dist/mcp/inspect.js +386 -0
- package/dist/mcp/inspect.js.map +1 -0
- package/dist/mcp/keys.d.ts +20 -0
- package/dist/mcp/keys.d.ts.map +1 -0
- package/dist/mcp/keys.js +87 -0
- package/dist/mcp/keys.js.map +1 -0
- package/dist/mcp/logs.d.ts +63 -0
- package/dist/mcp/logs.d.ts.map +1 -0
- package/dist/mcp/logs.js +217 -0
- package/dist/mcp/logs.js.map +1 -0
- package/dist/mcp/server.d.ts +64 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +485 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/session.d.ts +230 -0
- package/dist/mcp/session.d.ts.map +1 -0
- package/dist/mcp/session.js +742 -0
- package/dist/mcp/session.js.map +1 -0
- package/dist/navigation-errors.d.ts +28 -0
- package/dist/navigation-errors.d.ts.map +1 -0
- package/dist/navigation-errors.js +43 -0
- package/dist/navigation-errors.js.map +1 -0
- package/dist/navigation.d.ts +21 -0
- package/dist/navigation.d.ts.map +1 -0
- package/dist/navigation.js +33 -0
- package/dist/navigation.js.map +1 -0
- package/dist/router.d.ts +76 -0
- package/dist/router.d.ts.map +1 -0
- package/dist/router.js +296 -0
- package/dist/router.js.map +1 -0
- package/dist/routing.d.ts +101 -0
- package/dist/routing.d.ts.map +1 -0
- package/dist/routing.js +286 -0
- package/dist/routing.js.map +1 -0
- package/dist/server/adapters/build-step.d.ts +34 -0
- package/dist/server/adapters/build-step.d.ts.map +1 -0
- package/dist/server/adapters/build-step.js +112 -0
- package/dist/server/adapters/build-step.js.map +1 -0
- package/dist/server/adapters/bun.d.ts +8 -0
- package/dist/server/adapters/bun.d.ts.map +1 -0
- package/dist/server/adapters/bun.js +89 -0
- package/dist/server/adapters/bun.js.map +1 -0
- package/dist/server/adapters/bundle.d.ts +21 -0
- package/dist/server/adapters/bundle.d.ts.map +1 -0
- package/dist/server/adapters/bundle.js +86 -0
- package/dist/server/adapters/bundle.js.map +1 -0
- package/dist/server/adapters/cloudflare.d.ts +29 -0
- package/dist/server/adapters/cloudflare.d.ts.map +1 -0
- package/dist/server/adapters/cloudflare.js +105 -0
- package/dist/server/adapters/cloudflare.js.map +1 -0
- package/dist/server/adapters/index.d.ts +10 -0
- package/dist/server/adapters/index.d.ts.map +1 -0
- package/dist/server/adapters/index.js +24 -0
- package/dist/server/adapters/index.js.map +1 -0
- package/dist/server/adapters/runtime-node.d.ts +16 -0
- package/dist/server/adapters/runtime-node.d.ts.map +1 -0
- package/dist/server/adapters/runtime-node.js +29 -0
- package/dist/server/adapters/runtime-node.js.map +1 -0
- package/dist/server/adapters/runtime.d.ts +42 -0
- package/dist/server/adapters/runtime.d.ts.map +1 -0
- package/dist/server/adapters/runtime.js +115 -0
- package/dist/server/adapters/runtime.js.map +1 -0
- package/dist/server/adapters/shared.d.ts +66 -0
- package/dist/server/adapters/shared.d.ts.map +1 -0
- package/dist/server/adapters/shared.js +124 -0
- package/dist/server/adapters/shared.js.map +1 -0
- package/dist/server/adapters/static.d.ts +9 -0
- package/dist/server/adapters/static.d.ts.map +1 -0
- package/dist/server/adapters/static.js +70 -0
- package/dist/server/adapters/static.js.map +1 -0
- package/dist/server/adapters/vercel.d.ts +43 -0
- package/dist/server/adapters/vercel.d.ts.map +1 -0
- package/dist/server/adapters/vercel.js +119 -0
- package/dist/server/adapters/vercel.js.map +1 -0
- package/dist/server/bun-jsx.d.ts +18 -0
- package/dist/server/bun-jsx.d.ts.map +1 -0
- package/dist/server/bun-jsx.js +56 -0
- package/dist/server/bun-jsx.js.map +1 -0
- package/dist/server/cache-route.d.ts +38 -0
- package/dist/server/cache-route.d.ts.map +1 -0
- package/dist/server/cache-route.js +109 -0
- package/dist/server/cache-route.js.map +1 -0
- package/dist/server/cache.d.ts +131 -0
- package/dist/server/cache.d.ts.map +1 -0
- package/dist/server/cache.js +409 -0
- package/dist/server/cache.js.map +1 -0
- package/dist/server/frames.d.ts +45 -0
- package/dist/server/frames.d.ts.map +1 -0
- package/dist/server/frames.js +294 -0
- package/dist/server/frames.js.map +1 -0
- package/dist/server/http.d.ts +80 -0
- package/dist/server/http.d.ts.map +1 -0
- package/dist/server/http.js +453 -0
- package/dist/server/http.js.map +1 -0
- package/dist/server/jsx-dev-runtime.d.ts +5 -0
- package/dist/server/jsx-dev-runtime.d.ts.map +1 -0
- package/dist/server/jsx-dev-runtime.js +6 -0
- package/dist/server/jsx-dev-runtime.js.map +1 -0
- package/dist/server/jsx-runtime.d.ts +10 -0
- package/dist/server/jsx-runtime.d.ts.map +1 -0
- package/dist/server/jsx-runtime.js +11 -0
- package/dist/server/jsx-runtime.js.map +1 -0
- package/dist/server/live-app.d.ts +87 -0
- package/dist/server/live-app.d.ts.map +1 -0
- package/dist/server/live-app.js +307 -0
- package/dist/server/live-app.js.map +1 -0
- package/dist/server/live-build.d.ts +70 -0
- package/dist/server/live-build.d.ts.map +1 -0
- package/dist/server/live-build.js +222 -0
- package/dist/server/live-build.js.map +1 -0
- package/dist/server/live-dev.d.ts +62 -0
- package/dist/server/live-dev.d.ts.map +1 -0
- package/dist/server/live-dev.js +313 -0
- package/dist/server/live-dev.js.map +1 -0
- package/dist/server/live-manifest.d.ts +23 -0
- package/dist/server/live-manifest.d.ts.map +1 -0
- package/dist/server/live-manifest.js +7 -0
- package/dist/server/live-manifest.js.map +1 -0
- package/dist/server/live-prod.d.ts +30 -0
- package/dist/server/live-prod.d.ts.map +1 -0
- package/dist/server/live-prod.js +97 -0
- package/dist/server/live-prod.js.map +1 -0
- package/dist/server/live-routes.d.ts +72 -0
- package/dist/server/live-routes.d.ts.map +1 -0
- package/dist/server/live-routes.js +274 -0
- package/dist/server/live-routes.js.map +1 -0
- package/dist/server/live-web.d.ts +16 -0
- package/dist/server/live-web.d.ts.map +1 -0
- package/dist/server/live-web.js +159 -0
- package/dist/server/live-web.js.map +1 -0
- package/dist/server/live.d.ts +138 -0
- package/dist/server/live.d.ts.map +1 -0
- package/dist/server/live.js +542 -0
- package/dist/server/live.js.map +1 -0
- package/dist/server/middleware-node.d.ts +48 -0
- package/dist/server/middleware-node.d.ts.map +1 -0
- package/dist/server/middleware-node.js +167 -0
- package/dist/server/middleware-node.js.map +1 -0
- package/dist/server/middleware-runtime.d.ts +97 -0
- package/dist/server/middleware-runtime.d.ts.map +1 -0
- package/dist/server/middleware-runtime.js +447 -0
- package/dist/server/middleware-runtime.js.map +1 -0
- package/dist/server/middleware.d.ts +145 -0
- package/dist/server/middleware.d.ts.map +1 -0
- package/dist/server/middleware.js +365 -0
- package/dist/server/middleware.js.map +1 -0
- package/dist/server/ppr.d.ts +22 -0
- package/dist/server/ppr.d.ts.map +1 -0
- package/dist/server/ppr.js +58 -0
- package/dist/server/ppr.js.map +1 -0
- package/dist/server/scan.d.ts +48 -0
- package/dist/server/scan.d.ts.map +1 -0
- package/dist/server/scan.js +161 -0
- package/dist/server/scan.js.map +1 -0
- package/dist/server/server-components.d.ts +65 -0
- package/dist/server/server-components.d.ts.map +1 -0
- package/dist/server/server-components.js +215 -0
- package/dist/server/server-components.js.map +1 -0
- package/dist/terminal.d.ts +5 -0
- package/dist/terminal.d.ts.map +1 -0
- package/dist/terminal.js +5 -0
- package/dist/terminal.js.map +1 -0
- package/dist/testing.d.ts +5 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +5 -0
- package/dist/testing.js.map +1 -0
- package/dist/vite-plugin.d.ts +51 -0
- package/dist/vite-plugin.d.ts.map +1 -0
- package/dist/vite-plugin.js +403 -0
- package/dist/vite-plugin.js.map +1 -0
- package/package.json +130 -4
- package/src/cli/build.ts +182 -0
- package/src/cli/config.ts +72 -0
- package/src/cli/dev.ts +54 -0
- package/src/cli/index.ts +185 -0
- package/src/cli/run.ts +124 -0
- package/src/cli/start.ts +194 -0
- package/src/cli/ui.ts +93 -0
- package/src/client.tsx +122 -0
- package/src/config.ts +155 -0
- package/src/context.ts +69 -0
- package/src/dev-errors.ts +167 -0
- package/src/devtools.tsx +419 -0
- package/src/frame-mirror.ts +145 -0
- package/src/frame-protocol.ts +435 -0
- package/src/history.ts +201 -0
- package/src/index.ts +9 -0
- package/src/link.tsx +108 -0
- package/src/live-player.ts +449 -0
- package/src/live-protocol.ts +317 -0
- package/src/live-stub.tsx +32 -0
- package/src/mcp/cli.ts +188 -0
- package/src/mcp/frame.ts +224 -0
- package/src/mcp/index.ts +15 -0
- package/src/mcp/inspect.ts +445 -0
- package/src/mcp/keys.ts +86 -0
- package/src/mcp/logs.ts +225 -0
- package/src/mcp/server.ts +595 -0
- package/src/mcp/session.ts +821 -0
- package/src/navigation-errors.ts +60 -0
- package/src/navigation.ts +44 -0
- package/src/router.tsx +497 -0
- package/src/routing.ts +344 -0
- package/src/server/adapters/build-step.ts +135 -0
- package/src/server/adapters/bun.ts +92 -0
- package/src/server/adapters/bundle.ts +97 -0
- package/src/server/adapters/cloudflare.ts +111 -0
- package/src/server/adapters/index.ts +29 -0
- package/src/server/adapters/runtime-node.ts +34 -0
- package/src/server/adapters/runtime.ts +145 -0
- package/src/server/adapters/shared.ts +159 -0
- package/src/server/adapters/static.ts +68 -0
- package/src/server/adapters/vercel.ts +149 -0
- package/src/server/bun-jsx.ts +65 -0
- package/src/server/cache-route.ts +139 -0
- package/src/server/cache.ts +498 -0
- package/src/server/frames.ts +326 -0
- package/src/server/http.ts +467 -0
- package/src/server/jsx-dev-runtime.ts +9 -0
- package/src/server/jsx-runtime.ts +13 -0
- package/src/server/live-app.tsx +374 -0
- package/src/server/live-build.ts +258 -0
- package/src/server/live-dev.ts +357 -0
- package/src/server/live-manifest.ts +25 -0
- package/src/server/live-prod.ts +120 -0
- package/src/server/live-routes.ts +298 -0
- package/src/server/live-web.ts +170 -0
- package/src/server/live.ts +551 -0
- package/src/server/middleware-node.ts +168 -0
- package/src/server/middleware-runtime.ts +478 -0
- package/src/server/middleware.ts +451 -0
- package/src/server/ppr.ts +62 -0
- package/src/server/scan.ts +190 -0
- package/src/server/server-components.ts +224 -0
- package/src/terminal.ts +5 -0
- package/src/testing.ts +5 -0
- package/src/vite-plugin.ts +413 -0
package/dist/mcp/cli.js
ADDED
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `text mcp [dir]` — serve a headless Text.js app to coding agents over MCP
|
|
3
|
+
* (stdio). stdout carries JSON-RPC only: app `console.*` output and stray
|
|
4
|
+
* `process.stdout.write` calls are captured into the `logs` tool instead.
|
|
5
|
+
*/
|
|
6
|
+
import { resolve } from "node:path";
|
|
7
|
+
import { txMessage } from "@textjs/core";
|
|
8
|
+
import { captureConsole, LogBuffer } from "./logs.js";
|
|
9
|
+
export const MCP_HELP = `Usage: text mcp [dir] [options]
|
|
10
|
+
|
|
11
|
+
Serve the app in [dir] to coding agents over the Model Context Protocol (stdio).
|
|
12
|
+
The app runs headless, in-process: same routes, layouts and route handlers.
|
|
13
|
+
|
|
14
|
+
Options:
|
|
15
|
+
--path <pathname> Initial route (default /)
|
|
16
|
+
--cols <n> Grid width (default: text.config.ts viewport, else 100)
|
|
17
|
+
--rows <n> Grid height (default: text.config.ts viewport, else 32)
|
|
18
|
+
--theme <name> Theme preset
|
|
19
|
+
--no-config Ignore text.config.ts
|
|
20
|
+
--verbose Mirror captured logs to stderr
|
|
21
|
+
-h, --help Show this help
|
|
22
|
+
|
|
23
|
+
Tools: list_routes navigate read_frame press type paste scroll resize
|
|
24
|
+
inspect_tree find wait_for logs fetch reload
|
|
25
|
+
`;
|
|
26
|
+
export function parseMcpArgs(argv) {
|
|
27
|
+
const out = { dir: ".", skipConfig: false, verbose: false, help: false, unknown: [] };
|
|
28
|
+
const positional = [];
|
|
29
|
+
const num = (v) => {
|
|
30
|
+
const n = Number(v);
|
|
31
|
+
return v !== undefined && Number.isFinite(n) && n > 0 ? Math.floor(n) : undefined;
|
|
32
|
+
};
|
|
33
|
+
for (let i = 0; i < argv.length; i++) {
|
|
34
|
+
const a = argv[i];
|
|
35
|
+
const eq = a.indexOf("=");
|
|
36
|
+
const flag = a.startsWith("--") && eq > 0 ? a.slice(0, eq) : a;
|
|
37
|
+
const inline = a.startsWith("--") && eq > 0 ? a.slice(eq + 1) : undefined;
|
|
38
|
+
const value = () => inline ?? argv[++i];
|
|
39
|
+
if (flag === "-h" || flag === "--help")
|
|
40
|
+
out.help = true;
|
|
41
|
+
else if (flag === "--path")
|
|
42
|
+
out.path = value();
|
|
43
|
+
else if (flag === "--cols")
|
|
44
|
+
out.cols = num(value());
|
|
45
|
+
else if (flag === "--rows")
|
|
46
|
+
out.rows = num(value());
|
|
47
|
+
else if (flag === "--theme")
|
|
48
|
+
out.theme = value();
|
|
49
|
+
else if (flag === "--no-config")
|
|
50
|
+
out.skipConfig = true;
|
|
51
|
+
else if (flag === "--verbose")
|
|
52
|
+
out.verbose = true;
|
|
53
|
+
else if (a.startsWith("-") && a !== "-")
|
|
54
|
+
out.unknown.push(a);
|
|
55
|
+
else
|
|
56
|
+
positional.push(a);
|
|
57
|
+
}
|
|
58
|
+
// argv includes the command itself ("mcp") when called from `text`.
|
|
59
|
+
if (positional[0] === "mcp")
|
|
60
|
+
positional.shift();
|
|
61
|
+
if (positional[0])
|
|
62
|
+
out.dir = positional[0];
|
|
63
|
+
return out;
|
|
64
|
+
}
|
|
65
|
+
function formatEntry(e) {
|
|
66
|
+
return `[text mcp] ${e.level}${e.source !== "console" ? ` (${e.source})` : ""}: ${e.message}\n`;
|
|
67
|
+
}
|
|
68
|
+
/** Run the stdio server until stdin closes or a signal arrives. Resolves with the exit code. */
|
|
69
|
+
export async function runMcpCli(argv) {
|
|
70
|
+
const args = parseMcpArgs(argv);
|
|
71
|
+
const stderr = (s) => void process.stderr.write(s);
|
|
72
|
+
if (args.help) {
|
|
73
|
+
// Only a human asks for help, so stdout is not carrying JSON-RPC yet.
|
|
74
|
+
process.stdout.write(MCP_HELP);
|
|
75
|
+
return 0;
|
|
76
|
+
}
|
|
77
|
+
if (args.unknown.length > 0) {
|
|
78
|
+
stderr(`text mcp: unknown option${args.unknown.length > 1 ? "s" : ""} ${args.unknown.join(", ")}. See \`text mcp --help\`.\n`);
|
|
79
|
+
return 2;
|
|
80
|
+
}
|
|
81
|
+
if (typeof process.versions.bun !== "string") {
|
|
82
|
+
stderr(`${txMessage("TX019", "mcp", "mcp")}\n`);
|
|
83
|
+
return 1;
|
|
84
|
+
}
|
|
85
|
+
// 1. Own stdout before anything can write to it.
|
|
86
|
+
const realWrite = process.stdout.write.bind(process.stdout);
|
|
87
|
+
const logs = new LogBuffer();
|
|
88
|
+
const mirror = args.verbose ? (e) => stderr(formatEntry(e)) : undefined;
|
|
89
|
+
const capture = captureConsole(logs, mirror);
|
|
90
|
+
const strayWrite = ((chunk, encodingOrCb, cb) => {
|
|
91
|
+
const text = typeof chunk === "string" ? chunk : new TextDecoder().decode(chunk);
|
|
92
|
+
const entry = logs.push("log", "process", [text.replace(/\n$/, "")]);
|
|
93
|
+
mirror?.(entry);
|
|
94
|
+
const done = typeof encodingOrCb === "function" ? encodingOrCb : cb;
|
|
95
|
+
if (typeof done === "function")
|
|
96
|
+
queueMicrotask(() => done());
|
|
97
|
+
return true;
|
|
98
|
+
});
|
|
99
|
+
process.stdout.write = strayWrite;
|
|
100
|
+
const transportOut = {
|
|
101
|
+
write: (chunk) => realWrite(chunk),
|
|
102
|
+
once: (event, listener) => {
|
|
103
|
+
process.stdout.once(event, listener);
|
|
104
|
+
return transportOut;
|
|
105
|
+
},
|
|
106
|
+
on: (event, listener) => {
|
|
107
|
+
process.stdout.on(event, listener);
|
|
108
|
+
return transportOut;
|
|
109
|
+
},
|
|
110
|
+
};
|
|
111
|
+
const onRejection = (reason) => {
|
|
112
|
+
const e = logs.push("error", "process", ["Unhandled promise rejection:", reason]);
|
|
113
|
+
mirror?.(e);
|
|
114
|
+
};
|
|
115
|
+
const onException = (error) => {
|
|
116
|
+
const e = logs.push("error", "process", ["Uncaught exception:", error]);
|
|
117
|
+
mirror?.(e);
|
|
118
|
+
};
|
|
119
|
+
process.on("unhandledRejection", onRejection);
|
|
120
|
+
process.on("uncaughtException", onException);
|
|
121
|
+
const [{ StdioServerTransport }, { createTextMcpServer }] = await Promise.all([import("@modelcontextprotocol/sdk/server/stdio.js"), import("./server.js")]);
|
|
122
|
+
const root = resolve(args.dir);
|
|
123
|
+
const { server, controller } = createTextMcpServer({
|
|
124
|
+
root,
|
|
125
|
+
path: args.path,
|
|
126
|
+
cols: args.cols,
|
|
127
|
+
rows: args.rows,
|
|
128
|
+
theme: args.theme,
|
|
129
|
+
skipConfig: args.skipConfig,
|
|
130
|
+
logs,
|
|
131
|
+
captureConsole: false,
|
|
132
|
+
});
|
|
133
|
+
const transport = new StdioServerTransport(process.stdin, transportOut);
|
|
134
|
+
let resolveExit = () => undefined;
|
|
135
|
+
const exited = new Promise((r) => {
|
|
136
|
+
resolveExit = r;
|
|
137
|
+
});
|
|
138
|
+
let closing = false;
|
|
139
|
+
const shutdown = async (code) => {
|
|
140
|
+
if (closing)
|
|
141
|
+
return;
|
|
142
|
+
closing = true;
|
|
143
|
+
try {
|
|
144
|
+
await Promise.race([controller.dispose(), new Promise((r) => setTimeout(r, 2000))]);
|
|
145
|
+
await server.close().catch(() => undefined);
|
|
146
|
+
}
|
|
147
|
+
finally {
|
|
148
|
+
process.off("unhandledRejection", onRejection);
|
|
149
|
+
process.off("uncaughtException", onException);
|
|
150
|
+
capture.restore();
|
|
151
|
+
process.stdout.write = realWrite;
|
|
152
|
+
resolveExit(code);
|
|
153
|
+
// App timers or sockets must not keep a disconnected server alive.
|
|
154
|
+
setTimeout(() => process.exit(code), 500).unref();
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
process.stdin.once("end", () => void shutdown(0));
|
|
158
|
+
process.stdin.once("close", () => void shutdown(0));
|
|
159
|
+
process.once("SIGINT", () => void shutdown(130));
|
|
160
|
+
process.once("SIGTERM", () => void shutdown(143));
|
|
161
|
+
// The client went away mid-write (EPIPE): nothing can be delivered any more.
|
|
162
|
+
process.stdout.on("error", () => void shutdown(0));
|
|
163
|
+
await server.connect(transport);
|
|
164
|
+
// After connect: `Protocol.connect` installs its own transport `onclose`.
|
|
165
|
+
const onServerClose = server.server.onclose;
|
|
166
|
+
server.server.onclose = () => {
|
|
167
|
+
onServerClose?.();
|
|
168
|
+
void shutdown(0);
|
|
169
|
+
};
|
|
170
|
+
stderr(`▼ Text.js MCP server · ${root}\n`);
|
|
171
|
+
// Load the app in the background; tools wait for it and report load errors.
|
|
172
|
+
controller.start().catch((error) => {
|
|
173
|
+
stderr(`[text mcp] failed to start the app: ${error instanceof Error ? error.message : String(error)}\n`);
|
|
174
|
+
});
|
|
175
|
+
return exited;
|
|
176
|
+
}
|
|
177
|
+
//# sourceMappingURL=cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/mcp/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Frame extraction for agents: plain text, styled runs and text search, all in
|
|
3
|
+
* cell coordinates (wide graphemes such as CJK and emoji occupy two columns).
|
|
4
|
+
*/
|
|
5
|
+
import { type CellBuffer, type PackedColor } from "@textjs/core";
|
|
6
|
+
export interface Region {
|
|
7
|
+
x: number;
|
|
8
|
+
y: number;
|
|
9
|
+
width: number;
|
|
10
|
+
height: number;
|
|
11
|
+
}
|
|
12
|
+
export interface StyledRun {
|
|
13
|
+
/** Column of the first cell. */
|
|
14
|
+
x: number;
|
|
15
|
+
/** Width in cells. */
|
|
16
|
+
width: number;
|
|
17
|
+
text: string;
|
|
18
|
+
/** `#rrggbb` (or `#rrggbbaa` when translucent); `null` = terminal default. */
|
|
19
|
+
fg: string | null;
|
|
20
|
+
bg: string | null;
|
|
21
|
+
/** Subset of `bold dim italic underline strikethrough inverse`. */
|
|
22
|
+
attrs?: string[];
|
|
23
|
+
}
|
|
24
|
+
export interface StyledRow {
|
|
25
|
+
y: number;
|
|
26
|
+
runs: StyledRun[];
|
|
27
|
+
}
|
|
28
|
+
export interface TextMatch {
|
|
29
|
+
x: number;
|
|
30
|
+
y: number;
|
|
31
|
+
width: number;
|
|
32
|
+
height: number;
|
|
33
|
+
/** The full (trimmed) row the match is on. */
|
|
34
|
+
line: string;
|
|
35
|
+
}
|
|
36
|
+
export declare function colorHex(c: PackedColor): string | null;
|
|
37
|
+
export declare function attrNames(attrs: number): string[];
|
|
38
|
+
/** Clamp `region` to the buffer (the whole buffer when omitted). */
|
|
39
|
+
export declare function clampRegion(buffer: CellBuffer, region?: Partial<Region>): Region;
|
|
40
|
+
/** Plain text of `region`, one line per row (trailing spaces and blank rows trimmed). */
|
|
41
|
+
export declare function frameText(buffer: CellBuffer, region?: Partial<Region>, trim?: boolean): string;
|
|
42
|
+
/**
|
|
43
|
+
* Run-length encoded styled rows for `region`. Rows that are entirely blank,
|
|
44
|
+
* default-styled cells are omitted (each row carries its `y`).
|
|
45
|
+
*/
|
|
46
|
+
export declare function styledRows(buffer: CellBuffer, region?: Partial<Region>): StyledRow[];
|
|
47
|
+
export interface FindOptions {
|
|
48
|
+
/** Treat `query` as a regular expression (JavaScript syntax, no flags but `i`). */
|
|
49
|
+
regex?: boolean;
|
|
50
|
+
ignoreCase?: boolean;
|
|
51
|
+
/** Max matches (default 50). */
|
|
52
|
+
limit?: number;
|
|
53
|
+
}
|
|
54
|
+
/** Find `query` in the frame, row by row (matches never span rows). */
|
|
55
|
+
export declare function findText(buffer: CellBuffer, query: string, options?: FindOptions): TextMatch[];
|
|
56
|
+
/** Whether `text` appears anywhere in the frame (row by row). */
|
|
57
|
+
export declare function frameContains(buffer: CellBuffer, text: string): boolean;
|
|
58
|
+
//# sourceMappingURL=frame.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frame.d.ts","sourceRoot":"","sources":["../../src/mcp/frame.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAQL,KAAK,UAAU,EACf,KAAK,WAAW,EACjB,MAAM,cAAc,CAAC;AAEtB,MAAM,WAAW,MAAM;IACrB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,SAAS;IACxB,gCAAgC;IAChC,CAAC,EAAE,MAAM,CAAC;IACV,sBAAsB;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,8EAA8E;IAC9E,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAClB,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAClB,mEAAmE;IACnE,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,SAAS;IACxB,CAAC,EAAE,MAAM,CAAC;IACV,IAAI,EAAE,SAAS,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,SAAS;IACxB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,8CAA8C;IAC9C,IAAI,EAAE,MAAM,CAAC;CACd;AAaD,wBAAgB,QAAQ,CAAC,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,IAAI,CAMtD;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAIjD;AAED,oEAAoE;AACpE,wBAAgB,WAAW,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM,CAMhF;AA2CD,yFAAyF;AACzF,wBAAgB,SAAS,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,EAAE,IAAI,UAAO,GAAG,MAAM,CAS3F;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,GAAG,SAAS,EAAE,CAgCpF;AAWD,MAAM,WAAW,WAAW;IAC1B,mFAAmF;IACnF,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,gCAAgC;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,uEAAuE;AACvE,wBAAgB,QAAQ,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB,GAAG,SAAS,EAAE,CAuBlG;AAED,iEAAiE;AACjE,wBAAgB,aAAa,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAGvE"}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Frame extraction for agents: plain text, styled runs and text search, all in
|
|
3
|
+
* cell coordinates (wide graphemes such as CJK and emoji occupy two columns).
|
|
4
|
+
*/
|
|
5
|
+
import { ATTR_BOLD, ATTR_DIM, ATTR_INVERSE, ATTR_ITALIC, ATTR_STRIKETHROUGH, ATTR_UNDERLINE, ATTR_WIDE_CONT, } from "@textjs/core";
|
|
6
|
+
const ATTR_NAMES = [
|
|
7
|
+
[ATTR_BOLD, "bold"],
|
|
8
|
+
[ATTR_DIM, "dim"],
|
|
9
|
+
[ATTR_ITALIC, "italic"],
|
|
10
|
+
[ATTR_UNDERLINE, "underline"],
|
|
11
|
+
[ATTR_STRIKETHROUGH, "strikethrough"],
|
|
12
|
+
[ATTR_INVERSE, "inverse"],
|
|
13
|
+
];
|
|
14
|
+
const STYLE_MASK = ATTR_BOLD | ATTR_DIM | ATTR_ITALIC | ATTR_UNDERLINE | ATTR_STRIKETHROUGH | ATTR_INVERSE;
|
|
15
|
+
export function colorHex(c) {
|
|
16
|
+
if (c === 0)
|
|
17
|
+
return null;
|
|
18
|
+
const v = c >>> 0;
|
|
19
|
+
const rgb = (v >>> 8).toString(16).padStart(6, "0");
|
|
20
|
+
const a = v & 0xff;
|
|
21
|
+
return a === 0xff ? `#${rgb}` : `#${rgb}${a.toString(16).padStart(2, "0")}`;
|
|
22
|
+
}
|
|
23
|
+
export function attrNames(attrs) {
|
|
24
|
+
const out = [];
|
|
25
|
+
for (const [bit, name] of ATTR_NAMES)
|
|
26
|
+
if ((attrs & bit) !== 0)
|
|
27
|
+
out.push(name);
|
|
28
|
+
return out;
|
|
29
|
+
}
|
|
30
|
+
/** Clamp `region` to the buffer (the whole buffer when omitted). */
|
|
31
|
+
export function clampRegion(buffer, region) {
|
|
32
|
+
const x = Math.max(0, Math.min(buffer.width, Math.floor(region?.x ?? 0)));
|
|
33
|
+
const y = Math.max(0, Math.min(buffer.height, Math.floor(region?.y ?? 0)));
|
|
34
|
+
const width = Math.max(0, Math.min(buffer.width - x, Math.floor(region?.width ?? buffer.width - x)));
|
|
35
|
+
const height = Math.max(0, Math.min(buffer.height - y, Math.floor(region?.height ?? buffer.height - y)));
|
|
36
|
+
return { x, y, width, height };
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Display text of a cell: empty and control cells read as a space, and so
|
|
40
|
+
* does U+00A0 (fields draw their block cursor on a no-break space), so
|
|
41
|
+
* `find` / `wait_for` match what is visible.
|
|
42
|
+
*/
|
|
43
|
+
function cellText(ch) {
|
|
44
|
+
return ch === "" || ch === "\u00a0" || ch.charCodeAt(0) < 0x20 ? " " : ch;
|
|
45
|
+
}
|
|
46
|
+
/** A row slice as text plus a string-index → column map. */
|
|
47
|
+
function rowCells(buffer, y, x0, x1) {
|
|
48
|
+
let text = "";
|
|
49
|
+
const colsList = [];
|
|
50
|
+
for (let x = x0; x < x1; x++) {
|
|
51
|
+
const cell = buffer.getCell(x, y);
|
|
52
|
+
if (!cell)
|
|
53
|
+
break;
|
|
54
|
+
if ((cell.attrs & ATTR_WIDE_CONT) !== 0) {
|
|
55
|
+
// A wide grapheme cut by the region's left edge renders as a blank.
|
|
56
|
+
if (x === x0) {
|
|
57
|
+
colsList.push(x);
|
|
58
|
+
text += " ";
|
|
59
|
+
}
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
// The lead half of a wide glyph cut by the right edge must occupy one
|
|
63
|
+
// blank column (the symmetric case of a continuation at the left edge).
|
|
64
|
+
const clipped = x === x1 - 1 && ((buffer.getCell(x + 1, y)?.attrs ?? 0) & ATTR_WIDE_CONT) !== 0;
|
|
65
|
+
const ch = clipped ? " " : cellText(cell.char);
|
|
66
|
+
for (let i = 0; i < ch.length; i++)
|
|
67
|
+
colsList.push(x);
|
|
68
|
+
text += ch;
|
|
69
|
+
}
|
|
70
|
+
colsList.push(x1);
|
|
71
|
+
return { text, cols: Int32Array.from(colsList) };
|
|
72
|
+
}
|
|
73
|
+
/** Plain text of `region`, one line per row (trailing spaces and blank rows trimmed). */
|
|
74
|
+
export function frameText(buffer, region, trim = true) {
|
|
75
|
+
const r = clampRegion(buffer, region);
|
|
76
|
+
const lines = [];
|
|
77
|
+
for (let y = r.y; y < r.y + r.height; y++) {
|
|
78
|
+
const text = rowCells(buffer, y, r.x, r.x + r.width).text;
|
|
79
|
+
lines.push(trim ? text.trimEnd() : text);
|
|
80
|
+
}
|
|
81
|
+
if (trim)
|
|
82
|
+
while (lines.length > 0 && lines[lines.length - 1] === "")
|
|
83
|
+
lines.pop();
|
|
84
|
+
return lines.join("\n");
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Run-length encoded styled rows for `region`. Rows that are entirely blank,
|
|
88
|
+
* default-styled cells are omitted (each row carries its `y`).
|
|
89
|
+
*/
|
|
90
|
+
export function styledRows(buffer, region) {
|
|
91
|
+
const r = clampRegion(buffer, region);
|
|
92
|
+
const rows = [];
|
|
93
|
+
for (let y = r.y; y < r.y + r.height; y++) {
|
|
94
|
+
const runs = [];
|
|
95
|
+
let cur = null;
|
|
96
|
+
for (let x = r.x; x < r.x + r.width; x++) {
|
|
97
|
+
const cell = buffer.getCell(x, y);
|
|
98
|
+
if (!cell)
|
|
99
|
+
break;
|
|
100
|
+
const attrs = cell.attrs & STYLE_MASK;
|
|
101
|
+
const key = `${cell.fg}|${cell.bg}|${attrs}`;
|
|
102
|
+
const wideCont = (cell.attrs & ATTR_WIDE_CONT) !== 0;
|
|
103
|
+
// A wide grapheme's second cell extends its run; cut by the region's left edge, it reads as a blank.
|
|
104
|
+
if (wideCont && cur) {
|
|
105
|
+
cur.width++;
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
const clipped = x === r.x + r.width - 1 && ((buffer.getCell(x + 1, y)?.attrs ?? 0) & ATTR_WIDE_CONT) !== 0;
|
|
109
|
+
const ch = wideCont || clipped ? " " : cellText(cell.char);
|
|
110
|
+
if (cur && cur.key === key) {
|
|
111
|
+
cur.text += ch;
|
|
112
|
+
cur.width++;
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
if (cur)
|
|
116
|
+
runs.push(stripKey(cur));
|
|
117
|
+
cur = { key, x, width: 1, text: ch, fg: colorHex(cell.fg), bg: colorHex(cell.bg), ...(attrs ? { attrs: attrNames(attrs) } : {}) };
|
|
118
|
+
}
|
|
119
|
+
if (cur)
|
|
120
|
+
runs.push(stripKey(cur));
|
|
121
|
+
if (runs.every(isBlankRun))
|
|
122
|
+
continue;
|
|
123
|
+
rows.push({ y, runs });
|
|
124
|
+
}
|
|
125
|
+
return rows;
|
|
126
|
+
}
|
|
127
|
+
function isBlankRun(run) {
|
|
128
|
+
return run.bg === null && run.attrs === undefined && run.text.trim() === "";
|
|
129
|
+
}
|
|
130
|
+
function stripKey(run) {
|
|
131
|
+
const { key: _key, ...rest } = run;
|
|
132
|
+
return rest;
|
|
133
|
+
}
|
|
134
|
+
/** Find `query` in the frame, row by row (matches never span rows). */
|
|
135
|
+
export function findText(buffer, query, options = {}) {
|
|
136
|
+
const limit = options.limit ?? 50;
|
|
137
|
+
const out = [];
|
|
138
|
+
if (query === "")
|
|
139
|
+
return out;
|
|
140
|
+
let re;
|
|
141
|
+
if (options.regex)
|
|
142
|
+
re = new RegExp(query, options.ignoreCase ? "gi" : "g");
|
|
143
|
+
else
|
|
144
|
+
re = new RegExp(query.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), options.ignoreCase ? "gi" : "g");
|
|
145
|
+
for (let y = 0; y < buffer.height && out.length < limit; y++) {
|
|
146
|
+
const row = rowCells(buffer, y, 0, buffer.width);
|
|
147
|
+
re.lastIndex = 0;
|
|
148
|
+
for (let m = re.exec(row.text); m !== null && out.length < limit; m = re.exec(row.text)) {
|
|
149
|
+
if (m[0] === "") {
|
|
150
|
+
re.lastIndex++;
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
const x = row.cols[m.index];
|
|
154
|
+
const end = row.cols[m.index + m[0].length];
|
|
155
|
+
// A match ending inside a wide grapheme extends to cover it.
|
|
156
|
+
const width = Math.max(1, end - x);
|
|
157
|
+
out.push({ x, y, width, height: 1, line: row.text.trimEnd() });
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return out;
|
|
161
|
+
}
|
|
162
|
+
/** Whether `text` appears anywhere in the frame (row by row). */
|
|
163
|
+
export function frameContains(buffer, text) {
|
|
164
|
+
for (let y = 0; y < buffer.height; y++)
|
|
165
|
+
if (rowCells(buffer, y, 0, buffer.width).text.includes(text))
|
|
166
|
+
return true;
|
|
167
|
+
return false;
|
|
168
|
+
}
|
|
169
|
+
//# sourceMappingURL=frame.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frame.js","sourceRoot":"","sources":["../../src/mcp/frame.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@textjs/app/mcp` — drive Text.js apps from coding agents.
|
|
3
|
+
*
|
|
4
|
+
* `text mcp [dir]` serves these tools over stdio; `createTextMcpServer()`
|
|
5
|
+
* embeds the same server in another process (any MCP transport), and
|
|
6
|
+
* `HeadlessSession` is the transport-free core.
|
|
7
|
+
*/
|
|
8
|
+
export { createTextMcpServer, formatFrame, SessionController, type TextMcpServerOptions } from "./server.js";
|
|
9
|
+
export { HeadlessSession, SessionError, purgeModuleCache, type FetchResult, type FocusSummary, type FrameSnapshot, type SessionOptions, type SettleResult } from "./session.js";
|
|
10
|
+
export { findText, frameText, styledRows, type Region, type StyledRow, type StyledRun, type TextMatch } from "./frame.js";
|
|
11
|
+
export { FiberProbe, formatTree, inspect, type Bounds, type FocusableInfo, type InspectOptions, type InspectResult, type TreeNode } from "./inspect.js";
|
|
12
|
+
export { parseKeyInput, textToKeyEvents, KeySpecError, MAX_KEYS_PER_CALL } from "./keys.js";
|
|
13
|
+
export { captureConsole, LogBuffer, type LogEntry, type LogLevel } from "./logs.js";
|
|
14
|
+
export { MCP_HELP, parseMcpArgs, runMcpCli } from "./cli.js";
|
|
15
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/mcp/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,mBAAmB,EAAE,WAAW,EAAE,iBAAiB,EAAE,KAAK,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAC1G,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,gBAAgB,EAAE,KAAK,WAAW,EAAE,KAAK,YAAY,EAAE,KAAK,aAAa,EAAE,KAAK,cAAc,EAAE,KAAK,YAAY,EAAE,MAAM,WAAW,CAAC;AAC7K,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,UAAU,EAAE,KAAK,MAAM,EAAE,KAAK,SAAS,EAAE,KAAK,SAAS,EAAE,KAAK,SAAS,EAAE,MAAM,SAAS,CAAC;AACvH,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,KAAK,MAAM,EAAE,KAAK,aAAa,EAAE,KAAK,cAAc,EAAE,KAAK,aAAa,EAAE,KAAK,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrJ,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,QAAQ,CAAC;AACzF,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,KAAK,QAAQ,EAAE,KAAK,QAAQ,EAAE,MAAM,QAAQ,CAAC;AACjF,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@textjs/app/mcp` — drive Text.js apps from coding agents.
|
|
3
|
+
*
|
|
4
|
+
* `text mcp [dir]` serves these tools over stdio; `createTextMcpServer()`
|
|
5
|
+
* embeds the same server in another process (any MCP transport), and
|
|
6
|
+
* `HeadlessSession` is the transport-free core.
|
|
7
|
+
*/
|
|
8
|
+
export { createTextMcpServer, formatFrame, SessionController } from "./server.js";
|
|
9
|
+
export { HeadlessSession, SessionError, purgeModuleCache } from "./session.js";
|
|
10
|
+
export { findText, frameText, styledRows } from "./frame.js";
|
|
11
|
+
export { FiberProbe, formatTree, inspect } from "./inspect.js";
|
|
12
|
+
export { parseKeyInput, textToKeyEvents, KeySpecError, MAX_KEYS_PER_CALL } from "./keys.js";
|
|
13
|
+
export { captureConsole, LogBuffer } from "./logs.js";
|
|
14
|
+
export { MCP_HELP, parseMcpArgs, runMcpCli } from "./cli.js";
|
|
15
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/mcp/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,mBAAmB,EAAE,WAAW,EAAE,iBAAiB,EAA6B,MAAM,UAAU,CAAC;AAC1G,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,gBAAgB,EAAmG,MAAM,WAAW,CAAC;AAC7K,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,UAAU,EAA+D,MAAM,SAAS,CAAC;AACvH,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,OAAO,EAA2F,MAAM,WAAW,CAAC;AACrJ,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,QAAQ,CAAC;AACzF,OAAO,EAAE,cAAc,EAAE,SAAS,EAAgC,MAAM,QAAQ,CAAC;AACjF,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Component + scene tree inspection for `text mcp`.
|
|
3
|
+
*
|
|
4
|
+
* The React tree is read from fibers: `<FiberProbe>` (a class component
|
|
5
|
+
* mounted around the app) exposes its fiber via `_reactInternals`, which React
|
|
6
|
+
* sets on every class instance in development and production builds alike.
|
|
7
|
+
* Host fibers (`tx-box` / `tx-text` / raw text) point at their `SceneNode`
|
|
8
|
+
* (`stateNode`), whose `screenRect` from the last paint gives cell bounds.
|
|
9
|
+
*/
|
|
10
|
+
import { Component, type ReactNode } from "react";
|
|
11
|
+
import type { SceneNode } from "@textjs/core";
|
|
12
|
+
import type { FocusManager } from "@textjs/react";
|
|
13
|
+
export declare class FiberProbe extends Component<{
|
|
14
|
+
children?: ReactNode;
|
|
15
|
+
}> {
|
|
16
|
+
render(): ReactNode;
|
|
17
|
+
}
|
|
18
|
+
export interface Bounds {
|
|
19
|
+
x: number;
|
|
20
|
+
y: number;
|
|
21
|
+
width: number;
|
|
22
|
+
height: number;
|
|
23
|
+
}
|
|
24
|
+
export interface TreeNode {
|
|
25
|
+
/**
|
|
26
|
+
* `component` (React function/class), `box` / `text` (host scene nodes),
|
|
27
|
+
* `suspense`, or `portal` (content `<Modal>` / `<Dialog>` / toasts render
|
|
28
|
+
* into the root layer; its bounds are not part of the parent's).
|
|
29
|
+
*/
|
|
30
|
+
kind: "component" | "box" | "text" | "suspense" | "portal";
|
|
31
|
+
name: string;
|
|
32
|
+
key?: string;
|
|
33
|
+
/** Screen bounds from the last painted frame (union of painted host descendants for components). */
|
|
34
|
+
bounds?: Bounds;
|
|
35
|
+
/** Text content (text hosts; truncated). */
|
|
36
|
+
text?: string;
|
|
37
|
+
/** Focus id owned by this component (`useFocus`), when it can be attributed. */
|
|
38
|
+
focusId?: string;
|
|
39
|
+
focused?: boolean;
|
|
40
|
+
/** `wireframeLabel` / `title` of a box host, when set. */
|
|
41
|
+
label?: string;
|
|
42
|
+
children?: TreeNode[];
|
|
43
|
+
}
|
|
44
|
+
export interface FocusableInfo {
|
|
45
|
+
id: string;
|
|
46
|
+
focused: boolean;
|
|
47
|
+
/** Included in Tab order and not blocked by a focus trap (e.g. an open `<Modal>`). */
|
|
48
|
+
tabbable: boolean;
|
|
49
|
+
component?: string;
|
|
50
|
+
bounds?: Bounds;
|
|
51
|
+
}
|
|
52
|
+
export interface InspectOptions {
|
|
53
|
+
/** Include host `box` / `text` nodes (default `true`). */
|
|
54
|
+
hosts?: boolean;
|
|
55
|
+
/** Levels of the returned tree (default 40), counted from the top level, or from each match with `component`. */
|
|
56
|
+
maxDepth?: number;
|
|
57
|
+
/** Only return subtrees rooted at components whose name matches (case-insensitive substring). */
|
|
58
|
+
component?: string;
|
|
59
|
+
/** Hide components that render nothing visible (default `true`). */
|
|
60
|
+
hideEmpty?: boolean;
|
|
61
|
+
}
|
|
62
|
+
export interface InspectResult {
|
|
63
|
+
tree: TreeNode | null;
|
|
64
|
+
focusables: FocusableInfo[];
|
|
65
|
+
activeFocusId: string | null;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Walk the React tree under `probe`. Components are attributed to the focus id
|
|
69
|
+
* they registered with `useFocus()` (its `FOCUS_OWNER` hook-state marker).
|
|
70
|
+
*/
|
|
71
|
+
export declare function inspect(probe: FiberProbe | null, focus: FocusManager, options?: InspectOptions): InspectResult;
|
|
72
|
+
/** Render a tree as indented text: `Name [x,y w×h] "text" focus=id`. */
|
|
73
|
+
export declare function formatTree(node: TreeNode, indent?: string): string;
|
|
74
|
+
export interface SceneGrid {
|
|
75
|
+
/** The console root's scene node (`ConsoleRoot.rootNode`). */
|
|
76
|
+
root: SceneNode;
|
|
77
|
+
cols: number;
|
|
78
|
+
rows: number;
|
|
79
|
+
}
|
|
80
|
+
export interface HitResult {
|
|
81
|
+
/** Nearest component above the topmost painted host at the cell. */
|
|
82
|
+
component: string | null;
|
|
83
|
+
/** Component names from the app root down to `component`. */
|
|
84
|
+
path: string[];
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Hit-tester for cells: the topmost painted host scene node at `(x, y)` in
|
|
88
|
+
* paint order (overflow clipping, scroll offsets, absolute `zIndex` layers
|
|
89
|
+
* and portals such as `<Modal>`), attributed to its component chain.
|
|
90
|
+
* Ownership is computed once per tester.
|
|
91
|
+
*/
|
|
92
|
+
export declare function createHitTester(probe: FiberProbe | null, grid: SceneGrid): (x: number, y: number) => HitResult;
|
|
93
|
+
/** {@link createHitTester} for a single cell. */
|
|
94
|
+
export declare function hitTest(probe: FiberProbe | null, grid: SceneGrid, x: number, y: number): HitResult;
|
|
95
|
+
//# sourceMappingURL=inspect.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inspect.d.ts","sourceRoot":"","sources":["../../src/mcp/inspect.ts"],"names":[],"mappings":"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"}
|