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 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
- If `VOLC_API_KEY` is missing, the extension does not silently fail. It shows an error notification explaining:
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
- Manual fallback:
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
- # Shortcut. Default: ctrl+shift+r
139
- VOICE_INPUT_SHORTCUT=ctrl+shift+r
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
- ## Volcengine links
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
- "API key settings: https://console.volcengine.com/speech/new/setting/apikeys?projectName=default",
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("Run /voice key in interactive pi, or set VOLC_API_KEY in the environment.", "error");
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
- ctx.ui.notify(`Voice input loaded: ${startupConfig.shortcut} toggles recording.`, "info");
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.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": "git+ssh://git@github.com/tr-nc/pi-voice-input.git"
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": [