@micsushi/agent-hotline 0.5.1
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 +167 -0
- package/docs/README.md +30 -0
- package/docs/integrations/antigravity.md +62 -0
- package/docs/integrations/claude-code.md +48 -0
- package/docs/integrations/codex.md +48 -0
- package/docs/integrations/spoken-output.md +36 -0
- package/package.json +62 -0
- package/packages/backend/README.md +40 -0
- package/packages/backend/bin/agent-hotline-hook.js +11 -0
- package/packages/backend/bin/agent-hotline.js +138 -0
- package/packages/backend/package.json +20 -0
- package/packages/backend/skills/agent-hotline-spoken/SKILL.md +45 -0
- package/packages/backend/src/audio-cache-store.js +246 -0
- package/packages/backend/src/hook-command.js +320 -0
- package/packages/backend/src/hook-input-parser.js +671 -0
- package/packages/backend/src/installer.js +402 -0
- package/packages/backend/src/run-command.js +40 -0
- package/packages/backend/src/server.js +879 -0
- package/packages/backend/src/settings-store.js +191 -0
- package/packages/backend/src/speakable-filter.js +251 -0
- package/packages/backend/src/speech-queue-store.js +324 -0
- package/packages/backend/src/spool-store.js +80 -0
package/README.md
ADDED
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
# Agent Hotline
|
|
2
|
+
|
|
3
|
+
Agent Hotline is a local Windows tray app that reads useful parts of Codex, Claude Code, and Antigravity replies aloud.
|
|
4
|
+
|
|
5
|
+
You keep using your coding tool like normal. Agent Hotline listens for finished responses through local hooks, skips code-heavy bits, and reads the useful prose through the desktop WebView. The full reply stays in the original chat.
|
|
6
|
+
|
|
7
|
+
## What It Does
|
|
8
|
+
|
|
9
|
+
- Reads finished coding-agent replies aloud.
|
|
10
|
+
- Skips code blocks, diffs, logs, JSON, tables, and big dumps.
|
|
11
|
+
- Lets you save replies or auto-play them when idle.
|
|
12
|
+
- Gives you read, pause, resume, stop, replay, mute, and unmute controls.
|
|
13
|
+
- Stores settings under `%APPDATA%\Agent Hotline\`.
|
|
14
|
+
- Does not need model API keys or paid speech APIs for read-aloud.
|
|
15
|
+
|
|
16
|
+
## Status
|
|
17
|
+
|
|
18
|
+
Good enough for local development use.
|
|
19
|
+
|
|
20
|
+
Still missing:
|
|
21
|
+
|
|
22
|
+
- A normal packaged installer.
|
|
23
|
+
- A bundled backend sidecar for production installs.
|
|
24
|
+
- Voice input owned by Agent Hotline.
|
|
25
|
+
|
|
26
|
+
## Requirements
|
|
27
|
+
|
|
28
|
+
- Windows 10 or 11.
|
|
29
|
+
- Node.js 22 or newer.
|
|
30
|
+
- For terminal install only: no repo clone is needed.
|
|
31
|
+
- For desktop app development: Rust plus the usual Tauri Windows prerequisites.
|
|
32
|
+
|
|
33
|
+
## Install
|
|
34
|
+
|
|
35
|
+
### Terminal install from npm
|
|
36
|
+
|
|
37
|
+
Use this on a normal machine that should not clone this repo:
|
|
38
|
+
|
|
39
|
+
```powershell
|
|
40
|
+
npx --yes @micsushi/agent-hotline install --harness all --skill all
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
That one command downloads the Agent Hotline npm package and installs both parts:
|
|
44
|
+
|
|
45
|
+
- the hook/tool command used by Codex, Claude Code, and Antigravity
|
|
46
|
+
- the spoken-output skill or managed instructions
|
|
47
|
+
|
|
48
|
+
Start the local backend:
|
|
49
|
+
|
|
50
|
+
```powershell
|
|
51
|
+
npx --yes @micsushi/agent-hotline run
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
For one repo only:
|
|
55
|
+
|
|
56
|
+
```powershell
|
|
57
|
+
npx --yes @micsushi/agent-hotline install --harness all --skill all --scope repo --repo C:\path\to\repo
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Optional: install once globally so you can use shorter commands:
|
|
61
|
+
|
|
62
|
+
```powershell
|
|
63
|
+
npm install -g @micsushi/agent-hotline
|
|
64
|
+
agent-hotline install --harness all --skill all
|
|
65
|
+
agent-hotline run
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Useful separate commands:
|
|
69
|
+
|
|
70
|
+
```powershell
|
|
71
|
+
npx --yes @micsushi/agent-hotline install-hooks --harness all
|
|
72
|
+
npx --yes @micsushi/agent-hotline install-skill --target all
|
|
73
|
+
npx --yes @micsushi/agent-hotline hook
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Local checkout install
|
|
77
|
+
|
|
78
|
+
Use this only when developing Agent Hotline from this repo:
|
|
79
|
+
|
|
80
|
+
```powershell
|
|
81
|
+
npm install
|
|
82
|
+
npm run install-hotline -- --harness all --skill all
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
`npm install` also grabs the local TTS assets used by the desktop app. To repair those assets:
|
|
86
|
+
|
|
87
|
+
```powershell
|
|
88
|
+
npm run install:tts
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## What Gets Installed
|
|
92
|
+
|
|
93
|
+
The npm package includes the CLI/backend hook tool and the spoken skill/instructions. Users do not download those separately.
|
|
94
|
+
|
|
95
|
+
The polished desktop installer is not finished yet. Until then, the desktop control panel is run from a local checkout.
|
|
96
|
+
|
|
97
|
+
## Run Locally
|
|
98
|
+
|
|
99
|
+
From a global install, start the backend:
|
|
100
|
+
|
|
101
|
+
```powershell
|
|
102
|
+
ah run
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
From `npx`, start the backend:
|
|
106
|
+
|
|
107
|
+
```powershell
|
|
108
|
+
npx --yes @micsushi/agent-hotline run
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
From a local checkout, run it in the foreground while developing:
|
|
112
|
+
|
|
113
|
+
```powershell
|
|
114
|
+
npm run dev:backend
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Start the desktop app:
|
|
118
|
+
|
|
119
|
+
```powershell
|
|
120
|
+
npm run dev:desktop
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Backend URL:
|
|
124
|
+
|
|
125
|
+
```text
|
|
126
|
+
http://127.0.0.1:4777
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## Smoke Test
|
|
130
|
+
|
|
131
|
+
With the backend running, test the npm-installed hook:
|
|
132
|
+
|
|
133
|
+
```powershell
|
|
134
|
+
'{"source":"codex","response":{"text":"Spoken:`nAgent Hotline is ready to read this aloud.`n`nDisplayed:`nSmoke test complete."}}' | npx --yes @micsushi/agent-hotline hook
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
From a local checkout, test the local hook:
|
|
138
|
+
|
|
139
|
+
```powershell
|
|
140
|
+
'{"source":"codex","response":{"text":"Spoken:`nAgent Hotline is ready to read this aloud.`n`nDisplayed:`nSmoke test complete."}}' | node packages/backend/bin/agent-hotline.js hook
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
The sentence should show up in the Agent Hotline queue. If the backend is not running, the hook exits quietly.
|
|
144
|
+
|
|
145
|
+
## Checks
|
|
146
|
+
|
|
147
|
+
```powershell
|
|
148
|
+
npm test
|
|
149
|
+
npm run lint
|
|
150
|
+
npm run format:check
|
|
151
|
+
npm run check
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## Docs
|
|
155
|
+
|
|
156
|
+
- [Docs index](docs/README.md)
|
|
157
|
+
- [Codex setup](docs/integrations/codex.md)
|
|
158
|
+
- [Claude Code setup](docs/integrations/claude-code.md)
|
|
159
|
+
- [Antigravity setup](docs/integrations/antigravity.md)
|
|
160
|
+
|
|
161
|
+
## Repo Layout
|
|
162
|
+
|
|
163
|
+
```text
|
|
164
|
+
docs/ Human setup notes
|
|
165
|
+
packages/backend/ Local API, queue, settings, hook command
|
|
166
|
+
packages/desktop/ Tauri tray app and control panel
|
|
167
|
+
```
|
package/docs/README.md
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Agent Hotline Docs
|
|
2
|
+
|
|
3
|
+
Short setup notes for people using or hacking on Agent Hotline.
|
|
4
|
+
|
|
5
|
+
## Setup
|
|
6
|
+
|
|
7
|
+
- [Codex](integrations/codex.md)
|
|
8
|
+
- [Claude Code](integrations/claude-code.md)
|
|
9
|
+
- [Antigravity](integrations/antigravity.md)
|
|
10
|
+
- [Spoken output](integrations/spoken-output.md)
|
|
11
|
+
|
|
12
|
+
## Common Commands
|
|
13
|
+
|
|
14
|
+
```powershell
|
|
15
|
+
npm run install:tts
|
|
16
|
+
npm run install-hotline -- --harness all --skill all
|
|
17
|
+
npm run dev:backend
|
|
18
|
+
npm run dev:desktop
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
From npm:
|
|
22
|
+
|
|
23
|
+
```powershell
|
|
24
|
+
npx --yes @micsushi/agent-hotline install --harness all --skill all
|
|
25
|
+
npx --yes @micsushi/agent-hotline hook
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Notes
|
|
29
|
+
|
|
30
|
+
Read-aloud playback is local. Agent Hotline talks to its local backend and uses browser/WebView text-to-speech.
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# Antigravity Setup
|
|
2
|
+
|
|
3
|
+
Agent Hotline can read Antigravity replies aloud through its global hook setup. It only talks to the local Agent Hotline backend.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
Start Agent Hotline first:
|
|
8
|
+
|
|
9
|
+
```powershell
|
|
10
|
+
npm install
|
|
11
|
+
npm run dev:backend
|
|
12
|
+
npm run dev:desktop
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Install the Antigravity hook and spoken skill:
|
|
16
|
+
|
|
17
|
+
```powershell
|
|
18
|
+
npm run install-hotline -- --harness antigravity --skill antigravity
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
For a different backend URL, set `AGENT_HOTLINE_URL` before starting Antigravity.
|
|
22
|
+
|
|
23
|
+
## Use It
|
|
24
|
+
|
|
25
|
+
In Antigravity, say:
|
|
26
|
+
|
|
27
|
+
```text
|
|
28
|
+
hotline on
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
To stop adding read-aloud sections:
|
|
32
|
+
|
|
33
|
+
```text
|
|
34
|
+
hotline off
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Test
|
|
38
|
+
|
|
39
|
+
```powershell
|
|
40
|
+
@{
|
|
41
|
+
source = "antigravity"
|
|
42
|
+
hook_event_name = "Stop"
|
|
43
|
+
assistant_response = @{
|
|
44
|
+
text = "Spoken:`nAgent Hotline is ready to read Antigravity aloud.`n`nDisplayed:`nSmoke test complete."
|
|
45
|
+
}
|
|
46
|
+
} | ConvertTo-Json -Depth 8 | node packages/backend/bin/agent-hotline.js hook
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
If Agent Hotline is running, the sentence lands in the queue.
|
|
50
|
+
|
|
51
|
+
## Turn It Off
|
|
52
|
+
|
|
53
|
+
- Remove the `Stop` hook from `%USERPROFILE%\.gemini\config\hooks.json`.
|
|
54
|
+
- Or say `hotline off` in the session.
|
|
55
|
+
- Or turn off Antigravity playback in Agent Hotline settings.
|
|
56
|
+
|
|
57
|
+
## Troubleshooting
|
|
58
|
+
|
|
59
|
+
- No audio: make sure the backend and desktop app are running.
|
|
60
|
+
- Nothing queued: say `hotline on` and try again.
|
|
61
|
+
- Different port: set `AGENT_HOTLINE_URL`.
|
|
62
|
+
- Hook diagnostics: set `AGENT_HOTLINE_HOOK_DEBUG=1`.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Claude Code Setup
|
|
2
|
+
|
|
3
|
+
Agent Hotline can read Claude Code replies aloud through a `Stop` hook. It only talks to the local Agent Hotline backend.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
Start Agent Hotline first:
|
|
8
|
+
|
|
9
|
+
```powershell
|
|
10
|
+
npm install
|
|
11
|
+
npm run dev:backend
|
|
12
|
+
npm run dev:desktop
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Then install the Claude Code hook and spoken-output instructions:
|
|
16
|
+
|
|
17
|
+
```powershell
|
|
18
|
+
npx --yes @micsushi/agent-hotline install --harness claude-code --skill claude-code --scope global
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
From a local checkout:
|
|
22
|
+
|
|
23
|
+
```powershell
|
|
24
|
+
npm run install-hotline -- --harness claude-code --skill claude-code --scope global
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
For a different backend URL, set `AGENT_HOTLINE_URL` before starting Claude Code.
|
|
28
|
+
|
|
29
|
+
## Test
|
|
30
|
+
|
|
31
|
+
```powershell
|
|
32
|
+
'{"source":"claude","assistant_response":{"text":"Spoken:`nAgent Hotline is ready to read Claude Code aloud.`n`nDisplayed:`nSmoke test complete."}}' | node packages/backend/bin/agent-hotline.js hook
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
If Agent Hotline is running, the sentence lands in the queue. If not, the hook exits quietly.
|
|
36
|
+
|
|
37
|
+
## Turn It Off
|
|
38
|
+
|
|
39
|
+
- Repo setup: remove the hook from `.claude/settings.local.json`.
|
|
40
|
+
- Global setup: remove it from `%USERPROFILE%\.claude\settings.json`.
|
|
41
|
+
- Temporary: turn off Claude playback in Agent Hotline settings.
|
|
42
|
+
|
|
43
|
+
## Troubleshooting
|
|
44
|
+
|
|
45
|
+
- No audio: make sure the backend and desktop app are running.
|
|
46
|
+
- Nothing queued: the reply may have been filtered out, or Claude playback may be off.
|
|
47
|
+
- Different port: set `AGENT_HOTLINE_URL`.
|
|
48
|
+
- Hook diagnostics: set `AGENT_HOTLINE_HOOK_DEBUG=1` before starting Claude Code.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Codex Setup
|
|
2
|
+
|
|
3
|
+
Agent Hotline can read Codex replies aloud through a Codex `Stop` hook. It only talks to the local Agent Hotline backend.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
Start Agent Hotline first:
|
|
8
|
+
|
|
9
|
+
```powershell
|
|
10
|
+
npm install
|
|
11
|
+
npm run dev:backend
|
|
12
|
+
npm run dev:desktop
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Then install the Codex hook and spoken-output instructions:
|
|
16
|
+
|
|
17
|
+
```powershell
|
|
18
|
+
npx --yes @micsushi/agent-hotline install --harness codex --skill codex --scope global
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
From a local checkout:
|
|
22
|
+
|
|
23
|
+
```powershell
|
|
24
|
+
npm run install-hotline -- --harness codex --skill codex --scope global
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
For a different backend URL, set `AGENT_HOTLINE_URL` before starting Codex.
|
|
28
|
+
|
|
29
|
+
## Test
|
|
30
|
+
|
|
31
|
+
```powershell
|
|
32
|
+
'{"source":"codex","response":{"text":"Spoken:`nAgent Hotline is ready to read Codex aloud.`n`nDisplayed:`nSmoke test complete."}}' | node packages/backend/bin/agent-hotline.js hook
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
If Agent Hotline is running, the sentence lands in the queue. If not, the hook exits quietly.
|
|
36
|
+
|
|
37
|
+
## Turn It Off
|
|
38
|
+
|
|
39
|
+
- Repo setup: remove the hook from `<repo>\.codex\hooks.json`.
|
|
40
|
+
- Global setup: remove it from `%USERPROFILE%\.codex\hooks.json`.
|
|
41
|
+
- Temporary: turn off Codex playback in Agent Hotline settings.
|
|
42
|
+
|
|
43
|
+
## Troubleshooting
|
|
44
|
+
|
|
45
|
+
- No audio: make sure the backend and desktop app are running.
|
|
46
|
+
- Nothing queued: the reply may have been filtered out, or Codex playback may be off.
|
|
47
|
+
- Different port: set `AGENT_HOTLINE_URL`.
|
|
48
|
+
- Hook diagnostics: set `AGENT_HOTLINE_HOOK_DEBUG=1` before starting Codex.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Spoken Output
|
|
2
|
+
|
|
3
|
+
Agent Hotline works best when a reply has a short `Spoken:` section. It reads that part and ignores the rest.
|
|
4
|
+
|
|
5
|
+
Install the formatting instructions:
|
|
6
|
+
|
|
7
|
+
```powershell
|
|
8
|
+
npm run install-skill -- --target all
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
From npm:
|
|
12
|
+
|
|
13
|
+
```powershell
|
|
14
|
+
agent-hotline install-skill --target all
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Contract
|
|
18
|
+
|
|
19
|
+
```text
|
|
20
|
+
Spoken:
|
|
21
|
+
A short, conversational summary meant to be heard.
|
|
22
|
+
|
|
23
|
+
==========
|
|
24
|
+
|
|
25
|
+
Displayed:
|
|
26
|
+
The full normal answer with code, paths, commands, and details.
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Keep `Spoken:` short and plain. Put everything technical in `Displayed:`.
|
|
30
|
+
|
|
31
|
+
## Verify
|
|
32
|
+
|
|
33
|
+
1. Start Agent Hotline.
|
|
34
|
+
2. Install the hook and spoken-output instructions.
|
|
35
|
+
3. Ask for a normal reply.
|
|
36
|
+
4. Confirm Agent Hotline reads only the `Spoken:` text.
|
package/package.json
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@micsushi/agent-hotline",
|
|
3
|
+
"version": "0.5.1",
|
|
4
|
+
"description": "Local read-aloud hooks and tray app for AI coding agents.",
|
|
5
|
+
"bin": {
|
|
6
|
+
"ah": "packages/backend/bin/agent-hotline.js",
|
|
7
|
+
"agent-hotline": "packages/backend/bin/agent-hotline.js",
|
|
8
|
+
"agent-hotline-hook": "packages/backend/bin/agent-hotline-hook.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"README.md",
|
|
12
|
+
"docs/",
|
|
13
|
+
"packages/backend/bin/",
|
|
14
|
+
"packages/backend/src/",
|
|
15
|
+
"packages/backend/skills/",
|
|
16
|
+
"packages/backend/package.json"
|
|
17
|
+
],
|
|
18
|
+
"publishConfig": {
|
|
19
|
+
"access": "public"
|
|
20
|
+
},
|
|
21
|
+
"engines": {
|
|
22
|
+
"node": ">=18"
|
|
23
|
+
},
|
|
24
|
+
"workspaces": [
|
|
25
|
+
"packages/*"
|
|
26
|
+
],
|
|
27
|
+
"scripts": {
|
|
28
|
+
"start": "npm --prefix packages/backend start",
|
|
29
|
+
"dev:backend": "npm --prefix packages/backend start",
|
|
30
|
+
"dev:desktop": "npm --workspace @agent-hotline/desktop run dev",
|
|
31
|
+
"install:tts": "npm --workspace @agent-hotline/desktop run install:tts",
|
|
32
|
+
"install-hook": "node scripts/install-hook.js",
|
|
33
|
+
"install-skill": "node scripts/install-skill.js",
|
|
34
|
+
"install-hotline": "node packages/backend/bin/agent-hotline.js install",
|
|
35
|
+
"test": "npm --prefix packages/backend test && npm --workspace @agent-hotline/desktop run test",
|
|
36
|
+
"lint": "eslint . && npm run rust:clippy",
|
|
37
|
+
"lint:fix": "eslint . --fix",
|
|
38
|
+
"fix": "prettier . --write && npm run lint:fix && npm run rust:fmt",
|
|
39
|
+
"format": "prettier . --write && npm run rust:fmt",
|
|
40
|
+
"format:check": "prettier . --check && npm run rust:fmt:check",
|
|
41
|
+
"verify:eol": "node scripts/verify-ci-eol.js",
|
|
42
|
+
"rust:fmt": "cargo fmt --manifest-path packages/desktop/src-tauri/Cargo.toml",
|
|
43
|
+
"rust:fmt:check": "cargo fmt --manifest-path packages/desktop/src-tauri/Cargo.toml --check",
|
|
44
|
+
"rust:clippy": "cargo clippy --manifest-path packages/desktop/src-tauri/Cargo.toml --all-targets -- -D warnings",
|
|
45
|
+
"check": "npm test && npm run format:check && npm run lint && npm --prefix packages/backend run check && npm --workspace @agent-hotline/desktop run check",
|
|
46
|
+
"ci": "npm ci && npm run check"
|
|
47
|
+
},
|
|
48
|
+
"devDependencies": {
|
|
49
|
+
"@eslint/js": "^10.0.1",
|
|
50
|
+
"eslint": "^10.5.0",
|
|
51
|
+
"globals": "^17.6.0",
|
|
52
|
+
"prettier": "^3.8.4"
|
|
53
|
+
},
|
|
54
|
+
"repository": {
|
|
55
|
+
"type": "git",
|
|
56
|
+
"url": "git+https://github.com/Micsushi/agent-hotline.git"
|
|
57
|
+
},
|
|
58
|
+
"homepage": "https://github.com/Micsushi/agent-hotline#readme",
|
|
59
|
+
"bugs": {
|
|
60
|
+
"url": "https://github.com/Micsushi/agent-hotline/issues"
|
|
61
|
+
}
|
|
62
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Agent Hotline Backend
|
|
2
|
+
|
|
3
|
+
Local HTTP backend for Agent Hotline.
|
|
4
|
+
|
|
5
|
+
This package owns hook parsing, text filtering, the speech queue, settings, local API routes, and the `agent-hotline hook` command.
|
|
6
|
+
|
|
7
|
+
## Run
|
|
8
|
+
|
|
9
|
+
Background mode:
|
|
10
|
+
|
|
11
|
+
```powershell
|
|
12
|
+
ah run
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Dev mode:
|
|
16
|
+
|
|
17
|
+
```powershell
|
|
18
|
+
npm run dev:backend
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Default URL:
|
|
22
|
+
|
|
23
|
+
```text
|
|
24
|
+
http://127.0.0.1:4777
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Use `AGENT_HOTLINE_PORT` to change the port.
|
|
28
|
+
|
|
29
|
+
Runtime data lives in:
|
|
30
|
+
|
|
31
|
+
```text
|
|
32
|
+
%APPDATA%\Agent Hotline\
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Checks
|
|
36
|
+
|
|
37
|
+
```powershell
|
|
38
|
+
npm --prefix packages/backend test
|
|
39
|
+
npm --prefix packages/backend run check
|
|
40
|
+
```
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const { main: hookMain } = require("../src/hook-command");
|
|
4
|
+
const { installHooks, installSkills, npxHookCommand, parseArgs } = require("../src/installer");
|
|
5
|
+
const { launchBackend } = require("../src/run-command");
|
|
6
|
+
|
|
7
|
+
function printHelp() {
|
|
8
|
+
console.log(`Agent Hotline
|
|
9
|
+
|
|
10
|
+
Usage:
|
|
11
|
+
agent-hotline run
|
|
12
|
+
agent-hotline hook
|
|
13
|
+
agent-hotline install --harness codex --skill codex
|
|
14
|
+
agent-hotline install-hooks --harness all
|
|
15
|
+
agent-hotline install-skill --target all
|
|
16
|
+
agent-hotline install --harness all --skill all
|
|
17
|
+
|
|
18
|
+
Options:
|
|
19
|
+
--harness antigravity|claude-code|codex|all
|
|
20
|
+
--target antigravity|claude-code|codex|all
|
|
21
|
+
--skill antigravity|claude-code|codex|all
|
|
22
|
+
--scope global|repo
|
|
23
|
+
--repo <path>
|
|
24
|
+
--home <path>
|
|
25
|
+
--hook-command <command>
|
|
26
|
+
--port <port> Backend port for "run" (default: 4777)
|
|
27
|
+
--use-npx-hook Write hooks that call "npx --yes @micsushi/agent-hotline hook"
|
|
28
|
+
`);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function printResults(title, results) {
|
|
32
|
+
console.log(title);
|
|
33
|
+
for (const result of results) {
|
|
34
|
+
console.log(
|
|
35
|
+
` ${result.target || result.harness} (${result.scope}): ${result.path || result.configPath}`
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function isNpmExec() {
|
|
41
|
+
return (
|
|
42
|
+
process.env.npm_command === "exec" ||
|
|
43
|
+
/\bnpm exec\b/.test(process.env.npm_config_user_agent || "")
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function hookCommandFromArgs(args) {
|
|
48
|
+
if (args["hook-command"]) return args["hook-command"];
|
|
49
|
+
if (args["use-npx-hook"] || isNpmExec()) return npxHookCommand();
|
|
50
|
+
return undefined;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
async function main(argv = process.argv.slice(2), options = {}) {
|
|
54
|
+
const [command, subcommand, ...rest] = argv;
|
|
55
|
+
|
|
56
|
+
if (!command || command === "--help" || command === "-h") {
|
|
57
|
+
printHelp();
|
|
58
|
+
return 0;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (command === "hook") {
|
|
62
|
+
return hookMain();
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (command === "run" || command === "start") {
|
|
66
|
+
const args = parseArgs([subcommand, ...rest].filter(Boolean));
|
|
67
|
+
const launcher = options.launchBackend || launchBackend;
|
|
68
|
+
const result = launcher({ port: args.port });
|
|
69
|
+
console.log(`Agent Hotline backend started in the background on ${result.url}.`);
|
|
70
|
+
if (result.pid) {
|
|
71
|
+
console.log(`Process id: ${result.pid}`);
|
|
72
|
+
}
|
|
73
|
+
console.log("You can close this terminal; the backend will keep running.");
|
|
74
|
+
return 0;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (command === "install-hooks") {
|
|
78
|
+
const args = parseArgs([subcommand, ...rest].filter(Boolean));
|
|
79
|
+
const results = installHooks({
|
|
80
|
+
harness: args.harness || "all",
|
|
81
|
+
scope: args.scope || "global",
|
|
82
|
+
repo: args.repo,
|
|
83
|
+
home: args.home,
|
|
84
|
+
hookCommand: hookCommandFromArgs(args)
|
|
85
|
+
});
|
|
86
|
+
printResults("Installed Agent Hotline hooks:", results);
|
|
87
|
+
return 0;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (command === "install-skill") {
|
|
91
|
+
const args = parseArgs([subcommand, ...rest].filter(Boolean));
|
|
92
|
+
const results = installSkills({
|
|
93
|
+
target: args.target || args.harness || "all",
|
|
94
|
+
scope: args.scope || "global",
|
|
95
|
+
repo: args.repo,
|
|
96
|
+
home: args.home
|
|
97
|
+
});
|
|
98
|
+
printResults("Installed Agent Hotline spoken skill/instructions:", results);
|
|
99
|
+
return 0;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (command === "install") {
|
|
103
|
+
const args = parseArgs([subcommand, ...rest].filter(Boolean));
|
|
104
|
+
const hookResults = installHooks({
|
|
105
|
+
harness: args.harness || "all",
|
|
106
|
+
scope: args.scope || "global",
|
|
107
|
+
repo: args.repo,
|
|
108
|
+
home: args.home,
|
|
109
|
+
hookCommand: hookCommandFromArgs(args)
|
|
110
|
+
});
|
|
111
|
+
const skillResults = installSkills({
|
|
112
|
+
target: args.skill || args.target || args.harness || "all",
|
|
113
|
+
scope: args.scope || "global",
|
|
114
|
+
repo: args.repo,
|
|
115
|
+
home: args.home
|
|
116
|
+
});
|
|
117
|
+
printResults("Installed Agent Hotline hooks:", hookResults);
|
|
118
|
+
printResults("Installed Agent Hotline spoken skill/instructions:", skillResults);
|
|
119
|
+
return 0;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
console.error(`Unknown command "${command}".`);
|
|
123
|
+
printHelp();
|
|
124
|
+
return 1;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (require.main === module) {
|
|
128
|
+
main()
|
|
129
|
+
.then((code) => {
|
|
130
|
+
process.exitCode = code;
|
|
131
|
+
})
|
|
132
|
+
.catch((error) => {
|
|
133
|
+
console.error(error.message);
|
|
134
|
+
process.exitCode = 1;
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
module.exports = { main };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@agent-hotline/backend",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"description": "Local web backend for Agent Hotline.",
|
|
6
|
+
"type": "commonjs",
|
|
7
|
+
"bin": {
|
|
8
|
+
"ah": "bin/agent-hotline.js",
|
|
9
|
+
"agent-hotline": "bin/agent-hotline.js",
|
|
10
|
+
"agent-hotline-hook": "bin/agent-hotline-hook.js"
|
|
11
|
+
},
|
|
12
|
+
"scripts": {
|
|
13
|
+
"start": "node src/server.js",
|
|
14
|
+
"test": "node --test test/*.test.js",
|
|
15
|
+
"check": "node --check src/server.js && node --check src/settings-store.js && node --check src/speech-queue-store.js && node --check src/audio-cache-store.js && node --check src/installer.js && node --check src/hook-input-parser.js && node --check src/hook-command.js && node --check src/run-command.js && node --check src/speakable-filter.js && node --check bin/agent-hotline.js && node --check bin/agent-hotline-hook.js && node --check test/settings-store.test.js && node --check test/speech-queue-store.test.js && node --check test/audio-cache-store.test.js && node --check test/audio-endpoints.test.js && node --check test/installer.test.js && node --check test/run-command.test.js && node --check test/speakable-filter.test.js && node --check test/hook-input-parser.test.js && node --check test/hook-command.test.js && node --check test/server-endpoints.test.js"
|
|
16
|
+
},
|
|
17
|
+
"engines": {
|
|
18
|
+
"node": ">=18"
|
|
19
|
+
}
|
|
20
|
+
}
|