pi-xurl 0.1.0
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 +35 -0
- package/index.ts +141 -0
- package/package.json +39 -0
package/README.md
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# pi-xurl
|
|
2
|
+
|
|
3
|
+
Cross-agent thread reader. Resolve `agents://` URIs for Amp, Codex, Claude, Gemini, Pi, and OpenCode.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pi install npm:pi-xurl
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Requires [`@xuanwo/xurl`](https://github.com/Xuanwo/xurl) (invoked via `npx`).
|
|
12
|
+
|
|
13
|
+
## Tool: `xurl`
|
|
14
|
+
|
|
15
|
+
Resolve and read AI agent thread content by URI.
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
agents://codex/019c871c-b1f9-7f60-9c4f-87ed09f13592
|
|
19
|
+
agents://claude/2823d1df-720a-4c31-ac55-ae8ba726721f
|
|
20
|
+
pi://12cb4c19-2774-4de4-a0d0-9fa32fbae29f
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Parameters:
|
|
24
|
+
|
|
25
|
+
- `uri` (required) — thread URI
|
|
26
|
+
- `raw` — output raw JSON instead of markdown
|
|
27
|
+
- `list` — list subagents/entries for discovery
|
|
28
|
+
|
|
29
|
+
## Command: `/xurl`
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
/xurl <uri> [--raw] [--list]
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Shows short output inline, suggests tool for longer results.
|
package/index.ts
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* xurl Extension — resolve AI agent thread URIs from Pi
|
|
3
|
+
*
|
|
4
|
+
* Wraps Xuanwo/xurl (https://github.com/Xuanwo/xurl) as a Pi tool.
|
|
5
|
+
* Resolves agents:// URIs for Amp, Codex, Claude, Gemini, Pi, and OpenCode threads.
|
|
6
|
+
*
|
|
7
|
+
* Tool: xurl — resolve and read agent thread content by URI
|
|
8
|
+
* Command: /xurl <uri> [--raw] [--list]
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
|
12
|
+
import {
|
|
13
|
+
truncateHead,
|
|
14
|
+
DEFAULT_MAX_BYTES,
|
|
15
|
+
DEFAULT_MAX_LINES,
|
|
16
|
+
formatSize,
|
|
17
|
+
} from "@mariozechner/pi-coding-agent";
|
|
18
|
+
import { Type } from "@sinclair/typebox";
|
|
19
|
+
|
|
20
|
+
const XURL_CMD = "npx";
|
|
21
|
+
const XURL_ARGS = ["@xuanwo/xurl"];
|
|
22
|
+
|
|
23
|
+
export default function (pi: ExtensionAPI) {
|
|
24
|
+
pi.registerTool({
|
|
25
|
+
name: "xurl",
|
|
26
|
+
label: "xurl",
|
|
27
|
+
description: `Resolve and read AI agent thread content by URI.
|
|
28
|
+
|
|
29
|
+
Supports unified agents:// URIs and legacy provider URIs for: Amp, Codex, Claude, Gemini, Pi, OpenCode.
|
|
30
|
+
|
|
31
|
+
URI format: agents://<provider>/<thread_path>
|
|
32
|
+
Legacy: codex://<id>, claude://<id>, pi://<id>, amp://<id>, gemini://<id>, opencode://<id>
|
|
33
|
+
|
|
34
|
+
Examples:
|
|
35
|
+
agents://codex/019c871c-b1f9-7f60-9c4f-87ed09f13592
|
|
36
|
+
agents://claude/2823d1df-720a-4c31-ac55-ae8ba726721f
|
|
37
|
+
agents://pi/12cb4c19-2774-4de4-a0d0-9fa32fbae29f
|
|
38
|
+
|
|
39
|
+
Use raw=true for JSON output. Use list=true to discover subagents/entries before drilling down.`,
|
|
40
|
+
parameters: Type.Object({
|
|
41
|
+
uri: Type.String({
|
|
42
|
+
description: "Thread URI (e.g. agents://codex/<id>, agents://claude/<id>, pi://<id>)",
|
|
43
|
+
}),
|
|
44
|
+
raw: Type.Optional(
|
|
45
|
+
Type.Boolean({
|
|
46
|
+
description: "Output raw JSON instead of markdown (default: false)",
|
|
47
|
+
})
|
|
48
|
+
),
|
|
49
|
+
list: Type.Optional(
|
|
50
|
+
Type.Boolean({
|
|
51
|
+
description:
|
|
52
|
+
"List subagents (Codex/Claude) or session entries (Pi) for discovery. Use with main thread URI only.",
|
|
53
|
+
})
|
|
54
|
+
),
|
|
55
|
+
}),
|
|
56
|
+
|
|
57
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
58
|
+
async execute(_toolCallId, params, signal): Promise<any> {
|
|
59
|
+
const args = [...XURL_ARGS, params.uri];
|
|
60
|
+
if (params.raw) args.push("--raw");
|
|
61
|
+
if (params.list) args.push("--list");
|
|
62
|
+
|
|
63
|
+
const result = await pi.exec(XURL_CMD, args, {
|
|
64
|
+
signal,
|
|
65
|
+
timeout: 30_000,
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
if (result.code !== 0) {
|
|
69
|
+
const stderr = result.stderr?.trim() || "unknown error";
|
|
70
|
+
return {
|
|
71
|
+
content: [
|
|
72
|
+
{ type: "text" as const, text: `xurl failed (exit ${result.code}): ${stderr}` },
|
|
73
|
+
],
|
|
74
|
+
details: { exitCode: result.code, error: stderr },
|
|
75
|
+
isError: true,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const output = result.stdout;
|
|
80
|
+
const truncation = truncateHead(output, {
|
|
81
|
+
maxLines: DEFAULT_MAX_LINES,
|
|
82
|
+
maxBytes: DEFAULT_MAX_BYTES,
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
let text = truncation.content;
|
|
86
|
+
if (truncation.truncated) {
|
|
87
|
+
text += `\n\n[Output truncated: ${truncation.outputLines} of ${truncation.totalLines} lines`;
|
|
88
|
+
text += ` (${formatSize(truncation.outputBytes)} of ${formatSize(truncation.totalBytes)})]`;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return {
|
|
92
|
+
content: [{ type: "text" as const, text }],
|
|
93
|
+
details: {
|
|
94
|
+
uri: params.uri,
|
|
95
|
+
raw: params.raw ?? false,
|
|
96
|
+
list: params.list ?? false,
|
|
97
|
+
truncated: truncation.truncated,
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
},
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
pi.registerCommand("xurl", {
|
|
104
|
+
description: "Resolve an agent thread URI (usage: /xurl <uri> [--raw] [--list])",
|
|
105
|
+
handler: async (argsStr, ctx) => {
|
|
106
|
+
if (!argsStr?.trim()) {
|
|
107
|
+
ctx.ui.notify("Usage: /xurl <uri> [--raw] [--list]", "warning");
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const parts = argsStr.trim().split(/\s+/);
|
|
112
|
+
const uri = parts.find((p) => !p.startsWith("--"));
|
|
113
|
+
const raw = parts.includes("--raw");
|
|
114
|
+
const list = parts.includes("--list");
|
|
115
|
+
|
|
116
|
+
if (!uri) {
|
|
117
|
+
ctx.ui.notify("No URI provided. Usage: /xurl <uri> [--raw] [--list]", "warning");
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const args = [...XURL_ARGS, uri];
|
|
122
|
+
if (raw) args.push("--raw");
|
|
123
|
+
if (list) args.push("--list");
|
|
124
|
+
|
|
125
|
+
const result = await pi.exec(XURL_CMD, args, { timeout: 30_000 });
|
|
126
|
+
|
|
127
|
+
if (result.code !== 0) {
|
|
128
|
+
ctx.ui.notify(`xurl failed: ${result.stderr?.trim() || "unknown error"}`, "error");
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const output = result.stdout.trim();
|
|
133
|
+
const lines = output.split("\n");
|
|
134
|
+
if (lines.length <= 10) {
|
|
135
|
+
ctx.ui.notify(output, "info");
|
|
136
|
+
} else {
|
|
137
|
+
ctx.ui.notify(`${lines.length} lines returned. Use the xurl tool for full output.`, "info");
|
|
138
|
+
}
|
|
139
|
+
},
|
|
140
|
+
});
|
|
141
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "pi-xurl",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Cross-agent thread reader — resolve agents:// URIs for Amp, Codex, Claude, Gemini, Pi, OpenCode",
|
|
6
|
+
"main": "./index.ts",
|
|
7
|
+
"keywords": [
|
|
8
|
+
"pi",
|
|
9
|
+
"pi-extension",
|
|
10
|
+
"pi-package",
|
|
11
|
+
"xurl",
|
|
12
|
+
"agent-threads",
|
|
13
|
+
"codex",
|
|
14
|
+
"claude"
|
|
15
|
+
],
|
|
16
|
+
"author": "Edmund Miller <edmundmiller@hey.com>",
|
|
17
|
+
"license": "MIT",
|
|
18
|
+
"repository": {
|
|
19
|
+
"type": "git",
|
|
20
|
+
"url": "git+https://github.com/edmundmiller/dotfiles.git",
|
|
21
|
+
"directory": "pi-packages/pi-xurl"
|
|
22
|
+
},
|
|
23
|
+
"files": [
|
|
24
|
+
"index.ts",
|
|
25
|
+
"README.md"
|
|
26
|
+
],
|
|
27
|
+
"peerDependencies": {
|
|
28
|
+
"@mariozechner/pi-coding-agent": "*",
|
|
29
|
+
"@sinclair/typebox": "*"
|
|
30
|
+
},
|
|
31
|
+
"pi": {
|
|
32
|
+
"extensions": [
|
|
33
|
+
"./index.ts"
|
|
34
|
+
]
|
|
35
|
+
},
|
|
36
|
+
"scripts": {
|
|
37
|
+
"typecheck": "tsc --noEmit"
|
|
38
|
+
}
|
|
39
|
+
}
|