@danypops/pi-papyrus 0.46.0 → 0.46.3
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/extension/src/artifact/artifact-detail-view.ts +5 -1
- package/extension/src/rules/rules.ts +6 -2
- package/extension/src/task/task-detail-view.ts +9 -3
- package/extension/src/tool-rendering/artifact-card.ts +1 -1
- package/extension/src/tools/vehicle-artifact-renderers.ts +13 -11
- package/package.json +4 -4
|
@@ -8,12 +8,15 @@ import {
|
|
|
8
8
|
} from "@danypops/papyrus";
|
|
9
9
|
import type { ExtensionCommandContext } from "@earendil-works/pi-coding-agent";
|
|
10
10
|
import { matchesKey, sliceByColumn, type TUI, truncateToWidth, visibleWidth, wrapTextWithAnsi } from "@earendil-works/pi-tui";
|
|
11
|
-
import { buildDetailLines, type DetailField, type DetailSection } from "malevich-tui-components";
|
|
11
|
+
import { buildDetailLines, type DetailField, type DetailSection, type TextMeasure } from "malevich-tui-components";
|
|
12
12
|
import { BeautifulMermaidRenderer } from "../beautiful-mermaid-renderer.ts";
|
|
13
13
|
import { type ActiveTheme, renderMarkdownBody } from "../markdown.ts";
|
|
14
14
|
import { type ArtifactDetailContent, artifactDetailContent, artifactDetailsText } from "./artifact-detail-format.ts";
|
|
15
15
|
import { buildArtifactRelationshipLines } from "./artifact-relationship-lines.ts";
|
|
16
16
|
|
|
17
|
+
/** Real ANSI-aware measure for buildDetailLines -- without it, wrapped themed text loses color on every line but the first/last. */
|
|
18
|
+
const measure: TextMeasure = { visibleWidth, truncateToWidth, wrapTextWithAnsi };
|
|
19
|
+
|
|
17
20
|
interface ArtifactDetailLine {
|
|
18
21
|
text: string;
|
|
19
22
|
wide: boolean;
|
|
@@ -117,6 +120,7 @@ class ArtifactDetailViewport {
|
|
|
117
120
|
body: (s) => theme.fg("text", s),
|
|
118
121
|
line: (s) => theme.fg("dim", s),
|
|
119
122
|
},
|
|
123
|
+
measure,
|
|
120
124
|
}).map((text) => ({ text, wide: false }))
|
|
121
125
|
: [];
|
|
122
126
|
// buildDetailLines' fields/sections don't insert a leading blank before the
|
|
@@ -36,8 +36,12 @@ export async function showRules(ctx: ExtensionCommandContext): Promise<void> {
|
|
|
36
36
|
const updated = await callService<Record<string, unknown>, Artifact>("rules.update", { id: rule.id, title, body });
|
|
37
37
|
commandCtx.ui.notify(`Updated "${updated.title}"`, "info");
|
|
38
38
|
} else if (choice === "Preview injection") {
|
|
39
|
-
const
|
|
40
|
-
|
|
39
|
+
const result = await callService<Record<string, unknown>, { preview: string; combinedLength: number; warning?: string }>(
|
|
40
|
+
"rules.preview",
|
|
41
|
+
{ id: rule.id },
|
|
42
|
+
);
|
|
43
|
+
const text = result.warning === undefined ? result.preview : `${result.preview}\n\n⚠ ${result.warning}`;
|
|
44
|
+
commandCtx.ui.notify(text, result.warning === undefined ? "info" : "warning");
|
|
41
45
|
} else if (choice === "Link gated task") {
|
|
42
46
|
const taskId = await commandCtx.ui.input("Task artifact id:", "");
|
|
43
47
|
if (taskId) await callService("rules.gate", { id: rule.id, task_id: taskId });
|
|
@@ -11,12 +11,15 @@ import {
|
|
|
11
11
|
} from "@danypops/papyrus";
|
|
12
12
|
import type { ExtensionCommandContext } from "@earendil-works/pi-coding-agent";
|
|
13
13
|
import { matchesKey, sliceByColumn, type TUI, truncateToWidth, visibleWidth, wrapTextWithAnsi } from "@earendil-works/pi-tui";
|
|
14
|
-
import { buildDetailLines, type DetailField, type DetailSection } from "malevich-tui-components";
|
|
14
|
+
import { buildDetailLines, type DetailField, type DetailSection, type TextMeasure } from "malevich-tui-components";
|
|
15
15
|
import { BeautifulMermaidRenderer } from "../beautiful-mermaid-renderer.ts";
|
|
16
16
|
import { type ActiveTheme, renderMarkdownBody } from "../markdown.ts";
|
|
17
17
|
import { type TaskDetailContent, taskDetailContent, taskDetailsText } from "./task-detail-format.ts";
|
|
18
18
|
import { TASK_STATUS_PRESENTATION } from "./task-presentation.ts";
|
|
19
19
|
|
|
20
|
+
/** Real ANSI-aware measure for buildDetailLines -- without it, wrapped themed text loses color on every line but the first/last. */
|
|
21
|
+
const measure: TextMeasure = { visibleWidth, truncateToWidth, wrapTextWithAnsi };
|
|
22
|
+
|
|
20
23
|
interface DetailLine {
|
|
21
24
|
text: string;
|
|
22
25
|
graph: boolean;
|
|
@@ -122,12 +125,15 @@ class TaskDetailViewport {
|
|
|
122
125
|
const fields: DetailField[] = this.content.labels.length > 0 ? [{ label: "Labels", value: this.content.labels.join(", ") }] : [];
|
|
123
126
|
const labels =
|
|
124
127
|
fields.length > 0
|
|
125
|
-
? [
|
|
128
|
+
? [
|
|
129
|
+
...buildDetailLines(width, { fields, theme: detailTheme, measure }).map((text) => ({ text, graph: false })),
|
|
130
|
+
{ text: "", graph: false },
|
|
131
|
+
]
|
|
126
132
|
: [{ text: "", graph: false }];
|
|
127
133
|
const body = renderMarkdownBody(this.content.body, width, this.activeTheme).map((text) => ({ text, graph: false }));
|
|
128
134
|
const sections: DetailSection[] = this.content.sections.map((section) => ({ heading: section[0], lines: section.slice(1) }));
|
|
129
135
|
const sectionLines =
|
|
130
|
-
sections.length > 0 ? buildDetailLines(width, { sections, theme: detailTheme }).map((text) => ({ text, graph: false })) : [];
|
|
136
|
+
sections.length > 0 ? buildDetailLines(width, { sections, theme: detailTheme, measure }).map((text) => ({ text, graph: false })) : [];
|
|
131
137
|
const relationshipHeader =
|
|
132
138
|
this.graphLines.length > 0
|
|
133
139
|
? [{ text: "", graph: false }, ...wrap("Relationships:", "muted"), ...wrap(" Dependencies point prerequisite → dependent.", "dim")]
|
|
@@ -13,7 +13,7 @@ import type { ArtifactToolDetails } from "./render-model.ts";
|
|
|
13
13
|
* terminal's default color. wrapTextWithAnsi re-injects the active codes on every wrapped
|
|
14
14
|
* line instead.
|
|
15
15
|
*/
|
|
16
|
-
const measure: TextMeasure = { visibleWidth, truncateToWidth, wrapTextWithAnsi };
|
|
16
|
+
export const measure: TextMeasure = { visibleWidth, truncateToWidth, wrapTextWithAnsi };
|
|
17
17
|
|
|
18
18
|
/** Shared by every buildDetailLines caller in this extension (ArtifactCard, and
|
|
19
19
|
* tools/vehicle-artifact-renderers.ts's discuss/tasks.complete renderers) -- one Theme -> DetailViewTheme
|
|
@@ -19,8 +19,16 @@ import { renderVehicleResult } from "@danypops/vehicle-client-pi/vehicle-render"
|
|
|
19
19
|
import type { VehicleOperationDescriptor } from "@danypops/vehicle-core";
|
|
20
20
|
import type { Theme } from "@earendil-works/pi-coding-agent";
|
|
21
21
|
import { type Component, Text, truncateToWidth } from "@earendil-works/pi-tui";
|
|
22
|
-
import {
|
|
23
|
-
|
|
22
|
+
import {
|
|
23
|
+
buildDetailLines,
|
|
24
|
+
type DagEdge,
|
|
25
|
+
type DagNode,
|
|
26
|
+
DagView,
|
|
27
|
+
type DetailField,
|
|
28
|
+
type DetailSection,
|
|
29
|
+
statelessComponent,
|
|
30
|
+
} from "malevich-tui-components";
|
|
31
|
+
import { ArtifactCard, detailViewTheme, expandHint, measure, statusColor, statusGlyph } from "../tool-rendering/artifact-card.ts";
|
|
24
32
|
import { ArtifactListCard } from "../tool-rendering/artifact-list.ts";
|
|
25
33
|
import { type ArtifactFocusAnnotation, createArtifactDetails, createArtifactListDetails } from "../tool-rendering/render-model.ts";
|
|
26
34
|
|
|
@@ -268,12 +276,6 @@ function roundsSection(rounds: readonly DiscussionRoundOutput[]): DetailSection
|
|
|
268
276
|
};
|
|
269
277
|
}
|
|
270
278
|
|
|
271
|
-
/** A one-shot render function with nothing to invalidate -- every buildDetailLines-based
|
|
272
|
-
* renderer in this file (unlike ArtifactCard/DagView) has no cache to clear. */
|
|
273
|
-
function statelessComponent(render: (width: number) => string[]): Component {
|
|
274
|
-
return { render, invalidate: () => {} };
|
|
275
|
-
}
|
|
276
|
-
|
|
277
279
|
function renderDiscussionAndRounds(output: DiscussionAndRoundsOutput, theme: Theme, expanded: boolean): Component {
|
|
278
280
|
const discussion = output.discussion;
|
|
279
281
|
return statelessComponent((width) => {
|
|
@@ -283,7 +285,7 @@ function renderDiscussionAndRounds(output: DiscussionAndRoundsOutput, theme: The
|
|
|
283
285
|
{ label: "Status", value: theme.fg(statusColor(discussion.status), `${statusGlyph(discussion.status)} ${discussion.status}`) },
|
|
284
286
|
];
|
|
285
287
|
const sections: DetailSection[] = expanded && output.rounds.length > 0 ? [roundsSection(output.rounds)] : [];
|
|
286
|
-
const lines = buildDetailLines(safeWidth, { fields, sections, alignFields: true, theme: detailViewTheme(theme) });
|
|
288
|
+
const lines = buildDetailLines(safeWidth, { fields, sections, alignFields: true, theme: detailViewTheme(theme), measure });
|
|
287
289
|
if (!expanded && output.rounds.length > 0) {
|
|
288
290
|
const count = output.rounds.length;
|
|
289
291
|
lines.push(truncateToWidth(theme.fg("dim", `${count} round${count === 1 ? "" : "s"} · ${expandHint()}`), safeWidth));
|
|
@@ -295,7 +297,7 @@ function renderDiscussionAndRounds(output: DiscussionAndRoundsOutput, theme: The
|
|
|
295
297
|
function renderDiscussionRoundsOnly(output: DiscussionRoundsOnlyOutput, theme: Theme): Component {
|
|
296
298
|
return statelessComponent((width) => {
|
|
297
299
|
const sections: DetailSection[] = output.rounds.length > 0 ? [roundsSection(output.rounds)] : [{ lines: ["No rounds."] }];
|
|
298
|
-
return buildDetailLines(Math.max(1, width), { sections, theme: detailViewTheme(theme) });
|
|
300
|
+
return buildDetailLines(Math.max(1, width), { sections, theme: detailViewTheme(theme), measure });
|
|
299
301
|
});
|
|
300
302
|
}
|
|
301
303
|
|
|
@@ -373,7 +375,7 @@ function renderTaskCompletion(result: TaskCompletionOutput, theme: Theme, expand
|
|
|
373
375
|
lines: result.blocked.map((entry) => theme.fg("warning", `◼ ${entry.artifact.title}`)),
|
|
374
376
|
});
|
|
375
377
|
}
|
|
376
|
-
const lines = buildDetailLines(safeWidth, { fields, sections, alignFields: true, theme: detailViewTheme(theme) });
|
|
378
|
+
const lines = buildDetailLines(safeWidth, { fields, sections, alignFields: true, theme: detailViewTheme(theme), measure });
|
|
377
379
|
if (result.focused && expanded) {
|
|
378
380
|
lines.push(truncateToWidth(theme.fg("accent", `▶ focus ${result.focused.title}`), safeWidth));
|
|
379
381
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@danypops/pi-papyrus",
|
|
3
|
-
"version": "0.46.
|
|
3
|
+
"version": "0.46.3",
|
|
4
4
|
"description": "Pi host extension for Papyrus: native tools, TUI panels, and context injection over the daemon-backed graph store",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": ["pi-package"],
|
|
@@ -18,13 +18,13 @@
|
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
20
|
"@danypops/jittor": "^0.14.0",
|
|
21
|
-
"@danypops/papyrus": "^0.
|
|
21
|
+
"@danypops/papyrus": "^0.45.2",
|
|
22
22
|
"@danypops/vehicle-client": "^0.5.0",
|
|
23
|
-
"@danypops/vehicle-client-pi": "^0.
|
|
23
|
+
"@danypops/vehicle-client-pi": "^0.18.4",
|
|
24
24
|
"@danypops/vehicle-core": "^0.12.3",
|
|
25
25
|
"@danypops/vehicle-server": "^0.18.1",
|
|
26
26
|
"beautiful-mermaid": "1.1.3",
|
|
27
|
-
"malevich-tui-components": "^0.
|
|
27
|
+
"malevich-tui-components": "^0.24.0"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
30
|
"@danypops/pi-tui-harness": "^0.0.2",
|