@camstack/types 1.2.436 → 1.2.438
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +15 -0
- package/dist/addon.js +2 -2
- package/dist/addon.mjs +2 -2
- package/dist/capabilities/index.d.ts +3 -1
- package/dist/capabilities/ir-transmitter.cap.d.ts +84 -0
- package/dist/capabilities/llm.cap.d.ts +27 -0
- package/dist/capabilities/pet-feeder.cap.d.ts +12 -0
- package/dist/client.js +5 -0
- package/dist/client.mjs +5 -0
- package/dist/{composition-WNkEpwkF.js → composition-DCmtFE-X.js} +1 -1
- package/dist/{composition-DwA0uVW5.mjs → composition-DpFv_J6D.mjs} +1 -1
- package/dist/device/cap-vocabulary/entries/actuators.d.ts +1 -1
- package/dist/device/device-type.d.ts +4 -1
- package/dist/{err-msg-DIorGYeC.mjs → err-msg-BCdlR2Li.mjs} +3 -0
- package/dist/{err-msg-U7lLUMNz.js → err-msg-COHgq7Mb.js} +3 -0
- package/dist/generated/addon-api.d.ts +22 -0
- package/dist/generated/addon-cap-facts.d.ts +1 -1
- package/dist/generated/capability-router-map.d.ts +5 -2
- package/dist/generated/device-proxy.d.ts +2 -0
- package/dist/generated/device-scoped-caps.d.ts +1 -1
- package/dist/generated/method-access-map.d.ts +1 -1
- package/dist/generated/method-device-selectors.d.ts +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +369 -7
- package/dist/index.mjs +357 -8
- package/dist/ir/index.d.ts +5 -0
- package/dist/ir/ir-error.d.ts +6 -0
- package/dist/ir/ir-payload.d.ts +23 -0
- package/dist/ir/ir-timings.d.ts +17 -0
- package/dist/ir/pronto.d.ts +10 -0
- package/dist/ir/smartir.d.ts +31 -0
- package/dist/node.js +2 -2
- package/dist/node.mjs +2 -2
- package/dist/{sleep-Crlmu_tO.mjs → sleep-BAvUCi_2.mjs} +13 -1
- package/dist/{sleep-DHitF_e4.js → sleep-g6ZjBHBL.js} +13 -1
- package/dist/vendor-login-proxy/index.d.ts +1 -1
- package/dist/vendor-login-proxy/url-rewrite.d.ts +7 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_sleep = require("./sleep-
|
|
2
|
+
const require_sleep = require("./sleep-g6ZjBHBL.js");
|
|
3
3
|
const require_event_category = require("./event-category-E17zaHjN.js");
|
|
4
|
-
const require_composition = require("./composition-
|
|
4
|
+
const require_composition = require("./composition-DCmtFE-X.js");
|
|
5
5
|
const require_node_color = require("./node-color.js");
|
|
6
|
-
const require_err_msg = require("./err-msg-
|
|
6
|
+
const require_err_msg = require("./err-msg-COHgq7Mb.js");
|
|
7
7
|
const require_enums = require("./enums.js");
|
|
8
8
|
let zod = require("zod");
|
|
9
9
|
//#region src/media/media-owner-key.ts
|
|
@@ -44650,6 +44650,17 @@ var LlmProfileSchema = zod.z.object({
|
|
|
44650
44650
|
* field in its editor only when its descriptor lists it in `profileFields`. */
|
|
44651
44651
|
topK: zod.z.number().int().positive().optional(),
|
|
44652
44652
|
maxTokens: zod.z.number().int().positive().optional(),
|
|
44653
|
+
/** How hard the model "thinks" before it answers. Omitted = the model's own
|
|
44654
|
+
* default. `off` matters for structured output: a thinking model can spend
|
|
44655
|
+
* the whole completion on reasoning and return an empty `content`. Carried
|
|
44656
|
+
* only by the wires that have it — a kind offers the field in its editor
|
|
44657
|
+
* only when its descriptor lists it in `profileFields`. */
|
|
44658
|
+
reasoningEffort: zod.z.enum([
|
|
44659
|
+
"off",
|
|
44660
|
+
"low",
|
|
44661
|
+
"medium",
|
|
44662
|
+
"high"
|
|
44663
|
+
]).optional(),
|
|
44653
44664
|
/** Prompt context window. Advisory for cloud kinds (they enforce their own). */
|
|
44654
44665
|
contextLength: zod.z.number().int().positive().optional(),
|
|
44655
44666
|
/** Default system prompt. A caller's `system` REPLACES it (never appends —
|
|
@@ -44688,6 +44699,7 @@ var LlmProfileFieldSchema = zod.z.enum([
|
|
|
44688
44699
|
"topP",
|
|
44689
44700
|
"topK",
|
|
44690
44701
|
"maxTokens",
|
|
44702
|
+
"reasoningEffort",
|
|
44691
44703
|
"contextLength",
|
|
44692
44704
|
"systemPrompt",
|
|
44693
44705
|
"timeoutMs",
|
|
@@ -65196,6 +65208,83 @@ var buttonCapability = {
|
|
|
65196
65208
|
}) }
|
|
65197
65209
|
};
|
|
65198
65210
|
//#endregion
|
|
65211
|
+
//#region src/ir/ir-timings.ts
|
|
65212
|
+
/** Maximum number of mark/space entries one pulse train may carry. */
|
|
65213
|
+
var IR_TIMINGS_MAX = 1024;
|
|
65214
|
+
/**
|
|
65215
|
+
* A pulse train in signed microseconds: mark (+) first, then space (-), strictly
|
|
65216
|
+
* alternating, no zeros, 2..1024 entries.
|
|
65217
|
+
*/
|
|
65218
|
+
var IrTimingsSchema = zod.z.array(zod.z.number().int()).min(2).max(IR_TIMINGS_MAX).superRefine((timings, ctx) => {
|
|
65219
|
+
timings.forEach((value, index) => {
|
|
65220
|
+
const expectMark = index % 2 === 0;
|
|
65221
|
+
if (value === 0 || value > 0 !== expectMark) ctx.addIssue({
|
|
65222
|
+
code: "custom",
|
|
65223
|
+
message: `timing ${index} must be a non-zero ${expectMark ? "mark (positive)" : "space (negative)"}`,
|
|
65224
|
+
path: [index]
|
|
65225
|
+
});
|
|
65226
|
+
});
|
|
65227
|
+
});
|
|
65228
|
+
/** Per-command transmit options. Every key is optional; a transmitter applies what it can. */
|
|
65229
|
+
var TransmitSettingsSchema = zod.z.object({
|
|
65230
|
+
carrierHz: zod.z.number().int().positive().optional(),
|
|
65231
|
+
dutyCyclePercent: zod.z.number().int().min(1).max(100).optional(),
|
|
65232
|
+
repeat: zod.z.number().int().min(0).max(20).optional(),
|
|
65233
|
+
repeatDelayMs: zod.z.number().int().min(0).optional()
|
|
65234
|
+
});
|
|
65235
|
+
//#endregion
|
|
65236
|
+
//#region src/capabilities/ir-transmitter.cap.ts
|
|
65237
|
+
/** The setting keys a transmitter may declare as settable (`getInfo.settable`). */
|
|
65238
|
+
var TransmitSettingKeySchema = zod.z.enum([
|
|
65239
|
+
"carrierHz",
|
|
65240
|
+
"dutyCyclePercent",
|
|
65241
|
+
"repeat",
|
|
65242
|
+
"repeatDelayMs"
|
|
65243
|
+
]);
|
|
65244
|
+
var IrMediumSchema = zod.z.enum(["ir", "rf"]);
|
|
65245
|
+
var IrSendResultSchema = zod.z.object({
|
|
65246
|
+
ok: zod.z.literal(true),
|
|
65247
|
+
/** Settings the transmitter could not apply; the train was still sent. */
|
|
65248
|
+
ignoredSettings: zod.z.array(zod.z.string())
|
|
65249
|
+
});
|
|
65250
|
+
var IrTransmitterInfoSchema = zod.z.object({
|
|
65251
|
+
media: zod.z.array(IrMediumSchema),
|
|
65252
|
+
settable: zod.z.array(TransmitSettingKeySchema),
|
|
65253
|
+
maxTimings: zod.z.number().int().positive()
|
|
65254
|
+
});
|
|
65255
|
+
/**
|
|
65256
|
+
* ir-transmitter — emit a pulse train (infrared or RF) with settings. One cap
|
|
65257
|
+
* for both media: everything medium-specific is a per-call setting, validated
|
|
65258
|
+
* against what the transmitter declares in `getInfo`.
|
|
65259
|
+
*
|
|
65260
|
+
* `send` refuses with a typed user error: `ir-transmitter.offline` (the
|
|
65261
|
+
* transmitter cannot be reached) and `ir-transmitter.too-long` (more pulses
|
|
65262
|
+
* than the transmitter's `maxTimings`). A setting the transmitter cannot apply
|
|
65263
|
+
* is NOT a refusal: the train is sent and the key comes back in
|
|
65264
|
+
* `ignoredSettings`.
|
|
65265
|
+
*/
|
|
65266
|
+
var irTransmitterCapability = {
|
|
65267
|
+
name: "ir-transmitter",
|
|
65268
|
+
scope: "device",
|
|
65269
|
+
deviceNative: true,
|
|
65270
|
+
mode: "singleton",
|
|
65271
|
+
deviceTypes: [require_err_msg.DeviceType.Generic],
|
|
65272
|
+
methods: {
|
|
65273
|
+
send: require_sleep.method(zod.z.object({
|
|
65274
|
+
deviceId: zod.z.number().int().nonnegative(),
|
|
65275
|
+
timings: IrTimingsSchema,
|
|
65276
|
+
settings: TransmitSettingsSchema.optional()
|
|
65277
|
+
}), IrSendResultSchema, {
|
|
65278
|
+
kind: "mutation",
|
|
65279
|
+
auth: "protected"
|
|
65280
|
+
}),
|
|
65281
|
+
getInfo: require_sleep.method(zod.z.object({ deviceId: zod.z.number().int().nonnegative() }), IrTransmitterInfoSchema, {
|
|
65282
|
+
kind: "query",
|
|
65283
|
+
auth: "protected"
|
|
65284
|
+
})
|
|
65285
|
+
}
|
|
65286
|
+
};
|
|
65287
|
+
//#endregion
|
|
65199
65288
|
//#region src/capabilities/calendar-source.cap.ts
|
|
65200
65289
|
/**
|
|
65201
65290
|
* `calendar-source` — collection cap exposing per-provider calendars and
|
|
@@ -72345,9 +72434,14 @@ var PetFeederStatusSchema = zod.z.object({
|
|
|
72345
72434
|
* (`device_class: problem`, on = low). True when the tank reports empty,
|
|
72346
72435
|
* or, on a dual-hopper model, when EITHER hopper is empty. */
|
|
72347
72436
|
lowFood: zod.z.boolean(),
|
|
72348
|
-
/** Battery charge 0..100 (%).
|
|
72349
|
-
*
|
|
72437
|
+
/** Battery charge 0..100 (%). On a feeder running on `mains` this is the
|
|
72438
|
+
* BACKUP battery's charge, not the power source. Null when the device has
|
|
72439
|
+
* no battery reading. */
|
|
72350
72440
|
batteryPower: zod.z.number().min(0).max(100).nullable().meta(require_sleep.readingMeta("percentage")),
|
|
72441
|
+
/** What the feeder is powered from right now: `mains` (plugged in, the
|
|
72442
|
+
* battery is only a backup) or `battery`. Null when the device does not
|
|
72443
|
+
* report it. */
|
|
72444
|
+
powerSource: zod.z.enum(["mains", "battery"]).nullable(),
|
|
72351
72445
|
/**
|
|
72352
72446
|
* Desiccant life remaining, stored in seconds (duration base, D944).
|
|
72353
72447
|
* Providers convert from the days the feeder reports. Null when the
|
|
@@ -90847,6 +90941,20 @@ var METHOD_ACCESS_MAP = Object.freeze({
|
|
|
90847
90941
|
access: "create",
|
|
90848
90942
|
role: "viewer"
|
|
90849
90943
|
},
|
|
90944
|
+
"irTransmitter.getInfo": {
|
|
90945
|
+
capName: "ir-transmitter",
|
|
90946
|
+
capScope: "device",
|
|
90947
|
+
addonId: null,
|
|
90948
|
+
access: "view",
|
|
90949
|
+
role: "viewer"
|
|
90950
|
+
},
|
|
90951
|
+
"irTransmitter.send": {
|
|
90952
|
+
capName: "ir-transmitter",
|
|
90953
|
+
capScope: "device",
|
|
90954
|
+
addonId: null,
|
|
90955
|
+
access: "create",
|
|
90956
|
+
role: "viewer"
|
|
90957
|
+
},
|
|
90850
90958
|
"keychain.delete": {
|
|
90851
90959
|
capName: "keychain",
|
|
90852
90960
|
capScope: "system",
|
|
@@ -97215,6 +97323,7 @@ var KNOWN_CAP_NAMES = [
|
|
|
97215
97323
|
"image-settings",
|
|
97216
97324
|
"integrations",
|
|
97217
97325
|
"intercom",
|
|
97326
|
+
"ir-transmitter",
|
|
97218
97327
|
"keychain",
|
|
97219
97328
|
"keychain-admin",
|
|
97220
97329
|
"lawn-mower-control",
|
|
@@ -97366,6 +97475,7 @@ var DEVICE_CAP_NAMES = [
|
|
|
97366
97475
|
"image",
|
|
97367
97476
|
"image-settings",
|
|
97368
97477
|
"intercom",
|
|
97478
|
+
"ir-transmitter",
|
|
97369
97479
|
"lawn-mower-control",
|
|
97370
97480
|
"lock-control",
|
|
97371
97481
|
"media-player",
|
|
@@ -98857,6 +98967,11 @@ var ACTUATOR_CAP_VOCABULARY = {
|
|
|
98857
98967
|
icon: "circle-dot"
|
|
98858
98968
|
}]
|
|
98859
98969
|
},
|
|
98970
|
+
"ir-transmitter": {
|
|
98971
|
+
scope: "device",
|
|
98972
|
+
noun: t("IR / RF transmitter", "Trasmettitore IR / RF"),
|
|
98973
|
+
notOperatorFacing: { send: "a raw pulse train is not something an operator composes in an automation; the remote that owns the command table sends it" }
|
|
98974
|
+
},
|
|
98860
98975
|
control: {
|
|
98861
98976
|
scope: "device",
|
|
98862
98977
|
noun: t("Control", "Controllo"),
|
|
@@ -103303,6 +103418,7 @@ var CAPABILITY_NAMES = {
|
|
|
103303
103418
|
imageSettings: "image-settings",
|
|
103304
103419
|
integrations: "integrations",
|
|
103305
103420
|
intercom: "intercom",
|
|
103421
|
+
irTransmitter: "ir-transmitter",
|
|
103306
103422
|
keychain: "keychain",
|
|
103307
103423
|
keychainAdmin: "keychain-admin",
|
|
103308
103424
|
lawnMowerControl: "lawn-mower-control",
|
|
@@ -103751,6 +103867,10 @@ var CAPABILITY_ROUTER_KEYS = [
|
|
|
103751
103867
|
key: "intercom",
|
|
103752
103868
|
name: "intercom"
|
|
103753
103869
|
},
|
|
103870
|
+
{
|
|
103871
|
+
key: "irTransmitter",
|
|
103872
|
+
name: "ir-transmitter"
|
|
103873
|
+
},
|
|
103754
103874
|
{
|
|
103755
103875
|
key: "keychain",
|
|
103756
103876
|
name: "keychain"
|
|
@@ -104252,6 +104372,7 @@ var ALL_CAPABILITY_DEFINITIONS = [
|
|
|
104252
104372
|
imageSettingsCapability,
|
|
104253
104373
|
integrationsCapability,
|
|
104254
104374
|
intercomCapability,
|
|
104375
|
+
irTransmitterCapability,
|
|
104255
104376
|
keychainCapability,
|
|
104256
104377
|
keychainAdminCapability,
|
|
104257
104378
|
lawnMowerControlCapability,
|
|
@@ -105447,6 +105568,16 @@ var METHOD_DEVICE_SELECTORS = Object.freeze({
|
|
|
105447
105568
|
form: "single",
|
|
105448
105569
|
optional: false
|
|
105449
105570
|
}],
|
|
105571
|
+
"irTransmitter.getInfo": [{
|
|
105572
|
+
name: "deviceId",
|
|
105573
|
+
form: "single",
|
|
105574
|
+
optional: false
|
|
105575
|
+
}],
|
|
105576
|
+
"irTransmitter.send": [{
|
|
105577
|
+
name: "deviceId",
|
|
105578
|
+
form: "single",
|
|
105579
|
+
optional: false
|
|
105580
|
+
}],
|
|
105450
105581
|
"keychain.deleteDeviceScope": [{
|
|
105451
105582
|
name: "deviceId",
|
|
105452
105583
|
form: "single",
|
|
@@ -118280,6 +118411,29 @@ function rewriteSetCookie(cookie, route) {
|
|
|
118280
118411
|
return kept.join("; ");
|
|
118281
118412
|
}
|
|
118282
118413
|
/**
|
|
118414
|
+
* Every Set-Cookie of one vendor response, rewritten. Dropping `Domain` folds cookies
|
|
118415
|
+
* the vendor keeps apart (`session-id` on `.amazon.it` and on `.www.amazon.it`) into
|
|
118416
|
+
* one, so a past-dated set that only deleted the other domain's copy would delete the
|
|
118417
|
+
* live one the same response just set: that deletion is dropped.
|
|
118418
|
+
*/
|
|
118419
|
+
function rewriteSetCookies(cookies, route) {
|
|
118420
|
+
const now = Date.now();
|
|
118421
|
+
const liveNames = new Set(cookies.filter((c) => !isExpiredCookie(c, now)).map(cookieName));
|
|
118422
|
+
return cookies.filter((c) => !(isExpiredCookie(c, now) && liveNames.has(cookieName(c)))).map((c) => rewriteSetCookie(c, route));
|
|
118423
|
+
}
|
|
118424
|
+
function cookieName(cookie) {
|
|
118425
|
+
return cookie.split(";")[0]?.split("=")[0]?.trim() ?? "";
|
|
118426
|
+
}
|
|
118427
|
+
function isExpiredCookie(cookie, now) {
|
|
118428
|
+
const attrs = cookie.split(";").slice(1).map((part) => part.trim());
|
|
118429
|
+
const maxAge = attrs.find((a) => /^max-age=/i.test(a));
|
|
118430
|
+
if (maxAge !== void 0) return Number(maxAge.slice(8)) <= 0;
|
|
118431
|
+
const expires = attrs.find((a) => /^expires=/i.test(a));
|
|
118432
|
+
if (expires === void 0) return false;
|
|
118433
|
+
const at = Date.parse(expires.slice(8));
|
|
118434
|
+
return Number.isFinite(at) && at <= now;
|
|
118435
|
+
}
|
|
118436
|
+
/**
|
|
118283
118437
|
* A browser `Referer` that points into this proxy, turned back into the vendor URL it
|
|
118284
118438
|
* stands for. A Referer that is not ours is dropped (null): it names the hub.
|
|
118285
118439
|
*/
|
|
@@ -118398,6 +118552,26 @@ async function readRequestBody(req) {
|
|
|
118398
118552
|
}
|
|
118399
118553
|
return Buffer.concat(chunks);
|
|
118400
118554
|
}
|
|
118555
|
+
/** The path of the Referer sent upstream, or why none was sent — the query is never logged. */
|
|
118556
|
+
function forwardedRefererPath(forwarded, received) {
|
|
118557
|
+
if (forwarded !== void 0) return URL.canParse(forwarded) ? new URL(forwarded).pathname : "unparsable";
|
|
118558
|
+
return received === void 0 ? "absent" : "unmapped";
|
|
118559
|
+
}
|
|
118560
|
+
/** The form targets a vendor page posts to, path only (no query), so a lost path prefix is visible. */
|
|
118561
|
+
function formActionPaths(html) {
|
|
118562
|
+
const actions = [...html.matchAll(/<form\b[^>]*\baction\s*=\s*["']([^"']*)["']/gi)].map((m) => (m[1] ?? "").split("?")[0] ?? "").slice(0, 5);
|
|
118563
|
+
return actions.length === 0 ? "none" : actions.join(" | ");
|
|
118564
|
+
}
|
|
118565
|
+
/** Cookie NAMES only — values are session secrets and are never logged. */
|
|
118566
|
+
function cookieNames(header) {
|
|
118567
|
+
if (header === void 0 || header.length === 0) return "none";
|
|
118568
|
+
return header.split(";").map((part) => part.split("=")[0]?.trim() ?? "").join(",");
|
|
118569
|
+
}
|
|
118570
|
+
/** A Set-Cookie's name and attributes without its value, so a cookie the browser refuses is visible. */
|
|
118571
|
+
function setCookieShape(cookie) {
|
|
118572
|
+
const [first, ...attrs] = cookie.split(";").map((part) => part.trim());
|
|
118573
|
+
return [first?.split("=")[0] ?? "", ...attrs.filter((a) => !/^expires=/i.test(a))].join(";");
|
|
118574
|
+
}
|
|
118401
118575
|
function sendPlain(res, status, text) {
|
|
118402
118576
|
res.writeHead(status, {
|
|
118403
118577
|
"content-type": "text/plain; charset=utf-8",
|
|
@@ -118533,7 +118707,11 @@ var VendorLoginProxy = class {
|
|
|
118533
118707
|
host: upstream.host,
|
|
118534
118708
|
path: target.pathname,
|
|
118535
118709
|
status: upstreamRes.status,
|
|
118536
|
-
method
|
|
118710
|
+
method,
|
|
118711
|
+
refererPath: forwardedRefererPath(headers["referer"], req.headers["referer"]),
|
|
118712
|
+
formActions: kind === "html" && text !== null ? formActionPaths(text) : void 0,
|
|
118713
|
+
sentNames: cookieNames(headers["cookie"]),
|
|
118714
|
+
vendorSets: setCookies.map(setCookieShape).join(" | ")
|
|
118537
118715
|
} });
|
|
118538
118716
|
const settled = await attempt.evaluate({
|
|
118539
118717
|
status: upstreamRes.status,
|
|
@@ -118555,7 +118733,7 @@ var VendorLoginProxy = class {
|
|
|
118555
118733
|
upstreamRes.headers.forEach((value, name) => {
|
|
118556
118734
|
if (!DROP_RESPONSE_HEADERS.has(name.toLowerCase())) out[name] = value;
|
|
118557
118735
|
});
|
|
118558
|
-
if (setCookies.length > 0) out["set-cookie"] = setCookies
|
|
118736
|
+
if (setCookies.length > 0) out["set-cookie"] = rewriteSetCookies(setCookies, route);
|
|
118559
118737
|
if (location !== null) out["location"] = rewriteLocation(location, upstream, route);
|
|
118560
118738
|
out["cache-control"] = "no-store";
|
|
118561
118739
|
if (text !== null && kind !== null) {
|
|
@@ -119660,6 +119838,177 @@ function armRemovalReconcile(opts) {
|
|
|
119660
119838
|
return () => clearInterval(timer);
|
|
119661
119839
|
}
|
|
119662
119840
|
//#endregion
|
|
119841
|
+
//#region src/ir/ir-error.ts
|
|
119842
|
+
var IrCodecError = class extends Error {
|
|
119843
|
+
code;
|
|
119844
|
+
constructor(code, message) {
|
|
119845
|
+
super(message);
|
|
119846
|
+
this.name = "IrCodecError";
|
|
119847
|
+
this.code = code;
|
|
119848
|
+
}
|
|
119849
|
+
};
|
|
119850
|
+
//#endregion
|
|
119851
|
+
//#region src/ir/pronto.ts
|
|
119852
|
+
/** One Pronto frequency-word unit, in microseconds, per unit of the word. */
|
|
119853
|
+
var PRONTO_CLOCK_US = .241246;
|
|
119854
|
+
var LEARNED_FORM = 0;
|
|
119855
|
+
/**
|
|
119856
|
+
* Decode a learned (0000 form) Pronto hex string. The intro burst is followed by
|
|
119857
|
+
* the repeat burst once; a different form is refused with `pronto-unsupported-form`.
|
|
119858
|
+
*/
|
|
119859
|
+
function decodePronto(code) {
|
|
119860
|
+
const words = code.trim().split(/\s+/).filter((w) => w.length > 0);
|
|
119861
|
+
if (words.length < 4) throw new IrCodecError("pronto-malformed", `Pronto code needs at least 4 words, got ${words.length}`);
|
|
119862
|
+
const values = words.map((w) => /^[0-9a-fA-F]{1,4}$/.test(w) ? parseInt(w, 16) : NaN);
|
|
119863
|
+
if (values.some((v) => Number.isNaN(v))) throw new IrCodecError("pronto-malformed", "Pronto code must be 4-digit hexadecimal words");
|
|
119864
|
+
const [form, freqWord, introCount, repeatCount] = values;
|
|
119865
|
+
if (form === void 0 || freqWord === void 0 || introCount === void 0 || repeatCount === void 0) throw new IrCodecError("pronto-malformed", "Pronto header incomplete");
|
|
119866
|
+
if (form !== LEARNED_FORM) throw new IrCodecError("pronto-unsupported-form", `Pronto form ${words[0] ?? ""} is not supported, only the learned 0000 form`);
|
|
119867
|
+
if (freqWord === 0) throw new IrCodecError("pronto-malformed", "Pronto frequency word is zero");
|
|
119868
|
+
const pairs = introCount + repeatCount;
|
|
119869
|
+
if (pairs === 0 || values.length !== 4 + pairs * 2) throw new IrCodecError("pronto-malformed", `Pronto declares ${pairs} burst pairs but carries ${(values.length - 4) / 2} word pairs`);
|
|
119870
|
+
const unitUs = freqWord * PRONTO_CLOCK_US;
|
|
119871
|
+
const timings = values.slice(4).map((count, index) => {
|
|
119872
|
+
const us = Math.max(1, Math.round(count * unitUs));
|
|
119873
|
+
return index % 2 === 0 ? us : -us;
|
|
119874
|
+
});
|
|
119875
|
+
const checked = IrTimingsSchema.safeParse(timings);
|
|
119876
|
+
if (!checked.success) throw new IrCodecError("invalid-timings", `Pronto decoded to invalid timings: ${checked.error.message}`);
|
|
119877
|
+
return {
|
|
119878
|
+
timings: checked.data,
|
|
119879
|
+
carrierHz: Math.round(1e6 / unitUs)
|
|
119880
|
+
};
|
|
119881
|
+
}
|
|
119882
|
+
//#endregion
|
|
119883
|
+
//#region src/ir/ir-payload.ts
|
|
119884
|
+
/** What a remote command stores: a raw pulse train, or a learned Pronto code. */
|
|
119885
|
+
var IrPayloadSchema = zod.z.discriminatedUnion("kind", [zod.z.object({
|
|
119886
|
+
kind: zod.z.literal("raw"),
|
|
119887
|
+
timings: zod.z.array(zod.z.number().int()),
|
|
119888
|
+
settings: TransmitSettingsSchema.optional()
|
|
119889
|
+
}), zod.z.object({
|
|
119890
|
+
kind: zod.z.literal("pronto"),
|
|
119891
|
+
code: zod.z.string()
|
|
119892
|
+
})]);
|
|
119893
|
+
/** Resolve a payload to what `ir-transmitter.send` takes. Throws `IrCodecError`. */
|
|
119894
|
+
function toTimings(payload) {
|
|
119895
|
+
if (payload.kind === "pronto") {
|
|
119896
|
+
const decoded = decodePronto(payload.code);
|
|
119897
|
+
return {
|
|
119898
|
+
timings: decoded.timings,
|
|
119899
|
+
settings: { carrierHz: decoded.carrierHz }
|
|
119900
|
+
};
|
|
119901
|
+
}
|
|
119902
|
+
const checked = IrTimingsSchema.safeParse(payload.timings);
|
|
119903
|
+
if (!checked.success) throw new IrCodecError("invalid-timings", checked.error.message);
|
|
119904
|
+
return {
|
|
119905
|
+
timings: checked.data,
|
|
119906
|
+
settings: payload.settings ?? {}
|
|
119907
|
+
};
|
|
119908
|
+
}
|
|
119909
|
+
//#endregion
|
|
119910
|
+
//#region src/ir/smartir.ts
|
|
119911
|
+
/** SmartIR's own default pause between two commands, in seconds. */
|
|
119912
|
+
var DEFAULT_DELAY_S = .5;
|
|
119913
|
+
var SOURCES_KEY = "sources";
|
|
119914
|
+
var SmartIrDocumentSchema = zod.z.object({
|
|
119915
|
+
manufacturer: zod.z.string().optional(),
|
|
119916
|
+
supportedModels: zod.z.array(zod.z.string()).optional(),
|
|
119917
|
+
supportedController: zod.z.string().optional(),
|
|
119918
|
+
commandsEncoding: zod.z.string(),
|
|
119919
|
+
delay: zod.z.number().nonnegative().optional(),
|
|
119920
|
+
commands: zod.z.record(zod.z.string(), zod.z.unknown())
|
|
119921
|
+
});
|
|
119922
|
+
function describe(error) {
|
|
119923
|
+
return error instanceof Error ? error.message : "unknown error";
|
|
119924
|
+
}
|
|
119925
|
+
function rawPayload(value) {
|
|
119926
|
+
let parsed;
|
|
119927
|
+
try {
|
|
119928
|
+
parsed = JSON.parse(value);
|
|
119929
|
+
} catch (error) {
|
|
119930
|
+
throw new IrCodecError("invalid-raw", `Raw command is not a JSON array: ${describe(error)}`);
|
|
119931
|
+
}
|
|
119932
|
+
const checked = IrTimingsSchema.safeParse(parsed);
|
|
119933
|
+
if (!checked.success) throw new IrCodecError("invalid-timings", checked.error.message);
|
|
119934
|
+
return {
|
|
119935
|
+
kind: "raw",
|
|
119936
|
+
timings: checked.data
|
|
119937
|
+
};
|
|
119938
|
+
}
|
|
119939
|
+
function prontoPayload(value) {
|
|
119940
|
+
decodePronto(value);
|
|
119941
|
+
return {
|
|
119942
|
+
kind: "pronto",
|
|
119943
|
+
code: value
|
|
119944
|
+
};
|
|
119945
|
+
}
|
|
119946
|
+
/** Parse a SmartIR media_player JSON. Raw and Pronto are imported; other encodings are reported in `skipped`. */
|
|
119947
|
+
function parseSmartIr(document) {
|
|
119948
|
+
const parsed = SmartIrDocumentSchema.safeParse(document);
|
|
119949
|
+
if (!parsed.success) throw new IrCodecError("smartir-malformed", `Not a SmartIR document: ${parsed.error.message}`);
|
|
119950
|
+
const doc = parsed.data;
|
|
119951
|
+
const encoding = doc.commandsEncoding;
|
|
119952
|
+
const entries = [];
|
|
119953
|
+
for (const [name, value] of Object.entries(doc.commands)) if (name === SOURCES_KEY && typeof value === "object" && value !== null && !Array.isArray(value)) for (const [sourceName, sourceValue] of Object.entries(value)) entries.push({
|
|
119954
|
+
name: sourceName,
|
|
119955
|
+
group: "source",
|
|
119956
|
+
value: sourceValue
|
|
119957
|
+
});
|
|
119958
|
+
else entries.push({
|
|
119959
|
+
name,
|
|
119960
|
+
group: "command",
|
|
119961
|
+
value
|
|
119962
|
+
});
|
|
119963
|
+
const commands = [];
|
|
119964
|
+
const skipped = [];
|
|
119965
|
+
const supported = encoding === "Raw" || encoding === "Pronto";
|
|
119966
|
+
for (const { name, group, value } of entries) {
|
|
119967
|
+
if (!supported) {
|
|
119968
|
+
skipped.push({
|
|
119969
|
+
name,
|
|
119970
|
+
group,
|
|
119971
|
+
reason: `${encoding} encoding is not supported`
|
|
119972
|
+
});
|
|
119973
|
+
continue;
|
|
119974
|
+
}
|
|
119975
|
+
if (typeof value !== "string") {
|
|
119976
|
+
skipped.push({
|
|
119977
|
+
name,
|
|
119978
|
+
group,
|
|
119979
|
+
reason: "command is not a string"
|
|
119980
|
+
});
|
|
119981
|
+
continue;
|
|
119982
|
+
}
|
|
119983
|
+
try {
|
|
119984
|
+
commands.push({
|
|
119985
|
+
name,
|
|
119986
|
+
group,
|
|
119987
|
+
payload: encoding === "Raw" ? rawPayload(value) : prontoPayload(value)
|
|
119988
|
+
});
|
|
119989
|
+
} catch (error) {
|
|
119990
|
+
skipped.push({
|
|
119991
|
+
name,
|
|
119992
|
+
group,
|
|
119993
|
+
reason: describe(error)
|
|
119994
|
+
});
|
|
119995
|
+
}
|
|
119996
|
+
}
|
|
119997
|
+
return {
|
|
119998
|
+
table: {
|
|
119999
|
+
commands,
|
|
120000
|
+
interCommandDelayMs: Math.round((doc.delay ?? DEFAULT_DELAY_S) * 1e3),
|
|
120001
|
+
origin: {
|
|
120002
|
+
format: "smartir",
|
|
120003
|
+
manufacturer: doc.manufacturer,
|
|
120004
|
+
models: doc.supportedModels,
|
|
120005
|
+
controller: doc.supportedController
|
|
120006
|
+
}
|
|
120007
|
+
},
|
|
120008
|
+
skipped
|
|
120009
|
+
};
|
|
120010
|
+
}
|
|
120011
|
+
//#endregion
|
|
119663
120012
|
exports.ACCESSORY_LABEL = ACCESSORY_LABEL;
|
|
119664
120013
|
exports.ACCESS_ROLES = ACCESS_ROLES;
|
|
119665
120014
|
exports.ACTIVE_CRITERIA = require_composition.ACTIVE_CRITERIA;
|
|
@@ -120492,6 +120841,7 @@ exports.INITIAL_SPAN = INITIAL_SPAN;
|
|
|
120492
120841
|
exports.INTEGRAL_OUTPUTS = require_composition.INTEGRAL_OUTPUTS;
|
|
120493
120842
|
exports.INTERNAL_ACTION_PREFIX = INTERNAL_ACTION_PREFIX;
|
|
120494
120843
|
exports.INVERTIBLE_CAPS = INVERTIBLE_CAPS;
|
|
120844
|
+
exports.IR_TIMINGS_MAX = IR_TIMINGS_MAX;
|
|
120495
120845
|
exports.IconKeySchema = IconKeySchema;
|
|
120496
120846
|
exports.ImageContractSchema = ImageContractSchema;
|
|
120497
120847
|
exports.ImageContractStateSchema = ImageContractStateSchema;
|
|
@@ -120512,6 +120862,12 @@ exports.IntegrationWithStateSchema = IntegrationWithStateSchema;
|
|
|
120512
120862
|
exports.IntercomAbilitySchema = IntercomAbilitySchema;
|
|
120513
120863
|
exports.IntercomStatusSchema = IntercomStatusSchema;
|
|
120514
120864
|
exports.InvalidRecordError = require_sleep.InvalidRecordError;
|
|
120865
|
+
exports.IrCodecError = IrCodecError;
|
|
120866
|
+
exports.IrMediumSchema = IrMediumSchema;
|
|
120867
|
+
exports.IrPayloadSchema = IrPayloadSchema;
|
|
120868
|
+
exports.IrSendResultSchema = IrSendResultSchema;
|
|
120869
|
+
exports.IrTimingsSchema = IrTimingsSchema;
|
|
120870
|
+
exports.IrTransmitterInfoSchema = IrTransmitterInfoSchema;
|
|
120515
120871
|
exports.KEYCHAIN_MAX_REFS_PER_CALL = KEYCHAIN_MAX_REFS_PER_CALL;
|
|
120516
120872
|
exports.KEYCHAIN_RESET_CONFIRMATION = KEYCHAIN_RESET_CONFIRMATION;
|
|
120517
120873
|
exports.KEYCHAIN_RESET_TRIGGER_ACTOR = KEYCHAIN_RESET_TRIGGER_ACTOR;
|
|
@@ -121663,6 +122019,8 @@ exports.TrainingResultSchema = TrainingResultSchema;
|
|
|
121663
122019
|
exports.TrainingSplitPlanSchema = TrainingSplitPlanSchema;
|
|
121664
122020
|
exports.TrainingStageSchema = TrainingStageSchema;
|
|
121665
122021
|
exports.TransactRefusedError = require_sleep.TransactRefusedError;
|
|
122022
|
+
exports.TransmitSettingKeySchema = TransmitSettingKeySchema;
|
|
122023
|
+
exports.TransmitSettingsSchema = TransmitSettingsSchema;
|
|
121666
122024
|
exports.TransportPlaneCountsSchema = TransportPlaneCountsSchema;
|
|
121667
122025
|
exports.TransportPlaneSchema = TransportPlaneSchema;
|
|
121668
122026
|
exports.TurnServerSchema = TurnServerSchema;
|
|
@@ -122008,6 +122366,7 @@ exports.declareLogChannel = declareLogChannel;
|
|
|
122008
122366
|
exports.declaredSeriesKind = declaredSeriesKind;
|
|
122009
122367
|
exports.decodeCompositionToCards = decodeCompositionToCards;
|
|
122010
122368
|
exports.decodeKeyedArrayOverride = decodeKeyedArrayOverride;
|
|
122369
|
+
exports.decodePronto = decodePronto;
|
|
122011
122370
|
exports.decodePulseOverride = decodePulseOverride;
|
|
122012
122371
|
exports.decodeScalarOverride = decodeScalarOverride;
|
|
122013
122372
|
exports.decodeVectorBase64 = decodeVectorBase64;
|
|
@@ -122223,6 +122582,7 @@ exports.interpretStoredClusterModel = interpretStoredClusterModel;
|
|
|
122223
122582
|
exports.invalidClusterStepModelEntries = invalidClusterStepModelEntries;
|
|
122224
122583
|
exports.invertPresetFeature = invertPresetFeature;
|
|
122225
122584
|
exports.invocationFromEncodeProfile = require_composition.invocationFromEncodeProfile;
|
|
122585
|
+
exports.irTransmitterCapability = irTransmitterCapability;
|
|
122226
122586
|
exports.isAgentOnlyPlacement = isAgentOnlyPlacement;
|
|
122227
122587
|
exports.isAlarmControllableCap = isAlarmControllableCap;
|
|
122228
122588
|
exports.isAlertEpisodeOpen = isAlertEpisodeOpen;
|
|
@@ -122461,6 +122821,7 @@ exports.parseSecretRef = require_sleep.parseSecretRef;
|
|
|
122461
122821
|
exports.parseSecretStatePath = require_sleep.parseSecretStatePath;
|
|
122462
122822
|
exports.parseSessionPlacementPolicy = parseSessionPlacementPolicy;
|
|
122463
122823
|
exports.parseShareSource = parseShareSource;
|
|
122824
|
+
exports.parseSmartIr = parseSmartIr;
|
|
122464
122825
|
exports.parseStreamParamsFormPatch = parseStreamParamsFormPatch;
|
|
122465
122826
|
exports.parseTrainingEventLine = parseTrainingEventLine;
|
|
122466
122827
|
exports.patchAudio = patchAudio;
|
|
@@ -122797,6 +123158,7 @@ exports.toNodeId = require_sleep.toNodeId;
|
|
|
122797
123158
|
exports.toPercentShares = toPercentShares;
|
|
122798
123159
|
exports.toSecretFieldView = require_sleep.toSecretFieldView;
|
|
122799
123160
|
exports.toStreamSourceEntry = toStreamSourceEntry;
|
|
123161
|
+
exports.toTimings = toTimings;
|
|
122800
123162
|
exports.toastCapability = toastCapability;
|
|
122801
123163
|
exports.toggleAudioLabel = toggleAudioLabel;
|
|
122802
123164
|
exports.tokenize = require_composition.tokenize;
|