@lucas_zaia/agent-voice 1.1.1 β 1.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/README.md +6 -5
- package/package.json +1 -1
- package/src/adapters/codex.js +35 -5
- package/src/cli/notify.js +1 -1
package/README.md
CHANGED
|
@@ -14,7 +14,7 @@ long task, or stops to wait for your permission, a speaker says so out loud:
|
|
|
14
14
|
> π *"Codex precisa de vocΓͺ na sessΓ£o azul, do projeto api, para usar o Bash."*
|
|
15
15
|
|
|
16
16
|
It works on macOS, Windows and Linux. It can speak through an Amazon Echo (via
|
|
17
|
-
Home Assistant), your computer's own voice, or any command you choose. It has
|
|
17
|
+
[Home Assistant](https://www.home-assistant.io/)), your computer's own voice, or any command you choose. It has
|
|
18
18
|
no dependencies and needs only Node.js.
|
|
19
19
|
|
|
20
20
|
---
|
|
@@ -64,7 +64,7 @@ Agents
|
|
|
64
64
|
claude-code connected
|
|
65
65
|
codex not installed
|
|
66
66
|
Outputs (* = enabled)
|
|
67
|
-
* echo alexa notify.echo_dot_announce @ http://
|
|
67
|
+
* echo alexa notify.echo_dot_announce @ http://homeassistant.local:8123
|
|
68
68
|
Settings
|
|
69
69
|
minSeconds=30
|
|
70
70
|
cooldownSeconds=120
|
|
@@ -134,12 +134,13 @@ agent-voice output remove <name>
|
|
|
134
134
|
|
|
135
135
|
You need:
|
|
136
136
|
|
|
137
|
-
1. **Home Assistant**, reachable
|
|
137
|
+
1. **[Home Assistant](https://www.home-assistant.io/installation/)**, reachable over the network from the
|
|
138
|
+
machine where your agent runs (by default `http://homeassistant.local:8123`).
|
|
138
139
|
2. The **[Alexa Media Player](https://github.com/alandtse/alexa_media_player)**
|
|
139
140
|
integration, which creates `notify.<device>_speak` and
|
|
140
141
|
`notify.<device>_announce` entities for each Echo.
|
|
141
|
-
3. A **long-lived access token
|
|
142
|
-
*Long-lived access tokens* β *Create token*.
|
|
142
|
+
3. A **[long-lived access token](https://www.home-assistant.io/docs/authentication/#your-account-profile)**:
|
|
143
|
+
Home Assistant β your profile β *Security* β *Long-lived access tokens* β *Create token*.
|
|
143
144
|
|
|
144
145
|
```bash
|
|
145
146
|
agent-voice output add alexa
|
package/package.json
CHANGED
package/src/adapters/codex.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Translates Codex CLI hook payloads into canonical events. Codex hooks share
|
|
2
|
-
// Claude Code's shape; the differences are the event names,
|
|
3
|
-
//
|
|
4
|
-
import { existsSync } from 'node:fs';
|
|
2
|
+
// Claude Code's shape; the differences are the event names, session names living
|
|
3
|
+
// in Codex's session index, and Stop wanting JSON back.
|
|
4
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
5
5
|
import { homedir } from 'node:os';
|
|
6
6
|
import { join, dirname } from 'node:path';
|
|
7
7
|
import { str, projectOf } from './common.js';
|
|
@@ -22,6 +22,8 @@ export function configFile(env = process.env, home = homedir()) {
|
|
|
22
22
|
|
|
23
23
|
export const detect = (env = process.env, home = homedir()) => existsSync(dirname(configFile(env, home)));
|
|
24
24
|
|
|
25
|
+
export const sessionIndexFile = (env = process.env, home = homedir()) => join(dirname(configFile(env, home)), 'session_index.jsonl');
|
|
26
|
+
|
|
25
27
|
// Codex treats non-JSON stdout from a Stop hook as invalid.
|
|
26
28
|
export const hookReply = (sub) => (sub === 'stop' ? '{}' : '');
|
|
27
29
|
|
|
@@ -35,9 +37,37 @@ const MAPPING = {
|
|
|
35
37
|
permission: ['needs_input', permissionText],
|
|
36
38
|
};
|
|
37
39
|
|
|
38
|
-
export function
|
|
40
|
+
export function sessionName(sessionId, env = process.env, home = homedir()) {
|
|
41
|
+
const id = str(sessionId);
|
|
42
|
+
if (!id) return '';
|
|
43
|
+
try {
|
|
44
|
+
const lines = readFileSync(sessionIndexFile(env, home), 'utf8').split(/\r?\n/);
|
|
45
|
+
for (let i = lines.length - 1; i >= 0; i--) {
|
|
46
|
+
if (!lines[i].includes(id)) continue;
|
|
47
|
+
try {
|
|
48
|
+
const row = JSON.parse(lines[i]);
|
|
49
|
+
if (str(row.id) === id) return str(row.thread_name);
|
|
50
|
+
} catch {
|
|
51
|
+
return '';
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
} catch {
|
|
55
|
+
return '';
|
|
56
|
+
}
|
|
57
|
+
return '';
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function translate(sub, payload, home = homedir(), env = process.env) {
|
|
39
61
|
if (!Object.hasOwn(MAPPING, sub)) return null;
|
|
40
62
|
const p = payload && typeof payload === 'object' ? payload : {};
|
|
41
63
|
const [type, text] = MAPPING[sub];
|
|
42
|
-
|
|
64
|
+
const sessionId = str(p.session_id);
|
|
65
|
+
return {
|
|
66
|
+
type,
|
|
67
|
+
agent: name,
|
|
68
|
+
session_id: sessionId,
|
|
69
|
+
session_name: str(p.session_name) || str(p.thread_name) || sessionName(sessionId, env, home),
|
|
70
|
+
project: projectOf(p.cwd, home),
|
|
71
|
+
text: text(p),
|
|
72
|
+
};
|
|
43
73
|
}
|
package/src/cli/notify.js
CHANGED
|
@@ -48,7 +48,7 @@ export async function runNotify(args, { input = '', env = process.env, write = (
|
|
|
48
48
|
if (reply) write(reply);
|
|
49
49
|
let payload = {};
|
|
50
50
|
try { payload = JSON.parse(input); } catch { /* garbage in: the core logs the incomplete event */ }
|
|
51
|
-
const event = adapter.translate(sub, payload);
|
|
51
|
+
const event = adapter.translate(sub, payload, undefined, env);
|
|
52
52
|
if (!event) return 0;
|
|
53
53
|
await handle(event, createContext(env));
|
|
54
54
|
} catch (e) {
|