@camstack/types 1.2.435 → 1.2.437

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/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_sleep = require("./sleep-DHitF_e4.js");
3
3
  const require_event_category = require("./event-category-E17zaHjN.js");
4
- const require_composition = require("./composition-BZf_gqG7.js");
4
+ const require_composition = require("./composition-WNkEpwkF.js");
5
5
  const require_node_color = require("./node-color.js");
6
6
  const require_err_msg = require("./err-msg-U7lLUMNz.js");
7
7
  const require_enums = require("./enums.js");
@@ -15574,12 +15574,13 @@ var CHANGED = {
15574
15574
  expr: "now"
15575
15575
  };
15576
15576
  function numeric(input) {
15577
+ const { alsoFrom, ...base } = input;
15577
15578
  return {
15578
- ...input,
15579
+ ...base,
15579
15580
  family: "numeric",
15580
15581
  deviceType: require_err_msg.DeviceType.Sensor,
15581
15582
  memberDeviceType: require_err_msg.DeviceType.Sensor,
15582
- memberDeviceTypes: [require_err_msg.DeviceType.Sensor],
15583
+ memberDeviceTypes: [require_err_msg.DeviceType.Sensor, ...alsoFrom?.deviceTypes ?? []],
15583
15584
  activeWhen: void 0,
15584
15585
  commandCaps: [],
15585
15586
  baseUnit: require_sleep.baseUnitOf(input.quantity),
@@ -15587,9 +15588,10 @@ function numeric(input) {
15587
15588
  accept: [{
15588
15589
  cap: input.outputCap,
15589
15590
  fieldPath: input.outputField
15590
- }]
15591
+ }, ...alsoFrom === void 0 ? [] : [alsoFrom.accept]]
15591
15592
  };
15592
15593
  }
