@codyswann/lisa 2.228.0 → 2.229.1
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/dist/cli/ui-cmd.d.ts +9 -1
- package/dist/cli/ui-cmd.d.ts.map +1 -1
- package/dist/cli/ui-cmd.js +142 -11
- package/dist/cli/ui-cmd.js.map +1 -1
- package/dist/cli/ui-status-json.d.ts +29 -0
- package/dist/cli/ui-status-json.d.ts.map +1 -0
- package/dist/cli/ui-status-json.js +162 -0
- package/dist/cli/ui-status-json.js.map +1 -0
- package/dist/cli/ui-status.d.ts +42 -0
- package/dist/cli/ui-status.d.ts.map +1 -0
- package/dist/cli/ui-status.js +221 -0
- package/dist/cli/ui-status.js.map +1 -0
- package/package.json +3 -2
- package/plugins/lisa/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-agy/plugin.json +1 -1
- package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-agy/plugin.json +1 -1
- package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-agy/plugin.json +1 -1
- package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-agy/plugin.json +1 -1
- package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-agy/plugin.json +1 -1
- package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-agy/plugin.json +1 -1
- package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-agy/plugin.json +1 -1
- package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-agy/plugin.json +1 -1
- package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-agy/plugin.json +1 -1
- package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
- package/ui/README.md +15 -0
- package/ui/index.html +156 -0
package/dist/cli/ui-cmd.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import * as http from "node:http";
|
|
2
2
|
import { type JsonObject } from "../sync/json-path.js";
|
|
3
|
+
import { type StatusProbe } from "./ui-status.js";
|
|
4
|
+
export { createGithubAuthProbe, runProbe, type GitRemoteReader, type GithubAuthCheck, type ProbeResult, type StatusProbe, } from "./ui-status.js";
|
|
3
5
|
/** Default port for the settings console. */
|
|
4
6
|
export declare const DEFAULT_UI_PORT = 4780;
|
|
5
7
|
/** CLI options for `lisa ui`. */
|
|
@@ -9,6 +11,11 @@ export interface UiCmdOptions {
|
|
|
9
11
|
/** Set false (via --no-sync) to skip the config sync on startup */
|
|
10
12
|
readonly sync?: boolean;
|
|
11
13
|
}
|
|
14
|
+
/** Injectable runtime collaborators for `lisa ui`. */
|
|
15
|
+
export interface UiRuntimeDependencies {
|
|
16
|
+
/** Status probes exposed by GET /api/status. */
|
|
17
|
+
readonly probes?: readonly StatusProbe[];
|
|
18
|
+
}
|
|
12
19
|
/** Secret/variable and generated-artifact status exposed to the console. */
|
|
13
20
|
export interface RemoteEnvironmentStatus {
|
|
14
21
|
/** Whether each supported variable is visible to the `lisa ui` process. */
|
|
@@ -49,7 +56,8 @@ export declare function injectLiveConfig(html: string, config: JsonObject, remot
|
|
|
49
56
|
* Run the `lisa ui` command: sync, then serve the console until interrupted.
|
|
50
57
|
* @param targetPath - Project path argument (defaults to the current directory)
|
|
51
58
|
* @param options - CLI options
|
|
59
|
+
* @param dependencies - Optional status probes for tests and extensions
|
|
52
60
|
* @returns The listening server (callers/tests are responsible for closing it)
|
|
53
61
|
*/
|
|
54
|
-
export declare function runUi(targetPath: string | undefined, options?: UiCmdOptions): Promise<http.Server>;
|
|
62
|
+
export declare function runUi(targetPath: string | undefined, options?: UiCmdOptions, dependencies?: UiRuntimeDependencies): Promise<http.Server>;
|
|
55
63
|
//# sourceMappingURL=ui-cmd.d.ts.map
|
package/dist/cli/ui-cmd.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ui-cmd.d.ts","sourceRoot":"","sources":["../../src/cli/ui-cmd.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAIlC,OAAO,EAAgB,KAAK,UAAU,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"ui-cmd.d.ts","sourceRoot":"","sources":["../../src/cli/ui-cmd.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAIlC,OAAO,EAAgB,KAAK,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAGrE,OAAO,EAKL,KAAK,WAAW,EACjB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,qBAAqB,EACrB,QAAQ,EACR,KAAK,eAAe,EACpB,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,KAAK,WAAW,GACjB,MAAM,gBAAgB,CAAC;AAExB,6CAA6C;AAC7C,eAAO,MAAM,eAAe,OAAO,CAAC;AAKpC,iCAAiC;AACjC,MAAM,WAAW,YAAY;IAC3B,4EAA4E;IAC5E,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,mEAAmE;IACnE,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,sDAAsD;AACtD,MAAM,WAAW,qBAAqB;IACpC,gDAAgD;IAChD,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,WAAW,EAAE,CAAC;CAC1C;AAED,4EAA4E;AAC5E,MAAM,WAAW,uBAAuB;IACtC,2EAA2E;IAC3E,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACtD,8EAA8E;IAC9E,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CACvD;AAED,gFAAgF;AAChF,eAAO,MAAM,4BAA4B,uFAI/B,CAAC;AAEX,qEAAqE;AACrE,eAAO,MAAM,4BAA4B,yHAI/B,CAAC;AAYX;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,MAAM,EACf,WAAW,GAAE,MAAM,CAAC,UAAoC,GACvD,uBAAuB,CAezB;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAUnD;AAmBD;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,UAAU,EAClB,iBAAiB,GAAE,uBAGlB,GACA,MAAM,CAQR;AA0JD;;;;;;GAMG;AACH,wBAAsB,KAAK,CACzB,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,OAAO,GAAE,YAAiB,EAC1B,YAAY,GAAE,qBAA0B,GACvC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CA4BtB"}
|
package/dist/cli/ui-cmd.js
CHANGED
|
@@ -16,8 +16,13 @@ import { runConfigSync } from "../sync/config-sync.js";
|
|
|
16
16
|
import { isJsonObject } from "../sync/json-path.js";
|
|
17
17
|
import { deepMerge, readJsonOrNull } from "../utils/index.js";
|
|
18
18
|
import { printSyncReport } from "./sync-cmd.js";
|
|
19
|
+
import { createGithubAuthProbe, readStatusSnapshot, validateStatusProbes, } from "./ui-status.js";
|
|
20
|
+
export { createGithubAuthProbe, runProbe, } from "./ui-status.js";
|
|
19
21
|
/** Default port for the settings console. */
|
|
20
22
|
export const DEFAULT_UI_PORT = 4780;
|
|
23
|
+
const JSON_CONTENT_TYPE = "application/json; charset=utf-8";
|
|
24
|
+
const NO_STORE = "no-store";
|
|
25
|
+
const TEXT_CONTENT_TYPE = "text/plain; charset=utf-8";
|
|
21
26
|
/** Variables the remote AWS bootstrap understands. Values are never exposed. */
|
|
22
27
|
export const REMOTE_ENVIRONMENT_VARIABLES = [
|
|
23
28
|
"LISA_AWS_BOOTSTRAP_JSON",
|
|
@@ -105,13 +110,147 @@ export function injectLiveConfig(html, config, remoteEnvironment = {
|
|
|
105
110
|
const tag = `<script>window.LISA_LIVE_CONFIG = ${payload}; window.LISA_REMOTE_ENVIRONMENT = ${remotePayload};</script>`;
|
|
106
111
|
return html.replace("</body>", `${tag}\n</body>`);
|
|
107
112
|
}
|
|
113
|
+
/**
|
|
114
|
+
* Create a single-flight reader that coalesces concurrent status requests.
|
|
115
|
+
* @param probes - Validated live-status probes
|
|
116
|
+
* @returns Snapshot reader shared by one UI server
|
|
117
|
+
*/
|
|
118
|
+
function createStatusSnapshotReader(probes) {
|
|
119
|
+
// eslint-disable-next-line functional/no-let -- single-flight state clears after settlement
|
|
120
|
+
let inFlight;
|
|
121
|
+
return () => {
|
|
122
|
+
if (inFlight === undefined) {
|
|
123
|
+
const pending = readStatusSnapshot(probes);
|
|
124
|
+
inFlight = pending;
|
|
125
|
+
const clear = () => {
|
|
126
|
+
if (inFlight === pending) {
|
|
127
|
+
inFlight = undefined;
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
void pending.then(clear, clear);
|
|
131
|
+
}
|
|
132
|
+
return inFlight;
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Serve the same-origin live-status endpoint.
|
|
137
|
+
* @param request - Incoming loopback request
|
|
138
|
+
* @param response - Response associated with the request
|
|
139
|
+
* @param readSnapshot - Single-flight status snapshot reader
|
|
140
|
+
*/
|
|
141
|
+
function serveStatus(request, response, readSnapshot) {
|
|
142
|
+
if (request.method === "HEAD") {
|
|
143
|
+
response.writeHead(200, {
|
|
144
|
+
"cache-control": NO_STORE,
|
|
145
|
+
"content-type": JSON_CONTENT_TYPE,
|
|
146
|
+
});
|
|
147
|
+
response.end();
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
if (request.method !== "GET") {
|
|
151
|
+
response.writeHead(405, {
|
|
152
|
+
allow: "GET, HEAD",
|
|
153
|
+
"cache-control": NO_STORE,
|
|
154
|
+
"content-type": TEXT_CONTENT_TYPE,
|
|
155
|
+
});
|
|
156
|
+
response.end("Method not allowed");
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
void readSnapshot()
|
|
160
|
+
.then(snapshot => {
|
|
161
|
+
response.writeHead(200, {
|
|
162
|
+
"cache-control": NO_STORE,
|
|
163
|
+
"content-type": JSON_CONTENT_TYPE,
|
|
164
|
+
});
|
|
165
|
+
response.end(JSON.stringify({ probes: snapshot }));
|
|
166
|
+
})
|
|
167
|
+
.catch(error => {
|
|
168
|
+
response.writeHead(500, {
|
|
169
|
+
"cache-control": NO_STORE,
|
|
170
|
+
"content-type": JSON_CONTENT_TYPE,
|
|
171
|
+
});
|
|
172
|
+
response.end(JSON.stringify({
|
|
173
|
+
error: error instanceof Error ? error.message : String(error),
|
|
174
|
+
}));
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Parse an HTTP request target without allowing malformed input to escape.
|
|
179
|
+
* @param requestUrl - Raw request target supplied by Node HTTP
|
|
180
|
+
* @returns Parsed pathname, or undefined for an invalid target
|
|
181
|
+
*/
|
|
182
|
+
function requestPathname(requestUrl) {
|
|
183
|
+
try {
|
|
184
|
+
return new URL(requestUrl, "http://127.0.0.1").pathname;
|
|
185
|
+
}
|
|
186
|
+
catch {
|
|
187
|
+
return undefined;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Restrict loopback requests to the authority advertised by `lisa ui`.
|
|
192
|
+
* @param host - Incoming HTTP Host header
|
|
193
|
+
* @returns Whether the authority is 127.0.0.1 with an optional valid port
|
|
194
|
+
*/
|
|
195
|
+
function isLoopbackHost(host) {
|
|
196
|
+
if (host === "127.0.0.1") {
|
|
197
|
+
return true;
|
|
198
|
+
}
|
|
199
|
+
const prefix = "127.0.0.1:";
|
|
200
|
+
if (host === undefined || !host.startsWith(prefix)) {
|
|
201
|
+
return false;
|
|
202
|
+
}
|
|
203
|
+
const portText = host.slice(prefix.length);
|
|
204
|
+
const digitsOnly = Array.from(portText).every(character => character >= "0" && character <= "9");
|
|
205
|
+
const port = Number(portText);
|
|
206
|
+
return (portText.length > 0 &&
|
|
207
|
+
portText.length <= 5 &&
|
|
208
|
+
digitsOnly &&
|
|
209
|
+
port > 0 &&
|
|
210
|
+
port <= 65_535);
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Build the request handler after validating the complete probe registry.
|
|
214
|
+
* @param page - Hydrated settings console HTML
|
|
215
|
+
* @param probes - Live-status probes registered for this server
|
|
216
|
+
* @returns Loopback HTTP request handler
|
|
217
|
+
*/
|
|
218
|
+
function createUiRequestHandler(page, probes) {
|
|
219
|
+
const readSnapshot = createStatusSnapshotReader(probes);
|
|
220
|
+
validateStatusProbes(probes);
|
|
221
|
+
return (request, response) => {
|
|
222
|
+
if (!isLoopbackHost(request.headers.host)) {
|
|
223
|
+
response.writeHead(400, { "content-type": TEXT_CONTENT_TYPE });
|
|
224
|
+
response.end("Bad request");
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
const pathname = requestPathname(request.url ?? "/");
|
|
228
|
+
if (pathname === undefined) {
|
|
229
|
+
response.writeHead(400, { "content-type": TEXT_CONTENT_TYPE });
|
|
230
|
+
response.end("Bad request");
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
if (pathname === "/api/status") {
|
|
234
|
+
serveStatus(request, response, readSnapshot);
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
if (pathname === "/" || pathname === "/index.html") {
|
|
238
|
+
response.writeHead(200, { "content-type": "text/html; charset=utf-8" });
|
|
239
|
+
response.end(page);
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
response.writeHead(404, { "content-type": "text/plain" });
|
|
243
|
+
response.end("Not found");
|
|
244
|
+
};
|
|
245
|
+
}
|
|
108
246
|
/**
|
|
109
247
|
* Run the `lisa ui` command: sync, then serve the console until interrupted.
|
|
110
248
|
* @param targetPath - Project path argument (defaults to the current directory)
|
|
111
249
|
* @param options - CLI options
|
|
250
|
+
* @param dependencies - Optional status probes for tests and extensions
|
|
112
251
|
* @returns The listening server (callers/tests are responsible for closing it)
|
|
113
252
|
*/
|
|
114
|
-
export async function runUi(targetPath, options = {}) {
|
|
253
|
+
export async function runUi(targetPath, options = {}, dependencies = {}) {
|
|
115
254
|
const destDir = path.resolve(targetPath ?? ".");
|
|
116
255
|
const port = Number.parseInt(options.port ?? `${DEFAULT_UI_PORT}`, 10);
|
|
117
256
|
if (Number.isNaN(port) || port < 0 || port > 65535) {
|
|
@@ -127,16 +266,8 @@ export async function runUi(targetPath, options = {}) {
|
|
|
127
266
|
const config = await readMergedConfig(destDir);
|
|
128
267
|
const remoteEnvironment = inspectRemoteEnvironment(destDir);
|
|
129
268
|
const page = injectLiveConfig(html, config, remoteEnvironment);
|
|
130
|
-
const
|
|
131
|
-
|
|
132
|
-
if (url === "/" || url.startsWith("/index.html") || url.startsWith("/#")) {
|
|
133
|
-
response.writeHead(200, { "content-type": "text/html; charset=utf-8" });
|
|
134
|
-
response.end(page);
|
|
135
|
-
return;
|
|
136
|
-
}
|
|
137
|
-
response.writeHead(404, { "content-type": "text/plain" });
|
|
138
|
-
response.end("Not found");
|
|
139
|
-
});
|
|
269
|
+
const probes = dependencies.probes ?? [createGithubAuthProbe(destDir)];
|
|
270
|
+
const server = http.createServer(createUiRequestHandler(page, probes));
|
|
140
271
|
await new Promise(resolve => {
|
|
141
272
|
server.listen(port, "127.0.0.1", resolve);
|
|
142
273
|
});
|
package/dist/cli/ui-cmd.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ui-cmd.js","sourceRoot":"","sources":["../../src/cli/ui-cmd.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAmB,MAAM,sBAAsB,CAAC;AACrE,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"ui-cmd.js","sourceRoot":"","sources":["../../src/cli/ui-cmd.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime-safe JSON normalization for live-status probe results.
|
|
3
|
+
* @module cli/ui-status-json
|
|
4
|
+
*/
|
|
5
|
+
import type { JsonValue } from "../sync/json-path.js";
|
|
6
|
+
/** A probe result that never conflates missing evidence with a real value. */
|
|
7
|
+
export type ProbeResult<T extends JsonValue = JsonValue> = {
|
|
8
|
+
readonly state: "value";
|
|
9
|
+
readonly value: T;
|
|
10
|
+
readonly reason?: never;
|
|
11
|
+
readonly message?: never;
|
|
12
|
+
} | {
|
|
13
|
+
readonly state: "unknown";
|
|
14
|
+
readonly reason: string;
|
|
15
|
+
readonly message: string;
|
|
16
|
+
readonly value?: never;
|
|
17
|
+
} | {
|
|
18
|
+
readonly state: "not-applicable";
|
|
19
|
+
readonly value?: never;
|
|
20
|
+
readonly reason?: never;
|
|
21
|
+
readonly message?: never;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Detach and validate an entire probe result before transport.
|
|
25
|
+
* @param result - Runtime probe output
|
|
26
|
+
* @returns Safe tri-state result, or unknown for unsafe runtime data
|
|
27
|
+
*/
|
|
28
|
+
export declare function normalizeProbeResult<T extends JsonValue>(result: ProbeResult<T>): ProbeResult<T>;
|
|
29
|
+
//# sourceMappingURL=ui-status-json.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ui-status-json.d.ts","sourceRoot":"","sources":["../../src/cli/ui-status-json.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAWtD,8EAA8E;AAC9E,MAAM,MAAM,WAAW,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS,IACnD;IACE,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC;IAClB,QAAQ,CAAC,MAAM,CAAC,EAAE,KAAK,CAAC;IACxB,QAAQ,CAAC,OAAO,CAAC,EAAE,KAAK,CAAC;CAC1B,GACD;IACE,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC;CACxB,GACD;IACE,QAAQ,CAAC,KAAK,EAAE,gBAAgB,CAAC;IACjC,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC;IACvB,QAAQ,CAAC,MAAM,CAAC,EAAE,KAAK,CAAC;IACxB,QAAQ,CAAC,OAAO,CAAC,EAAE,KAAK,CAAC;CAC1B,CAAC;AAuMN;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,SAAS,SAAS,EACtD,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,GACrB,WAAW,CAAC,CAAC,CAAC,CAahB"}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
/** Transport budgets prevent status probes from monopolizing the UI process. */
|
|
2
|
+
const MAX_JSON_DEPTH = 64;
|
|
3
|
+
const MAX_JSON_NODES = 10_000;
|
|
4
|
+
/**
|
|
5
|
+
* Require enumerable data without invoking accessors.
|
|
6
|
+
* @param descriptor - Candidate property descriptor
|
|
7
|
+
* @param message - Error text for an unsafe descriptor
|
|
8
|
+
* @returns The descriptor's inert data value
|
|
9
|
+
*/
|
|
10
|
+
function requireData(descriptor, message) {
|
|
11
|
+
if (descriptor === undefined ||
|
|
12
|
+
!descriptor.enumerable ||
|
|
13
|
+
!("value" in descriptor)) {
|
|
14
|
+
throw new TypeError(message);
|
|
15
|
+
}
|
|
16
|
+
return descriptor.value;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Clone one JSON array without invoking accessors or custom hooks.
|
|
20
|
+
* @param value - Candidate array
|
|
21
|
+
* @param ancestors - Active recursion path
|
|
22
|
+
* @param depth - Current tree depth
|
|
23
|
+
* @param budget - Remaining traversal budget
|
|
24
|
+
* @returns Detached JSON array
|
|
25
|
+
*/
|
|
26
|
+
function cloneArray(value, ancestors, depth, budget) {
|
|
27
|
+
if (value.length > budget.nodesRemaining) {
|
|
28
|
+
throw new TypeError("Probe value exceeds the JSON node limit");
|
|
29
|
+
}
|
|
30
|
+
const allowedKeys = new Set([
|
|
31
|
+
"length",
|
|
32
|
+
...Array.from({ length: value.length }, (_entry, index) => String(index)),
|
|
33
|
+
]);
|
|
34
|
+
if (Reflect.ownKeys(value).some(key => typeof key !== "string" || !allowedKeys.has(key))) {
|
|
35
|
+
throw new TypeError("Probe arrays must contain only indexed JSON data");
|
|
36
|
+
}
|
|
37
|
+
const descriptors = Object.getOwnPropertyDescriptors(value);
|
|
38
|
+
return Array.from({ length: value.length }, (_entry, index) => cloneJsonValue(requireData(descriptors[String(index)], "Probe arrays cannot contain holes or accessors"), ancestors, depth, budget));
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Clone one plain JSON object without invoking accessors or custom hooks.
|
|
42
|
+
* @param value - Candidate object
|
|
43
|
+
* @param ancestors - Active recursion path
|
|
44
|
+
* @param depth - Current tree depth
|
|
45
|
+
* @param budget - Remaining traversal budget
|
|
46
|
+
* @returns Detached JSON object
|
|
47
|
+
*/
|
|
48
|
+
function cloneObject(value, ancestors, depth, budget) {
|
|
49
|
+
const prototype = Object.getPrototypeOf(value);
|
|
50
|
+
if (prototype !== Object.prototype && prototype !== null) {
|
|
51
|
+
throw new TypeError("Probe objects must use a plain object prototype");
|
|
52
|
+
}
|
|
53
|
+
const descriptors = Object.getOwnPropertyDescriptors(value);
|
|
54
|
+
const entries = Reflect.ownKeys(value).map(key => {
|
|
55
|
+
if (typeof key !== "string") {
|
|
56
|
+
throw new TypeError("Probe objects cannot contain symbol properties");
|
|
57
|
+
}
|
|
58
|
+
return [
|
|
59
|
+
key,
|
|
60
|
+
cloneJsonValue(requireData(descriptors[key], "Probe objects cannot contain hidden properties or accessors"), ancestors, depth, budget),
|
|
61
|
+
];
|
|
62
|
+
});
|
|
63
|
+
return Object.fromEntries(entries);
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Clone a scalar supported by JSON.
|
|
67
|
+
* @param value - Candidate scalar
|
|
68
|
+
* @returns Valid JSON scalar
|
|
69
|
+
*/
|
|
70
|
+
function cloneScalar(value) {
|
|
71
|
+
if (value === null ||
|
|
72
|
+
typeof value === "string" ||
|
|
73
|
+
typeof value === "boolean" ||
|
|
74
|
+
(typeof value === "number" && Number.isFinite(value))) {
|
|
75
|
+
return value;
|
|
76
|
+
}
|
|
77
|
+
throw new TypeError("Probe scalar is not finite or is not JSON data");
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Clone runtime input into a detached JSON data tree.
|
|
81
|
+
* @param value - Candidate value
|
|
82
|
+
* @param ancestors - Active recursion path
|
|
83
|
+
* @param depth - Current tree depth
|
|
84
|
+
* @param budget - Remaining traversal budget
|
|
85
|
+
* @returns Detached JSON data
|
|
86
|
+
*/
|
|
87
|
+
function cloneJsonValue(value, ancestors = [], depth = 0, budget = { nodesRemaining: MAX_JSON_NODES }) {
|
|
88
|
+
if (depth > MAX_JSON_DEPTH) {
|
|
89
|
+
throw new TypeError("Probe value exceeds the JSON depth limit");
|
|
90
|
+
}
|
|
91
|
+
if (budget.nodesRemaining <= 0) {
|
|
92
|
+
throw new TypeError("Probe value exceeds the JSON node limit");
|
|
93
|
+
}
|
|
94
|
+
// eslint-disable-next-line functional/immutable-data -- one private counter bounds a single traversal
|
|
95
|
+
budget.nodesRemaining -= 1;
|
|
96
|
+
if (typeof value !== "object" || value === null) {
|
|
97
|
+
return cloneScalar(value);
|
|
98
|
+
}
|
|
99
|
+
if (ancestors.includes(value)) {
|
|
100
|
+
throw new TypeError("Probe value is cyclic");
|
|
101
|
+
}
|
|
102
|
+
const next = [...ancestors, value];
|
|
103
|
+
return Array.isArray(value)
|
|
104
|
+
? cloneArray(value, next, depth + 1, budget)
|
|
105
|
+
: cloneObject(value, next, depth + 1, budget);
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Validate an exact set of own keys on a detached object.
|
|
109
|
+
* @param value - Detached object
|
|
110
|
+
* @param expected - Required unique keys
|
|
111
|
+
* @returns True when no key is missing or extra
|
|
112
|
+
*/
|
|
113
|
+
function hasExactKeys(value, expected) {
|
|
114
|
+
const actual = Object.keys(value);
|
|
115
|
+
return (actual.length === expected.length &&
|
|
116
|
+
expected.every(key => Object.hasOwn(value, key)));
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Convert a detached JSON tree back into the strict result union.
|
|
120
|
+
* @param value - Detached JSON tree
|
|
121
|
+
* @returns Strict tri-state result
|
|
122
|
+
*/
|
|
123
|
+
function parseResult(value) {
|
|
124
|
+
if (value === null || Array.isArray(value) || typeof value !== "object") {
|
|
125
|
+
throw new TypeError("Probe result must be a plain object");
|
|
126
|
+
}
|
|
127
|
+
if (value.state === "value" && hasExactKeys(value, ["state", "value"])) {
|
|
128
|
+
return { state: "value", value: value.value };
|
|
129
|
+
}
|
|
130
|
+
if (value.state === "unknown" &&
|
|
131
|
+
hasExactKeys(value, ["message", "reason", "state"]) &&
|
|
132
|
+
typeof value.reason === "string" &&
|
|
133
|
+
value.reason.trim().length > 0 &&
|
|
134
|
+
typeof value.message === "string" &&
|
|
135
|
+
value.message.trim().length > 0) {
|
|
136
|
+
return { state: "unknown", reason: value.reason, message: value.message };
|
|
137
|
+
}
|
|
138
|
+
if (value.state === "not-applicable" && hasExactKeys(value, ["state"])) {
|
|
139
|
+
return { state: "not-applicable" };
|
|
140
|
+
}
|
|
141
|
+
throw new TypeError("Probe result does not match the tri-state contract");
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Detach and validate an entire probe result before transport.
|
|
145
|
+
* @param result - Runtime probe output
|
|
146
|
+
* @returns Safe tri-state result, or unknown for unsafe runtime data
|
|
147
|
+
*/
|
|
148
|
+
export function normalizeProbeResult(result) {
|
|
149
|
+
try {
|
|
150
|
+
return parseResult(cloneJsonValue(result));
|
|
151
|
+
}
|
|
152
|
+
catch (error) {
|
|
153
|
+
return {
|
|
154
|
+
state: "unknown",
|
|
155
|
+
reason: "non-serializable-value",
|
|
156
|
+
message: error instanceof Error
|
|
157
|
+
? `Probe returned unsafe JSON data: ${error.message}`
|
|
158
|
+
: "Probe returned unreadable data",
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
//# sourceMappingURL=ui-status-json.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ui-status-json.js","sourceRoot":"","sources":["../../src/cli/ui-status-json.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { JsonValue } from "../sync/json-path.js";
|
|
2
|
+
import { type ProbeResult } from "./ui-status-json.js";
|
|
3
|
+
export type { ProbeResult } from "./ui-status-json.js";
|
|
4
|
+
/** One bounded, independently executable live-status probe. */
|
|
5
|
+
export interface StatusProbe<T extends JsonValue = JsonValue> {
|
|
6
|
+
/** Stable identifier used as the status endpoint's object key. */
|
|
7
|
+
readonly id: string;
|
|
8
|
+
/** Abort-aware operation returning an explicit tri-state result. */
|
|
9
|
+
readonly run: (signal: AbortSignal) => Promise<ProbeResult<T>>;
|
|
10
|
+
/** Maximum time the status endpoint will await this probe. */
|
|
11
|
+
readonly timeoutMs: number;
|
|
12
|
+
}
|
|
13
|
+
/** Injectable check used by the reference GitHub authentication probe. */
|
|
14
|
+
export type GithubAuthCheck = (cwd: string, timeoutMs: number, signal: AbortSignal, hostname: string) => Promise<"authenticated" | "not-authenticated">;
|
|
15
|
+
/** Injectable effective-origin reader used by the GitHub reference probe. */
|
|
16
|
+
export type GitRemoteReader = (cwd: string, timeoutMs: number, signal: AbortSignal) => Promise<string>;
|
|
17
|
+
/**
|
|
18
|
+
* Run one probe without allowing it to block siblings or fabricate data.
|
|
19
|
+
* @param probe - Probe to execute
|
|
20
|
+
* @returns Explicit result, or unknown for invalid input, failure, or timeout
|
|
21
|
+
*/
|
|
22
|
+
export declare function runProbe<T extends JsonValue>(probe: StatusProbe<T>): Promise<ProbeResult<T>>;
|
|
23
|
+
/**
|
|
24
|
+
* Create the reference GitHub authentication probe.
|
|
25
|
+
* @param cwd - Project root used as the command working directory
|
|
26
|
+
* @param check - Injectable command check used by focused tests
|
|
27
|
+
* @param readRemote - Injectable effective-origin reader used by focused tests
|
|
28
|
+
* @returns Reference probe for the live-status transport
|
|
29
|
+
*/
|
|
30
|
+
export declare function createGithubAuthProbe(cwd: string, check?: GithubAuthCheck, readRemote?: GitRemoteReader): StatusProbe<boolean>;
|
|
31
|
+
/**
|
|
32
|
+
* Validate probe keys before binding a server so status snapshots cannot lose data.
|
|
33
|
+
* @param probes - Registered status probes
|
|
34
|
+
*/
|
|
35
|
+
export declare function validateStatusProbes(probes: readonly StatusProbe[]): void;
|
|
36
|
+
/**
|
|
37
|
+
* Execute all probes concurrently, with failures isolated per probe.
|
|
38
|
+
* @param probes - Probes to execute
|
|
39
|
+
* @returns Results keyed by stable probe identifier
|
|
40
|
+
*/
|
|
41
|
+
export declare function readStatusSnapshot(probes: readonly StatusProbe[]): Promise<Record<string, ProbeResult>>;
|
|
42
|
+
//# sourceMappingURL=ui-status.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ui-status.d.ts","sourceRoot":"","sources":["../../src/cli/ui-status.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAwB,KAAK,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAC7E,YAAY,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAEvD,+DAA+D;AAC/D,MAAM,WAAW,WAAW,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS;IAC1D,kEAAkE;IAClE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,oEAAoE;IACpE,QAAQ,CAAC,GAAG,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/D,8DAA8D;IAC9D,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED,0EAA0E;AAC1E,MAAM,MAAM,eAAe,GAAG,CAC5B,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,WAAW,EACnB,QAAQ,EAAE,MAAM,KACb,OAAO,CAAC,eAAe,GAAG,mBAAmB,CAAC,CAAC;AAEpD,6EAA6E;AAC7E,MAAM,MAAM,eAAe,GAAG,CAC5B,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,WAAW,KAChB,OAAO,CAAC,MAAM,CAAC,CAAC;AAyCrB;;;;GAIG;AACH,wBAAsB,QAAQ,CAAC,CAAC,SAAS,SAAS,EAChD,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC,GACpB,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAiCzB;AA6HD;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,MAAM,EACX,KAAK,GAAE,eAAqC,EAC5C,UAAU,GAAE,eAAkC,GAC7C,WAAW,CAAC,OAAO,CAAC,CAkBtB;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,WAAW,EAAE,GAAG,IAAI,CASzE;AAED;;;;GAIG;AACH,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,SAAS,WAAW,EAAE,GAC7B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAKtC"}
|