@camstack/types 1.2.436 → 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/CHANGELOG.md CHANGED
@@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [1.2.437] - 2026-10-28
11
+
12
+ ### Changed
13
+
14
+ - The vendor sign-in proxy keeps the vendor's session cookie when the vendor also deletes a same-named cookie on another domain
15
+ - An AI profile can turn the model's thinking off or set its effort
16
+
10
17
  ## [1.2.436] - 2026-10-28
11
18
 
12
19
  ### Changed
@@ -63,6 +63,12 @@ export declare const LlmProfileSchema: z.ZodObject<{
63
63
  topP: z.ZodOptional<z.ZodNumber>;
64
64
  topK: z.ZodOptional<z.ZodNumber>;
65
65
  maxTokens: z.ZodOptional<z.ZodNumber>;
66
+ reasoningEffort: z.ZodOptional<z.ZodEnum<{
67
+ high: "high";
68
+ low: "low";
69
+ medium: "medium";
70
+ off: "off";
71
+ }>>;
66
72
  contextLength: z.ZodOptional<z.ZodNumber>;
67
73
  systemPrompt: z.ZodOptional<z.ZodString>;
68
74
  timeoutMs: z.ZodDefault<z.ZodNumber>;
@@ -87,6 +93,7 @@ export declare const LlmProfileFieldSchema: z.ZodEnum<{
87
93
  firstTokenTimeoutMs: "firstTokenTimeoutMs";
88
94
  idleTimeoutMs: "idleTimeoutMs";
89
95
  maxTokens: "maxTokens";
96
+ reasoningEffort: "reasoningEffort";
90
97
  retry: "retry";
91
98
  systemPrompt: "systemPrompt";
92
99
  temperature: "temperature";
@@ -144,6 +151,7 @@ export declare const LlmProfileKindDescriptorSchema: z.ZodObject<{
144
151
  firstTokenTimeoutMs: "firstTokenTimeoutMs";
145
152
  idleTimeoutMs: "idleTimeoutMs";
146
153
  maxTokens: "maxTokens";
154
+ reasoningEffort: "reasoningEffort";
147
155
  retry: "retry";
148
156
  systemPrompt: "systemPrompt";
149
157
  temperature: "temperature";
@@ -527,6 +535,7 @@ export declare const llmCapability: {
527
535
  firstTokenTimeoutMs: "firstTokenTimeoutMs";
528
536
  idleTimeoutMs: "idleTimeoutMs";
529
537
  maxTokens: "maxTokens";
538
+ reasoningEffort: "reasoningEffort";
530
539
  retry: "retry";
531
540
  systemPrompt: "systemPrompt";
532
541
  temperature: "temperature";
@@ -556,6 +565,12 @@ export declare const llmCapability: {
556
565
  topP: z.ZodOptional<z.ZodNumber>;
557
566
  topK: z.ZodOptional<z.ZodNumber>;
558
567
  maxTokens: z.ZodOptional<z.ZodNumber>;
568
+ reasoningEffort: z.ZodOptional<z.ZodEnum<{
569
+ high: "high";
570
+ low: "low";
571
+ medium: "medium";
572
+ off: "off";
573
+ }>>;
559
574
  contextLength: z.ZodOptional<z.ZodNumber>;
560
575
  systemPrompt: z.ZodOptional<z.ZodString>;
561
576
  timeoutMs: z.ZodDefault<z.ZodNumber>;
@@ -582,6 +597,12 @@ export declare const llmCapability: {
582
597
  topP: z.ZodOptional<z.ZodNumber>;
583
598
  topK: z.ZodOptional<z.ZodNumber>;
584
599
  maxTokens: z.ZodOptional<z.ZodNumber>;
600
+ reasoningEffort: z.ZodOptional<z.ZodEnum<{
601
+ high: "high";
602
+ low: "low";
603
+ medium: "medium";
604
+ off: "off";
605
+ }>>;
585
606
  contextLength: z.ZodOptional<z.ZodNumber>;
586
607
  systemPrompt: z.ZodOptional<z.ZodString>;
587
608
  timeoutMs: z.ZodDefault<z.ZodNumber>;
@@ -607,6 +628,12 @@ export declare const llmCapability: {
607
628
  topP: z.ZodOptional<z.ZodNumber>;
608
629
  topK: z.ZodOptional<z.ZodNumber>;
609
630
  maxTokens: z.ZodOptional<z.ZodNumber>;
631
+ reasoningEffort: z.ZodOptional<z.ZodEnum<{
632
+ high: "high";
633
+ low: "low";
634
+ medium: "medium";
635
+ off: "off";
636
+ }>>;
610
637
  contextLength: z.ZodOptional<z.ZodNumber>;
611
638
  systemPrompt: z.ZodOptional<z.ZodString>;
612
639
  timeoutMs: z.ZodDefault<z.ZodNumber>;
package/dist/index.js CHANGED
@@ -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",
@@ -118280,6 +118292,29 @@ function rewriteSetCookie(cookie, route) {
118280
118292
  return kept.join("; ");
118281
118293
  }
118282
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
+ /**
118283
118318
  * A browser `Referer` that points into this proxy, turned back into the vendor URL it
118284
118319
  * stands for. A Referer that is not ours is dropped (null): it names the hub.
118285
118320
  */
@@ -118398,6 +118433,26 @@ async function readRequestBody(req) {
118398
118433
  }
118399
118434
  return Buffer.concat(chunks);
118400
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
+ }
118401
118456
  function sendPlain(res, status, text) {
118402
118457
  res.writeHead(status, {
118403
118458
  "content-type": "text/plain; charset=utf-8",
@@ -118533,7 +118588,11 @@ var VendorLoginProxy = class {
118533
118588
  host: upstream.host,
118534
118589
  path: target.pathname,
118535
118590
  status: upstreamRes.status,
118536
- 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(" | ")
118537
118596
  } });
118538
118597
  const settled = await attempt.evaluate({
118539
118598
  status: upstreamRes.status,
@@ -118555,7 +118614,7 @@ var VendorLoginProxy = class {
118555
118614
  upstreamRes.headers.forEach((value, name) => {
118556
118615
  if (!DROP_RESPONSE_HEADERS.has(name.toLowerCase())) out[name] = value;
118557
118616
  });
118558
- if (setCookies.length > 0) out["set-cookie"] = setCookies.map((c) => rewriteSetCookie(c, route));
118617
+ if (setCookies.length > 0) out["set-cookie"] = rewriteSetCookies(setCookies, route);
118559
118618
  if (location !== null) out["location"] = rewriteLocation(location, upstream, route);
118560
118619
  out["cache-control"] = "no-store";
118561
118620
  if (text !== null && kind !== null) {
package/dist/index.mjs CHANGED
@@ -44649,6 +44649,17 @@ var LlmProfileSchema = z.object({
44649
44649
  * field in its editor only when its descriptor lists it in `profileFields`. */
44650
44650
  topK: z.number().int().positive().optional(),
44651
44651
  maxTokens: z.number().int().positive().optional(),
44652
+ /** How hard the model "thinks" before it answers. Omitted = the model's own
44653
+ * default. `off` matters for structured output: a thinking model can spend
44654
+ * the whole completion on reasoning and return an empty `content`. Carried
44655
+ * only by the wires that have it — a kind offers the field in its editor
44656
+ * only when its descriptor lists it in `profileFields`. */
44657
+ reasoningEffort: z.enum([
44658
+ "off",
44659
+ "low",
44660
+ "medium",
44661
+ "high"
44662
+ ]).optional(),
44652
44663
  /** Prompt context window. Advisory for cloud kinds (they enforce their own). */
44653
44664
  contextLength: z.number().int().positive().optional(),
44654
44665
  /** Default system prompt. A caller's `system` REPLACES it (never appends —
@@ -44687,6 +44698,7 @@ var LlmProfileFieldSchema = z.enum([
44687
44698
  "topP",
44688
44699
  "topK",
44689
44700
  "maxTokens",
44701
+ "reasoningEffort",
44690
44702
  "contextLength",
44691
44703
  "systemPrompt",
44692
44704
  "timeoutMs",
@@ -118279,6 +118291,29 @@ function rewriteSetCookie(cookie, route) {
118279
118291
  return kept.join("; ");
118280
118292
  }
118281
118293
  /**
118294
+ * Every Set-Cookie of one vendor response, rewritten. Dropping `Domain` folds cookies
118295
+ * the vendor keeps apart (`session-id` on `.amazon.it` and on `.www.amazon.it`) into
118296
+ * one, so a past-dated set that only deleted the other domain's copy would delete the
118297
+ * live one the same response just set: that deletion is dropped.
118298
+ */
118299
+ function rewriteSetCookies(cookies, route) {
118300
+ const now = Date.now();
118301
+ const liveNames = new Set(cookies.filter((c) => !isExpiredCookie(c, now)).map(cookieName));
118302
+ return cookies.filter((c) => !(isExpiredCookie(c, now) && liveNames.has(cookieName(c)))).map((c) => rewriteSetCookie(c, route));
118303
+ }
118304
+ function cookieName(cookie) {
118305
+ return cookie.split(";")[0]?.split("=")[0]?.trim() ?? "";
118306
+ }
118307
+ function isExpiredCookie(cookie, now) {
118308
+ const attrs = cookie.split(";").slice(1).map((part) => part.trim());
118309
+ const maxAge = attrs.find((a) => /^max-age=/i.test(a));
118310
+ if (maxAge !== void 0) return Number(maxAge.slice(8)) <= 0;
118311
+ const expires = attrs.find((a) => /^expires=/i.test(a));
118312
+ if (expires === void 0) return false;
118313
+ const at = Date.parse(expires.slice(8));
118314
+ return Number.isFinite(at) && at <= now;
118315
+ }
118316
+ /**
118282
118317
  * A browser `Referer` that points into this proxy, turned back into the vendor URL it
118283
118318
  * stands for. A Referer that is not ours is dropped (null): it names the hub.
118284
118319
  */
@@ -118397,6 +118432,26 @@ async function readRequestBody(req) {
118397
118432
  }
118398
118433
  return Buffer.concat(chunks);
118399
118434
  }
118435
+ /** The path of the Referer sent upstream, or why none was sent — the query is never logged. */
118436
+ function forwardedRefererPath(forwarded, received) {
118437
+ if (forwarded !== void 0) return URL.canParse(forwarded) ? new URL(forwarded).pathname : "unparsable";
118438
+ return received === void 0 ? "absent" : "unmapped";
118439
+ }
118440
+ /** The form targets a vendor page posts to, path only (no query), so a lost path prefix is visible. */
118441
+ function formActionPaths(html) {
118442
+ const actions = [...html.matchAll(/<form\b[^>]*\baction\s*=\s*["']([^"']*)["']/gi)].map((m) => (m[1] ?? "").split("?")[0] ?? "").slice(0, 5);
118443
+ return actions.length === 0 ? "none" : actions.join(" | ");
118444
+ }
118445
+ /** Cookie NAMES only — values are session secrets and are never logged. */
118446
+ function cookieNames(header) {
118447
+ if (header === void 0 || header.length === 0) return "none";
118448
+ return header.split(";").map((part) => part.split("=")[0]?.trim() ?? "").join(",");
118449
+ }
118450
+ /** A Set-Cookie's name and attributes without its value, so a cookie the browser refuses is visible. */
118451
+ function setCookieShape(cookie) {
118452
+ const [first, ...attrs] = cookie.split(";").map((part) => part.trim());
118453
+ return [first?.split("=")[0] ?? "", ...attrs.filter((a) => !/^expires=/i.test(a))].join(";");
118454
+ }
118400
118455
  function sendPlain(res, status, text) {
118401
118456
  res.writeHead(status, {
118402
118457
  "content-type": "text/plain; charset=utf-8",
@@ -118532,7 +118587,11 @@ var VendorLoginProxy = class {
118532
118587
  host: upstream.host,
118533
118588
  path: target.pathname,
118534
118589
  status: upstreamRes.status,
118535
- method
118590
+ method,
118591
+ refererPath: forwardedRefererPath(headers["referer"], req.headers["referer"]),
118592
+ formActions: kind === "html" && text !== null ? formActionPaths(text) : void 0,
118593
+ sentNames: cookieNames(headers["cookie"]),
118594
+ vendorSets: setCookies.map(setCookieShape).join(" | ")
118536
118595
  } });
118537
118596
  const settled = await attempt.evaluate({
118538
118597
  status: upstreamRes.status,
@@ -118554,7 +118613,7 @@ var VendorLoginProxy = class {
118554
118613
  upstreamRes.headers.forEach((value, name) => {
118555
118614
  if (!DROP_RESPONSE_HEADERS.has(name.toLowerCase())) out[name] = value;
118556
118615
  });
118557
- if (setCookies.length > 0) out["set-cookie"] = setCookies.map((c) => rewriteSetCookie(c, route));
118616
+ if (setCookies.length > 0) out["set-cookie"] = rewriteSetCookies(setCookies, route);
118558
118617
  if (location !== null) out["location"] = rewriteLocation(location, upstream, route);
118559
118618
  out["cache-control"] = "no-store";
118560
118619
  if (text !== null && kind !== null) {
@@ -1,3 +1,3 @@
1
1
  export { VendorLoginProxy, type LoginProxyAttemptSpec, type LoginProxyResponseView, type LoginProxyVerdict, type VendorLoginProxyOptions, } from './login-proxy.js';
2
- export { rewriteBody, rewriteLocation, rewriteReferer, rewriteFormBody, rewriteSetCookie, type LoginProxyRoute, type LoginProxyScheme, type LoginProxyUpstream, } from './url-rewrite.js';
2
+ export { rewriteBody, rewriteLocation, rewriteReferer, rewriteFormBody, rewriteSetCookie, rewriteSetCookies, type LoginProxyRoute, type LoginProxyScheme, type LoginProxyUpstream, } from './url-rewrite.js';
3
3
  export { VENDOR_LOGIN_PROXY_PREFIX } from './prefix.js';
@@ -59,6 +59,13 @@ export declare function rewriteBody(body: string, kind: BodyKind, currentUpstrea
59
59
  * origin), `Path` narrowed to this attempt's prefix, `Secure` kept (the hub is HTTPS).
60
60
  */
61
61
  export declare function rewriteSetCookie(cookie: string, route: LoginProxyRoute): string;
62
+ /**
63
+ * Every Set-Cookie of one vendor response, rewritten. Dropping `Domain` folds cookies
64
+ * the vendor keeps apart (`session-id` on `.amazon.it` and on `.www.amazon.it`) into
65
+ * one, so a past-dated set that only deleted the other domain's copy would delete the
66
+ * live one the same response just set: that deletion is dropped.
67
+ */
68
+ export declare function rewriteSetCookies(cookies: readonly string[], route: LoginProxyRoute): string[];
62
69
  /**
63
70
  * A browser `Referer` that points into this proxy, turned back into the vendor URL it
64
71
  * stands for. A Referer that is not ours is dropped (null): it names the hub.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/types",
3
- "version": "1.2.436",
3
+ "version": "1.2.437",
4
4
  "description": "Shared types, interfaces, and model catalogs for the CamStack detection ecosystem",
5
5
  "keywords": [
6
6
  "camstack",