@saifymatteo/pi-extensions 0.1.1 → 0.1.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/README.md +38 -32
- package/package.json +9 -3
- package/packages/pi-bg-bash/README.md +4 -0
- package/packages/pi-bg-bash/package.json +4 -2
- package/packages/pi-claude-usage/README.md +5 -1
- package/packages/pi-claude-usage/package.json +4 -2
- package/packages/pi-claude-usage/src/index.ts +10 -1
- package/packages/pi-claude-usage/test/behavior.test.mjs +71 -0
- package/packages/pi-clipboard-image/README.md +4 -0
- package/packages/pi-clipboard-image/package.json +4 -2
- package/packages/pi-codeblock-borders/README.md +4 -0
- package/packages/pi-codeblock-borders/package.json +4 -2
- package/packages/pi-codegraph/README.md +4 -0
- package/packages/pi-codegraph/package.json +4 -2
- package/packages/pi-compact-tools/README.md +4 -0
- package/packages/pi-compact-tools/package.json +4 -2
- package/packages/pi-decisions/README.md +4 -0
- package/packages/pi-decisions/package.json +4 -2
- package/packages/pi-load-pi-dotenv/README.md +4 -0
- package/packages/pi-load-pi-dotenv/package.json +4 -2
- package/packages/pi-model-go/README.md +4 -0
- package/packages/pi-model-go/package.json +4 -2
- package/packages/pi-prestart-working/README.md +4 -0
- package/packages/pi-prestart-working/package.json +4 -2
- package/packages/pi-root-guard/README.md +4 -0
- package/packages/pi-root-guard/package.json +4 -2
- package/packages/pi-session-finder/README.md +4 -0
- package/packages/pi-session-finder/package.json +4 -2
- package/packages/pi-session-id/README.md +4 -0
- package/packages/pi-session-id/package.json +4 -2
- package/packages/pi-session-nav/README.md +4 -0
- package/packages/pi-session-nav/package.json +4 -2
- package/packages/pi-session-rename/README.md +4 -0
- package/packages/pi-session-rename/package.json +4 -2
- package/packages/pi-session-retention/README.md +4 -0
- package/packages/pi-session-retention/package.json +4 -2
- package/packages/pi-skill-usage-log/README.md +4 -0
- package/packages/pi-skill-usage-log/package.json +4 -2
- package/packages/pi-tool-usage-log/README.md +4 -0
- package/packages/pi-tool-usage-log/package.json +4 -2
- package/packages/pi-tts/README.md +4 -0
- package/packages/pi-tts/package.json +4 -2
- package/packages/pi-user-image-previews/README.md +4 -0
- package/packages/pi-user-image-previews/package.json +4 -2
- package/packages/pi-vision/README.md +5 -1
- package/packages/pi-vision/package.json +5 -2
- package/packages/pi-vision/skills/vision-tools/SKILL.md +37 -21
- package/packages/pi-vision/skills/vision-tools/references/long-screenshot-ocr.md +7 -7
- package/packages/pi-vision/skills/vision-tools/references/restore-graphic.md +7 -7
- package/packages/pi-vision/skills/vision-tools/references/restore-ui.md +4 -4
- package/packages/pi-vision/skills/vision-tools/scripts/long_screenshot_ocr.py +4 -4
- package/packages/pi-vision/test/skill-cli.test.mjs +71 -0
- package/packages/pi-wait/README.md +4 -0
- package/packages/pi-wait/package.json +4 -2
- package/packages/pi-zvec/README.md +4 -0
- package/packages/pi-zvec/package.json +4 -2
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# pi-session-finder
|
|
2
2
|
|
|
3
|
+

