@danypops/pi-papyrus 0.38.3 → 0.38.4

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 { ExtensionCommandContext } from "@earendil-works/pi-coding-agent";
2
2
  import { matchesKey, sliceByColumn, truncateToWidth, visibleWidth, wrapTextWithAnsi, type TUI } from "@earendil-works/pi-tui";
3
+ import { buildDetailLines, type DetailField, type DetailSection } from "malevich-tui-components";
3
4
  import {
4
5
  ARTIFACT_DETAIL_HORIZONTAL_PAN_COLUMNS,
5
6
  ARTIFACT_DETAIL_MAX_VISIBLE_LINES,
@@ -90,12 +91,34 @@ class ArtifactDetailViewport {
90
91
  { text: "", wide: false },
91
92
  ];
92
93
  const body = renderMarkdownBody(this.content.body, width, this.activeTheme).map((text) => ({ text, wide: false }));
93
- const labels = this.content.labels.length > 0
94
- ? [{ text: "", wide: false }, ...wrap("Labels:", "muted"), ...wrap(this.content.labels.join(", "))]
94
+
95
+ // Labels + Metadata are plain field/flat-line shapes -- delegated to malevich's
96
+ // buildDetailLines. The body (markdown-rendered) and relationships (horizontally
97
+ // pannable "wide" lines) stay hand-rolled: buildDetailLines has no concept of
98
+ // either, and forcing them through it would either drop markdown formatting or
99
+ // lose the pan feature.
100
+ const fields: DetailField[] = this.content.labels.length > 0 ? [{ label: "Labels", value: this.content.labels.join(", ") }] : [];
101
+ const sections: DetailSection[] = this.content.metadata.length > 0
102
+ ? [{ heading: "Metadata:", lines: this.content.metadata.map((line) => ` ${line}`) }]
95
103
  : [];
96
- const metadata = this.content.metadata.length > 0
97
- ? [{ text: "", wide: false }, ...wrap("Metadata:", "muted"), ...this.content.metadata.flatMap((line) => wrap(` ${line}`, "dim"))]
104
+ const labelsAndMetadata = (fields.length > 0 || sections.length > 0)
105
+ ? buildDetailLines(width, {
106
+ fields,
107
+ sections,
108
+ theme: {
109
+ field: (s) => theme.fg("muted", s),
110
+ heading: (s) => theme.fg("muted", s),
111
+ byline: (s) => theme.fg("dim", s),
112
+ body: (s) => theme.fg("text", s),
113
+ line: (s) => theme.fg("dim", s),
114
+ },
115
+ }).map((text) => ({ text, wide: false }))
98
116
  : [];
117
+ // buildDetailLines' fields/sections don't insert a leading blank before the
118
+ // first field the way the original hand-rolled labels block did -- add it back
119
+ // when either piece rendered anything, matching the original layout exactly.
120
+ const labelsAndMetadataWithLeadingBlank = fields.length > 0 ? [{ text: "", wide: false }, ...labelsAndMetadata] : labelsAndMetadata;
121
+
99
122
  const relationships = this.content.relationships.length > 0
100
123
  ? [
101
124
  { text: "", wide: false },
@@ -103,7 +126,7 @@ class ArtifactDetailViewport {
103
126
  ...this.content.relationships.map((text) => ({ text: theme.fg("text", text), wide: true })),
104
127
  ]
105
128
  : [];
106
- this.lines = [...identity, ...body, ...labels, ...metadata, ...relationships];
129
+ this.lines = [...identity, ...body, ...labelsAndMetadataWithLeadingBlank, ...relationships];
107
130
  this.offsetY = Math.min(this.offsetY, Math.max(0, this.lines.length - this.visibleLines));
108
131
  }
109
132
  }
@@ -26,7 +26,7 @@ import {
26
26
  } from "@danypops/papyrus";
27
27
  import { formatMetadata } from "./artifact-format.ts";
28
28
  import { callService, subscribeTaskPushChannel } from "./service-client.ts";
29
- import type { PushChannelClient } from "@danypops/daemon-kit/pi-client";
29
+ import type { PushChannelClient } from "@danypops/vehicle-client/daemon-client";
30
30
  import { registerDomainTools, resolveNameFields } from "./domain-tools.ts";
31
31
  import { registerNotesVehicle } from "./vehicle-notes-client.ts";
32
32
  import { BoundedPoll } from "./bounded-poll.ts";
@@ -1,4 +1,4 @@
1
- import { connectPushChannel, createRetryingClient, type PushChannelClient, type PushChannelState, type RetryingClient } from "@danypops/daemon-kit/pi-client";
1
+ import { connectPushChannel, createRetryingClient, type PushChannelClient, type PushChannelState, type RetryingClient } from "@danypops/vehicle-client/daemon-client";
2
2
  import { connectPapyrusClient, resolvePushChannelTarget, resolveVehicleClientTarget, type OperationName, type PapyrusClient, type VehicleClientTarget } from "@danypops/papyrus";
