pi-skill-shiori 0.6.13 → 0.6.17
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/CHANGELOG.md +28 -3
- package/README.md +9 -9
- package/docs/verification/pi-sdk-smoke.json +110 -0
- package/package.json +9 -6
- package/src/index.ts +4 -0
- package/src/retrieval-expanded.ts +1 -4
- package/src/retrieval.ts +11 -6
- /package/{Docs → docs}/recommendation-surface.md +0 -0
- /package/{Docs → docs}/usage.md +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,31 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## [0.6.17] - 2026-10-24
|
|
6
|
+
|
|
7
|
+
### Changed
|
|
8
|
+
|
|
9
|
+
- Tokenize each retrieval query once and reuse its tokens while scoring skills.
|
|
10
|
+
|
|
11
|
+
## [0.6.16] - 2026-10-17
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
|
|
15
|
+
- Share the retrieval-index contract between standard and expanded retrieval.
|
|
16
|
+
|
|
17
|
+
## [0.6.15] - 2026-10-16
|
|
18
|
+
|
|
19
|
+
### Changed
|
|
20
|
+
|
|
21
|
+
- Pin Pi SDK development and smoke-test dependencies to 1.2.0 and guard user-only prompt handling for the new `before_agent_start` message union.
|
|
22
|
+
|
|
23
|
+
## [0.6.14] - 2026-10-12
|
|
24
|
+
|
|
25
|
+
### Changed
|
|
26
|
+
|
|
27
|
+
- Pin the Pi SDK development and smoke-test dependencies to 1.1.0.
|
|
28
|
+
- Standardize the documentation directory to lowercase so the Pi SDK smoke report is available at `docs/verification/pi-sdk-smoke.json` on case-sensitive hosts.
|
|
29
|
+
|
|
5
30
|
## [0.6.13] - 2026-10-05
|
|
6
31
|
|
|
7
32
|
### Added
|
|
@@ -84,14 +109,14 @@ This project follows semantic versioning.
|
|
|
84
109
|
|
|
85
110
|
### Changed
|
|
86
111
|
|
|
87
|
-
- `
|
|
112
|
+
- `docs/recommendation-surface.md` documents the dogfood review outcome and recommendation to keep badges on default surfaces.
|
|
88
113
|
|
|
89
114
|
## [0.6.1] - 2026-07-01
|
|
90
115
|
|
|
91
116
|
### Changed
|
|
92
117
|
|
|
93
118
|
- README aligned with Pi OSS minimal-docs policy: badges, required entrypoint sections, Quick start, Package contents, Links.
|
|
94
|
-
- Detailed configuration and operational notes moved to `
|
|
119
|
+
- Detailed configuration and operational notes moved to `docs/usage.md`.
|
|
95
120
|
- README install examples and status text updated to match package version `0.6.1`.
|
|
96
121
|
|
|
97
122
|
## [0.6.0] - 2026-06-29
|
|
@@ -99,7 +124,7 @@ This project follows semantic versioning.
|
|
|
99
124
|
### Added
|
|
100
125
|
|
|
101
126
|
- Bounded recommendation reason badges (`[trigger]`, `[description]`, `[low match]`) on recommended skills in auto-inject, `/shiori:recommend`, and `shiori_recommend` surfaces.
|
|
102
|
-
- `
|
|
127
|
+
- `docs/recommendation-surface.md` describing badge vocabulary, a multi-skill example, and how badges relate to Always Visible Skill policy and recommendation metrics.
|
|
103
128
|
- Tests for reason present, absent, low-confidence, and badge formatting.
|
|
104
129
|
|
|
105
130
|
### Changed
|
package/README.md
CHANGED
|
@@ -19,7 +19,7 @@ For maintenance priorities and the phased plan, see [`ROADMAP.md`](ROADMAP.md).
|
|
|
19
19
|
|
|
20
20
|
Pi Skill Shiori is a [Pi](https://pi.dev/) package for vaults or projects with many Agent Skills where the default catalog becomes noisy and expensive. It hides the normal skill catalog when safe, recommends triggerable skills with compact summaries, and loads full `SKILL.md` bodies on demand.
|
|
21
21
|
|
|
22
|
-
`0.6.
|
|
22
|
+
`0.6.17` is the current working release. Prompt-boundary suppression is intentionally conservative: if Shiori cannot safely recognize a catalog boundary, it leaves the prompt untouched and warns instead of deleting too much.
|
|
23
23
|
|
|
24
24
|
## Features
|
|
25
25
|
|
|
@@ -38,7 +38,7 @@ Pi Skill Shiori is a [Pi](https://pi.dev/) package for vaults or projects with m
|
|
|
38
38
|
### Global install from npm
|
|
39
39
|
|
|
40
40
|
```bash
|
|
41
|
-
pi install npm:pi-skill-shiori@0.6.
|
|
41
|
+
pi install npm:pi-skill-shiori@0.6.17
|
|
42
42
|
```
|
|
43
43
|
|
|
44
44
|
Without a version pin:
|
|
@@ -50,7 +50,7 @@ pi install npm:pi-skill-shiori
|
|
|
50
50
|
### Project-local install from npm
|
|
51
51
|
|
|
52
52
|
```bash
|
|
53
|
-
pi install -l npm:pi-skill-shiori@0.6.
|
|
53
|
+
pi install -l npm:pi-skill-shiori@0.6.17
|
|
54
54
|
```
|
|
55
55
|
|
|
56
56
|
Without a version pin:
|
|
@@ -62,7 +62,7 @@ pi install -l npm:pi-skill-shiori
|
|
|
62
62
|
### Install from GitHub
|
|
63
63
|
|
|
64
64
|
```bash
|
|
65
|
-
pi install git:github.com/eiei114/pi-skill-shiori@v0.6.
|
|
65
|
+
pi install git:github.com/eiei114/pi-skill-shiori@v0.6.17
|
|
66
66
|
pi install -l git:github.com/eiei114/pi-skill-shiori
|
|
67
67
|
```
|
|
68
68
|
|
|
@@ -82,7 +82,7 @@ pi install -l /absolute/path/to/pi-skill-shiori
|
|
|
82
82
|
## Quick start
|
|
83
83
|
|
|
84
84
|
1. Install the package (see [Install](#install)).
|
|
85
|
-
2. Create `.pi/skill-shiori.yml` in your Pi project (see [
|
|
85
|
+
2. Create `.pi/skill-shiori.yml` in your Pi project (see [docs/usage.md](docs/usage.md#configure)).
|
|
86
86
|
3. Start Pi and run `/shiori:doctor` to confirm policy path, indexed roots, and suppression status.
|
|
87
87
|
4. Use `/shiori:bootstrap` to write `.pi/skill-shiori.generated.yml`, review it, copy needed sections into `.pi/skill-shiori.yml`, then run `/shiori:reload`.
|
|
88
88
|
5. Ask the agent for help; Shiori injects compact candidates or use `/shiori:recommend` for an interactive flow.
|
|
@@ -113,17 +113,17 @@ shiori_load_skill({ skill: "reddit-research" })
|
|
|
113
113
|
|
|
114
114
|
`shiori_load_skill` loads one skill by name. The Pi UI shows a compact result like `✓ Loaded reddit-research (6.3KB)`.
|
|
115
115
|
|
|
116
|
-
Recommended skills show compact reason badges (`[trigger]`, `[description]`, `[low match]`). See [`
|
|
116
|
+
Recommended skills show compact reason badges (`[trigger]`, `[description]`, `[low match]`). See [`docs/recommendation-surface.md`](docs/recommendation-surface.md) for badge vocabulary and metrics interplay.
|
|
117
117
|
|
|
118
|
-
For inventory roots, policy YAML, suppression statuses, and feedback metrics, see [`
|
|
118
|
+
For inventory roots, policy YAML, suppression statuses, and feedback metrics, see [`docs/usage.md`](docs/usage.md).
|
|
119
119
|
|
|
120
120
|
## Package contents
|
|
121
121
|
|
|
122
122
|
| Path | Purpose |
|
|
123
123
|
|---|---|
|
|
124
124
|
| `src/` | Pi extension entrypoint and Shiori runtime |
|
|
125
|
-
| `
|
|
126
|
-
| `
|
|
125
|
+
| `docs/usage.md` | Configuration, inventory, suppression, and metrics details |
|
|
126
|
+
| `docs/recommendation-surface.md` | Recommendation badges and surface behavior |
|
|
127
127
|
| `ROADMAP.md` | Maintenance direction and phased plan |
|
|
128
128
|
| `CHANGELOG.md` | Version history |
|
|
129
129
|
| `SECURITY.md` | Vulnerability reporting |
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema_version": 1,
|
|
3
|
+
"verification_contract": "pi-sdk-behavior-v2",
|
|
4
|
+
"sdk_versions": {
|
|
5
|
+
"@earendil-works/pi-agent-core": "1.2.0",
|
|
6
|
+
"@earendil-works/pi-ai": "1.2.0",
|
|
7
|
+
"@earendil-works/pi-coding-agent": "1.2.0",
|
|
8
|
+
"@earendil-works/pi-tui": "1.2.0"
|
|
9
|
+
},
|
|
10
|
+
"platform": "win32",
|
|
11
|
+
"model_inference": "none; actual Pi host executes local Shiori slash commands in RPC mode",
|
|
12
|
+
"boundary": "The Pi SDK host, extension loader, extension lifecycle and Shiori commands are real. The deterministic smoke skill is filesystem input; no provider/model call or mocked host is used. Pi settings, home and temp paths are isolated and removed after the checks.",
|
|
13
|
+
"unhandled_errors": 0,
|
|
14
|
+
"extension_load_errors": 0,
|
|
15
|
+
"cases": [
|
|
16
|
+
{
|
|
17
|
+
"name": "extension_load",
|
|
18
|
+
"command": "npm run smoke:pi (actual locally pinned Pi RPC host and Shiori extension)",
|
|
19
|
+
"exit_code": 0,
|
|
20
|
+
"passed": true,
|
|
21
|
+
"evidence": "[extension_load] Pi SDK 1.2.0\n[first process stdout]\n{\"id\":\"load-commands\",\"type\":\"response\",\"command\":\"get_commands\",\"success\":true,\"data\":{\"commands\":[{\"name\":\"shiori:doctor\",\"description\":\"Show Pi Skill Shiori configuration and inventory status\",\"source\":\"extension\",\"sourceInfo\":{\"path\":\"<REPOSITORY>\\\\src\\\\index.ts\",\"source\":\"cli\",\"scope\":\"temporary\",\"origin\":\"top-level\"}},{\"name\":\"shiori:reload\",\"description\":\"Rebuild Pi Skill Shiori inventory and optional Pi runtime resources\",\"source\":\"extension\",\"sourceInfo\":{\"path\":\"<REPOSITORY>\\\\src\\\\index.ts\",\"source\":\"cli\",\"scope\":\"temporary\",\"origin\":\"top-level\"}},{\"name\":\"shiori:recommend\",\"description\":\"Recommend Agent Skills for a natural-language task and queue it for the agent\",\"source\":\"extension\",\"sourceInfo\":{\"path\":\"<REPOSITORY>\\\\src\\\\index.ts\",\"source\":\"cli\",\"scope\":\"temporary\",\"origin\":\"top-level\"}},{\"name\":\"shiori:stats\",\"description\":\"Show Pi Skill Shiori operational counters and recommendation feedback\",\"source\":\"extension\",\"sourceInfo\":{\"path\":\"<REPOSITORY>\\\\src\\\\index.ts\",\"source\":\"cli\",\"scope\":\"temporary\",\"origin\":\"top-level\"}},{\"name\":\"shiori:bootstrap\",\"description\":\"Generate a review policy draft from discovered skill descriptions\",\"source\":\"extension\",\"sourceInfo\":{\"path\":\"<REPOSITORY>\\\\src\\\\index.ts\",\"source\":\"cli\",\"scope\":\"temporary\",\"origin\":\"top-level\"}}]}}\n\n[first process stderr]\n",
|
|
22
|
+
"assertions": [
|
|
23
|
+
{
|
|
24
|
+
"id": "extension_registered",
|
|
25
|
+
"expected": "The actual Pi host lists Shiori's registered doctor command.",
|
|
26
|
+
"observed": "{\"commands\":[\"shiori:doctor\",\"shiori:reload\",\"shiori:recommend\",\"shiori:stats\",\"shiori:bootstrap\"]}",
|
|
27
|
+
"passed": true
|
|
28
|
+
}
|
|
29
|
+
]
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"name": "happy_path",
|
|
33
|
+
"command": "npm run smoke:pi (actual locally pinned Pi RPC host and Shiori extension)",
|
|
34
|
+
"exit_code": 0,
|
|
35
|
+
"passed": true,
|
|
36
|
+
"evidence": "[happy_path] Pi SDK 1.2.0\n[first process stdout]\n{\"id\":\"happy-commands\",\"type\":\"response\",\"command\":\"get_commands\",\"success\":true,\"data\":{\"commands\":[{\"name\":\"shiori:doctor\",\"description\":\"Show Pi Skill Shiori configuration and inventory status\",\"source\":\"extension\",\"sourceInfo\":{\"path\":\"<REPOSITORY>\\\\src\\\\index.ts\",\"source\":\"cli\",\"scope\":\"temporary\",\"origin\":\"top-level\"}},{\"name\":\"shiori:reload\",\"description\":\"Rebuild Pi Skill Shiori inventory and optional Pi runtime resources\",\"source\":\"extension\",\"sourceInfo\":{\"path\":\"<REPOSITORY>\\\\src\\\\index.ts\",\"source\":\"cli\",\"scope\":\"temporary\",\"origin\":\"top-level\"}},{\"name\":\"shiori:recommend\",\"description\":\"Recommend Agent Skills for a natural-language task and queue it for the agent\",\"source\":\"extension\",\"sourceInfo\":{\"path\":\"<REPOSITORY>\\\\src\\\\index.ts\",\"source\":\"cli\",\"scope\":\"temporary\",\"origin\":\"top-level\"}},{\"name\":\"shiori:stats\",\"description\":\"Show Pi Skill Shiori operational counters and recommendation feedback\",\"source\":\"extension\",\"sourceInfo\":{\"path\":\"<REPOSITORY>\\\\src\\\\index.ts\",\"source\":\"cli\",\"scope\":\"temporary\",\"origin\":\"top-level\"}},{\"name\":\"shiori:bootstrap\",\"description\":\"Generate a review policy draft from discovered skill descriptions\",\"source\":\"extension\",\"sourceInfo\":{\"path\":\"<REPOSITORY>\\\\src\\\\index.ts\",\"source\":\"cli\",\"scope\":\"temporary\",\"origin\":\"top-level\"}}]}}\n{\"type\":\"extension_ui_request\",\"id\":\"<RPC_ID>\",\"method\":\"input\",\"title\":\"What do you want help with?\",\"placeholder\":\"Describe your task in natural language…\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<RPC_ID>\",\"method\":\"select\",\"title\":\"How should Shiori use these recommendations?\",\"options\":[\"Pre-load matches and queue task for agent\",\"Review recommendations only\",\"Cancel\"]}\n{\"type\":\"extension_ui_request\",\"id\":\"<RPC_ID>\",\"method\":\"notify\",\"message\":\"Matched 1 skill(s): smoke-skill [trigger]\",\"notifyType\":\"info\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<RPC_ID>\",\"method\":\"select\",\"title\":\"Follow up on a recommendation:\",\"options\":[\"smoke-skill [trigger]\",\"Done\"]}\n{\"id\":\"happy-prompt\",\"type\":\"response\",\"command\":\"prompt\",\"success\":true,\"data\":{\"disposition\":\"handled\"}}\n\n[first process stderr]\n",
|
|
37
|
+
"assertions": [
|
|
38
|
+
{
|
|
39
|
+
"id": "feature_response",
|
|
40
|
+
"expected": "Pi handles Shiori's interactive recommendation command and the real extension returns its discovered smoke-skill.",
|
|
41
|
+
"observed": "{\"response\":{\"id\":\"happy-prompt\",\"type\":\"response\",\"command\":\"prompt\",\"success\":true,\"data\":{\"disposition\":\"handled\"}},\"notification\":{\"type\":\"extension_ui_request\",\"id\":\"<RPC_ID>\",\"method\":\"notify\",\"message\":\"Matched 1 skill(s): smoke-skill [trigger]\",\"notifyType\":\"info\"}}",
|
|
42
|
+
"passed": true
|
|
43
|
+
}
|
|
44
|
+
]
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
"name": "error_path",
|
|
48
|
+
"command": "npm run smoke:pi (actual locally pinned Pi RPC host and Shiori extension)",
|
|
49
|
+
"exit_code": 0,
|
|
50
|
+
"passed": true,
|
|
51
|
+
"evidence": "[error_path] Pi SDK 1.2.0\n[first process stdout]\n{\"id\":\"error-commands\",\"type\":\"response\",\"command\":\"get_commands\",\"success\":true,\"data\":{\"commands\":[{\"name\":\"shiori:doctor\",\"description\":\"Show Pi Skill Shiori configuration and inventory status\",\"source\":\"extension\",\"sourceInfo\":{\"path\":\"<REPOSITORY>\\\\src\\\\index.ts\",\"source\":\"cli\",\"scope\":\"temporary\",\"origin\":\"top-level\"}},{\"name\":\"shiori:reload\",\"description\":\"Rebuild Pi Skill Shiori inventory and optional Pi runtime resources\",\"source\":\"extension\",\"sourceInfo\":{\"path\":\"<REPOSITORY>\\\\src\\\\index.ts\",\"source\":\"cli\",\"scope\":\"temporary\",\"origin\":\"top-level\"}},{\"name\":\"shiori:recommend\",\"description\":\"Recommend Agent Skills for a natural-language task and queue it for the agent\",\"source\":\"extension\",\"sourceInfo\":{\"path\":\"<REPOSITORY>\\\\src\\\\index.ts\",\"source\":\"cli\",\"scope\":\"temporary\",\"origin\":\"top-level\"}},{\"name\":\"shiori:stats\",\"description\":\"Show Pi Skill Shiori operational counters and recommendation feedback\",\"source\":\"extension\",\"sourceInfo\":{\"path\":\"<REPOSITORY>\\\\src\\\\index.ts\",\"source\":\"cli\",\"scope\":\"temporary\",\"origin\":\"top-level\"}},{\"name\":\"shiori:bootstrap\",\"description\":\"Generate a review policy draft from discovered skill descriptions\",\"source\":\"extension\",\"sourceInfo\":{\"path\":\"<REPOSITORY>\\\\src\\\\index.ts\",\"source\":\"cli\",\"scope\":\"temporary\",\"origin\":\"top-level\"}}]}}\n{\"type\":\"extension_ui_request\",\"id\":\"<RPC_ID>\",\"method\":\"input\",\"title\":\"What do you want help with?\",\"placeholder\":\"Describe your task in natural language…\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<RPC_ID>\",\"method\":\"notify\",\"message\":\"Recommendation cancelled.\",\"notifyType\":\"info\"}\n{\"id\":\"error-prompt\",\"type\":\"response\",\"command\":\"prompt\",\"success\":true,\"data\":{\"disposition\":\"handled\"}}\n\n[first process stderr]\n",
|
|
52
|
+
"assertions": [
|
|
53
|
+
{
|
|
54
|
+
"id": "handled_error",
|
|
55
|
+
"expected": "Cancelling Shiori's actual RPC input dialog is handled with its cancellation notice and no model call.",
|
|
56
|
+
"observed": "{\"response\":{\"id\":\"error-prompt\",\"type\":\"response\",\"command\":\"prompt\",\"success\":true,\"data\":{\"disposition\":\"handled\"}},\"cancelled\":{\"type\":\"extension_ui_request\",\"id\":\"<RPC_ID>\",\"method\":\"notify\",\"message\":\"Recommendation cancelled.\",\"notifyType\":\"info\"}}",
|
|
57
|
+
"passed": true
|
|
58
|
+
}
|
|
59
|
+
]
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
"name": "reload_cleanup",
|
|
63
|
+
"command": "npm run smoke:pi (actual locally pinned Pi RPC host and Shiori extension)",
|
|
64
|
+
"exit_code": 0,
|
|
65
|
+
"passed": true,
|
|
66
|
+
"evidence": "[reload sequence]\nfirst process:\n reload-stats-before: success=true disposition=handled\n reload-inventory: success=true disposition=handled\n reload-stats-after: success=true disposition=handled\n reload-recommend: success=true disposition=handled\n firstExitCode=0\nsecond process:\n reload-recommend: success=true disposition=handled\n secondExitCode=0\n[reload_cleanup] Pi SDK 1.2.0\n[first process stdout]\n{\"id\":\"reload-first-commands\",\"type\":\"response\",\"command\":\"get_commands\",\"success\":true,\"data\":{\"commands\":[{\"name\":\"shiori:doctor\",\"description\":\"Show Pi Skill Shiori configuration and inventory status\",\"source\":\"extension\",\"sourceInfo\":{\"path\":\"<REPOSITORY>\\\\src\\\\index.ts\",\"source\":\"cli\",\"scope\":\"temporary\",\"origin\":\"top-level\"}},{\"name\":\"shiori:reload\",\"description\":\"Rebuild Pi Skill Shiori inventory and optional Pi runtime resources\",\"source\":\"extension\",\"sourceInfo\":{\"path\":\"<REPOSITORY>\\\\src\\\\index.ts\",\"source\":\"cli\",\"scope\":\"temporary\",\"origin\":\"top-level\"}},{\"name\":\"shiori:recommend\",\"description\":\"Recommend Agent Skills for a natural-language task and queue it for the agent\",\"source\":\"extension\",\"sourceInfo\":{\"path\":\"<REPOSITORY>\\\\src\\\\index.ts\",\"source\":\"cli\",\"scope\":\"temporary\",\"origin\":\"top-level\"}},{\"name\":\"shiori:stats\",\"description\":\"Show Pi Skill Shiori operational counters and recommendation feedback\",\"source\":\"extension\",\"sourceInfo\":{\"path\":\"<REPOSITORY>\\\\src\\\\index.ts\",\"source\":\"cli\",\"scope\":\"temporary\",\"origin\":\"top-level\"}},{\"name\":\"shiori:bootstrap\",\"description\":\"Generate a review policy draft from discovered skill descriptions\",\"source\":\"extension\",\"sourceInfo\":{\"path\":\"<REPOSITORY>\\\\src\\\\index.ts\",\"source\":\"cli\",\"scope\":\"temporary\",\"origin\":\"top-level\"}}]}}\n{\"type\":\"extension_ui_request\",\"id\":\"<RPC_ID>\",\"method\":\"notify\",\"message\":\"Recommendation feedback (session-local, no prompts stored)\\noffers: 0 | candidate slots: 0 | loaded: 0\\nabandoned: 0 | zero-candidate queries: 0 | follow-through: n/a\\nTiming (session-local) | inventory refresh: count=1 last=<DURATION> total=<DURATION> max=<DURATION> | retrieval: count=0 last=<DURATION> total=<DURATION> max=<DURATION>\\n\\n{\\n \\\"inventoryCount\\\": 1,\\n \\\"duplicateCount\\\": 0,\\n \\\"candidateHitCount\\\": 0,\\n \\\"zeroCandidateCount\\\": 0,\\n \\\"loadedSkillCount\\\": 0,\\n \\\"explicitInvocationCount\\\": 0,\\n \\\"retrievalBackend\\\": \\\"sqlite-fts\\\",\\n \\\"suppressionStatus\\\": \\\"disabled\\\",\\n \\\"inventoryRefreshCount\\\": 1,\\n \\\"inventoryAutoRefreshCount\\\": 0,\\n \\\"timing\\\": {\\n \\\"inventoryRefresh\\\": {\\n \\\"lastMs\\\": \"<DURATION>\",\\n \\\"totalMs\\\": \"<DURATION>\",\\n \\\"maxMs\\\": \"<DURATION>\",\\n \\\"count\\\": 1\\n },\\n \\\"retrieval\\\": {\\n \\\"lastMs\\\": \"<DURATION>\",\\n \\\"totalMs\\\": \"<DURATION>\",\\n \\\"maxMs\\\": \"<DURATION>\",\\n \\\"count\\\": 0\\n }\\n },\\n \\\"lastReloadAt\\\": \\\"<TIMESTAMP>\\\",\\n \\\"recommendationFeedback\\\": {\\n \\\"totalOffers\\\": 0,\\n \\\"totalCandidateSlots\\\": 0,\\n \\\"totalLoaded\\\": 0,\\n \\\"totalAbandoned\\\": 0,\\n \\\"zeroCandidateQueries\\\": 0,\\n \\\"followThroughRate\\\": null,\\n \\\"bySource\\\": {\\n \\\"auto-inject\\\": {\\n \\\"offers\\\": 0,\\n \\\"candidateSlots\\\": 0,\\n \\\"loaded\\\": 0,\\n \\\"zeroHits\\\": 0\\n },\\n \\\"command\\\": {\\n \\\"offers\\\": 0,\\n \\\"candidateSlots\\\": 0,\\n \\\"loaded\\\": 0,\\n \\\"zeroHits\\\": 0\\n },\\n \\\"tool\\\": {\\n \n…[elided 3910 characters]…\n,\"command\":\"prompt\",\"success\":true,\"data\":{\"disposition\":\"handled\"}}\n{\"type\":\"extension_ui_request\",\"id\":\"<RPC_ID>\",\"method\":\"input\",\"title\":\"What do you want help with?\",\"placeholder\":\"Describe your task in natural language…\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<RPC_ID>\",\"method\":\"select\",\"title\":\"How should Shiori use these recommendations?\",\"options\":[\"Pre-load matches and queue task for agent\",\"Review recommendations only\",\"Cancel\"]}\n{\"type\":\"extension_ui_request\",\"id\":\"<RPC_ID>\",\"method\":\"notify\",\"message\":\"Matched 1 skill(s): smoke-skill [trigger]\",\"notifyType\":\"info\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<RPC_ID>\",\"method\":\"select\",\"title\":\"Follow up on a recommendation:\",\"options\":[\"smoke-skill [trigger]\",\"Done\"]}\n{\"id\":\"reload-recommend\",\"type\":\"response\",\"command\":\"prompt\",\"success\":true,\"data\":{\"disposition\":\"handled\"}}\n\n[first process stderr]\n\n[second process stdout]\n{\"id\":\"reload-second-commands\",\"type\":\"response\",\"command\":\"get_commands\",\"success\":true,\"data\":{\"commands\":[{\"name\":\"shiori:doctor\",\"description\":\"Show Pi Skill Shiori configuration and inventory status\",\"source\":\"extension\",\"sourceInfo\":{\"path\":\"<REPOSITORY>\\\\src\\\\index.ts\",\"source\":\"cli\",\"scope\":\"temporary\",\"origin\":\"top-level\"}},{\"name\":\"shiori:reload\",\"description\":\"Rebuild Pi Skill Shiori inventory and optional Pi runtime resources\",\"source\":\"extension\",\"sourceInfo\":{\"path\":\"<REPOSITORY>\\\\src\\\\index.ts\",\"source\":\"cli\",\"scope\":\"temporary\",\"origin\":\"top-level\"}},{\"name\":\"shiori:recommend\",\"description\":\"Recommend Agent Skills for a natural-language task and queue it for the agent\",\"source\":\"extension\",\"sourceInfo\":{\"path\":\"<REPOSITORY>\\\\src\\\\index.ts\",\"source\":\"cli\",\"scope\":\"temporary\",\"origin\":\"top-level\"}},{\"name\":\"shiori:stats\",\"description\":\"Show Pi Skill Shiori operational counters and recommendation feedback\",\"source\":\"extension\",\"sourceInfo\":{\"path\":\"<REPOSITORY>\\\\src\\\\index.ts\",\"source\":\"cli\",\"scope\":\"temporary\",\"origin\":\"top-level\"}},{\"name\":\"shiori:bootstrap\",\"description\":\"Generate a review policy draft from discovered skill descriptions\",\"source\":\"extension\",\"sourceInfo\":{\"path\":\"<REPOSITORY>\\\\src\\\\index.ts\",\"source\":\"cli\",\"scope\":\"temporary\",\"origin\":\"top-level\"}}]}}\n{\"type\":\"extension_ui_request\",\"id\":\"<RPC_ID>\",\"method\":\"input\",\"title\":\"What do you want help with?\",\"placeholder\":\"Describe your task in natural language…\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<RPC_ID>\",\"method\":\"select\",\"title\":\"How should Shiori use these recommendations?\",\"options\":[\"Pre-load matches and queue task for agent\",\"Review recommendations only\",\"Cancel\"]}\n{\"type\":\"extension_ui_request\",\"id\":\"<RPC_ID>\",\"method\":\"notify\",\"message\":\"Matched 1 skill(s): smoke-skill [trigger]\",\"notifyType\":\"info\"}\n{\"type\":\"extension_ui_request\",\"id\":\"<RPC_ID>\",\"method\":\"select\",\"title\":\"Follow up on a recommendation:\",\"options\":[\"smoke-skill [trigger]\",\"Done\"]}\n{\"id\":\"reload-recommend\",\"type\":\"response\",\"command\":\"prompt\",\"success\":true,\"data\":{\"disposition\":\"handled\"}}\n\n[second process stderr]\n",
|
|
67
|
+
"assertions": [
|
|
68
|
+
{
|
|
69
|
+
"id": "inventory_reload",
|
|
70
|
+
"expected": "Runtime reload re-registers Shiori and resets its session-local inventory counter to the single new session_start refresh.",
|
|
71
|
+
"observed": "{\"post_reload_commands\":[\"shiori:doctor\",\"shiori:reload\",\"shiori:recommend\",\"shiori:stats\",\"shiori:bootstrap\"],\"post_reload_inventory_refresh_count\":1}",
|
|
72
|
+
"passed": true
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
"id": "reloaded_extension_registered",
|
|
76
|
+
"expected": "A second actual Pi process registers Shiori again after the first process shuts down.",
|
|
77
|
+
"observed": "{\"commands\":[\"shiori:doctor\",\"shiori:reload\",\"shiori:recommend\",\"shiori:stats\",\"shiori:bootstrap\"]}",
|
|
78
|
+
"passed": true
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
"id": "reloaded_feature_response",
|
|
82
|
+
"expected": "The second process handles Shiori's interactive recommendation and returns the discovered skill.",
|
|
83
|
+
"observed": "{\"response\":{\"id\":\"reload-recommend\",\"type\":\"response\",\"command\":\"prompt\",\"success\":true,\"data\":{\"disposition\":\"handled\"}},\"notification\":{\"type\":\"extension_ui_request\",\"id\":\"<RPC_ID>\",\"method\":\"notify\",\"message\":\"Matched 1 skill(s): smoke-skill [trigger]\",\"notifyType\":\"info\"}}",
|
|
84
|
+
"passed": true
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
"id": "clean_shutdown",
|
|
88
|
+
"expected": "Both actual Pi processes exit with status 0 and emit no unhandled or shutdown errors.",
|
|
89
|
+
"observed": "{\"first_exit_code\":0,\"second_exit_code\":0,\"runtime_errors\":null,\"extension_load_errors\":null}",
|
|
90
|
+
"passed": true
|
|
91
|
+
}
|
|
92
|
+
]
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
"name": "host_shell",
|
|
96
|
+
"command": "npm run smoke:pi (native host shell launches the locally pinned Pi CLI)",
|
|
97
|
+
"exit_code": 0,
|
|
98
|
+
"passed": true,
|
|
99
|
+
"evidence": "1.2.0\n",
|
|
100
|
+
"assertions": [
|
|
101
|
+
{
|
|
102
|
+
"id": "native_shell_boundary",
|
|
103
|
+
"expected": "The native host shell launches the locally pinned Pi CLI and returns exactly its SDK version.",
|
|
104
|
+
"observed": "{\"exit_code\":0,\"output\":\"1.2.0\",\"expectedVersion\":\"1.2.0\"}",
|
|
105
|
+
"passed": true
|
|
106
|
+
}
|
|
107
|
+
]
|
|
108
|
+
}
|
|
109
|
+
]
|
|
110
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-skill-shiori",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.17",
|
|
4
4
|
"description": "Pi extension that reduces Agent Skill catalog tokens with policy-based skill retrieval and on-demand skill loading.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -27,17 +27,19 @@
|
|
|
27
27
|
"LICENSE",
|
|
28
28
|
"SECURITY.md",
|
|
29
29
|
"CHANGELOG.md",
|
|
30
|
-
"
|
|
30
|
+
"docs",
|
|
31
31
|
"src"
|
|
32
32
|
],
|
|
33
33
|
"scripts": {
|
|
34
34
|
"typecheck": "tsc --noEmit",
|
|
35
35
|
"build": "tsc --noEmit",
|
|
36
36
|
"test": "npm run typecheck && tsx --test tests/*.test.mjs",
|
|
37
|
+
"smoke:pi": "node scripts/pi-sdk-smoke.mjs",
|
|
37
38
|
"prepublishOnly": "npm test",
|
|
38
39
|
"release:npm:dry": "npm pack --dry-run",
|
|
39
40
|
"release:npm": "npm publish --access public",
|
|
40
|
-
"version:check": "node scripts/check-version-bump.mjs"
|
|
41
|
+
"version:check": "node scripts/check-version-bump.mjs",
|
|
42
|
+
"smoke:pi:curated": "node scripts/pi-sdk-smoke.mjs --update-curated-report"
|
|
41
43
|
},
|
|
42
44
|
"pi": {
|
|
43
45
|
"extensions": [
|
|
@@ -54,9 +56,10 @@
|
|
|
54
56
|
"typebox": "*"
|
|
55
57
|
},
|
|
56
58
|
"devDependencies": {
|
|
57
|
-
"@earendil-works/pi-
|
|
58
|
-
"@earendil-works/pi-
|
|
59
|
-
"@earendil-works/pi-
|
|
59
|
+
"@earendil-works/pi-agent-core": "1.2.0",
|
|
60
|
+
"@earendil-works/pi-ai": "1.2.0",
|
|
61
|
+
"@earendil-works/pi-coding-agent": "1.2.0",
|
|
62
|
+
"@earendil-works/pi-tui": "1.2.0",
|
|
60
63
|
"@types/node": "^26.0.0",
|
|
61
64
|
"tsx": "^4.22.4",
|
|
62
65
|
"typebox": "latest",
|
package/src/index.ts
CHANGED
|
@@ -142,6 +142,10 @@ export default function piSkillShiori(pi: ExtensionAPI) {
|
|
|
142
142
|
ctx.ui.notify("Pi Skill Shiori: Skill Catalog suppression pattern not found; leaving system prompt unchanged.", "warning");
|
|
143
143
|
}
|
|
144
144
|
|
|
145
|
+
if (event.messageType === "custom") {
|
|
146
|
+
return { systemPrompt: suppression.systemPrompt };
|
|
147
|
+
}
|
|
148
|
+
|
|
145
149
|
const candidates = await measureTiming(
|
|
146
150
|
stats.timing.retrieval,
|
|
147
151
|
() => retrieveCandidatesExpanded(event.prompt, current.skills, current.policy, current),
|
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
import { buildRetrievalQueries } from "./query.js";
|
|
2
2
|
import { compareCandidates, excludedSkillNames, retrieveCandidates } from "./retrieval.js";
|
|
3
|
+
import type { RetrievalIndex } from "./retrieval.js";
|
|
3
4
|
import type { ShioriPolicy, SkillCandidate, SkillRecord } from "./types.js";
|
|
4
5
|
|
|
5
|
-
interface RetrievalIndex {
|
|
6
|
-
search(query: string, limit: number): SkillRecord[];
|
|
7
|
-
}
|
|
8
|
-
|
|
9
6
|
export function retrieveCandidatesExpanded(
|
|
10
7
|
query: string,
|
|
11
8
|
skills: SkillRecord[],
|
package/src/retrieval.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { attachRecommendationReason } from "./recommendation-reason.js";
|
|
2
2
|
import type { ShioriPolicy, SkillCandidate, SkillRecord } from "./types.js";
|
|
3
3
|
|
|
4
|
-
interface RetrievalIndex {
|
|
4
|
+
export interface RetrievalIndex {
|
|
5
5
|
search(query: string, limit: number): SkillRecord[];
|
|
6
6
|
}
|
|
7
7
|
|
|
@@ -12,20 +12,21 @@ export function retrieveCandidates(
|
|
|
12
12
|
index?: RetrievalIndex,
|
|
13
13
|
): SkillCandidate[] {
|
|
14
14
|
const normalizedQuery = normalize(query);
|
|
15
|
+
const queryTokens = tokenize(normalizedQuery);
|
|
15
16
|
const candidatesByName = new Map<string, SkillCandidate>();
|
|
16
17
|
const triggerableSkills = skills.filter(
|
|
17
18
|
(skill) => (policy.skills[skill.name]?.activation ?? policy.defaults.activation) === "triggerable",
|
|
18
19
|
);
|
|
19
20
|
|
|
20
21
|
for (const skill of triggerableSkills) {
|
|
21
|
-
const triggerCandidate = evaluateSkill(skill, normalizedQuery, policy, true);
|
|
22
|
+
const triggerCandidate = evaluateSkill(skill, normalizedQuery, queryTokens, policy, true);
|
|
22
23
|
if (triggerCandidate) candidatesByName.set(skill.name, triggerCandidate);
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
const ftsMatches = index?.search(query, policy.candidateInjection.maxCandidates * 4) ?? [];
|
|
26
27
|
const scoringPool = ftsMatches.length > 0 ? ftsMatches : skills;
|
|
27
28
|
for (const skill of scoringPool) {
|
|
28
|
-
const candidate = evaluateSkill(skill, normalizedQuery, policy, false);
|
|
29
|
+
const candidate = evaluateSkill(skill, normalizedQuery, queryTokens, policy, false);
|
|
29
30
|
if (!candidate) continue;
|
|
30
31
|
const previous = candidatesByName.get(skill.name);
|
|
31
32
|
if (!previous || candidate.score > previous.score) {
|
|
@@ -89,6 +90,7 @@ export function excludedSkillNames(
|
|
|
89
90
|
function evaluateSkill(
|
|
90
91
|
skill: SkillRecord,
|
|
91
92
|
normalizedQuery: string,
|
|
93
|
+
queryTokens: ReadonlySet<string>,
|
|
92
94
|
policy: ShioriPolicy,
|
|
93
95
|
exactTriggerOnly: boolean,
|
|
94
96
|
): SkillCandidate | undefined {
|
|
@@ -113,7 +115,7 @@ function evaluateSkill(
|
|
|
113
115
|
if (exactTriggerOnly) return undefined;
|
|
114
116
|
|
|
115
117
|
const text = normalize(`${skill.name} ${skill.description} ${includes.join(" ")}`);
|
|
116
|
-
const tokenScore = scoreTokens(
|
|
118
|
+
const tokenScore = scoreTokens(queryTokens, text);
|
|
117
119
|
if (tokenScore < policy.candidateInjection.minScore) return undefined;
|
|
118
120
|
return attachRecommendationReason(
|
|
119
121
|
{
|
|
@@ -134,8 +136,11 @@ function includesNormalized(query: string, trigger: string): boolean {
|
|
|
134
136
|
return query.includes(normalize(trigger));
|
|
135
137
|
}
|
|
136
138
|
|
|
137
|
-
function
|
|
138
|
-
|
|
139
|
+
function tokenize(query: string): Set<string> {
|
|
140
|
+
return new Set(query.split(/[^\p{L}\p{N}_-]+/u).filter((token) => token.length >= 2));
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function scoreTokens(tokens: ReadonlySet<string>, text: string): number {
|
|
139
144
|
if (tokens.size === 0) return 0;
|
|
140
145
|
let hits = 0;
|
|
141
146
|
for (const token of tokens) {
|
|
File without changes
|
/package/{Docs → docs}/usage.md
RENAMED
|
File without changes
|