@docyrus/docyrus 0.0.41 → 0.0.42

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. package/README.md +2 -0
  2. package/main.js +1823 -697
  3. package/main.js.map +4 -4
  4. package/package.json +8 -7
  5. package/resources/pi-agent/extensions/control.ts +0 -8
  6. package/resources/pi-agent/extensions/knowledge.ts +0 -7
  7. package/resources/pi-agent/extensions/loop.ts +1 -5
  8. package/resources/pi-agent/extensions/pi-bash-live-view/package.json +1 -1
  9. package/resources/pi-agent/extensions/pi-custom-compaction/events/register-events.ts +0 -10
  10. package/resources/pi-agent/extensions/pi-custom-compaction/package.json +4 -4
  11. package/resources/pi-agent/extensions/plan.ts +0 -4
  12. package/resources/pi-agent/extensions/prompt-editor.ts +0 -18
  13. package/resources/pi-agent/extensions/prompt-url-widget.ts +0 -4
  14. package/resources/pi-agent/extensions/review.ts +0 -4
  15. package/resources/pi-agent/skills/agent-browser/SKILL.md +779 -0
  16. package/resources/pi-agent/skills/agent-browser/references/authentication.md +303 -0
  17. package/resources/pi-agent/skills/agent-browser/references/commands.md +295 -0
  18. package/resources/pi-agent/skills/agent-browser/references/profiling.md +120 -0
  19. package/resources/pi-agent/skills/agent-browser/references/proxy-support.md +194 -0
  20. package/resources/pi-agent/skills/agent-browser/references/session-management.md +193 -0
  21. package/resources/pi-agent/skills/agent-browser/references/snapshot-refs.md +219 -0
  22. package/resources/pi-agent/skills/agent-browser/references/video-recording.md +173 -0
  23. package/resources/pi-agent/skills/agent-browser/templates/authenticated-session.sh +105 -0
  24. package/resources/pi-agent/skills/agent-browser/templates/capture-workflow.sh +69 -0
  25. package/resources/pi-agent/skills/agent-browser/templates/form-automation.sh +62 -0
  26. package/resources/pi-agent/skills/docyrus-platform/references/docyrus-cli-usage.md +73 -0
  27. package/resources/pi-agent/skills/grill-me/SKILL.md +109 -0
  28. package/server-loader.js +79 -28
  29. package/server-loader.js.map +4 -4
