pi-harness-runtime 0.10.27 → 0.10.43
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/.pi/plugins/herdr-clipboard/herdr-plugin.toml +22 -0
- package/.pi/plugins/herdr-clipboard/start-bridge.sh +29 -0
- package/.pi/plugins/herdr-clipboard/tmux-watch.sh +39 -0
- package/CHANGELOG.md +19 -0
- package/README.md +87 -1
- package/config.toml.example +35 -0
- package/package.json +5 -3
- package/packages/architecture-generator/dist/adr.d.ts +1 -1
- package/packages/architecture-generator/dist/adr.d.ts.map +1 -1
- package/packages/architecture-generator/dist/adr.js +2 -2
- package/packages/architecture-generator/dist/adr.js.map +1 -1
- package/packages/architecture-generator/dist/index.d.ts +3 -3
- package/packages/architecture-generator/dist/index.js +3 -3
- package/packages/architecture-generator/dist/mermaid.d.ts +1 -1
- package/packages/architecture-generator/dist/mermaid.d.ts.map +1 -1
- package/packages/architecture-generator/dist/mermaid.js +20 -20
- package/packages/architecture-generator/dist/mermaid.js.map +1 -1
- package/packages/architecture-generator/dist/types.d.ts +2 -2
- package/packages/architecture-generator/dist/types.d.ts.map +1 -1
- package/packages/architecture-generator/src/adr.ts +16 -16
- package/packages/architecture-generator/src/index.ts +3 -3
- package/packages/architecture-generator/src/mermaid.ts +48 -54
- package/packages/architecture-generator/src/types.ts +15 -15
- package/packages/capability-registry/src/types.js +10 -0
- package/packages/clipboard/dist/src/copy-sync.d.ts.map +1 -1
- package/packages/clipboard/dist/src/copy-sync.js +45 -3
- package/packages/clipboard/dist/src/copy-sync.js.map +1 -1
- package/packages/clipboard/dist/src/index.d.ts +1 -0
- package/packages/clipboard/dist/src/index.d.ts.map +1 -1
- package/packages/clipboard/dist/src/index.js +1 -0
- package/packages/clipboard/dist/src/index.js.map +1 -1
- package/packages/clipboard/dist/src/paste-bridge.d.ts +19 -0
- package/packages/clipboard/dist/src/paste-bridge.d.ts.map +1 -0
- package/packages/clipboard/dist/src/paste-bridge.js +78 -0
- package/packages/clipboard/dist/src/paste-bridge.js.map +1 -0
- package/packages/clipboard/src/copy-sync.ts +52 -3
- package/packages/clipboard/src/index.ts +1 -0
- package/packages/clipboard/src/paste-bridge.ts +86 -0
- package/packages/clipboard-plugin/dist/index.d.ts +28 -0
- package/packages/clipboard-plugin/dist/index.d.ts.map +1 -0
- package/packages/clipboard-plugin/dist/index.js +64 -0
- package/packages/clipboard-plugin/dist/index.js.map +1 -0
- package/packages/clipboard-plugin/dist/types.d.ts +30 -0
- package/packages/clipboard-plugin/dist/types.d.ts.map +1 -0
- package/packages/clipboard-plugin/dist/types.js +5 -0
- package/packages/clipboard-plugin/dist/types.js.map +1 -0
- package/packages/clipboard-plugin/src/index.ts +74 -0
- package/packages/clipboard-plugin/src/types.ts +30 -0
- package/packages/file-copy-helper/dist/src/extension.js +84 -25
- package/packages/file-copy-helper/src/extension.debug.ts +226 -0
- package/packages/file-copy-helper/src/extension.ts +89 -59
- package/packages/knowledge-graph/dist/graph-extractor.d.ts +1 -1
- package/packages/knowledge-graph/dist/graph-extractor.d.ts.map +1 -1
- package/packages/knowledge-graph/dist/graph-extractor.js +46 -55
- package/packages/knowledge-graph/dist/graph-extractor.js.map +1 -1
- package/packages/knowledge-graph/dist/index.d.ts +4 -4
- package/packages/knowledge-graph/dist/index.js +4 -4
- package/packages/knowledge-graph/dist/mcp-client.d.ts +2 -2
- package/packages/knowledge-graph/dist/mcp-client.d.ts.map +1 -1
- package/packages/knowledge-graph/dist/mcp-client.js +22 -22
- package/packages/knowledge-graph/dist/mcp-client.js.map +1 -1
- package/packages/knowledge-graph/dist/provenance-linker.d.ts +1 -1
- package/packages/knowledge-graph/dist/provenance-linker.d.ts.map +1 -1
- package/packages/knowledge-graph/dist/provenance-linker.js +14 -15
- package/packages/knowledge-graph/dist/provenance-linker.js.map +1 -1
- package/packages/knowledge-graph/dist/types.d.ts +2 -2
- package/packages/knowledge-graph/dist/types.d.ts.map +1 -1
- package/packages/knowledge-graph/src/graph-extractor.ts +263 -280
- package/packages/knowledge-graph/src/index.ts +4 -4
- package/packages/knowledge-graph/src/mcp-client.ts +188 -197
- package/packages/knowledge-graph/src/provenance-linker.ts +69 -73
- package/packages/knowledge-graph/src/types.ts +46 -46
- package/packages/milestone-manager/dist/engine.d.ts +1 -1
- package/packages/milestone-manager/dist/engine.d.ts.map +1 -1
- package/packages/milestone-manager/dist/engine.js +7 -9
- package/packages/milestone-manager/dist/engine.js.map +1 -1
- package/packages/milestone-manager/dist/index.d.ts +2 -2
- package/packages/milestone-manager/dist/index.js +2 -2
- package/packages/milestone-manager/dist/types.d.ts +2 -2
- package/packages/milestone-manager/dist/types.d.ts.map +1 -1
- package/packages/milestone-manager/src/engine.ts +83 -91
- package/packages/milestone-manager/src/index.ts +2 -2
- package/packages/milestone-manager/src/types.ts +13 -13
- package/packages/notification/dist/adapters/line-adapter.d.ts +17 -0
- package/packages/notification/dist/adapters/line-adapter.d.ts.map +1 -0
- package/packages/notification/dist/adapters/line-adapter.js +99 -0
- package/packages/notification/dist/adapters/line-adapter.js.map +1 -0
- package/packages/notification/dist/index.d.ts +1 -0
- package/packages/notification/dist/index.d.ts.map +1 -1
- package/packages/notification/dist/index.js +1 -0
- package/packages/notification/dist/index.js.map +1 -1
- package/packages/notification/dist/notification-center.d.ts.map +1 -1
- package/packages/notification/dist/notification-center.js +4 -0
- package/packages/notification/dist/notification-center.js.map +1 -1
- package/packages/notification/dist/types.d.ts +6 -2
- package/packages/notification/dist/types.d.ts.map +1 -1
- package/packages/notification/src/adapters/line-adapter.ts +119 -0
- package/packages/notification/src/index.ts +1 -0
- package/packages/notification/src/notification-center.ts +6 -0
- package/packages/notification/src/types.ts +7 -2
- package/packages/project-bootstrap/dist/bootstrap.d.ts +1 -1
- package/packages/project-bootstrap/dist/bootstrap.d.ts.map +1 -1
- package/packages/project-bootstrap/dist/bootstrap.js +37 -45
- package/packages/project-bootstrap/dist/bootstrap.js.map +1 -1
- package/packages/project-bootstrap/dist/frappe.d.ts +1 -1
- package/packages/project-bootstrap/dist/frappe.d.ts.map +1 -1
- package/packages/project-bootstrap/dist/frappe.js +34 -34
- package/packages/project-bootstrap/dist/frappe.js.map +1 -1
- package/packages/project-bootstrap/dist/index.d.ts +5 -5
- package/packages/project-bootstrap/dist/index.js +5 -5
- package/packages/project-bootstrap/dist/minimal.d.ts +1 -1
- package/packages/project-bootstrap/dist/minimal.js +13 -13
- package/packages/project-bootstrap/dist/minimal.js.map +1 -1
- package/packages/project-bootstrap/dist/types.d.ts +1 -1
- package/packages/project-bootstrap/dist/types.d.ts.map +1 -1
- package/packages/project-bootstrap/dist/typescript.d.ts +1 -1
- package/packages/project-bootstrap/dist/typescript.d.ts.map +1 -1
- package/packages/project-bootstrap/dist/typescript.js +38 -38
- package/packages/project-bootstrap/dist/typescript.js.map +1 -1
- package/packages/project-bootstrap/src/bootstrap.ts +121 -136
- package/packages/project-bootstrap/src/frappe.ts +65 -71
- package/packages/project-bootstrap/src/index.ts +5 -5
- package/packages/project-bootstrap/src/minimal.ts +31 -31
- package/packages/project-bootstrap/src/types.ts +38 -38
- package/packages/project-bootstrap/src/typescript.ts +69 -78
- package/packages/provider-router/dist/src/types.js +1 -1
- package/packages/write-review/src/index.ts +47 -0
- package/packages/write-review/src/injection.ts +21 -1
- package/prompts/agents/reviewer.md +57 -0
- package/prompts/agents/writer.md +42 -0
- package/prompts/slash-commands.md +40 -0
- package/prompts/write-review.md +50 -0
- package/scripts/copy-plugins.js +56 -0
|
@@ -4,79 +4,73 @@
|
|
|
4
4
|
* Generate Mermaid diagrams.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import type {
|
|
8
|
-
ArchitectureDiagram,
|
|
9
|
-
DiagramType,
|
|
10
|
-
ArchitectureAnalysis,
|
|
11
|
-
} from "./types.js";
|
|
7
|
+
import type { ArchitectureDiagram, DiagramType, ArchitectureAnalysis } from './types.js';
|
|
12
8
|
|
|
13
9
|
/**
|
|
14
10
|
* Generate component diagram
|
|
15
11
|
*/
|
|
16
|
-
export function generateComponentDiagram(
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
}),
|
|
28
|
-
" end",
|
|
29
|
-
...analysis.dependencies.map((d) => ` ${d.from} --> ${d.to}`),
|
|
30
|
-
].join("\n");
|
|
12
|
+
export function generateComponentDiagram(analysis: ArchitectureAnalysis): ArchitectureDiagram {
|
|
13
|
+
const mermaid = [
|
|
14
|
+
'graph TB',
|
|
15
|
+
' subgraph Layers',
|
|
16
|
+
...analysis.layers.map((layer, i) => {
|
|
17
|
+
const nodes = analysis.components.filter((_, j) => j % analysis.layers.length === i);
|
|
18
|
+
return ` ${nodes.join(' --> ')}`;
|
|
19
|
+
}),
|
|
20
|
+
' end',
|
|
21
|
+
...analysis.dependencies.map(d => ` ${d.from} --> ${d.to}`),
|
|
22
|
+
].join('\n');
|
|
31
23
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
24
|
+
return {
|
|
25
|
+
type: 'component',
|
|
26
|
+
title: 'Architecture Components',
|
|
27
|
+
mermaid,
|
|
28
|
+
description: 'Component diagram showing layers and dependencies',
|
|
29
|
+
};
|
|
38
30
|
}
|
|
39
31
|
|
|
40
32
|
/**
|
|
41
33
|
* Generate sequence diagram
|
|
42
34
|
*/
|
|
43
35
|
export function generateSequenceDiagram(
|
|
44
|
-
|
|
45
|
-
|
|
36
|
+
title: string,
|
|
37
|
+
steps: { actor: string; action: string; target: string }[]
|
|
46
38
|
): ArchitectureDiagram {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
39
|
+
const mermaid = [
|
|
40
|
+
'sequenceDiagram',
|
|
41
|
+
...steps.map(
|
|
42
|
+
s => ` ${s.actor}->>+${s.target}: ${s.action}`
|
|
43
|
+
),
|
|
44
|
+
].join('\n');
|
|
51
45
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
46
|
+
return {
|
|
47
|
+
type: 'sequence',
|
|
48
|
+
title,
|
|
49
|
+
mermaid,
|
|
50
|
+
description: 'Sequence diagram showing interaction flow',
|
|
51
|
+
};
|
|
58
52
|
}
|
|
59
53
|
|
|
60
54
|
/**
|
|
61
55
|
* Generate flow diagram
|
|
62
56
|
*/
|
|
63
57
|
export function generateFlowDiagram(
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
58
|
+
title: string,
|
|
59
|
+
nodes: { id: string; label: string }[],
|
|
60
|
+
edges: { from: string; to: string; label?: string }[]
|
|
67
61
|
): ArchitectureDiagram {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
62
|
+
const mermaid = [
|
|
63
|
+
'flowchart LR',
|
|
64
|
+
...nodes.map(n => ` ${n.id}[${n.label}]`),
|
|
65
|
+
...edges.map(
|
|
66
|
+
e => ` ${e.from}${e.label ? `-->|"${e.label}"|` : '->>'}${e.to}`
|
|
67
|
+
),
|
|
68
|
+
].join('\n');
|
|
75
69
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
70
|
+
return {
|
|
71
|
+
type: 'flow',
|
|
72
|
+
title,
|
|
73
|
+
mermaid,
|
|
74
|
+
description: 'Flow diagram showing process flow',
|
|
75
|
+
};
|
|
82
76
|
}
|
|
@@ -4,27 +4,27 @@
|
|
|
4
4
|
* Generate ADR and Mermaid diagrams from project analysis.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
export type DiagramType =
|
|
7
|
+
export type DiagramType = 'component' | 'flow' | 'sequence' | 'er' | 'class';
|
|
8
8
|
|
|
9
9
|
export interface ArchitectureDiagram {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
type: DiagramType;
|
|
11
|
+
title: string;
|
|
12
|
+
mermaid: string;
|
|
13
|
+
description?: string;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
export interface ADR {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
17
|
+
id: string;
|
|
18
|
+
title: string;
|
|
19
|
+
status: 'proposed' | 'accepted' | 'deprecated';
|
|
20
|
+
context: string;
|
|
21
|
+
decision: string;
|
|
22
|
+
consequences: string;
|
|
23
|
+
createdAt: string;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
export interface ArchitectureAnalysis {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
components: string[];
|
|
28
|
+
dependencies: { from: string; to: string }[];
|
|
29
|
+
layers: string[];
|
|
30
30
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"copy-sync.d.ts","sourceRoot":"","sources":["../../src/copy-sync.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;
|
|
1
|
+
{"version":3,"file":"copy-sync.d.ts","sourceRoot":"","sources":["../../src/copy-sync.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AA8KH;;;GAGG;AACH,wBAAsB,WAAW,CAAC,GAAG,EAAE;IACtC,EAAE,EAAE;QAAE,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,KAAK,IAAI,CAAA;KAAE,CAAC;CACrD,GAAG,OAAO,CAAC,IAAI,CAAC,CAoChB;AAKD,KAAK,KAAK,GAAG,GAAG,CAAC;AAEjB;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,GAAG,IAAI,CAapE"}
|
|
@@ -65,9 +65,51 @@ function repairMojibake(text) {
|
|
|
65
65
|
return text;
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
|
-
// ───
|
|
68
|
+
// ─── Detect clipboard tool ──────────────────────────────────────────────────
|
|
69
|
+
/**
|
|
70
|
+
* Detect the best available system clipboard tool.
|
|
71
|
+
* Returns "wl-copy" (Wayland), "xclip" (X11), or null (none).
|
|
72
|
+
*/
|
|
73
|
+
function detectClipboardTool() {
|
|
74
|
+
const { spawnSync } = require("node:child_process");
|
|
75
|
+
// Wayland first (wl-copy is more modern)
|
|
76
|
+
if (spawnSync("wl-copy", ["--help"], { stdio: "ignore" }).status === 0) {
|
|
77
|
+
return "wl-copy";
|
|
78
|
+
}
|
|
79
|
+
// X11 fallback (xclip)
|
|
80
|
+
if (spawnSync("xclip", ["-help"], { stdio: "ignore" }).status === 0) {
|
|
81
|
+
return "xclip";
|
|
82
|
+
}
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
// ─── Read from system clipboard ───────────────────────────────────────────────
|
|
86
|
+
function readFromSystemClipboard(tool) {
|
|
87
|
+
const { execSync } = require("node:child_process");
|
|
88
|
+
try {
|
|
89
|
+
let cmd;
|
|
90
|
+
if (tool === "wl-copy") {
|
|
91
|
+
cmd = "wl-copy --primary --type text/plain 2>/dev/null || wl-copy 2>/dev/null || true";
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
cmd = "xclip -selection clipboard -o 2>/dev/null || true";
|
|
95
|
+
}
|
|
96
|
+
const content = execSync(cmd, { encoding: "utf8", timeout: 2000 }).trim();
|
|
97
|
+
return content || null;
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
// ─── Read from Xvfb clipboard (fallback) ──────────────────────────────────────
|
|
69
104
|
function readFromClipboard() {
|
|
70
|
-
// Try
|
|
105
|
+
// 1. Try system clipboard first (xclip/wl-copy - what herdr uses)
|
|
106
|
+
const tool = detectClipboardTool();
|
|
107
|
+
if (tool) {
|
|
108
|
+
const content = readFromSystemClipboard(tool);
|
|
109
|
+
if (content)
|
|
110
|
+
return repairMojibake(content);
|
|
111
|
+
}
|
|
112
|
+
// 2. Try Xvfb xclip (legacy fallback for headless servers)
|
|
71
113
|
try {
|
|
72
114
|
const content = execSync(`"${XCLIP_WRAPPER}" -selection clipboard -o 2>/dev/null || DISPLAY=:99 xclip -selection clipboard -o 2>/dev/null || true`, { encoding: "utf8", timeout: 2000 })
|
|
73
115
|
.trim()
|
|
@@ -79,7 +121,7 @@ function readFromClipboard() {
|
|
|
79
121
|
catch {
|
|
80
122
|
// Fall through
|
|
81
123
|
}
|
|
82
|
-
// Fallback: read bridge file directly
|
|
124
|
+
// 3. Fallback: read bridge file directly
|
|
83
125
|
try {
|
|
84
126
|
if (existsSync(BRIDGE_FILE)) {
|
|
85
127
|
const content = readFileSync(BRIDGE_FILE, "utf8").trim();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"copy-sync.js","sourceRoot":"","sources":["../../src/copy-sync.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAClE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,UAAU,EAAE,YAAY,IAAI,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAE/E,iFAAiF;AAEjF,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,kBAAkB,CAAC,CAAC;AACxD,MAAM,aAAa,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;AAEhE,iFAAiF;AAEjF;;;;;;;;;;;;;;GAcG;AACH,SAAS,UAAU,CAAC,IAAY;IAC/B,qEAAqE;IACrE,4EAA4E;IAC5E,MAAM,IAAI,GAAG,2CAA2C,CAAC;IACzD,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACxB,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,SAAS,cAAc,CAAC,IAAY;IACnC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAEnC,IAAI,CAAC;QACJ,qEAAqE;QACrE,mEAAmE;QACnE,mEAAmE;QACnE,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IACrD,CAAC;IAAC,MAAM,CAAC;QACR,oDAAoD;QACpD,OAAO,IAAI,CAAC;IACb,CAAC;AACF,CAAC;AAED,iFAAiF;AAEjF,SAAS,iBAAiB;IACzB,
|
|
1
|
+
{"version":3,"file":"copy-sync.js","sourceRoot":"","sources":["../../src/copy-sync.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export type { ClipboardContent, ClipboardOptions } from "./types.js";
|
|
2
2
|
export * from "./gist-relay.js";
|
|
3
3
|
export { registerGithubLoginCommand } from "./github-login.js";
|
|
4
|
+
export { pasteFromBridge, registerPasteShortcut } from "./paste-bridge.js";
|
|
4
5
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AACrE,cAAc,iBAAiB,CAAC;AAChC,OAAO,EAAE,0BAA0B,EAAE,MAAM,mBAAmB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AACrE,cAAc,iBAAiB,CAAC;AAChC,OAAO,EAAE,0BAA0B,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AACA,cAAc,iBAAiB,CAAC;AAChC,OAAO,EAAE,0BAA0B,EAAE,MAAM,mBAAmB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AACA,cAAc,iBAAiB,CAAC;AAChC,OAAO,EAAE,0BAA0B,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Paste Bridge — prefix+p shortcut for clipboard paste
|
|
3
|
+
*
|
|
4
|
+
* Reads content from the bridge file (~/.herdr-clipboard) and sends it
|
|
5
|
+
* to the terminal's active pane.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Read content from the bridge file.
|
|
9
|
+
* Returns null if the file doesn't exist or is empty.
|
|
10
|
+
*/
|
|
11
|
+
export declare function pasteFromBridge(): string | null;
|
|
12
|
+
type AnyPi = any;
|
|
13
|
+
/**
|
|
14
|
+
* Register prefix+p as the paste shortcut.
|
|
15
|
+
* Reads from bridge file and sends content to terminal.
|
|
16
|
+
*/
|
|
17
|
+
export declare function registerPasteShortcut(pi: AnyPi, Key: AnyPi): void;
|
|
18
|
+
export {};
|
|
19
|
+
//# sourceMappingURL=paste-bridge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paste-bridge.d.ts","sourceRoot":"","sources":["../../src/paste-bridge.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAkCH;;;GAGG;AACH,wBAAgB,eAAe,IAAI,MAAM,GAAG,IAAI,CAW/C;AAKD,KAAK,KAAK,GAAG,GAAG,CAAC;AAEjB;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,GAAG,IAAI,CAoBjE"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Paste Bridge — prefix+p shortcut for clipboard paste
|
|
3
|
+
*
|
|
4
|
+
* Reads content from the bridge file (~/.herdr-clipboard) and sends it
|
|
5
|
+
* to the terminal's active pane.
|
|
6
|
+
*/
|
|
7
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
8
|
+
import { join } from "node:path";
|
|
9
|
+
import { homedir } from "node:os";
|
|
10
|
+
// ─── Bridge file path ─────────────────────────────────────────────────────────
|
|
11
|
+
const BRIDGE_FILE = join(homedir(), ".herdr-clipboard");
|
|
12
|
+
// ─── Mojibake repair ──────────────────────────────────────────────────────────
|
|
13
|
+
/**
|
|
14
|
+
* Detect UTF-8 mojibake (double-encoding: UTF-8 → Latin-1 → UTF-8).
|
|
15
|
+
*/
|
|
16
|
+
function isMojibake(text) {
|
|
17
|
+
const moji = /[\u00e2\u00c2\u00e3\u00c3][\u0080-\u00ff]/;
|
|
18
|
+
return moji.test(text);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Repair UTF-8 mojibake.
|
|
22
|
+
*/
|
|
23
|
+
function repairMojibake(text) {
|
|
24
|
+
if (!isMojibake(text))
|
|
25
|
+
return text;
|
|
26
|
+
try {
|
|
27
|
+
return Buffer.from(text, "latin1").toString("utf8");
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return text;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
// ─── Read from bridge ─────────────────────────────────────────────────────────
|
|
34
|
+
/**
|
|
35
|
+
* Read content from the bridge file.
|
|
36
|
+
* Returns null if the file doesn't exist or is empty.
|
|
37
|
+
*/
|
|
38
|
+
export function pasteFromBridge() {
|
|
39
|
+
try {
|
|
40
|
+
if (!existsSync(BRIDGE_FILE)) {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
const content = readFileSync(BRIDGE_FILE, "utf8").trim();
|
|
44
|
+
if (!content)
|
|
45
|
+
return null;
|
|
46
|
+
return repairMojibake(content);
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Register prefix+p as the paste shortcut.
|
|
54
|
+
* Reads from bridge file and sends content to terminal.
|
|
55
|
+
*/
|
|
56
|
+
export function registerPasteShortcut(pi, Key) {
|
|
57
|
+
try {
|
|
58
|
+
pi.registerShortcut(Key.prefix("p"), {
|
|
59
|
+
description: "Paste from clipboard bridge",
|
|
60
|
+
handler: async (rawCtx) => {
|
|
61
|
+
const content = pasteFromBridge();
|
|
62
|
+
if (!content) {
|
|
63
|
+
rawCtx.ui.notify("Clipboard bridge is empty", "warning");
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
// Send content to terminal input
|
|
67
|
+
// The ctx.sendKeys approach depends on the runtime API
|
|
68
|
+
// For now, notify success - actual paste to terminal handled by runtime
|
|
69
|
+
rawCtx.ui.notify(`Pasting ${content.length} chars from bridge`, "info");
|
|
70
|
+
// TODO: Send keys to terminal pane when runtime API is available
|
|
71
|
+
},
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
catch (err) {
|
|
75
|
+
console.error("[paste-bridge] Failed to register shortcut:", err);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=paste-bridge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paste-bridge.js","sourceRoot":"","sources":["../../src/paste-bridge.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAElC,iFAAiF;AAEjF,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,kBAAkB,CAAC,CAAC;AAExD,iFAAiF;AAEjF;;GAEG;AACH,SAAS,UAAU,CAAC,IAAY;IAC/B,MAAM,IAAI,GAAG,2CAA2C,CAAC;IACzD,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACxB,CAAC;AAED;;GAEG;AACH,SAAS,cAAc,CAAC,IAAY;IACnC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACnC,IAAI,CAAC;QACJ,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IACrD,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,IAAI,CAAC;IACb,CAAC;AACF,CAAC;AAED,iFAAiF;AAEjF;;;GAGG;AACH,MAAM,UAAU,eAAe;IAC9B,IAAI,CAAC;QACJ,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;YAC9B,OAAO,IAAI,CAAC;QACb,CAAC;QACD,MAAM,OAAO,GAAG,YAAY,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;QACzD,IAAI,CAAC,OAAO;YAAE,OAAO,IAAI,CAAC;QAC1B,OAAO,cAAc,CAAC,OAAO,CAAC,CAAC;IAChC,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,IAAI,CAAC;IACb,CAAC;AACF,CAAC;AAOD;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CAAC,EAAS,EAAE,GAAU;IAC1D,IAAI,CAAC;QACJ,EAAE,CAAC,gBAAgB,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE;YACpC,WAAW,EAAE,6BAA6B;YAC1C,OAAO,EAAE,KAAK,EAAE,MAAa,EAAE,EAAE;gBAChC,MAAM,OAAO,GAAG,eAAe,EAAE,CAAC;gBAClC,IAAI,CAAC,OAAO,EAAE,CAAC;oBACd,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,2BAA2B,EAAE,SAAS,CAAC,CAAC;oBACzD,OAAO;gBACR,CAAC;gBACD,iCAAiC;gBACjC,uDAAuD;gBACvD,wEAAwE;gBACxE,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,WAAW,OAAO,CAAC,MAAM,oBAAoB,EAAE,MAAM,CAAC,CAAC;gBACxE,iEAAiE;YAClE,CAAC;SACD,CAAC,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACd,OAAO,CAAC,KAAK,CAAC,6CAA6C,EAAE,GAAG,CAAC,CAAC;IACnE,CAAC;AACF,CAAC"}
|
|
@@ -71,10 +71,59 @@ function repairMojibake(text: string): string {
|
|
|
71
71
|
}
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
-
// ───
|
|
74
|
+
// ─── Detect clipboard tool ──────────────────────────────────────────────────
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Detect the best available system clipboard tool.
|
|
78
|
+
* Returns "wl-copy" (Wayland), "xclip" (X11), or null (none).
|
|
79
|
+
*/
|
|
80
|
+
function detectClipboardTool(): string | null {
|
|
81
|
+
const { spawnSync } = require("node:child_process");
|
|
82
|
+
|
|
83
|
+
// Wayland first (wl-copy is more modern)
|
|
84
|
+
if (spawnSync("wl-copy", ["--help"], { stdio: "ignore" }).status === 0) {
|
|
85
|
+
return "wl-copy";
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// X11 fallback (xclip)
|
|
89
|
+
if (spawnSync("xclip", ["-help"], { stdio: "ignore" }).status === 0) {
|
|
90
|
+
return "xclip";
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// ─── Read from system clipboard ───────────────────────────────────────────────
|
|
97
|
+
|
|
98
|
+
function readFromSystemClipboard(tool: string): string | null {
|
|
99
|
+
const { execSync } = require("node:child_process");
|
|
100
|
+
|
|
101
|
+
try {
|
|
102
|
+
let cmd: string;
|
|
103
|
+
if (tool === "wl-copy") {
|
|
104
|
+
cmd = "wl-copy --primary --type text/plain 2>/dev/null || wl-copy 2>/dev/null || true";
|
|
105
|
+
} else {
|
|
106
|
+
cmd = "xclip -selection clipboard -o 2>/dev/null || true";
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const content = execSync(cmd, { encoding: "utf8", timeout: 2000 }).trim();
|
|
110
|
+
return content || null;
|
|
111
|
+
} catch {
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// ─── Read from Xvfb clipboard (fallback) ──────────────────────────────────────
|
|
75
117
|
|
|
76
118
|
function readFromClipboard(): string | null {
|
|
77
|
-
// Try
|
|
119
|
+
// 1. Try system clipboard first (xclip/wl-copy - what herdr uses)
|
|
120
|
+
const tool = detectClipboardTool();
|
|
121
|
+
if (tool) {
|
|
122
|
+
const content = readFromSystemClipboard(tool);
|
|
123
|
+
if (content) return repairMojibake(content);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// 2. Try Xvfb xclip (legacy fallback for headless servers)
|
|
78
127
|
try {
|
|
79
128
|
const content = execSync(
|
|
80
129
|
`"${XCLIP_WRAPPER}" -selection clipboard -o 2>/dev/null || DISPLAY=:99 xclip -selection clipboard -o 2>/dev/null || true`,
|
|
@@ -89,7 +138,7 @@ function readFromClipboard(): string | null {
|
|
|
89
138
|
// Fall through
|
|
90
139
|
}
|
|
91
140
|
|
|
92
|
-
// Fallback: read bridge file directly
|
|
141
|
+
// 3. Fallback: read bridge file directly
|
|
93
142
|
try {
|
|
94
143
|
if (existsSync(BRIDGE_FILE)) {
|
|
95
144
|
const content = readFileSync(BRIDGE_FILE, "utf8").trim();
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Paste Bridge — prefix+p shortcut for clipboard paste
|
|
3
|
+
*
|
|
4
|
+
* Reads content from the bridge file (~/.herdr-clipboard) and sends it
|
|
5
|
+
* to the terminal's active pane.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
9
|
+
import { join } from "node:path";
|
|
10
|
+
import { homedir } from "node:os";
|
|
11
|
+
|
|
12
|
+
// ─── Bridge file path ─────────────────────────────────────────────────────────
|
|
13
|
+
|
|
14
|
+
const BRIDGE_FILE = join(homedir(), ".herdr-clipboard");
|
|
15
|
+
|
|
16
|
+
// ─── Mojibake repair ──────────────────────────────────────────────────────────
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Detect UTF-8 mojibake (double-encoding: UTF-8 → Latin-1 → UTF-8).
|
|
20
|
+
*/
|
|
21
|
+
function isMojibake(text: string): boolean {
|
|
22
|
+
const moji = /[\u00e2\u00c2\u00e3\u00c3][\u0080-\u00ff]/;
|
|
23
|
+
return moji.test(text);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Repair UTF-8 mojibake.
|
|
28
|
+
*/
|
|
29
|
+
function repairMojibake(text: string): string {
|
|
30
|
+
if (!isMojibake(text)) return text;
|
|
31
|
+
try {
|
|
32
|
+
return Buffer.from(text, "latin1").toString("utf8");
|
|
33
|
+
} catch {
|
|
34
|
+
return text;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// ─── Read from bridge ─────────────────────────────────────────────────────────
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Read content from the bridge file.
|
|
42
|
+
* Returns null if the file doesn't exist or is empty.
|
|
43
|
+
*/
|
|
44
|
+
export function pasteFromBridge(): string | null {
|
|
45
|
+
try {
|
|
46
|
+
if (!existsSync(BRIDGE_FILE)) {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
const content = readFileSync(BRIDGE_FILE, "utf8").trim();
|
|
50
|
+
if (!content) return null;
|
|
51
|
+
return repairMojibake(content);
|
|
52
|
+
} catch {
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// ─── Register shortcut ────────────────────────────────────────────────────────
|
|
58
|
+
|
|
59
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
60
|
+
type AnyPi = any;
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Register prefix+p as the paste shortcut.
|
|
64
|
+
* Reads from bridge file and sends content to terminal.
|
|
65
|
+
*/
|
|
66
|
+
export function registerPasteShortcut(pi: AnyPi, Key: AnyPi): void {
|
|
67
|
+
try {
|
|
68
|
+
pi.registerShortcut(Key.prefix("p"), {
|
|
69
|
+
description: "Paste from clipboard bridge",
|
|
70
|
+
handler: async (rawCtx: AnyPi) => {
|
|
71
|
+
const content = pasteFromBridge();
|
|
72
|
+
if (!content) {
|
|
73
|
+
rawCtx.ui.notify("Clipboard bridge is empty", "warning");
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
// Send content to terminal input
|
|
77
|
+
// The ctx.sendKeys approach depends on the runtime API
|
|
78
|
+
// For now, notify success - actual paste to terminal handled by runtime
|
|
79
|
+
rawCtx.ui.notify(`Pasting ${content.length} chars from bridge`, "info");
|
|
80
|
+
// TODO: Send keys to terminal pane when runtime API is available
|
|
81
|
+
},
|
|
82
|
+
});
|
|
83
|
+
} catch (err) {
|
|
84
|
+
console.error("[paste-bridge] Failed to register shortcut:", err);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Clipboard Bridge Plugin — Main Entry
|
|
3
|
+
*
|
|
4
|
+
* Provides clipboard bridge functionality as a pi plugin.
|
|
5
|
+
* Integrates paste-from-bridge and paste shortcut registration.
|
|
6
|
+
*/
|
|
7
|
+
import type { FrameworkExtension, ToolExtension } from "@pi/framework-plugin-sdk";
|
|
8
|
+
export type { ClipboardBridgeConfig } from "./types.js";
|
|
9
|
+
/**
|
|
10
|
+
* Create a clipboard bridge tool plugin.
|
|
11
|
+
* Provides paste-from-bridge functionality.
|
|
12
|
+
*/
|
|
13
|
+
export declare function createClipboardBridgeTool(): ToolExtension;
|
|
14
|
+
/**
|
|
15
|
+
* Create a clipboard bridge framework extension.
|
|
16
|
+
* For framework detection compatibility.
|
|
17
|
+
*/
|
|
18
|
+
export declare function createClipboardBridgePlugin(): FrameworkExtension;
|
|
19
|
+
/**
|
|
20
|
+
* Register the paste shortcut with pi runtime.
|
|
21
|
+
* Call this during plugin activation.
|
|
22
|
+
*/
|
|
23
|
+
export declare function registerPasteShortcutHandler(pi: unknown, Key: unknown): void;
|
|
24
|
+
/**
|
|
25
|
+
* Default plugin export.
|
|
26
|
+
*/
|
|
27
|
+
export default createClipboardBridgeTool;
|
|
28
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAGlF,YAAY,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAExD;;;GAGG;AACH,wBAAgB,yBAAyB,IAAI,aAAa,CAqBzD;AAED;;;GAGG;AACH,wBAAgB,2BAA2B,IAAI,kBAAkB,CAahE;AAED;;;GAGG;AACH,wBAAgB,4BAA4B,CAC3C,EAAE,EAAE,OAAO,EACX,GAAG,EAAE,OAAO,GACV,IAAI,CAGN;AAED;;GAEG;eACY,yBAAyB"}
|