pi-autotalk 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/CHANGELOG.md +13 -0
- package/LICENSE +21 -0
- package/README.md +233 -0
- package/docs/examples.md +49 -0
- package/docs/github-template.md +43 -0
- package/docs/release.md +38 -0
- package/docs/repository-settings.md +41 -0
- package/docs/template-checklist.md +85 -0
- package/docs/typescript.md +75 -0
- package/extensions/index.ts +226 -0
- package/lib/autotalk.ts +84 -0
- package/package.json +54 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
This project follows semantic versioning.
|
|
6
|
+
|
|
7
|
+
## [0.1.0] - YYYY-MM-DD
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- Initial Pi package template.
|
|
12
|
+
- Example extension, Agent Skill, prompt, and theme.
|
|
13
|
+
- CI and npm Trusted Publishing workflow.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 YOUR_NAME
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
# Pi AutoTalk
|
|
2
|
+
|
|
3
|
+
[](https://github.com/eiei114/pi-autotalk/actions/workflows/ci.yml)
|
|
4
|
+
[](https://github.com/eiei114/pi-autotalk/actions/workflows/publish.yml)
|
|
5
|
+
[](https://www.npmjs.com/package/pi-autotalk)
|
|
6
|
+
[](https://www.npmjs.com/package/pi-autotalk)
|
|
7
|
+
[](LICENSE)
|
|
8
|
+
[](https://pi.dev/packages)
|
|
9
|
+
[](docs/release.md)
|
|
10
|
+
|
|
11
|
+
> Timed AutoTalk for Pi: periodically send your editor thoughts to the agent for brainstorming.
|
|
12
|
+
|
|
13
|
+
Pi AutoTalk turns Pi's interactive editor into a lightweight thinking buffer. Turn it on, type rough notes or mutterings into the editor, and Pi periodically sends them back to the agent as an AutoTalk thought memo.
|
|
14
|
+
|
|
15
|
+
Status: **MVP implemented and locally dogfooded**. AutoTalk is always off by default and only runs after `/autotalk:on`.
|
|
16
|
+
|
|
17
|
+
## Why
|
|
18
|
+
|
|
19
|
+
Sometimes you do not want to craft a polished prompt. You want to think out loud, let the agent react, and keep moving. AutoTalk is for that mode:
|
|
20
|
+
|
|
21
|
+
- brainstorming while typing fragments
|
|
22
|
+
- talking through an idea before it becomes a task
|
|
23
|
+
- keeping momentum without repeatedly pressing submit
|
|
24
|
+
- asking Pi to reflect on your current train of thought
|
|
25
|
+
|
|
26
|
+
## What it does
|
|
27
|
+
|
|
28
|
+
When enabled, AutoTalk:
|
|
29
|
+
|
|
30
|
+
1. watches the interactive editor buffer;
|
|
31
|
+
2. waits until you have stopped typing for a short moment;
|
|
32
|
+
3. sends the full buffer on an interval;
|
|
33
|
+
4. wraps it in an `[AutoTalk]` thought-memo prefix;
|
|
34
|
+
5. clears the editor only if the text has not changed since it was read.
|
|
35
|
+
|
|
36
|
+
It is deliberately conservative. Slash commands are protected, enabled state is not persisted, and AutoTalk messages tell the agent not to edit files, run commands, or send external requests unless explicitly asked.
|
|
37
|
+
|
|
38
|
+
## Commands
|
|
39
|
+
|
|
40
|
+
| Command | Purpose |
|
|
41
|
+
|---|---|
|
|
42
|
+
| `/autotalk:on` | Start timed sending. Does not immediately send existing editor text. |
|
|
43
|
+
| `/autotalk:off` | Stop timed sending and clear AutoTalk footer status. |
|
|
44
|
+
| `/autotalk:mode` | Select busy-agent delivery mode: `followUp` or `steer`. |
|
|
45
|
+
| `/autotalk:settings` | Configure interval seconds and delivery mode. |
|
|
46
|
+
|
|
47
|
+
## Behavior details
|
|
48
|
+
|
|
49
|
+
### Sending interval
|
|
50
|
+
|
|
51
|
+
- Default: `10` seconds.
|
|
52
|
+
- Allowed range: `5` to `120` seconds.
|
|
53
|
+
- Settings UI rejects non-integers and out-of-range values.
|
|
54
|
+
|
|
55
|
+
### Typing guard
|
|
56
|
+
|
|
57
|
+
AutoTalk skips a tick if the editor changed within the last 2 seconds. This avoids sending half-typed fragments at the exact moment you are still writing.
|
|
58
|
+
|
|
59
|
+
### Slash-command guard
|
|
60
|
+
|
|
61
|
+
If the editor starts with `/`, AutoTalk pauses for that tick and does not clear the editor. This prevents commands like `/autotalk:off`, `/reload`, or `/model` from being auto-sent as thought memos.
|
|
62
|
+
|
|
63
|
+
### Safe clearing
|
|
64
|
+
|
|
65
|
+
After sending a non-empty buffer, AutoTalk clears the editor only if the editor still exactly matches the text that was sent. If you type more while a send is happening, the new text is preserved.
|
|
66
|
+
|
|
67
|
+
### Empty prompt
|
|
68
|
+
|
|
69
|
+
If the editor is empty, AutoTalk sends a one-shot continuation prompt:
|
|
70
|
+
|
|
71
|
+
```text
|
|
72
|
+
[AutoTalk]
|
|
73
|
+
入力欄が空です。ここまでの流れから、次に考える問いを1つ出してください。
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
That empty prompt is sent only once. It resets after a real non-empty thought memo is sent.
|
|
77
|
+
|
|
78
|
+
### Busy-agent delivery modes
|
|
79
|
+
|
|
80
|
+
When the agent is already responding:
|
|
81
|
+
|
|
82
|
+
- `followUp` queues the thought memo after the current work finishes.
|
|
83
|
+
- `steer` sends it as steering input for the current stream.
|
|
84
|
+
|
|
85
|
+
Use `followUp` for orderly logs. Use `steer` for live brainstorming and course correction.
|
|
86
|
+
|
|
87
|
+
## AutoTalk message format
|
|
88
|
+
|
|
89
|
+
Non-empty editor text is sent like this:
|
|
90
|
+
|
|
91
|
+
```text
|
|
92
|
+
[AutoTalk]
|
|
93
|
+
これは自動送信されたユーザーの思考メモです。
|
|
94
|
+
アイデアを広げ、論点を整理し、次の問いを1つ出してください。
|
|
95
|
+
明示依頼でない限り、ファイル編集・コマンド実行・外部送信はしないでください。
|
|
96
|
+
|
|
97
|
+
--- 思考メモ ---
|
|
98
|
+
{editor text}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Settings persistence
|
|
102
|
+
|
|
103
|
+
AutoTalk persists interval and delivery mode globally at:
|
|
104
|
+
|
|
105
|
+
```text
|
|
106
|
+
~/.pi/agent/extensions/autotalk/settings.json
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Example:
|
|
110
|
+
|
|
111
|
+
```json
|
|
112
|
+
{
|
|
113
|
+
"intervalSec": 10,
|
|
114
|
+
"deliveryMode": "followUp"
|
|
115
|
+
}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
The enabled/disabled state is **never persisted**. Every Pi session starts with AutoTalk off.
|
|
119
|
+
|
|
120
|
+
## Install
|
|
121
|
+
|
|
122
|
+
### From npm
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
pi install npm:pi-autotalk
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### From GitHub
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
pi install git:github.com/eiei114/pi-autotalk
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### Local development install
|
|
135
|
+
|
|
136
|
+
Clone or keep the repo under:
|
|
137
|
+
|
|
138
|
+
```text
|
|
139
|
+
C:/Users/Keisu/Projects/OSS/pi-autotalk
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Then add it to a project `.pi/settings.json`:
|
|
143
|
+
|
|
144
|
+
```json
|
|
145
|
+
{
|
|
146
|
+
"packages": [
|
|
147
|
+
"..\\..\\..\\OSS\\pi-autotalk"
|
|
148
|
+
]
|
|
149
|
+
}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
After editing settings, reload Pi:
|
|
153
|
+
|
|
154
|
+
```text
|
|
155
|
+
/reload
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
## Quick start
|
|
159
|
+
|
|
160
|
+
```text
|
|
161
|
+
/autotalk:on
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
Type a thought into the editor and stop typing. After the configured interval, Pi will receive it as an AutoTalk thought memo.
|
|
165
|
+
|
|
166
|
+
Useful commands:
|
|
167
|
+
|
|
168
|
+
```text
|
|
169
|
+
/autotalk:settings
|
|
170
|
+
/autotalk:mode
|
|
171
|
+
/autotalk:off
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
## Package contents
|
|
175
|
+
|
|
176
|
+
| Path | Purpose |
|
|
177
|
+
|---|---|
|
|
178
|
+
| `extensions/index.ts` | Pi extension entrypoint and command/timer wiring. |
|
|
179
|
+
| `lib/autotalk.ts` | Settings validation, persistence, and message formatting helpers. |
|
|
180
|
+
| `tests/` | Node test suite for package metadata, formatting, settings, and registration. |
|
|
181
|
+
| `docs/` | Release and template maintenance docs. |
|
|
182
|
+
|
|
183
|
+
## Development
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
npm install
|
|
187
|
+
npm run ci
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
`npm run ci` runs:
|
|
191
|
+
|
|
192
|
+
1. `tsc --noEmit`
|
|
193
|
+
2. `node --test tests/*.test.mjs`
|
|
194
|
+
3. `npm pack --dry-run`
|
|
195
|
+
|
|
196
|
+
## Security and privacy
|
|
197
|
+
|
|
198
|
+
AutoTalk intentionally sends editor contents to the active Pi agent. Treat it like an auto-submit feature.
|
|
199
|
+
|
|
200
|
+
Safety choices in the MVP:
|
|
201
|
+
|
|
202
|
+
- starts disabled on every launch;
|
|
203
|
+
- requires explicit `/autotalk:on`;
|
|
204
|
+
- never persists enabled state;
|
|
205
|
+
- pauses while the editor begins with `/`;
|
|
206
|
+
- does not clear the editor if new text appeared during send;
|
|
207
|
+
- frames messages as thought memos, not direct execution requests;
|
|
208
|
+
- asks the agent not to edit files, run commands, or send external requests unless explicitly requested.
|
|
209
|
+
|
|
210
|
+
Pi packages can execute code with your local permissions. Review extensions before installing third-party packages.
|
|
211
|
+
|
|
212
|
+
For vulnerability reporting, see [`SECURITY.md`](SECURITY.md).
|
|
213
|
+
|
|
214
|
+
## Release
|
|
215
|
+
|
|
216
|
+
This package is set up for npm Trusted Publishing, so no `NPM_TOKEN` is required.
|
|
217
|
+
|
|
218
|
+
```bash
|
|
219
|
+
npm version patch
|
|
220
|
+
git push --follow-tags
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
See [`docs/release.md`](docs/release.md) for setup details.
|
|
224
|
+
|
|
225
|
+
## Links
|
|
226
|
+
|
|
227
|
+
- npm: https://www.npmjs.com/package/pi-autotalk
|
|
228
|
+
- GitHub: https://github.com/eiei114/pi-autotalk
|
|
229
|
+
- Issues: https://github.com/eiei114/pi-autotalk/issues
|
|
230
|
+
|
|
231
|
+
## License
|
|
232
|
+
|
|
233
|
+
MIT
|
package/docs/examples.md
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Examples
|
|
2
|
+
|
|
3
|
+
This template ships one minimal example for each Pi package resource type.
|
|
4
|
+
|
|
5
|
+
## Extension
|
|
6
|
+
|
|
7
|
+
`extensions/hello.ts` registers:
|
|
8
|
+
|
|
9
|
+
- `/template-hello`
|
|
10
|
+
- a small session status indicator
|
|
11
|
+
|
|
12
|
+
Try it with:
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
pi -e .
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Then run:
|
|
19
|
+
|
|
20
|
+
```txt
|
|
21
|
+
/template-hello YourName
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Agent Skill
|
|
25
|
+
|
|
26
|
+
`skills/example-skill/SKILL.md` demonstrates a minimal Agent Skill.
|
|
27
|
+
|
|
28
|
+
Replace it with your real workflow instructions.
|
|
29
|
+
|
|
30
|
+
## Prompt template
|
|
31
|
+
|
|
32
|
+
`prompts/example.md` demonstrates a tiny prompt template with one variable.
|
|
33
|
+
|
|
34
|
+
## Theme
|
|
35
|
+
|
|
36
|
+
`themes/example-theme.json` is a placeholder theme. Replace it or remove `themes/` if your package does not ship themes.
|
|
37
|
+
|
|
38
|
+
## Typed custom tool
|
|
39
|
+
|
|
40
|
+
`extensions/index.ts` registers:
|
|
41
|
+
|
|
42
|
+
- `/template-info`
|
|
43
|
+
- `template_greet` custom tool
|
|
44
|
+
|
|
45
|
+
The tool demonstrates:
|
|
46
|
+
|
|
47
|
+
- TypeBox object parameters
|
|
48
|
+
- a string enum schema via `StringEnum`
|
|
49
|
+
- shared logic imported from `lib/greeting.ts`
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# GitHub Template Repository
|
|
2
|
+
|
|
3
|
+
Enable template mode on the source repository:
|
|
4
|
+
|
|
5
|
+
```txt
|
|
6
|
+
GitHub repo → Settings → General → Template repository
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
Create a public repository from the template:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
gh repo create OWNER/new-pi-extension \
|
|
13
|
+
--public \
|
|
14
|
+
--template OWNER/pi-extension-template \
|
|
15
|
+
--clone
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Create a private repository from the template:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
gh repo create OWNER/new-pi-extension \
|
|
22
|
+
--private \
|
|
23
|
+
--template OWNER/pi-extension-template \
|
|
24
|
+
--clone
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Include all branches if needed:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
gh repo create OWNER/new-pi-extension \
|
|
31
|
+
--public \
|
|
32
|
+
--template OWNER/pi-extension-template \
|
|
33
|
+
--include-all-branches \
|
|
34
|
+
--clone
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
After creation:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
cd new-pi-extension
|
|
41
|
+
npm install
|
|
42
|
+
npm run ci
|
|
43
|
+
```
|
package/docs/release.md
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Release
|
|
2
|
+
|
|
3
|
+
This package uses npm Trusted Publishing with GitHub Actions OIDC.
|
|
4
|
+
|
|
5
|
+
Do not add `NPM_TOKEN` or long-lived npm tokens to GitHub Secrets.
|
|
6
|
+
|
|
7
|
+
## One-time npm setup
|
|
8
|
+
|
|
9
|
+
On npmjs.com, configure Trusted Publishing for this package:
|
|
10
|
+
|
|
11
|
+
- Publisher: GitHub Actions
|
|
12
|
+
- Repository: this GitHub repository
|
|
13
|
+
- Workflow filename: `publish.yml`
|
|
14
|
+
|
|
15
|
+
## Publish
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm version patch
|
|
19
|
+
git push --follow-tags
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
The `v*` tag triggers `.github/workflows/publish.yml`, which runs CI and publishes to npm.
|
|
23
|
+
|
|
24
|
+
## GitHub Actions requirements
|
|
25
|
+
|
|
26
|
+
- `permissions: id-token: write`
|
|
27
|
+
- GitHub-hosted runner
|
|
28
|
+
- No `NPM_TOKEN`
|
|
29
|
+
- `npm publish` from the configured workflow file
|
|
30
|
+
|
|
31
|
+
## First release checklist
|
|
32
|
+
|
|
33
|
+
- [ ] `package.json` name is final
|
|
34
|
+
- [ ] `repository.url` points to the real GitHub repository
|
|
35
|
+
- [ ] npm Trusted Publisher is configured
|
|
36
|
+
- [ ] `npm run ci` passes
|
|
37
|
+
- [ ] `npm pack --dry-run` contains only intended files
|
|
38
|
+
- [ ] `CHANGELOG.md` has the release date
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Repository Settings
|
|
2
|
+
|
|
3
|
+
Use this file after creating a real repository from the template.
|
|
4
|
+
|
|
5
|
+
## GitHub About
|
|
6
|
+
|
|
7
|
+
Suggested fields:
|
|
8
|
+
|
|
9
|
+
- Description: one-line pitch for the Pi package
|
|
10
|
+
- Website: npm package URL or project docs URL
|
|
11
|
+
- Topics:
|
|
12
|
+
- `pi`
|
|
13
|
+
- `pi-package`
|
|
14
|
+
- `agent-skill`
|
|
15
|
+
- `typescript`
|
|
16
|
+
|
|
17
|
+
## Template mode
|
|
18
|
+
|
|
19
|
+
If this repository itself should be reusable as a template:
|
|
20
|
+
|
|
21
|
+
```txt
|
|
22
|
+
Settings → General → Template repository
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Branch protection
|
|
26
|
+
|
|
27
|
+
Recommended for public packages:
|
|
28
|
+
|
|
29
|
+
- Require pull request before merging
|
|
30
|
+
- Require status checks to pass
|
|
31
|
+
- Require `CI` workflow
|
|
32
|
+
- Block force pushes on the default branch
|
|
33
|
+
|
|
34
|
+
## npm package page
|
|
35
|
+
|
|
36
|
+
After first publish:
|
|
37
|
+
|
|
38
|
+
- Confirm README renders correctly
|
|
39
|
+
- Confirm package provenance appears
|
|
40
|
+
- Confirm package contents are intentional
|
|
41
|
+
- Add npm URL to GitHub About and README
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# Template Setup Checklist
|
|
2
|
+
|
|
3
|
+
このテンプレートから新しい Pi 拡張OSSを作った後に埋めること。
|
|
4
|
+
|
|
5
|
+
## Repository
|
|
6
|
+
|
|
7
|
+
- [ ] GitHub repository name を決める
|
|
8
|
+
- [ ] GitHub About 欄を書く
|
|
9
|
+
- [ ] GitHub topics を設定する
|
|
10
|
+
- [ ] `pi`
|
|
11
|
+
- [ ] `pi-package`
|
|
12
|
+
- [ ] `agent-skill`
|
|
13
|
+
- [ ] `typescript`
|
|
14
|
+
- [ ] GitHub Settingsで `Template repository` をONにする
|
|
15
|
+
- [ ] Repository URL を `package.json` に反映する
|
|
16
|
+
- [ ] README の `OWNER/REPO` を実リポジトリに置き換える
|
|
17
|
+
|
|
18
|
+
## Package metadata
|
|
19
|
+
|
|
20
|
+
- [ ] `package.json` の `name` を変更する
|
|
21
|
+
- [ ] `description` を書く
|
|
22
|
+
- [ ] `author` を入れる
|
|
23
|
+
- [ ] `repository.url` を埋める
|
|
24
|
+
- [ ] `bugs.url` を埋める
|
|
25
|
+
- [ ] `homepage` を埋める
|
|
26
|
+
- [ ] `keywords` を見直す
|
|
27
|
+
- [ ] `LICENSE` の年・名前を更新する
|
|
28
|
+
|
|
29
|
+
## README placeholders
|
|
30
|
+
|
|
31
|
+
- [ ] `PACKAGE_DISPLAY_NAME` を置き換える
|
|
32
|
+
- [ ] `PACKAGE_NAME` を置き換える
|
|
33
|
+
- [ ] `OWNER/REPO` を置き換える
|
|
34
|
+
- [ ] one-line pitch を書く
|
|
35
|
+
- [ ] feature list を書く
|
|
36
|
+
- [ ] quick start command を実コマンドにする
|
|
37
|
+
- [ ] npm URL を確認する
|
|
38
|
+
- [ ] GitHub URL を確認する
|
|
39
|
+
|
|
40
|
+
## Pi package manifest
|
|
41
|
+
|
|
42
|
+
- [ ] `pi.extensions` に公開する拡張だけを残す
|
|
43
|
+
- [ ] `pi.skills` に公開する skill だけを残す
|
|
44
|
+
- [ ] 不要なら `prompts/` を消す
|
|
45
|
+
- [ ] 不要なら `themes/` を消す
|
|
46
|
+
- [ ] サンプル名を実名に変える
|
|
47
|
+
|
|
48
|
+
## TypeScript
|
|
49
|
+
|
|
50
|
+
- [ ] `extensions/index.ts` を実装に合わせて更新する
|
|
51
|
+
- [ ] `extensions/hello.ts` が不要なら削除する
|
|
52
|
+
- [ ] 共通ロジックを `lib/` に切り出す
|
|
53
|
+
- [ ] `strict: true` を維持する
|
|
54
|
+
- [ ] custom tool parameters は TypeBox schema で定義する
|
|
55
|
+
- [ ] string choices は `StringEnum` helper を使う
|
|
56
|
+
- [ ] runtime dependency は `dependencies`、Pi提供packageは `peerDependencies` に置く
|
|
57
|
+
- [ ] `package.json.files` に公開対象だけを入れる
|
|
58
|
+
|
|
59
|
+
## GitHub Template repo
|
|
60
|
+
|
|
61
|
+
- [ ] `gh repo create --template OWNER/pi-extension-template` で作成できることを確認する
|
|
62
|
+
- [ ] public/privateどちらの作成例もdocsに載せる
|
|
63
|
+
|
|
64
|
+
## CI / Release
|
|
65
|
+
|
|
66
|
+
- [ ] `npm run ci` が通る
|
|
67
|
+
- [ ] `npm pack --dry-run` が通る
|
|
68
|
+
- [ ] npm Trusted Publishing を設定する
|
|
69
|
+
- [ ] `NPM_TOKEN` を使っていないことを確認する
|
|
70
|
+
- [ ] tag publish が動くことを初回リリースで確認する
|
|
71
|
+
|
|
72
|
+
## npm page
|
|
73
|
+
|
|
74
|
+
- [ ] npm package URL を README に追加する
|
|
75
|
+
- [ ] npm description が適切に表示されるか確認する
|
|
76
|
+
- [ ] provenance が付いているか確認する
|
|
77
|
+
- [ ] 不要なファイルが package に含まれていないか確認する
|
|
78
|
+
|
|
79
|
+
## Before first release
|
|
80
|
+
|
|
81
|
+
- [ ] サンプルコードを実機 Pi でロードする
|
|
82
|
+
- [ ] `pi install git:github.com/OWNER/REPO` を試す
|
|
83
|
+
- [ ] `pi -e .` を試す
|
|
84
|
+
- [ ] README のコマンドがコピペで動くか確認する
|
|
85
|
+
- [ ] CHANGELOG に `0.1.0` を書く
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# TypeScript Guide
|
|
2
|
+
|
|
3
|
+
This is a TypeScript-first Pi package template.
|
|
4
|
+
|
|
5
|
+
## Layout
|
|
6
|
+
|
|
7
|
+
```txt
|
|
8
|
+
extensions/*.ts Pi extension entrypoints
|
|
9
|
+
lib/*.ts Shared TypeScript helpers
|
|
10
|
+
skills/*/SKILL.md Agent Skills
|
|
11
|
+
prompts/*.md Prompt templates
|
|
12
|
+
themes/*.json Themes
|
|
13
|
+
tests/*.test.mjs Smoke tests
|
|
14
|
+
tests/*.test.ts Optional TypeScript tests if you add a TS test runner
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Pi loads TypeScript extensions directly, so no build step is required for normal use.
|
|
18
|
+
|
|
19
|
+
## Strict mode
|
|
20
|
+
|
|
21
|
+
`tsconfig.json` keeps `strict: true`. Prefer fixing types over loosening compiler options.
|
|
22
|
+
|
|
23
|
+
## Extension entrypoints
|
|
24
|
+
|
|
25
|
+
Two entrypoint styles are shown:
|
|
26
|
+
|
|
27
|
+
- `extensions/hello.ts`: single-file extension
|
|
28
|
+
- `extensions/index.ts`: index-style extension that imports shared code from `lib/`
|
|
29
|
+
|
|
30
|
+
For larger packages, keep entrypoints thin and put reusable logic in `lib/`.
|
|
31
|
+
|
|
32
|
+
## TypeBox schemas
|
|
33
|
+
|
|
34
|
+
Use TypeBox schemas for custom tool parameters.
|
|
35
|
+
|
|
36
|
+
```ts
|
|
37
|
+
import { Type } from "typebox";
|
|
38
|
+
|
|
39
|
+
const parameters = Type.Object({
|
|
40
|
+
name: Type.String({ description: "Name to greet" }),
|
|
41
|
+
});
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## String enums
|
|
45
|
+
|
|
46
|
+
For string choices, use the local `StringEnum` helper from `lib/schema.ts`.
|
|
47
|
+
|
|
48
|
+
```ts
|
|
49
|
+
import { StringEnum } from "../lib/schema.ts";
|
|
50
|
+
|
|
51
|
+
const mode = StringEnum(["short", "friendly"], {
|
|
52
|
+
description: "Greeting style",
|
|
53
|
+
});
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
This emits a JSON Schema `enum`, which is friendlier to model providers than a union of string literals.
|
|
57
|
+
|
|
58
|
+
## Runtime dependencies vs peer dependencies
|
|
59
|
+
|
|
60
|
+
Pi bundles core packages for extension authors. Keep Pi-provided packages as `peerDependencies` and also install them as `devDependencies` for local typechecking.
|
|
61
|
+
|
|
62
|
+
Use `peerDependencies` for:
|
|
63
|
+
|
|
64
|
+
- `@earendil-works/pi-coding-agent`
|
|
65
|
+
- `@earendil-works/pi-ai`
|
|
66
|
+
- `@earendil-works/pi-tui`
|
|
67
|
+
- `typebox`
|
|
68
|
+
|
|
69
|
+
Use `dependencies` for runtime packages your extension imports that Pi does not provide.
|
|
70
|
+
|
|
71
|
+
Use `devDependencies` for local-only tools such as TypeScript, test runners, and linters.
|
|
72
|
+
|
|
73
|
+
## Package contents
|
|
74
|
+
|
|
75
|
+
Control npm package contents with `package.json` `files`. Prefer this over `.npmignore` so the published package stays explicit.
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
ExtensionAPI,
|
|
3
|
+
ExtensionCommandContext,
|
|
4
|
+
ExtensionContext,
|
|
5
|
+
} from "@earendil-works/pi-coding-agent";
|
|
6
|
+
import {
|
|
7
|
+
DEFAULT_SETTINGS,
|
|
8
|
+
formatEmptyPrompt,
|
|
9
|
+
formatThoughtMemo,
|
|
10
|
+
IDLE_BEFORE_SEND_MS,
|
|
11
|
+
loadSettings,
|
|
12
|
+
normalizeInterval,
|
|
13
|
+
saveSettings,
|
|
14
|
+
WATCH_EDITOR_MS,
|
|
15
|
+
type AutoTalkSettings,
|
|
16
|
+
type DeliveryMode,
|
|
17
|
+
} from "../lib/autotalk.ts";
|
|
18
|
+
|
|
19
|
+
type Timer = ReturnType<typeof setInterval>;
|
|
20
|
+
|
|
21
|
+
export default function (pi: ExtensionAPI) {
|
|
22
|
+
let settings: AutoTalkSettings = { ...DEFAULT_SETTINGS };
|
|
23
|
+
let enabled = false;
|
|
24
|
+
let tickTimer: Timer | undefined;
|
|
25
|
+
let editorWatcher: Timer | undefined;
|
|
26
|
+
let latestContext: ExtensionContext | undefined;
|
|
27
|
+
let lastObservedEditorText = "";
|
|
28
|
+
let lastInputChangeAt = Date.now();
|
|
29
|
+
let emptyPromptSent = false;
|
|
30
|
+
let sending = false;
|
|
31
|
+
|
|
32
|
+
function updateStatus(ctx = latestContext): void {
|
|
33
|
+
if (!ctx?.hasUI) return;
|
|
34
|
+
|
|
35
|
+
if (!enabled) {
|
|
36
|
+
ctx.ui.setStatus("autotalk", undefined);
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
ctx.ui.setStatus(
|
|
41
|
+
"autotalk",
|
|
42
|
+
ctx.ui.theme.fg("accent", "AutoTalk") +
|
|
43
|
+
ctx.ui.theme.fg("dim", ` on ${settings.intervalSec}s ${settings.deliveryMode}`),
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function clearTimers(): void {
|
|
48
|
+
if (tickTimer) clearInterval(tickTimer);
|
|
49
|
+
if (editorWatcher) clearInterval(editorWatcher);
|
|
50
|
+
tickTimer = undefined;
|
|
51
|
+
editorWatcher = undefined;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function observeEditor(ctx = latestContext): void {
|
|
55
|
+
if (!ctx?.hasUI) return;
|
|
56
|
+
|
|
57
|
+
const current = ctx.ui.getEditorText();
|
|
58
|
+
if (current !== lastObservedEditorText) {
|
|
59
|
+
lastObservedEditorText = current;
|
|
60
|
+
lastInputChangeAt = Date.now();
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function sendUserMessage(ctx: ExtensionContext, text: string): void {
|
|
65
|
+
if (ctx.isIdle()) {
|
|
66
|
+
pi.sendUserMessage(text);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
pi.sendUserMessage(text, { deliverAs: settings.deliveryMode });
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function startTimers(ctx: ExtensionContext): void {
|
|
74
|
+
clearTimers();
|
|
75
|
+
latestContext = ctx;
|
|
76
|
+
lastObservedEditorText = ctx.hasUI ? ctx.ui.getEditorText() : "";
|
|
77
|
+
lastInputChangeAt = Date.now();
|
|
78
|
+
|
|
79
|
+
editorWatcher = setInterval(() => observeEditor(), WATCH_EDITOR_MS);
|
|
80
|
+
tickTimer = setInterval(() => {
|
|
81
|
+
void tick();
|
|
82
|
+
}, settings.intervalSec * 1_000);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
async function tick(): Promise<void> {
|
|
86
|
+
const ctx = latestContext;
|
|
87
|
+
if (!enabled || sending || !ctx?.hasUI) return;
|
|
88
|
+
|
|
89
|
+
observeEditor(ctx);
|
|
90
|
+
|
|
91
|
+
if (Date.now() - lastInputChangeAt < IDLE_BEFORE_SEND_MS) return;
|
|
92
|
+
|
|
93
|
+
const editorText = ctx.ui.getEditorText();
|
|
94
|
+
|
|
95
|
+
if (editorText.startsWith("/")) return;
|
|
96
|
+
|
|
97
|
+
if (editorText.trim() === "") {
|
|
98
|
+
if (emptyPromptSent) return;
|
|
99
|
+
|
|
100
|
+
try {
|
|
101
|
+
sending = true;
|
|
102
|
+
sendUserMessage(ctx, formatEmptyPrompt());
|
|
103
|
+
emptyPromptSent = true;
|
|
104
|
+
} finally {
|
|
105
|
+
sending = false;
|
|
106
|
+
}
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const textToSend = editorText;
|
|
111
|
+
|
|
112
|
+
try {
|
|
113
|
+
sending = true;
|
|
114
|
+
sendUserMessage(ctx, formatThoughtMemo(textToSend));
|
|
115
|
+
emptyPromptSent = false;
|
|
116
|
+
|
|
117
|
+
if (ctx.ui.getEditorText() === textToSend) {
|
|
118
|
+
ctx.ui.setEditorText("");
|
|
119
|
+
lastObservedEditorText = "";
|
|
120
|
+
lastInputChangeAt = Date.now();
|
|
121
|
+
} else {
|
|
122
|
+
observeEditor(ctx);
|
|
123
|
+
}
|
|
124
|
+
} finally {
|
|
125
|
+
sending = false;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function requireUi(ctx: ExtensionCommandContext): boolean {
|
|
130
|
+
if (ctx.hasUI) return true;
|
|
131
|
+
ctx.ui.notify("AutoTalk requires Pi interactive UI.", "warning");
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function enable(ctx: ExtensionCommandContext): void {
|
|
136
|
+
if (!requireUi(ctx)) return;
|
|
137
|
+
|
|
138
|
+
enabled = true;
|
|
139
|
+
emptyPromptSent = false;
|
|
140
|
+
startTimers(ctx);
|
|
141
|
+
updateStatus(ctx);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function disable(ctx = latestContext): void {
|
|
145
|
+
enabled = false;
|
|
146
|
+
clearTimers();
|
|
147
|
+
updateStatus(ctx);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
async function setMode(ctx: ExtensionCommandContext): Promise<void> {
|
|
151
|
+
if (!requireUi(ctx)) return;
|
|
152
|
+
|
|
153
|
+
const choice = await ctx.ui.select("AutoTalk delivery mode:", ["followUp", "steer"]);
|
|
154
|
+
if (choice !== "followUp" && choice !== "steer") return;
|
|
155
|
+
|
|
156
|
+
settings = { ...settings, deliveryMode: choice as DeliveryMode };
|
|
157
|
+
await saveSettings(settings);
|
|
158
|
+
updateStatus(ctx);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
async function openSettings(ctx: ExtensionCommandContext): Promise<void> {
|
|
162
|
+
if (!requireUi(ctx)) return;
|
|
163
|
+
|
|
164
|
+
const intervalInput = await ctx.ui.input(
|
|
165
|
+
"AutoTalk interval seconds (5-120):",
|
|
166
|
+
String(settings.intervalSec),
|
|
167
|
+
);
|
|
168
|
+
if (intervalInput === undefined) return;
|
|
169
|
+
|
|
170
|
+
const intervalSec = normalizeInterval(intervalInput.trim());
|
|
171
|
+
if (intervalSec === undefined) {
|
|
172
|
+
ctx.ui.notify("Interval must be an integer from 5 to 120 seconds.", "warning");
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
const mode = await ctx.ui.select("AutoTalk delivery mode:", ["followUp", "steer"]);
|
|
177
|
+
if (mode !== "followUp" && mode !== "steer") return;
|
|
178
|
+
|
|
179
|
+
settings = { intervalSec, deliveryMode: mode as DeliveryMode };
|
|
180
|
+
await saveSettings(settings);
|
|
181
|
+
|
|
182
|
+
if (enabled) startTimers(ctx);
|
|
183
|
+
updateStatus(ctx);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
pi.on("session_start", async (_event, ctx) => {
|
|
187
|
+
latestContext = ctx;
|
|
188
|
+
settings = await loadSettings();
|
|
189
|
+
enabled = false;
|
|
190
|
+
clearTimers();
|
|
191
|
+
updateStatus(ctx);
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
pi.on("session_shutdown", () => {
|
|
195
|
+
enabled = false;
|
|
196
|
+
clearTimers();
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
pi.registerCommand("autotalk:on", {
|
|
200
|
+
description: "Start AutoTalk timed editor sending",
|
|
201
|
+
handler: async (_args, ctx) => {
|
|
202
|
+
enable(ctx);
|
|
203
|
+
},
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
pi.registerCommand("autotalk:off", {
|
|
207
|
+
description: "Stop AutoTalk timed editor sending",
|
|
208
|
+
handler: async (_args, ctx) => {
|
|
209
|
+
disable(ctx);
|
|
210
|
+
},
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
pi.registerCommand("autotalk:mode", {
|
|
214
|
+
description: "Choose AutoTalk busy-agent delivery mode",
|
|
215
|
+
handler: async (_args, ctx) => {
|
|
216
|
+
await setMode(ctx);
|
|
217
|
+
},
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
pi.registerCommand("autotalk:settings", {
|
|
221
|
+
description: "Configure AutoTalk interval and delivery mode",
|
|
222
|
+
handler: async (_args, ctx) => {
|
|
223
|
+
await openSettings(ctx);
|
|
224
|
+
},
|
|
225
|
+
});
|
|
226
|
+
}
|
package/lib/autotalk.ts
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
4
|
+
|
|
5
|
+
export type DeliveryMode = "followUp" | "steer";
|
|
6
|
+
|
|
7
|
+
export interface AutoTalkSettings {
|
|
8
|
+
intervalSec: number;
|
|
9
|
+
deliveryMode: DeliveryMode;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const DEFAULT_INTERVAL_SEC = 10;
|
|
13
|
+
export const MIN_INTERVAL_SEC = 5;
|
|
14
|
+
export const MAX_INTERVAL_SEC = 120;
|
|
15
|
+
export const IDLE_BEFORE_SEND_MS = 2_000;
|
|
16
|
+
export const WATCH_EDITOR_MS = 250;
|
|
17
|
+
|
|
18
|
+
export const DEFAULT_SETTINGS: AutoTalkSettings = {
|
|
19
|
+
intervalSec: DEFAULT_INTERVAL_SEC,
|
|
20
|
+
deliveryMode: "followUp",
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export function getSettingsPath(): string {
|
|
24
|
+
return join(homedir(), ".pi", "agent", "extensions", "autotalk", "settings.json");
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function isDeliveryMode(value: unknown): value is DeliveryMode {
|
|
28
|
+
return value === "followUp" || value === "steer";
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function normalizeSettings(value: unknown): AutoTalkSettings {
|
|
32
|
+
if (!value || typeof value !== "object") return { ...DEFAULT_SETTINGS };
|
|
33
|
+
|
|
34
|
+
const candidate = value as { intervalSec?: unknown; deliveryMode?: unknown };
|
|
35
|
+
const intervalSec = normalizeInterval(candidate.intervalSec) ?? DEFAULT_SETTINGS.intervalSec;
|
|
36
|
+
const deliveryMode = isDeliveryMode(candidate.deliveryMode)
|
|
37
|
+
? candidate.deliveryMode
|
|
38
|
+
: DEFAULT_SETTINGS.deliveryMode;
|
|
39
|
+
|
|
40
|
+
return { intervalSec, deliveryMode };
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function normalizeInterval(value: unknown): number | undefined {
|
|
44
|
+
if (typeof value === "string" && value.trim() !== "") {
|
|
45
|
+
return normalizeInterval(Number(value));
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (typeof value !== "number" || !Number.isInteger(value)) return undefined;
|
|
49
|
+
if (value < MIN_INTERVAL_SEC || value > MAX_INTERVAL_SEC) return undefined;
|
|
50
|
+
return value;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export async function loadSettings(path = getSettingsPath()): Promise<AutoTalkSettings> {
|
|
54
|
+
try {
|
|
55
|
+
const text = await readFile(path, "utf8");
|
|
56
|
+
return normalizeSettings(JSON.parse(text));
|
|
57
|
+
} catch {
|
|
58
|
+
return { ...DEFAULT_SETTINGS };
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export async function saveSettings(
|
|
63
|
+
settings: AutoTalkSettings,
|
|
64
|
+
path = getSettingsPath(),
|
|
65
|
+
): Promise<void> {
|
|
66
|
+
await mkdir(dirname(path), { recursive: true });
|
|
67
|
+
await writeFile(path, `${JSON.stringify(settings, null, 2)}
|
|
68
|
+
`, "utf8");
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function formatThoughtMemo(text: string): string {
|
|
72
|
+
return `[AutoTalk]
|
|
73
|
+
これは自動送信されたユーザーの思考メモです。
|
|
74
|
+
アイデアを広げ、論点を整理し、次の問いを1つ出してください。
|
|
75
|
+
明示依頼でない限り、ファイル編集・コマンド実行・外部送信はしないでください。
|
|
76
|
+
|
|
77
|
+
--- 思考メモ ---
|
|
78
|
+
${text}`;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export function formatEmptyPrompt(): string {
|
|
82
|
+
return `[AutoTalk]
|
|
83
|
+
入力欄が空です。ここまでの流れから、次に考える問いを1つ出してください。`;
|
|
84
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "pi-autotalk",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "A Pi extension for timed AutoTalk brainstorming from the editor input.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"author": "eiei114",
|
|
8
|
+
"keywords": [
|
|
9
|
+
"pi-package",
|
|
10
|
+
"pi",
|
|
11
|
+
"pi-extension",
|
|
12
|
+
"autotalk",
|
|
13
|
+
"brainstorming",
|
|
14
|
+
"typescript"
|
|
15
|
+
],
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "git+https://github.com/eiei114/pi-autotalk.git"
|
|
19
|
+
},
|
|
20
|
+
"bugs": {
|
|
21
|
+
"url": "https://github.com/eiei114/pi-autotalk/issues"
|
|
22
|
+
},
|
|
23
|
+
"homepage": "https://github.com/eiei114/pi-autotalk#readme",
|
|
24
|
+
"files": [
|
|
25
|
+
"extensions/",
|
|
26
|
+
"lib/",
|
|
27
|
+
"docs/",
|
|
28
|
+
"README.md",
|
|
29
|
+
"LICENSE",
|
|
30
|
+
"CHANGELOG.md"
|
|
31
|
+
],
|
|
32
|
+
"scripts": {
|
|
33
|
+
"typecheck": "tsc --noEmit",
|
|
34
|
+
"test": "node --test tests/*.test.mjs",
|
|
35
|
+
"ci": "npm run typecheck && npm test && npm run pack:check",
|
|
36
|
+
"pack:check": "npm pack --dry-run"
|
|
37
|
+
},
|
|
38
|
+
"pi": {
|
|
39
|
+
"extensions": [
|
|
40
|
+
"./extensions"
|
|
41
|
+
]
|
|
42
|
+
},
|
|
43
|
+
"publishConfig": {
|
|
44
|
+
"access": "public"
|
|
45
|
+
},
|
|
46
|
+
"peerDependencies": {
|
|
47
|
+
"@earendil-works/pi-coding-agent": "*"
|
|
48
|
+
},
|
|
49
|
+
"devDependencies": {
|
|
50
|
+
"@earendil-works/pi-coding-agent": "latest",
|
|
51
|
+
"@types/node": "^22.0.0",
|
|
52
|
+
"typescript": "^6.0.3"
|
|
53
|
+
}
|
|
54
|
+
}
|