@jarkkojs/readseek-api 0.11.0 → 0.11.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/README.md +6 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +218 -0
- package/dist/show-presentation.d.ts +15 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -43,6 +43,12 @@ separate extraction step or destination argument. Cache population is an interna
|
|
|
43
43
|
write; reading never invokes inference. Syntax checks return diagnostics even
|
|
44
44
|
when the native process exits 1 (findings); exit 2 is a failure.
|
|
45
45
|
|
|
46
|
+
`presentShowResult()` and `formatShowResult()` provide shared readable output for
|
|
47
|
+
`show_content`, `show_structure`, `show_metadata`, and `show_assets`. Summaries
|
|
48
|
+
identify selections and counts; bodies contain anchored lines, document sections,
|
|
49
|
+
structure trees, fields, or asset paths. Notices identify omitted source ranges
|
|
50
|
+
and how to continue. Formatting never mutates the decoded result.
|
|
51
|
+
|
|
46
52
|
This is a breaking contract: legacy `inspect`/`extract` methods, selectable facets,
|
|
47
53
|
and old command names are removed, not aliased.
|
|
48
54
|
|
package/dist/index.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ export * from "./argv.ts";
|
|
|
5
5
|
export * from "./client.ts";
|
|
6
6
|
export { serializeEditPlan } from "./edit-plan.ts";
|
|
7
7
|
export * from "./hashline.ts";
|
|
8
|
+
export * from "./show-presentation.ts";
|
|
8
9
|
export { READSEEK_BINARY_ENV, READSEEK_PLATFORM_PACKAGES, readSeekBinaryName, readSeekPlatformKey, resolveReadSeekBinaryFromPackages, resolveReadSeekBinaryOverride, resolveReadSeekCacheDir, type ModuleResolver, type ReadSeekCacheOptions, } from "./platform.ts";
|
|
9
10
|
export { canonicalPathKey, expandUserPath, isSubPath, resolveScopedPath, resolveToCwd, } from "./path.ts";
|
|
10
11
|
export { cleanReadSeekErrorText } from "./error.ts";
|
package/dist/index.js
CHANGED
|
@@ -1347,6 +1347,221 @@ function createReadSeekClient(runner) {
|
|
|
1347
1347
|
}
|
|
1348
1348
|
};
|
|
1349
1349
|
}
|
|
1350
|
+
// src/show-presentation.ts
|
|
1351
|
+
function isShowTool(name) {
|
|
1352
|
+
return name === "show_content" || name === "show_structure" || name === "show_metadata" || name === "show_assets";
|
|
1353
|
+
}
|
|
1354
|
+
function record(value) {
|
|
1355
|
+
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
1356
|
+
}
|
|
1357
|
+
function records(value) {
|
|
1358
|
+
return Array.isArray(value) ? value.map(record) : [];
|
|
1359
|
+
}
|
|
1360
|
+
function text(value) {
|
|
1361
|
+
return typeof value === "string" ? value : "";
|
|
1362
|
+
}
|
|
1363
|
+
function count(value) {
|
|
1364
|
+
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0 ? value : undefined;
|
|
1365
|
+
}
|
|
1366
|
+
function safe(value) {
|
|
1367
|
+
return value.replace(/[\x00-\x09\x0b-\x1f\x7f-\x9f]/g, (char) => {
|
|
1368
|
+
if (char === "\t")
|
|
1369
|
+
return "\\t";
|
|
1370
|
+
if (char === "\r")
|
|
1371
|
+
return "\\r";
|
|
1372
|
+
return `\\x${char.charCodeAt(0).toString(16).padStart(2, "0")}`;
|
|
1373
|
+
});
|
|
1374
|
+
}
|
|
1375
|
+
function inline(value) {
|
|
1376
|
+
return safe(text(value)).replaceAll(`
|
|
1377
|
+
`, "\\n");
|
|
1378
|
+
}
|
|
1379
|
+
function plural(n, unit) {
|
|
1380
|
+
return `${n} ${unit}${n === 1 ? "" : "s"}`;
|
|
1381
|
+
}
|
|
1382
|
+
function fields(value, omit = []) {
|
|
1383
|
+
return Object.entries(value).flatMap(([key, item]) => {
|
|
1384
|
+
if (omit.includes(key) || item === undefined || item === null || typeof item === "object")
|
|
1385
|
+
return [];
|
|
1386
|
+
const label = key.replaceAll("_", " ");
|
|
1387
|
+
return [`${label[0]?.toUpperCase() ?? ""}${label.slice(1)}: ${safe(String(item))}`];
|
|
1388
|
+
}).join(`
|
|
1389
|
+
`);
|
|
1390
|
+
}
|
|
1391
|
+
function location(value) {
|
|
1392
|
+
const start = text(value.start_anchor) || (count(value.start_line) !== undefined ? `${value.start_line}${text(value.start_hash) ? `:${value.start_hash}` : ""}` : "");
|
|
1393
|
+
const end = text(value.end_anchor) || (count(value.end_line) !== undefined ? `${value.end_line}${text(value.end_hash) ? `:${value.end_hash}` : ""}` : "");
|
|
1394
|
+
return start ? ` ${inline(start)}${end && end !== start ? ` - ${inline(end)}` : ""}` : "";
|
|
1395
|
+
}
|
|
1396
|
+
function sourceStructure(structure) {
|
|
1397
|
+
const sections = [];
|
|
1398
|
+
if (structure.root) {
|
|
1399
|
+
const lines = [];
|
|
1400
|
+
const stack = [{ node: record(structure.root), depth: 0 }];
|
|
1401
|
+
while (stack.length > 0) {
|
|
1402
|
+
const { node, depth } = stack.pop();
|
|
1403
|
+
lines.push(`${" ".repeat(Math.min(depth, 12))}${inline(node.kind) || "node"}${text(node.name) ? ` ${inline(node.name)}` : ""}${location(node)}`);
|
|
1404
|
+
const children = records(node.children);
|
|
1405
|
+
for (let i = children.length - 1;i >= 0; i--)
|
|
1406
|
+
stack.push({ node: children[i], depth: depth + 1 });
|
|
1407
|
+
}
|
|
1408
|
+
sections.push(`Tree
|
|
1409
|
+
${lines.join(`
|
|
1410
|
+
`)}`);
|
|
1411
|
+
}
|
|
1412
|
+
const symbols = records(structure.symbols);
|
|
1413
|
+
if (symbols.length > 0) {
|
|
1414
|
+
sections.push(`Symbols
|
|
1415
|
+
${symbols.map((symbol) => `${inline(symbol.kind) || "symbol"} ${inline(symbol.qualified_name || symbol.name)}${location(symbol)}`).join(`
|
|
1416
|
+
`)}`);
|
|
1417
|
+
}
|
|
1418
|
+
return sections.join(`
|
|
1419
|
+
|
|
1420
|
+
`) || "No structure found in this selection.";
|
|
1421
|
+
}
|
|
1422
|
+
function documentNodes(nodes, content) {
|
|
1423
|
+
const depths = new Map;
|
|
1424
|
+
return nodes.map((node) => {
|
|
1425
|
+
const depth = Math.min((depths.get(text(node.parent_id)) ?? -1) + 1, 12);
|
|
1426
|
+
depths.set(text(node.id), depth);
|
|
1427
|
+
const indent = " ".repeat(depth);
|
|
1428
|
+
const label = inline(node.title) || inline(node.kind) || "node";
|
|
1429
|
+
const page = count(node.page);
|
|
1430
|
+
const selector = text(node.id) ? `node:${inline(node.id)}` : "";
|
|
1431
|
+
const position = [selector, page !== undefined ? `page:${page}` : ""].filter(Boolean).join(" · ");
|
|
1432
|
+
const heading = `${indent}${label}${position ? ` [${position}]` : ""}`;
|
|
1433
|
+
const body = text(node.text);
|
|
1434
|
+
return content && body ? `${heading}
|
|
1435
|
+
${safe(body).split(`
|
|
1436
|
+
`).map((line) => indent + line).join(`
|
|
1437
|
+
`)}` : heading;
|
|
1438
|
+
}).join(content ? `
|
|
1439
|
+
|
|
1440
|
+
` : `
|
|
1441
|
+
`);
|
|
1442
|
+
}
|
|
1443
|
+
function assetList(assets) {
|
|
1444
|
+
return assets.map((asset) => {
|
|
1445
|
+
const id = text(asset.id);
|
|
1446
|
+
const page = count(asset.page);
|
|
1447
|
+
const heading = [id ? `asset:${inline(id)}` : inline(asset.kind) || "image", inline(asset.mime), page !== undefined ? `page:${page}` : ""].filter(Boolean).join(" · ");
|
|
1448
|
+
const details = fields(asset, ["id", "kind", "mime", "page", "bbox", "content_identity"]);
|
|
1449
|
+
return `${heading}${details ? `
|
|
1450
|
+
${details.split(`
|
|
1451
|
+
`).map((line) => ` ${line}`).join(`
|
|
1452
|
+
`)}` : ""}`;
|
|
1453
|
+
}).join(`
|
|
1454
|
+
|
|
1455
|
+
`);
|
|
1456
|
+
}
|
|
1457
|
+
function presentShowResult(tool, value, options = {}) {
|
|
1458
|
+
const output = record(value);
|
|
1459
|
+
const metadata = record(output.metadata);
|
|
1460
|
+
const content = record(output.content);
|
|
1461
|
+
const cursor = record(output.cursor);
|
|
1462
|
+
const structure = record(output.structure);
|
|
1463
|
+
const document = typeof output.format === "string" && (Array.isArray(output.nodes) || typeof output.source === "string");
|
|
1464
|
+
const path = inline(options.path || output.source || output.file || content.file || structure.file || metadata.file || cursor.file) || "(unknown path)";
|
|
1465
|
+
const summary = [];
|
|
1466
|
+
const result = { summary: "", body: "", notices: [], metadata: {} };
|
|
1467
|
+
if (tool === "show_metadata") {
|
|
1468
|
+
const data = Object.keys(metadata).length > 0 ? metadata : output;
|
|
1469
|
+
if (text(data.format || data.language || data.type))
|
|
1470
|
+
summary.push(inline(data.format || data.language || data.type));
|
|
1471
|
+
if (count(data.pages) !== undefined) {
|
|
1472
|
+
result.metadata.pages = data.pages;
|
|
1473
|
+
summary.push(plural(result.metadata.pages, "page"));
|
|
1474
|
+
}
|
|
1475
|
+
result.body = fields(data) || "No metadata available.";
|
|
1476
|
+
} else if (tool === "show_assets") {
|
|
1477
|
+
const assets = records(output.assets);
|
|
1478
|
+
result.metadata.assets = assets.length;
|
|
1479
|
+
summary.push(plural(assets.length, "asset"));
|
|
1480
|
+
result.body = assetList(assets) || "No assets in this selection.";
|
|
1481
|
+
} else if (document) {
|
|
1482
|
+
const nodes = records(output.nodes);
|
|
1483
|
+
const assets = records(output.assets);
|
|
1484
|
+
result.metadata.nodes = nodes.length;
|
|
1485
|
+
if (count(output.pages) !== undefined)
|
|
1486
|
+
result.metadata.pages = output.pages;
|
|
1487
|
+
summary.push(plural(nodes.length, "node"));
|
|
1488
|
+
if (result.metadata.pages !== undefined)
|
|
1489
|
+
summary.push(plural(result.metadata.pages, "page"));
|
|
1490
|
+
const sections = [text(output.title) ? safe(text(output.title)) : "", documentNodes(nodes, tool === "show_content")];
|
|
1491
|
+
if (assets.length > 0) {
|
|
1492
|
+
result.metadata.assets = assets.length;
|
|
1493
|
+
sections.push(`Assets
|
|
1494
|
+
${assetList(assets)}`);
|
|
1495
|
+
}
|
|
1496
|
+
result.body = sections.filter(Boolean).join(`
|
|
1497
|
+
|
|
1498
|
+
`) || "No content in this selection.";
|
|
1499
|
+
} else if (tool === "show_structure") {
|
|
1500
|
+
const symbols = records(structure.symbols);
|
|
1501
|
+
result.metadata.symbols = symbols.length;
|
|
1502
|
+
summary.push(plural(symbols.length, "symbol"));
|
|
1503
|
+
result.body = sourceStructure(structure);
|
|
1504
|
+
} else if (content.kind === "image" || count(content.width) !== undefined && count(content.height) !== undefined || count(metadata.width) !== undefined && count(metadata.height) !== undefined || text(content.mime).startsWith("image/") || text(metadata.mime).startsWith("image/") || text(metadata.type).startsWith("image/")) {
|
|
1505
|
+
const description = Object.keys(content).length > 0 ? content : Object.keys(metadata).length > 0 ? metadata : output;
|
|
1506
|
+
if (count(description.width) !== undefined && count(description.height) !== undefined) {
|
|
1507
|
+
summary.push(`${description.width} × ${description.height}`);
|
|
1508
|
+
} else if (count(metadata.width) !== undefined && count(metadata.height) !== undefined) {
|
|
1509
|
+
summary.push(`${metadata.width} × ${metadata.height}`);
|
|
1510
|
+
}
|
|
1511
|
+
const mime = text(description.mime || metadata.mime || metadata.type);
|
|
1512
|
+
if (mime)
|
|
1513
|
+
summary.push(inline(mime));
|
|
1514
|
+
result.body = fields(description, ["hashlines"]) || fields(metadata) || "No content in this selection.";
|
|
1515
|
+
} else if (Array.isArray(content.hashlines) || Array.isArray(cursor.hashlines)) {
|
|
1516
|
+
const lines = records(content.hashlines ?? cursor.hashlines);
|
|
1517
|
+
const start = count(content.start_line) ?? count(lines[0]?.line);
|
|
1518
|
+
const end = count(content.end_line) ?? count(lines.at(-1)?.line);
|
|
1519
|
+
const total = count(content.line_count) ?? count(cursor.line_count);
|
|
1520
|
+
if (start !== undefined && end !== undefined && start <= end) {
|
|
1521
|
+
result.metadata.start_line = start;
|
|
1522
|
+
result.metadata.end_line = end;
|
|
1523
|
+
summary.push(`lines ${start}-${end}${total !== undefined ? ` of ${total}` : ""}`);
|
|
1524
|
+
} else
|
|
1525
|
+
summary.push(plural(lines.length, "line"));
|
|
1526
|
+
const lang = text(metadata.language || content.language);
|
|
1527
|
+
if (lang)
|
|
1528
|
+
summary.push(inline(lang));
|
|
1529
|
+
const rows = lines.map((line) => `${line.line}${options.noAnchors ? "" : `:${text(line.hash)}`} | ${safe(text(line.text)).replaceAll("\\n", "\\\\n")}`);
|
|
1530
|
+
const identifier = record(cursor.identifier);
|
|
1531
|
+
if (count(cursor.line) !== undefined)
|
|
1532
|
+
result.metadata.line = cursor.line;
|
|
1533
|
+
if (count(cursor.column) !== undefined)
|
|
1534
|
+
result.metadata.column = cursor.column;
|
|
1535
|
+
if (Object.keys(cursor).length > 0) {
|
|
1536
|
+
const symbol = record(cursor.symbol);
|
|
1537
|
+
const description = [text(identifier.text), text(symbol.qualified_name || symbol.name), text(symbol.kind)].filter(Boolean);
|
|
1538
|
+
rows.unshift(`Cursor: ${cursor.line ?? "?"}:${cursor.column ?? "?"}${description.length > 0 ? ` · ${[...new Set(description)].map(inline).join(" · ")}` : ""}`, "");
|
|
1539
|
+
}
|
|
1540
|
+
result.body = rows.join(`
|
|
1541
|
+
`) || "Empty source selection.";
|
|
1542
|
+
if (start !== undefined && start > 1)
|
|
1543
|
+
result.notices.push(`Earlier lines omitted. Read preceding content with at: line:1 and limit: ${start - 1}.`);
|
|
1544
|
+
if (end !== undefined && total !== undefined && end < total) {
|
|
1545
|
+
result.notices.push(`More lines available. Continue with at: line:${end + 1}.`);
|
|
1546
|
+
} else if (content.truncated === true && (end === undefined || total === undefined)) {
|
|
1547
|
+
result.notices.push(`Content is truncated.${end !== undefined ? ` Continue with at: line:${end + 1}.` : " Select a smaller range with at and limit."}`);
|
|
1548
|
+
}
|
|
1549
|
+
} else {
|
|
1550
|
+
const description = Object.keys(content).length > 0 ? content : output;
|
|
1551
|
+
result.body = fields(description) || "No content in this selection.";
|
|
1552
|
+
}
|
|
1553
|
+
if (tool === "show_structure")
|
|
1554
|
+
result.notices.push("Structure is limited to the requested depth, kind, and outline. Use a deeper depth or focus with at to inspect further.");
|
|
1555
|
+
if (text(output.warning))
|
|
1556
|
+
result.notices.push(safe(text(output.warning)));
|
|
1557
|
+
result.summary = summary.join(" · ") || "complete";
|
|
1558
|
+
return result;
|
|
1559
|
+
}
|
|
1560
|
+
function formatShowResult(presentation) {
|
|
1561
|
+
return [presentation.summary, presentation.body, ...presentation.notices.map((notice) => `Note: ${notice}`)].filter(Boolean).join(`
|
|
1562
|
+
|
|
1563
|
+
`);
|
|
1564
|
+
}
|
|
1350
1565
|
// src/platform.ts
|
|
1351
1566
|
import { accessSync, constants as fsConstants, existsSync, statSync } from "node:fs";
|
|
1352
1567
|
import { createRequire } from "node:module";
|
|
@@ -2113,13 +2328,16 @@ export {
|
|
|
2113
2328
|
expandUserPath,
|
|
2114
2329
|
failureFromProcessResult,
|
|
2115
2330
|
fallbackToolDescriptionMap,
|
|
2331
|
+
formatShowResult,
|
|
2116
2332
|
getToolContract,
|
|
2333
|
+
isShowTool,
|
|
2117
2334
|
isSubPath,
|
|
2118
2335
|
parseLineAnchor,
|
|
2119
2336
|
parseReadSeekKdl,
|
|
2120
2337
|
parseSelector,
|
|
2121
2338
|
parseSuccessfulKdl,
|
|
2122
2339
|
preferredToolDescriptionMap,
|
|
2340
|
+
presentShowResult,
|
|
2123
2341
|
readSeekBinaryName,
|
|
2124
2342
|
readSeekPlatformKey,
|
|
2125
2343
|
readSeekProcessEnvironment,
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export type ShowTool = "show_content" | "show_structure" | "show_metadata" | "show_assets";
|
|
2
|
+
export interface ShowPresentation {
|
|
3
|
+
summary: string;
|
|
4
|
+
body: string;
|
|
5
|
+
notices: string[];
|
|
6
|
+
metadata: Record<string, number>;
|
|
7
|
+
}
|
|
8
|
+
export interface ShowPresentationOptions {
|
|
9
|
+
path?: string;
|
|
10
|
+
at?: string;
|
|
11
|
+
noAnchors?: boolean;
|
|
12
|
+
}
|
|
13
|
+
export declare function isShowTool(name: string): name is ShowTool;
|
|
14
|
+
export declare function presentShowResult(tool: ShowTool, value: unknown, options?: ShowPresentationOptions): ShowPresentation;
|
|
15
|
+
export declare function formatShowResult(presentation: ShowPresentation): string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jarkkojs/readseek-api",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.1",
|
|
4
4
|
"description": "Shared ReadSeek CLI contract, validation, argv builders, and bounded process runners",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
"vitest": "^4.1.0"
|
|
52
52
|
},
|
|
53
53
|
"dependencies": {
|
|
54
|
-
"@jarkkojs/readseek": "^0.11.
|
|
54
|
+
"@jarkkojs/readseek": "^0.11.1",
|
|
55
55
|
"@bgotink/kdl": "0.4.0",
|
|
56
56
|
"@sinclair/typebox": "0.34.52"
|
|
57
57
|
}
|