pi-voice-input 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/AGENTS.md +94 -0
- package/README.md +6 -75
- package/extensions/voice-input.ts +34 -5
- package/package.json +5 -3
package/AGENTS.md
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# AGENTS.md
|
|
2
|
+
|
|
3
|
+
Development workflow for this repo.
|
|
4
|
+
|
|
5
|
+
## Project
|
|
6
|
+
|
|
7
|
+
- Package: `pi-voice-input`
|
|
8
|
+
- GitHub: `git@github.com:tr-nc/pi-voice-input.git`
|
|
9
|
+
- npm: `pi-voice-input`
|
|
10
|
+
- Main extension: `extensions/voice-input.ts`
|
|
11
|
+
- Current provider: VolcEngine WebSocket ASR only
|
|
12
|
+
- Provider architecture should remain extensible so more ASR providers can be added later.
|
|
13
|
+
|
|
14
|
+
## Secrets and local data
|
|
15
|
+
|
|
16
|
+
- Never commit API keys, `.env`, recordings, logs, caches, or `node_modules`.
|
|
17
|
+
- User credentials belong in `~/.pi/agent/voice-input.env`, usually written by `/voice key`.
|
|
18
|
+
- Do not print or copy real API keys into commits, docs, tests, or command output.
|
|
19
|
+
- The explicit VolcEngine API key URL that should be shown to users is:
|
|
20
|
+
`https://console.volcengine.com/speech/new/setting/apikeys?projectName=default`
|
|
21
|
+
|
|
22
|
+
## Before committing
|
|
23
|
+
|
|
24
|
+
Run from the repo root:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npm install --package-lock=false
|
|
28
|
+
npx tsc --noEmit --module NodeNext --moduleResolution NodeNext --target ES2022 --skipLibCheck --types node extensions/voice-input.ts
|
|
29
|
+
PI_OFFLINE=1 pi -e ./extensions/voice-input.ts --list-models
|
|
30
|
+
npm pack --dry-run
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Check that `npm pack --dry-run` includes only publishable files, normally:
|
|
34
|
+
|
|
35
|
+
```text
|
|
36
|
+
.env.example
|
|
37
|
+
AGENTS.md
|
|
38
|
+
README.md
|
|
39
|
+
extensions/voice-input.ts
|
|
40
|
+
package.json
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Clean local generated files before committing:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
rm -rf node_modules package-lock.json logs recordings
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Then check:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
git status --short
|
|
53
|
+
rg -n "VOLC_API_KEY=|[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}" \
|
|
54
|
+
--glob '!node_modules/**' --glob '!package-lock.json' . || true
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Use conventional commit messages, for example:
|
|
58
|
+
|
|
59
|
+
- `feat: add voice API key setup command`
|
|
60
|
+
- `fix: handle missing recorder cleanly`
|
|
61
|
+
- `docs: clarify npm installation`
|
|
62
|
+
- `chore: update package metadata`
|
|
63
|
+
|
|
64
|
+
## Release workflow
|
|
65
|
+
|
|
66
|
+
1. Bump `package.json` version. npm versions are immutable.
|
|
67
|
+
2. Validate with the commands above.
|
|
68
|
+
3. Commit with a conventional commit message.
|
|
69
|
+
4. Push to GitHub:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
git push origin main
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
5. Publish to npm:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
npm publish --access public
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
6. Update the local installed pi package and verify startup:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
pi update npm:pi-voice-input
|
|
85
|
+
PI_OFFLINE=1 pi --list-models
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
If testing a local checkout instead of the npm package, use:
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
pi -e ./extensions/voice-input.ts
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Do not leave local development wrappers in `~/.pi/agent/extensions/voice-input.ts` when validating the npm installation path.
|
package/README.md
CHANGED
|
@@ -43,18 +43,6 @@ Install the published package with pi:
|
|
|
43
43
|
pi install npm:pi-voice-input
|
|
44
44
|
```
|
|
45
45
|
|
|
46
|
-
To pin a specific version:
|
|
47
|
-
|
|
48
|
-
```bash
|
|
49
|
-
pi install npm:pi-voice-input@0.1.0
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
If pi is already running, reload extensions after installation:
|
|
53
|
-
|
|
54
|
-
```text
|
|
55
|
-
/reload
|
|
56
|
-
```
|
|
57
|
-
|
|
58
46
|
## Providers
|
|
59
47
|
|
|
60
48
|
The extension is structured around a provider boundary: recording, editor insertion, and command handling are generic; ASR transport/protocol logic is provider-specific.
|
|
@@ -78,76 +66,18 @@ In pi, run:
|
|
|
78
66
|
|
|
79
67
|
Paste your VolcEngine Speech API key into the prompt. The extension saves it for future sessions and keeps it out of your project files.
|
|
80
68
|
|
|
81
|
-
Then verify:
|
|
82
|
-
|
|
83
|
-
```text
|
|
84
|
-
/voice config
|
|
85
|
-
```
|
|
86
|
-
|
|
87
69
|
You can get/manage the key here:
|
|
88
70
|
|
|
89
71
|
https://console.volcengine.com/speech/new/setting/apikeys?projectName=default
|
|
90
72
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
- that the current provider API key is missing
|
|
94
|
-
- to run `/voice key`
|
|
95
|
-
- the VolcEngine API-key settings URL
|
|
96
|
-
- that `/voice config` can be used to verify detection
|
|
73
|
+
The key URL is also shown inside pi when the key is missing, when you run `/voice key`, and in `/voice help`:
|
|
97
74
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
```bash
|
|
101
|
-
mkdir -p ~/.pi/agent
|
|
102
|
-
cp .env.example ~/.pi/agent/voice-input.env
|
|
103
|
-
$EDITOR ~/.pi/agent/voice-input.env
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
## Configuration reference
|
|
107
|
-
|
|
108
|
-
Example:
|
|
109
|
-
|
|
110
|
-
```bash
|
|
111
|
-
# Required for the current provider. Usually set by /voice key.
|
|
112
|
-
VOLC_API_KEY=your_volcengine_speech_api_key
|
|
113
|
-
|
|
114
|
-
# Current provider: VolcEngine WebSocket ASR endpoint and resource
|
|
115
|
-
VOLC_WS_URL=wss://openspeech.bytedance.com/api/v3/sauc/bigmodel_nostream
|
|
116
|
-
VOLC_STREAM_RESOURCE_ID=volc.seedasr.sauc.duration
|
|
117
|
-
|
|
118
|
-
# Empty means auto-detect. Example: zh-CN.
|
|
119
|
-
ASR_LANGUAGE=
|
|
120
|
-
|
|
121
|
-
# Optional contextual prompt for ASR.
|
|
122
|
-
ASR_PROMPT=
|
|
123
|
-
|
|
124
|
-
# Faster for post-recording batch transcription. Use 200 for realtime-like packet size.
|
|
125
|
-
STREAM_SEGMENT_MS=5000
|
|
126
|
-
ASR_REQUEST_TIMEOUT_MS=90000
|
|
127
|
-
|
|
128
|
-
# Empty means use PipeWire's default source.
|
|
129
|
-
RECORDER_TARGET=
|
|
130
|
-
RECORDING_FINALIZE_DELAY=0.1
|
|
131
|
-
|
|
132
|
-
# Storage for recordings, logs, and state.
|
|
133
|
-
VOICE_INPUT_HOME=~/.pi/agent/voice-input
|
|
134
|
-
RECORDINGS_DIR=recordings
|
|
135
|
-
RECORDER_STATE=recording.json
|
|
136
|
-
RECORDER_LOG_DIR=logs
|
|
75
|
+
Then verify:
|
|
137
76
|
|
|
138
|
-
|
|
139
|
-
|
|
77
|
+
```text
|
|
78
|
+
/voice config
|
|
140
79
|
```
|
|
141
80
|
|
|
142
|
-
Config loading order, later values override earlier ones:
|
|
143
|
-
|
|
144
|
-
1. `~/.pi/agent/voice-input.env`
|
|
145
|
-
2. package-local `.env`
|
|
146
|
-
3. current-working-directory `.env`
|
|
147
|
-
4. shell environment variables
|
|
148
|
-
|
|
149
|
-
Do not commit real credentials. Prefer `/voice key`, or keep private local values in `.env` or `~/.pi/agent/voice-input.env`.
|
|
150
|
-
|
|
151
81
|
## Usage
|
|
152
82
|
|
|
153
83
|
Shortcut:
|
|
@@ -166,6 +96,7 @@ Slash commands:
|
|
|
166
96
|
/voice status # show recorder state
|
|
167
97
|
/voice config # show effective non-secret config and whether API key is detected
|
|
168
98
|
/voice key # prompt for and save the current provider API key
|
|
99
|
+
/voice help # show setup help, including the explicit VolcEngine API key URL
|
|
169
100
|
```
|
|
170
101
|
|
|
171
102
|
## Notes
|
|
@@ -202,7 +133,7 @@ After changing the extension while pi is open, run:
|
|
|
202
133
|
/reload
|
|
203
134
|
```
|
|
204
135
|
|
|
205
|
-
##
|
|
136
|
+
## Links
|
|
206
137
|
|
|
207
138
|
- API key settings: https://console.volcengine.com/speech/new/setting/apikeys?projectName=default
|
|
208
139
|
- ASR product page: https://www.volcengine.com/product/asr
|
|
@@ -22,6 +22,7 @@ import WebSocket from "ws";
|
|
|
22
22
|
const EXTENSION_DIR = path.dirname(fileURLToPath(import.meta.url));
|
|
23
23
|
const PACKAGE_ROOT = path.resolve(EXTENSION_DIR, "..");
|
|
24
24
|
const PRIVATE_CONFIG_PATH = path.join(homedir(), ".pi", "agent", "voice-input.env");
|
|
25
|
+
const VOLC_API_KEY_URL = "https://console.volcengine.com/speech/new/setting/apikeys?projectName=default";
|
|
25
26
|
const DEFAULT_SHORTCUT = Key.ctrlShift("r");
|
|
26
27
|
|
|
27
28
|
const MSG_TYPE_CLIENT_FULL_REQUEST = 0b0001;
|
|
@@ -458,7 +459,7 @@ function missingCredentialsMessage(): string {
|
|
|
458
459
|
return [
|
|
459
460
|
"Missing VOLC_API_KEY for the current VolcEngine ASR provider.",
|
|
460
461
|
"Run /voice key and paste your VolcEngine Speech API key.",
|
|
461
|
-
|
|
462
|
+
`Get/create the key here: ${VOLC_API_KEY_URL}`,
|
|
462
463
|
"Run /voice config to verify whether the key is detected.",
|
|
463
464
|
].join("\n");
|
|
464
465
|
}
|
|
@@ -717,14 +718,26 @@ async function toggleRecording(ctx: ExtensionContext) {
|
|
|
717
718
|
else await startRecording(ctx);
|
|
718
719
|
}
|
|
719
720
|
|
|
721
|
+
function setupHelp(config = getConfig()): string {
|
|
722
|
+
return [
|
|
723
|
+
"pi Voice Input setup:",
|
|
724
|
+
"- Current provider: VolcEngine WebSocket ASR",
|
|
725
|
+
`- API key: ${config.apiKey ? "set" : "missing"}`,
|
|
726
|
+
"- To save/update the key, run: /voice key",
|
|
727
|
+
`- Get/create a VolcEngine Speech API key here: ${VOLC_API_KEY_URL}`,
|
|
728
|
+
"- After saving the key, run: /voice config",
|
|
729
|
+
].join("\n");
|
|
730
|
+
}
|
|
731
|
+
|
|
720
732
|
async function configureApiKey(ctx: ExtensionContext, providedKey = "") {
|
|
721
733
|
let apiKey = providedKey.trim();
|
|
722
734
|
|
|
723
735
|
if (!apiKey) {
|
|
724
736
|
if (!ctx.hasUI) {
|
|
725
|
-
ctx.ui.notify(
|
|
737
|
+
ctx.ui.notify(`Run /voice key in interactive pi, or get a key from ${VOLC_API_KEY_URL} and set VOLC_API_KEY.`, "error");
|
|
726
738
|
return;
|
|
727
739
|
}
|
|
740
|
+
ctx.ui.notify(`Get/create a VolcEngine Speech API key here:\n${VOLC_API_KEY_URL}`, "info");
|
|
728
741
|
const current = getConfig().apiKey;
|
|
729
742
|
const placeholder = current ? "Paste a new VolcEngine API key (current key is already set)" : "Paste VOLC_API_KEY";
|
|
730
743
|
apiKey = (await ctx.ui.input("VolcEngine API key", placeholder))?.trim() ?? "";
|
|
@@ -752,6 +765,7 @@ function configSummary(config: VoiceConfig): string {
|
|
|
752
765
|
`- state: ${config.statePath}`,
|
|
753
766
|
`- shortcut: ${config.shortcut}`,
|
|
754
767
|
"Run /voice key to save/update the current provider API key.",
|
|
768
|
+
`VolcEngine API key URL: ${VOLC_API_KEY_URL}`,
|
|
755
769
|
"Config files checked: ~/.pi/agent/voice-input.env, package .env, current .env; shell env overrides them.",
|
|
756
770
|
].join("\n");
|
|
757
771
|
}
|
|
@@ -772,7 +786,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
772
786
|
});
|
|
773
787
|
|
|
774
788
|
pi.registerCommand("voice", {
|
|
775
|
-
description: "Voice input: start | stop | status | toggle | cancel | config | key",
|
|
789
|
+
description: "Voice input: start | stop | status | toggle | cancel | config | key | help",
|
|
776
790
|
handler: async (args, ctx) => {
|
|
777
791
|
const input = (args || "toggle").trim();
|
|
778
792
|
const action = (input.split(/\s+/, 1)[0] || "toggle").toLowerCase();
|
|
@@ -804,11 +818,15 @@ export default function (pi: ExtensionAPI) {
|
|
|
804
818
|
await configureApiKey(ctx, rest);
|
|
805
819
|
return;
|
|
806
820
|
}
|
|
821
|
+
if (["help", "doctor"].includes(action)) {
|
|
822
|
+
ctx.ui.notify(setupHelp(getConfig()), "info");
|
|
823
|
+
return;
|
|
824
|
+
}
|
|
807
825
|
if (action === "toggle" || action === "") {
|
|
808
826
|
await toggleRecording(ctx);
|
|
809
827
|
return;
|
|
810
828
|
}
|
|
811
|
-
ctx.ui.notify("Usage: /voice start | stop | status | toggle | cancel | config | key", "error");
|
|
829
|
+
ctx.ui.notify("Usage: /voice start | stop | status | toggle | cancel | config | key | help", "error");
|
|
812
830
|
} catch (error) {
|
|
813
831
|
ctx.ui.setStatus("voice-input", undefined);
|
|
814
832
|
ctx.ui.notify(`Voice command error: ${error instanceof Error ? error.message : String(error)}`, "error");
|
|
@@ -817,6 +835,17 @@ export default function (pi: ExtensionAPI) {
|
|
|
817
835
|
});
|
|
818
836
|
|
|
819
837
|
pi.on("session_start", (_event, ctx) => {
|
|
820
|
-
|
|
838
|
+
if (getConfig().apiKey) {
|
|
839
|
+
ctx.ui.notify(`Voice input loaded: ${startupConfig.shortcut} toggles recording.`, "info");
|
|
840
|
+
return;
|
|
841
|
+
}
|
|
842
|
+
ctx.ui.notify(
|
|
843
|
+
[
|
|
844
|
+
`Voice input loaded: ${startupConfig.shortcut} toggles recording.`,
|
|
845
|
+
"API key is missing. Run /voice key to set it up.",
|
|
846
|
+
`Get/create a VolcEngine Speech API key here: ${VOLC_API_KEY_URL}`,
|
|
847
|
+
].join("\n"),
|
|
848
|
+
"warning",
|
|
849
|
+
);
|
|
821
850
|
});
|
|
822
851
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-voice-input",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "provider-extensible voice input extension for pi",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [
|
|
@@ -12,9 +12,10 @@
|
|
|
12
12
|
"asr"
|
|
13
13
|
],
|
|
14
14
|
"license": "MIT",
|
|
15
|
+
"author": "tr-nc",
|
|
15
16
|
"repository": {
|
|
16
17
|
"type": "git",
|
|
17
|
-
"url": "
|
|
18
|
+
"url": "https://github.com/tr-nc/pi-voice-input.git"
|
|
18
19
|
},
|
|
19
20
|
"bugs": {
|
|
20
21
|
"url": "https://github.com/tr-nc/pi-voice-input/issues"
|
|
@@ -23,7 +24,8 @@
|
|
|
23
24
|
"files": [
|
|
24
25
|
"extensions",
|
|
25
26
|
".env.example",
|
|
26
|
-
"README.md"
|
|
27
|
+
"README.md",
|
|
28
|
+
"AGENTS.md"
|
|
27
29
|
],
|
|
28
30
|
"pi": {
|
|
29
31
|
"extensions": [
|