@danypops/pi-papyrus 0.45.3 → 0.45.5
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.
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Theme } from "@earendil-works/pi-coding-agent";
|
|
2
|
-
import { type Component, truncateToWidth
|
|
2
|
+
import { type Component, truncateToWidth } from "@earendil-works/pi-tui";
|
|
3
|
+
import { buildDetailLines, type DetailField, type DetailSection } from "malevich-tui-components";
|
|
3
4
|
import type { ArtifactToolDetails } from "./render-model.ts";
|
|
4
5
|
|
|
5
6
|
const KIND_GLYPHS: Readonly<Record<string, string>> = {
|
|
@@ -92,33 +93,55 @@ export class ArtifactCard implements Component {
|
|
|
92
93
|
this.invalidate();
|
|
93
94
|
}
|
|
94
95
|
|
|
96
|
+
/** Every field as a labeled `Label: value` line (buildDetailLines), matching the same
|
|
97
|
+
* convention pi-tickets' issue-detail-view.ts already uses -- not bare stacked values. */
|
|
98
|
+
private fields(): DetailField[] {
|
|
99
|
+
const artifact = this.details.artifact;
|
|
100
|
+
const status = this.theme.fg(statusColor(artifact.status), `${statusGlyph(artifact.status)} ${artifact.status}`);
|
|
101
|
+
return [
|
|
102
|
+
{ label: "Title", value: artifact.title },
|
|
103
|
+
{ label: "Kind", value: `${kindGlyph(artifact.kind)} ${artifact.kind}` },
|
|
104
|
+
{ label: "Status", value: status },
|
|
105
|
+
...(this.expanded ? [{ label: "ID", value: artifact.id }] : []),
|
|
106
|
+
...(this.expanded && artifact.subtype ? [{ label: "Subtype", value: artifact.subtype }] : []),
|
|
107
|
+
...(this.expanded && artifact.labels.length > 0 ? [{ label: "Labels", value: artifact.labels.join(", ") }] : []),
|
|
108
|
+
];
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
private sections(): DetailSection[] {
|
|
112
|
+
if (!this.expanded) return [];
|
|
113
|
+
const sections: DetailSection[] = [];
|
|
114
|
+
const artifact = this.details.artifact;
|
|
115
|
+
if (artifact.body) sections.push({ heading: "Body:", body: artifact.body });
|
|
116
|
+
if (this.details.completeness.truncated) {
|
|
117
|
+
sections.push({ lines: [`[truncated ${this.details.completeness.omitted} characters]`] });
|
|
118
|
+
}
|
|
119
|
+
return sections;
|
|
120
|
+
}
|
|
121
|
+
|
|
95
122
|
render(width: number): string[] {
|
|
96
123
|
const safeWidth = Math.max(1, width);
|
|
97
124
|
if (this.cachedLines && this.cachedWidth === safeWidth) return this.cachedLines;
|
|
98
125
|
|
|
99
|
-
const
|
|
100
|
-
const
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
126
|
+
const theme = this.theme;
|
|
127
|
+
const lines = buildDetailLines(safeWidth, {
|
|
128
|
+
fields: this.fields(),
|
|
129
|
+
sections: this.sections(),
|
|
130
|
+
alignFields: true,
|
|
131
|
+
theme: {
|
|
132
|
+
field: (s) => theme.fg("text", s),
|
|
133
|
+
heading: (s) => theme.fg("toolTitle", theme.bold(s)),
|
|
134
|
+
byline: (s) => theme.fg("muted", s),
|
|
135
|
+
body: (s) => theme.fg("text", s),
|
|
136
|
+
line: (s) => theme.fg("warning", s),
|
|
137
|
+
},
|
|
138
|
+
});
|
|
108
139
|
|
|
109
140
|
if (this.details.focus) {
|
|
110
|
-
lines.push(truncateToWidth(focusLine(this.details.focus,
|
|
141
|
+
lines.push(truncateToWidth(focusLine(this.details.focus, theme), safeWidth));
|
|
111
142
|
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
const metadata = [artifact.subtype, ...artifact.labels].filter(Boolean).join(" · ");
|
|
115
|
-
if (metadata) lines.push(truncateToWidth(this.theme.fg("muted", metadata), safeWidth));
|
|
116
|
-
if (artifact.body) lines.push(...wrapTextWithAnsi(artifact.body, safeWidth));
|
|
117
|
-
if (this.details.completeness.truncated) {
|
|
118
|
-
lines.push(truncateToWidth(this.theme.fg("warning", `[truncated ${this.details.completeness.omitted} characters]`), safeWidth));
|
|
119
|
-
}
|
|
120
|
-
} else if (artifact.body || artifact.labels.length > 0) {
|
|
121
|
-
lines.push(truncateToWidth(this.theme.fg("dim", expandHint()), safeWidth));
|
|
143
|
+
if (!this.expanded && (this.details.artifact.body || this.details.artifact.labels.length > 0)) {
|
|
144
|
+
lines.push(truncateToWidth(theme.fg("dim", expandHint()), safeWidth));
|
|
122
145
|
}
|
|
123
146
|
|
|
124
147
|
this.cachedWidth = safeWidth;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { pickIdentityArgument } from "@danypops/vehicle-client-pi/vehicle-render";
|
|
1
2
|
import type { AgentToolResult, Theme, ToolRenderResultOptions } from "@earendil-works/pi-coding-agent";
|
|
2
3
|
import { type Component, Text } from "@earendil-works/pi-tui";
|
|
3
4
|
import { ArtifactCard } from "./artifact-card.ts";
|
|
@@ -6,25 +7,18 @@ import { type PapyrusToolDetails, parsePapyrusToolDetails } from "./render-model
|
|
|
6
7
|
|
|
7
8
|
const CALL_VALUE_MAX_CHARACTERS = 80;
|
|
8
9
|
|
|
10
|
+
/** name/title before id: a caller that already knows the name shouldn't have the raw id echoed back at it. */
|
|
11
|
+
const IDENTITY_ARG_KEYS = ["name", "title", "id", "text", "query", "kind", "template_id"];
|
|
12
|
+
|
|
9
13
|
export interface PapyrusToolRenderContext {
|
|
10
14
|
lastComponent: Component | undefined;
|
|
11
15
|
isError: boolean;
|
|
12
16
|
}
|
|
13
17
|
|
|
14
|
-
function primaryArgument(args: Record<string, unknown>): string | undefined {
|
|
15
|
-
// name/title before id: a caller that already knows the name shouldn't have the raw id echoed
|
|
16
|
-
// back at it; id only surfaces here when it's genuinely the only identifying argument given.
|
|
17
|
-
for (const key of ["name", "title", "id", "text", "query", "kind", "template_id"]) {
|
|
18
|
-
const value = args[key];
|
|
19
|
-
if (typeof value === "string" && value.trim()) return value.slice(0, CALL_VALUE_MAX_CHARACTERS);
|
|
20
|
-
}
|
|
21
|
-
return undefined;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
18
|
/** Compact native call header that never echoes bodies or structured payloads. */
|
|
25
19
|
export function renderPapyrusToolCall(label: string, args: Record<string, unknown>, theme: Theme): Component {
|
|
26
20
|
const action = typeof args.action === "string" ? args.action : "call";
|
|
27
|
-
const primary =
|
|
21
|
+
const primary = pickIdentityArgument(args, IDENTITY_ARG_KEYS, CALL_VALUE_MAX_CHARACTERS);
|
|
28
22
|
const text = [
|
|
29
23
|
theme.fg("toolTitle", theme.bold(label)),
|
|
30
24
|
theme.fg("muted", action),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@danypops/pi-papyrus",
|
|
3
|
-
"version": "0.45.
|
|
3
|
+
"version": "0.45.5",
|
|
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"],
|
|
@@ -20,11 +20,11 @@
|
|
|
20
20
|
"@danypops/jittor": "^0.14.0",
|
|
21
21
|
"@danypops/papyrus": "^0.44.0",
|
|
22
22
|
"@danypops/vehicle-client": "^0.5.0",
|
|
23
|
-
"@danypops/vehicle-client-pi": "^0.16.
|
|
23
|
+
"@danypops/vehicle-client-pi": "^0.16.7",
|
|
24
24
|
"@danypops/vehicle-core": "^0.10.0",
|
|
25
25
|
"@danypops/vehicle-server": "^0.13.0",
|
|
26
26
|
"beautiful-mermaid": "1.1.3",
|
|
27
|
-
"malevich-tui-components": "^0.
|
|
27
|
+
"malevich-tui-components": "^0.21.2"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
30
|
"@danypops/pi-tui-harness": "^0.0.2",
|