@@ -0,0 +1,109 @@
1
+ ---
2
+ name: grill-me
3
+ description: >
4
+ Interview the user relentlessly about a plan, architecture, or data model design until reaching shared understanding, resolving each branch of the decision tree. Use when the user wants to stress-test a plan, get grilled on their design, or mentions "grill me".
5
+
6
+ **Triggers — use this skill when:**
7
+ - User says "grill me", "stress test this", "challenge my design"
8
+ - User asks to "poke holes", "find gaps", "review my thinking"
9
+ - User wants to validate a plan before implementing
10
+ - User says "interview me about this", "question my decisions"
11
+ - Used after `/architect` or `/plan` when the user wants to pressure-test the output
12
+ ---
13
+
14
+ # Grill Me
15
+
16
+ Interview the user relentlessly about every aspect of their plan until reaching a shared understanding. Walk down each branch of the design tree, resolving dependencies between decisions one by one.
17
+
18
+ ## How It Works
19
+
20
+ Ask questions **one at a time**. For each question, provide your recommended answer based on what you know about the codebase and the Docyrus platform.
21
+
22
+ If a question can be answered by exploring the codebase or the discovery snapshot, explore it yourself instead of asking.
23
+
24
+ ## Question Domains
25
+
26
+ Work through these domains systematically, but adapt the order based on what matters most for the specific plan:
27
+
28
+ ### Data Model
29
+
30
+ - Why this data source and not an extension of an existing one?
31
+ - What is the expected record volume? Does the schema hold up at 10x scale?
32
+ - Are there fields that should be computed (formulas) instead of stored?
33
+ - Could any proposed data source be replaced by a custom query instead?
34
+ - Are slug and naming choices consistent with existing tenant conventions?
35
+
36
+ ### Field Design
37
+
38
+ - Is this the right field type? (e.g., `field-select` vs `field-radioGroup`, `field-text` vs `field-richText`)
39
+ - Should this field be required, optional, or have a default value?
40
+ - Are validation rules sufficient? Too strict? Missing edge cases?
41
+ - For relation fields: is the cardinality correct? Should it be bidirectional?
42
+ - Are there fields that will rarely be used and could be deferred?
43
+
44
+ ### Enumerations
45
+
46
+ - Are enum options exhaustive? What happens when a new option is needed later?
47
+ - Should this be an enum or a separate data source with its own lifecycle?
48
+ - Are enum values and labels clear and consistent?
49
+ - Is the ordering intentional?
50
+
51
+ ### Relations and Dependencies
52
+
53
+ - What is the dependency graph between data sources? Are there cycles?
54
+ - What happens when a related record is deleted?
55
+ - Are there implicit relations that should be explicit?
56
+ - Does the creation order in the apply plan respect all dependencies?
57
+
58
+ ### Access Control and Security
59
+
60
+ - Who should be able to read/write/delete these records?
61
+ - Are there tenant-level vs app-level permission considerations?
62
+ - Should any fields be hidden or read-only for certain roles?
63
+
64
+ ### Edge Cases and Failure Modes
65
+
66
+ - What happens with empty states? First record ever created?
67
+ - What if the user enters unexpected data?
68
+ - Are there race conditions in concurrent record creation?
69
+ - What if a bulk import has partial failures?
70
+
71
+ ### Implementation Feasibility
72
+
73
+ - Can this be built with existing Docyrus field types, or does it require platform changes?
74
+ - Are there known limitations in the current API that affect this design?
75
+ - Is the proposed migration path realistic?
76
+
77
+ ## Interview Protocol
78
+
79
+ 1. Start by reading the plan or architecture artifacts (PLAN.md, DATA_SOURCES.md, discovery snapshot, or whatever is available).
80
+ 2. Identify the most critical or uncertain decision in the plan.
81
+ 3. Ask one focused question about it, with your recommended answer.
82
+ 4. Based on the user's response, either drill deeper into that branch or move to the next decision.
83
+ 5. Track resolved decisions and open questions as you go.
84
+ 6. When all major branches are resolved, summarize the final shared understanding.
85
+
86
+ ## Output on Completion
87
+
88
+ When the interview is complete, produce a summary:
89
+
90
+ ```markdown
91
+ ## Resolved Decisions
92
+
93
+ - [Decision 1]: [Resolution]
94
+ - [Decision 2]: [Resolution]
95
+ ...
96
+
97
+ ## Changes to the Plan
98
+
99
+ - [Change 1]
100
+ - [Change 2]
101
+ ...
102
+
103
+ ## Remaining Open Questions
104
+
105
+ - [Question 1]
106
+ ...
107
+ ```
108
+
109
+ If the plan artifacts exist on disk (PLAN.md, data-sources.plan.json), offer to update them with the resolved decisions.
package/server-loader.js CHANGED
@@ -13288,7 +13288,7 @@ var require_promise = __commonJS({
13288
13288
  }
13289
13289
  });
13290
13290
 
13291
- // ../../node_modules/.pnpm/@hono+node-server@1.19.11_hono@4.12.8/node_modules/@hono/node-server/dist/index.mjs
13291
+ // ../../node_modules/.pnpm/@hono+node-server@1.19.13_hono@4.12.12/node_modules/@hono/node-server/dist/index.mjs
13292
13292
  var dist_exports = {};
