@etazio/agent-sdk 0.1.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/CHANGELOG.md +11 -0
- package/LICENSE +21 -0
- package/README.md +145 -0
- package/index.js +1752 -0
- package/index.js.map +6 -0
- package/package.json +51 -0
- package/types/audio.d.ts +86 -0
- package/types/index.d.ts +168 -0
- package/types/shared/agents.d.ts +689 -0
- package/types/shared/avatar.d.ts +137 -0
- package/types/shared/board.d.ts +124 -0
- package/types/shared/calendar.d.ts +64 -0
- package/types/shared/chat.d.ts +161 -0
- package/types/shared/dto.d.ts +235 -0
- package/types/shared/errors.d.ts +15 -0
- package/types/shared/events.d.ts +391 -0
- package/types/shared/generator.d.ts +317 -0
- package/types/shared/images.d.ts +79 -0
- package/types/shared/index.d.ts +17 -0
- package/types/shared/markdown.d.ts +76 -0
- package/types/shared/roles.d.ts +29 -0
- package/types/shared/schemas.d.ts +251 -0
- package/types/shared/sso.d.ts +124 -0
- package/types/shared/tv.d.ts +121 -0
- package/types/shared/view.d.ts +103 -0
- package/types/shared/web.d.ts +297 -0
- package/types/speech.d.ts +39 -0
- package/types/version.d.ts +2 -0
- package/types/voice.d.ts +61 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.1.0 – 2026-09-16
|
|
4
|
+
|
|
5
|
+
Erste veröffentlichte Fassung als `@etazio/agent-sdk` (vorher intern `@spacelane/huddle-agent`).
|
|
6
|
+
|
|
7
|
+
- `connect()` / `EtazioAgent` für `agent-protocol/v1`: Handshake, Ack-Auswertung, Reconnect mit derselben `participantId`
|
|
8
|
+
- Typisierte Aufrufe: `say`, `goTo`, `sit`/`stand`, `setState`, `action`, `setTv`, `react`/`wave`, `meetingToken`, `boardOp`
|
|
9
|
+
- Sprachschleife `attachVoice()` mit VAD, Barge-in und OpenAI-Adaptern für STT/TTS (`@livekit/rtc-node` optional)
|
|
10
|
+
- Umbenannt: `HuddleAgent` → `EtazioAgent`, `HuddleAgentError` → `EtazioAgentError`, `HuddleVoice` → `EtazioVoice`
|
|
11
|
+
- Neu: `SDK_VERSION`
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 spacelane – Marcel Wiskow
|
|
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.
|
package/README.md
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
# @etazio/agent-sdk
|
|
2
|
+
|
|
3
|
+
Offizielles SDK für KI-Agenten im [Etazio](https://etazio.de)-Office.
|
|
4
|
+
|
|
5
|
+
Ein Agent ist in Etazio ein Teilnehmer wie jeder Mensch: Er steht im Raum, trägt ein KI-Zeichen,
|
|
6
|
+
läuft über dieselben Wege, schreibt im Chat und kann – wenn man zu ihm hingeht und `E` drückt –
|
|
7
|
+
auch sprechen. Das SDK übernimmt Handshake, Fehlerauswertung und Reconnect; alles Weitere sind
|
|
8
|
+
typisierte Aufrufe.
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
npm install @etazio/agent-sdk
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Voraussetzung: Node.js ≥ 20.19. Das Paket ist ESM mit eigenen TypeScript-Typen.
|
|
15
|
+
|
|
16
|
+
## Agent in 15 Zeilen
|
|
17
|
+
|
|
18
|
+
```ts
|
|
19
|
+
import { connect } from '@etazio/agent-sdk'
|
|
20
|
+
|
|
21
|
+
const agent = await connect({
|
|
22
|
+
url: process.env.ETAZIO_URL!, // z. B. https://app.etazio.de
|
|
23
|
+
token: process.env.ETAZIO_AGENT_TOKEN!, // hag_…
|
|
24
|
+
client: { name: 'hello-world', version: '1.0.0' },
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
console.log('Scopes:', agent.scopes.join(', '))
|
|
28
|
+
console.log('Im Office:', agent.world?.participants.map((p) => p.name).join(', '))
|
|
29
|
+
|
|
30
|
+
// Jemand spricht den Agenten an: @Erwähnung, Direktnachricht, Hingehen + E, Zone oder Arbeitsplatz
|
|
31
|
+
agent.on('address', async (a) => {
|
|
32
|
+
await agent.say(a.conv, `Hallo ${a.from.displayName}, ich bin da.`)
|
|
33
|
+
})
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
ETAZIO_URL=https://app.etazio.de ETAZIO_AGENT_TOKEN=hag_… npx tsx agent.ts
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Token besorgen
|
|
41
|
+
|
|
42
|
+
In Etazio auf der Agenten-Seite des Workspace **Agent anlegen**, Betrieb „Auf eurem eigenen Server“ wählen und die
|
|
43
|
+
nötigen Berechtigungen (Scopes) setzen. Das Token (`hag_…`) wird **nur einmal** angezeigt und kann
|
|
44
|
+
jederzeit rotiert oder per Kill-Switch gesperrt werden. Behandle es wie ein Passwort.
|
|
45
|
+
|
|
46
|
+
## Aufrufe
|
|
47
|
+
|
|
48
|
+
| Aufruf | Wofür | Scope |
|
|
49
|
+
|---|---|---|
|
|
50
|
+
| `connect(options)` / `new EtazioAgent(options).connect()` | Verbinden und Handshake | `office.read` (+ `world.presence`) |
|
|
51
|
+
| `agent.refresh()` | Frischer Überblick über Personen, Zonen, Objekte | wie oben |
|
|
52
|
+
| `agent.say(conv, text, parentId?)` | Nachricht im Chat, Thread oder DM | `chat.write` |
|
|
53
|
+
| `agent.typing(conv)` / `agent.typingWhile(conv, work)` | Tipp-Anzeige | `chat.write` |
|
|
54
|
+
| `agent.ask(conv, text, block)` | Nachricht mit Bestätigungsknöpfen | `chat.write` |
|
|
55
|
+
| `agent.goTo({ x, z } \| { zoneId } \| { participantId })` | Hingehen (Wegfindung macht der Server) | `world.move` |
|
|
56
|
+
| `agent.sit(seatId)` / `agent.stand()` | Hinsetzen, Aufstehen | `world.seat` |
|
|
57
|
+
| `agent.setState(placementId, state)` | Objektzustand setzen | `object.state` |
|
|
58
|
+
| `agent.action(placementId, action, data?)` | Objektaktion auslösen | `object.action` |
|
|
59
|
+
| `agent.setTv(placementId, tvState)` | Fernseher steuern | `tv.control` |
|
|
60
|
+
| `agent.react(glyph)` / `agent.wave()` | Reaktion, Winken | `world.react` |
|
|
61
|
+
| `agent.meetingToken(target?)` | LiveKit-Token für Audio | `meeting.audio` |
|
|
62
|
+
| `agent.boardOp(envelope)` | Whiteboard bearbeiten | `board.write` |
|
|
63
|
+
| `agent.can(scope)` | Prüfen, ob das Token einen Scope hat | – |
|
|
64
|
+
| `agent.close()` | Verbindung beenden | – |
|
|
65
|
+
|
|
66
|
+
Nützliche Eigenschaften: `agent.hello`, `agent.world`, `agent.scopes`, `agent.participantId`, `agent.connected`.
|
|
67
|
+
|
|
68
|
+
## Ereignisse
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
agent.on('ready', (hello) => { /* nach jedem (Re-)Connect */ })
|
|
72
|
+
agent.on('address', (a) => { /* Ansprache */ })
|
|
73
|
+
agent.on('chat', (m) => { /* jede sichtbare Chatnachricht (chat.read) */ })
|
|
74
|
+
agent.on('participantJoined', (p) => {})
|
|
75
|
+
agent.on('zone', (z) => {})
|
|
76
|
+
agent.on('throttled', (t) => { /* Budget überschritten – langsamer werden */ })
|
|
77
|
+
agent.on('revoked', (r) => { /* Token gesperrt – kein Reconnect */ })
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Außerdem: `voice`, `participantLeft`, `seat`, `objectState`, `objectAction`, `emote`, `disconnect`, `error`.
|
|
81
|
+
Welche Ereignisse ankommen, bestimmen die Scopes des Tokens.
|
|
82
|
+
|
|
83
|
+
## Fehler
|
|
84
|
+
|
|
85
|
+
Jede Ablehnung wird zu einem `EtazioAgentError` mit `code` – etwa `forbidden` (Scope fehlt),
|
|
86
|
+
`rate_limited`, `not_found`, `timeout`, `unavailable`.
|
|
87
|
+
|
|
88
|
+
```ts
|
|
89
|
+
import { EtazioAgentError } from '@etazio/agent-sdk'
|
|
90
|
+
|
|
91
|
+
try {
|
|
92
|
+
await agent.goTo({ zoneId: 'meeting-1' })
|
|
93
|
+
} catch (err) {
|
|
94
|
+
if (err instanceof EtazioAgentError && err.code === 'forbidden') {
|
|
95
|
+
console.error('Dem Token fehlt world.move')
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Reconnect
|
|
101
|
+
|
|
102
|
+
`autoReconnect` ist standardmäßig an. Nach jedem Wiederverbinden meldet sich das SDK mit derselben
|
|
103
|
+
`participantId` zurück, damit Position und Sitzplatz erhalten bleiben, und feuert erneut `ready`.
|
|
104
|
+
Nach `revoked` (Token rotiert, Agent deaktiviert, Kill-Switch) verbindet es sich bewusst nicht neu.
|
|
105
|
+
|
|
106
|
+
## Sprechen
|
|
107
|
+
|
|
108
|
+
Mit `attachVoice()` hört der Agent zu, sobald ein Mensch neben ihm `E` drückt, und antwortet
|
|
109
|
+
gesprochen – mit Untertitel im Chat. Erkennung (STT) und Stimme (TTS) laufen bei dir; für OpenAI
|
|
110
|
+
liegen fertige Adapter bei. Eigene Anbieter implementieren `SttAdapter` bzw. `TtsAdapter`.
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
npm install @livekit/rtc-node # optional, native Bindings (glibc – kein Alpine)
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
```ts
|
|
117
|
+
import { attachVoice, connect, openAiStt, openAiTts } from '@etazio/agent-sdk'
|
|
118
|
+
|
|
119
|
+
const agent = await connect({
|
|
120
|
+
url: process.env.ETAZIO_URL!,
|
|
121
|
+
token: process.env.ETAZIO_AGENT_TOKEN!,
|
|
122
|
+
capabilities: ['chat', 'voice'],
|
|
123
|
+
})
|
|
124
|
+
const speech = { apiKey: process.env.OPENAI_API_KEY!, voice: 'alloy', language: 'de' }
|
|
125
|
+
|
|
126
|
+
attachVoice(agent, {
|
|
127
|
+
stt: openAiStt(speech),
|
|
128
|
+
tts: openAiTts(speech),
|
|
129
|
+
async reply({ text, signal }) {
|
|
130
|
+
// eigenes Modell hier – `signal` weiterreichen, damit Dazwischenreden die Anfrage abbricht
|
|
131
|
+
const antwort = await meinModell(text, { signal })
|
|
132
|
+
return antwort
|
|
133
|
+
},
|
|
134
|
+
})
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Nötige Scopes: `meeting.audio`, `voice.listen`, `voice.speak` (plus `chat.write` für Untertitel).
|
|
138
|
+
Der Server entscheidet, wann ein Agent zuhören darf – nur im offenen Gespräch und nur dem Menschen,
|
|
139
|
+
der es eröffnet hat. Was der Mensch sagt, wird nirgends gespeichert.
|
|
140
|
+
|
|
141
|
+
Stellschrauben: `silenceMs` (Standard 700) und `threshold` (0.02).
|
|
142
|
+
|
|
143
|
+
## Lizenz
|
|
144
|
+
|
|
145
|
+
MIT
|