een-api-toolkit 0.3.22 → 0.3.28
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/.claude/agents/een-devices-agent.md +37 -0
- package/.claude/agents/een-media-agent.md +71 -12
- package/CHANGELOG.md +10 -153
- package/README.md +23 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.js.map +1 -1
- package/docs/AI-CONTEXT.md +1 -1
- package/docs/ai-reference/AI-AUTH.md +1 -1
- package/docs/ai-reference/AI-DEVICES.md +1 -1
- package/docs/ai-reference/AI-EVENTS.md +1 -1
- package/docs/ai-reference/AI-MEDIA.md +1 -1
- package/docs/ai-reference/AI-SETUP.md +1 -1
- package/docs/ai-reference/AI-USERS.md +1 -1
- package/package.json +1 -1
|
@@ -71,8 +71,15 @@ type CameraStatus =
|
|
|
71
71
|
| 'offline'
|
|
72
72
|
| 'streaming'
|
|
73
73
|
| 'recording'
|
|
74
|
+
| 'registered'
|
|
75
|
+
| 'deviceOffline'
|
|
76
|
+
| 'bridgeOffline'
|
|
77
|
+
| 'invalidCredentials'
|
|
74
78
|
| 'error'
|
|
75
79
|
| 'unknown'
|
|
80
|
+
|
|
81
|
+
// Status can also be nested in an object:
|
|
82
|
+
// camera.status?.connectionStatus
|
|
76
83
|
```
|
|
77
84
|
|
|
78
85
|
### Bridge Interface
|
|
@@ -287,8 +294,38 @@ onMounted(fetchCameras)
|
|
|
287
294
|
| FORBIDDEN | No permission | Show access denied message |
|
|
288
295
|
| API_ERROR | Server error | Show error, allow retry |
|
|
289
296
|
|
|
297
|
+
## Camera ID Usage
|
|
298
|
+
|
|
299
|
+
The `camera.id` property is used consistently across all toolkit functions:
|
|
300
|
+
- `getCameras()` returns cameras with `id` property
|
|
301
|
+
- `listFeeds({ deviceId: camera.id })` for feeds
|
|
302
|
+
- `getLiveImage({ cameraId: camera.id })` for images
|
|
303
|
+
- LivePlayer SDK: `{ cameraId: camera.id }` for live video
|
|
304
|
+
|
|
305
|
+
**Note:** Some legacy EEN documentation may refer to "ESN" (Electronic Serial Number). This is outdated terminology - the current API uses `id`. In the toolkit, always use `camera.id`.
|
|
306
|
+
|
|
307
|
+
## Checking Camera Status for Previews
|
|
308
|
+
|
|
309
|
+
Before loading previews or video, check if the camera is in a viewable state:
|
|
310
|
+
|
|
311
|
+
```typescript
|
|
312
|
+
function isCameraOnline(status?: CameraStatus | { connectionStatus?: CameraStatus }): boolean {
|
|
313
|
+
// Handle both string status and nested object status
|
|
314
|
+
const statusStr = typeof status === 'string' ? status : status?.connectionStatus
|
|
315
|
+
return statusStr === 'online' || statusStr === 'streaming' || statusStr === 'registered'
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// Usage
|
|
319
|
+
if (isCameraOnline(camera.status)) {
|
|
320
|
+
// Safe to load preview or video
|
|
321
|
+
} else {
|
|
322
|
+
// Show "Camera offline" message
|
|
323
|
+
}
|
|
324
|
+
```
|
|
325
|
+
|
|
290
326
|
## Constraints
|
|
291
327
|
- Always check authentication before API calls
|
|
292
328
|
- Use appropriate status filters to reduce payload
|
|
293
329
|
- Handle pagination for accounts with many devices
|
|
294
330
|
- Use include[] to request only needed fields
|
|
331
|
+
- Check camera status before loading previews (offline cameras won't have streams)
|
|
@@ -58,12 +58,14 @@ assistant: "I'll use the een-media-agent to diagnose the HLS configuration and a
|
|
|
58
58
|
- Modify multipartUrl with query parameters
|
|
59
59
|
- Use multipartUrl without initMediaSession() first
|
|
60
60
|
- Assume timestamps are ISO 8601 (they use +00:00 format)
|
|
61
|
+
- Pass ANY arguments to LivePlayer constructor - it MUST be called as `new LivePlayer()` with no arguments
|
|
61
62
|
|
|
62
63
|
**ALWAYS:**
|
|
63
64
|
- Use getLiveImage() for simple thumbnails
|
|
64
65
|
- Use initMediaSession() before multipartUrl
|
|
65
66
|
- Use formatTimestamp() for EEN API timestamps
|
|
66
67
|
- Check authentication before media operations
|
|
68
|
+
- Pass config to LivePlayer's `start()` method, NOT the constructor
|
|
67
69
|
|
|
68
70
|
## Choosing the Right Preview Method
|
|
69
71
|
|
|
@@ -213,28 +215,82 @@ function setupHlsPlayer(videoElement: HTMLVideoElement, hlsUrl: string) {
|
|
|
213
215
|
|
|
214
216
|
## Live Video SDK Integration
|
|
215
217
|
|
|
216
|
-
For full-quality live video, use the EEN Live Video SDK:
|
|
218
|
+
For full-quality live video, use the EEN Live Video Web SDK:
|
|
217
219
|
|
|
218
220
|
```typescript
|
|
219
|
-
// Install: npm install @
|
|
221
|
+
// Install: npm install @een/live-video-web-sdk
|
|
220
222
|
|
|
221
|
-
import
|
|
223
|
+
import LivePlayer from '@een/live-video-web-sdk'
|
|
222
224
|
import { useAuthStore } from 'een-api-toolkit'
|
|
223
225
|
|
|
224
|
-
|
|
226
|
+
// Store player instance for cleanup
|
|
227
|
+
let livePlayer: LivePlayer | null = null
|
|
228
|
+
|
|
229
|
+
async function setupLiveVideo(videoElement: HTMLVideoElement, cameraId: string) {
|
|
225
230
|
const authStore = useAuthStore()
|
|
226
231
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
+
// CRITICAL: Create LivePlayer WITHOUT arguments
|
|
233
|
+
livePlayer = new LivePlayer()
|
|
234
|
+
|
|
235
|
+
// CRITICAL: Pass config to start(), NOT to constructor
|
|
236
|
+
await livePlayer.start({
|
|
237
|
+
videoElement, // HTML video element (required)
|
|
238
|
+
cameraId, // Camera device ID (required)
|
|
239
|
+
baseUrl: authStore.baseUrl, // EEN API base URL (required)
|
|
240
|
+
jwt: authStore.token // Auth token (required)
|
|
232
241
|
})
|
|
233
242
|
|
|
234
|
-
|
|
243
|
+
return livePlayer
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// Clean up when done
|
|
247
|
+
function stopLiveVideo() {
|
|
248
|
+
if (livePlayer) {
|
|
249
|
+
livePlayer.stop()
|
|
250
|
+
livePlayer = null
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
### IMPORTANT: LivePlayer Usage Pattern
|
|
256
|
+
|
|
257
|
+
**CORRECT pattern:**
|
|
258
|
+
```typescript
|
|
259
|
+
const player = new LivePlayer() // No arguments to constructor
|
|
260
|
+
await player.start(config) // Config passed to start()
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
**WRONG pattern (will cause "Video Stream is done" errors):**
|
|
264
|
+
```typescript
|
|
265
|
+
const player = new LivePlayer(config) // DON'T pass config here
|
|
266
|
+
await player.start() // This won't work correctly
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
### IMPORTANT: Video Element Must Be in DOM
|
|
270
|
+
|
|
271
|
+
The video element MUST be rendered in the DOM before calling `player.start()`.
|
|
272
|
+
|
|
273
|
+
**Problem:** Using `v-if` to conditionally show the video element means it doesn't exist during loading:
|
|
274
|
+
```vue
|
|
275
|
+
<!-- WRONG: Video element doesn't exist when loading=true -->
|
|
276
|
+
<div v-if="loading">Loading...</div>
|
|
277
|
+
<video v-else ref="videoRef" /> <!-- Not in DOM during loading! -->
|
|
278
|
+
```
|
|
235
279
|
|
|
236
|
-
|
|
280
|
+
**Solution:** Always render the video element, use CSS to hide it:
|
|
281
|
+
```vue
|
|
282
|
+
<!-- CORRECT: Video element always exists in DOM -->
|
|
283
|
+
<div v-if="loading" class="loading-overlay">Loading...</div>
|
|
284
|
+
<div class="video-container" :class="{ hidden: loading }">
|
|
285
|
+
<video ref="videoRef" /> <!-- Always in DOM -->
|
|
286
|
+
</div>
|
|
287
|
+
|
|
288
|
+
<style>
|
|
289
|
+
.video-container.hidden {
|
|
290
|
+
visibility: hidden;
|
|
291
|
+
position: absolute;
|
|
237
292
|
}
|
|
293
|
+
</style>
|
|
238
294
|
```
|
|
239
295
|
|
|
240
296
|
## Error Handling
|
|
@@ -253,4 +309,7 @@ function setupLiveVideo(container: HTMLElement, cameraId: string) {
|
|
|
253
309
|
| Image not loading | Auth not in cookies | Call initMediaSession() first |
|
|
254
310
|
| Timestamp errors | Wrong format | Use formatTimestamp() |
|
|
255
311
|
| CORS errors | Direct API access | Use toolkit functions, not direct fetch |
|
|
256
|
-
| Black video | HLS auth missing | Configure xhrSetup with token |
|
|
312
|
+
| Black video (HLS) | HLS auth missing | Configure xhrSetup with token |
|
|
313
|
+
| "Video Stream is done" immediately | Config passed to LivePlayer constructor | MUST use `new LivePlayer()` with no args, then `player.start(config)` |
|
|
314
|
+
| "Video element not found" | Video element not in DOM | Ensure video element is rendered (not hidden by v-if) before SDK init |
|
|
315
|
+
| Black video, no errors (LivePlayer) | Video element hidden by v-if | Use CSS visibility/opacity instead of v-if for conditional video display |
|
package/CHANGELOG.md
CHANGED
|
@@ -2,170 +2,27 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
-
## [0.3.
|
|
5
|
+
## [0.3.28] - 2026-01-23
|
|
6
6
|
|
|
7
7
|
### Release Summary
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
## Summary
|
|
11
|
-
|
|
12
|
-
- Added Preview, HD Image, and Video buttons to event modal lightboxes in vue-events and vue-event-subscriptions example apps
|
|
13
|
-
- Implemented proper authentication for media fetching using `getRecordedImage` and HLS player with Authorization headers
|
|
14
|
-
- Created `useHlsPlayer` composable for both apps following vue-alerts-metrics pattern
|
|
15
|
-
|
|
16
|
-
## Changes
|
|
17
|
-
|
|
18
|
-
- **vue-events**: Updated EventsModal.vue with media buttons and HLS video support
|
|
19
|
-
- **vue-event-subscriptions**: Updated LiveEvents.vue with media buttons and HLS video support
|
|
20
|
-
- Added hls.js dependency to both example apps
|
|
21
|
-
- Created composables/useHlsPlayer.ts in both apps
|
|
22
|
-
|
|
23
|
-
## Test Plan
|
|
24
|
-
|
|
25
|
-
- [x] Unit tests: 341 passed
|
|
26
|
-
- [x] Build: successful
|
|
27
|
-
- [x] E2E tests for all 8 example apps passed (123 total):
|
|
28
|
-
- vue-users: 14 passed
|
|
29
|
-
- vue-cameras: 13 passed
|
|
30
|
-
- vue-bridges: 13 passed
|
|
31
|
-
- vue-events: 16 passed
|
|
32
|
-
- vue-feeds: 12 passed
|
|
33
|
-
- vue-media: 20 passed
|
|
34
|
-
- vue-alerts-metrics: 20 passed
|
|
35
|
-
- vue-event-subscriptions: 15 passed
|
|
36
|
-
|
|
37
|
-
## Version
|
|
38
|
-
|
|
39
|
-
v0.3.20
|
|
40
|
-
|
|
41
|
-
## Commits
|
|
42
|
-
|
|
43
|
-
- 8f11b04 feat: Add media buttons to event modal lightboxes in vue-events and vue-event-subscriptions
|
|
44
|
-
|
|
45
|
-
🤖 Generated with [Claude Code](https://claude.com/claude-code)
|
|
46
|
-
|
|
47
|
-
#### PR #65: feat: Restructure AI documentation with specialized agents
|
|
48
|
-
## Summary
|
|
49
|
-
|
|
50
|
-
Restructures the AI documentation from a single monolithic file into domain-specific documents with specialized Claude agents for context-efficient AI assistance.
|
|
51
|
-
|
|
52
|
-
### Changes
|
|
53
|
-
|
|
54
|
-
**Documentation Split (7 files):**
|
|
55
|
-
- `AI-CONTEXT.md` - Overview and navigation (entry point)
|
|
56
|
-
- `AI-SETUP.md` - Vue 3 scaffolding, Pinia, Vite configuration
|
|
57
|
-
- `AI-AUTH.md` - OAuth flow, tokens, route guards
|
|
58
|
-
- `AI-USERS.md` - User management API
|
|
59
|
-
- `AI-DEVICES.md` - Cameras & Bridges API
|
|
60
|
-
- `AI-MEDIA.md` - Media, Feeds, Live Video, HLS
|
|
61
|
-
- `AI-EVENTS.md` - Events, Alerts, Metrics, SSE subscriptions
|
|
62
|
-
|
|
63
|
-
**Specialized Agents (6 new agents):**
|
|
64
|
-
- `een-setup-agent` - Vue 3 project setup assistance
|
|
65
|
-
- `een-auth-agent` - OAuth authentication help
|
|
66
|
-
- `een-users-agent` - User management features
|
|
67
|
-
- `een-devices-agent` - Camera and bridge operations
|
|
68
|
-
- `een-media-agent` - Video and media troubleshooting
|
|
69
|
-
- `een-events-agent` - Events and real-time streaming
|
|
70
|
-
|
|
71
|
-
**CLI Tool:**
|
|
72
|
-
- Added `npx een-setup-agents` command for easy agent installation
|
|
73
|
-
- Copies agents to `.claude/agents/` for automatic discovery
|
|
74
|
-
|
|
75
|
-
**Generation Script:**
|
|
76
|
-
- Refactored to generate split files by default
|
|
77
|
-
- `--single` flag for legacy monolithic output
|
|
78
|
-
- Extracts examples from actual Vue components
|
|
79
|
-
|
|
80
|
-
### Benefits
|
|
81
|
-
|
|
82
|
-
| Metric | Before | After (typical task) |
|
|
83
|
-
|--------|--------|---------------------|
|
|
84
|
-
| Tokens per task | ~15-18K | ~5-8K |
|
|
85
|
-
| Context preserved | Limited | Substantial |
|
|
86
|
-
| Agent specialization | None | 6 domain agents |
|
|
87
|
-
|
|
88
|
-
## Test Results
|
|
89
|
-
|
|
90
|
-
- **Lint:** ✅ Passed (1 pre-existing warning)
|
|
91
|
-
- **Unit Tests:** ✅ 341 passed
|
|
92
|
-
- **Build:** ✅ Successful
|
|
93
|
-
- **E2E Tests:** ✅ 70 passed across 8 example apps
|
|
94
|
-
|
|
95
|
-
## Version
|
|
96
|
-
|
|
97
|
-
`0.3.20`
|
|
98
|
-
|
|
99
|
-
## Commits
|
|
100
|
-
|
|
101
|
-
- `8e1cc78` feat: Restructure AI documentation into domain-specific files with specialized agents
|
|
102
|
-
|
|
103
|
-
---
|
|
104
|
-
|
|
105
|
-
🤖 Generated with [Claude Code](https://claude.ai/code)
|
|
106
|
-
|
|
107
|
-
#### PR #66: Release v0.3.20: AI Documentation Restructure
|
|
108
|
-
## Summary
|
|
109
|
-
|
|
110
|
-
This release restructures the AI documentation for improved context efficiency:
|
|
111
|
-
|
|
112
|
-
- **Split AI-CONTEXT.md** into 7 domain-specific documents (~2-4K tokens each vs 15K+ monolithic)
|
|
113
|
-
- **Added 6 specialized Claude agents** for domain-specific assistance
|
|
114
|
-
- **New CLI tool**: `npx een-setup-agents` for easy agent installation in consumer projects
|
|
115
|
-
- **Code quality fixes** addressing Gemini code review feedback
|
|
116
|
-
|
|
117
|
-
## Changes
|
|
118
|
-
|
|
119
|
-
### New Files
|
|
120
|
-
- `.claude/agents/` - 6 specialized agents (auth, users, devices, media, events, setup)
|
|
121
|
-
- `docs/ai-reference/` - 6 domain-specific AI reference documents
|
|
122
|
-
- `scripts/setup-agents.ts` - CLI tool for agent installation
|
|
123
|
-
|
|
124
|
-
### Modified
|
|
125
|
-
- `docs/AI-CONTEXT.md` - Now serves as overview with navigation
|
|
126
|
-
- `scripts/generate-ai-context.ts` - Rewritten to support split file generation
|
|
127
|
-
- `package.json` - Added bin entry and updated files array
|
|
128
|
-
- `CLAUDE.md` - Added agent documentation section
|
|
129
|
-
|
|
130
|
-
### Commits
|
|
131
|
-
- `8e1cc78` feat: Restructure AI documentation into domain-specific files with specialized agents
|
|
132
|
-
- `407db5f` fix: Address Gemini code review feedback
|
|
133
|
-
- `ecd6cfd` Merge pull request #65
|
|
134
|
-
|
|
135
|
-
## Test Results
|
|
136
|
-
|
|
137
|
-
- **Lint**: ✅ Passed (1 pre-existing warning)
|
|
138
|
-
- **Unit Tests**: ✅ 341 passed
|
|
139
|
-
- **Build**: ✅ Successful
|
|
140
|
-
- **E2E Tests**: ✅ 70 passed across 8 example apps
|
|
141
|
-
|
|
142
|
-
## Version
|
|
143
|
-
|
|
144
|
-
`0.3.20`
|
|
145
|
-
|
|
146
|
-
---
|
|
147
|
-
|
|
148
|
-
🤖 Generated with [Claude Code](https://claude.ai/code)
|
|
149
|
-
|
|
9
|
+
No PR descriptions available for this release.
|
|
150
10
|
|
|
151
11
|
### Detailed Changes
|
|
152
12
|
|
|
153
|
-
#### Features
|
|
154
|
-
- feat: Restructure AI documentation into domain-specific files with specialized agents
|
|
155
|
-
- feat: Add media buttons to event modal lightboxes in vue-events and vue-event-subscriptions
|
|
156
|
-
|
|
157
13
|
#### Bug Fixes
|
|
158
|
-
- fix:
|
|
159
|
-
- fix: Address Gemini code review feedback
|
|
160
|
-
- fix: Address code review feedback from PR #64
|
|
14
|
+
- fix: Suppress eslint console.log warning in debug utility
|
|
161
15
|
|
|
162
16
|
#### Other Changes
|
|
163
|
-
-
|
|
164
|
-
-
|
|
17
|
+
- docs: Address Gemini and Claude review comments
|
|
18
|
+
- chore: Add OAuth proxy startup to PR-and-check skill
|
|
19
|
+
- docs: Add Claude Code agent setup instructions to Live Viewer prompt
|
|
20
|
+
- docs: Add Claude Code agents documentation to User Guide and README
|
|
21
|
+
- docs: Improve agent documentation based on usage experience
|
|
165
22
|
|
|
166
23
|
### Links
|
|
167
24
|
- [npm package](https://www.npmjs.com/package/een-api-toolkit)
|
|
168
|
-
- [Full Changelog](https://github.com/klaushofrichter/een-api-toolkit/compare/v0.3.
|
|
25
|
+
- [Full Changelog](https://github.com/klaushofrichter/een-api-toolkit/compare/v0.3.22...v0.3.28)
|
|
169
26
|
|
|
170
27
|
---
|
|
171
|
-
*Released: 2026-01-
|
|
28
|
+
*Released: 2026-01-23 08:45:39 CST*
|
package/README.md
CHANGED
|
@@ -176,6 +176,29 @@ if (!cameraError) {
|
|
|
176
176
|
| **[AI Context](./docs/AI-CONTEXT.md)** | Single-file reference for AI assistants (also in npm package) |
|
|
177
177
|
| **[AI Prompts](./docs/Prompts.md)** | Example prompts for generating apps with AI |
|
|
178
178
|
|
|
179
|
+
## Claude Code Agents
|
|
180
|
+
|
|
181
|
+
The toolkit includes specialized [Claude Code](https://docs.anthropic.com/en/docs/claude-code) agents for AI-assisted development. These agents have deep knowledge of the EEN API and toolkit patterns.
|
|
182
|
+
|
|
183
|
+
> **Note:** These agents use Claude Code's specific format. To use with other AI assistants (Gemini CLI, Copilot, etc.), the agent specs would need conversion.
|
|
184
|
+
|
|
185
|
+
**Available agents:**
|
|
186
|
+
- `een-setup-agent` - Project scaffolding, Pinia setup, Vite configuration
|
|
187
|
+
- `een-auth-agent` - OAuth flows, route guards, token management
|
|
188
|
+
- `een-users-agent` - User listing and profile APIs
|
|
189
|
+
- `een-devices-agent` - Camera and bridge management
|
|
190
|
+
- `een-media-agent` - Live video, previews, HLS playback
|
|
191
|
+
- `een-events-agent` - Events, alerts, metrics, SSE subscriptions
|
|
192
|
+
|
|
193
|
+
**Installation:**
|
|
194
|
+
```bash
|
|
195
|
+
npx een-setup-agents
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
> **Important:** After running the setup script, **restart Claude Code** for the agents to become available.
|
|
199
|
+
|
|
200
|
+
See the [User Guide](./docs/USER-GUIDE.md#claude-code-agents) for detailed agent documentation.
|
|
201
|
+
|
|
179
202
|
## Example Applications
|
|
180
203
|
|
|
181
204
|
The `examples/` directory contains complete Vue 3 applications demonstrating toolkit features:
|