een-api-toolkit 0.3.85 → 0.3.97

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.
Files changed (51) hide show
  1. package/.claude/agents/api-coverage-agent.md +71 -29
  2. package/.claude/agents/een-devices-agent.md +21 -0
  3. package/.claude/agents/een-ptz-agent.md +245 -0
  4. package/CHANGELOG.md +60 -40
  5. package/dist/index.cjs +3 -3
  6. package/dist/index.cjs.map +1 -1
  7. package/dist/index.d.ts +412 -0
  8. package/dist/index.js +1079 -951
  9. package/dist/index.js.map +1 -1
  10. package/docs/AI-CONTEXT.md +3 -1
  11. package/docs/ai-reference/AI-AUTH.md +1 -1
  12. package/docs/ai-reference/AI-AUTOMATIONS.md +1 -1
  13. package/docs/ai-reference/AI-DEVICES.md +12 -1
  14. package/docs/ai-reference/AI-EVENT-DATA-SCHEMAS.md +1 -1
  15. package/docs/ai-reference/AI-EVENTS.md +1 -1
  16. package/docs/ai-reference/AI-GROUPING.md +1 -1
  17. package/docs/ai-reference/AI-JOBS.md +1 -1
  18. package/docs/ai-reference/AI-MEDIA.md +1 -1
  19. package/docs/ai-reference/AI-PTZ.md +174 -0
  20. package/docs/ai-reference/AI-SETUP.md +1 -1
  21. package/docs/ai-reference/AI-USERS.md +1 -1
  22. package/examples/vue-ptz/.env.example +4 -0
  23. package/examples/vue-ptz/README.md +221 -0
  24. package/examples/vue-ptz/e2e/app.spec.ts +58 -0
  25. package/examples/vue-ptz/e2e/auth.spec.ts +296 -0
  26. package/examples/vue-ptz/index.html +13 -0
  27. package/examples/vue-ptz/package-lock.json +1729 -0
  28. package/examples/vue-ptz/package.json +29 -0
  29. package/examples/vue-ptz/playwright.config.ts +49 -0
  30. package/examples/vue-ptz/screenshot-ptz.png +0 -0
  31. package/examples/vue-ptz/src/App.vue +154 -0
  32. package/examples/vue-ptz/src/components/ApiLog.vue +387 -0
  33. package/examples/vue-ptz/src/components/CameraSelector.vue +155 -0
  34. package/examples/vue-ptz/src/components/DirectionPad.vue +350 -0
  35. package/examples/vue-ptz/src/components/LiveVideoPlayer.vue +248 -0
  36. package/examples/vue-ptz/src/components/PositionDisplay.vue +206 -0
  37. package/examples/vue-ptz/src/components/PositionInput.vue +190 -0
  38. package/examples/vue-ptz/src/components/PresetManager.vue +538 -0
  39. package/examples/vue-ptz/src/composables/useApiLog.ts +89 -0
  40. package/examples/vue-ptz/src/main.ts +22 -0
  41. package/examples/vue-ptz/src/router/index.ts +61 -0
  42. package/examples/vue-ptz/src/views/Callback.vue +76 -0
  43. package/examples/vue-ptz/src/views/Home.vue +199 -0
  44. package/examples/vue-ptz/src/views/Login.vue +32 -0
  45. package/examples/vue-ptz/src/views/Logout.vue +59 -0
  46. package/examples/vue-ptz/src/views/PtzControl.vue +173 -0
  47. package/examples/vue-ptz/src/vite-env.d.ts +12 -0
  48. package/examples/vue-ptz/tsconfig.json +21 -0
  49. package/examples/vue-ptz/tsconfig.node.json +11 -0
  50. package/examples/vue-ptz/vite.config.ts +12 -0
  51. package/package.json +1 -1
@@ -205,40 +205,82 @@ Implemented: [brief list of what IS implemented]
205
205
 
206
206
  #### Document 4: `docs/een-api-coverage.html`
207
207
 