3
3
 
4
4
  type ClientConnector = () => Promise<PapyrusClient>;
@@ -1,5 +1,6 @@
1
1
  import type { ExtensionCommandContext } from "@earendil-works/pi-coding-agent";
2
2
  import { matchesKey, sliceByColumn, truncateToWidth, visibleWidth, wrapTextWithAnsi, type TUI } from "@earendil-works/pi-tui";
3
+ import { buildDetailLines, type DetailField, type DetailSection } from "malevich-tui-components";
3
4
  import {
4
5
  TASK_DETAIL_HORIZONTAL_PAN_COLUMNS,
5
6
  TASK_DETAIL_MAX_VISIBLE_LINES,
@@ -92,17 +93,32 @@ class TaskDetailViewport {
92
93
  (text.length === 0 ? [""] : wrapTextWithAnsi(theme.fg(color, text), width)).map((line) => ({ text: line, graph: false }));
93
94
  const status = TASK_STATUS_PRESENTATION[this.status as keyof typeof TASK_STATUS_PRESENTATION];
94
95
  const headline = status ? theme.fg(status.color, theme.bold(this.content.headline)) : theme.bold(this.content.headline);
96
+
97
+ // Labels + the checklist/gates/metadata/history sections are plain field/flat-line
98
+ // shapes -- delegated to malevich's buildDetailLines. The headline/identity (styled
99
+ // per task status), body (markdown-rendered), and the relationship graph
100
+ // (horizontally pannable "wide" lines) stay hand-rolled: buildDetailLines has no
101
+ // concept of any of those.
95
102
  const identity = [
96
103
  ...wrapTextWithAnsi(headline, width).map((text) => ({ text, graph: false })),
97
104
  ...wrap(this.content.identity, "muted"),
98
- ...(this.content.labels.length > 0 ? wrap(`Labels: ${this.content.labels.join(", ")}`, "muted") : []),
99
- { text: "", graph: false },
100
105
  ];
106
+ const detailTheme = {
107
+ field: (s: string) => theme.fg("muted", s),
108
+ heading: (s: string) => theme.fg("muted", s),
109
+ byline: (s: string) => theme.fg("dim", s),
110
+ body: (s: string) => theme.fg("text", s),
111
+ line: (s: string) => theme.fg("dim", s),
112
+ };
113
+ const fields: DetailField[] = this.content.labels.length > 0 ? [{ label: "Labels", value: this.content.labels.join(", ") }] : [];
114
+ const labels = fields.length > 0
115
+ ? [...buildDetailLines(width, { fields, theme: detailTheme }).map((text) => ({ text, graph: false })), { text: "", graph: false }]
116
+ : [{ text: "", graph: false }];
101
117
  const body = renderMarkdownBody(this.content.body, width, this.activeTheme).map((text) => ({ text, graph: false }));
102
- const sections = this.content.sections.flatMap((section) => [
103
- { text: "", graph: false },
104
- ...section.flatMap((line, index) => wrap(line, index === 0 ? "muted" : "dim")),
105
- ]);
118
+ const sections: DetailSection[] = this.content.sections.map((section) => ({ heading: section[0], lines: section.slice(1) }));
119
+ const sectionLines = sections.length > 0
120
+ ? buildDetailLines(width, { sections, theme: detailTheme }).map((text) => ({ text, graph: false }))
121
+ : [];
106
122
  const relationshipHeader = this.graphLines.length > 0
107
123
  ? [
108
124
  { text: "", graph: false },
@@ -112,8 +128,9 @@ class TaskDetailViewport {
112
128
  : [];
113
129
  this.detailLines = [
114
130
  ...identity,
131
+ ...labels,
115
132
  ...body,
116
- ...sections,
133
+ ...sectionLines,
117
134
  ...relationshipHeader,
118
135
  ...this.graphLines.map((text) => ({ text: theme.fg("text", text), graph: true })),
119
136
  ];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@danypops/pi-papyrus",
3
- "version": "0.38.3",
3
+ "version": "0.38.4",
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"],
@@ -17,12 +17,13 @@
17
17
  "typebox": "*"
18
18
  },
19
19
  "dependencies": {
20
- "@danypops/daemon-kit": "^0.10.0",
21
20
  "@danypops/papyrus": "^0.38.1",
22
- "@danypops/vehicle-core": "^0.1.0",
21
+ "@danypops/vehicle-core": "^0.1.1",
22
+ "@danypops/vehicle-server": "^0.1.1",
23
23
  "@danypops/vehicle-client": "^0.1.1",
24
24
  "@danypops/vehicle-client-pi": "^0.1.5",
25
- "beautiful-mermaid": "1.1.3"
25
+ "beautiful-mermaid": "1.1.3",
26
+ "malevich-tui-components": "^0.5.0"
26
27
  },
27
28
  "devDependencies": {
28
29
  "@earendil-works/pi-coding-agent": "^0.80.10",