|
|
4
|
+
|
|
5
|
+
*`/session-global` searches saved sessions across all projects. They are grouped by folder, with forks nested under their parent.*
|
|
6
|
+
|
|
3
7
|
Search saved sessions across projects, display their fork families, and open or fork a conversation into the current project.
|
|
4
8
|
|
|
5
9
|
## Running locally
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@saifymatteo/pi-session-finder",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"license": "AGPL-3.0-only",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [
|
|
7
|
-
"pi-package"
|
|
7
|
+
"pi-package",
|
|
8
|
+
"pi-extension"
|
|
8
9
|
],
|
|
9
10
|
"files": [
|
|
10
11
|
"src",
|
|
@@ -13,6 +14,7 @@
|
|
|
13
14
|
"LICENSE"
|
|
14
15
|
],
|
|
15
16
|
"pi": {
|
|
17
|
+
"image": "https://raw.githubusercontent.com/saifymatteo/pi-extensions/main/packages/pi-session-finder/screenshot.png",
|
|
16
18
|
"extensions": [
|
|
17
19
|
"./src/index.ts"
|
|
18
20
|
]
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@saifymatteo/pi-session-id",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"license": "AGPL-3.0-only",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [
|
|
7
|
-
"pi-package"
|
|
7
|
+
"pi-package",
|
|
8
|
+
"pi-extension"
|
|
8
9
|
],
|
|
9
10
|
"files": [
|
|
10
11
|
"src",
|
|
@@ -13,6 +14,7 @@
|
|
|
13
14
|
"LICENSE"
|
|
14
15
|
],
|
|
15
16
|
"pi": {
|
|
17
|
+
"image": "https://raw.githubusercontent.com/saifymatteo/pi-extensions/main/packages/pi-session-id/screenshot.png",
|
|
16
18
|
"extensions": [
|
|
17
19
|
"./src/index.ts"
|
|
18
20
|
]
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# pi-session-nav
|
|
2
2
|
|
|
3
|
+

|
|
4
|
+
|
|
5
|
+
*Alt+O lists the conversation's messages. Pick one and press Enter to jump to it.*
|
|
6
|
+
|
|
3
7
|
Navigate visible user and assistant messages on the active conversation branch without adding transcript entries.
|
|
4
8
|
|
|
5
9
|
## Running locally
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@saifymatteo/pi-session-nav",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"license": "AGPL-3.0-only",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [
|
|
7
|
-
"pi-package"
|
|
7
|
+
"pi-package",
|
|
8
|
+
"pi-extension"
|
|
8
9
|
],
|
|
9
10
|
"files": [
|
|
10
11
|
"src",
|
|
@@ -13,6 +14,7 @@
|
|
|
13
14
|
"LICENSE"
|
|
14
15
|
],
|
|
15
16
|
"pi": {
|
|
17
|
+
"image": "https://raw.githubusercontent.com/saifymatteo/pi-extensions/main/packages/pi-session-nav/screenshot.png",
|
|
16
18
|
"extensions": [
|
|
17
19
|
"./src/index.ts"
|
|
18
20
|
]
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# pi-session-rename
|
|
2
2
|
|
|
3
|
+

|
|
4
|
+
|
|
5
|
+
*After the first prompt, the session gets a generated title. It appears in the footer and in the terminal tab title.*
|
|
6
|
+
|
|
3
7
|
Automatically title main interactive sessions from the first submitted prompt and optionally mirror the name to a Herdr tab. Manual names take precedence; failed generation retries on later prompts.
|
|
4
8
|
|
|
5
9
|
## Running locally
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@saifymatteo/pi-session-rename",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"license": "AGPL-3.0-only",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [
|
|
7
|
-
"pi-package"
|
|
7
|
+
"pi-package",
|
|
8
|
+
"pi-extension"
|
|
8
9
|
],
|
|
9
10
|
"files": [
|
|
10
11
|
"src",
|
|
@@ -13,6 +14,7 @@
|
|
|
13
14
|
"LICENSE"
|
|
14
15
|
],
|
|
15
16
|
"pi": {
|
|
17
|
+
"image": "https://raw.githubusercontent.com/saifymatteo/pi-extensions/main/packages/pi-session-rename/screenshot.png",
|
|
16
18
|
"extensions": [
|
|
17
19
|
"./src/index.ts"
|
|
18
20
|
]
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@saifymatteo/pi-session-retention",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"license": "AGPL-3.0-only",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [
|
|
7
|
-
"pi-package"
|
|
7
|
+
"pi-package",
|
|
8
|
+
"pi-extension"
|
|
8
9
|
],
|
|
9
10
|
"files": [
|
|
10
11
|
"src",
|
|
@@ -13,6 +14,7 @@
|
|
|
13
14
|
"LICENSE"
|
|
14
15
|
],
|
|
15
16
|
"pi": {
|
|
17
|
+
"image": "https://raw.githubusercontent.com/saifymatteo/pi-extensions/main/packages/pi-session-retention/screenshot.png",
|
|
16
18
|
"extensions": [
|
|
17
19
|
"./src/index.ts"
|
|
18
20
|
]
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# pi-skill-usage-log
|
|
2
2
|
|
|
3
|
+

|
|
4
|
+
|
|
5
|
+
*`/skill-usage` shows which installed skills were loaded and which were actually used, across all projects.*
|
|
6
|
+
|
|
3
7
|
Passively record skill loads and subsequent tool activity, then show cross-project usage without adding the report to conversation context.
|
|
4
8
|
|
|
5
9
|
## Running locally
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@saifymatteo/pi-skill-usage-log",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"license": "AGPL-3.0-only",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [
|
|
7
|
-
"pi-package"
|
|
7
|
+
"pi-package",
|
|
8
|
+
"pi-extension"
|
|
8
9
|
],
|
|
9
10
|
"files": [
|
|
10
11
|
"src",
|
|
@@ -13,6 +14,7 @@
|
|
|
13
14
|
"LICENSE"
|
|
14
15
|
],
|
|
15
16
|
"pi": {
|
|
17
|
+
"image": "https://raw.githubusercontent.com/saifymatteo/pi-extensions/main/packages/pi-skill-usage-log/screenshot.png",
|
|
16
18
|
"extensions": [
|
|
17
19
|
"./src/index.ts"
|
|
18
20
|
]
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# pi-tool-usage-log
|
|
2
2
|
|
|
3
|
+

|
|
4
|
+
|
|
5
|
+
*`/tool-usage` totals every tool call: count, sessions, errors, nested calls, average duration and last use.*
|
|
6
|
+
|
|
3
7
|
Passively record direct and nested tool executions and show aggregate usage, errors, duration, selected model and thinking level.
|
|
4
8
|
|
|
5
9
|
## Running locally
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@saifymatteo/pi-tool-usage-log",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"license": "AGPL-3.0-only",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [
|
|
7
|
-
"pi-package"
|
|
7
|
+
"pi-package",
|
|
8
|
+
"pi-extension"
|
|
8
9
|
],
|
|
9
10
|
"files": [
|
|
10
11
|
"src",
|
|
@@ -13,6 +14,7 @@
|
|
|
13
14
|
"LICENSE"
|
|
14
15
|
],
|
|
15
16
|
"pi": {
|
|
17
|
+
"image": "https://raw.githubusercontent.com/saifymatteo/pi-extensions/main/packages/pi-tool-usage-log/screenshot.png",
|
|
16
18
|
"extensions": [
|
|
17
19
|
"./src/index.ts"
|
|
18
20
|
]
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# @saifymatteo/pi-tts
|
|
2
2
|
|
|
3
|
+

|
|
4
|
+
|
|
5
|
+
*The agent calls `text_to_speech`, and the WAV file from the configured speech endpoint is saved into the project.*
|
|
6
|
+
|
|
3
7
|
## Purpose and registrations
|
|
4
8
|
|
|
5
9
|
Registers `text_to_speech` when the registry has a `type: "tts"` model; no slash commands or playback. Sends narration to a service and saves a new WAV, never overwriting an existing output. Uses standard fetch/streams and Pi tool registration; requires filesystem hard-link support for atomic publication.
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@saifymatteo/pi-tts",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"license": "AGPL-3.0-only",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [
|
|
7
|
-
"pi-package"
|
|
7
|
+
"pi-package",
|
|
8
|
+
"pi-extension"
|
|
8
9
|
],
|
|
9
10
|
"files": [
|
|
10
11
|
"src",
|
|
@@ -14,6 +15,7 @@
|
|
|
14
15
|
"LICENSE"
|
|
15
16
|
],
|
|
16
17
|
"pi": {
|
|
18
|
+
"image": "https://raw.githubusercontent.com/saifymatteo/pi-extensions/main/packages/pi-tts/screenshot.png",
|
|
17
19
|
"extensions": [
|
|
18
20
|
"./src/index.ts"
|
|
19
21
|
]
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# Inline user image previews
|
|
2
2
|
|
|
3
|
+

|
|
4
|
+
|
|
5
|
+
*An attached image gets a collapsible preview row in the transcript. Ctrl+O opens it inline. Stock pi shows nothing.*
|
|
6
|
+
|
|
3
7
|
Adds collapsible UI-only previews for newly submitted image attachments.
|
|
4
8
|
|
|
5
9
|
## Try locally
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@saifymatteo/pi-user-image-previews",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "Adds collapsible UI-only previews for newly submitted image attachments.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "AGPL-3.0-only",
|
|
7
7
|
"keywords": [
|
|
8
|
-
"pi-package"
|
|
8
|
+
"pi-package",
|
|
9
|
+
"pi-extension"
|
|
9
10
|
],
|
|
10
11
|
"files": [
|
|
11
12
|
"src",
|
|
@@ -14,6 +15,7 @@
|
|
|
14
15
|
"LICENSE"
|
|
15
16
|
],
|
|
16
17
|
"pi": {
|
|
18
|
+
"image": "https://raw.githubusercontent.com/saifymatteo/pi-extensions/main/packages/pi-user-image-previews/screenshot.png",
|
|
17
19
|
"extensions": [
|
|
18
20
|
"./src/index.ts"
|
|
19
21
|
]
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# @saifymatteo/pi-vision
|
|
2
2
|
|
|
3
|
+

|
|
4
|
+
|
|
5
|
+
*The main model here is text-only. Stock pi drops the image. With pi-vision, a configured vision model describes the image and the main model works from that description.*
|
|
6
|
+
|
|
3
7
|
## Purpose and registrations
|
|
4
8
|
|
|
5
9
|
Registers a `context` hook, not a tool or slash command. Preserves native images for image-capable session models by default. For text-only/unknown models it replaces image blocks with model-generated descriptions. Optional `describe` / `describe-old` policies self-describe all/older images using the current model on OpenAI Chat Completions connections.
|
|
@@ -12,7 +16,7 @@ Resolution also consults agent `models.json`, `models-store.json`, `auth.json`,
|
|
|
12
16
|
|
|
13
17
|
## Bundled skill
|
|
14
18
|
|
|
15
|
-
The package bundles the `vision-tools` skill (`skills/vision-tools`): `bin/` launcher CLIs (`crop`, `detect`, `glance`, `ground`, `trace`, `vision-doctor`), Python tools under `scripts/`, reference guides, and `SKILL.md`. The extension's guidance messages point the agent at `vision-doctor` and the skill. Requires Python 3 with Pillow (PIL); the CLIs are Python scripts, not compiled binaries. Based on [Anionex/agent-vision-toolkit](https://github.com/Anionex/agent-vision-toolkit) (MIT), modified in this repository — see [NOTICE.md](NOTICE.md).
|
|
19
|
+
The package bundles the `vision-tools` skill (`skills/vision-tools`): `bin/` launcher CLIs (`crop`, `detect`, `glance`, `ground`, `trace`, `vision-doctor`), Python tools under `scripts/`, reference guides, and `SKILL.md`. Invoke the launchers with Python and their absolute skill-relative paths, for example `python3 "<skill-directory>/bin/crop" image.png --region 0,0,100,100 -o detail.png`. Follow the interpreter-selection guidance in `SKILL.md` if Windows exposes Python as `python` or `py -3`. No PATH registration, executable bit, or agent-home shim is required. The extension does not modify PATH. Automated long-screenshot OCR prefers the bundled `bin/glance` with the current Python interpreter, falling back to PATH only if that script is missing. The extension's guidance messages point the agent at `vision-doctor` and the skill. Requires Python 3 with Pillow (PIL); the CLIs are Python scripts, not compiled binaries. Based on [Anionex/agent-vision-toolkit](https://github.com/Anionex/agent-vision-toolkit) (MIT), modified in this repository — see [NOTICE.md](NOTICE.md).
|
|
16
20
|
|
|
17
21
|
## Host limitations and security
|
|
18
22
|
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@saifymatteo/pi-vision",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"license": "AGPL-3.0-only",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [
|
|
7
|
-
"pi-package"
|
|
7
|
+
"pi-package",
|
|
8
|
+
"pi-extension",
|
|
9
|
+
"pi-skill"
|
|
8
10
|
],
|
|
9
11
|
"files": [
|
|
10
12
|
"src",
|
|
@@ -15,6 +17,7 @@
|
|
|
15
17
|
"skills"
|
|
16
18
|
],
|
|
17
19
|
"pi": {
|
|
20
|
+
"image": "https://raw.githubusercontent.com/saifymatteo/pi-extensions/main/packages/pi-vision/screenshot.png",
|
|
18
21
|
"extensions": [
|
|
19
22
|
"./src/index.ts"
|
|
20
23
|
],
|
|
@@ -33,20 +33,35 @@ For browser or accessible GUI work, prefer DOM/accessibility information for
|
|
|
33
33
|
controls and state. Use screenshot coordinates when that information is
|
|
34
34
|
unavailable or the task specifically concerns appearance.
|
|
35
35
|
|
|
36
|
+
## Run the packaged scripts
|
|
37
|
+
|
|
38
|
+
1. Resolve `<skill-dir>` to the absolute directory containing this `SKILL.md`,
|
|
39
|
+
using the skill location supplied by the host. Replace that placeholder in
|
|
40
|
+
commands below; keep script paths quoted and keep the project's working
|
|
41
|
+
directory.
|
|
42
|
+
2. Select a Python 3 interpreter: try `python3 --version`; on Windows, use
|
|
43
|
+
`python --version` or `py -3 --version` if needed. Substitute that command
|
|
44
|
+
for `python3` in the examples.
|
|
45
|
+
3. Invoke `bin/<tool>` and `scripts/<name>.py` through that interpreter. The
|
|
46
|
+
extensionless files in `bin/` are Python scripts, not installed binaries.
|
|
47
|
+
This works without PATH registration, executable permissions, or agent-home
|
|
48
|
+
symlinks. Short tool names in prose refer to these same script paths.
|
|
49
|
+
|
|
50
|
+
Use `--help` on the selected script for additional options.
|
|
51
|
+
|
|
36
52
|
## Local tools: use when their output is needed
|
|
37
53
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
load resources referenced by the page.
|
|
54
|
+
These tools do not use the vision API; HTML rendering can load resources
|
|
55
|
+
referenced by the page.
|
|
41
56
|
|
|
42
57
|
| Need | Command |
|
|
43
58
|
| --- | --- |
|
|
44
|
-
| Reusable crop or close-up | `crop shot.png --region X1,Y1,X2,Y2 -o detail.png` |
|
|
45
|
-
| Locate pixel differences | `python3 scripts/pixel_diff.py before.png after.png` |
|
|
46
|
-
| Measure a region's palette | `python3 scripts/dominant_colors.py shot.png --region X1,Y1,X2,Y2` |
|
|
47
|
-
| Vectorize a flat graphic | `trace icon.png -o icon.svg` |
|
|
48
|
-
| Extract a transparent foreground | `python3 scripts/extract_fg.py shot.png --region X1,Y1,X2,Y2 -o icon.png` |
|
|
49
|
-
| Render an HTML file | `python3 scripts/html_shot.py page.html --width 1440 --height 900 -o page.png` |
|
|
59
|
+
| Reusable crop or close-up | `python3 "<skill-dir>/bin/crop" shot.png --region X1,Y1,X2,Y2 -o detail.png` |
|
|
60
|
+
| Locate pixel differences | `python3 "<skill-dir>/scripts/pixel_diff.py" before.png after.png` |
|
|
61
|
+
| Measure a region's palette | `python3 "<skill-dir>/scripts/dominant_colors.py" shot.png --region X1,Y1,X2,Y2` |
|
|
62
|
+
| Vectorize a flat graphic | `python3 "<skill-dir>/bin/trace" icon.png -o icon.svg` |
|
|
63
|
+
| Extract a transparent foreground | `python3 "<skill-dir>/scripts/extract_fg.py" shot.png --region X1,Y1,X2,Y2 -o icon.png` |
|
|
64
|
+
| Render an HTML file | `python3 "<skill-dir>/scripts/html_shot.py" page.html --width 1440 --height 900 -o page.png` |
|
|
50
65
|
|
|
51
66
|
- `crop --scale 4` enlarges a crop; it adds no missing detail. Coordinates
|
|
52
67
|
measured on that output use the enlarged grid, not the original image.
|
|
@@ -84,11 +99,11 @@ separately configured vision chain, not to the main agent model automatically.
|
|
|
84
99
|
Structured output does not guarantee better recognition or localization.
|
|
85
100
|
|
|
86
101
|
```bash
|
|
87
|
-
glance shot.png -q "Read the small status label."
|
|
88
|
-
glance shot.png --region X1,Y1,X2,Y2 --ocr
|
|
89
|
-
glance before.png after.png -q "What changed semantically?"
|
|
90
|
-
ground shot.png "the send button"
|
|
91
|
-
detect shot.png "buttons"
|
|
102
|
+
python3 "<skill-dir>/bin/glance" shot.png -q "Read the small status label."
|
|
103
|
+
python3 "<skill-dir>/bin/glance" shot.png --region X1,Y1,X2,Y2 --ocr
|
|
104
|
+
python3 "<skill-dir>/bin/glance" before.png after.png -q "What changed semantically?"
|
|
105
|
+
python3 "<skill-dir>/bin/ground" shot.png "the send button"
|
|
106
|
+
python3 "<skill-dir>/bin/detect" shot.png "buttons"
|
|
92
107
|
```
|
|
93
108
|
|
|
94
109
|
`ground` and `detect` return estimated boxes in original-image pixels, including
|
|
@@ -98,9 +113,9 @@ For multi-image questions, pass the images in one call so the model sees them
|
|
|
98
113
|
together. Native side-by-side inspection is also sufficient for semantic
|
|
99
114
|
comparison; use pixel diff when numerical differences matter.
|
|
100
115
|
|
|
101
|
-
The long-screenshot OCR script
|
|
102
|
-
|
|
103
|
-
|
|
116
|
+
The long-screenshot OCR script invokes this skill's `bin/glance` with its
|
|
117
|
+
current Python interpreter, falling back to PATH only if the bundled script
|
|
118
|
+
is missing. Its `--split-only` mode makes chunks without API requests.
|
|
104
119
|
|
|
105
120
|
### Configuration and failures
|
|
106
121
|
|
|
@@ -112,10 +127,11 @@ conversion on supported connections. Text-only or unknown-capability models
|
|
|
112
127
|
still use the configured compatibility bridge. This policy does not route CLI
|
|
113
128
|
calls through the main model.
|
|
114
129
|
|
|
115
|
-
On a model-backed CLI configuration/API error, run
|
|
116
|
-
`vision-doctor
|
|
117
|
-
a test image. Relay failures honestly.
|
|
118
|
-
available; report if the scripted output
|
|
130
|
+
On a model-backed CLI configuration/API error, run
|
|
131
|
+
`python3 "<skill-dir>/bin/vision-doctor"`. Add `--smoke` only when a real
|
|
132
|
+
diagnostic request is needed; it sends a test image. Relay failures honestly.
|
|
133
|
+
Continue with native inspection when available; report if the scripted output
|
|
134
|
+
cannot be produced. Keep provider
|
|
119
135
|
changes user-controlled: do not scrape credentials, hand-export secret overrides,
|
|
120
136
|
or silently switch to an unconfigured provider.
|
|
121
137
|
|
|
@@ -12,7 +12,7 @@ beyond a temporary file's lifetime. Inspect the script's help before choosing
|
|
|
12
12
|
options:
|
|
13
13
|
|
|
14
14
|
```bash
|
|
15
|
-
python3 scripts/long_screenshot_ocr.py --help
|
|
15
|
+
python3 "<skill-dir>/scripts/long_screenshot_ocr.py" --help
|
|
16
16
|
```
|
|
17
17
|
|
|
18
18
|
Prefer native chunk reading by the main agent; the glance-backed script is
|
|
@@ -22,7 +22,7 @@ splitter; verify joins even when the cut falls in a low-content band.
|
|
|
22
22
|
### Native chunk reading
|
|
23
23
|
|
|
24
24
|
```bash
|
|
25
|
-
python3 scripts/long_screenshot_ocr.py work/page.png --split-only
|
|
25
|
+
python3 "<skill-dir>/scripts/long_screenshot_ocr.py" work/page.png --split-only
|
|
26
26
|
```
|
|
27
27
|
|
|
28
28
|
This writes ordered chunk images and `manifest.json` without vision calls.
|
|
@@ -38,10 +38,10 @@ Choose the content mode; this path makes configured vision calls:
|
|
|
38
38
|
|
|
39
39
|
```bash
|
|
40
40
|
# Web pages, documents, logs, tables, and other general content
|
|
41
|
-
python3 scripts/long_screenshot_ocr.py work/page.png -o work/page.ocr.md
|
|
41
|
+
python3 "<skill-dir>/scripts/long_screenshot_ocr.py" work/page.png -o work/page.ocr.md
|
|
42
42
|
|
|
43
43
|
# Chat histories: preserve message grouping, senders, timestamps, and quotes
|
|
44
|
-
python3 scripts/long_screenshot_ocr.py work/chat.png --mode chat -o work/chat.ocr.md
|
|
44
|
+
python3 "<skill-dir>/scripts/long_screenshot_ocr.py" work/chat.png --mode chat -o work/chat.ocr.md
|
|
45
45
|
```
|
|
46
46
|
|
|
47
47
|
Without `-o`, write `<input-stem>.ocr.md`; store chunks, sidecars, the manifest,
|
|
@@ -63,7 +63,7 @@ Use `--resume` after an interrupted run. A chunk is reused only when its image,
|
|
|
63
63
|
mode, and custom prompt fingerprint still match:
|
|
64
64
|
|
|
65
65
|
```bash
|
|
66
|
-
python3 scripts/long_screenshot_ocr.py work/chat.png --mode chat --resume -o work/chat.ocr.md
|
|
66
|
+
python3 "<skill-dir>/scripts/long_screenshot_ocr.py" work/chat.png --mode chat --resume -o work/chat.ocr.md
|
|
67
67
|
```
|
|
68
68
|
|
|
69
69
|
If the defaults produce awkward chunks, rerun with `--target-height`,
|
|
@@ -85,8 +85,8 @@ context; do not make tiny OCR tiles unless the source text is unusually small.
|
|
|
85
85
|
unresolved, targeted specialist OCR is available:
|
|
86
86
|
|
|
87
87
|
```bash
|
|
88
|
-
glance work/page_chunks/chunk_002.png --ocr "Re-check the final five lines carefully."
|
|
89
|
-
glance work/page_chunks/chunk_002.png --region X1,Y1,X2,Y2 --ocr
|
|
88
|
+
python3 "<skill-dir>/bin/glance" work/page_chunks/chunk_002.png --ocr "Re-check the final five lines carefully."
|
|
89
|
+
python3 "<skill-dir>/bin/glance" work/page_chunks/chunk_002.png --region X1,Y1,X2,Y2 --ocr
|
|
90
90
|
```
|
|
91
91
|
|
|
92
92
|
5. Keep visible spelling and punctuation verbatim. Write `[unreadable]` for
|
|
@@ -25,16 +25,16 @@ pixels as foreground.
|
|
|
25
25
|
|
|
26
26
|
```bash
|
|
27
27
|
# Known tight region
|
|
28
|
-
python3 scripts/extract_fg.py shot.png \
|
|
28
|
+
python3 "<skill-dir>/scripts/extract_fg.py" shot.png \
|
|
29
29
|
--region X1,Y1,X2,Y2 -o asset.png
|
|
30
30
|
|
|
31
31
|
# Dark or gray line art
|
|
32
|
-
python3 scripts/extract_fg.py shot.png \
|
|
32
|
+
python3 "<skill-dir>/scripts/extract_fg.py" shot.png \
|
|
33
33
|
--region X1,Y1,X2,Y2 --mode dark -o asset.png
|
|
34
34
|
|
|
35
35
|
# Center and enlarge a small visual before automatic extraction
|
|
36
|
-
crop shot.png --region X1,Y1,X2,Y2 --scale 4 -o work/asset4x.png
|
|
37
|
-
python3 scripts/extract_fg.py work/asset4x.png
|
|
36
|
+
python3 "<skill-dir>/bin/crop" shot.png --region X1,Y1,X2,Y2 --scale 4 -o work/asset4x.png
|
|
37
|
+
python3 "<skill-dir>/scripts/extract_fg.py" work/asset4x.png
|
|
38
38
|
```
|
|
39
39
|
|
|
40
40
|
Use `--exclude-color '#RRGGBB'` when a connected background color would
|
|
@@ -47,9 +47,9 @@ clean alpha edges, and no neighboring fragments before reuse.
|
|
|
47
47
|
## Rebuild an SVG only when the deliverable needs one
|
|
48
48
|
|
|
49
49
|
```bash
|
|
50
|
-
trace asset.png -o asset.svg
|
|
51
|
-
trace asset.png --polygon -o asset.svg
|
|
52
|
-
trace shot.png --region X1,Y1,X2,Y2 -o asset.svg
|
|
50
|
+
python3 "<skill-dir>/bin/trace" asset.png -o asset.svg
|
|
51
|
+
python3 "<skill-dir>/bin/trace" asset.png --polygon -o asset.svg
|
|
52
|
+
python3 "<skill-dir>/bin/trace" shot.png --region X1,Y1,X2,Y2 -o asset.svg
|
|
53
53
|
```
|
|
54
54
|
|
|
55
55
|
Ship traced paths directly for organic or irregular shapes. For rectangles,
|
|
@@ -140,13 +140,13 @@ extraction, tighten the final region to the visual's own ink; adjacent text or
|
|
|
140
140
|
rules inside the region can become foreground components too.
|
|
141
141
|
|
|
142
142
|
```bash
|
|
143
|
-
crop shot.png --region X1,Y1,X2,Y2 --scale 4 -o work/icon4x.png
|
|
144
|
-
python3 scripts/extract_fg.py work/icon4x.png
|
|
143
|
+
python3 "<skill-dir>/bin/crop" shot.png --region X1,Y1,X2,Y2 --scale 4 -o work/icon4x.png
|
|
144
|
+
python3 "<skill-dir>/scripts/extract_fg.py" work/icon4x.png
|
|
145
145
|
|
|
146
146
|
# Or extract directly from a known tight region:
|
|
147
|
-
python3 scripts/extract_fg.py shot.png \
|
|
147
|
+
python3 "<skill-dir>/scripts/extract_fg.py" shot.png \
|
|
148
148
|
--region X1,Y1,X2,Y2 -o work/icon.png
|
|
149
|
-
python3 scripts/extract_fg.py shot.png \
|
|
149
|
+
python3 "<skill-dir>/scripts/extract_fg.py" shot.png \
|
|
150
150
|
--region X1,Y1,X2,Y2 --mode dark -o work/logo.png
|
|
151
151
|
```
|
|
152
152
|
|
|
@@ -456,13 +456,13 @@ def command_for_path(path: Path) -> list[str]:
|
|
|
456
456
|
|
|
457
457
|
|
|
458
458
|
def resolve_glance_command() -> list[str]:
|
|
459
|
+
bundled_glance = Path(__file__).resolve().parents[1] / "bin" / "glance"
|
|
460
|
+
if bundled_glance.is_file():
|
|
461
|
+
return [sys.executable, str(bundled_glance)]
|
|
459
462
|
discovered = shutil.which("glance")
|
|
460
463
|
if discovered:
|
|
461
464
|
return command_for_path(Path(discovered))
|
|
462
|
-
|
|
463
|
-
if repository_glance.is_file():
|
|
464
|
-
return command_for_path(repository_glance)
|
|
465
|
-
raise FileNotFoundError("glance is not on PATH; install the toolkit first")
|
|
465
|
+
raise FileNotFoundError("glance is not in this skill directory or on PATH")
|
|
466
466
|
|
|
467
467
|
|
|
468
468
|
def ocr_prompt(mode: str, index: int, total: int, custom: str | None) -> str:
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { readFileSync, readdirSync, existsSync } from 'node:fs';
|
|
4
|
+
import { join } from 'node:path';
|
|
5
|
+
import { fileURLToPath } from 'node:url';
|
|
6
|
+
import { spawnSync } from 'node:child_process';
|
|
7
|
+
|
|
8
|
+
const skill = fileURLToPath(new URL('../skills/vision-tools/', import.meta.url));
|
|
9
|
+
|
|
10
|
+
test('skill command examples invoke bundled Python scripts independently of PATH and cwd', () => {
|
|
11
|
+
const docs = [join(skill, 'SKILL.md'), ...readdirSync(join(skill, 'references')).map(name => join(skill, 'references', name))];
|
|
12
|
+
const launchers = new Set();
|
|
13
|
+
for (const doc of docs) {
|
|
14
|
+
const source = readFileSync(doc, 'utf8');
|
|
15
|
+
for (const [, commands] of source.matchAll(/```bash\n([\s\S]*?)```/g)) {
|
|
16
|
+
assert.equal(/^\s*(?:crop|detect|glance|ground|trace|vision-doctor)\s+\S/m.test(commands), false, `${doc}: bare launcher command`);
|
|
17
|
+
}
|
|
18
|
+
assert.equal(/python3 scripts\//.test(source), false, `${doc}: cwd-relative script path`);
|
|
19
|
+
for (const [, relative] of source.matchAll(/python3 "<skill-dir>\/([^"]+)"/g)) {
|
|
20
|
+
assert.ok(existsSync(join(skill, relative)), `${doc}: missing bundled script ${relative}`);
|
|
21
|
+
if (relative.startsWith('bin/')) launchers.add(relative.slice(4));
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
assert.deepEqual([...launchers].sort(), ['crop', 'detect', 'glance', 'ground', 'trace', 'vision-doctor'].sort());
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
test('automated OCR finds bundled glance without PATH, including non-executable paths with spaces', t => {
|
|
28
|
+
const python = [['python3'], ['python'], ['py', '-3']].find(([command, ...args]) => {
|
|
29
|
+
const result = spawnSync(command, [...args, '--version'], { encoding: 'utf8', timeout: 10_000 });
|
|
30
|
+
return result.status === 0 && /^Python 3\./.test(result.stdout);
|
|
31
|
+
});
|
|
32
|
+
if (!python) return t.skip('Python 3 is not installed');
|
|
33
|
+
const code = `
|
|
34
|
+
import importlib.util
|
|
35
|
+
from pathlib import Path
|
|
36
|
+
import subprocess
|
|
37
|
+
import sys
|
|
38
|
+
import tempfile
|
|
39
|
+
from unittest.mock import patch
|
|
40
|
+
|
|
41
|
+
source = Path(sys.argv[1])
|
|
42
|
+
spec = importlib.util.spec_from_file_location("long_screenshot_ocr", source)
|
|
43
|
+
module = importlib.util.module_from_spec(spec)
|
|
44
|
+
sys.modules[spec.name] = module
|
|
45
|
+
spec.loader.exec_module(module)
|
|
46
|
+
with tempfile.TemporaryDirectory(prefix="vision skill ") as directory:
|
|
47
|
+
skill = Path(directory)
|
|
48
|
+
script = skill / "scripts" / "long_screenshot_ocr.py"
|
|
49
|
+
script.parent.mkdir()
|
|
50
|
+
script.touch()
|
|
51
|
+
glance = skill / "bin" / "glance"
|
|
52
|
+
glance.parent.mkdir()
|
|
53
|
+
glance.write_text('print("bundled glance reached")', encoding="utf-8")
|
|
54
|
+
with patch.object(module, "__file__", str(script)), patch.object(module.shutil, "which", return_value=None):
|
|
55
|
+
command = module.resolve_glance_command()
|
|
56
|
+
assert command == [sys.executable, str(glance)], command
|
|
57
|
+
result = subprocess.run(command, capture_output=True, text=True, check=True)
|
|
58
|
+
assert result.stdout.strip() == "bundled glance reached", result.stdout
|
|
59
|
+
with patch.object(module, "__file__", str(script)), patch.object(module.shutil, "which", return_value="/unrelated/glance"):
|
|
60
|
+
assert module.resolve_glance_command() == command, "prefer the packaged script over unrelated PATH commands"
|
|
61
|
+
glance.unlink()
|
|
62
|
+
external = skill / "custom_glance.py"
|
|
63
|
+
external.touch()
|
|
64
|
+
with patch.object(module, "__file__", str(script)), patch.object(module.shutil, "which", return_value=str(external)):
|
|
65
|
+
assert module.resolve_glance_command() == [sys.executable, str(external)], "retain the external fallback"
|
|
66
|
+
`;
|
|
67
|
+
const result = spawnSync(python[0], [...python.slice(1), '-c', code, join(skill, 'scripts', 'long_screenshot_ocr.py')], {
|
|
68
|
+
encoding: 'utf8', timeout: 20_000, env: { ...process.env, PYTHONDONTWRITEBYTECODE: '1' },
|
|
69
|
+
});
|
|
70
|
+
assert.equal(result.status, 0, result.stderr || result.error?.message);
|
|
71
|
+
});
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# @saifymatteo/pi-wait
|
|
2
2
|
|
|
3
|
+

|
|
4
|
+
|
|
5
|
+
*The agent starts a build in the background, then calls `wait` on `shell:1`. The job's output comes back in the same turn. Needs pi-bg-bash.*
|
|
6
|
+
|
|
3
7
|
## Purpose and registrations
|
|
4
8
|
|
|
5
9
|
Registers the `wait` tool, joining 1..64 unique explicit `shell:<id>` / `agent:<id>` jobs. Returns results in requested order. Timeout releases claims without stopping work; abort/session changes invalidate the join. No commands or configuration files; no external CLI/model service.
|