@holdyourvoice/hyv 3.0.1 → 3.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Readme.md +11 -0
- package/dist/cli.js +17 -9
- package/dist/cli.test.js +1 -0
- package/dist/mcp.js +1 -1
- package/dist/mcp.test.js +1 -1
- package/package.json +1 -1
package/Readme.md
CHANGED
|
@@ -57,6 +57,17 @@ To contribute, clone this repository, run `npm install`, then run `npm test` and
|
|
|
57
57
|
|
|
58
58
|
Build the fully local Claude Desktop extension with `npm run pack:claude`, then install `dist/hold-your-voice.mcpb` from **Settings → Extensions → Advanced settings → Install Extension**. The extension accepts text and portable profile JSON in the current conversation only. It does not read or write files, make network requests, or retain writing. See the [Claude Desktop guide](docs/CLAUDE-DESKTOP.md).
|
|
59
59
|
|
|
60
|
+
### Use it in Claude Code
|
|
61
|
+
|
|
62
|
+
Hold Your Voice is also a free Claude Code plugin. It starts the same local MCP server through the public npm package; drafts, samples, and profiles stay on your machine.
|
|
63
|
+
|
|
64
|
+
```text
|
|
65
|
+
/plugin marketplace add shashank-sn/holdyourvoice
|
|
66
|
+
/plugin install hold-your-voice@hold-your-voice
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
It requires Node.js 20 or newer and npm. See the [Claude Code guide](docs/CLAUDE-CODE.md).
|
|
70
|
+
|
|
60
71
|
### Build a local VoiceDNA profile
|
|
61
72
|
|
|
62
73
|
```bash
|
package/dist/cli.js
CHANGED
|
@@ -4,7 +4,7 @@ import { rules, RULESET_VERSION } from './ai-editor.js';
|
|
|
4
4
|
import { analyze, rewritePrompt, verify } from './pipeline.js';
|
|
5
5
|
import { parseProfile } from './profile.js';
|
|
6
6
|
import { buildProfile } from './voice-dna.js';
|
|
7
|
-
const usage = 'Commands: profile, analyze, rewrite-prompt, verify, patterns';
|
|
7
|
+
const usage = 'Commands: profile, analyze, rewrite-prompt, verify, patterns, mcp';
|
|
8
8
|
function input(path) {
|
|
9
9
|
return path === '-' ? readFileSync(0, 'utf8') : readFileSync(path, 'utf8');
|
|
10
10
|
}
|
|
@@ -33,7 +33,7 @@ function profileArguments(args) {
|
|
|
33
33
|
throw new Error('Usage: hyv profile profile.json sample-a.md sample-b.md [sample-c.md] [--avoid=phrase]');
|
|
34
34
|
return { output, samples, avoid };
|
|
35
35
|
}
|
|
36
|
-
export function runCli(args) {
|
|
36
|
+
export async function runCli(args) {
|
|
37
37
|
const [command, ...rest] = args;
|
|
38
38
|
if (command === 'profile') {
|
|
39
39
|
const { output, samples, avoid } = profileArguments(rest);
|
|
@@ -66,12 +66,20 @@ export function runCli(args) {
|
|
|
66
66
|
json({ version: RULESET_VERSION, rules: rules.map(({ expression, ...rule }) => ({ ...rule, expression: expression.source })) });
|
|
67
67
|
return 0;
|
|
68
68
|
}
|
|
69
|
+
if (command === 'mcp') {
|
|
70
|
+
if (rest.length > 0)
|
|
71
|
+
throw new Error('Usage: hyv mcp');
|
|
72
|
+
await import('./mcp.js');
|
|
73
|
+
return 0;
|
|
74
|
+
}
|
|
69
75
|
throw new Error(`${usage}.`);
|
|
70
76
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
77
|
+
void (async () => {
|
|
78
|
+
try {
|
|
79
|
+
process.exitCode = await runCli(process.argv.slice(2));
|
|
80
|
+
}
|
|
81
|
+
catch (error) {
|
|
82
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
83
|
+
process.exitCode = 1;
|
|
84
|
+
}
|
|
85
|
+
})();
|
package/dist/cli.test.js
CHANGED
|
@@ -44,6 +44,7 @@ test('uses exit code 2 for a failed candidate gate and 1 for misuse', () => {
|
|
|
44
44
|
assert.equal(verification.status, 2);
|
|
45
45
|
assert.deepEqual(Object.keys(JSON.parse(verification.stdout)).sort(), ['candidate', 'original', 'passed', 'preservationScore', 'regressions', 'version']);
|
|
46
46
|
assert.equal(run('unknown-command').status, 1);
|
|
47
|
+
assert.equal(run('mcp', 'unexpected').status, 1);
|
|
47
48
|
}
|
|
48
49
|
finally {
|
|
49
50
|
rmSync(directory, { recursive: true, force: true });
|
package/dist/mcp.js
CHANGED
|
@@ -12,7 +12,7 @@ function json(value) {
|
|
|
12
12
|
function failure(error) {
|
|
13
13
|
return { content: [{ type: 'text', text: error instanceof Error ? error.message : String(error) }], isError: true };
|
|
14
14
|
}
|
|
15
|
-
const server = new McpServer({ name: 'hold-your-voice', version: '3.0.
|
|
15
|
+
const server = new McpServer({ name: 'hold-your-voice', version: '3.0.2' });
|
|
16
16
|
server.registerTool('hyv_build_profile', {
|
|
17
17
|
description: 'Build a portable VoiceDNA profile from at least two writing samples. The samples stay in memory and are not saved.',
|
|
18
18
|
inputSchema: { samples, avoid },
|
package/dist/mcp.test.js
CHANGED
|
@@ -3,7 +3,7 @@ import { spawn } from 'node:child_process';
|
|
|
3
3
|
import { once } from 'node:events';
|
|
4
4
|
import test from 'node:test';
|
|
5
5
|
test('serves the read-only Claude tools over stdio', async () => {
|
|
6
|
-
const server = spawn(process.execPath, [new URL('./
|
|
6
|
+
const server = spawn(process.execPath, [new URL('./cli.js', import.meta.url).pathname, 'mcp'], { stdio: ['pipe', 'pipe', 'pipe'] });
|
|
7
7
|
let stdout = '';
|
|
8
8
|
let stderr = '';
|
|
9
9
|
server.stdout.on('data', (chunk) => { stdout += chunk; });
|
package/package.json
CHANGED