15594
+ var CLIMATE_DEVICES = [require_err_msg.DeviceType.Thermostat, require_err_msg.DeviceType.Climate];
15593
15595
  function binary(input) {
15594
15596
  return {
15595
15597
  ...input,
@@ -15615,7 +15617,14 @@ var GROUP_TEMPLATES = [
15615
15617
  quantity: "temperature",
15616
15618
  defaultAggregate: "mean",
15617
15619
  empty: "null",
15618
- companions: [NOW$2]
15620
+ companions: [NOW$2],
15621
+ alsoFrom: {
15622
+ deviceTypes: CLIMATE_DEVICES,
15623
+ accept: {
15624
+ cap: "climate-control",
15625
+ fieldPath: "currentTemp"
15626
+ }
15627
+ }
15619
15628
  }),
15620
15629
  numeric({
15621
15630
  id: "humidity",
@@ -15626,7 +15635,14 @@ var GROUP_TEMPLATES = [
15626
15635
  quantity: "humidity",
15627
15636
  defaultAggregate: "mean",
15628
15637
  empty: "null",
15629
- companions: [NOW$2]
15638
+ companions: [NOW$2],
15639
+ alsoFrom: {
15640
+ deviceTypes: CLIMATE_DEVICES,
15641
+ accept: {
15642
+ cap: "climate-control",
15643
+ fieldPath: "currentHumidity"
15644
+ }
15645
+ }
15630
15646
  }),
15631
15647
  numeric({
15632
15648
  id: "pressure",
@@ -44634,6 +44650,17 @@ var LlmProfileSchema = zod.z.object({
44634
44650
  * field in its editor only when its descriptor lists it in `profileFields`. */
44635
44651
  topK: zod.z.number().int().positive().optional(),
44636
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(),
44637
44664
  /** Prompt context window. Advisory for cloud kinds (they enforce their own). */
44638
44665
  contextLength: zod.z.number().int().positive().optional(),
44639
44666
  /** Default system prompt. A caller's `system` REPLACES it (never appends —
@@ -44672,6 +44699,7 @@ var LlmProfileFieldSchema = zod.z.enum([
44672
44699
  "topP",
44673
44700
  "topK",
44674
44701
  "maxTokens",
44702
+ "reasoningEffort",
44675
44703
  "contextLength",
44676
44704
  "systemPrompt",
44677
44705
  "timeoutMs",
@@ -46320,6 +46348,43 @@ var NotificationActionSchema = zod.z.object({
46320
46348
  */
46321
46349
  mode: zod.z.enum(["navigate", "background"]).optional()
46322
46350
  });
46351
+ /** A delivery parameter value: what a notifier declared it takes. */
46352
+ var DeliveryParamValueSchema = zod.z.union([
46353
+ zod.z.string(),
46354
+ zod.z.number(),
46355
+ zod.z.boolean()
46356
+ ]);
46357
+ /**
46358
+ * One extra delivery parameter a notifier KIND declares (D938). A rule that
46359
+ * addresses a target of that kind may set it; a kind that declares nothing is
46360
+ * never handed one. The admin UI derives its control from this descriptor —
46361
+ * no editor knows a service by name.
46362
+ *
46363
+ * Optional fields are `.optional()`, never `.default()` (a Zod default does not
46364
+ * run on the addon cap path).
46365
+ */
46366
+ var DeliveryParamSchema = zod.z.object({
46367
+ key: zod.z.string().min(1),
46368
+ label: zod.z.string(),
46369
+ /** i18n key of the label, resolved by the declaring addon's namespace. */
46370
+ labelKey: zod.z.string().optional(),
46371
+ type: zod.z.enum([
46372
+ "enum",
46373
+ "number",
46374
+ "boolean",
46375
+ "string"
46376
+ ]),
46377
+ /** `enum` only: the closed set of accepted values. */
46378
+ options: zod.z.array(zod.z.object({
46379
+ value: zod.z.string(),
46380
+ label: zod.z.string()
46381
+ })).optional(),
46382
+ /** `number` only. */
46383
+ min: zod.z.number().optional(),
46384
+ max: zod.z.number().optional(),
46385
+ /** What the notifier does when the rule sets nothing; shown as the placeholder. */
46386
+ default: DeliveryParamValueSchema.optional()
46387
+ });
46323
46388
  /**
46324
46389
  * The canonical notification. `body` is the only hard field (Apprise model).
46325
46390
  * `priority` is a 5-level ORDINAL (1=lowest … 3=normal(default) … 5=urgent),
@@ -46342,7 +46407,13 @@ var NotificationSchema = zod.z.object({
46342
46407
  tag: zod.z.string().optional(),
46343
46408
  deviceId: zod.z.number().optional(),
46344
46409
  eventId: zod.z.string().optional(),
46345
- metadata: zod.z.record(zod.z.string(), zod.z.unknown()).optional()
46410
+ metadata: zod.z.record(zod.z.string(), zod.z.unknown()).optional(),
46411
+ /**
46412
+ * Values for the parameters the target's kind DECLARES in
46413
+ * {@link TargetKindSchema} `deliveryParams`. Already validated against the
46414
+ * declaration by the sender; a notifier reads only the keys it declared.
46415
+ */
46416
+ delivery: zod.z.record(zod.z.string(), DeliveryParamValueSchema).optional()
46346
46417
  });
46347
46418
  /** One declared native severity/priority level for a kind. */
46348
46419
  var TargetKindLevelSchema = zod.z.object({
@@ -46450,6 +46521,11 @@ var TargetKindSchema = zod.z.object({
46450
46521
  */
46451
46522
  destinationKeys: zod.z.array(zod.z.string()).optional(),
46452
46523
  supportsDiscovery: zod.z.boolean(),
46524
+ /**
46525
+ * Extra delivery parameters a rule may set for a target of this kind (D938).
46526
+ * Absent = none; the rule editor then offers nothing.
46527
+ */
46528
+ deliveryParams: zod.z.array(DeliveryParamSchema).optional(),
46453
46529
  caps: TargetKindCapsSchema
46454
46530
  });
46455
46531
  /**
@@ -63687,7 +63763,9 @@ var ManifestShapeSchema = zod.z.object({
63687
63763
  icon: zod.z.string().optional()
63688
63764
  }).optional(),
63689
63765
  protected: zod.z.boolean().optional(),
63690
- removable: zod.z.boolean().optional()
63766
+ removable: zod.z.boolean().optional(),
63767
+ /** Declared Integrations-page block (mirror of `AddonDeclaration.integrationSection`). */
63768
+ integrationSection: zod.z.enum(["system", "providers"]).optional()
63691
63769
  });
63692
63770
  var AddonProcessSchema = zod.z.object({
63693
63771
  pid: zod.z.number().optional(),
@@ -81397,6 +81475,7 @@ function evaluateAggregate(input) {
81397
81475
  function sourcePickForTemplate(template) {
81398
81476
  const valueKind = template.family === "numeric" ? "number" : template.activeWhen === void 0 ? "boolean" : "state";
81399
81477
  return {
81478
+ fieldChoice: template.family === "numeric" ? "first-match" : "operator",
81400
81479
  purpose: "member",
81401
81480
  multiple: true,
81402
81481
  max: 64,
@@ -81416,6 +81495,7 @@ function sourcePickForTemplate(template) {
81416
81495
  /** A statistic or integral reads one field that declares history. */
81417
81496
  function sourcePickForHistory(kind) {
81418
81497
  return {
81498
+ fieldChoice: "operator",
81419
81499
  purpose: "historised",
81420
81500
  multiple: false,
81421
81501
  max: 1,
@@ -81455,6 +81535,7 @@ function sourcePickForMath(kind) {
81455
81535
  const multiple = kind === "sum" || kind === "expression";
81456
81536
  const max = kind === "difference" || kind === "ratio" ? 2 : multiple ? 64 : 1;
81457
81537
  return {
81538
+ fieldChoice: "operator",
81458
81539
  purpose: "reading",
81459
81540
  multiple: multiple || max > 1,
81460
81541
  max,
@@ -109879,6 +109960,46 @@ function prepareNotification(caps, n) {
109879
109960
  };
109880
109961
  }
109881
109962
  //#endregion
109963
+ //#region src/notification/delivery-params.ts
109964
+ function valueFor(param, raw) {
109965
+ switch (param.type) {
109966
+ case "enum": return typeof raw === "string" && (param.options ?? []).some((o) => o.value === raw) ? raw : void 0;
109967
+ case "number": {
109968
+ if (typeof raw !== "number" || !Number.isFinite(raw)) return void 0;
109969
+ const floor = param.min ?? Number.NEGATIVE_INFINITY;
109970
+ const ceil = param.max ?? Number.POSITIVE_INFINITY;
109971
+ return Math.min(ceil, Math.max(floor, raw));
109972
+ }
109973
+ case "boolean": return typeof raw === "boolean" ? raw : void 0;
109974
+ case "string": return typeof raw === "string" && raw.length > 0 ? raw : void 0;
109975
+ }
109976
+ }
109977
+ /**
109978
+ * The values a rule target's `params` contribute for a kind: only declared
109979
+ * keys, only valid values. `undefined` when nothing survives — a notifier that
109980
+ * declared nothing is never handed a `delivery` block.
109981
+ */
109982
+ function resolveDeliveryParams(declared, params) {
109983
+ if (declared === void 0 || params === void 0) return void 0;
109984
+ const out = {};
109985
+ for (const param of declared) {
109986
+ const value = valueFor(param, params[param.key]);
109987
+ if (value !== void 0) out[param.key] = value;
109988
+ }
109989
+ return Object.keys(out).length > 0 ? out : void 0;
109990
+ }
109991
+ /** The union of several kinds' declarations; the first declaration of a key wins. */
109992
+ function deliveryParamsDeclaredBy(perKind) {
109993
+ const seen = /* @__PURE__ */ new Set();
109994
+ const out = [];
109995
+ for (const declared of perKind) for (const param of declared ?? []) {
109996
+ if (seen.has(param.key)) continue;
109997
+ seen.add(param.key);
109998
+ out.push(param);
109999
+ }
110000
+ return out;
110001
+ }
110002
+ //#endregion
109882
110003
  //#region src/notification/system-event-filters.ts
109883
110004
  /**
109884
110005
  * WHICH narrowing filter speaks about WHICH system-event kind — one predicate,
@@ -118171,6 +118292,29 @@ function rewriteSetCookie(cookie, route) {
118171
118292
  return kept.join("; ");
118172
118293
  }
118173
118294
  /**
118295
+ * Every Set-Cookie of one vendor response, rewritten. Dropping `Domain` folds cookies
118296
+ * the vendor keeps apart (`session-id` on `.amazon.it` and on `.www.amazon.it`) into
118297
+ * one, so a past-dated set that only deleted the other domain's copy would delete the
118298
+ * live one the same response just set: that deletion is dropped.
118299
+ */
118300
+ function rewriteSetCookies(cookies, route) {
118301
+ const now = Date.now();
118302
+ const liveNames = new Set(cookies.filter((c) => !isExpiredCookie(c, now)).map(cookieName));
118303
+ return cookies.filter((c) => !(isExpiredCookie(c, now) && liveNames.has(cookieName(c)))).map((c) => rewriteSetCookie(c, route));
118304
+ }
118305
+ function cookieName(cookie) {
118306
+ return cookie.split(";")[0]?.split("=")[0]?.trim() ?? "";
118307
+ }
118308
+ function isExpiredCookie(cookie, now) {
118309
+ const attrs = cookie.split(";").slice(1).map((part) => part.trim());
118310
+ const maxAge = attrs.find((a) => /^max-age=/i.test(a));
118311
+ if (maxAge !== void 0) return Number(maxAge.slice(8)) <= 0;
118312
+ const expires = attrs.find((a) => /^expires=/i.test(a));
118313
+ if (expires === void 0) return false;
118314
+ const at = Date.parse(expires.slice(8));
118315
+ return Number.isFinite(at) && at <= now;
118316
+ }
118317
+ /**
118174
118318
  * A browser `Referer` that points into this proxy, turned back into the vendor URL it
118175
118319
  * stands for. A Referer that is not ours is dropped (null): it names the hub.
118176
118320
  */
@@ -118189,6 +118333,29 @@ function rewriteReferer(referer, route) {
118189
118333
  if (upstream === void 0) return null;
118190
118334
  return `${upstream.scheme}://${upstream.host}${rest?.[2] ?? "/"}${url.search}`;
118191
118335
  }
118336
+ function decodeFormComponent(raw) {
118337
+ try {
118338
+ return decodeURIComponent(raw.replace(/\+/g, " "));
118339
+ } catch {
118340
+ return null;
118341
+ }
118342
+ }
118343
+ /**
118344
+ * An `application/x-www-form-urlencoded` body whose field VALUES that are proxy URLs of
118345
+ * this attempt (absolute or root-relative) are turned back into the vendor URL they stand
118346
+ * for — the page's hidden inputs were rewritten on the way out (`rewriteBody`), and the
118347
+ * vendor must get its own URL back. Field order and every untouched pair stay byte-identical.
118348
+ */
118349
+ function rewriteFormBody(body, route) {
118350
+ return body.split("&").map((pair) => {
118351
+ const eq = pair.indexOf("=");
118352
+ if (eq === -1) return pair;
118353
+ const value = decodeFormComponent(pair.slice(eq + 1));
118354
+ if (value === null || !/^(?:https?:\/\/|\/)/i.test(value)) return pair;
118355
+ const back = rewriteReferer(value, route);
118356
+ return back === null ? pair : `${pair.slice(0, eq + 1)}${encodeURIComponent(back)}`;
118357
+ }).join("&");
118358
+ }
118192
118359
  /** Cookies the browser holds for the hub itself must never reach a vendor. */
118193
118360
  function filterForwardedCookies(cookieHeader) {
118194
118361
  return cookieHeader.split(";").map((part) => part.trim()).filter((part) => part.length > 0 && !part.toLowerCase().startsWith("camstack_")).join("; ");
@@ -118249,6 +118416,9 @@ function bodyKindOf(contentType) {
118249
118416
  if (type.startsWith("text/") || type.includes("javascript") || type.includes("json") || type.includes("xml")) return "other";
118250
118417
  return null;
118251
118418
  }
118419
+ function isFormEncoded(contentType) {
118420
+ return (firstHeader(contentType) ?? "").toLowerCase().startsWith("application/x-www-form-urlencoded");
118421
+ }
118252
118422
  function firstHeader(value) {
118253
118423
  return Array.isArray(value) ? value[0] : value;
118254
118424
  }
@@ -118263,6 +118433,26 @@ async function readRequestBody(req) {
118263
118433
  }
118264
118434
  return Buffer.concat(chunks);
118265
118435
  }
118436
+ /** The path of the Referer sent upstream, or why none was sent — the query is never logged. */
118437
+ function forwardedRefererPath(forwarded, received) {
118438
+ if (forwarded !== void 0) return URL.canParse(forwarded) ? new URL(forwarded).pathname : "unparsable";
118439
+ return received === void 0 ? "absent" : "unmapped";
118440
+ }
118441
+ /** The form targets a vendor page posts to, path only (no query), so a lost path prefix is visible. */
118442
+ function formActionPaths(html) {
118443
+ const actions = [...html.matchAll(/<form\b[^>]*\baction\s*=\s*["']([^"']*)["']/gi)].map((m) => (m[1] ?? "").split("?")[0] ?? "").slice(0, 5);
118444
+ return actions.length === 0 ? "none" : actions.join(" | ");
118445
+ }
118446
+ /** Cookie NAMES only — values are session secrets and are never logged. */
118447
+ function cookieNames(header) {
118448
+ if (header === void 0 || header.length === 0) return "none";
118449
+ return header.split(";").map((part) => part.split("=")[0]?.trim() ?? "").join(",");
118450
+ }
118451
+ /** A Set-Cookie's name and attributes without its value, so a cookie the browser refuses is visible. */
118452
+ function setCookieShape(cookie) {
118453
+ const [first, ...attrs] = cookie.split(";").map((part) => part.trim());
118454
+ return [first?.split("=")[0] ?? "", ...attrs.filter((a) => !/^expires=/i.test(a))].join(";");
118455
+ }
118266
118456
  function sendPlain(res, status, text) {
118267
118457
  res.writeHead(status, {
118268
118458
  "content-type": "text/plain; charset=utf-8",
@@ -118379,7 +118569,7 @@ var VendorLoginProxy = class {
118379
118569
  sendPlain(res, 413, "Request too large");
118380
118570
  return;
118381
118571
  }
118382
- body = read;
118572
+ body = isFormEncoded(req.headers["content-type"]) ? Buffer.from(rewriteFormBody(read.toString("utf8"), route), "utf8") : read;
118383
118573
  }
118384
118574
  const headers = this.#requestHeaders(req, route, upstream);
118385
118575
  const upstreamRes = await this.#fetch(target, {
@@ -118393,11 +118583,16 @@ var VendorLoginProxy = class {
118393
118583
  const kind = bodyKindOf(upstreamRes.headers.get("content-type") ?? "");
118394
118584
  const declaredLength = Number(upstreamRes.headers.get("content-length") ?? "0");
118395
118585
  const text = kind !== null && !(declaredLength > MAX_TEXT_BODY_BYTES) && method !== "HEAD" ? await upstreamRes.text() : null;
118396
- this.#logger.debug("vendor login proxy: upstream answered", { meta: {
118586
+ this.#logger.info("vendor login proxy: upstream answered", { meta: {
118397
118587
  addonId: this.#addonId,
118398
118588
  host: upstream.host,
118589
+ path: target.pathname,
118399
118590
  status: upstreamRes.status,
118400
- method
118591
+ method,
118592
+ refererPath: forwardedRefererPath(headers["referer"], req.headers["referer"]),
118593
+ formActions: kind === "html" && text !== null ? formActionPaths(text) : void 0,
118594
+ sentNames: cookieNames(headers["cookie"]),
118595
+ vendorSets: setCookies.map(setCookieShape).join(" | ")
118401
118596
  } });
118402
118597
  const settled = await attempt.evaluate({
118403
118598
  status: upstreamRes.status,
@@ -118419,7 +118614,7 @@ var VendorLoginProxy = class {
118419
118614
  upstreamRes.headers.forEach((value, name) => {
118420
118615
  if (!DROP_RESPONSE_HEADERS.has(name.toLowerCase())) out[name] = value;
118421
118616
  });
118422
- if (setCookies.length > 0) out["set-cookie"] = setCookies.map((c) => rewriteSetCookie(c, route));
118617
+ if (setCookies.length > 0) out["set-cookie"] = rewriteSetCookies(setCookies, route);
118423
118618
  if (location !== null) out["location"] = rewriteLocation(location, upstream, route);
118424
118619
  out["cache-control"] = "no-store";
118425
118620
  if (text !== null && kind !== null) {
@@ -120086,6 +120281,8 @@ exports.DeclareKindResultSchema = DeclareKindResultSchema;
120086
120281
  exports.DeclaredDevices = DeclaredDevices;
120087
120282
  exports.DecodedAudioChunkSchema = require_sleep.DecodedAudioChunkSchema;
120088
120283
  exports.DeleteIntegrationResultSchema = DeleteIntegrationResultSchema;
120284
+ exports.DeliveryParamSchema = DeliveryParamSchema;
120285
+ exports.DeliveryParamValueSchema = DeliveryParamValueSchema;
120089
120286
  exports.DerivativeHelperSpecSchema = require_composition.DerivativeHelperSpecSchema;
120090
120287
  exports.DetailCropConventionSchema = DetailCropConventionSchema;
120091
120288
  exports.DetectionCatalogClassMapSchema = DetectionCatalogClassMapSchema;
@@ -121883,6 +122080,7 @@ exports.defineRecordKinds = require_sleep.defineRecordKinds;
121883
122080
  exports.dehydrateConfigField = require_sleep.dehydrateConfigField;
121884
122081
  exports.dehydrateSchema = require_sleep.dehydrateSchema;
121885
122082
  exports.deleteAlarmProfile = deleteAlarmProfile;
122083
+ exports.deliveryParamsDeclaredBy = deliveryParamsDeclaredBy;
121886
122084
  exports.derivativeDraft = derivativeDraft;
121887
122085
  exports.derivativeUnitLabel = derivativeUnitLabel;
121888
122086
  exports.deriveBatteryPresence = deriveBatteryPresence;
@@ -122441,6 +122639,7 @@ exports.resolveContainerPrimaryChild = resolveContainerPrimaryChild;
122441
122639
  exports.resolveCoreBlockEntry = resolveCoreBlockEntry;
122442
122640
  exports.resolveCoreBlockFiles = resolveCoreBlockFiles;
122443
122641
  exports.resolveCreateExportSubject = resolveCreateExportSubject;
122642
+ exports.resolveDeliveryParams = resolveDeliveryParams;
122444
122643
  exports.resolveDeviceControlKind = resolveDeviceControlKind;
122445
122644
  exports.resolveDeviceProfile = resolveDeviceProfile;
122446
122645
  exports.resolveDeviceTarget = resolveDeviceTarget;