@parity-app/cli 0.5.0 → 0.5.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/bin.mjs +7 -6
- package/dist/{client-DgpoM3e7.mjs → client-CoW-KcnT.mjs} +47 -130
- package/dist/index.d.mts +1 -0
- package/dist/index.mjs +1 -1
- package/dist/schema-BpGSCLEu.mjs +113 -0
- package/dist/{src-D85OVBQL.mjs → src-5CrSA_RX.mjs} +1 -1
- package/dist/{src-BryimTPw.mjs → src-C4faIpux.mjs} +10 -0
- package/dist/{src-BwTWa2_Y.mjs → src-Cr8pfFJE.mjs} +1 -1
- package/dist/{src-CpoDOrn3.mjs → src-Zm_PYFFH.mjs} +2 -2
- package/dist/{src-CqmC2-Em.mjs → src-p0vFxRBz.mjs} +3 -3
- package/package.json +3 -2
- package/skills/execute.md +16 -1
- package/skills/guide/checking.md +2 -1
package/dist/bin.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
2
|
+
import { a as errorCodes, i as closest, o as errorDetails, r as CodedError, s as readErrorDetails } from "./schema-BpGSCLEu.mjs";
|
|
3
|
+
import { a as describeExec, c as describeProps, f as setCaller, i as describeConsole, l as describeStatus, n as describeAccessibility, o as describeModes, p as mcpCallerName, r as describeComponents, s as describeProblems, t as call, u as describeTokens } from "./client-CoW-KcnT.mjs";
|
|
3
4
|
import { mkdir, readFile, readdir, writeFile } from "node:fs/promises";
|
|
4
5
|
import { dirname, join, normalize, relative, resolve, sep } from "node:path";
|
|
5
6
|
import { parseArgs } from "node:util";
|
|
@@ -386,8 +387,8 @@ const executeOperation = {
|
|
|
386
387
|
*/
|
|
387
388
|
async function runCheck(library, options) {
|
|
388
389
|
if (!library) throw new Error("parity lib check <library> [--tab t] [--mode m]");
|
|
389
|
-
const { applyLibraryEdits, componentNode, generateId, librarySource, parseLibraryEdits, withLibraryContext } = await import("./src-
|
|
390
|
-
const { registryDir, registryEntries } = await import("./src-
|
|
390
|
+
const { applyLibraryEdits, componentNode, generateId, librarySource, parseLibraryEdits, withLibraryContext } = await import("./src-p0vFxRBz.mjs");
|
|
391
|
+
const { registryDir, registryEntries } = await import("./src-Cr8pfFJE.mjs");
|
|
391
392
|
const entry = (await registryEntries()).find((item) => item.manifest.id === library);
|
|
392
393
|
if (!entry) throw new Error(`The registry has no library "${library}"`);
|
|
393
394
|
let manifest = entry.manifest;
|
|
@@ -515,8 +516,8 @@ function describeCheck(report) {
|
|
|
515
516
|
* because it reads the project's files and its own copy of TypeScript.
|
|
516
517
|
*/
|
|
517
518
|
async function runLib(packageName, options) {
|
|
518
|
-
const { appManifestPath, generateLibrary, manifestText, mergeManifest, reviseLibrary } = await import("./src-
|
|
519
|
-
const { covers, registryDir, registryEntries } = await import("./src-
|
|
519
|
+
const { appManifestPath, generateLibrary, manifestText, mergeManifest, reviseLibrary } = await import("./src-Zm_PYFFH.mjs");
|
|
520
|
+
const { covers, registryDir, registryEntries } = await import("./src-Cr8pfFJE.mjs");
|
|
520
521
|
const spec = packageName === void 0 ? void 0 : packageSpec(packageName);
|
|
521
522
|
let root = resolve(options.root ?? ".");
|
|
522
523
|
if (spec && (spec.version !== void 0 || options.registry && !options.root)) {
|
|
@@ -527,7 +528,7 @@ async function runLib(packageName, options) {
|
|
|
527
528
|
console.error(`Installing ${spec.name} ${version} on its own…`);
|
|
528
529
|
root = await installedVersion(spec.name, version);
|
|
529
530
|
}
|
|
530
|
-
const { parseLibraryEdits } = await import("./src-
|
|
531
|
+
const { parseLibraryEdits } = await import("./src-Zm_PYFFH.mjs");
|
|
531
532
|
const trialEdits = options.edits ? parseLibraryEdits(JSON.parse(await readFile(resolve(options.edits), "utf8"))) : void 0;
|
|
532
533
|
const recordedId = options.registry && spec ? options.id ?? (await registryEntries()).find((entry) => entry.manifest.package?.name === spec.name)?.manifest.id : void 0;
|
|
533
534
|
const appErrors = recordedId ? await readAppErrors(registryDir(), recordedId) : void 0;
|
|
@@ -1,35 +1,38 @@
|
|
|
1
|
+
import { c as unknownReference, n as nonBlankString, r as CodedError, s as readErrorDetails, t as jsonText } from "./schema-BpGSCLEu.mjs";
|
|
1
2
|
import { join } from "node:path";
|
|
2
3
|
import { randomUUID } from "node:crypto";
|
|
3
4
|
import { readFileSync, readdirSync, realpathSync, rmSync } from "node:fs";
|
|
4
5
|
import { homedir } from "node:os";
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
// ../agent/src/routing.ts
|
|
8
|
+
/**
|
|
9
|
+
* Which running copy of Parity an agent's call goes to (PAR-514). Several copies can run at once, each with its own
|
|
10
|
+
* projects open: the person's app, a dev session, `pnpm perf`. Agents care about the project, not the copy, so every
|
|
11
|
+
* call is sent to the copy that has its project open. The CLI decides, once, with these rules, and sends that copy the
|
|
12
|
+
* exact tab it chose; the app matches a tab reference with the same `matchTab`. Nothing here touches files or the
|
|
13
|
+
* network, so the app's renderer can use it too.
|
|
14
|
+
*/
|
|
15
|
+
/** How to reach one running copy: what it writes to its registry entry. A number an entry lacks reads as 0. */
|
|
16
|
+
const copyEntry = z.object({
|
|
17
|
+
version: z.number().catch(0),
|
|
18
|
+
url: z.string(),
|
|
19
|
+
token: z.string(),
|
|
20
|
+
/** The app's main process, which names the copy and its entry. A service the app restarts is the same copy. */
|
|
21
|
+
app: z.number(),
|
|
22
|
+
/** When the copy started, in milliseconds since the epoch. A project open in two copies goes to the older one. */
|
|
23
|
+
startedAt: z.number().catch(0)
|
|
24
|
+
});
|
|
25
|
+
/** An entry's text. The file from before the registry names the app's main process `pid`. */
|
|
26
|
+
const entryText = jsonText(copyEntry.extend({
|
|
27
|
+
app: z.number().optional().catch(void 0),
|
|
28
|
+
pid: z.number().optional().catch(void 0)
|
|
29
|
+
}).transform(({ app, pid, ...entry }) => ({
|
|
30
|
+
...entry,
|
|
31
|
+
app: app ?? pid ?? 0
|
|
32
|
+
})));
|
|
5
33
|
/** Reads a registry entry's text, or nothing when it isn't one. A file from before the registry stands for its copy. */
|
|
6
34
|
function readCopyEntry(text) {
|
|
7
|
-
|
|
8
|
-
let value;
|
|
9
|
-
try {
|
|
10
|
-
value = JSON.parse(text);
|
|
11
|
-
} catch {
|
|
12
|
-
return;
|
|
13
|
-
}
|
|
14
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
15
|
-
const fields = new Map(Object.entries(value));
|
|
16
|
-
const [version, url, token, app, pid, startedAt] = [
|
|
17
|
-
"version",
|
|
18
|
-
"url",
|
|
19
|
-
"token",
|
|
20
|
-
"app",
|
|
21
|
-
"pid",
|
|
22
|
-
"startedAt"
|
|
23
|
-
].map((key) => fields.get(key));
|
|
24
|
-
if (typeof url !== "string" || typeof token !== "string") return void 0;
|
|
25
|
-
const number = (field) => typeof field === "number" ? field : void 0;
|
|
26
|
-
return {
|
|
27
|
-
version: number(version) ?? 0,
|
|
28
|
-
url,
|
|
29
|
-
token,
|
|
30
|
-
app: number(app) ?? number(pid) ?? 0,
|
|
31
|
-
startedAt: number(startedAt) ?? 0
|
|
32
|
-
};
|
|
35
|
+
return entryText.safeParse(text).data;
|
|
33
36
|
}
|
|
34
37
|
/**
|
|
35
38
|
* A project folder as routing compares it: forward slashes, no trailing slash, and on Windows (a drive letter or a
|
|
@@ -160,15 +163,21 @@ function byAge(a, b) {
|
|
|
160
163
|
return a.entry.startedAt - b.entry.startedAt || a.entry.app - b.entry.app;
|
|
161
164
|
}
|
|
162
165
|
// ../agent/src/registry.ts
|
|
166
|
+
/** The settings that place the registry. One that's blank counts as unset. */
|
|
167
|
+
const registrySettings = z.object({
|
|
168
|
+
PARITY_AGENT_FILE: nonBlankString.optional().catch(void 0),
|
|
169
|
+
PARITY_AGENT_DIR: nonBlankString.optional().catch(void 0)
|
|
170
|
+
});
|
|
163
171
|
/** The registry these settings name: `PARITY_AGENT_FILE`, else `PARITY_AGENT_DIR`, else `~/.parity/agents`. */
|
|
164
172
|
function agentRegistry(env, home) {
|
|
165
|
-
|
|
173
|
+
const { PARITY_AGENT_FILE: file, PARITY_AGENT_DIR: folder } = registrySettings.parse(env);
|
|
174
|
+
if (file) return {
|
|
166
175
|
kind: "file",
|
|
167
|
-
path:
|
|
176
|
+
path: file
|
|
168
177
|
};
|
|
169
178
|
return {
|
|
170
179
|
kind: "folder",
|
|
171
|
-
path:
|
|
180
|
+
path: folder ?? join(home, ".parity", "agents")
|
|
172
181
|
};
|
|
173
182
|
}
|
|
174
183
|
/** The file before the registry, where an app from before it says how to reach it. */
|
|
@@ -221,105 +230,10 @@ function readText(path) {
|
|
|
221
230
|
return;
|
|
222
231
|
}
|
|
223
232
|
}
|
|
224
|
-
// ../core/src/errors.ts
|
|
225
|
-
/**
|
|
226
|
-
* Why an agent's call failed, as a stable code it can act on without reading the message. The CLI and MCP publish
|
|
227
|
-
* these; the app throws them where it knows the cause.
|
|
228
|
-
*/
|
|
229
|
-
const errorCodes = [
|
|
230
|
-
"invalid_input",
|
|
231
|
-
"not_running",
|
|
232
|
-
"not_answering",
|
|
233
|
-
"unknown_tab",
|
|
234
|
-
"tab_not_ready",
|
|
235
|
-
"unknown_design",
|
|
236
|
-
"unknown_node",
|
|
237
|
-
"ambiguous_reference",
|
|
238
|
-
"unknown_state",
|
|
239
|
-
"unknown_mode",
|
|
240
|
-
"unknown_viewport",
|
|
241
|
-
"unknown_component",
|
|
242
|
-
"unknown_icon_set",
|
|
243
|
-
"unknown_edit_id",
|
|
244
|
-
"conflict",
|
|
245
|
-
"execution_failed",
|
|
246
|
-
"app_error"
|
|
247
|
-
];
|
|
248
|
-
/** An error with a stable code, the field it's about and what to use instead. */
|
|
249
|
-
var CodedError = class extends Error {
|
|
250
|
-
details;
|
|
251
|
-
constructor(message, details) {
|
|
252
|
-
super(message);
|
|
253
|
-
this.name = "CodedError";
|
|
254
|
-
this.details = {
|
|
255
|
-
...details,
|
|
256
|
-
retryable: details.retryable ?? false
|
|
257
|
-
};
|
|
258
|
-
}
|
|
259
|
-
};
|
|
260
|
-
/** An unknown reference, naming the valid ones closest to what was asked for, up to `alternativeLimit`. */
|
|
261
|
-
function unknownReference(code, message, reference, candidates, field) {
|
|
262
|
-
return new CodedError(message, {
|
|
263
|
-
code,
|
|
264
|
-
...field === void 0 ? {} : { field },
|
|
265
|
-
alternatives: closest(reference, candidates)
|
|
266
|
-
});
|
|
267
|
-
}
|
|
268
|
-
/**
|
|
269
|
-
* Candidates sharing text with the reference first, ignoring case, then the rest by how few single-character edits
|
|
270
|
-
* away they are, so a typo's intended id makes the cut; ties keep their own order. All of them when they fit.
|
|
271
|
-
*/
|
|
272
|
-
function closest(reference, candidates, limit = 20) {
|
|
273
|
-
const unique = [...new Set(candidates)];
|
|
274
|
-
if (unique.length <= limit) return unique;
|
|
275
|
-
const wanted = reference.toLowerCase();
|
|
276
|
-
const ranked = unique.map((candidate, index) => {
|
|
277
|
-
const lower = candidate.toLowerCase();
|
|
278
|
-
const near = wanted.length > 0 && (lower.includes(wanted) || wanted.includes(lower));
|
|
279
|
-
return {
|
|
280
|
-
candidate,
|
|
281
|
-
index,
|
|
282
|
-
near: near ? 0 : 1,
|
|
283
|
-
distance: near ? 0 : editDistance(wanted, lower)
|
|
284
|
-
};
|
|
285
|
-
});
|
|
286
|
-
ranked.sort((a, b) => a.near - b.near || a.distance - b.distance || a.index - b.index);
|
|
287
|
-
return ranked.slice(0, limit).map(({ candidate }) => candidate);
|
|
288
|
-
}
|
|
289
|
-
/** How many single-character insertions, deletions or substitutions turn one string into the other. */
|
|
290
|
-
function editDistance(a, b) {
|
|
291
|
-
let previous = Array.from({ length: b.length + 1 }, (_, index) => index);
|
|
292
|
-
for (let i = 1; i <= a.length; i++) {
|
|
293
|
-
const row = [i];
|
|
294
|
-
for (let j = 1; j <= b.length; j++) row[j] = Math.min(previous[j] + 1, row[j - 1] + 1, previous[j - 1] + (a[i - 1] === b[j - 1] ? 0 : 1));
|
|
295
|
-
previous = row;
|
|
296
|
-
}
|
|
297
|
-
return previous[b.length];
|
|
298
|
-
}
|
|
299
|
-
/** A thrown value's details, when it carries them. */
|
|
300
|
-
function errorDetails(error) {
|
|
301
|
-
return error instanceof CodedError ? error.details : void 0;
|
|
302
|
-
}
|
|
303
|
-
/** Details that came from another process, checked before they're trusted. Anything malformed reads as none. */
|
|
304
|
-
function readErrorDetails(value) {
|
|
305
|
-
if (!value || typeof value !== "object") return void 0;
|
|
306
|
-
const code = "code" in value ? value.code : void 0;
|
|
307
|
-
const known = errorCodes.find((candidate) => candidate === code);
|
|
308
|
-
if (!known) return void 0;
|
|
309
|
-
const retryable = "retryable" in value && value.retryable === true;
|
|
310
|
-
const field = "field" in value && typeof value.field === "string" && value.field ? value.field : void 0;
|
|
311
|
-
const alternatives = "alternatives" in value && Array.isArray(value.alternatives) ? value.alternatives.filter((item) => typeof item === "string").slice(0, 20) : void 0;
|
|
312
|
-
return {
|
|
313
|
-
code: known,
|
|
314
|
-
retryable,
|
|
315
|
-
...field === void 0 ? {} : { field },
|
|
316
|
-
...alternatives === void 0 ? {} : { alternatives }
|
|
317
|
-
};
|
|
318
|
-
}
|
|
319
233
|
// src/caller.ts
|
|
320
234
|
/** Declared caller names are displayed verbatim apart from surrounding whitespace. */
|
|
321
235
|
function declaredName(value) {
|
|
322
|
-
return
|
|
236
|
+
return nonBlankString.safeParse(value).data;
|
|
323
237
|
}
|
|
324
238
|
/** Reserve the session suffix inside the desktop boundary's 80-character caller-id limit. */
|
|
325
239
|
function sessionCallerId(name, session) {
|
|
@@ -405,10 +319,13 @@ async function runningCopies() {
|
|
|
405
319
|
report
|
|
406
320
|
}] : [];
|
|
407
321
|
}))).flat();
|
|
408
|
-
if (entries.length > 0 && copies.length === 0)
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
322
|
+
if (entries.length > 0 && copies.length === 0) {
|
|
323
|
+
const where = entries.map((entry) => entry.url).join(", ");
|
|
324
|
+
throw new CodedError(`Parity isn't answering at ${where}. Is the app still running?`, {
|
|
325
|
+
code: "not_answering",
|
|
326
|
+
retryable: true
|
|
327
|
+
});
|
|
328
|
+
}
|
|
412
329
|
if (copies.length === 0) throw new CodedError(`Parity isn't running (nothing in ${registry.path}). Start the app, then try again.`, {
|
|
413
330
|
code: "not_running",
|
|
414
331
|
retryable: true
|
|
@@ -793,4 +710,4 @@ function scriptPath(url) {
|
|
|
793
710
|
return url || "an unknown script";
|
|
794
711
|
}
|
|
795
712
|
}
|
|
796
|
-
export {
|
|
713
|
+
export { describeExec as a, describeProps as c, registry as d, setCaller as f, describeConsole as i, describeStatus as l, describeAccessibility as n, describeModes as o, mcpCallerName as p, describeComponents as r, describeProblems as s, call as t, describeTokens as u };
|
package/dist/index.d.mts
CHANGED
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { t as call, n as describeAccessibility, r as describeComponents, i as describeConsole, a as describeExec, o as describeModes, s as describeProblems, c as describeProps, l as describeStatus, u as describeTokens, d as registry, f as setCaller } from "./client-
|
|
1
|
+
export { t as call, n as describeAccessibility, r as describeComponents, i as describeConsole, a as describeExec, o as describeModes, s as describeProblems, c as describeProps, l as describeStatus, u as describeTokens, d as registry, f as setCaller } from "./client-CoW-KcnT.mjs";
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
// ../core/src/errors.ts
|
|
3
|
+
/**
|
|
4
|
+
* Why an agent's call failed, as a stable code it can act on without reading the message. The CLI and MCP publish
|
|
5
|
+
* these; the app throws them where it knows the cause.
|
|
6
|
+
*/
|
|
7
|
+
const errorCodes = [
|
|
8
|
+
"invalid_input",
|
|
9
|
+
"not_running",
|
|
10
|
+
"not_answering",
|
|
11
|
+
"unknown_tab",
|
|
12
|
+
"tab_not_ready",
|
|
13
|
+
"unknown_design",
|
|
14
|
+
"unknown_node",
|
|
15
|
+
"ambiguous_reference",
|
|
16
|
+
"unknown_state",
|
|
17
|
+
"unknown_mode",
|
|
18
|
+
"unknown_viewport",
|
|
19
|
+
"unknown_component",
|
|
20
|
+
"unknown_icon_set",
|
|
21
|
+
"unknown_edit_id",
|
|
22
|
+
"conflict",
|
|
23
|
+
"execution_failed",
|
|
24
|
+
"app_error"
|
|
25
|
+
];
|
|
26
|
+
/** Details as another process sends them. Each field that's malformed falls back on its own; only the code must hold. */
|
|
27
|
+
const errorDetailsSchema = z.object({
|
|
28
|
+
code: z.enum(errorCodes),
|
|
29
|
+
/** Whether sending the same request again, unchanged, can succeed. */
|
|
30
|
+
retryable: z.boolean().catch(false),
|
|
31
|
+
/** The request field at fault, as a path: `design`, `state`, `edits/0/find`. */
|
|
32
|
+
field: z.string().min(1).optional().catch(void 0),
|
|
33
|
+
/** Valid references to use instead of an unknown or ambiguous one, at most `alternativeLimit` of them. */
|
|
34
|
+
alternatives: z.array(z.unknown()).transform((items) => items.filter((item) => typeof item === "string").slice(0, 20)).optional().catch(void 0)
|
|
35
|
+
});
|
|
36
|
+
/** An error with a stable code, the field it's about and what to use instead. */
|
|
37
|
+
var CodedError = class extends Error {
|
|
38
|
+
details;
|
|
39
|
+
constructor(message, details) {
|
|
40
|
+
super(message);
|
|
41
|
+
this.name = "CodedError";
|
|
42
|
+
this.details = {
|
|
43
|
+
...details,
|
|
44
|
+
retryable: details.retryable ?? false
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
/** An unknown reference, naming the valid ones closest to what was asked for, up to `alternativeLimit`. */
|
|
49
|
+
function unknownReference(code, message, reference, candidates, field) {
|
|
50
|
+
return new CodedError(message, {
|
|
51
|
+
code,
|
|
52
|
+
...field === void 0 ? {} : { field },
|
|
53
|
+
alternatives: closest(reference, candidates)
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Candidates sharing text with the reference first, ignoring case, then the rest by how few single-character edits
|
|
58
|
+
* away they are, so a typo's intended id makes the cut; ties keep their own order. All of them when they fit.
|
|
59
|
+
*/
|
|
60
|
+
function closest(reference, candidates, limit = 20) {
|
|
61
|
+
const unique = [...new Set(candidates)];
|
|
62
|
+
if (unique.length <= limit) return unique;
|
|
63
|
+
const wanted = reference.toLowerCase();
|
|
64
|
+
const ranked = unique.map((candidate, index) => {
|
|
65
|
+
const lower = candidate.toLowerCase();
|
|
66
|
+
const near = wanted.length > 0 && (lower.includes(wanted) || wanted.includes(lower));
|
|
67
|
+
return {
|
|
68
|
+
candidate,
|
|
69
|
+
index,
|
|
70
|
+
near: near ? 0 : 1,
|
|
71
|
+
distance: near ? 0 : editDistance(wanted, lower)
|
|
72
|
+
};
|
|
73
|
+
});
|
|
74
|
+
ranked.sort((a, b) => a.near - b.near || a.distance - b.distance || a.index - b.index);
|
|
75
|
+
return ranked.slice(0, limit).map(({ candidate }) => candidate);
|
|
76
|
+
}
|
|
77
|
+
/** How many single-character insertions, deletions or substitutions turn one string into the other. */
|
|
78
|
+
function editDistance(a, b) {
|
|
79
|
+
let previous = Array.from({ length: b.length + 1 }, (_, index) => index);
|
|
80
|
+
for (let i = 1; i <= a.length; i++) {
|
|
81
|
+
const row = [i];
|
|
82
|
+
for (let j = 1; j <= b.length; j++) row[j] = Math.min(previous[j] + 1, row[j - 1] + 1, previous[j - 1] + (a[i - 1] === b[j - 1] ? 0 : 1));
|
|
83
|
+
previous = row;
|
|
84
|
+
}
|
|
85
|
+
return previous[b.length];
|
|
86
|
+
}
|
|
87
|
+
/** A thrown value's details, when it carries them. */
|
|
88
|
+
function errorDetails(error) {
|
|
89
|
+
return error instanceof CodedError ? error.details : void 0;
|
|
90
|
+
}
|
|
91
|
+
/** Details that came from another process, checked before they're trusted. Anything malformed reads as none. */
|
|
92
|
+
function readErrorDetails(value) {
|
|
93
|
+
return errorDetailsSchema.safeParse(value).data;
|
|
94
|
+
}
|
|
95
|
+
z.record(z.string(), z.unknown());
|
|
96
|
+
/** Text with something besides whitespace, trimmed. */
|
|
97
|
+
const nonBlankString = z.string().trim().min(1, "can't be blank");
|
|
98
|
+
z.number();
|
|
99
|
+
/** JSON text holding what `schema` checks. Text that isn't JSON fails as `expected JSON`. */
|
|
100
|
+
function jsonText(schema) {
|
|
101
|
+
return z.string().transform((text, context) => {
|
|
102
|
+
try {
|
|
103
|
+
return JSON.parse(text);
|
|
104
|
+
} catch {
|
|
105
|
+
context.addIssue({
|
|
106
|
+
code: "custom",
|
|
107
|
+
message: "expected JSON"
|
|
108
|
+
});
|
|
109
|
+
return z.NEVER;
|
|
110
|
+
}
|
|
111
|
+
}).pipe(schema);
|
|
112
|
+
}
|
|
113
|
+
export { errorCodes as a, unknownReference as c, closest as i, nonBlankString as n, errorDetails as o, CodedError as r, readErrorDetails as s, jsonText as t };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { p as parseLibraryManifest, u as libraryManifestExtension } from "./src-
|
|
1
|
+
import { p as parseLibraryManifest, u as libraryManifestExtension } from "./src-C4faIpux.mjs";
|
|
2
2
|
import { createRequire } from "node:module";
|
|
3
3
|
import { readFile, readdir } from "node:fs/promises";
|
|
4
4
|
import { dirname, join } from "node:path";
|
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
import "./schema-BpGSCLEu.mjs";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
// ../core/src/adapters.ts
|
|
4
|
+
const packageVersions = z.record(z.string(), z.string());
|
|
5
|
+
z.looseObject({
|
|
6
|
+
name: z.string().optional(),
|
|
7
|
+
dependencies: packageVersions.optional(),
|
|
8
|
+
devDependencies: packageVersions.optional(),
|
|
9
|
+
scripts: z.record(z.string(), z.string()).optional()
|
|
10
|
+
});
|
|
1
11
|
// ../core/src/devices.ts
|
|
2
12
|
const deviceKinds = [
|
|
3
13
|
"phone",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { t as covers, n as registryDir, r as registryEntries } from "./src-
|
|
1
|
+
export { t as covers, n as registryDir, r as registryEntries } from "./src-5CrSA_RX.mjs";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { D as collectCustomProperties, a as applyLibraryEdits, c as isSampleElement, f as parseLibraryEdits, j as lengthToPixels, l as isSampleRender, m as renderSlotOf, p as parseLibraryManifest, s as isMadeValue, u as libraryManifestExtension } from "./src-
|
|
2
|
-
import "./src-
|
|
1
|
+
import { D as collectCustomProperties, a as applyLibraryEdits, c as isSampleElement, f as parseLibraryEdits, j as lengthToPixels, l as isSampleRender, m as renderSlotOf, p as parseLibraryManifest, s as isMadeValue, u as libraryManifestExtension } from "./src-C4faIpux.mjs";
|
|
2
|
+
import "./src-5CrSA_RX.mjs";
|
|
3
3
|
import { a as publishedVersions, n as packageFile, o as repositoryFiles, r as publishedSource } from "./published-CdXoUgfD.mjs";
|
|
4
4
|
import { createRequire } from "node:module";
|
|
5
5
|
import { mkdir, readFile, readdir, realpath, rm, stat, writeFile } from "node:fs/promises";
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import "./
|
|
2
|
-
export { a as applyLibraryEdits, t as componentNode, T as generateId, n as librarySource, f as parseLibraryEdits, i as withLibraryContext } from "./src-
|
|
3
|
-
import "./src-
|
|
1
|
+
import "./schema-BpGSCLEu.mjs";
|
|
2
|
+
export { a as applyLibraryEdits, t as componentNode, T as generateId, n as librarySource, f as parseLibraryEdits, i as withLibraryContext } from "./src-C4faIpux.mjs";
|
|
3
|
+
import "./src-Zm_PYFFH.mjs";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@parity-app/cli",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.1",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "Drive the Parity app from a terminal or an agent: read state, run edits, take screenshots, serve MCP.",
|
|
@@ -44,7 +44,8 @@
|
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
46
|
"semver": "^7.8.5",
|
|
47
|
-
"typescript": "6.0.3"
|
|
47
|
+
"typescript": "6.0.3",
|
|
48
|
+
"zod": "4.6.7"
|
|
48
49
|
},
|
|
49
50
|
"devDependencies": {
|
|
50
51
|
"@parity-app/agent": "0.0.0",
|
package/skills/execute.md
CHANGED
|
@@ -89,7 +89,7 @@ SetTokens({ name: value | { theme: value } }): void
|
|
|
89
89
|
|
|
90
90
|
// Checking
|
|
91
91
|
Screenshot(design, { state?, mode?, scale? }?): number
|
|
92
|
-
Measure(design, { state?, mode? }?): Layout
|
|
92
|
+
Measure(design, { state?, mode? }?): Layout // one frame: one state id, one mode id
|
|
93
93
|
Problems(design, { state?, mode? }?): Problem[]
|
|
94
94
|
Accessibility(design, { state?, mode? }?): Finding[]
|
|
95
95
|
|
|
@@ -436,6 +436,21 @@ Print(
|
|
|
436
436
|
)
|
|
437
437
|
```
|
|
438
438
|
|
|
439
|
+
`Measure` takes one state id and one mode id, because it returns one frame's layout. A list, `"all"` or `"shown"` fails
|
|
440
|
+
with `invalid_input`, naming the ids it takes. To measure several frames, call it once for each; every layout says which
|
|
441
|
+
state and mode it drew:
|
|
442
|
+
|
|
443
|
+
```js
|
|
444
|
+
const signup = Designs().find((design) => design.id === "signup")
|
|
445
|
+
const layouts = []
|
|
446
|
+
for (const state of signup.states) {
|
|
447
|
+
for (const mode of [signup.showing.mode, ...signup.showing.beside]) {
|
|
448
|
+
layouts.push(await Measure("signup", { state: state.id, mode }))
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
for (const layout of layouts) Print(`${layout.state} in ${layout.mode}: ${layout.width} × ${layout.height}`)
|
|
452
|
+
```
|
|
453
|
+
|
|
439
454
|
`Accessibility` returns axe-core's findings per node and frame, with the rule, its impact and what's wrong.
|
|
440
455
|
|
|
441
456
|
These frames are drawn in the same window as the canvas's: as wide as the frame, and as tall as the design's fixed
|
package/skills/guide/checking.md
CHANGED
|
@@ -21,7 +21,8 @@ small details.
|
|
|
21
21
|
box. A node that only spills past a parent that doesn't clip still shows, so it isn't listed.
|
|
22
22
|
- **Unknown components.** A name that isn't in `Components()`; it draws as a placeholder.
|
|
23
23
|
|
|
24
|
-
`Measure` gives every node's box in one frame, for checking alignment or sizes by numbers.
|
|
24
|
+
`Measure` gives every node's box in one frame, for checking alignment or sizes by numbers. It takes one state and one
|
|
25
|
+
mode; to compare frames, call it for each, as the execute skill shows.
|
|
25
26
|
|
|
26
27
|
## Accessibility
|
|
27
28
|
|