@aigne/afs-omada 1.11.0-beta.12

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.
@@ -0,0 +1,2076 @@
1
+ const require_client = require('./client.cjs');
2
+ const require_types = require('./types.cjs');
3
+ const require_decorate = require('./_virtual/_@oxc-project_runtime@0.108.0/helpers/decorate.cjs');
4
+ let ufo = require("ufo");
5
+ let _aigne_afs = require("@aigne/afs");
6
+ let _aigne_afs_provider = require("@aigne/afs/provider");
7
+ let zod = require("zod");
8
+
9
+ //#region src/omada-afs.ts
10
+ /** Validate an ID parameter (siteId, ssidId, networkId) is safe for URL construction. */
11
+ function validateIdParam(value, name) {
12
+ if (!/^[\w-]+$/.test(value)) throw new _aigne_afs.AFSNotFoundError(`Invalid ${name}: ${value}`);
13
+ }
14
+ /** Parse write payload content, normalizing JSON parse errors. */
15
+ function parseWritePayload(payload) {
16
+ if (typeof payload.content === "string") try {
17
+ return JSON.parse(payload.content);
18
+ } catch {
19
+ throw new Error("Invalid JSON in write payload");
20
+ }
21
+ return payload.content;
22
+ }
23
+ /** Validate portId is a positive integer. */
24
+ function validatePortId(portId) {
25
+ const num = Number.parseInt(portId, 10);
26
+ if (!Number.isFinite(num) || num < 1 || String(num) !== portId) throw new _aigne_afs.AFSNotFoundError(`Invalid port: ${portId}`);
27
+ return num;
28
+ }
29
+ const ssidWriteSchema = zod.z.object({
30
+ name: zod.z.string().optional(),
31
+ enable: zod.z.boolean().optional(),
32
+ band: zod.z.number().int().min(0).max(2).optional(),
33
+ security: zod.z.string().optional(),
34
+ vlanId: zod.z.number().int().min(0).max(4094).optional(),
35
+ guestNetwork: zod.z.boolean().optional()
36
+ }).strict();
37
+ const wiredNetworkWriteSchema = zod.z.object({
38
+ name: zod.z.string().optional(),
39
+ vlanId: zod.z.number().int().min(0).max(4094).optional(),
40
+ subnet: zod.z.string().optional(),
41
+ gateway: zod.z.string().optional(),
42
+ dhcpEnabled: zod.z.boolean().optional()
43
+ }).strict();
44
+ const wifiOptimizationWriteSchema = zod.z.object({
45
+ autoChannel: zod.z.boolean().optional(),
46
+ roaming: zod.z.boolean().optional(),
47
+ bandSteering: zod.z.boolean().optional()
48
+ }).strict();
49
+ const portConfigWriteSchema = zod.z.object({
50
+ enable: zod.z.boolean().optional(),
51
+ poeEnabled: zod.z.boolean().optional(),
52
+ vlanId: zod.z.number().int().min(0).max(4094).optional(),
53
+ profileName: zod.z.string().optional()
54
+ }).strict();
55
+ const deviceConfigWriteSchema = zod.z.object({
56
+ name: zod.z.string().optional(),
57
+ poeEnabled: zod.z.boolean().optional(),
58
+ txPower: zod.z.number().int().min(0).max(30).optional(),
59
+ channel: zod.z.number().int().min(0).optional()
60
+ }).strict();
61
+ const DEVICE_TYPE_MAP = {
62
+ gateway: "gateways",
63
+ switch: "switches",
64
+ ap: "aps"
65
+ };
66
+ const DEVICE_KIND_MAP = {
67
+ gateways: "network:gateway",
68
+ switches: "network:switch",
69
+ aps: "network:access-point"
70
+ };
71
+ const VALID_DEVICE_CATEGORIES = [
72
+ "gateways",
73
+ "switches",
74
+ "aps"
75
+ ];
76
+ /**
77
+ * AFSOmadaProvider maps TP-Link Omada SDN Controller as an AFS filesystem.
78
+ *
79
+ * Controller -> Sites -> Devices (Gateways/Switches/APs) -> Clients
80
+ * are mapped to a directory hierarchy accessible via standard AFS operations.
81
+ */
82
+ var AFSOmadaProvider = class AFSOmadaProvider extends _aigne_afs_provider.AFSBaseProvider {
83
+ static securityProfiles() {
84
+ return {
85
+ admin: {
86
+ actionPolicy: "full",
87
+ sensitivity: "full"
88
+ },
89
+ user: {
90
+ actionPolicy: "standard",
91
+ sensitiveFields: ["mac", "ip"],
92
+ sensitivity: "redacted"
93
+ },
94
+ guest: {
95
+ actionPolicy: "safe",
96
+ accessMode: "readonly",
97
+ sensitiveFields: ["mac", "ip"],
98
+ sensitivity: "redacted"
99
+ }
100
+ };
101
+ }
102
+ static schema() {
103
+ return require_types.afsOmadaOptionsSchema;
104
+ }
105
+ static manifest() {
106
+ return {
107
+ name: "omada",
108
+ description: "TP-Link Omada SDN Controller — network devices as filesystem.\n- Controller -> Sites -> Devices (Gateways/Switches/APs) -> Clients\n- Read device status, manage ports, view dashboard, configure networks\n- VPN, firewall, routing, NAT, logs, firmware management\n- Path structure: `/sites/{siteId}/devices/{type}/{mac}`",
109
+ uriTemplate: "omada://{host}",
110
+ category: "network",
111
+ schema: zod.z.object({ host: zod.z.string() }),
112
+ tags: [
113
+ "omada",
114
+ "network",
115
+ "sdn",
116
+ "device"
117
+ ],
118
+ capabilityTags: [
119
+ "read-write",
120
+ "crud",
121
+ "search",
122
+ "auth:token",
123
+ "remote",
124
+ "http",
125
+ "on-premise"
126
+ ],
127
+ security: {
128
+ riskLevel: "external",
129
+ resourceAccess: ["internet", "local-network"],
130
+ dataSensitivity: ["system-config"],
131
+ notes: ["Manages network infrastructure — misconfiguration can cause network outages"]
132
+ },
133
+ capabilities: {
134
+ network: { egress: true },
135
+ secrets: ["omada/password"]
136
+ }
137
+ };
138
+ }
139
+ static treeSchema() {
140
+ return {
141
+ operations: [
142
+ "list",
143
+ "read",
144
+ "write",
145
+ "search",
146
+ "exec",
147
+ "stat",
148
+ "explain"
149
+ ],
150
+ tree: {
151
+ "/": {
152
+ kind: "network:controller",
153
+ actions: ["create-site"]
154
+ },
155
+ "/sites": {
156
+ kind: "afs:directory",
157
+ operations: ["list"]
158
+ },
159
+ "/sites/{siteId}": {
160
+ kind: "network:site",
161
+ operations: ["list", "read"]
162
+ },
163
+ "/sites/{siteId}/devices": {
164
+ kind: "network:device-group",
165
+ operations: ["list"]
166
+ },
167
+ "/sites/{siteId}/devices/gateways": {
168
+ kind: "network:device-group",
169
+ operations: ["list"]
170
+ },
171
+ "/sites/{siteId}/devices/gateways/{mac}": {
172
+ kind: "network:gateway",
173
+ operations: [
174
+ "read",
175
+ "write",
176
+ "exec"
177
+ ],
178
+ actions: ["reboot", "upgrade-firmware"],
179
+ destructive: ["reboot"]
180
+ },
181
+ "/sites/{siteId}/devices/gateways/{mac}/firmware": {
182
+ kind: "network:firmware",
183
+ operations: ["read"]
184
+ },
185
+ "/sites/{siteId}/devices/switches": {
186
+ kind: "network:device-group",
187
+ operations: ["list"]
188
+ },
189
+ "/sites/{siteId}/devices/switches/{mac}": {
190
+ kind: "network:switch",
191
+ operations: [
192
+ "read",
193
+ "write",
194
+ "exec"
195
+ ],
196
+ actions: ["reboot", "upgrade-firmware"],
197
+ destructive: ["reboot"]
198
+ },
199
+ "/sites/{siteId}/devices/switches/{mac}/ports": {
200
+ kind: "network:port-group",
201
+ operations: ["list"]
202
+ },
203
+ "/sites/{siteId}/devices/switches/{mac}/firmware": {
204
+ kind: "network:firmware",
205
+ operations: ["read"]
206
+ },
207
+ "/sites/{siteId}/devices/aps": {
208
+ kind: "network:device-group",
209
+ operations: ["list"]
210
+ },
211
+ "/sites/{siteId}/devices/aps/{mac}": {
212
+ kind: "network:access-point",
213
+ operations: [
214
+ "read",
215
+ "write",
216
+ "exec"
217
+ ],
218
+ actions: ["reboot", "upgrade-firmware"],
219
+ destructive: ["reboot"]
220
+ },
221
+ "/sites/{siteId}/devices/aps/{mac}/firmware": {
222
+ kind: "network:firmware",
223
+ operations: ["read"]
224
+ },
225
+ "/sites/{siteId}/clients": {
226
+ kind: "afs:directory",
227
+ operations: ["list"]
228
+ },
229
+ "/sites/{siteId}/clients/{mac}": {
230
+ kind: "network:client",
231
+ operations: ["read", "exec"],
232
+ actions: ["block", "unblock"]
233
+ },
234
+ "/sites/{siteId}/dashboard": {
235
+ kind: "network:dashboard",
236
+ operations: ["read"]
237
+ },
238
+ "/sites/{siteId}/networks": {
239
+ kind: "network:network",
240
+ operations: ["list", "read"]
241
+ },
242
+ "/sites/{siteId}/networks/wireless": {
243
+ kind: "network:wireless",
244
+ operations: ["list"]
245
+ },
246
+ "/sites/{siteId}/networks/wireless/{ssidId}": {
247
+ kind: "network:ssid",
248
+ operations: ["read"]
249
+ },
250
+ "/sites/{siteId}/networks/wired": {
251
+ kind: "network:wired",
252
+ operations: ["list"]
253
+ },
254
+ "/sites/{siteId}/networks/wired/{netId}": {
255
+ kind: "network:vlan",
256
+ operations: ["read"]
257
+ },
258
+ "/sites/{siteId}/networks/wifi-optimization": {
259
+ kind: "network:wifi-optimization",
260
+ operations: ["read"]
261
+ },
262
+ "/sites/{siteId}/vpn": {
263
+ kind: "network:vpn",
264
+ operations: ["read"]
265
+ },
266
+ "/sites/{siteId}/firewall": {
267
+ kind: "network:firewall",
268
+ operations: ["read"]
269
+ },
270
+ "/sites/{siteId}/routing": {
271
+ kind: "network:routing",
272
+ operations: ["read"]
273
+ },
274
+ "/sites/{siteId}/nat": {
275
+ kind: "network:nat",
276
+ operations: ["read"]
277
+ },
278
+ "/sites/{siteId}/logs": {
279
+ kind: "network:logs",
280
+ operations: ["read"]
281
+ }
282
+ },
283
+ auth: {
284
+ type: "custom",
285
+ env: ["OMADA_CLIENT_ID", "OMADA_CLIENT_SECRET"]
286
+ },
287
+ bestFor: [
288
+ "network monitoring",
289
+ "SDN management",
290
+ "device control"
291
+ ],
292
+ notFor: ["file storage", "database queries"]
293
+ };
294
+ }
295
+ static async load({ config } = {}) {
296
+ return new AFSOmadaProvider(require_types.afsOmadaOptionsSchema.parse(config));
297
+ }
298
+ name;
299
+ description;
300
+ accessMode;
301
+ client;
302
+ constructor(options) {
303
+ super();
304
+ const parsed = require_types.afsOmadaOptionsSchema.parse(options);
305
+ this.name = parsed.name;
306
+ this.description = parsed.description;
307
+ this.accessMode = parsed.accessMode;
308
+ this.client = new require_client.OmadaApiClient(parsed.baseUrl, parsed.clientId, parsed.clientSecret, parsed.omadacId, parsed.strictSsl);
309
+ }
310
+ async readCapabilities(_ctx) {
311
+ const manifest = {
312
+ schemaVersion: 1,
313
+ provider: this.name,
314
+ description: this.description || "TP-Link Omada SDN Controller — network devices as filesystem",
315
+ tools: [],
316
+ actions: [],
317
+ operations: this.getOperationsDeclaration()
318
+ };
319
+ return {
320
+ id: "/.meta/.capabilities",
321
+ path: "/.meta/.capabilities",
322
+ content: manifest,
323
+ meta: {
324
+ kind: "afs:capabilities",
325
+ operations: [
326
+ "list",
327
+ "read",
328
+ "stat",
329
+ "explain",
330
+ "search",
331
+ "write",
332
+ "exec",
333
+ "delete"
334
+ ].filter((op) => {
335
+ return manifest.operations[op];
336
+ })
337
+ }
338
+ };
339
+ }
340
+ async listRoot(_ctx) {
341
+ const sites = (await this.client.request("/sites"))?.data ?? [];
342
+ return { data: [this.buildEntry("/sites", { meta: {
343
+ kind: "network:container",
344
+ childrenCount: sites.length
345
+ } })] };
346
+ }
347
+ async readRoot(_ctx) {
348
+ return this.buildEntry("/", {
349
+ content: "Omada SDN Controller",
350
+ meta: {
351
+ kind: "network:controller",
352
+ childrenCount: 1,
353
+ description: "Omada SDN Controller"
354
+ }
355
+ });
356
+ }
357
+ async metaRoot(_ctx) {
358
+ return this.buildEntry("/.meta", { meta: {
359
+ kind: "network:controller",
360
+ childrenCount: 1,
361
+ description: "Omada SDN Controller",
362
+ events: [
363
+ {
364
+ type: "omada:device_reboot",
365
+ description: "Device reboot initiated"
366
+ },
367
+ {
368
+ type: "omada:firmware_upgrade",
369
+ description: "Device firmware upgrade initiated"
370
+ },
371
+ {
372
+ type: "omada:client_blocked",
373
+ description: "Client blocked from network"
374
+ },
375
+ {
376
+ type: "omada:client_unblocked",
377
+ description: "Client unblocked from network"
378
+ },
379
+ {
380
+ type: "omada:network_updated",
381
+ description: "Network configuration updated"
382
+ },
383
+ {
384
+ type: "omada:device_config_updated",
385
+ description: "Device configuration updated"
386
+ }
387
+ ]
388
+ } });
389
+ }
390
+ async statRoot(_ctx) {
391
+ return { data: {
392
+ id: "/",
393
+ path: "/",
394
+ meta: {
395
+ kind: "network:controller",
396
+ childrenCount: 1,
397
+ description: "Omada SDN Controller"
398
+ }
399
+ } };
400
+ }
401
+ async listSites(_ctx) {
402
+ return { data: ((await this.client.request("/sites"))?.data ?? []).map((site) => this.buildEntry((0, ufo.joinURL)("/sites", site.siteId), {
403
+ id: site.siteId,
404
+ meta: {
405
+ kind: "network:site",
406
+ childrenCount: 9,
407
+ description: site.name
408
+ }
409
+ })) };
410
+ }
411
+ async readSites(_ctx) {
412
+ const sites = (await this.client.request("/sites"))?.data ?? [];
413
+ return this.buildEntry("/sites", {
414
+ content: sites.map((s) => `${s.siteId}: ${s.name}`).join("\n"),
415
+ meta: {
416
+ kind: "network:container",
417
+ childrenCount: sites.length
418
+ }
419
+ });
420
+ }
421
+ async metaSites(_ctx) {
422
+ const sites = (await this.client.request("/sites"))?.data ?? [];
423
+ return this.buildEntry("/sites/.meta", { meta: {
424
+ kind: "network:container",
425
+ childrenCount: sites.length
426
+ } });
427
+ }
428
+ async statSites(_ctx) {
429
+ return { data: {
430
+ id: "/sites",
431
+ path: "/sites",
432
+ meta: {
433
+ kind: "network:container",
434
+ childrenCount: ((await this.client.request("/sites"))?.data ?? []).length
435
+ }
436
+ } };
437
+ }
438
+ async listSite(ctx) {
439
+ const { siteId } = ctx.params;
440
+ await this.validateSite(siteId);
441
+ return { data: [
442
+ this.buildEntry((0, ufo.joinURL)("/sites", siteId, "devices"), { meta: {
443
+ kind: "network:device-group",
444
+ childrenCount: 3
445
+ } }),
446
+ this.buildEntry((0, ufo.joinURL)("/sites", siteId, "clients"), { meta: { childrenCount: -1 } }),
447
+ this.buildEntry((0, ufo.joinURL)("/sites", siteId, "dashboard"), { meta: {
448
+ kind: "network:dashboard",
449
+ childrenCount: 0
450
+ } }),
451
+ this.buildEntry((0, ufo.joinURL)("/sites", siteId, "networks"), { meta: {
452
+ kind: "network:network",
453
+ childrenCount: 3
454
+ } }),
455
+ this.buildEntry((0, ufo.joinURL)("/sites", siteId, "vpn"), { meta: {
456
+ kind: "network:vpn",
457
+ childrenCount: 0
458
+ } }),
459
+ this.buildEntry((0, ufo.joinURL)("/sites", siteId, "firewall"), { meta: {
460
+ kind: "network:firewall",
461
+ childrenCount: 0
462
+ } }),
463
+ this.buildEntry((0, ufo.joinURL)("/sites", siteId, "routing"), { meta: {
464
+ kind: "network:routing",
465
+ childrenCount: 0
466
+ } }),
467
+ this.buildEntry((0, ufo.joinURL)("/sites", siteId, "nat"), { meta: {
468
+ kind: "network:nat",
469
+ childrenCount: 0
470
+ } }),
471
+ this.buildEntry((0, ufo.joinURL)("/sites", siteId, "logs"), { meta: {
472
+ kind: "network:logs",
473
+ childrenCount: 0
474
+ } })
475
+ ] };
476
+ }
477
+ async readSite(ctx) {
478
+ const { siteId } = ctx.params;
479
+ const site = await this.getSite(siteId);
480
+ return this.buildEntry((0, ufo.joinURL)("/sites", siteId), {
481
+ id: site.siteId,
482
+ content: `${site.name} (${site.region || "default"})`,
483
+ meta: {
484
+ kind: "network:site",
485
+ childrenCount: 9,
486
+ description: site.name
487
+ }
488
+ });
489
+ }
490
+ async metaSite(ctx) {
491
+ const { siteId } = ctx.params;
492
+ const site = await this.getSite(siteId);
493
+ return this.buildEntry((0, ufo.joinURL)("/sites", siteId, ".meta"), { meta: {
494
+ kind: "network:site",
495
+ childrenCount: 9,
496
+ description: site.name
497
+ } });
498
+ }
499
+ async statSite(ctx) {
500
+ const { siteId } = ctx.params;
501
+ const site = await this.getSite(siteId);
502
+ return { data: {
503
+ id: site.siteId,
504
+ path: (0, ufo.joinURL)("/sites", siteId),
505
+ meta: {
506
+ kind: "network:site",
507
+ childrenCount: 9,
508
+ description: site.name
509
+ }
510
+ } };
511
+ }
512
+ async listDevicesContainer(ctx) {
513
+ const { siteId } = ctx.params;
514
+ await this.validateSite(siteId);
515
+ const devices = await this.getAllDevices(siteId);
516
+ const gateways = devices.filter((d) => DEVICE_TYPE_MAP[d.type] === "gateways");
517
+ const switches = devices.filter((d) => DEVICE_TYPE_MAP[d.type] === "switches");
518
+ const aps = devices.filter((d) => DEVICE_TYPE_MAP[d.type] === "aps");
519
+ return { data: [
520
+ this.buildEntry((0, ufo.joinURL)("/sites", siteId, "devices/gateways"), { meta: {
521
+ kind: "network:device-group",
522
+ childrenCount: gateways.length
523
+ } }),
524
+ this.buildEntry((0, ufo.joinURL)("/sites", siteId, "devices/switches"), { meta: {
525
+ kind: "network:device-group",
526
+ childrenCount: switches.length
527
+ } }),
528
+ this.buildEntry((0, ufo.joinURL)("/sites", siteId, "devices/aps"), { meta: {
529
+ kind: "network:device-group",
530
+ childrenCount: aps.length
531
+ } })
532
+ ] };
533
+ }
534
+ async readDevicesContainer(ctx) {
535
+ const { siteId } = ctx.params;
536
+ await this.validateSite(siteId);
537
+ const devices = await this.getAllDevices(siteId);
538
+ const gateways = devices.filter((d) => DEVICE_TYPE_MAP[d.type] === "gateways");
539
+ const switches = devices.filter((d) => DEVICE_TYPE_MAP[d.type] === "switches");
540
+ const aps = devices.filter((d) => DEVICE_TYPE_MAP[d.type] === "aps");
541
+ return this.buildEntry((0, ufo.joinURL)("/sites", siteId, "devices"), {
542
+ content: `Devices: ${devices.length} total\nGateways: ${gateways.length} | Switches: ${switches.length} | APs: ${aps.length}`,
543
+ meta: {
544
+ kind: "network:device-group",
545
+ childrenCount: 3
546
+ }
547
+ });
548
+ }
549
+ async metaDevicesContainer(ctx) {
550
+ const { siteId } = ctx.params;
551
+ await this.validateSite(siteId);
552
+ return this.buildEntry((0, ufo.joinURL)("/sites", siteId, "devices/.meta"), { meta: {
553
+ kind: "network:device-group",
554
+ childrenCount: 3
555
+ } });
556
+ }
557
+ async statDevicesContainer(ctx) {
558
+ const { siteId } = ctx.params;
559
+ await this.validateSite(siteId);
560
+ return { data: {
561
+ id: (0, ufo.joinURL)("/sites", siteId, "devices"),
562
+ path: (0, ufo.joinURL)("/sites", siteId, "devices"),
563
+ meta: {
564
+ kind: "network:device-group",
565
+ childrenCount: 3
566
+ }
567
+ } };
568
+ }
569
+ async listDeviceCategory(ctx) {
570
+ const { siteId, category } = ctx.params;
571
+ this.validateDeviceCategory(category);
572
+ await this.validateSite(siteId);
573
+ return { data: (await this.getDevicesByCategory(siteId, category)).map((device) => {
574
+ const mac = require_types.normalizeMac(device.mac);
575
+ const kind = DEVICE_KIND_MAP[category];
576
+ const status = require_types.mapDeviceStatus(device.status);
577
+ return this.buildEntry((0, ufo.joinURL)("/sites", siteId, "devices", category, mac), {
578
+ id: mac,
579
+ content: this.formatDeviceContent(device, category),
580
+ meta: {
581
+ kind,
582
+ childrenCount: this.deviceChildrenCount(category),
583
+ model: device.model,
584
+ status,
585
+ firmware: device.firmwareVersion
586
+ }
587
+ });
588
+ }) };
589
+ }
590
+ async readDeviceCategory(ctx) {
591
+ const { siteId, category } = ctx.params;
592
+ this.validateDeviceCategory(category);
593
+ await this.validateSite(siteId);
594
+ const devices = await this.getDevicesByCategory(siteId, category);
595
+ return this.buildEntry((0, ufo.joinURL)("/sites", siteId, "devices", category), {
596
+ content: devices.map((d) => `${require_types.normalizeMac(d.mac)}: ${d.name} (${d.model})`).join("\n"),
597
+ meta: {
598
+ kind: "network:device-group",
599
+ childrenCount: devices.length
600
+ }
601
+ });
602
+ }
603
+ async metaDeviceCategory(ctx) {
604
+ const { siteId, category } = ctx.params;
605
+ this.validateDeviceCategory(category);
606
+ await this.validateSite(siteId);
607
+ const devices = await this.getDevicesByCategory(siteId, category);
608
+ return this.buildEntry((0, ufo.joinURL)("/sites", siteId, "devices", category, ".meta"), { meta: {
609
+ kind: "network:device-group",
610
+ childrenCount: devices.length
611
+ } });
612
+ }
613
+ async statDeviceCategory(ctx) {
614
+ const { siteId, category } = ctx.params;
615
+ this.validateDeviceCategory(category);
616
+ await this.validateSite(siteId);
617
+ const devices = await this.getDevicesByCategory(siteId, category);
618
+ return { data: {
619
+ id: (0, ufo.joinURL)("/sites", siteId, "devices", category),
620
+ path: (0, ufo.joinURL)("/sites", siteId, "devices", category),
621
+ meta: {
622
+ kind: "network:device-group",
623
+ childrenCount: devices.length
624
+ }
625
+ } };
626
+ }
627
+ async listDevice(ctx) {
628
+ const { siteId, category, mac } = ctx.params;
629
+ this.validateDeviceCategory(category);
630
+ const normalizedMac = require_types.normalizeMac(mac);
631
+ await this.getDevice(siteId, category, normalizedMac);
632
+ const basePath = (0, ufo.joinURL)("/sites", siteId, "devices", category, normalizedMac);
633
+ const children = [];
634
+ if (category === "switches") children.push(this.buildEntry((0, ufo.joinURL)(basePath, "ports"), { meta: { kind: "network:port-group" } }));
635
+ children.push(this.buildEntry((0, ufo.joinURL)(basePath, "firmware"), { meta: {
636
+ kind: "network:firmware",
637
+ childrenCount: 0
638
+ } }));
639
+ return { data: children };
640
+ }
641
+ async readDevice(ctx) {
642
+ const { siteId, category, mac } = ctx.params;
643
+ this.validateDeviceCategory(category);
644
+ const normalizedMac = require_types.normalizeMac(mac);
645
+ const device = await this.getDevice(siteId, category, normalizedMac);
646
+ return this.buildEntry((0, ufo.joinURL)("/sites", siteId, "devices", category, normalizedMac), {
647
+ id: normalizedMac,
648
+ content: this.formatDeviceContent(device, category),
649
+ meta: {
650
+ kind: DEVICE_KIND_MAP[category],
651
+ childrenCount: this.deviceChildrenCount(category),
652
+ model: device.model,
653
+ status: require_types.mapDeviceStatus(device.status),
654
+ firmware: device.firmwareVersion
655
+ }
656
+ });
657
+ }
658
+ async metaDevice(ctx) {
659
+ const { siteId, category, mac } = ctx.params;
660
+ this.validateDeviceCategory(category);
661
+ const normalizedMac = require_types.normalizeMac(mac);
662
+ const device = await this.getDevice(siteId, category, normalizedMac);
663
+ return this.buildEntry((0, ufo.joinURL)("/sites", siteId, "devices", category, normalizedMac, ".meta"), { meta: {
664
+ kind: DEVICE_KIND_MAP[category],
665
+ childrenCount: this.deviceChildrenCount(category),
666
+ model: device.model,
667
+ status: require_types.mapDeviceStatus(device.status),
668
+ firmware: device.firmwareVersion
669
+ } });
670
+ }
671
+ async statDevice(ctx) {
672
+ const { siteId, category, mac } = ctx.params;
673
+ this.validateDeviceCategory(category);
674
+ const normalizedMac = require_types.normalizeMac(mac);
675
+ const device = await this.getDevice(siteId, category, normalizedMac);
676
+ return { data: {
677
+ id: normalizedMac,
678
+ path: (0, ufo.joinURL)("/sites", siteId, "devices", category, normalizedMac),
679
+ meta: {
680
+ kind: DEVICE_KIND_MAP[category],
681
+ childrenCount: this.deviceChildrenCount(category),
682
+ model: device.model,
683
+ status: require_types.mapDeviceStatus(device.status),
684
+ firmware: device.firmwareVersion
685
+ }
686
+ } };
687
+ }
688
+ async listClients(ctx) {
689
+ const { siteId } = ctx.params;
690
+ await this.validateSite(siteId);
691
+ return { data: ((await this.client.request((0, ufo.joinURL)("/sites", siteId, "clients")))?.data ?? []).map((c) => {
692
+ const mac = require_types.normalizeMac(c.mac);
693
+ return this.buildEntry((0, ufo.joinURL)("/sites", siteId, "clients", mac), {
694
+ id: mac,
695
+ content: this.formatClientContent(c),
696
+ meta: {
697
+ kind: "network:client",
698
+ childrenCount: 0,
699
+ ip: c.ip,
700
+ ssid: c.ssid
701
+ }
702
+ });
703
+ }) };
704
+ }
705
+ async readClients(ctx) {
706
+ const { siteId } = ctx.params;
707
+ await this.validateSite(siteId);
708
+ const clients = (await this.client.request((0, ufo.joinURL)("/sites", siteId, "clients")))?.data ?? [];
709
+ return this.buildEntry((0, ufo.joinURL)("/sites", siteId, "clients"), {
710
+ content: clients.map((c) => `${require_types.normalizeMac(c.mac)}: ${c.name} (${c.ip})`).join("\n"),
711
+ meta: { childrenCount: -1 }
712
+ });
713
+ }
714
+ async metaClients(ctx) {
715
+ const { siteId } = ctx.params;
716
+ await this.validateSite(siteId);
717
+ return this.buildEntry((0, ufo.joinURL)("/sites", siteId, "clients/.meta"), { meta: { childrenCount: -1 } });
718
+ }
719
+ async statClients(ctx) {
720
+ const { siteId } = ctx.params;
721
+ await this.validateSite(siteId);
722
+ return { data: {
723
+ id: (0, ufo.joinURL)("/sites", siteId, "clients"),
724
+ path: (0, ufo.joinURL)("/sites", siteId, "clients"),
725
+ meta: { childrenCount: -1 }
726
+ } };
727
+ }
728
+ async listClient(ctx) {
729
+ const { siteId, mac } = ctx.params;
730
+ const normalizedMac = require_types.normalizeMac(mac);
731
+ await this.getClient(siteId, normalizedMac);
732
+ return { data: [] };
733
+ }
734
+ async readClient(ctx) {
735
+ const { siteId, mac } = ctx.params;
736
+ const normalizedMac = require_types.normalizeMac(mac);
737
+ const client = await this.getClient(siteId, normalizedMac);
738
+ return this.buildEntry((0, ufo.joinURL)("/sites", siteId, "clients", normalizedMac), {
739
+ id: normalizedMac,
740
+ content: this.formatClientContent(client),
741
+ meta: {
742
+ kind: "network:client",
743
+ childrenCount: 0,
744
+ ip: client.ip,
745
+ ssid: client.ssid
746
+ }
747
+ });
748
+ }
749
+ async metaClient(ctx) {
750
+ const { siteId, mac } = ctx.params;
751
+ const normalizedMac = require_types.normalizeMac(mac);
752
+ const client = await this.getClient(siteId, normalizedMac);
753
+ return this.buildEntry((0, ufo.joinURL)("/sites", siteId, "clients", normalizedMac, ".meta"), { meta: {
754
+ kind: "network:client",
755
+ childrenCount: 0,
756
+ ip: client.ip,
757
+ ssid: client.ssid
758
+ } });
759
+ }
760
+ async statClient(ctx) {
761
+ const { siteId, mac } = ctx.params;
762
+ const normalizedMac = require_types.normalizeMac(mac);
763
+ const client = await this.getClient(siteId, normalizedMac);
764
+ return { data: {
765
+ id: normalizedMac,
766
+ path: (0, ufo.joinURL)("/sites", siteId, "clients", normalizedMac),
767
+ meta: {
768
+ kind: "network:client",
769
+ childrenCount: 0,
770
+ ip: client.ip,
771
+ ssid: client.ssid
772
+ }
773
+ } };
774
+ }
775
+ async listDashboard(ctx) {
776
+ await this.validateSite(ctx.params.siteId);
777
+ return { data: [] };
778
+ }
779
+ async readDashboard(ctx) {
780
+ const { siteId } = ctx.params;
781
+ const site = await this.getSite(siteId);
782
+ const dashboard = await this.client.request((0, ufo.joinURL)("/sites", siteId, "dashboard"));
783
+ const totalDevices = dashboard?.totalDevices ?? 0;
784
+ const connectedDevices = dashboard?.connectedDevices ?? 0;
785
+ const totalClients = dashboard?.totalClients ?? 0;
786
+ const gatewayNum = dashboard?.gatewayNum ?? 0;
787
+ const switchNum = dashboard?.switchNum ?? 0;
788
+ const apNum = dashboard?.apNum ?? 0;
789
+ return this.buildEntry((0, ufo.joinURL)("/sites", siteId, "dashboard"), {
790
+ content: `${site.name} Dashboard\nDevices: ${totalDevices} (${connectedDevices} connected) | Clients: ${totalClients}\nGateways: ${gatewayNum} | Switches: ${switchNum} | APs: ${apNum}`,
791
+ meta: {
792
+ kind: "network:dashboard",
793
+ childrenCount: 0
794
+ }
795
+ });
796
+ }
797
+ async metaDashboard(ctx) {
798
+ const { siteId } = ctx.params;
799
+ await this.validateSite(siteId);
800
+ return this.buildEntry((0, ufo.joinURL)("/sites", siteId, "dashboard/.meta"), { meta: {
801
+ kind: "network:dashboard",
802
+ childrenCount: 0
803
+ } });
804
+ }
805
+ async statDashboard(ctx) {
806
+ const { siteId } = ctx.params;
807
+ await this.validateSite(siteId);
808
+ return { data: {
809
+ id: (0, ufo.joinURL)("/sites", siteId, "dashboard"),
810
+ path: (0, ufo.joinURL)("/sites", siteId, "dashboard"),
811
+ meta: {
812
+ kind: "network:dashboard",
813
+ childrenCount: 0
814
+ }
815
+ } };
816
+ }
817
+ async listNetworks(ctx) {
818
+ const { siteId } = ctx.params;
819
+ await this.validateSite(siteId);
820
+ const ssidCount = (await this.client.request((0, ufo.joinURL)("/sites", siteId, "setting/ssids")))?.data?.length ?? 0;
821
+ const netCount = (await this.client.request((0, ufo.joinURL)("/sites", siteId, "setting/lan/networks")))?.data?.length ?? 0;
822
+ return { data: [
823
+ this.buildEntry((0, ufo.joinURL)("/sites", siteId, "networks/wireless"), { meta: {
824
+ kind: "network:wireless",
825
+ childrenCount: ssidCount
826
+ } }),
827
+ this.buildEntry((0, ufo.joinURL)("/sites", siteId, "networks/wired"), { meta: {
828
+ kind: "network:wired",
829
+ childrenCount: netCount
830
+ } }),
831
+ this.buildEntry((0, ufo.joinURL)("/sites", siteId, "networks/wifi-optimization"), { meta: {
832
+ kind: "network:wifi-optimization",
833
+ childrenCount: 0
834
+ } })
835
+ ] };
836
+ }
837
+ async readNetworks(ctx) {
838
+ const { siteId } = ctx.params;
839
+ await this.validateSite(siteId);
840
+ return this.buildEntry((0, ufo.joinURL)("/sites", siteId, "networks"), {
841
+ content: "Network configuration summary",
842
+ meta: {
843
+ kind: "network:network",
844
+ childrenCount: 3
845
+ }
846
+ });
847
+ }
848
+ async metaNetworks(ctx) {
849
+ const { siteId } = ctx.params;
850
+ await this.validateSite(siteId);
851
+ return this.buildEntry((0, ufo.joinURL)("/sites", siteId, "networks/.meta"), { meta: {
852
+ kind: "network:network",
853
+ childrenCount: 3
854
+ } });
855
+ }
856
+ async statNetworks(ctx) {
857
+ const { siteId } = ctx.params;
858
+ await this.validateSite(siteId);
859
+ return { data: {
860
+ id: (0, ufo.joinURL)("/sites", siteId, "networks"),
861
+ path: (0, ufo.joinURL)("/sites", siteId, "networks"),
862
+ meta: {
863
+ kind: "network:network",
864
+ childrenCount: 3
865
+ }
866
+ } };
867
+ }
868
+ async listWirelessSsids(ctx) {
869
+ const { siteId } = ctx.params;
870
+ await this.validateSite(siteId);
871
+ return { data: ((await this.client.request((0, ufo.joinURL)("/sites", siteId, "setting/ssids")))?.data ?? []).map((ssid) => this.buildEntry((0, ufo.joinURL)("/sites", siteId, "networks/wireless", ssid.id), {
872
+ id: ssid.id,
873
+ content: this.formatSsidContent(ssid),
874
+ meta: {
875
+ kind: "network:ssid",
876
+ name: ssid.name,
877
+ band: this.mapBand(ssid.band),
878
+ security: ssid.security,
879
+ vlanId: ssid.vlanId,
880
+ enabled: ssid.enable,
881
+ childrenCount: 0
882
+ }
883
+ })) };
884
+ }
885
+ async readWireless(ctx) {
886
+ const { siteId } = ctx.params;
887
+ await this.validateSite(siteId);
888
+ const ssids = (await this.client.request((0, ufo.joinURL)("/sites", siteId, "setting/ssids")))?.data ?? [];
889
+ return this.buildEntry((0, ufo.joinURL)("/sites", siteId, "networks/wireless"), {
890
+ content: ssids.map((s) => `${s.id}: ${s.name} (${this.mapBand(s.band)})`).join("\n"),
891
+ meta: {
892
+ kind: "network:wireless",
893
+ childrenCount: ssids.length
894
+ }
895
+ });
896
+ }
897
+ async metaWireless(ctx) {
898
+ const { siteId } = ctx.params;
899
+ await this.validateSite(siteId);
900
+ const ssids = (await this.client.request((0, ufo.joinURL)("/sites", siteId, "setting/ssids")))?.data ?? [];
901
+ return this.buildEntry((0, ufo.joinURL)("/sites", siteId, "networks/wireless/.meta"), { meta: {
902
+ kind: "network:wireless",
903
+ childrenCount: ssids.length
904
+ } });
905
+ }
906
+ async statWireless(ctx) {
907
+ const { siteId } = ctx.params;
908
+ await this.validateSite(siteId);
909
+ const ssids = (await this.client.request((0, ufo.joinURL)("/sites", siteId, "setting/ssids")))?.data ?? [];
910
+ return { data: {
911
+ id: (0, ufo.joinURL)("/sites", siteId, "networks/wireless"),
912
+ path: (0, ufo.joinURL)("/sites", siteId, "networks/wireless"),
913
+ meta: {
914
+ kind: "network:wireless",
915
+ childrenCount: ssids.length
916
+ }
917
+ } };
918
+ }
919
+ async readSsid(ctx) {
920
+ const { siteId, ssidId } = ctx.params;
921
+ await this.validateSite(siteId);
922
+ const ssid = await this.getSsid(siteId, ssidId);
923
+ return this.buildEntry((0, ufo.joinURL)("/sites", siteId, "networks/wireless", ssidId), {
924
+ id: ssidId,
925
+ content: this.formatSsidContent(ssid),
926
+ meta: {
927
+ kind: "network:ssid",
928
+ name: ssid.name,
929
+ band: this.mapBand(ssid.band),
930
+ security: ssid.security,
931
+ vlanId: ssid.vlanId,
932
+ enabled: ssid.enable,
933
+ childrenCount: 0
934
+ }
935
+ });
936
+ }
937
+ async listSsid(ctx) {
938
+ const { siteId, ssidId } = ctx.params;
939
+ await this.validateSite(siteId);
940
+ await this.getSsid(siteId, ssidId);
941
+ return { data: [] };
942
+ }
943
+ async metaSsid(ctx) {
944
+ const { siteId, ssidId } = ctx.params;
945
+ await this.validateSite(siteId);
946
+ const ssid = await this.getSsid(siteId, ssidId);
947
+ return this.buildEntry((0, ufo.joinURL)("/sites", siteId, "networks/wireless", ssidId, ".meta"), { meta: {
948
+ kind: "network:ssid",
949
+ name: ssid.name,
950
+ childrenCount: 0
951
+ } });
952
+ }
953
+ async statSsid(ctx) {
954
+ const { siteId, ssidId } = ctx.params;
955
+ await this.validateSite(siteId);
956
+ const ssid = await this.getSsid(siteId, ssidId);
957
+ return { data: {
958
+ id: ssidId,
959
+ path: (0, ufo.joinURL)("/sites", siteId, "networks/wireless", ssidId),
960
+ meta: {
961
+ kind: "network:ssid",
962
+ name: ssid.name,
963
+ childrenCount: 0
964
+ }
965
+ } };
966
+ }
967
+ async writeSsid(ctx, payload) {
968
+ const { siteId, ssidId } = ctx.params;
969
+ await this.validateSite(siteId);
970
+ await this.getSsid(siteId, ssidId);
971
+ const raw = parseWritePayload(payload);
972
+ const config = ssidWriteSchema.parse(raw);
973
+ await this.client.patch((0, ufo.joinURL)("/sites", siteId, "setting/ssids", ssidId), config);
974
+ this.emit({
975
+ type: "omada:network_updated",
976
+ path: (0, ufo.joinURL)("/sites", siteId, "networks/wireless", ssidId),
977
+ data: {
978
+ siteId,
979
+ ssidId,
980
+ networkType: "wireless"
981
+ }
982
+ });
983
+ return {
984
+ data: this.buildEntry((0, ufo.joinURL)("/sites", siteId, "networks/wireless", ssidId), {
985
+ content: JSON.stringify(config),
986
+ meta: { kind: "network:ssid" }
987
+ }),
988
+ message: "SSID config updated"
989
+ };
990
+ }
991
+ async listWiredNetworks(ctx) {
992
+ const { siteId } = ctx.params;
993
+ await this.validateSite(siteId);
994
+ return { data: ((await this.client.request((0, ufo.joinURL)("/sites", siteId, "setting/lan/networks")))?.data ?? []).map((net) => this.buildEntry((0, ufo.joinURL)("/sites", siteId, "networks/wired", net.id), {
995
+ id: net.id,
996
+ content: this.formatWiredNetworkContent(net),
997
+ meta: {
998
+ kind: "network:vlan",
999
+ name: net.name,
1000
+ vlanId: net.vlanId,
1001
+ subnet: net.subnet,
1002
+ childrenCount: 0
1003
+ }
1004
+ })) };
1005
+ }
1006
+ async readWired(ctx) {
1007
+ const { siteId } = ctx.params;
1008
+ await this.validateSite(siteId);
1009
+ const networks = (await this.client.request((0, ufo.joinURL)("/sites", siteId, "setting/lan/networks")))?.data ?? [];
1010
+ return this.buildEntry((0, ufo.joinURL)("/sites", siteId, "networks/wired"), {
1011
+ content: networks.map((n) => `${n.id}: ${n.name} (VLAN ${n.vlanId})`).join("\n"),
1012
+ meta: {
1013
+ kind: "network:wired",
1014
+ childrenCount: networks.length
1015
+ }
1016
+ });
1017
+ }
1018
+ async metaWired(ctx) {
1019
+ const { siteId } = ctx.params;
1020
+ await this.validateSite(siteId);
1021
+ const networks = (await this.client.request((0, ufo.joinURL)("/sites", siteId, "setting/lan/networks")))?.data ?? [];
1022
+ return this.buildEntry((0, ufo.joinURL)("/sites", siteId, "networks/wired/.meta"), { meta: {
1023
+ kind: "network:wired",
1024
+ childrenCount: networks.length
1025
+ } });
1026
+ }
1027
+ async statWired(ctx) {
1028
+ const { siteId } = ctx.params;
1029
+ await this.validateSite(siteId);
1030
+ const networks = (await this.client.request((0, ufo.joinURL)("/sites", siteId, "setting/lan/networks")))?.data ?? [];
1031
+ return { data: {
1032
+ id: (0, ufo.joinURL)("/sites", siteId, "networks/wired"),
1033
+ path: (0, ufo.joinURL)("/sites", siteId, "networks/wired"),
1034
+ meta: {
1035
+ kind: "network:wired",
1036
+ childrenCount: networks.length
1037
+ }
1038
+ } };
1039
+ }
1040
+ async readWiredNetwork(ctx) {
1041
+ const { siteId, networkId } = ctx.params;
1042
+ await this.validateSite(siteId);
1043
+ const net = await this.getWiredNetwork(siteId, networkId);
1044
+ return this.buildEntry((0, ufo.joinURL)("/sites", siteId, "networks/wired", networkId), {
1045
+ id: networkId,
1046
+ content: this.formatWiredNetworkContent(net),
1047
+ meta: {
1048
+ kind: "network:vlan",
1049
+ name: net.name,
1050
+ vlanId: net.vlanId,
1051
+ subnet: net.subnet,
1052
+ childrenCount: 0
1053
+ }
1054
+ });
1055
+ }
1056
+ async listWiredNetwork(ctx) {
1057
+ const { siteId, networkId } = ctx.params;
1058
+ await this.validateSite(siteId);
1059
+ await this.getWiredNetwork(siteId, networkId);
1060
+ return { data: [] };
1061
+ }
1062
+ async metaWiredNetwork(ctx) {
1063
+ const { siteId, networkId } = ctx.params;
1064
+ await this.validateSite(siteId);
1065
+ const net = await this.getWiredNetwork(siteId, networkId);
1066
+ return this.buildEntry((0, ufo.joinURL)("/sites", siteId, "networks/wired", networkId, ".meta"), { meta: {
1067
+ kind: "network:vlan",
1068
+ name: net.name,
1069
+ childrenCount: 0
1070
+ } });
1071
+ }
1072
+ async statWiredNetwork(ctx) {
1073
+ const { siteId, networkId } = ctx.params;
1074
+ await this.validateSite(siteId);
1075
+ const net = await this.getWiredNetwork(siteId, networkId);
1076
+ return { data: {
1077
+ id: networkId,
1078
+ path: (0, ufo.joinURL)("/sites", siteId, "networks/wired", networkId),
1079
+ meta: {
1080
+ kind: "network:vlan",
1081
+ name: net.name,
1082
+ childrenCount: 0
1083
+ }
1084
+ } };
1085
+ }
1086
+ async writeWiredNetwork(ctx, payload) {
1087
+ const { siteId, networkId } = ctx.params;
1088
+ await this.validateSite(siteId);
1089
+ await this.getWiredNetwork(siteId, networkId);
1090
+ const raw = parseWritePayload(payload);
1091
+ const config = wiredNetworkWriteSchema.parse(raw);
1092
+ await this.client.patch((0, ufo.joinURL)("/sites", siteId, "setting/lan/networks", networkId), config);
1093
+ return {
1094
+ data: this.buildEntry((0, ufo.joinURL)("/sites", siteId, "networks/wired", networkId), {
1095
+ content: JSON.stringify(config),
1096
+ meta: { kind: "network:vlan" }
1097
+ }),
1098
+ message: "Wired network config updated"
1099
+ };
1100
+ }
1101
+ async listWifiOptimization(ctx) {
1102
+ await this.validateSite(ctx.params.siteId);
1103
+ return { data: [] };
1104
+ }
1105
+ async readWifiOptimization(ctx) {
1106
+ const { siteId } = ctx.params;
1107
+ await this.validateSite(siteId);
1108
+ const opt = await this.client.request((0, ufo.joinURL)("/sites", siteId, "setting/wlan/optimization"));
1109
+ const lines = [
1110
+ `Auto Channel: ${opt?.autoChannel ? "enabled" : "disabled"}`,
1111
+ `Roaming: ${opt?.roaming ? "enabled" : "disabled"}`,
1112
+ `Band Steering: ${opt?.bandSteering ? "enabled" : "disabled"}`
1113
+ ];
1114
+ return this.buildEntry((0, ufo.joinURL)("/sites", siteId, "networks/wifi-optimization"), {
1115
+ content: lines.join("\n"),
1116
+ meta: {
1117
+ kind: "network:wifi-optimization",
1118
+ childrenCount: 0
1119
+ }
1120
+ });
1121
+ }
1122
+ async metaWifiOptimization(ctx) {
1123
+ const { siteId } = ctx.params;
1124
+ await this.validateSite(siteId);
1125
+ return this.buildEntry((0, ufo.joinURL)("/sites", siteId, "networks/wifi-optimization/.meta"), { meta: {
1126
+ kind: "network:wifi-optimization",
1127
+ childrenCount: 0
1128
+ } });
1129
+ }
1130
+ async statWifiOptimization(ctx) {
1131
+ const { siteId } = ctx.params;
1132
+ await this.validateSite(siteId);
1133
+ return { data: {
1134
+ id: (0, ufo.joinURL)("/sites", siteId, "networks/wifi-optimization"),
1135
+ path: (0, ufo.joinURL)("/sites", siteId, "networks/wifi-optimization"),
1136
+ meta: {
1137
+ kind: "network:wifi-optimization",
1138
+ childrenCount: 0
1139
+ }
1140
+ } };
1141
+ }
1142
+ async writeWifiOptimization(ctx, payload) {
1143
+ const { siteId } = ctx.params;
1144
+ await this.validateSite(siteId);
1145
+ const raw = parseWritePayload(payload);
1146
+ const config = wifiOptimizationWriteSchema.parse(raw);
1147
+ await this.client.patch((0, ufo.joinURL)("/sites", siteId, "setting/wlan/optimization"), config);
1148
+ return {
1149
+ data: this.buildEntry((0, ufo.joinURL)("/sites", siteId, "networks/wifi-optimization"), {
1150
+ content: JSON.stringify(config),
1151
+ meta: { kind: "network:wifi-optimization" }
1152
+ }),
1153
+ message: "WiFi optimization config updated"
1154
+ };
1155
+ }
1156
+ async listVpn(ctx) {
1157
+ await this.validateSite(ctx.params.siteId);
1158
+ return { data: [] };
1159
+ }
1160
+ async readVpn(ctx) {
1161
+ const { siteId } = ctx.params;
1162
+ await this.validateSite(siteId);
1163
+ const vpn = await this.client.request((0, ufo.joinURL)("/sites", siteId, "setting/vpn"));
1164
+ const lines = [
1165
+ `IPsec: ${vpn?.ipsec?.enabled ? "enabled" : "disabled"}`,
1166
+ `L2TP: ${vpn?.l2tp?.enabled ? "enabled" : "disabled"}`,
1167
+ `WireGuard: ${vpn?.wireguard?.enabled ? "enabled" : "disabled"}`
1168
+ ];
1169
+ return this.buildEntry((0, ufo.joinURL)("/sites", siteId, "vpn"), {
1170
+ content: lines.join("\n"),
1171
+ meta: {
1172
+ kind: "network:vpn",
1173
+ childrenCount: 0
1174
+ }
1175
+ });
1176
+ }
1177
+ async metaVpn(ctx) {
1178
+ const { siteId } = ctx.params;
1179
+ await this.validateSite(siteId);
1180
+ return this.buildEntry((0, ufo.joinURL)("/sites", siteId, "vpn/.meta"), { meta: {
1181
+ kind: "network:vpn",
1182
+ childrenCount: 0
1183
+ } });
1184
+ }
1185
+ async statVpn(ctx) {
1186
+ const { siteId } = ctx.params;
1187
+ await this.validateSite(siteId);
1188
+ return { data: {
1189
+ id: (0, ufo.joinURL)("/sites", siteId, "vpn"),
1190
+ path: (0, ufo.joinURL)("/sites", siteId, "vpn"),
1191
+ meta: {
1192
+ kind: "network:vpn",
1193
+ childrenCount: 0
1194
+ }
1195
+ } };
1196
+ }
1197
+ async listFirewall(ctx) {
1198
+ await this.validateSite(ctx.params.siteId);
1199
+ return { data: [] };
1200
+ }
1201
+ async readFirewall(ctx) {
1202
+ const { siteId } = ctx.params;
1203
+ await this.validateSite(siteId);
1204
+ const rules = (await this.client.request((0, ufo.joinURL)("/sites", siteId, "setting/firewall/acl")))?.data ?? [];
1205
+ return this.buildEntry((0, ufo.joinURL)("/sites", siteId, "firewall"), {
1206
+ content: `Firewall ACL rules: ${rules.length}`,
1207
+ meta: {
1208
+ kind: "network:firewall",
1209
+ childrenCount: 0,
1210
+ ruleCount: rules.length
1211
+ }
1212
+ });
1213
+ }
1214
+ async metaFirewall(ctx) {
1215
+ const { siteId } = ctx.params;
1216
+ await this.validateSite(siteId);
1217
+ return this.buildEntry((0, ufo.joinURL)("/sites", siteId, "firewall/.meta"), { meta: {
1218
+ kind: "network:firewall",
1219
+ childrenCount: 0
1220
+ } });
1221
+ }
1222
+ async statFirewall(ctx) {
1223
+ const { siteId } = ctx.params;
1224
+ await this.validateSite(siteId);
1225
+ return { data: {
1226
+ id: (0, ufo.joinURL)("/sites", siteId, "firewall"),
1227
+ path: (0, ufo.joinURL)("/sites", siteId, "firewall"),
1228
+ meta: {
1229
+ kind: "network:firewall",
1230
+ childrenCount: 0
1231
+ }
1232
+ } };
1233
+ }
1234
+ async listRouting(ctx) {
1235
+ await this.validateSite(ctx.params.siteId);
1236
+ return { data: [] };
1237
+ }
1238
+ async readRouting(ctx) {
1239
+ const { siteId } = ctx.params;
1240
+ await this.validateSite(siteId);
1241
+ const routing = await this.client.request((0, ufo.joinURL)("/sites", siteId, "setting/routing"));
1242
+ const staticCount = routing?.staticRoutes?.length ?? 0;
1243
+ const policyCount = routing?.policyRoutes?.length ?? 0;
1244
+ return this.buildEntry((0, ufo.joinURL)("/sites", siteId, "routing"), {
1245
+ content: `Static routes: ${staticCount} | Policy routes: ${policyCount}`,
1246
+ meta: {
1247
+ kind: "network:routing",
1248
+ childrenCount: 0
1249
+ }
1250
+ });
1251
+ }
1252
+ async metaRouting(ctx) {
1253
+ const { siteId } = ctx.params;
1254
+ await this.validateSite(siteId);
1255
+ return this.buildEntry((0, ufo.joinURL)("/sites", siteId, "routing/.meta"), { meta: {
1256
+ kind: "network:routing",
1257
+ childrenCount: 0
1258
+ } });
1259
+ }
1260
+ async statRouting(ctx) {
1261
+ const { siteId } = ctx.params;
1262
+ await this.validateSite(siteId);
1263
+ return { data: {
1264
+ id: (0, ufo.joinURL)("/sites", siteId, "routing"),
1265
+ path: (0, ufo.joinURL)("/sites", siteId, "routing"),
1266
+ meta: {
1267
+ kind: "network:routing",
1268
+ childrenCount: 0
1269
+ }
1270
+ } };
1271
+ }
1272
+ async listNat(ctx) {
1273
+ await this.validateSite(ctx.params.siteId);
1274
+ return { data: [] };
1275
+ }
1276
+ async readNat(ctx) {
1277
+ const { siteId } = ctx.params;
1278
+ await this.validateSite(siteId);
1279
+ const rules = (await this.client.request((0, ufo.joinURL)("/sites", siteId, "setting/nat")))?.data ?? [];
1280
+ return this.buildEntry((0, ufo.joinURL)("/sites", siteId, "nat"), {
1281
+ content: `NAT rules: ${rules.length}`,
1282
+ meta: {
1283
+ kind: "network:nat",
1284
+ childrenCount: 0,
1285
+ ruleCount: rules.length
1286
+ }
1287
+ });
1288
+ }
1289
+ async metaNat(ctx) {
1290
+ const { siteId } = ctx.params;
1291
+ await this.validateSite(siteId);
1292
+ return this.buildEntry((0, ufo.joinURL)("/sites", siteId, "nat/.meta"), { meta: {
1293
+ kind: "network:nat",
1294
+ childrenCount: 0
1295
+ } });
1296
+ }
1297
+ async statNat(ctx) {
1298
+ const { siteId } = ctx.params;
1299
+ await this.validateSite(siteId);
1300
+ return { data: {
1301
+ id: (0, ufo.joinURL)("/sites", siteId, "nat"),
1302
+ path: (0, ufo.joinURL)("/sites", siteId, "nat"),
1303
+ meta: {
1304
+ kind: "network:nat",
1305
+ childrenCount: 0
1306
+ }
1307
+ } };
1308
+ }
1309
+ async listLogs(ctx) {
1310
+ await this.validateSite(ctx.params.siteId);
1311
+ return { data: [] };
1312
+ }
1313
+ async readLogs(ctx) {
1314
+ const { siteId } = ctx.params;
1315
+ await this.validateSite(siteId);
1316
+ const entries = (await this.client.request((0, ufo.joinURL)("/sites", siteId, "logs")))?.data ?? [];
1317
+ const content = entries.map((e) => `[${new Date(e.timestamp).toISOString()}] ${e.level}: ${e.message}`).join("\n");
1318
+ return this.buildEntry((0, ufo.joinURL)("/sites", siteId, "logs"), {
1319
+ content: content || "No log entries",
1320
+ meta: {
1321
+ kind: "network:logs",
1322
+ childrenCount: 0,
1323
+ entryCount: entries.length
1324
+ }
1325
+ });
1326
+ }
1327
+ async metaLogs(ctx) {
1328
+ const { siteId } = ctx.params;
1329
+ await this.validateSite(siteId);
1330
+ return this.buildEntry((0, ufo.joinURL)("/sites", siteId, "logs/.meta"), { meta: {
1331
+ kind: "network:logs",
1332
+ childrenCount: 0
1333
+ } });
1334
+ }
1335
+ async statLogs(ctx) {
1336
+ const { siteId } = ctx.params;
1337
+ await this.validateSite(siteId);
1338
+ return { data: {
1339
+ id: (0, ufo.joinURL)("/sites", siteId, "logs"),
1340
+ path: (0, ufo.joinURL)("/sites", siteId, "logs"),
1341
+ meta: {
1342
+ kind: "network:logs",
1343
+ childrenCount: 0
1344
+ }
1345
+ } };
1346
+ }
1347
+ async readSwitchPorts(ctx) {
1348
+ const { siteId, mac } = ctx.params;
1349
+ const normalizedMac = require_types.normalizeMac(mac);
1350
+ await this.getDevice(siteId, "switches", normalizedMac);
1351
+ const ports = await this.getSwitchPorts(siteId, normalizedMac);
1352
+ return this.buildEntry((0, ufo.joinURL)("/sites", siteId, "devices/switches", normalizedMac, "ports"), {
1353
+ content: ports.map((p) => `Port ${p.port}: ${p.name} (${p.linkSpeed})`).join("\n"),
1354
+ meta: {
1355
+ kind: "network:port-group",
1356
+ childrenCount: ports.length
1357
+ }
1358
+ });
1359
+ }
1360
+ async metaSwitchPorts(ctx) {
1361
+ const { siteId, mac } = ctx.params;
1362
+ const normalizedMac = require_types.normalizeMac(mac);
1363
+ await this.getDevice(siteId, "switches", normalizedMac);
1364
+ const ports = await this.getSwitchPorts(siteId, normalizedMac);
1365
+ return this.buildEntry((0, ufo.joinURL)("/sites", siteId, "devices/switches", normalizedMac, "ports/.meta"), { meta: {
1366
+ kind: "network:port-group",
1367
+ childrenCount: ports.length
1368
+ } });
1369
+ }
1370
+ async statSwitchPorts(ctx) {
1371
+ const { siteId, mac } = ctx.params;
1372
+ const normalizedMac = require_types.normalizeMac(mac);
1373
+ await this.getDevice(siteId, "switches", normalizedMac);
1374
+ const ports = await this.getSwitchPorts(siteId, normalizedMac);
1375
+ return { data: {
1376
+ id: (0, ufo.joinURL)("/sites", siteId, "devices/switches", normalizedMac, "ports"),
1377
+ path: (0, ufo.joinURL)("/sites", siteId, "devices/switches", normalizedMac, "ports"),
1378
+ meta: {
1379
+ kind: "network:port-group",
1380
+ childrenCount: ports.length
1381
+ }
1382
+ } };
1383
+ }
1384
+ async listSwitchPorts(ctx) {
1385
+ const { siteId, mac } = ctx.params;
1386
+ const normalizedMac = require_types.normalizeMac(mac);
1387
+ await this.getDevice(siteId, "switches", normalizedMac);
1388
+ return { data: (await this.getSwitchPorts(siteId, normalizedMac)).map((port) => this.buildEntry((0, ufo.joinURL)("/sites", siteId, "devices/switches", normalizedMac, "ports", String(port.port)), {
1389
+ id: String(port.port),
1390
+ content: this.formatPortContent(port),
1391
+ meta: {
1392
+ kind: "network:port",
1393
+ port: port.port,
1394
+ childrenCount: 0,
1395
+ linkSpeed: port.linkSpeed,
1396
+ poeEnabled: port.poeEnabled,
1397
+ vlanId: port.vlanId
1398
+ }
1399
+ })) };
1400
+ }
1401
+ async listNonSwitchPorts(ctx) {
1402
+ const { category } = ctx.params;
1403
+ if (category === "switches") return { data: [] };
1404
+ throw new _aigne_afs.AFSNotFoundError(`Ports are only available on switches, not ${category}`);
1405
+ }
1406
+ async readSwitchPort(ctx) {
1407
+ const { siteId, mac, portId } = ctx.params;
1408
+ const normalizedMac = require_types.normalizeMac(mac);
1409
+ await this.getDevice(siteId, "switches", normalizedMac);
1410
+ const port = await this.getSwitchPort(siteId, normalizedMac, validatePortId(portId));
1411
+ return this.buildEntry((0, ufo.joinURL)("/sites", siteId, "devices/switches", normalizedMac, "ports", portId), {
1412
+ id: portId,
1413
+ content: this.formatPortContent(port),
1414
+ meta: {
1415
+ kind: "network:port",
1416
+ port: port.port,
1417
+ childrenCount: 0,
1418
+ linkSpeed: port.linkSpeed,
1419
+ poeEnabled: port.poeEnabled,
1420
+ vlanId: port.vlanId
1421
+ }
1422
+ });
1423
+ }
1424
+ async listSwitchPort(ctx) {
1425
+ const { siteId, mac, portId } = ctx.params;
1426
+ const normalizedMac = require_types.normalizeMac(mac);
1427
+ await this.getSwitchPort(siteId, normalizedMac, validatePortId(portId));
1428
+ return { data: [] };
1429
+ }
1430
+ async metaSwitchPort(ctx) {
1431
+ const { siteId, mac, portId } = ctx.params;
1432
+ const normalizedMac = require_types.normalizeMac(mac);
1433
+ const port = await this.getSwitchPort(siteId, normalizedMac, validatePortId(portId));
1434
+ return this.buildEntry((0, ufo.joinURL)("/sites", siteId, "devices/switches", normalizedMac, "ports", portId, ".meta"), { meta: {
1435
+ kind: "network:port",
1436
+ port: port.port,
1437
+ childrenCount: 0
1438
+ } });
1439
+ }
1440
+ async statSwitchPort(ctx) {
1441
+ const { siteId, mac, portId } = ctx.params;
1442
+ const normalizedMac = require_types.normalizeMac(mac);
1443
+ const port = await this.getSwitchPort(siteId, normalizedMac, validatePortId(portId));
1444
+ return { data: {
1445
+ id: portId,
1446
+ path: (0, ufo.joinURL)("/sites", siteId, "devices/switches", normalizedMac, "ports", portId),
1447
+ meta: {
1448
+ kind: "network:port",
1449
+ port: port.port,
1450
+ childrenCount: 0
1451
+ }
1452
+ } };
1453
+ }
1454
+ async readSwitchPortConfig(ctx) {
1455
+ const { siteId, mac, portId } = ctx.params;
1456
+ const normalizedMac = require_types.normalizeMac(mac);
1457
+ const port = await this.getSwitchPort(siteId, normalizedMac, validatePortId(portId));
1458
+ const config = {
1459
+ enable: port.enable,
1460
+ poeEnabled: port.poeEnabled,
1461
+ vlanId: port.vlanId,
1462
+ profileName: port.profileName
1463
+ };
1464
+ return this.buildEntry((0, ufo.joinURL)("/sites", siteId, "devices/switches", normalizedMac, "ports", portId, "config"), {
1465
+ content: JSON.stringify(config),
1466
+ meta: { kind: "network:port-config" }
1467
+ });
1468
+ }
1469
+ async writeSwitchPortConfig(ctx, payload) {
1470
+ const { siteId, mac, portId } = ctx.params;
1471
+ const normalizedMac = require_types.normalizeMac(mac);
1472
+ await this.getSwitchPort(siteId, normalizedMac, validatePortId(portId));
1473
+ const raw = parseWritePayload(payload);
1474
+ const config = portConfigWriteSchema.parse(raw);
1475
+ await this.client.patch((0, ufo.joinURL)("/sites", siteId, "devices", normalizedMac, "ports", portId), config);
1476
+ return {
1477
+ data: this.buildEntry((0, ufo.joinURL)("/sites", siteId, "devices/switches", normalizedMac, "ports", portId, "config"), {
1478
+ content: JSON.stringify(config),
1479
+ meta: { kind: "network:port-config" }
1480
+ }),
1481
+ message: "Port config updated"
1482
+ };
1483
+ }
1484
+ async listFirmware(ctx) {
1485
+ const { siteId, category, mac } = ctx.params;
1486
+ this.validateDeviceCategory(category);
1487
+ const normalizedMac = require_types.normalizeMac(mac);
1488
+ await this.getDevice(siteId, category, normalizedMac);
1489
+ return { data: [] };
1490
+ }
1491
+ async readFirmware(ctx) {
1492
+ const { siteId, category, mac } = ctx.params;
1493
+ this.validateDeviceCategory(category);
1494
+ const normalizedMac = require_types.normalizeMac(mac);
1495
+ await this.getDevice(siteId, category, normalizedMac);
1496
+ const fw = await this.client.request((0, ufo.joinURL)("/sites", siteId, "devices", normalizedMac, "firmware"));
1497
+ const lines = [
1498
+ `Current: ${fw?.currentVersion ?? "unknown"}`,
1499
+ `Latest: ${fw?.latestVersion ?? "unknown"}`,
1500
+ `Update available: ${fw?.hasUpdate ? "yes" : "no"}`
1501
+ ];
1502
+ return this.buildEntry((0, ufo.joinURL)("/sites", siteId, "devices", category, normalizedMac, "firmware"), {
1503
+ content: lines.join("\n"),
1504
+ meta: {
1505
+ kind: "network:firmware",
1506
+ childrenCount: 0,
1507
+ currentVersion: fw?.currentVersion,
1508
+ latestVersion: fw?.latestVersion,
1509
+ hasUpdate: fw?.hasUpdate ?? false
1510
+ }
1511
+ });
1512
+ }
1513
+ async metaFirmware(ctx) {
1514
+ const { siteId, category, mac } = ctx.params;
1515
+ this.validateDeviceCategory(category);
1516
+ const normalizedMac = require_types.normalizeMac(mac);
1517
+ await this.getDevice(siteId, category, normalizedMac);
1518
+ return this.buildEntry((0, ufo.joinURL)("/sites", siteId, "devices", category, normalizedMac, "firmware/.meta"), { meta: {
1519
+ kind: "network:firmware",
1520
+ childrenCount: 0
1521
+ } });
1522
+ }
1523
+ async statFirmware(ctx) {
1524
+ const { siteId, category, mac } = ctx.params;
1525
+ this.validateDeviceCategory(category);
1526
+ const normalizedMac = require_types.normalizeMac(mac);
1527
+ await this.getDevice(siteId, category, normalizedMac);
1528
+ return { data: {
1529
+ id: (0, ufo.joinURL)("/sites", siteId, "devices", category, normalizedMac, "firmware"),
1530
+ path: (0, ufo.joinURL)("/sites", siteId, "devices", category, normalizedMac, "firmware"),
1531
+ meta: {
1532
+ kind: "network:firmware",
1533
+ childrenCount: 0
1534
+ }
1535
+ } };
1536
+ }
1537
+ async explainRoot(_ctx) {
1538
+ const sites = (await this.client.request("/sites"))?.data ?? [];
1539
+ let totalDevices = 0;
1540
+ for (const site of sites) try {
1541
+ const dashboard = await this.client.request((0, ufo.joinURL)("/sites", site.siteId, "dashboard"));
1542
+ totalDevices += dashboard?.totalDevices ?? 0;
1543
+ } catch {}
1544
+ return {
1545
+ content: [
1546
+ "# Omada SDN Controller",
1547
+ "",
1548
+ `**Sites:** ${sites.length}`,
1549
+ `**Total Devices:** ${totalDevices}`,
1550
+ "",
1551
+ "## Sites",
1552
+ "",
1553
+ ...sites.map((s) => `- **${s.name}** (${s.siteId})`)
1554
+ ].join("\n"),
1555
+ format: "markdown"
1556
+ };
1557
+ }
1558
+ async explainSite(ctx) {
1559
+ const { siteId } = ctx.params;
1560
+ const site = await this.getSite(siteId);
1561
+ const dashboard = await this.client.request((0, ufo.joinURL)("/sites", siteId, "dashboard"));
1562
+ const clientCount = (await this.client.request((0, ufo.joinURL)("/sites", siteId, "clients")))?.data?.length ?? 0;
1563
+ return {
1564
+ content: [
1565
+ `# ${site.name}`,
1566
+ "",
1567
+ `**Site ID:** ${siteId}`,
1568
+ `**Devices:** ${dashboard?.totalDevices ?? 0} (${dashboard?.connectedDevices ?? 0} connected)`,
1569
+ `**Clients:** ${clientCount}`,
1570
+ `**Gateways:** ${dashboard?.gatewayNum ?? 0}`,
1571
+ `**Switches:** ${dashboard?.switchNum ?? 0}`,
1572
+ `**APs:** ${dashboard?.apNum ?? 0}`
1573
+ ].join("\n"),
1574
+ format: "markdown"
1575
+ };
1576
+ }
1577
+ async explainSiteChild(ctx) {
1578
+ const { siteId } = ctx.params;
1579
+ await this.validateSite(siteId);
1580
+ return {
1581
+ content: `Path: ${ctx.path}`,
1582
+ format: "text"
1583
+ };
1584
+ }
1585
+ async searchAll(ctx, query, options) {
1586
+ const basePath = ctx.params.path ? `/${ctx.params.path}` : "/";
1587
+ const searchQuery = query.toLowerCase();
1588
+ const limit = options?.limit ?? 100;
1589
+ const results = [];
1590
+ let sitesToSearch = [];
1591
+ const allSites = (await this.client.request("/sites"))?.data ?? [];
1592
+ const siteMatch = basePath.match(/^\/sites\/([^/]+)/);
1593
+ if (siteMatch) {
1594
+ const matchedSite = allSites.find((s) => s.siteId === siteMatch[1]);
1595
+ if (!matchedSite) throw new _aigne_afs.AFSNotFoundError(basePath);
1596
+ sitesToSearch = [matchedSite];
1597
+ } else sitesToSearch = allSites;
1598
+ for (const site of sitesToSearch) {
1599
+ if (results.length >= limit) break;
1600
+ const devices = await this.getAllDevices(site.siteId);
1601
+ for (const device of devices) {
1602
+ if (results.length >= limit) break;
1603
+ const mac = require_types.normalizeMac(device.mac);
1604
+ const category = DEVICE_TYPE_MAP[device.type] || "unknown";
1605
+ if ([
1606
+ device.name,
1607
+ device.model,
1608
+ mac,
1609
+ device.firmwareVersion
1610
+ ].join(" ").toLowerCase().includes(searchQuery)) results.push(this.buildEntry((0, ufo.joinURL)("/sites", site.siteId, "devices", category, mac), {
1611
+ id: mac,
1612
+ content: this.formatDeviceContent(device, category),
1613
+ meta: {
1614
+ kind: DEVICE_KIND_MAP[category],
1615
+ childrenCount: 0,
1616
+ model: device.model,
1617
+ status: require_types.mapDeviceStatus(device.status),
1618
+ firmware: device.firmwareVersion
1619
+ }
1620
+ }));
1621
+ }
1622
+ const clients = (await this.client.request((0, ufo.joinURL)("/sites", site.siteId, "clients")))?.data ?? [];
1623
+ for (const c of clients) {
1624
+ if (results.length >= limit) break;
1625
+ const mac = require_types.normalizeMac(c.mac);
1626
+ if ([
1627
+ c.name,
1628
+ c.ip,
1629
+ mac,
1630
+ c.ssid
1631
+ ].join(" ").toLowerCase().includes(searchQuery)) results.push(this.buildEntry((0, ufo.joinURL)("/sites", site.siteId, "clients", mac), {
1632
+ id: mac,
1633
+ content: this.formatClientContent(c),
1634
+ meta: {
1635
+ kind: "network:client",
1636
+ childrenCount: 0,
1637
+ ip: c.ip,
1638
+ ssid: c.ssid
1639
+ }
1640
+ }));
1641
+ }
1642
+ }
1643
+ return { data: results };
1644
+ }
1645
+ async listRootActions(_ctx) {
1646
+ return { data: [this.buildEntry("/.actions/create-site", {
1647
+ id: "create-site",
1648
+ meta: {
1649
+ kind: "network:action",
1650
+ name: "create-site",
1651
+ severity: "boundary",
1652
+ description: "Create a new site on the Omada controller"
1653
+ }
1654
+ })] };
1655
+ }
1656
+ async execCreateSite(_ctx, args) {
1657
+ const name = args.name;
1658
+ if (!name) throw new Error("create-site requires 'name' argument");
1659
+ const region = args.region || "default";
1660
+ const result = await this.client.post("/sites", {
1661
+ name,
1662
+ region
1663
+ });
1664
+ return {
1665
+ success: true,
1666
+ data: {
1667
+ siteId: result.siteId,
1668
+ name: result.name
1669
+ }
1670
+ };
1671
+ }
1672
+ async listDeviceActions(ctx) {
1673
+ const { siteId, category, mac } = ctx.params;
1674
+ this.validateDeviceCategory(category);
1675
+ const normalizedMac = require_types.normalizeMac(mac);
1676
+ await this.getDevice(siteId, category, normalizedMac);
1677
+ const basePath = (0, ufo.joinURL)("/sites", siteId, "devices", category, normalizedMac);
1678
+ return { data: [this.buildEntry((0, ufo.joinURL)(basePath, ".actions/reboot"), {
1679
+ id: "reboot",
1680
+ meta: {
1681
+ kind: "network:action",
1682
+ name: "reboot",
1683
+ severity: "boundary",
1684
+ description: "Reboot this device"
1685
+ }
1686
+ }), this.buildEntry((0, ufo.joinURL)(basePath, ".actions/upgrade-firmware"), {
1687
+ id: "upgrade-firmware",
1688
+ meta: {
1689
+ kind: "network:action",
1690
+ name: "upgrade-firmware",
1691
+ severity: "critical",
1692
+ description: "Upgrade this device's firmware to latest version"
1693
+ }
1694
+ })] };
1695
+ }
1696
+ async execDeviceReboot(ctx) {
1697
+ const { siteId, category, mac } = ctx.params;
1698
+ this.validateDeviceCategory(category);
1699
+ const normalizedMac = require_types.normalizeMac(mac);
1700
+ await this.getDevice(siteId, category, normalizedMac);
1701
+ await this.client.post((0, ufo.joinURL)("/sites", siteId, "cmd/devices", normalizedMac, "reboot"));
1702
+ this.emit({
1703
+ type: "omada:device_reboot",
1704
+ path: (0, ufo.joinURL)("/sites", siteId, "devices", category, normalizedMac),
1705
+ data: {
1706
+ mac: normalizedMac,
1707
+ siteId
1708
+ }
1709
+ });
1710
+ return {
1711
+ success: true,
1712
+ data: {
1713
+ mac: normalizedMac,
1714
+ action: "reboot"
1715
+ }
1716
+ };
1717
+ }
1718
+ async execDeviceUpgradeFirmware(ctx) {
1719
+ const { siteId, category, mac } = ctx.params;
1720
+ this.validateDeviceCategory(category);
1721
+ const normalizedMac = require_types.normalizeMac(mac);
1722
+ await this.getDevice(siteId, category, normalizedMac);
1723
+ await this.client.post((0, ufo.joinURL)("/sites", siteId, "cmd/devices", normalizedMac, "upgrade"));
1724
+ this.emit({
1725
+ type: "omada:firmware_upgrade",
1726
+ path: (0, ufo.joinURL)("/sites", siteId, "devices", category, normalizedMac),
1727
+ data: {
1728
+ mac: normalizedMac,
1729
+ siteId
1730
+ }
1731
+ });
1732
+ return {
1733
+ success: true,
1734
+ data: {
1735
+ mac: normalizedMac,
1736
+ action: "upgrade-firmware"
1737
+ }
1738
+ };
1739
+ }
1740
+ async listClientActions(ctx) {
1741
+ const { siteId, mac } = ctx.params;
1742
+ const normalizedMac = require_types.normalizeMac(mac);
1743
+ await this.getClient(siteId, normalizedMac);
1744
+ const basePath = (0, ufo.joinURL)("/sites", siteId, "clients", normalizedMac);
1745
+ return { data: [this.buildEntry((0, ufo.joinURL)(basePath, ".actions/block"), {
1746
+ id: "block",
1747
+ meta: {
1748
+ kind: "network:action",
1749
+ name: "block",
1750
+ severity: "boundary",
1751
+ description: "Block this client"
1752
+ }
1753
+ }), this.buildEntry((0, ufo.joinURL)(basePath, ".actions/unblock"), {
1754
+ id: "unblock",
1755
+ meta: {
1756
+ kind: "network:action",
1757
+ name: "unblock",
1758
+ severity: "boundary",
1759
+ description: "Unblock this client"
1760
+ }
1761
+ })] };
1762
+ }
1763
+ async execClientBlock(ctx) {
1764
+ const { siteId, mac } = ctx.params;
1765
+ const normalizedMac = require_types.normalizeMac(mac);
1766
+ await this.getClient(siteId, normalizedMac);
1767
+ await this.client.post((0, ufo.joinURL)("/sites", siteId, "cmd/clients", normalizedMac, "block"));
1768
+ this.emit({
1769
+ type: "omada:client_blocked",
1770
+ path: (0, ufo.joinURL)("/sites", siteId, "clients", normalizedMac),
1771
+ data: {
1772
+ mac: normalizedMac,
1773
+ siteId
1774
+ }
1775
+ });
1776
+ return {
1777
+ success: true,
1778
+ data: {
1779
+ mac: normalizedMac,
1780
+ action: "block"
1781
+ }
1782
+ };
1783
+ }
1784
+ async execClientUnblock(ctx) {
1785
+ const { siteId, mac } = ctx.params;
1786
+ const normalizedMac = require_types.normalizeMac(mac);
1787
+ await this.getClient(siteId, normalizedMac);
1788
+ await this.client.post((0, ufo.joinURL)("/sites", siteId, "cmd/clients", normalizedMac, "unblock"));
1789
+ this.emit({
1790
+ type: "omada:client_unblocked",
1791
+ path: (0, ufo.joinURL)("/sites", siteId, "clients", normalizedMac),
1792
+ data: {
1793
+ mac: normalizedMac,
1794
+ siteId
1795
+ }
1796
+ });
1797
+ return {
1798
+ success: true,
1799
+ data: {
1800
+ mac: normalizedMac,
1801
+ action: "unblock"
1802
+ }
1803
+ };
1804
+ }
1805
+ async readDeviceConfig(ctx) {
1806
+ const { siteId, category, mac } = ctx.params;
1807
+ this.validateDeviceCategory(category);
1808
+ const normalizedMac = require_types.normalizeMac(mac);
1809
+ const device = await this.getDevice(siteId, category, normalizedMac);
1810
+ const configData = {
1811
+ name: device.name,
1812
+ model: device.model,
1813
+ firmwareVersion: device.firmwareVersion
1814
+ };
1815
+ return this.buildEntry((0, ufo.joinURL)("/sites", siteId, "devices", category, normalizedMac, "config"), {
1816
+ content: JSON.stringify(configData),
1817
+ meta: { kind: "network:config" }
1818
+ });
1819
+ }
1820
+ async writeDeviceConfig(ctx, payload) {
1821
+ const { siteId, category, mac } = ctx.params;
1822
+ this.validateDeviceCategory(category);
1823
+ const normalizedMac = require_types.normalizeMac(mac);
1824
+ await this.getDevice(siteId, category, normalizedMac);
1825
+ const raw = parseWritePayload(payload);
1826
+ const config = deviceConfigWriteSchema.parse(raw);
1827
+ await this.client.patch((0, ufo.joinURL)("/sites", siteId, "devices", normalizedMac), config);
1828
+ this.emit({
1829
+ type: "omada:device_config_updated",
1830
+ path: (0, ufo.joinURL)("/sites", siteId, "devices", category, normalizedMac),
1831
+ data: {
1832
+ mac: normalizedMac,
1833
+ siteId,
1834
+ category
1835
+ }
1836
+ });
1837
+ return {
1838
+ data: this.buildEntry((0, ufo.joinURL)("/sites", siteId, "devices", category, normalizedMac, "config"), {
1839
+ content: JSON.stringify(config),
1840
+ meta: { kind: "network:config" }
1841
+ }),
1842
+ message: "Device config updated"
1843
+ };
1844
+ }
1845
+ async getSite(siteId) {
1846
+ validateIdParam(siteId, "siteId");
1847
+ const site = ((await this.client.request("/sites"))?.data ?? []).find((s) => s.siteId === siteId);
1848
+ if (!site) throw new _aigne_afs.AFSNotFoundError((0, ufo.joinURL)("/sites", siteId));
1849
+ return site;
1850
+ }
1851
+ async validateSite(siteId) {
1852
+ await this.getSite(siteId);
1853
+ }
1854
+ validateDeviceCategory(category) {
1855
+ if (!VALID_DEVICE_CATEGORIES.includes(category)) throw new _aigne_afs.AFSNotFoundError(`Invalid device category: ${category}. Valid: ${VALID_DEVICE_CATEGORIES.join(", ")}`);
1856
+ }
1857
+ async getAllDevices(siteId) {
1858
+ return (await this.client.request((0, ufo.joinURL)("/sites", siteId, "devices")))?.data ?? [];
1859
+ }
1860
+ async getDevicesByCategory(siteId, category) {
1861
+ return (await this.getAllDevices(siteId)).filter((d) => DEVICE_TYPE_MAP[d.type] === category);
1862
+ }
1863
+ async getDevice(siteId, category, normalizedMac) {
1864
+ const device = (await this.getDevicesByCategory(siteId, category)).find((d) => require_types.normalizeMac(d.mac) === normalizedMac);
1865
+ if (!device) throw new _aigne_afs.AFSNotFoundError((0, ufo.joinURL)("/sites", siteId, "devices", category, normalizedMac));
1866
+ return device;
1867
+ }
1868
+ async getClient(siteId, normalizedMac) {
1869
+ const client = ((await this.client.request((0, ufo.joinURL)("/sites", siteId, "clients")))?.data ?? []).find((c) => require_types.normalizeMac(c.mac) === normalizedMac);
1870
+ if (!client) throw new _aigne_afs.AFSNotFoundError((0, ufo.joinURL)("/sites", siteId, "clients", normalizedMac));
1871
+ return client;
1872
+ }
1873
+ formatDeviceContent(device, category) {
1874
+ const status = require_types.mapDeviceStatus(device.status);
1875
+ const lines = [`${device.name} \u2014 ${device.model} (${status})`];
1876
+ if (category === "gateways") {
1877
+ const cpu = device.cpuUtil ?? 0;
1878
+ const mem = device.memUtil ?? 0;
1879
+ const uptime = device.uptime ?? "unknown";
1880
+ lines.push(`CPU: ${cpu}% | Mem: ${mem}% | Uptime: ${uptime}`);
1881
+ } else if (category === "switches") {
1882
+ if (device.poeRemain !== void 0) lines.push(`PoE remaining: ${device.poeRemain}W`);
1883
+ } else if (category === "aps") {
1884
+ const parts = [];
1885
+ if (device.radioSetting2g) parts.push(`2.4G: ch${device.radioSetting2g.channel} @${device.radioSetting2g.txPower}dBm`);
1886
+ if (device.radioSetting5g) parts.push(`5G: ch${device.radioSetting5g.channel} @${device.radioSetting5g.txPower}dBm`);
1887
+ if (parts.length > 0) lines.push(parts.join(" | "));
1888
+ }
1889
+ return lines.join("\n");
1890
+ }
1891
+ formatClientContent(client) {
1892
+ const lines = [`${client.name} \u2014 ${client.ip}`];
1893
+ const parts = [];
1894
+ if (client.ssid) parts.push(`SSID: ${client.ssid}`);
1895
+ if (client.signalLevel !== void 0) parts.push(`Signal: ${client.signalLevel}dBm`);
1896
+ if (parts.length > 0) lines.push(parts.join(" | "));
1897
+ return lines.join("\n");
1898
+ }
1899
+ async getSsid(siteId, ssidId) {
1900
+ validateIdParam(ssidId, "ssidId");
1901
+ const ssid = ((await this.client.request((0, ufo.joinURL)("/sites", siteId, "setting/ssids")))?.data ?? []).find((s) => s.id === ssidId);
1902
+ if (!ssid) throw new _aigne_afs.AFSNotFoundError((0, ufo.joinURL)("/sites", siteId, "networks/wireless", ssidId));
1903
+ return ssid;
1904
+ }
1905
+ async getWiredNetwork(siteId, networkId) {
1906
+ validateIdParam(networkId, "networkId");
1907
+ const net = ((await this.client.request((0, ufo.joinURL)("/sites", siteId, "setting/lan/networks")))?.data ?? []).find((n) => n.id === networkId);
1908
+ if (!net) throw new _aigne_afs.AFSNotFoundError((0, ufo.joinURL)("/sites", siteId, "networks/wired", networkId));
1909
+ return net;
1910
+ }
1911
+ mapBand(band) {
1912
+ switch (band) {
1913
+ case 0: return "2.4GHz";
1914
+ case 1: return "2.4GHz+5GHz";
1915
+ case 2: return "5GHz";
1916
+ default: return `unknown(${band})`;
1917
+ }
1918
+ }
1919
+ formatSsidContent(ssid) {
1920
+ return [`${ssid.name} \u2014 ${this.mapBand(ssid.band)}`, `Security: ${ssid.security} | VLAN: ${ssid.vlanId} | Guest: ${ssid.guestNetwork ? "yes" : "no"}`].join("\n");
1921
+ }
1922
+ deviceChildrenCount(category) {
1923
+ return category === "switches" ? 2 : 1;
1924
+ }
1925
+ async getSwitchPorts(siteId, normalizedMac) {
1926
+ return (await this.client.request((0, ufo.joinURL)("/sites", siteId, "devices", normalizedMac, "ports")))?.data ?? [];
1927
+ }
1928
+ async getSwitchPort(siteId, normalizedMac, portId) {
1929
+ const port = (await this.getSwitchPorts(siteId, normalizedMac)).find((p) => p.port === portId);
1930
+ if (!port) throw new _aigne_afs.AFSNotFoundError((0, ufo.joinURL)("/sites", siteId, "devices/switches", normalizedMac, "ports", String(portId)));
1931
+ return port;
1932
+ }
1933
+ formatPortContent(port) {
1934
+ return [`${port.name} \u2014 ${port.linkSpeed} (${port.duplex})`, `VLAN: ${port.vlanId} | PoE: ${port.poeEnabled ? `enabled (${port.poePower}W)` : "disabled"}`].join("\n");
1935
+ }
1936
+ formatWiredNetworkContent(net) {
1937
+ return [`${net.name} \u2014 VLAN ${net.vlanId}`, `Subnet: ${net.subnet} | Gateway: ${net.gateway} | DHCP: ${net.dhcpEnabled ? "enabled" : "disabled"}`].join("\n");
1938
+ }
1939
+ };
1940
+ require_decorate.__decorate([(0, _aigne_afs_provider.Read)("/.meta/.capabilities")], AFSOmadaProvider.prototype, "readCapabilities", null);
1941
+ require_decorate.__decorate([(0, _aigne_afs_provider.List)("/")], AFSOmadaProvider.prototype, "listRoot", null);
1942
+ require_decorate.__decorate([(0, _aigne_afs_provider.Read)("/")], AFSOmadaProvider.prototype, "readRoot", null);
1943
+ require_decorate.__decorate([(0, _aigne_afs_provider.Meta)("/")], AFSOmadaProvider.prototype, "metaRoot", null);
1944
+ require_decorate.__decorate([(0, _aigne_afs_provider.Stat)("/")], AFSOmadaProvider.prototype, "statRoot", null);
1945
+ require_decorate.__decorate([(0, _aigne_afs_provider.List)("/sites")], AFSOmadaProvider.prototype, "listSites", null);
1946
+ require_decorate.__decorate([(0, _aigne_afs_provider.Read)("/sites")], AFSOmadaProvider.prototype, "readSites", null);
1947
+ require_decorate.__decorate([(0, _aigne_afs_provider.Meta)("/sites")], AFSOmadaProvider.prototype, "metaSites", null);
1948
+ require_decorate.__decorate([(0, _aigne_afs_provider.Stat)("/sites")], AFSOmadaProvider.prototype, "statSites", null);
1949
+ require_decorate.__decorate([(0, _aigne_afs_provider.List)("/sites/:siteId")], AFSOmadaProvider.prototype, "listSite", null);
1950
+ require_decorate.__decorate([(0, _aigne_afs_provider.Read)("/sites/:siteId")], AFSOmadaProvider.prototype, "readSite", null);
1951
+ require_decorate.__decorate([(0, _aigne_afs_provider.Meta)("/sites/:siteId")], AFSOmadaProvider.prototype, "metaSite", null);
1952
+ require_decorate.__decorate([(0, _aigne_afs_provider.Stat)("/sites/:siteId")], AFSOmadaProvider.prototype, "statSite", null);
1953
+ require_decorate.__decorate([(0, _aigne_afs_provider.List)("/sites/:siteId/devices")], AFSOmadaProvider.prototype, "listDevicesContainer", null);
1954
+ require_decorate.__decorate([(0, _aigne_afs_provider.Read)("/sites/:siteId/devices")], AFSOmadaProvider.prototype, "readDevicesContainer", null);
1955
+ require_decorate.__decorate([(0, _aigne_afs_provider.Meta)("/sites/:siteId/devices")], AFSOmadaProvider.prototype, "metaDevicesContainer", null);
1956
+ require_decorate.__decorate([(0, _aigne_afs_provider.Stat)("/sites/:siteId/devices")], AFSOmadaProvider.prototype, "statDevicesContainer", null);
1957
+ require_decorate.__decorate([(0, _aigne_afs_provider.List)("/sites/:siteId/devices/:category")], AFSOmadaProvider.prototype, "listDeviceCategory", null);
1958
+ require_decorate.__decorate([(0, _aigne_afs_provider.Read)("/sites/:siteId/devices/:category")], AFSOmadaProvider.prototype, "readDeviceCategory", null);
1959
+ require_decorate.__decorate([(0, _aigne_afs_provider.Meta)("/sites/:siteId/devices/:category")], AFSOmadaProvider.prototype, "metaDeviceCategory", null);
1960
+ require_decorate.__decorate([(0, _aigne_afs_provider.Stat)("/sites/:siteId/devices/:category")], AFSOmadaProvider.prototype, "statDeviceCategory", null);
1961
+ require_decorate.__decorate([(0, _aigne_afs_provider.List)("/sites/:siteId/devices/:category/:mac")], AFSOmadaProvider.prototype, "listDevice", null);
1962
+ require_decorate.__decorate([(0, _aigne_afs_provider.Read)("/sites/:siteId/devices/:category/:mac")], AFSOmadaProvider.prototype, "readDevice", null);
1963
+ require_decorate.__decorate([(0, _aigne_afs_provider.Meta)("/sites/:siteId/devices/:category/:mac")], AFSOmadaProvider.prototype, "metaDevice", null);
1964
+ require_decorate.__decorate([(0, _aigne_afs_provider.Stat)("/sites/:siteId/devices/:category/:mac")], AFSOmadaProvider.prototype, "statDevice", null);
1965
+ require_decorate.__decorate([(0, _aigne_afs_provider.List)("/sites/:siteId/clients")], AFSOmadaProvider.prototype, "listClients", null);
1966
+ require_decorate.__decorate([(0, _aigne_afs_provider.Read)("/sites/:siteId/clients")], AFSOmadaProvider.prototype, "readClients", null);
1967
+ require_decorate.__decorate([(0, _aigne_afs_provider.Meta)("/sites/:siteId/clients")], AFSOmadaProvider.prototype, "metaClients", null);
1968
+ require_decorate.__decorate([(0, _aigne_afs_provider.Stat)("/sites/:siteId/clients")], AFSOmadaProvider.prototype, "statClients", null);
1969
+ require_decorate.__decorate([(0, _aigne_afs_provider.List)("/sites/:siteId/clients/:mac")], AFSOmadaProvider.prototype, "listClient", null);
1970
+ require_decorate.__decorate([(0, _aigne_afs_provider.Read)("/sites/:siteId/clients/:mac")], AFSOmadaProvider.prototype, "readClient", null);
1971
+ require_decorate.__decorate([(0, _aigne_afs_provider.Meta)("/sites/:siteId/clients/:mac")], AFSOmadaProvider.prototype, "metaClient", null);
1972
+ require_decorate.__decorate([(0, _aigne_afs_provider.Stat)("/sites/:siteId/clients/:mac")], AFSOmadaProvider.prototype, "statClient", null);
1973
+ require_decorate.__decorate([(0, _aigne_afs_provider.List)("/sites/:siteId/dashboard")], AFSOmadaProvider.prototype, "listDashboard", null);
1974
+ require_decorate.__decorate([(0, _aigne_afs_provider.Read)("/sites/:siteId/dashboard")], AFSOmadaProvider.prototype, "readDashboard", null);
1975
+ require_decorate.__decorate([(0, _aigne_afs_provider.Meta)("/sites/:siteId/dashboard")], AFSOmadaProvider.prototype, "metaDashboard", null);
1976
+ require_decorate.__decorate([(0, _aigne_afs_provider.Stat)("/sites/:siteId/dashboard")], AFSOmadaProvider.prototype, "statDashboard", null);
1977
+ require_decorate.__decorate([(0, _aigne_afs_provider.List)("/sites/:siteId/networks")], AFSOmadaProvider.prototype, "listNetworks", null);
1978
+ require_decorate.__decorate([(0, _aigne_afs_provider.Read)("/sites/:siteId/networks")], AFSOmadaProvider.prototype, "readNetworks", null);
1979
+ require_decorate.__decorate([(0, _aigne_afs_provider.Meta)("/sites/:siteId/networks")], AFSOmadaProvider.prototype, "metaNetworks", null);
1980
+ require_decorate.__decorate([(0, _aigne_afs_provider.Stat)("/sites/:siteId/networks")], AFSOmadaProvider.prototype, "statNetworks", null);
1981
+ require_decorate.__decorate([(0, _aigne_afs_provider.List)("/sites/:siteId/networks/wireless")], AFSOmadaProvider.prototype, "listWirelessSsids", null);
1982
+ require_decorate.__decorate([(0, _aigne_afs_provider.Read)("/sites/:siteId/networks/wireless")], AFSOmadaProvider.prototype, "readWireless", null);
1983
+ require_decorate.__decorate([(0, _aigne_afs_provider.Meta)("/sites/:siteId/networks/wireless")], AFSOmadaProvider.prototype, "metaWireless", null);
1984
+ require_decorate.__decorate([(0, _aigne_afs_provider.Stat)("/sites/:siteId/networks/wireless")], AFSOmadaProvider.prototype, "statWireless", null);
1985
+ require_decorate.__decorate([(0, _aigne_afs_provider.Read)("/sites/:siteId/networks/wireless/:ssidId")], AFSOmadaProvider.prototype, "readSsid", null);
1986
+ require_decorate.__decorate([(0, _aigne_afs_provider.List)("/sites/:siteId/networks/wireless/:ssidId")], AFSOmadaProvider.prototype, "listSsid", null);
1987
+ require_decorate.__decorate([(0, _aigne_afs_provider.Meta)("/sites/:siteId/networks/wireless/:ssidId")], AFSOmadaProvider.prototype, "metaSsid", null);
1988
+ require_decorate.__decorate([(0, _aigne_afs_provider.Stat)("/sites/:siteId/networks/wireless/:ssidId")], AFSOmadaProvider.prototype, "statSsid", null);
1989
+ require_decorate.__decorate([(0, _aigne_afs_provider.Write)("/sites/:siteId/networks/wireless/:ssidId")], AFSOmadaProvider.prototype, "writeSsid", null);
1990
+ require_decorate.__decorate([(0, _aigne_afs_provider.List)("/sites/:siteId/networks/wired")], AFSOmadaProvider.prototype, "listWiredNetworks", null);
1991
+ require_decorate.__decorate([(0, _aigne_afs_provider.Read)("/sites/:siteId/networks/wired")], AFSOmadaProvider.prototype, "readWired", null);
1992
+ require_decorate.__decorate([(0, _aigne_afs_provider.Meta)("/sites/:siteId/networks/wired")], AFSOmadaProvider.prototype, "metaWired", null);
1993
+ require_decorate.__decorate([(0, _aigne_afs_provider.Stat)("/sites/:siteId/networks/wired")], AFSOmadaProvider.prototype, "statWired", null);
1994
+ require_decorate.__decorate([(0, _aigne_afs_provider.Read)("/sites/:siteId/networks/wired/:networkId")], AFSOmadaProvider.prototype, "readWiredNetwork", null);
1995
+ require_decorate.__decorate([(0, _aigne_afs_provider.List)("/sites/:siteId/networks/wired/:networkId")], AFSOmadaProvider.prototype, "listWiredNetwork", null);
1996
+ require_decorate.__decorate([(0, _aigne_afs_provider.Meta)("/sites/:siteId/networks/wired/:networkId")], AFSOmadaProvider.prototype, "metaWiredNetwork", null);
1997
+ require_decorate.__decorate([(0, _aigne_afs_provider.Stat)("/sites/:siteId/networks/wired/:networkId")], AFSOmadaProvider.prototype, "statWiredNetwork", null);
1998
+ require_decorate.__decorate([(0, _aigne_afs_provider.Write)("/sites/:siteId/networks/wired/:networkId")], AFSOmadaProvider.prototype, "writeWiredNetwork", null);
1999
+ require_decorate.__decorate([(0, _aigne_afs_provider.List)("/sites/:siteId/networks/wifi-optimization")], AFSOmadaProvider.prototype, "listWifiOptimization", null);
2000
+ require_decorate.__decorate([(0, _aigne_afs_provider.Read)("/sites/:siteId/networks/wifi-optimization")], AFSOmadaProvider.prototype, "readWifiOptimization", null);
2001
+ require_decorate.__decorate([(0, _aigne_afs_provider.Meta)("/sites/:siteId/networks/wifi-optimization")], AFSOmadaProvider.prototype, "metaWifiOptimization", null);
2002
+ require_decorate.__decorate([(0, _aigne_afs_provider.Stat)("/sites/:siteId/networks/wifi-optimization")], AFSOmadaProvider.prototype, "statWifiOptimization", null);
2003
+ require_decorate.__decorate([(0, _aigne_afs_provider.Write)("/sites/:siteId/networks/wifi-optimization")], AFSOmadaProvider.prototype, "writeWifiOptimization", null);
2004
+ require_decorate.__decorate([(0, _aigne_afs_provider.List)("/sites/:siteId/vpn")], AFSOmadaProvider.prototype, "listVpn", null);
2005
+ require_decorate.__decorate([(0, _aigne_afs_provider.Read)("/sites/:siteId/vpn")], AFSOmadaProvider.prototype, "readVpn", null);
2006
+ require_decorate.__decorate([(0, _aigne_afs_provider.Meta)("/sites/:siteId/vpn")], AFSOmadaProvider.prototype, "metaVpn", null);
2007
+ require_decorate.__decorate([(0, _aigne_afs_provider.Stat)("/sites/:siteId/vpn")], AFSOmadaProvider.prototype, "statVpn", null);
2008
+ require_decorate.__decorate([(0, _aigne_afs_provider.List)("/sites/:siteId/firewall")], AFSOmadaProvider.prototype, "listFirewall", null);
2009
+ require_decorate.__decorate([(0, _aigne_afs_provider.Read)("/sites/:siteId/firewall")], AFSOmadaProvider.prototype, "readFirewall", null);
2010
+ require_decorate.__decorate([(0, _aigne_afs_provider.Meta)("/sites/:siteId/firewall")], AFSOmadaProvider.prototype, "metaFirewall", null);
2011
+ require_decorate.__decorate([(0, _aigne_afs_provider.Stat)("/sites/:siteId/firewall")], AFSOmadaProvider.prototype, "statFirewall", null);
2012
+ require_decorate.__decorate([(0, _aigne_afs_provider.List)("/sites/:siteId/routing")], AFSOmadaProvider.prototype, "listRouting", null);
2013
+ require_decorate.__decorate([(0, _aigne_afs_provider.Read)("/sites/:siteId/routing")], AFSOmadaProvider.prototype, "readRouting", null);
2014
+ require_decorate.__decorate([(0, _aigne_afs_provider.Meta)("/sites/:siteId/routing")], AFSOmadaProvider.prototype, "metaRouting", null);
2015
+ require_decorate.__decorate([(0, _aigne_afs_provider.Stat)("/sites/:siteId/routing")], AFSOmadaProvider.prototype, "statRouting", null);
2016
+ require_decorate.__decorate([(0, _aigne_afs_provider.List)("/sites/:siteId/nat")], AFSOmadaProvider.prototype, "listNat", null);
2017
+ require_decorate.__decorate([(0, _aigne_afs_provider.Read)("/sites/:siteId/nat")], AFSOmadaProvider.prototype, "readNat", null);
2018
+ require_decorate.__decorate([(0, _aigne_afs_provider.Meta)("/sites/:siteId/nat")], AFSOmadaProvider.prototype, "metaNat", null);
2019
+ require_decorate.__decorate([(0, _aigne_afs_provider.Stat)("/sites/:siteId/nat")], AFSOmadaProvider.prototype, "statNat", null);
2020
+ require_decorate.__decorate([(0, _aigne_afs_provider.List)("/sites/:siteId/logs")], AFSOmadaProvider.prototype, "listLogs", null);
2021
+ require_decorate.__decorate([(0, _aigne_afs_provider.Read)("/sites/:siteId/logs")], AFSOmadaProvider.prototype, "readLogs", null);
2022
+ require_decorate.__decorate([(0, _aigne_afs_provider.Meta)("/sites/:siteId/logs")], AFSOmadaProvider.prototype, "metaLogs", null);
2023
+ require_decorate.__decorate([(0, _aigne_afs_provider.Stat)("/sites/:siteId/logs")], AFSOmadaProvider.prototype, "statLogs", null);
2024
+ require_decorate.__decorate([(0, _aigne_afs_provider.Read)("/sites/:siteId/devices/switches/:mac/ports")], AFSOmadaProvider.prototype, "readSwitchPorts", null);
2025
+ require_decorate.__decorate([(0, _aigne_afs_provider.Meta)("/sites/:siteId/devices/switches/:mac/ports")], AFSOmadaProvider.prototype, "metaSwitchPorts", null);
2026
+ require_decorate.__decorate([(0, _aigne_afs_provider.Stat)("/sites/:siteId/devices/switches/:mac/ports")], AFSOmadaProvider.prototype, "statSwitchPorts", null);
2027
+ require_decorate.__decorate([(0, _aigne_afs_provider.List)("/sites/:siteId/devices/switches/:mac/ports")], AFSOmadaProvider.prototype, "listSwitchPorts", null);
2028
+ require_decorate.__decorate([(0, _aigne_afs_provider.List)("/sites/:siteId/devices/:category/:mac/ports")], AFSOmadaProvider.prototype, "listNonSwitchPorts", null);
2029
+ require_decorate.__decorate([(0, _aigne_afs_provider.Read)("/sites/:siteId/devices/switches/:mac/ports/:portId")], AFSOmadaProvider.prototype, "readSwitchPort", null);
2030
+ require_decorate.__decorate([(0, _aigne_afs_provider.List)("/sites/:siteId/devices/switches/:mac/ports/:portId")], AFSOmadaProvider.prototype, "listSwitchPort", null);
2031
+ require_decorate.__decorate([(0, _aigne_afs_provider.Meta)("/sites/:siteId/devices/switches/:mac/ports/:portId")], AFSOmadaProvider.prototype, "metaSwitchPort", null);
2032
+ require_decorate.__decorate([(0, _aigne_afs_provider.Stat)("/sites/:siteId/devices/switches/:mac/ports/:portId")], AFSOmadaProvider.prototype, "statSwitchPort", null);
2033
+ require_decorate.__decorate([(0, _aigne_afs_provider.Read)("/sites/:siteId/devices/switches/:mac/ports/:portId/config")], AFSOmadaProvider.prototype, "readSwitchPortConfig", null);
2034
+ require_decorate.__decorate([(0, _aigne_afs_provider.Write)("/sites/:siteId/devices/switches/:mac/ports/:portId/config")], AFSOmadaProvider.prototype, "writeSwitchPortConfig", null);
2035
+ require_decorate.__decorate([(0, _aigne_afs_provider.List)("/sites/:siteId/devices/:category/:mac/firmware")], AFSOmadaProvider.prototype, "listFirmware", null);
2036
+ require_decorate.__decorate([(0, _aigne_afs_provider.Read)("/sites/:siteId/devices/:category/:mac/firmware")], AFSOmadaProvider.prototype, "readFirmware", null);
2037
+ require_decorate.__decorate([(0, _aigne_afs_provider.Meta)("/sites/:siteId/devices/:category/:mac/firmware")], AFSOmadaProvider.prototype, "metaFirmware", null);
2038
+ require_decorate.__decorate([(0, _aigne_afs_provider.Stat)("/sites/:siteId/devices/:category/:mac/firmware")], AFSOmadaProvider.prototype, "statFirmware", null);
2039
+ require_decorate.__decorate([(0, _aigne_afs_provider.Explain)("/")], AFSOmadaProvider.prototype, "explainRoot", null);
2040
+ require_decorate.__decorate([(0, _aigne_afs_provider.Explain)("/sites/:siteId")], AFSOmadaProvider.prototype, "explainSite", null);
2041
+ require_decorate.__decorate([
2042
+ (0, _aigne_afs_provider.Explain)("/sites/:siteId/devices"),
2043
+ (0, _aigne_afs_provider.Explain)("/sites/:siteId/devices/:category"),
2044
+ (0, _aigne_afs_provider.Explain)("/sites/:siteId/devices/:category/:mac"),
2045
+ (0, _aigne_afs_provider.Explain)("/sites/:siteId/devices/:category/:mac/ports"),
2046
+ (0, _aigne_afs_provider.Explain)("/sites/:siteId/devices/:category/:mac/ports/:portId"),
2047
+ (0, _aigne_afs_provider.Explain)("/sites/:siteId/devices/:category/:mac/firmware"),
2048
+ (0, _aigne_afs_provider.Explain)("/sites/:siteId/clients"),
2049
+ (0, _aigne_afs_provider.Explain)("/sites/:siteId/clients/:mac"),
2050
+ (0, _aigne_afs_provider.Explain)("/sites/:siteId/dashboard"),
2051
+ (0, _aigne_afs_provider.Explain)("/sites/:siteId/networks"),
2052
+ (0, _aigne_afs_provider.Explain)("/sites/:siteId/networks/wireless"),
2053
+ (0, _aigne_afs_provider.Explain)("/sites/:siteId/networks/wireless/:ssidId"),
2054
+ (0, _aigne_afs_provider.Explain)("/sites/:siteId/networks/wired"),
2055
+ (0, _aigne_afs_provider.Explain)("/sites/:siteId/networks/wired/:networkId"),
2056
+ (0, _aigne_afs_provider.Explain)("/sites/:siteId/networks/wifi-optimization"),
2057
+ (0, _aigne_afs_provider.Explain)("/sites/:siteId/vpn"),
2058
+ (0, _aigne_afs_provider.Explain)("/sites/:siteId/firewall"),
2059
+ (0, _aigne_afs_provider.Explain)("/sites/:siteId/routing"),
2060
+ (0, _aigne_afs_provider.Explain)("/sites/:siteId/nat"),
2061
+ (0, _aigne_afs_provider.Explain)("/sites/:siteId/logs")
2062
+ ], AFSOmadaProvider.prototype, "explainSiteChild", null);
2063
+ require_decorate.__decorate([(0, _aigne_afs_provider.Search)("/:path*")], AFSOmadaProvider.prototype, "searchAll", null);
2064
+ require_decorate.__decorate([(0, _aigne_afs_provider.Actions)("/")], AFSOmadaProvider.prototype, "listRootActions", null);
2065
+ require_decorate.__decorate([_aigne_afs_provider.Actions.Exec("/", "create-site")], AFSOmadaProvider.prototype, "execCreateSite", null);
2066
+ require_decorate.__decorate([(0, _aigne_afs_provider.Actions)("/sites/:siteId/devices/:category/:mac")], AFSOmadaProvider.prototype, "listDeviceActions", null);
2067
+ require_decorate.__decorate([_aigne_afs_provider.Actions.Exec("/sites/:siteId/devices/:category/:mac", "reboot")], AFSOmadaProvider.prototype, "execDeviceReboot", null);
2068
+ require_decorate.__decorate([_aigne_afs_provider.Actions.Exec("/sites/:siteId/devices/:category/:mac", "upgrade-firmware")], AFSOmadaProvider.prototype, "execDeviceUpgradeFirmware", null);
2069
+ require_decorate.__decorate([(0, _aigne_afs_provider.Actions)("/sites/:siteId/clients/:mac")], AFSOmadaProvider.prototype, "listClientActions", null);
2070
+ require_decorate.__decorate([_aigne_afs_provider.Actions.Exec("/sites/:siteId/clients/:mac", "block")], AFSOmadaProvider.prototype, "execClientBlock", null);
2071
+ require_decorate.__decorate([_aigne_afs_provider.Actions.Exec("/sites/:siteId/clients/:mac", "unblock")], AFSOmadaProvider.prototype, "execClientUnblock", null);
2072
+ require_decorate.__decorate([(0, _aigne_afs_provider.Read)("/sites/:siteId/devices/:category/:mac/config")], AFSOmadaProvider.prototype, "readDeviceConfig", null);
2073
+ require_decorate.__decorate([(0, _aigne_afs_provider.Write)("/sites/:siteId/devices/:category/:mac/config")], AFSOmadaProvider.prototype, "writeDeviceConfig", null);
2074
+
2075
+ //#endregion
2076
+ exports.AFSOmadaProvider = AFSOmadaProvider;