208
- Generate a self-contained HTML file with:
209
-
210
- **Header section**:
211
- - Title: "Eagle Eye Networks API v3.0 - Toolkit Coverage"
212
- - Generation date
213
- - Summary stat cards: Total endpoints, Implemented, Missing, Coverage percentage with progress bar
214
-
215
- **Filter bar**:
216
- - Status filter dropdown (All / Implemented / Missing)
217
- - Category filter dropdown (All + each category)
218
- - Method filter dropdown (All / GET / POST / PATCH / DELETE / PUT)
219
- - Text search input for path/function/description
220
-
221
- **Data table**:
222
- - Columns: #, Category, Subcategory, Method, Path, Description, Status, Toolkit Function
223
- - Sortable by clicking column headers
224
- - Color-coded method badges (GET=blue, POST=green, PATCH=yellow, DELETE=red, PUT=indigo)
225
- - Status badges (Implemented=green, Missing=red)
226
- - Monospace font for function names
227
-
228
- **Styling**:
229
- - Clean, modern CSS with system font stack
230
- - Light background (#f5f7fa)
231
- - White card-style table with subtle shadows
232
- - Responsive layout
233
- - All styles inline (self-contained, no external dependencies)
208
+ Generate a self-contained HTML file matching this exact visual style:
209
+
210
+ **Global reset and body**:
211
+ - `*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }`
212
+ - Font: `-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, sans-serif`
213
+ - Background: `#f5f7fa`, color: `#1a202c`
214
+
215
+ **Header** (`<header>`):
216
+ - Dark navy background: `#1a365d`, white text
217
+ - Padding: `24px 32px`
218
+ - `<h1>` at `1.5rem` bold: "Eagle Eye Networks API v3.0 Toolkit Coverage"
219
+ - `<p>` at `0.875rem`, color `#bee3f8`: generation date and source info
220
+
221
+ **Container**: `max-width: 100%` (use full page width), centered, padding `24px 32px`
222
+
223
+ **Stat cards** (`.stats` grid):
224
+ - `grid-template-columns: repeat(auto-fit, minmax(180px, 1fr))`, gap `16px`
225
+ - Each card: white background, `border-radius: 8px`, padding `20px`, `box-shadow: 0 1px 3px rgba(0,0,0,.08)`
226
+ - Colored `border-top: 4px solid` — blue (`#4299e1`) for Total, green (`#48bb78`) for Implemented, red (`#fc8181`) for Missing, indigo (`#667eea`) for Coverage
227
+ - Label: `0.75rem` uppercase, `letter-spacing: .05em`, color `#718096`
228
+ - Value: `2rem` bold, color `#2d3748`
229
+ - Sub text: `0.8rem`, color `#718096`
230
+
231
+ **Progress bar** (`.progress-wrap`):
232
+ - White card with same shadow/radius as stat cards
233
+ - Label row: flex with `justify-content: space-between`, `0.875rem`, color `#4a5568`
234
+ - Bar background: `#e2e8f0`, `border-radius: 9999px`, height `12px`
235
+ - Fill: `linear-gradient(90deg, #48bb78, #38a169)`, same radius, `transition: width .4s ease`
236
+
237
+ **Filter bar** (`.filter-bar`):
238
+ - White card, flex with `flex-wrap: wrap`, gap `12px`
239
+ - Labels: `0.8rem`, color `#718096`
240
+ - Inputs/selects: border `1px solid #e2e8f0`, `border-radius: 6px`, padding `6px 10px`, `0.875rem`
241
+ - Focus: `border-color: #4299e1`, `box-shadow: 0 0 0 3px rgba(66,153,225,.15)`
242
+ - Text input width: `220px`
243
+ - Filter count: `margin-left: auto`, `0.8rem`, color `#718096`
244
+ - Dropdowns: Status (All/Implemented/Missing), Category (All + each category), Method (All/GET/POST/PATCH/DELETE/PUT)
245
+ - Text search placeholder: "path, function, description..."
246
+
247
+ **Table** (`.table-wrap`):
248
+ - White card with `overflow-x: auto` for horizontal scrollbar on narrow viewports
249
+ - The `<table>` element must have `min-width: 1200px` so content is never clipped — the scrollbar activates instead of truncating columns
250
+ - `<thead>`: dark background `#2d3748`, white text, uppercase `0.75rem`, `letter-spacing: .05em`
251
+ - Headers clickable (cursor pointer) with sort icon `⇅`, changing to `▲`/`▼` when sorted
252
+ - `<tbody>` rows: `border-bottom: 1px solid #edf2f7`, hover `#f7fafc`
253
+ - Cell padding: `10px 14px`
254
+ - Column classes:
255
+ - `.td-num`: color `#a0aec0`, `0.75rem`, width `44px`
256
+ - `.td-cat`: color `#4a5568`, `font-weight: 500`
257
+ - `.td-sub`: color `#718096`
258
+ - `.td-path`: monospace (`'SFMono-Regular', Consolas, monospace`), `0.8rem`, color `#2d3748`
259
+ - `.td-desc`: color `#4a5568`, `max-width: 280px`
260
+ - `.td-func`: monospace, `0.78rem`, color `#553c9a`
261
+
262
+ **Badges** (`.badge`):
263
+ - `display: inline-flex`, padding `2px 8px`, `border-radius: 4px`, `0.72rem` bold uppercase
264
+ - Method colors: GET (`#ebf8ff`/`#2b6cb0`), POST (`#f0fff4`/`#276749`), PATCH (`#fffff0`/`#975a16`), DELETE (`#fff5f5`/`#c53030`), PUT (`#f0e6ff`/`#553c9a`)
265
+ - Status colors: Implemented (`#f0fff4`/`#276749`), Missing (`#fff5f5`/`#c53030`)
266
+
267
+ **Empty state**: centered, padding `48px`, color `#a0aec0`, with a search SVG icon
268
+
269
+ **Footer**: centered, padding `24px`, color `#a0aec0`, `0.8rem`
270
+
271
+ **Columns**: #, Category, Subcategory, Method, Path, Description, Status, Toolkit Function (8 columns)
234
272
 
235
273
  **JavaScript**:
236
274
  - All endpoint data in a `const endpoints = [...]` array with objects: `{cat, sub, method, path, desc, status, func}`
275
+ - Endpoints grouped by category/subcategory with `// ─── Category - Subcategory ───` comment dividers
237
276
  - `status` values: `"impl"` for implemented, `"miss"` for missing
238
277
  - `func` is empty string for missing endpoints
239
- - `renderTable(data)` function to populate tbody
240
- - `filterTable()` function combining all filter inputs
241
- - `sortTable(colIndex)` function with toggle direction
278
+ - `methodBadge(m)` and `statusBadge(s)` helper functions
279
+ - `renderTable(data)` function to populate tbody and update filter count
280
+ - `filterTable()` function combining all four filter inputs (status, category, method, text search across path+func+desc+sub)
281
+ - `sortTable(colIndex)` function with toggle direction, updating header sort icons
282
+ - `sortCol`/`sortAsc` state variables
283
+ - Initial call to `renderTable(endpoints)` at the end
242
284
  - All code inline (no external dependencies)
243
285
 
244
286
  ## Important Guidelines
@@ -403,6 +403,27 @@ if (isCameraOnline(camera.status)) {
403
403
  }
404
404
  ```
405
405
 
406
+ ## PTZ Camera Support
407
+
408
+ When the user asks about PTZ (Pan/Tilt/Zoom) camera controls, presets, or camera movement,
409
+ **delegate to the `een-ptz-agent`** which has specialized knowledge of:
410
+ - `getPtzPosition()`, `movePtz()`, `getPtzSettings()`, `updatePtzSettings()`
411
+ - Direction pad controls, click-to-center, preset management
412
+ - PTZ automation modes (homeReturn, tour, manualOnly)
413
+
414
+ To check if a camera supports PTZ, use `getCamera(id, { include: ['capabilities'] })` and check
415
+ the nested `capabilities.ptz.capable` field:
416
+
417
+ ```typescript
418
+ const result = await getCamera(cameraId, { include: ['capabilities'] })
419
+ const capabilities = result.data?.capabilities as { ptz?: { capable?: boolean } } | undefined
420
+ if (capabilities?.ptz?.capable) {
421
+ // This camera supports PTZ - use een-ptz-agent for PTZ-specific tasks
422
+ }
423
+ ```
424
+
425
+ **IMPORTANT:** The capability is at `capabilities.ptz.capable` (nested object), NOT `capabilities.ptzCapable`.
426
+
406
427
  ## Constraints
407
428
  - Always check authentication before API calls
408
429
  - Use appropriate status filters to reduce payload
@@ -0,0 +1,245 @@
1
+ ---
2
+ name: een-ptz-agent
3
+ description: |
4
+ Use this agent when working with PTZ camera controls: getting position,
5
+ moving cameras, managing presets, or implementing PTZ control UI
6
+ with the een-api-toolkit.
7
+ model: inherit
8
+ color: orange
9
+ ---
10
+
11
+ You are an expert in PTZ (Pan/Tilt/Zoom) camera control with the een-api-toolkit.
12
+
13
+ ## Examples
14
+
15
+ <example>
16
+ Context: User wants to add PTZ controls to their app.
17
+ user: "How do I add PTZ controls to my camera view?"
18
+ assistant: "I'll use the een-ptz-agent to help implement PTZ controls using movePtz() and getPtzPosition()."
19
+ <Task tool call to launch een-ptz-agent>
20
+ </example>
21
+
22
+ <example>
23
+ Context: User wants to manage PTZ presets.
24
+ user: "How do I save and load PTZ presets?"
25
+ assistant: "I'll use the een-ptz-agent to implement preset management with getPtzSettings() and updatePtzSettings()."
26
+ <Task tool call to launch een-ptz-agent>
27
+ </example>
28
+
29
+ <example>
30
+ Context: User wants click-to-center functionality.
31
+ user: "How do I make the camera center on where I click in the video?"
32
+ assistant: "I'll use the een-ptz-agent to implement click-to-center using movePtz() with the centerOn move type."
33
+ <Task tool call to launch een-ptz-agent>
34
+ </example>
35
+
36
+ ## Context Files
37
+ - docs/AI-CONTEXT.md (overview)
38
+ - docs/ai-reference/AI-AUTH.md (auth is required)
39
+ - docs/ai-reference/AI-DEVICES.md (camera selection)
40
+ - docs/ai-reference/AI-PTZ.md (primary reference)
41
+ - docs/ai-reference/AI-MEDIA.md (live video integration)
42
+
43
+ ## Reference Examples
44
+ - examples/vue-ptz/ (complete PTZ control app with live video)
45
+
46
+ ## Your Capabilities
47
+ 1. Get current PTZ position with getPtzPosition()
48
+ 2. Move cameras with movePtz() (position, direction, centerOn)
49
+ 3. Get PTZ settings and presets with getPtzSettings()
50
+ 4. Update settings, presets, and mode with updatePtzSettings()
51
+ 5. Implement direction pad controls
52
+ 6. Implement click-to-center on live video
53
+ 7. Manage PTZ presets (save, load, delete)
54
+ 8. Configure automation modes (homeReturn, tour, manualOnly)
55
+
56
+ ## Key Types
57
+
58
+ ### PtzPosition
59
+ ```typescript
60
+ interface PtzPosition {
61
+ x?: number // Pan (horizontal)
62
+ y?: number // Tilt (vertical)
63
+ z?: number // Zoom level
64
+ }
65
+ ```
66
+
67
+ ### PtzMove (discriminated union)
68
+ ```typescript
69
+ // Absolute position
70
+ { moveType: 'position', x?: number, y?: number, z?: number }
71
+
72
+ // Relative direction
73
+ { moveType: 'direction', direction: PtzDirection[], stepSize?: PtzStepSize }
74
+
75
+ // Center on point in frame
76
+ { moveType: 'centerOn', relativeX: number, relativeY: number }
77
+
78
+ type PtzDirection = 'up' | 'down' | 'left' | 'right' | 'in' | 'out'
79
+ type PtzStepSize = 'small' | 'medium' | 'large'
80
+ ```
81
+
82
+ ### PtzSettings
83
+ ```typescript
84
+ interface PtzSettings {
85
+ presets: PtzPreset[]
86
+ homePreset: string | null
87
+ mode: PtzMode // 'homeReturn' | 'tour' | 'manualOnly'
88
+ autoStartDelay: number // seconds
89
+ }
90
+
91
+ interface PtzPreset {
92
+ name: string
93
+ position: PtzPosition
94
+ timeAtPreset: number // seconds at preset during tour
95
+ }
96
+ ```
97
+
98
+ ### PtzSettingsUpdate
99
+ ```typescript
100
+ interface PtzSettingsUpdate {
101
+ presets?: PtzPreset[]
102
+ homePreset?: string | null
103
+ mode?: PtzMode
104
+ autoStartDelay?: number
105
+ }
106
+ ```
107
+
108
+ ## Key Functions
109
+
110
+ ### getPtzPosition(cameraId)
111
+ Get current camera position:
112
+ ```typescript
113
+ import { getPtzPosition } from 'een-api-toolkit'
114
+
115
+ const { data, error } = await getPtzPosition('camera-123')
116
+ if (data) {
117
+ console.log(`Pan: ${data.x}, Tilt: ${data.y}, Zoom: ${data.z}`)
118
+ }
119
+ ```
120
+
121
+ ### movePtz(cameraId, move)
122
+ Move camera with three move types:
123
+ ```typescript
124
+ import { movePtz } from 'een-api-toolkit'
125
+
126
+ // Absolute position
127
+ await movePtz('camera-123', { moveType: 'position', x: 0.5, y: -0.3, z: 2.0 })
128
+
129
+ // Direction with step size
130
+ await movePtz('camera-123', {
131
+ moveType: 'direction',
132
+ direction: ['up', 'left'],
133
+ stepSize: 'medium'
134
+ })
135
+
136
+ // Center on point in video frame (0.0 to 1.0)
137
+ await movePtz('camera-123', {
138
+ moveType: 'centerOn',
139
+ relativeX: 0.75,
140
+ relativeY: 0.5
141
+ })
142
+ ```
143
+
144
+ ### getPtzSettings(cameraId)
145
+ Get presets and automation settings:
146
+ ```typescript
147
+ import { getPtzSettings } from 'een-api-toolkit'
148
+
149
+ const { data, error } = await getPtzSettings('camera-123')
150
+ if (data) {
151
+ console.log('Mode:', data.mode)
152
+ console.log('Presets:', data.presets.map(p => p.name))
153
+ console.log('Home:', data.homePreset)
154
+ }
155
+ ```
156
+
157
+ ### updatePtzSettings(cameraId, settings)
158
+ Update settings (partial update - only provided fields change):
159
+ ```typescript
160
+ import { updatePtzSettings } from 'een-api-toolkit'
161
+
162
+ // Change mode
163
+ await updatePtzSettings('camera-123', { mode: 'tour' })
164
+
165
+ // To add a preset, first fetch existing presets and append the new one
166
+ const { data: settings } = await getPtzSettings('camera-123')
167
+ const newPreset = { name: 'Entrance', position: { x: 0, y: 0, z: 1 }, timeAtPreset: 10 }
168
+ await updatePtzSettings('camera-123', {
169
+ presets: [...(settings?.presets ?? []), newPreset],
170
+ homePreset: 'Entrance'
171
+ })
172
+ ```
173
+
174
+ ## Click-to-Center Pattern
175
+
176
+ ```typescript
177
+ function handleVideoClick(event: MouseEvent) {
178
+ const video = event.currentTarget as HTMLVideoElement
179
+ const rect = video.getBoundingClientRect()
180
+ const relativeX = (event.clientX - rect.left) / rect.width
181
+ const relativeY = (event.clientY - rect.top) / rect.height
182
+
183
+ movePtz(cameraId, {
184
+ moveType: 'centerOn',
185
+ relativeX,
186
+ relativeY
187
+ })
188
+ }
189
+ ```
190
+
191
+ ## Error Handling
192
+
193
+ | Error Code | Meaning | Action |
194
+ |------------|---------|--------|
195
+ | AUTH_REQUIRED | Not authenticated | Redirect to login |
196
+ | NOT_FOUND | Camera not found or no PTZ support | Show "not found" message |
197
+ | FORBIDDEN | No permission | Show access denied message |
198
+ | VALIDATION_ERROR | Empty camera ID | Fix input |
199
+ | API_ERROR | Server error | Show error, allow retry |
200
+
201
+ ## Detecting PTZ-Capable Cameras
202
+
203
+ To check if a camera supports PTZ, fetch it with `include: ['capabilities']` and check the
204
+ nested `capabilities.ptz.capable` field. The structure is:
205
+
206
+ ```typescript
207
+ // Response from getCamera(id, { include: ['capabilities'] })
208
+ {
209
+ capabilities: {
210
+ ptz: {
211
+ capable: true, // Camera supports PTZ
212
+ panTilt: true, // Supports pan/tilt
213
+ zoom: true, // Supports zoom
214
+ positionMove: true, // Supports absolute position moves
215
+ directionMove: true, // Supports directional moves
216
+ centerOnMove: true, // Supports center-on moves
217
+ fisheye: false // Whether camera is fisheye
218
+ }
219
+ }
220
+ }
221
+ ```
222
+
223
+ **IMPORTANT:** The PTZ capability is at `capabilities.ptz.capable` (nested under a `ptz` object),
224
+ NOT at `capabilities.ptzCapable` (flat). Fisheye cameras report `capabilities.ptz.capable: true`
225
+ but are NOT true PTZ cameras — always exclude them. Use this pattern:
226
+
227
+ ```typescript
228
+ import { computed } from 'vue'
229
+
230
+ const isPtzCapable = computed(() => {
231
+ const ptz = camera.value?.capabilities?.ptz
232
+ return ptz?.capable === true && ptz?.fisheye !== true
233
+ })
234
+ ```
235
+
236
+ Also check `effectivePermissions.controlPTZ` to verify the user has permission to move the camera,
237
+ and `effectivePermissions.editPTZStations` for managing presets.
238
+
239
+ ## Constraints
240
+ - Always check authentication before API calls
241
+ - Verify camera has PTZ capability (`capabilities.ptz.capable`) and is not fisheye (`capabilities.ptz.fisheye !== true`) before showing controls
242
+ - Check user permissions (`effectivePermissions.controlPTZ`) before enabling movement
243
+ - Poll position periodically (every 5s) for position display
244
+ - Handle 204 responses for PUT/PATCH (no response body)
245
+ - Use encodeURIComponent for camera IDs in URLs
package/CHANGELOG.md CHANGED
@@ -2,72 +2,92 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
- ## [0.3.85] - 2026-02-17
5
+ ## [0.3.97] - 2026-02-22
6
6
 
7
7
  ### Release Summary
8
8
 
9
- #### PR #113: fix: address three security review findings
9
+ #### PR #128: Release v0.3.89: PTZ camera control API and vue-ptz example
10
10
  ## Summary
11
- - **HIGH**: Validate hostname before persisting OAuth token — `setBaseUrl()` now returns boolean; `handleAuthCallback()` checks it before calling `setToken()`, preventing token persistence when hostname is rejected
12
- - **MEDIUM**: Pin external proxy repo clone in CI workflows (`validate-pr`, `test-release`) to commit SHA `4e8f45f` to prevent supply chain attacks
13
- - **LOW**: Remove unnecessary `id-token: write` permission from `claude-code-review` workflow
14
11
 
15
- ## Test plan
16
- - [x] 644/644 unit tests pass
17
- - [x] 225/225 E2E tests pass across all 11 example apps
18
- - [x] Lint clean, build succeeds
19
- - [ ] Validate-PR workflow passes on this PR
12
+ This release adds PTZ (Pan/Tilt/Zoom) camera control support to the toolkit:
20
13
 
21
- 🤖 Generated with [Claude Code](https://claude.com/claude-code)
22
-
23
- #### PR #118: Release v0.3.85 - API coverage docs and workflow security fix
24
- ## Summary
14
+ - **PTZ API functions**: `getPtzPosition()`, `movePtz()`, `getPtzSettings()`, `updatePtzSettings()` with full TypeScript types
15
+ - **PTZ types**: `PtzPosition`, `PtzMove` (discriminated union: position/direction/centerOn), `PtzSettings`, `PtzPreset`, `PtzSettingsUpdate`
16
+ - **vue-ptz example app**: Complete PTZ control application with live video, direction pad, click-to-center, position display, preset management, and API call logging
17
+ - **Camera capabilities**: Added `capabilities` field to `Camera` type for PTZ detection via `include: ['capabilities']`
18
+ - **Documentation**: AI-PTZ.md reference doc, een-ptz-agent, updated AI-CONTEXT.md and CLAUDE.md
19
+ - **E2E tests**: Conditional PTZ API tests that exercise position read, direction move, and preset loading when a PTZ camera is available
25
20
 
26
- - Add EEN API v3.0 coverage documentation (4 documents comparing 211 API endpoints against 51 implemented, 24.2% coverage)
27
- - Add `api-coverage-agent` for on-demand regeneration of coverage docs
28
- - Update README with agent list and coverage section
29
- - Fix workflow_dispatch restriction to production branch (security)
21
+ ### Additional changes
22
+ - Dependabot: CodeQL action bump to 4.32.3
23
+ - CI: Use floating v1 tag for claude-code-action instead of SHA pin
30
24
 
31
25
  ## Commits
32
26
 
33
- - `baa7e1b` feat: add EEN API coverage documentation and agent
34
- - `eea17e8` docs: add missing agents to README agent list
35
- - `bb47cc2` docs: rename een-api-coverage-agent to api-coverage-agent
36
- - `c794fba` fix: restrict workflow_dispatch to production branch to prevent supply chain attack
37
- - `6e782e2` fix: restrict npm-publish workflow_dispatch to production branch
27
+ - `c552fd0` feat: add PTZ camera control API and vue-ptz example app
28
+ - `6a12649` fix: use single getCameras call with include and pagination for PTZ discovery
29
+ - `2b04b26` fix: address review findings in vue-ptz example app
30
+ - `92a18e4` fix: address remaining review findings
31
+ - `4d01c2c` fix: use floating v1 tag for claude-code-action instead of SHA pin
32
+ - `3f197ba` chore(deps): bump github/codeql-action from 4.32.2 to 4.32.3
33
+
34
+ ## Test Results
35
+
36
+ | Check | Result |
37
+ |-------|--------|
38
+ | Lint | Pass (0 errors) |
39
+ | Unit tests | 681 passed (24 suites) |
40
+ | Build | Pass |
41
+ | E2E (12 apps) | All passed |
42
+ | Security review | No vulnerabilities found |
43
+ | Confidential data scan | Clean |
38
44
 
39
- ## Test Results (from PR #117)
45
+ **Version**: 0.3.89
40
46
 
41
- - **Lint**: Passed
42
- - **Unit tests**: 644 passed
43
- - **Build**: Succeeded
44
- - **E2E tests**: 236 passed across all 11 example apps
45
- - **Security review**: No vulnerabilities
46
- - **Code review**: Approved by Claude Sonnet 4.5
47
+ 🤖 Generated with [Claude Code](https://claude.com/claude-code)
48
+
49
+ #### PR #130: Release v0.3.96: PTZ fisheye exclusion and API coverage docs
50
+ ## Summary
51
+ - Add fisheye camera exclusion to PTZ type definitions, agent docs, AI reference docs, and vue-ptz example
52
+ - Add PTZ sub-capability fields (`fisheye`, `panTilt`, `zoom`, `positionMove`, `directionMove`, `centerOnMove`) to `Camera.capabilities.ptz` type
53
+ - Regenerate API coverage docs with full-width layout and scrollbar fix
47
54
 
48
55
  ## Version
56
+ v0.3.96
49
57
 
50
- v0.3.85
58
+ ## Commits
59
+ - `1d9da62` docs: regenerate API coverage docs with full-width layout and scrollbar fix
60
+ - `044c9ae` docs: add fisheye camera exclusion guidance to PTZ agent
61
+ - `f65ff2e` fix: add PTZ sub-capability fields to Camera type and update docs
62
+ - `6ecf253` fix: address review findings for PTZ fisheye guidance
63
+ - `97cf632` fix: exclude fisheye cameras from PTZ selector in vue-ptz example
64
+
65
+ ## Test Results
66
+ - Lint: passed (1 pre-existing warning)
67
+ - Unit tests: 683/683 passed
68
+ - Build: passed
69
+ - E2E: 12/12 example apps passed
70
+ - Security: no vulnerabilities (type/docs changes only)
71
+ - Confidential data scan: clean across 280 changed .md files
51
72
 
52
73
  🤖 Generated with [Claude Code](https://claude.com/claude-code)
53
74
 
54
75
 
55
76
  ### Detailed Changes
56
77
 
57
- #### Features
58
- - feat: add EEN API coverage documentation and agent
59
-
60
78
  #### Bug Fixes
61
- - fix: restrict npm-publish workflow_dispatch to production branch
62
- - fix: restrict workflow_dispatch to production branch to prevent supply chain attack
79
+ - fix: fix sorting bug in coverage table and add undefined fisheye test
80
+ - fix: exclude fisheye cameras from PTZ selector in vue-ptz example
81
+ - fix: address review findings for PTZ fisheye guidance
82
+ - fix: add PTZ sub-capability fields to Camera type and update docs
63
83
 
64
84
  #### Other Changes
65
- - docs: rename een-api-coverage-agent to api-coverage-agent
66
- - docs: add missing agents to README agent list
85
+ - docs: add fisheye camera exclusion guidance to PTZ agent
86
+ - docs: regenerate API coverage docs with full-width layout and scrollbar fix
67
87
 
68
88
  ### Links
69
89
  - [npm package](https://www.npmjs.com/package/een-api-toolkit)
70
- - [Full Changelog](https://github.com/klaushofrichter/een-api-toolkit/compare/v0.3.82...v0.3.85)
90
+ - [Full Changelog](https://github.com/klaushofrichter/een-api-toolkit/compare/v0.3.91...v0.3.97)
71
91
 
72
92
  ---
73
- *Released: 2026-02-17 11:45:53 CST*
93
+ *Released: 2026-02-22 19:53:20 CST*