13293
13293
  __export(dist_exports, {
13294
13294
  RequestError: () => RequestError,
@@ -13341,9 +13341,9 @@ function writeFromReadableStream(stream, writable) {
13341
13341
  }
13342
13342
  return writeFromReadableStreamDefaultReader(stream.getReader(), writable);
13343
13343
  }
13344
- var import_http, import_http2, import_http22, import_stream, import_crypto, RequestError, toRequestError, GlobalRequest, Request2, newHeadersFromIncoming, wrapBodyStream, newRequestFromIncoming, getRequestCache, requestCache, incomingKey, urlKey, headersKey, abortControllerKey, getAbortController, requestPrototype, newRequest, responseCache, getResponseCache, cacheKey, GlobalResponse, Response2, buildOutgoingHttpHeaders, X_ALREADY_SENT, outgoingEnded, handleRequestError, handleFetchError, handleResponseError, flushHeaders, responseViaCache, isPromise, responseViaResponseObject, getRequestListener, createAdaptorServer, serve;
13344
+ var import_http, import_http2, import_http22, import_stream, import_crypto, RequestError, toRequestError, GlobalRequest, Request2, newHeadersFromIncoming, wrapBodyStream, newRequestFromIncoming, getRequestCache, requestCache, incomingKey, urlKey, headersKey, abortControllerKey, getAbortController, requestPrototype, newRequest, responseCache, getResponseCache, cacheKey, GlobalResponse, Response2, buildOutgoingHttpHeaders, X_ALREADY_SENT, outgoingEnded, incomingDraining, DRAIN_TIMEOUT_MS, MAX_DRAIN_BYTES, drainIncoming, handleRequestError, handleFetchError, handleResponseError, flushHeaders, responseViaCache, isPromise, responseViaResponseObject, getRequestListener, createAdaptorServer, serve;
13345
13345
  var init_dist = __esm({
13346
- "../../node_modules/.pnpm/@hono+node-server@1.19.11_hono@4.12.8/node_modules/@hono/node-server/dist/index.mjs"() {
13346
+ "../../node_modules/.pnpm/@hono+node-server@1.19.13_hono@4.12.12/node_modules/@hono/node-server/dist/index.mjs"() {
13347
13347
  "use strict";
13348
13348
  import_http = require("http");
13349
13349
  import_http2 = require("http2");
@@ -13624,6 +13624,50 @@ var init_dist = __esm({
13624
13624
  global.crypto = import_crypto.default;
13625
13625
  }
13626
13626
  outgoingEnded = /* @__PURE__ */ Symbol("outgoingEnded");
13627
+ incomingDraining = /* @__PURE__ */ Symbol("incomingDraining");
13628
+ DRAIN_TIMEOUT_MS = 500;
13629
+ MAX_DRAIN_BYTES = 64 * 1024 * 1024;
13630
+ drainIncoming = (incoming) => {
13631
+ const incomingWithDrainState = incoming;
13632
+ if (incoming.destroyed || incomingWithDrainState[incomingDraining]) {
13633
+ return;
13634
+ }
13635
+ incomingWithDrainState[incomingDraining] = true;
13636
+ if (incoming instanceof import_http2.Http2ServerRequest) {
13637
+ try {
13638
+ ;
13639
+ incoming.stream?.close?.(import_http2.constants.NGHTTP2_NO_ERROR);
13640
+ } catch {
13641
+ }
13642
+ return;
13643
+ }
13644
+ let bytesRead = 0;
13645
+ const cleanup = () => {
13646
+ clearTimeout(timer);
13647
+ incoming.off("data", onData);
13648
+ incoming.off("end", cleanup);
13649
+ incoming.off("error", cleanup);
13650
+ };
13651
+ const forceClose = () => {
13652
+ cleanup();
13653
+ const socket = incoming.socket;
13654
+ if (socket && !socket.destroyed) {
13655
+ socket.destroySoon();
13656
+ }
13657
+ };
13658
+ const timer = setTimeout(forceClose, DRAIN_TIMEOUT_MS);
13659
+ timer.unref?.();
13660
+ const onData = (chunk) => {
13661
+ bytesRead += chunk.length;
13662
+ if (bytesRead > MAX_DRAIN_BYTES) {
13663
+ forceClose();
13664
+ }
13665
+ };
13666
+ incoming.on("data", onData);
13667
+ incoming.on("end", cleanup);
13668
+ incoming.on("error", cleanup);
13669
+ incoming.resume();
13670
+ };
13627
13671
  handleRequestError = () => new Response(null, {
13628
13672
  status: 400
13629
13673
  });
@@ -13795,14 +13839,18 @@ var init_dist = __esm({
13795
13839
  setTimeout(() => {
13796
13840
  if (!incomingEnded) {
13797
13841
  setTimeout(() => {
13798
- incoming.destroy();
13799
- outgoing.destroy();
13842
+ drainIncoming(incoming);
13800
13843
  });
13801
13844
  }
13802
13845
  });
13803
13846
  }
13804
13847
  };
13805
13848
  }
13849
+ outgoing.on("finish", () => {
13850
+ if (!incomingEnded) {
13851
+ drainIncoming(incoming);
13852
+ }
13853
+ });
13806
13854
  }
13807
13855
  outgoing.on("close", () => {
13808
13856
  const abortController = req[abortControllerKey];
@@ -13817,7 +13865,7 @@ var init_dist = __esm({
13817
13865
  setTimeout(() => {
13818
13866
  if (!incomingEnded) {
13819
13867
  setTimeout(() => {
13820
- incoming.destroy();
13868
+ drainIncoming(incoming);
13821
13869
  });
13822
13870
  }
13823
13871
  });
@@ -14003,7 +14051,7 @@ var import_node_crypto6 = require("node:crypto");
14003
14051
  var import_promises14 = require("node:fs/promises");
14004
14052
  var import_node_path18 = require("node:path");
14005
14053
 
14006
- // ../../node_modules/.pnpm/hono@4.12.8/node_modules/hono/dist/compose.js
14054
+ // ../../node_modules/.pnpm/hono@4.12.12/node_modules/hono/dist/compose.js
14007
14055
  var compose = (middleware, onError, onNotFound) => {
14008
14056
  return (context, next) => {
14009
14057
  let index2 = -1;
@@ -14047,10 +14095,10 @@ var compose = (middleware, onError, onNotFound) => {
14047
14095
  };
14048
14096
  };
14049
14097
 
14050
- // ../../node_modules/.pnpm/hono@4.12.8/node_modules/hono/dist/request/constants.js
14098
+ // ../../node_modules/.pnpm/hono@4.12.12/node_modules/hono/dist/request/constants.js
14051
14099
  var GET_MATCH_RESULT = /* @__PURE__ */ Symbol();
14052
14100
 
14053
- // ../../node_modules/.pnpm/hono@4.12.8/node_modules/hono/dist/utils/body.js
14101
+ // ../../node_modules/.pnpm/hono@4.12.12/node_modules/hono/dist/utils/body.js
14054
14102
  var parseBody = async (request, options = /* @__PURE__ */ Object.create(null)) => {
14055
14103
  const { all: all2 = false, dot = false } = options;
14056
14104
  const headers = request instanceof HonoRequest ? request.raw.headers : request.headers;
@@ -14122,7 +14170,7 @@ var handleParsingNestedValues = (form, key, value2) => {
14122
14170
  });
14123
14171
  };
14124
14172
 
14125
- // ../../node_modules/.pnpm/hono@4.12.8/node_modules/hono/dist/utils/url.js
14173
+ // ../../node_modules/.pnpm/hono@4.12.12/node_modules/hono/dist/utils/url.js
14126
14174
  var splitPath = (path3) => {
14127
14175
  const paths = path3.split("/");
14128
14176
  if (paths[0] === "") {
@@ -14326,7 +14374,7 @@ var getQueryParams = (url, key) => {
14326
14374
  };
14327
14375
  var decodeURIComponent_ = decodeURIComponent;
14328
14376
 
14329
- // ../../node_modules/.pnpm/hono@4.12.8/node_modules/hono/dist/request.js
14377
+ // ../../node_modules/.pnpm/hono@4.12.12/node_modules/hono/dist/request.js
14330
14378
  var tryDecodeURIComponent = (str) => tryDecode(str, decodeURIComponent_);
14331
14379
  var HonoRequest = class {
14332
14380
  /**
@@ -14407,7 +14455,7 @@ var HonoRequest = class {
14407
14455
  return headerData;
14408
14456
  }
14409
14457
  async parseBody(options) {
14410
- return this.bodyCache.parsedBody ??= await parseBody(this, options);
14458
+ return parseBody(this, options);
14411
14459
  }
14412
14460
  #cachedBody = (key) => {
14413
14461
  const { bodyCache, raw: raw2 } = this;
@@ -14594,7 +14642,7 @@ var HonoRequest = class {
14594
14642
  }
14595
14643
  };
14596
14644
 
14597
- // ../../node_modules/.pnpm/hono@4.12.8/node_modules/hono/dist/utils/html.js
14645
+ // ../../node_modules/.pnpm/hono@4.12.12/node_modules/hono/dist/utils/html.js
14598
14646
  var HtmlEscapedCallbackPhase = {
14599
14647
  Stringify: 1,
14600
14648
  BeforeStream: 2,
@@ -14636,7 +14684,7 @@ var resolveCallback = async (str, phase, preserveCallbacks, context, buffer) =>
14636
14684
  }
14637
14685
  };
14638
14686
 
14639
- // ../../node_modules/.pnpm/hono@4.12.8/node_modules/hono/dist/context.js
14687
+ // ../../node_modules/.pnpm/hono@4.12.12/node_modules/hono/dist/context.js
14640
14688
  var TEXT_PLAIN = "text/plain; charset=UTF-8";
14641
14689
  var setDefaultContentType = (contentType, headers) => {
14642
14690
  return {
@@ -15043,7 +15091,7 @@ var Context = class {
15043
15091
  };
15044
15092
  };
15045
15093
 
15046
- // ../../node_modules/.pnpm/hono@4.12.8/node_modules/hono/dist/router.js
15094
+ // ../../node_modules/.pnpm/hono@4.12.12/node_modules/hono/dist/router.js
15047
15095
  var METHOD_NAME_ALL = "ALL";
15048
15096
  var METHOD_NAME_ALL_LOWERCASE = "all";
15049
15097
  var METHODS = ["get", "post", "put", "delete", "options", "patch"];
@@ -15051,10 +15099,10 @@ var MESSAGE_MATCHER_IS_ALREADY_BUILT = "Can not add a route since the matcher is
15051
15099
  var UnsupportedPathError = class extends Error {
15052
15100
  };
15053
15101
 
15054
- // ../../node_modules/.pnpm/hono@4.12.8/node_modules/hono/dist/utils/constants.js
15102
+ // ../../node_modules/.pnpm/hono@4.12.12/node_modules/hono/dist/utils/constants.js
15055
15103
  var COMPOSED_HANDLER = "__COMPOSED_HANDLER";
15056
15104
 
15057
- // ../../node_modules/.pnpm/hono@4.12.8/node_modules/hono/dist/hono-base.js
15105
+ // ../../node_modules/.pnpm/hono@4.12.12/node_modules/hono/dist/hono-base.js
15058
15106
  var notFoundHandler = (c) => {
15059
15107
  return c.text("404 Not Found", 404);
15060
15108
  };
@@ -15425,7 +15473,7 @@ var Hono = class _Hono {
15425
15473
  };
15426
15474
  };
15427
15475
 
15428
- // ../../node_modules/.pnpm/hono@4.12.8/node_modules/hono/dist/router/reg-exp-router/matcher.js
15476
+ // ../../node_modules/.pnpm/hono@4.12.12/node_modules/hono/dist/router/reg-exp-router/matcher.js
15429
15477
  var emptyParam = [];
15430
15478
  function match(method, path3) {
15431
15479
  const matchers = this.buildAllMatchers();
@@ -15446,7 +15494,7 @@ function match(method, path3) {
15446
15494
  return match2(method, path3);
15447
15495
  }
15448
15496
 
15449
- // ../../node_modules/.pnpm/hono@4.12.8/node_modules/hono/dist/router/reg-exp-router/node.js
15497
+ // ../../node_modules/.pnpm/hono@4.12.12/node_modules/hono/dist/router/reg-exp-router/node.js
15450
15498
  var LABEL_REG_EXP_STR = "[^/]+";
15451
15499
  var ONLY_WILDCARD_REG_EXP_STR = ".*";
15452
15500
  var TAIL_WILDCARD_REG_EXP_STR = "(?:|/.*)";
@@ -15554,7 +15602,7 @@ var Node = class _Node {
15554
15602
  }
15555
15603
  };
15556
15604
 
15557
- // ../../node_modules/.pnpm/hono@4.12.8/node_modules/hono/dist/router/reg-exp-router/trie.js
15605
+ // ../../node_modules/.pnpm/hono@4.12.12/node_modules/hono/dist/router/reg-exp-router/trie.js
15558
15606
  var Trie = class {
15559
15607
  #context = { varIndex: 0 };
15560
15608
  #root = new Node();
@@ -15610,7 +15658,7 @@ var Trie = class {
15610
15658
  }
15611
15659
  };
15612
15660
 
15613
- // ../../node_modules/.pnpm/hono@4.12.8/node_modules/hono/dist/router/reg-exp-router/router.js
15661
+ // ../../node_modules/.pnpm/hono@4.12.12/node_modules/hono/dist/router/reg-exp-router/router.js
15614
15662
  var nullMatcher = [/^$/, [], /* @__PURE__ */ Object.create(null)];
15615
15663
  var wildcardRegExpCache = /* @__PURE__ */ Object.create(null);
15616
15664
  function buildWildcardRegExp(path3) {
@@ -15789,7 +15837,7 @@ var RegExpRouter = class {
15789
15837
  }
15790
15838
  };
15791
15839
 
15792
- // ../../node_modules/.pnpm/hono@4.12.8/node_modules/hono/dist/router/smart-router/router.js
15840
+ // ../../node_modules/.pnpm/hono@4.12.12/node_modules/hono/dist/router/smart-router/router.js
15793
15841
  var SmartRouter = class {
15794
15842
  name = "SmartRouter";
15795
15843
  #routers = [];
@@ -15844,7 +15892,7 @@ var SmartRouter = class {
15844
15892
  }
15845
15893
  };
15846
15894
 
15847
- // ../../node_modules/.pnpm/hono@4.12.8/node_modules/hono/dist/router/trie-router/node.js
15895
+ // ../../node_modules/.pnpm/hono@4.12.12/node_modules/hono/dist/router/trie-router/node.js
15848
15896
  var emptyParams = /* @__PURE__ */ Object.create(null);
15849
15897
  var hasChildren = (children) => {
15850
15898
  for (const _ in children) {
@@ -16019,7 +16067,7 @@ var Node2 = class _Node2 {
16019
16067
  }
16020
16068
  };
16021
16069
 
16022
- // ../../node_modules/.pnpm/hono@4.12.8/node_modules/hono/dist/router/trie-router/router.js
16070
+ // ../../node_modules/.pnpm/hono@4.12.12/node_modules/hono/dist/router/trie-router/router.js
16023
16071
  var TrieRouter = class {
16024
16072
  name = "TrieRouter";
16025
16073
  #node;
@@ -16041,7 +16089,7 @@ var TrieRouter = class {
16041
16089
  }
16042
16090
  };
16043
16091
 
16044
- // ../../node_modules/.pnpm/hono@4.12.8/node_modules/hono/dist/hono.js
16092
+ // ../../node_modules/.pnpm/hono@4.12.12/node_modules/hono/dist/hono.js
16045
16093
  var Hono2 = class extends Hono {
16046
16094
  /**
16047
16095
  * Creates an instance of the Hono class.
@@ -16056,7 +16104,7 @@ var Hono2 = class extends Hono {
16056
16104
  }
16057
16105
  };
16058
16106
 
16059
- // ../../node_modules/.pnpm/hono@4.12.8/node_modules/hono/dist/middleware/cors/index.js
16107
+ // ../../node_modules/.pnpm/hono@4.12.12/node_modules/hono/dist/middleware/cors/index.js
16060
16108
  var cors = (options) => {
16061
16109
  const defaults = {
16062
16110
  origin: "*",
@@ -16071,6 +16119,9 @@ var cors = (options) => {
16071
16119
  const findAllowOrigin = ((optsOrigin) => {
16072
16120
  if (typeof optsOrigin === "string") {
16073
16121
  if (optsOrigin === "*") {
16122
+ if (opts.credentials) {
16123
+ return (origin) => origin || null;
16124
+ }
16074
16125
  return () => optsOrigin;
16075
16126
  } else {
16076
16127
  return (origin) => optsOrigin === origin ? origin : null;
@@ -16105,7 +16156,7 @@ var cors = (options) => {
16105
16156
  set("Access-Control-Expose-Headers", opts.exposeHeaders.join(","));
16106
16157
  }
16107
16158
  if (c.req.method === "OPTIONS") {
16108
- if (opts.origin !== "*") {
16159
+ if (opts.origin !== "*" || opts.credentials) {
16109
16160
  set("Vary", "Origin");
16110
16161
  }
16111
16162
  if (opts.maxAge != null) {
@@ -16135,7 +16186,7 @@ var cors = (options) => {
16135
16186
  });
16136
16187
  }
16137
16188
  await next();
16138
- if (opts.origin !== "*") {
16189
+ if (opts.origin !== "*" || opts.credentials) {
16139
16190
  c.header("Vary", "Origin", { append: true });
16140
16191
  }
16141
16192
  };