@kuralle-syrinx/cli 4.4.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/LICENSE +22 -0
- package/README.md +152 -0
- package/dist/index.js +1161 -0
- package/dist/index.js.map +7 -0
- package/package.json +53 -0
- package/src/__fixtures__/good-text-agent.mjs +21 -0
- package/src/__fixtures__/no-callable-export.mjs +7 -0
- package/src/__fixtures__/throwing-agent.mjs +8 -0
- package/src/agent-resolve.test.ts +50 -0
- package/src/agent-resolve.ts +80 -0
- package/src/cli.test.ts +154 -0
- package/src/cli.ts +225 -0
- package/src/doctor.test.ts +50 -0
- package/src/doctor.ts +101 -0
- package/src/exit-codes.ts +38 -0
- package/src/fixture.test.ts +100 -0
- package/src/fixture.ts +96 -0
- package/src/help.ts +70 -0
- package/src/index.ts +37 -0
- package/src/text-command.test.ts +32 -0
- package/src/text-command.ts +32 -0
- package/src/text-turn.test.ts +49 -0
- package/src/text-turn.ts +108 -0
- package/src/turn-command.test.ts +80 -0
- package/src/turn-command.ts +81 -0
- package/src/turn-runner.test.ts +111 -0
- package/src/turn-runner.ts +381 -0
- package/src/version.test.ts +69 -0
- package/src/version.ts +92 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Kuralle
|
|
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.
|
|
22
|
+
|
package/README.md
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
# @kuralle-syrinx/cli
|
|
2
|
+
|
|
3
|
+
The agent-facing CLI for a Syrinx voice agent. A coding agent cannot verify its
|
|
4
|
+
own work on a voice agent by ear — there is no deterministic, machine-readable
|
|
5
|
+
way to run a turn or a text exchange. The [Studio](../../apps/studio) is for
|
|
6
|
+
the human (ears, barge-in feel, warmth); this CLI is for a coding agent
|
|
7
|
+
(fixtures, text, exit codes).
|
|
8
|
+
|
|
9
|
+
**This is not a console.** No REPL, no chat loop, no microphone. If a check
|
|
10
|
+
needs ears, run it in the Studio instead — this CLI refuses rather than
|
|
11
|
+
approximating.
|
|
12
|
+
|
|
13
|
+
**This CLI brings no providers of its own.** It does not depend on Deepgram,
|
|
14
|
+
Cartesia, OpenAI, or any STT/TTS/reasoner SDK — a global `npm install -g
|
|
15
|
+
@kuralle-syrinx/cli` does not download a single provider package. Every
|
|
16
|
+
provider-touching command takes `--agent <module>#<export>`, pointing the CLI
|
|
17
|
+
at *your* code; your module brings its own providers.
|
|
18
|
+
|
|
19
|
+
## Install
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
npm install -g @kuralle-syrinx/cli
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Installs a `syrinx` binary — a single self-contained, built JavaScript file
|
|
26
|
+
(no `ts-node`/`tsx` required to run it).
|
|
27
|
+
|
|
28
|
+
## `--agent` (required for `turn` and `text`)
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
--agent <module>[#namedExport]
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
`<module>` is a path to your own code (resolved relative to cwd unless
|
|
35
|
+
absolute); the export must be a zero-arg factory returning a
|
|
36
|
+
`VoiceAgentSession` — or a `Promise` of one — the same contract
|
|
37
|
+
[`examples/02-hello-voice-headless/scripts/dev-server.ts`](../../examples/02-hello-voice-headless/scripts/dev-server.ts)'s
|
|
38
|
+
own `--agent` flag already uses (not a second convention). Omit `#export` for
|
|
39
|
+
a default export (or a `createSession` export, checked in that order).
|
|
40
|
+
|
|
41
|
+
```ts
|
|
42
|
+
// my-agent.ts
|
|
43
|
+
import { VoiceAgentSession } from "@kuralle-syrinx/core";
|
|
44
|
+
import { DeepgramSTTPlugin } from "@kuralle-syrinx/deepgram";
|
|
45
|
+
// ...your own providers...
|
|
46
|
+
|
|
47
|
+
export default function createSession() {
|
|
48
|
+
const session = new VoiceAgentSession({ plugins: { /* ... */ } });
|
|
49
|
+
session.registerPlugin("stt", new DeepgramSTTPlugin());
|
|
50
|
+
// ...
|
|
51
|
+
return session;
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Resolution failures are loud and specific, never a silent fallback:
|
|
56
|
+
- Module not found, or the named export doesn't exist / isn't callable →
|
|
57
|
+
`USAGE`, naming the callable exports that *were* found.
|
|
58
|
+
- The export resolves and is callable but **throws when invoked** → `CONFIG`
|
|
59
|
+
— most plausibly your module is missing something it needs (an env var, a
|
|
60
|
+
key file, ...).
|
|
61
|
+
|
|
62
|
+
## Commands
|
|
63
|
+
|
|
64
|
+
### `syrinx turn --in <fixture.wav|fixture.json> --agent <module>#<export> [options]`
|
|
65
|
+
|
|
66
|
+
Run one turn through the resolved agent and report the transcript, the reply,
|
|
67
|
+
and per-stage timings.
|
|
68
|
+
|
|
69
|
+
Given a `fixture.json` sidecar produced by the Studio's "Save as fixture"
|
|
70
|
+
(format `syrinx.fixture.v1`, paired with the WAV it captured), the command
|
|
71
|
+
honours the sidecar's recorded capture config and **refuses** — a `USAGE`
|
|
72
|
+
exit, not a silently-wrong replay — when it cannot honestly satisfy it (an
|
|
73
|
+
unrecognised fixture format, or audio that isn't mono 16 kHz). When the
|
|
74
|
+
sidecar carries an `expectedTranscript`, the replayed transcript is asserted
|
|
75
|
+
against it; a mismatch is an `ASSERTION` exit, not a passing run.
|
|
76
|
+
|
|
77
|
+
```
|
|
78
|
+
syrinx turn --in ./captured.json --agent ./my-agent.ts --json
|
|
79
|
+
syrinx turn --in ./hello.wav --agent ./my-agent.ts#createSession
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### `syrinx text "<message>" --agent <module>#<export>`
|
|
83
|
+
|
|
84
|
+
Send a typed turn (no STT, no microphone) to the resolved agent and report the
|
|
85
|
+
reply — pushes the same `user.text_received` packet a real typed turn would.
|
|
86
|
+
|
|
87
|
+
```
|
|
88
|
+
syrinx text "What's the cancellation policy?" --agent ./my-agent.ts --json
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### `syrinx doctor [--agent <module>#<export>]`
|
|
92
|
+
|
|
93
|
+
Reports the Node runtime and whether `@kuralle-syrinx/core` is installed in
|
|
94
|
+
the current project and which version. Also reports, informationally only,
|
|
95
|
+
which well-known provider keys (`DEEPGRAM_API_KEY`, `OPENAI_API_KEY`, ...) are
|
|
96
|
+
present in the environment (**never** their values) — this CLI does not
|
|
97
|
+
require any specific one; whatever `--agent` resolves to owns its own
|
|
98
|
+
requirements. Pass `--agent` to check whether a *specific* agent module
|
|
99
|
+
resolves, without invoking it. Always exits `SUCCESS` — this command
|
|
100
|
+
diagnoses, it does not assert.
|
|
101
|
+
|
|
102
|
+
```
|
|
103
|
+
syrinx doctor --json
|
|
104
|
+
syrinx doctor --agent ./my-agent.ts --json
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## `--json`
|
|
108
|
+
|
|
109
|
+
`--json` is a first-class output mode on every command, not a side flag: it
|
|
110
|
+
emits exactly one parseable JSON object on stdout, `{ ok, verb, ... }` on
|
|
111
|
+
success or `{ ok: false, verb, error: { code, message, ... } }` on failure.
|
|
112
|
+
Diagnostics — currently just the version-skew warning below — always go to
|
|
113
|
+
stderr, never stdout, so `--json` output stays parseable no matter what.
|
|
114
|
+
Without `--json`, commands print a short human-readable summary to stdout and
|
|
115
|
+
errors to stderr.
|
|
116
|
+
|
|
117
|
+
## Version skew
|
|
118
|
+
|
|
119
|
+
On start, the CLI resolves the invoking project's installed
|
|
120
|
+
`@kuralle-syrinx/core` from the nearest `node_modules` (not its own bundled
|
|
121
|
+
version). If the major version differs from the CLI's own major, it prints a
|
|
122
|
+
warning naming both versions to stderr and keeps going — it warns, it does not
|
|
123
|
+
refuse.
|
|
124
|
+
|
|
125
|
+
## Exit codes
|
|
126
|
+
|
|
127
|
+
| Code | Name | Meaning |
|
|
128
|
+
| --- | --- | --- |
|
|
129
|
+
| 0 | `SUCCESS` | the command completed and, where applicable, any assertion matched |
|
|
130
|
+
| 1 | `INTERNAL` | an unexpected error inside the CLI itself — treat as a bug |
|
|
131
|
+
| 2 | `USAGE` | bad invocation: unknown verb/flag, a missing required argument, a `--agent` that could not be resolved, or a fixture the CLI cannot honour |
|
|
132
|
+
| 3 | `CONFIG` | the resolved `--agent` module threw constructing a session — most plausibly its own missing configuration |
|
|
133
|
+
| 4 | `BACKEND` | the agent or backend failed while running the turn (provider/network error, timeout, pipeline error) |
|
|
134
|
+
| 5 | `ASSERTION` | a replayed fixture's transcript drifted from the expected transcript |
|
|
135
|
+
|
|
136
|
+
The same table is printed by `syrinx --help`.
|
|
137
|
+
|
|
138
|
+
## Reuse, not reimplementation
|
|
139
|
+
|
|
140
|
+
`packages/cli/src/turn-runner.ts` owns exactly one thing: feeding audio into
|
|
141
|
+
an already-built `VoiceAgentSession` and capturing the transcript/reply/
|
|
142
|
+
timings/artifacts (`driveTurn`) — it never constructs a provider. Two callers
|
|
143
|
+
share it:
|
|
144
|
+
- The CLI's own `turn` command, via the `--agent` seam above.
|
|
145
|
+
- `examples/02-hello-voice-headless/src/run-one-turn.ts`'s `runOneTurn`, which
|
|
146
|
+
keeps its own hardcoded Deepgram+OpenAI+Cartesia+Silero default kernel
|
|
147
|
+
(legitimate there — it's a demo harness, not a shipped package) and
|
|
148
|
+
delegates the actual turn-driving mechanics to `driveTurn` here, imported
|
|
149
|
+
as `@kuralle-syrinx/cli/turn-runner`.
|
|
150
|
+
|
|
151
|
+
There is exactly one implementation of "drive a turn"; only the (necessarily
|
|
152
|
+
different) provider wiring differs between the two callers.
|