@cursor/july 0.1.21 → 0.1.22

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 (66) hide show
  1. package/dist/channels/slack/bot-mentions.d.ts +2 -0
  2. package/dist/channels/slack/bot-mentions.d.ts.map +1 -1
  3. package/dist/channels/slack/bot-mentions.js +29 -8
  4. package/dist/channels/slack/types.d.ts +13 -2
  5. package/dist/channels/slack/types.d.ts.map +1 -1
  6. package/dist/docs/404.html +1 -1
  7. package/dist/docs/ab.html +2 -2
  8. package/dist/docs/assets/{app.jDxLzWv4.js → app.BKNKMLp4.js} +1 -1
  9. package/dist/docs/assets/chunks/@localSearchIndexroot.YFE6WoMB.js +1 -0
  10. package/dist/docs/assets/chunks/{VPLocalSearchBox.Y6bDR1-a.js → VPLocalSearchBox.sOSfEZR6.js} +1 -1
  11. package/dist/docs/assets/chunks/{theme.CLazCWlJ.js → theme.BvCHT5lj.js} +2 -2
  12. package/dist/docs/building-with-agents.html +2 -2
  13. package/dist/docs/concepts.html +2 -2
  14. package/dist/docs/deployment.html +2 -2
  15. package/dist/docs/evals.html +2 -2
  16. package/dist/docs/example-agents/approval-buddy.html +2 -2
  17. package/dist/docs/example-agents/benny.html +2 -2
  18. package/dist/docs/example-agents/bugbot.html +2 -2
  19. package/dist/docs/example-agents/codebase-wiki.html +2 -2
  20. package/dist/docs/example-agents/codeowners-review.html +2 -2
  21. package/dist/docs/example-agents/concierge.html +2 -2
  22. package/dist/docs/example-agents/fsd.html +2 -2
  23. package/dist/docs/example-agents/index.html +2 -2
  24. package/dist/docs/example-agents/knowledge-base.html +2 -2
  25. package/dist/docs/example-agents/oncall.html +2 -2
  26. package/dist/docs/example-agents/security-reviewer.html +2 -2
  27. package/dist/docs/example-agents/slack-agent.html +2 -2
  28. package/dist/docs/example-agents/weather-agent.html +2 -2
  29. package/dist/docs/guides/agent-to-agent.html +2 -2
  30. package/dist/docs/guides/cloud-runtime.html +2 -2
  31. package/dist/docs/guides/github.html +2 -2
  32. package/dist/docs/guides/human-in-the-loop.html +2 -2
  33. package/dist/docs/guides/mcp-oauth.html +2 -2
  34. package/dist/docs/guides/slack.html +2 -2
  35. package/dist/docs/guides/webhooks.html +2 -2
  36. package/dist/docs/hillclimbing.html +2 -2
  37. package/dist/docs/index.html +2 -2
  38. package/dist/docs/quickstart.html +2 -2
  39. package/dist/docs/reference/agent-config.html +2 -2
  40. package/dist/docs/reference/channels.html +2 -2
  41. package/dist/docs/reference/cli.html +2 -2
  42. package/dist/docs/reference/connections.html +2 -2
  43. package/dist/docs/reference/hooks.html +2 -2
  44. package/dist/docs/reference/http-api.html +2 -2
  45. package/dist/docs/reference/instructions.html +2 -2
  46. package/dist/docs/reference/playground.html +2 -2
  47. package/dist/docs/reference/project-layout.html +2 -2
  48. package/dist/docs/reference/prompt.html +2 -2
  49. package/dist/docs/reference/schedules.html +2 -2
  50. package/dist/docs/reference/sessions.html +2 -2
  51. package/dist/docs/reference/skills.html +2 -2
  52. package/dist/docs/reference/subagents.html +2 -2
  53. package/dist/docs/reference/tools.html +2 -2
  54. package/dist/docs/scaffolding-agents.html +2 -2
  55. package/dist/docs/storage.html +2 -2
  56. package/dist/docs/troubleshooting.html +2 -2
  57. package/dist/internal/local-env.d.ts +6 -4
  58. package/dist/internal/local-env.d.ts.map +1 -1
  59. package/dist/internal/local-env.js +14 -6
  60. package/package.json +1 -1
  61. package/src/channels/slack/bot-mentions.test.ts +50 -0
  62. package/src/channels/slack/bot-mentions.ts +26 -2
  63. package/src/channels/slack/types.ts +13 -2
  64. package/src/internal/local-env.test.ts +20 -0
  65. package/src/internal/local-env.ts +14 -6
  66. package/dist/docs/assets/chunks/@localSearchIndexroot.DoJHJjqF.js +0 -1
@@ -9,9 +9,9 @@
9
9
  <link rel="preload stylesheet" href="/docs/assets/style.Bj-IXa5W.css" as="style">
10
10
  <link rel="preload stylesheet" href="/docs/vp-icons.css" as="style">
11
11
 
12
- <script type="module" src="/docs/assets/app.jDxLzWv4.js"></script>
12
+ <script type="module" src="/docs/assets/app.BKNKMLp4.js"></script>
13
13
  <link rel="preload" href="/docs/assets/inter-roman-latin.Di8DUHzh.woff2" as="font" type="font/woff2" crossorigin="">
14
- <link rel="modulepreload" href="/docs/assets/chunks/theme.CLazCWlJ.js">
14
+ <link rel="modulepreload" href="/docs/assets/chunks/theme.BvCHT5lj.js">
15
15
  <link rel="modulepreload" href="/docs/assets/chunks/framework.CAZyNGu9.js">
16
16
  <link rel="modulepreload" href="/docs/assets/example-agents_weather-agent.md.C9Qv-W0o.lean.js">
17
17
  <script id="check-dark-mode">(()=>{const e=localStorage.getItem("vitepress-theme-appearance")||"auto",a=window.matchMedia("(prefers-color-scheme: dark)").matches;(!e||e==="auto"?a:e==="dark")&&document.documentElement.classList.add("dark")})();</script>
@@ -9,9 +9,9 @@
9
9
  <link rel="preload stylesheet" href="/docs/assets/style.Bj-IXa5W.css" as="style">
10
10
  <link rel="preload stylesheet" href="/docs/vp-icons.css" as="style">
11
11
 
12
- <script type="module" src="/docs/assets/app.jDxLzWv4.js"></script>
12
+ <script type="module" src="/docs/assets/app.BKNKMLp4.js"></script>
13
13
  <link rel="preload" href="/docs/assets/inter-roman-latin.Di8DUHzh.woff2" as="font" type="font/woff2" crossorigin="">
14
- <link rel="modulepreload" href="/docs/assets/chunks/theme.CLazCWlJ.js">
14
+ <link rel="modulepreload" href="/docs/assets/chunks/theme.BvCHT5lj.js">
15
15
  <link rel="modulepreload" href="/docs/assets/chunks/framework.CAZyNGu9.js">
16
16
  <link rel="modulepreload" href="/docs/assets/guides_agent-to-agent.md.Bpzgq2Pq.lean.js">
17
17
  <script id="check-dark-mode">(()=>{const e=localStorage.getItem("vitepress-theme-appearance")||"auto",a=window.matchMedia("(prefers-color-scheme: dark)").matches;(!e||e==="auto"?a:e==="dark")&&document.documentElement.classList.add("dark")})();</script>
@@ -9,9 +9,9 @@
9
9
  <link rel="preload stylesheet" href="/docs/assets/style.Bj-IXa5W.css" as="style">
10
10
  <link rel="preload stylesheet" href="/docs/vp-icons.css" as="style">
11
11
 
12
- <script type="module" src="/docs/assets/app.jDxLzWv4.js"></script>
12
+ <script type="module" src="/docs/assets/app.BKNKMLp4.js"></script>
13
13
  <link rel="preload" href="/docs/assets/inter-roman-latin.Di8DUHzh.woff2" as="font" type="font/woff2" crossorigin="">
14
- <link rel="modulepreload" href="/docs/assets/chunks/theme.CLazCWlJ.js">
14
+ <link rel="modulepreload" href="/docs/assets/chunks/theme.BvCHT5lj.js">
15
15
  <link rel="modulepreload" href="/docs/assets/chunks/framework.CAZyNGu9.js">
16
16
  <link rel="modulepreload" href="/docs/assets/guides_cloud-runtime.md.gVzabdQL.lean.js">
17
17
  <script id="check-dark-mode">(()=>{const e=localStorage.getItem("vitepress-theme-appearance")||"auto",a=window.matchMedia("(prefers-color-scheme: dark)").matches;(!e||e==="auto"?a:e==="dark")&&document.documentElement.classList.add("dark")})();</script>
@@ -9,9 +9,9 @@
9
9
  <link rel="preload stylesheet" href="/docs/assets/style.Bj-IXa5W.css" as="style">
10
10
  <link rel="preload stylesheet" href="/docs/vp-icons.css" as="style">
11
11
 
12
- <script type="module" src="/docs/assets/app.jDxLzWv4.js"></script>
12
+ <script type="module" src="/docs/assets/app.BKNKMLp4.js"></script>
13
13
  <link rel="preload" href="/docs/assets/inter-roman-latin.Di8DUHzh.woff2" as="font" type="font/woff2" crossorigin="">
14
- <link rel="modulepreload" href="/docs/assets/chunks/theme.CLazCWlJ.js">
14
+ <link rel="modulepreload" href="/docs/assets/chunks/theme.BvCHT5lj.js">
15
15
  <link rel="modulepreload" href="/docs/assets/chunks/framework.CAZyNGu9.js">
16
16
  <link rel="modulepreload" href="/docs/assets/guides_github.md.DOOCpqsW.lean.js">
17
17
  <script id="check-dark-mode">(()=>{const e=localStorage.getItem("vitepress-theme-appearance")||"auto",a=window.matchMedia("(prefers-color-scheme: dark)").matches;(!e||e==="auto"?a:e==="dark")&&document.documentElement.classList.add("dark")})();</script>
@@ -9,9 +9,9 @@
9
9
  <link rel="preload stylesheet" href="/docs/assets/style.Bj-IXa5W.css" as="style">
10
10
  <link rel="preload stylesheet" href="/docs/vp-icons.css" as="style">
11
11
 
12
- <script type="module" src="/docs/assets/app.jDxLzWv4.js"></script>
12
+ <script type="module" src="/docs/assets/app.BKNKMLp4.js"></script>
13
13
  <link rel="preload" href="/docs/assets/inter-roman-latin.Di8DUHzh.woff2" as="font" type="font/woff2" crossorigin="">
14
- <link rel="modulepreload" href="/docs/assets/chunks/theme.CLazCWlJ.js">
14
+ <link rel="modulepreload" href="/docs/assets/chunks/theme.BvCHT5lj.js">
15
15
  <link rel="modulepreload" href="/docs/assets/chunks/framework.CAZyNGu9.js">
16
16
  <link rel="modulepreload" href="/docs/assets/guides_human-in-the-loop.md.DlUqsp1S.lean.js">
17
17
  <script id="check-dark-mode">(()=>{const e=localStorage.getItem("vitepress-theme-appearance")||"auto",a=window.matchMedia("(prefers-color-scheme: dark)").matches;(!e||e==="auto"?a:e==="dark")&&document.documentElement.classList.add("dark")})();</script>
@@ -9,9 +9,9 @@
9
9
  <link rel="preload stylesheet" href="/docs/assets/style.Bj-IXa5W.css" as="style">
10
10
  <link rel="preload stylesheet" href="/docs/vp-icons.css" as="style">
11
11
 
12
- <script type="module" src="/docs/assets/app.jDxLzWv4.js"></script>
12
+ <script type="module" src="/docs/assets/app.BKNKMLp4.js"></script>
13
13
  <link rel="preload" href="/docs/assets/inter-roman-latin.Di8DUHzh.woff2" as="font" type="font/woff2" crossorigin="">
14
- <link rel="modulepreload" href="/docs/assets/chunks/theme.CLazCWlJ.js">
14
+ <link rel="modulepreload" href="/docs/assets/chunks/theme.BvCHT5lj.js">
15
15
  <link rel="modulepreload" href="/docs/assets/chunks/framework.CAZyNGu9.js">
16
16
  <link rel="modulepreload" href="/docs/assets/guides_mcp-oauth.md.Dd8EgSem.lean.js">
17
17
  <script id="check-dark-mode">(()=>{const e=localStorage.getItem("vitepress-theme-appearance")||"auto",a=window.matchMedia("(prefers-color-scheme: dark)").matches;(!e||e==="auto"?a:e==="dark")&&document.documentElement.classList.add("dark")})();</script>
@@ -9,9 +9,9 @@
9
9
  <link rel="preload stylesheet" href="/docs/assets/style.Bj-IXa5W.css" as="style">
10
10
  <link rel="preload stylesheet" href="/docs/vp-icons.css" as="style">
11
11
 
12
- <script type="module" src="/docs/assets/app.jDxLzWv4.js"></script>
12
+ <script type="module" src="/docs/assets/app.BKNKMLp4.js"></script>
13
13
  <link rel="preload" href="/docs/assets/inter-roman-latin.Di8DUHzh.woff2" as="font" type="font/woff2" crossorigin="">
14
- <link rel="modulepreload" href="/docs/assets/chunks/theme.CLazCWlJ.js">
14
+ <link rel="modulepreload" href="/docs/assets/chunks/theme.BvCHT5lj.js">
15
15
  <link rel="modulepreload" href="/docs/assets/chunks/framework.CAZyNGu9.js">
16
16
  <link rel="modulepreload" href="/docs/assets/guides_slack.md.D_xFKlnF.lean.js">
17
17
  <script id="check-dark-mode">(()=>{const e=localStorage.getItem("vitepress-theme-appearance")||"auto",a=window.matchMedia("(prefers-color-scheme: dark)").matches;(!e||e==="auto"?a:e==="dark")&&document.documentElement.classList.add("dark")})();</script>
@@ -9,9 +9,9 @@
9
9
  <link rel="preload stylesheet" href="/docs/assets/style.Bj-IXa5W.css" as="style">
10
10
  <link rel="preload stylesheet" href="/docs/vp-icons.css" as="style">
11
11
 
12
- <script type="module" src="/docs/assets/app.jDxLzWv4.js"></script>
12
+ <script type="module" src="/docs/assets/app.BKNKMLp4.js"></script>
13
13
  <link rel="preload" href="/docs/assets/inter-roman-latin.Di8DUHzh.woff2" as="font" type="font/woff2" crossorigin="">
14
- <link rel="modulepreload" href="/docs/assets/chunks/theme.CLazCWlJ.js">
14
+ <link rel="modulepreload" href="/docs/assets/chunks/theme.BvCHT5lj.js">
15
15
  <link rel="modulepreload" href="/docs/assets/chunks/framework.CAZyNGu9.js">
16
16
  <link rel="modulepreload" href="/docs/assets/guides_webhooks.md.B1EswtUu.lean.js">
17
17
  <script id="check-dark-mode">(()=>{const e=localStorage.getItem("vitepress-theme-appearance")||"auto",a=window.matchMedia("(prefers-color-scheme: dark)").matches;(!e||e==="auto"?a:e==="dark")&&document.documentElement.classList.add("dark")})();</script>
@@ -9,9 +9,9 @@
9
9
  <link rel="preload stylesheet" href="/docs/assets/style.Bj-IXa5W.css" as="style">
10
10
  <link rel="preload stylesheet" href="/docs/vp-icons.css" as="style">
11
11
 
12
- <script type="module" src="/docs/assets/app.jDxLzWv4.js"></script>
12
+ <script type="module" src="/docs/assets/app.BKNKMLp4.js"></script>
13
13
  <link rel="preload" href="/docs/assets/inter-roman-latin.Di8DUHzh.woff2" as="font" type="font/woff2" crossorigin="">
14
- <link rel="modulepreload" href="/docs/assets/chunks/theme.CLazCWlJ.js">
14
+ <link rel="modulepreload" href="/docs/assets/chunks/theme.BvCHT5lj.js">
15
15
  <link rel="modulepreload" href="/docs/assets/chunks/framework.CAZyNGu9.js">
16
16
  <link rel="modulepreload" href="/docs/assets/hillclimbing.md.DHNast08.lean.js">
17
17
  <script id="check-dark-mode">(()=>{const e=localStorage.getItem("vitepress-theme-appearance")||"auto",a=window.matchMedia("(prefers-color-scheme: dark)").matches;(!e||e==="auto"?a:e==="dark")&&document.documentElement.classList.add("dark")})();</script>
@@ -9,9 +9,9 @@
9
9
  <link rel="preload stylesheet" href="/docs/assets/style.Bj-IXa5W.css" as="style">
10
10
  <link rel="preload stylesheet" href="/docs/vp-icons.css" as="style">
11
11
 
12
- <script type="module" src="/docs/assets/app.jDxLzWv4.js"></script>
12
+ <script type="module" src="/docs/assets/app.BKNKMLp4.js"></script>
13
13
  <link rel="preload" href="/docs/assets/inter-roman-latin.Di8DUHzh.woff2" as="font" type="font/woff2" crossorigin="">
14
- <link rel="modulepreload" href="/docs/assets/chunks/theme.CLazCWlJ.js">
14
+ <link rel="modulepreload" href="/docs/assets/chunks/theme.BvCHT5lj.js">
15
15
  <link rel="modulepreload" href="/docs/assets/chunks/framework.CAZyNGu9.js">
16
16
  <link rel="modulepreload" href="/docs/assets/index.md.t0TM2Qzz.lean.js">
17
17
  <script id="check-dark-mode">(()=>{const e=localStorage.getItem("vitepress-theme-appearance")||"auto",a=window.matchMedia("(prefers-color-scheme: dark)").matches;(!e||e==="auto"?a:e==="dark")&&document.documentElement.classList.add("dark")})();</script>
@@ -9,9 +9,9 @@
9
9
  <link rel="preload stylesheet" href="/docs/assets/style.Bj-IXa5W.css" as="style">
10
10
  <link rel="preload stylesheet" href="/docs/vp-icons.css" as="style">
11
11
 
12
- <script type="module" src="/docs/assets/app.jDxLzWv4.js"></script>
12
+ <script type="module" src="/docs/assets/app.BKNKMLp4.js"></script>
13
13
  <link rel="preload" href="/docs/assets/inter-roman-latin.Di8DUHzh.woff2" as="font" type="font/woff2" crossorigin="">
14
- <link rel="modulepreload" href="/docs/assets/chunks/theme.CLazCWlJ.js">
14
+ <link rel="modulepreload" href="/docs/assets/chunks/theme.BvCHT5lj.js">
15
15
  <link rel="modulepreload" href="/docs/assets/chunks/framework.CAZyNGu9.js">
16
16
  <link rel="modulepreload" href="/docs/assets/quickstart.md.BU6Iwi_9.lean.js">
17
17
  <script id="check-dark-mode">(()=>{const e=localStorage.getItem("vitepress-theme-appearance")||"auto",a=window.matchMedia("(prefers-color-scheme: dark)").matches;(!e||e==="auto"?a:e==="dark")&&document.documentElement.classList.add("dark")})();</script>
@@ -9,9 +9,9 @@
9
9
  <link rel="preload stylesheet" href="/docs/assets/style.Bj-IXa5W.css" as="style">
10
10
  <link rel="preload stylesheet" href="/docs/vp-icons.css" as="style">
11
11
 
12
- <script type="module" src="/docs/assets/app.jDxLzWv4.js"></script>
12
+ <script type="module" src="/docs/assets/app.BKNKMLp4.js"></script>
13
13
  <link rel="preload" href="/docs/assets/inter-roman-latin.Di8DUHzh.woff2" as="font" type="font/woff2" crossorigin="">
14
- <link rel="modulepreload" href="/docs/assets/chunks/theme.CLazCWlJ.js">
14
+ <link rel="modulepreload" href="/docs/assets/chunks/theme.BvCHT5lj.js">
15
15
  <link rel="modulepreload" href="/docs/assets/chunks/framework.CAZyNGu9.js">
16
16
  <link rel="modulepreload" href="/docs/assets/reference_agent-config.md.DrW2JUM8.lean.js">
17
17
  <script id="check-dark-mode">(()=>{const e=localStorage.getItem("vitepress-theme-appearance")||"auto",a=window.matchMedia("(prefers-color-scheme: dark)").matches;(!e||e==="auto"?a:e==="dark")&&document.documentElement.classList.add("dark")})();</script>
@@ -9,9 +9,9 @@
9
9
  <link rel="preload stylesheet" href="/docs/assets/style.Bj-IXa5W.css" as="style">
10
10
  <link rel="preload stylesheet" href="/docs/vp-icons.css" as="style">
11
11
 
12
- <script type="module" src="/docs/assets/app.jDxLzWv4.js"></script>
12
+ <script type="module" src="/docs/assets/app.BKNKMLp4.js"></script>
13
13
  <link rel="preload" href="/docs/assets/inter-roman-latin.Di8DUHzh.woff2" as="font" type="font/woff2" crossorigin="">
14
- <link rel="modulepreload" href="/docs/assets/chunks/theme.CLazCWlJ.js">
14
+ <link rel="modulepreload" href="/docs/assets/chunks/theme.BvCHT5lj.js">
15
15
  <link rel="modulepreload" href="/docs/assets/chunks/framework.CAZyNGu9.js">
16
16
  <link rel="modulepreload" href="/docs/assets/reference_channels.md.DdmiKgqf.lean.js">
17
17
  <script id="check-dark-mode">(()=>{const e=localStorage.getItem("vitepress-theme-appearance")||"auto",a=window.matchMedia("(prefers-color-scheme: dark)").matches;(!e||e==="auto"?a:e==="dark")&&document.documentElement.classList.add("dark")})();</script>
@@ -9,9 +9,9 @@
9
9
  <link rel="preload stylesheet" href="/docs/assets/style.Bj-IXa5W.css" as="style">
10
10
  <link rel="preload stylesheet" href="/docs/vp-icons.css" as="style">
11
11
 
12
- <script type="module" src="/docs/assets/app.jDxLzWv4.js"></script>
12
+ <script type="module" src="/docs/assets/app.BKNKMLp4.js"></script>
13
13
  <link rel="preload" href="/docs/assets/inter-roman-latin.Di8DUHzh.woff2" as="font" type="font/woff2" crossorigin="">
14
- <link rel="modulepreload" href="/docs/assets/chunks/theme.CLazCWlJ.js">
14
+ <link rel="modulepreload" href="/docs/assets/chunks/theme.BvCHT5lj.js">
15
15
  <link rel="modulepreload" href="/docs/assets/chunks/framework.CAZyNGu9.js">
16
16
  <link rel="modulepreload" href="/docs/assets/reference_cli.md.DnYfr5V2.lean.js">
17
17
  <script id="check-dark-mode">(()=>{const e=localStorage.getItem("vitepress-theme-appearance")||"auto",a=window.matchMedia("(prefers-color-scheme: dark)").matches;(!e||e==="auto"?a:e==="dark")&&document.documentElement.classList.add("dark")})();</script>
@@ -9,9 +9,9 @@
9
9
  <link rel="preload stylesheet" href="/docs/assets/style.Bj-IXa5W.css" as="style">
10
10
  <link rel="preload stylesheet" href="/docs/vp-icons.css" as="style">
11
11
 
12
- <script type="module" src="/docs/assets/app.jDxLzWv4.js"></script>
12
+ <script type="module" src="/docs/assets/app.BKNKMLp4.js"></script>
13
13
  <link rel="preload" href="/docs/assets/inter-roman-latin.Di8DUHzh.woff2" as="font" type="font/woff2" crossorigin="">
14
- <link rel="modulepreload" href="/docs/assets/chunks/theme.CLazCWlJ.js">
14
+ <link rel="modulepreload" href="/docs/assets/chunks/theme.BvCHT5lj.js">
15
15
  <link rel="modulepreload" href="/docs/assets/chunks/framework.CAZyNGu9.js">
16
16
  <link rel="modulepreload" href="/docs/assets/reference_connections.md.B9Q3TOve.lean.js">
17
17
  <script id="check-dark-mode">(()=>{const e=localStorage.getItem("vitepress-theme-appearance")||"auto",a=window.matchMedia("(prefers-color-scheme: dark)").matches;(!e||e==="auto"?a:e==="dark")&&document.documentElement.classList.add("dark")})();</script>
@@ -9,9 +9,9 @@
9
9
  <link rel="preload stylesheet" href="/docs/assets/style.Bj-IXa5W.css" as="style">
10
10
  <link rel="preload stylesheet" href="/docs/vp-icons.css" as="style">
11
11
 
12
- <script type="module" src="/docs/assets/app.jDxLzWv4.js"></script>
12
+ <script type="module" src="/docs/assets/app.BKNKMLp4.js"></script>
13
13
  <link rel="preload" href="/docs/assets/inter-roman-latin.Di8DUHzh.woff2" as="font" type="font/woff2" crossorigin="">
14
- <link rel="modulepreload" href="/docs/assets/chunks/theme.CLazCWlJ.js">
14
+ <link rel="modulepreload" href="/docs/assets/chunks/theme.BvCHT5lj.js">
15
15
  <link rel="modulepreload" href="/docs/assets/chunks/framework.CAZyNGu9.js">
16
16
  <link rel="modulepreload" href="/docs/assets/reference_hooks.md.DyLVfE1O.lean.js">
17
17
  <script id="check-dark-mode">(()=>{const e=localStorage.getItem("vitepress-theme-appearance")||"auto",a=window.matchMedia("(prefers-color-scheme: dark)").matches;(!e||e==="auto"?a:e==="dark")&&document.documentElement.classList.add("dark")})();</script>
@@ -9,9 +9,9 @@
9
9
  <link rel="preload stylesheet" href="/docs/assets/style.Bj-IXa5W.css" as="style">
10
10
  <link rel="preload stylesheet" href="/docs/vp-icons.css" as="style">
11
11
 
12
- <script type="module" src="/docs/assets/app.jDxLzWv4.js"></script>
12
+ <script type="module" src="/docs/assets/app.BKNKMLp4.js"></script>
13
13
  <link rel="preload" href="/docs/assets/inter-roman-latin.Di8DUHzh.woff2" as="font" type="font/woff2" crossorigin="">
14
- <link rel="modulepreload" href="/docs/assets/chunks/theme.CLazCWlJ.js">
14
+ <link rel="modulepreload" href="/docs/assets/chunks/theme.BvCHT5lj.js">
15
15
  <link rel="modulepreload" href="/docs/assets/chunks/framework.CAZyNGu9.js">
16
16
  <link rel="modulepreload" href="/docs/assets/reference_http-api.md.BncLd3PZ.lean.js">
17
17
  <script id="check-dark-mode">(()=>{const e=localStorage.getItem("vitepress-theme-appearance")||"auto",a=window.matchMedia("(prefers-color-scheme: dark)").matches;(!e||e==="auto"?a:e==="dark")&&document.documentElement.classList.add("dark")})();</script>
@@ -9,9 +9,9 @@
9
9
  <link rel="preload stylesheet" href="/docs/assets/style.Bj-IXa5W.css" as="style">
10
10
  <link rel="preload stylesheet" href="/docs/vp-icons.css" as="style">
11
11
 
12
- <script type="module" src="/docs/assets/app.jDxLzWv4.js"></script>
12
+ <script type="module" src="/docs/assets/app.BKNKMLp4.js"></script>
13
13
  <link rel="preload" href="/docs/assets/inter-roman-latin.Di8DUHzh.woff2" as="font" type="font/woff2" crossorigin="">
14
- <link rel="modulepreload" href="/docs/assets/chunks/theme.CLazCWlJ.js">
14
+ <link rel="modulepreload" href="/docs/assets/chunks/theme.BvCHT5lj.js">
15
15
  <link rel="modulepreload" href="/docs/assets/chunks/framework.CAZyNGu9.js">
16
16
  <link rel="modulepreload" href="/docs/assets/reference_instructions.md.CgoV-YEb.lean.js">
17
17
  <script id="check-dark-mode">(()=>{const e=localStorage.getItem("vitepress-theme-appearance")||"auto",a=window.matchMedia("(prefers-color-scheme: dark)").matches;(!e||e==="auto"?a:e==="dark")&&document.documentElement.classList.add("dark")})();</script>
@@ -9,9 +9,9 @@
9
9
  <link rel="preload stylesheet" href="/docs/assets/style.Bj-IXa5W.css" as="style">
10
10
  <link rel="preload stylesheet" href="/docs/vp-icons.css" as="style">
11
11
 
12
- <script type="module" src="/docs/assets/app.jDxLzWv4.js"></script>
12
+ <script type="module" src="/docs/assets/app.BKNKMLp4.js"></script>
13
13
  <link rel="preload" href="/docs/assets/inter-roman-latin.Di8DUHzh.woff2" as="font" type="font/woff2" crossorigin="">
14
- <link rel="modulepreload" href="/docs/assets/chunks/theme.CLazCWlJ.js">
14
+ <link rel="modulepreload" href="/docs/assets/chunks/theme.BvCHT5lj.js">
15
15
  <link rel="modulepreload" href="/docs/assets/chunks/framework.CAZyNGu9.js">
16
16
  <link rel="modulepreload" href="/docs/assets/reference_playground.md.CPZhfYaO.lean.js">
17
17
  <script id="check-dark-mode">(()=>{const e=localStorage.getItem("vitepress-theme-appearance")||"auto",a=window.matchMedia("(prefers-color-scheme: dark)").matches;(!e||e==="auto"?a:e==="dark")&&document.documentElement.classList.add("dark")})();</script>
@@ -9,9 +9,9 @@
9
9
  <link rel="preload stylesheet" href="/docs/assets/style.Bj-IXa5W.css" as="style">
10
10
  <link rel="preload stylesheet" href="/docs/vp-icons.css" as="style">
11
11
 
12
- <script type="module" src="/docs/assets/app.jDxLzWv4.js"></script>
12
+ <script type="module" src="/docs/assets/app.BKNKMLp4.js"></script>
13
13
  <link rel="preload" href="/docs/assets/inter-roman-latin.Di8DUHzh.woff2" as="font" type="font/woff2" crossorigin="">
14
- <link rel="modulepreload" href="/docs/assets/chunks/theme.CLazCWlJ.js">
14
+ <link rel="modulepreload" href="/docs/assets/chunks/theme.BvCHT5lj.js">
15
15
  <link rel="modulepreload" href="/docs/assets/chunks/framework.CAZyNGu9.js">
16
16
  <link rel="modulepreload" href="/docs/assets/reference_project-layout.md.Bd_CKtNS.lean.js">
17
17
  <script id="check-dark-mode">(()=>{const e=localStorage.getItem("vitepress-theme-appearance")||"auto",a=window.matchMedia("(prefers-color-scheme: dark)").matches;(!e||e==="auto"?a:e==="dark")&&document.documentElement.classList.add("dark")})();</script>
@@ -9,9 +9,9 @@
9
9
  <link rel="preload stylesheet" href="/docs/assets/style.Bj-IXa5W.css" as="style">
10
10
  <link rel="preload stylesheet" href="/docs/vp-icons.css" as="style">
11
11
 
12
- <script type="module" src="/docs/assets/app.jDxLzWv4.js"></script>
12
+ <script type="module" src="/docs/assets/app.BKNKMLp4.js"></script>
13
13
  <link rel="preload" href="/docs/assets/inter-roman-latin.Di8DUHzh.woff2" as="font" type="font/woff2" crossorigin="">
14
- <link rel="modulepreload" href="/docs/assets/chunks/theme.CLazCWlJ.js">
14
+ <link rel="modulepreload" href="/docs/assets/chunks/theme.BvCHT5lj.js">
15
15
  <link rel="modulepreload" href="/docs/assets/chunks/framework.CAZyNGu9.js">
16
16
  <link rel="modulepreload" href="/docs/assets/reference_prompt.md.BaiweQxE.lean.js">
17
17
  <script id="check-dark-mode">(()=>{const e=localStorage.getItem("vitepress-theme-appearance")||"auto",a=window.matchMedia("(prefers-color-scheme: dark)").matches;(!e||e==="auto"?a:e==="dark")&&document.documentElement.classList.add("dark")})();</script>
@@ -9,9 +9,9 @@
9
9
  <link rel="preload stylesheet" href="/docs/assets/style.Bj-IXa5W.css" as="style">
10
10
  <link rel="preload stylesheet" href="/docs/vp-icons.css" as="style">
11
11
 
12
- <script type="module" src="/docs/assets/app.jDxLzWv4.js"></script>
12
+ <script type="module" src="/docs/assets/app.BKNKMLp4.js"></script>
13
13
  <link rel="preload" href="/docs/assets/inter-roman-latin.Di8DUHzh.woff2" as="font" type="font/woff2" crossorigin="">
14
- <link rel="modulepreload" href="/docs/assets/chunks/theme.CLazCWlJ.js">
14
+ <link rel="modulepreload" href="/docs/assets/chunks/theme.BvCHT5lj.js">
15
15
  <link rel="modulepreload" href="/docs/assets/chunks/framework.CAZyNGu9.js">
16
16
  <link rel="modulepreload" href="/docs/assets/reference_schedules.md.w_F2mXB6.lean.js">
17
17
  <script id="check-dark-mode">(()=>{const e=localStorage.getItem("vitepress-theme-appearance")||"auto",a=window.matchMedia("(prefers-color-scheme: dark)").matches;(!e||e==="auto"?a:e==="dark")&&document.documentElement.classList.add("dark")})();</script>
@@ -9,9 +9,9 @@
9
9
  <link rel="preload stylesheet" href="/docs/assets/style.Bj-IXa5W.css" as="style">
10
10
  <link rel="preload stylesheet" href="/docs/vp-icons.css" as="style">
11
11
 
12
- <script type="module" src="/docs/assets/app.jDxLzWv4.js"></script>
12
+ <script type="module" src="/docs/assets/app.BKNKMLp4.js"></script>
13
13
  <link rel="preload" href="/docs/assets/inter-roman-latin.Di8DUHzh.woff2" as="font" type="font/woff2" crossorigin="">
14
- <link rel="modulepreload" href="/docs/assets/chunks/theme.CLazCWlJ.js">
14
+ <link rel="modulepreload" href="/docs/assets/chunks/theme.BvCHT5lj.js">
15
15
  <link rel="modulepreload" href="/docs/assets/chunks/framework.CAZyNGu9.js">
16
16
  <link rel="modulepreload" href="/docs/assets/reference_sessions.md.DLd6mvbv.lean.js">
17
17
  <script id="check-dark-mode">(()=>{const e=localStorage.getItem("vitepress-theme-appearance")||"auto",a=window.matchMedia("(prefers-color-scheme: dark)").matches;(!e||e==="auto"?a:e==="dark")&&document.documentElement.classList.add("dark")})();</script>
@@ -9,9 +9,9 @@
9
9
  <link rel="preload stylesheet" href="/docs/assets/style.Bj-IXa5W.css" as="style">
10
10
  <link rel="preload stylesheet" href="/docs/vp-icons.css" as="style">
11
11
 
12
- <script type="module" src="/docs/assets/app.jDxLzWv4.js"></script>
12
+ <script type="module" src="/docs/assets/app.BKNKMLp4.js"></script>
13
13
  <link rel="preload" href="/docs/assets/inter-roman-latin.Di8DUHzh.woff2" as="font" type="font/woff2" crossorigin="">
14
- <link rel="modulepreload" href="/docs/assets/chunks/theme.CLazCWlJ.js">
14
+ <link rel="modulepreload" href="/docs/assets/chunks/theme.BvCHT5lj.js">
15
15
  <link rel="modulepreload" href="/docs/assets/chunks/framework.CAZyNGu9.js">
16
16
  <link rel="modulepreload" href="/docs/assets/reference_skills.md.B_jHN7JL.lean.js">
17
17
  <script id="check-dark-mode">(()=>{const e=localStorage.getItem("vitepress-theme-appearance")||"auto",a=window.matchMedia("(prefers-color-scheme: dark)").matches;(!e||e==="auto"?a:e==="dark")&&document.documentElement.classList.add("dark")})();</script>
@@ -9,9 +9,9 @@
9
9
  <link rel="preload stylesheet" href="/docs/assets/style.Bj-IXa5W.css" as="style">
10
10
  <link rel="preload stylesheet" href="/docs/vp-icons.css" as="style">
11
11
 
12
- <script type="module" src="/docs/assets/app.jDxLzWv4.js"></script>
12
+ <script type="module" src="/docs/assets/app.BKNKMLp4.js"></script>
13
13
  <link rel="preload" href="/docs/assets/inter-roman-latin.Di8DUHzh.woff2" as="font" type="font/woff2" crossorigin="">
14
- <link rel="modulepreload" href="/docs/assets/chunks/theme.CLazCWlJ.js">
14
+ <link rel="modulepreload" href="/docs/assets/chunks/theme.BvCHT5lj.js">
15
15
  <link rel="modulepreload" href="/docs/assets/chunks/framework.CAZyNGu9.js">
16
16
  <link rel="modulepreload" href="/docs/assets/reference_subagents.md.zWAMNfi1.lean.js">
17
17
  <script id="check-dark-mode">(()=>{const e=localStorage.getItem("vitepress-theme-appearance")||"auto",a=window.matchMedia("(prefers-color-scheme: dark)").matches;(!e||e==="auto"?a:e==="dark")&&document.documentElement.classList.add("dark")})();</script>
@@ -9,9 +9,9 @@
9
9
  <link rel="preload stylesheet" href="/docs/assets/style.Bj-IXa5W.css" as="style">
10
10
  <link rel="preload stylesheet" href="/docs/vp-icons.css" as="style">
11
11
 
12
- <script type="module" src="/docs/assets/app.jDxLzWv4.js"></script>
12
+ <script type="module" src="/docs/assets/app.BKNKMLp4.js"></script>
13
13
  <link rel="preload" href="/docs/assets/inter-roman-latin.Di8DUHzh.woff2" as="font" type="font/woff2" crossorigin="">
14
- <link rel="modulepreload" href="/docs/assets/chunks/theme.CLazCWlJ.js">
14
+ <link rel="modulepreload" href="/docs/assets/chunks/theme.BvCHT5lj.js">
15
15
  <link rel="modulepreload" href="/docs/assets/chunks/framework.CAZyNGu9.js">
16
16
  <link rel="modulepreload" href="/docs/assets/reference_tools.md.BRSDnTbN.lean.js">
17
17
  <script id="check-dark-mode">(()=>{const e=localStorage.getItem("vitepress-theme-appearance")||"auto",a=window.matchMedia("(prefers-color-scheme: dark)").matches;(!e||e==="auto"?a:e==="dark")&&document.documentElement.classList.add("dark")})();</script>
@@ -9,9 +9,9 @@
9
9
  <link rel="preload stylesheet" href="/docs/assets/style.Bj-IXa5W.css" as="style">
10
10
  <link rel="preload stylesheet" href="/docs/vp-icons.css" as="style">
11
11
 
12
- <script type="module" src="/docs/assets/app.jDxLzWv4.js"></script>
12
+ <script type="module" src="/docs/assets/app.BKNKMLp4.js"></script>
13
13
  <link rel="preload" href="/docs/assets/inter-roman-latin.Di8DUHzh.woff2" as="font" type="font/woff2" crossorigin="">
14
- <link rel="modulepreload" href="/docs/assets/chunks/theme.CLazCWlJ.js">
14
+ <link rel="modulepreload" href="/docs/assets/chunks/theme.BvCHT5lj.js">
15
15
  <link rel="modulepreload" href="/docs/assets/chunks/framework.CAZyNGu9.js">
16
16
  <link rel="modulepreload" href="/docs/assets/scaffolding-agents.md.C3pTrmoE.lean.js">
17
17
  <script id="check-dark-mode">(()=>{const e=localStorage.getItem("vitepress-theme-appearance")||"auto",a=window.matchMedia("(prefers-color-scheme: dark)").matches;(!e||e==="auto"?a:e==="dark")&&document.documentElement.classList.add("dark")})();</script>
@@ -9,9 +9,9 @@
9
9
  <link rel="preload stylesheet" href="/docs/assets/style.Bj-IXa5W.css" as="style">
10
10
  <link rel="preload stylesheet" href="/docs/vp-icons.css" as="style">
11
11
 
12
- <script type="module" src="/docs/assets/app.jDxLzWv4.js"></script>
12
+ <script type="module" src="/docs/assets/app.BKNKMLp4.js"></script>
13
13
  <link rel="preload" href="/docs/assets/inter-roman-latin.Di8DUHzh.woff2" as="font" type="font/woff2" crossorigin="">
14
- <link rel="modulepreload" href="/docs/assets/chunks/theme.CLazCWlJ.js">
14
+ <link rel="modulepreload" href="/docs/assets/chunks/theme.BvCHT5lj.js">
15
15
  <link rel="modulepreload" href="/docs/assets/chunks/framework.CAZyNGu9.js">
16
16
  <link rel="modulepreload" href="/docs/assets/storage.md.DRTdnFvd.lean.js">
17
17
  <script id="check-dark-mode">(()=>{const e=localStorage.getItem("vitepress-theme-appearance")||"auto",a=window.matchMedia("(prefers-color-scheme: dark)").matches;(!e||e==="auto"?a:e==="dark")&&document.documentElement.classList.add("dark")})();</script>
@@ -9,9 +9,9 @@
9
9
  <link rel="preload stylesheet" href="/docs/assets/style.Bj-IXa5W.css" as="style">
10
10
  <link rel="preload stylesheet" href="/docs/vp-icons.css" as="style">
11
11
 
12
- <script type="module" src="/docs/assets/app.jDxLzWv4.js"></script>
12
+ <script type="module" src="/docs/assets/app.BKNKMLp4.js"></script>
13
13
  <link rel="preload" href="/docs/assets/inter-roman-latin.Di8DUHzh.woff2" as="font" type="font/woff2" crossorigin="">
14
- <link rel="modulepreload" href="/docs/assets/chunks/theme.CLazCWlJ.js">
14
+ <link rel="modulepreload" href="/docs/assets/chunks/theme.BvCHT5lj.js">
15
15
  <link rel="modulepreload" href="/docs/assets/chunks/framework.CAZyNGu9.js">
16
16
  <link rel="modulepreload" href="/docs/assets/troubleshooting.md.CmQkmnzC.lean.js">
17
17
  <script id="check-dark-mode">(()=>{const e=localStorage.getItem("vitepress-theme-appearance")||"auto",a=window.matchMedia("(prefers-color-scheme: dark)").matches;(!e||e==="auto"?a:e==="dark")&&document.documentElement.classList.add("dark")})();</script>
@@ -1,8 +1,10 @@
1
1
  /**
2
- * Loads an agent directory's `.env.local` (and each immediate child's,
3
- * for multi-agent hosts) into process.env. Real env always wins
4
- * `process.loadEnvFile` never overrides. Values a previous call loaded are
5
- * refreshed, so a reload picks up edits made since.
2
+ * Loads an agent directory's env files (and each immediate child's, for
3
+ * multi-agent hosts) into process.env. Load order per directory is
4
+ * `.env.local` then `.env` — `process.loadEnvFile` never overrides, so
5
+ * real env wins over both, and `.env.local` wins over checked-in `.env`
6
+ * defaults. Values a previous call loaded are refreshed, so a reload
7
+ * picks up edits made since.
6
8
  */
7
9
  export declare function loadAgentLocalEnv(dir: string): string[];
8
10
  //# sourceMappingURL=local-env.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"local-env.d.ts","sourceRoot":"","sources":["../../src/internal/local-env.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AASH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAsCvD"}
1
+ {"version":3,"file":"local-env.d.ts","sourceRoot":"","sources":["../../src/internal/local-env.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AASH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CA4CvD"}
@@ -1,8 +1,10 @@
1
1
  /**
2
- * Loads an agent directory's `.env.local` (and each immediate child's,
3
- * for multi-agent hosts) into process.env. Real env always wins
4
- * `process.loadEnvFile` never overrides. Values a previous call loaded are
5
- * refreshed, so a reload picks up edits made since.
2
+ * Loads an agent directory's env files (and each immediate child's, for
3
+ * multi-agent hosts) into process.env. Load order per directory is
4
+ * `.env.local` then `.env` — `process.loadEnvFile` never overrides, so
5
+ * real env wins over both, and `.env.local` wins over checked-in `.env`
6
+ * defaults. Values a previous call loaded are refreshed, so a reload
7
+ * picks up edits made since.
6
8
  */
7
9
  import { existsSync, readdirSync } from "node:fs";
8
10
  import { join } from "node:path";
@@ -25,7 +27,13 @@ export function loadAgentLocalEnv(dir) {
25
27
  const trackLoadedKeys = () => {
26
28
  fileLoadedKeys = new Set(Object.keys(process.env).filter((key) => !realKeys.has(key)));
27
29
  };
28
- tryLoad(join(dir, ".env.local"));
30
+ const tryLoadDir = (agentDir) => {
31
+ // `.env.local` first so its values win over checked-in `.env` defaults
32
+ // under loadEnvFile's no-override semantics.
33
+ tryLoad(join(agentDir, ".env.local"));
34
+ tryLoad(join(agentDir, ".env"));
35
+ };
36
+ tryLoadDir(dir);
29
37
  let children;
30
38
  try {
31
39
  children = readdirSync(dir, { withFileTypes: true })
@@ -40,7 +48,7 @@ export function loadAgentLocalEnv(dir) {
40
48
  if (child === "node_modules") {
41
49
  continue;
42
50
  }
43
- tryLoad(join(dir, child, ".env.local"));
51
+ tryLoadDir(join(dir, child));
44
52
  }
45
53
  trackLoadedKeys();
46
54
  return loaded;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cursor/july",
3
- "version": "0.1.21",
3
+ "version": "0.1.22",
4
4
  "description": "(early alpha) Filesystem-first framework for defining Cursor agents as markdown and TypeScript and serving them over channels with the Cursor SDK.",
5
5
  "license": "SEE LICENSE IN LICENSE.md",
6
6
  "repository": {
@@ -159,6 +159,56 @@ describe("SlackBotMentionGate", () => {
159
159
  expect(verdict.allow).toBe(true);
160
160
  });
161
161
 
162
+ it("matches compound botId:username entries case-insensitively", () => {
163
+ const g = gate({ allowFrom: ["BCURSOR:Lasso"] });
164
+ const fromCursorAsLasso = botMention({
165
+ author: {
166
+ userId: "UCURSOR",
167
+ isBot: true,
168
+ botId: "BCURSOR",
169
+ userName: "lasso",
170
+ },
171
+ });
172
+ expect(g.evaluate(fromCursorAsLasso).allow).toBe(true);
173
+ });
174
+
175
+ it("compound entries deny other usernames and missing usernames", () => {
176
+ const g = gate({ allowFrom: ["BCURSOR:Lasso"] });
177
+ expect(
178
+ g.evaluate(
179
+ botMention({
180
+ author: {
181
+ userId: "UCURSOR",
182
+ isBot: true,
183
+ botId: "BCURSOR",
184
+ userName: "SomeOtherAgent",
185
+ },
186
+ })
187
+ )
188
+ ).toMatchObject({ allow: false });
189
+ // No username on the event → fail closed.
190
+ expect(
191
+ g.evaluate(
192
+ botMention({
193
+ author: { userId: "UCURSOR", isBot: true, botId: "BCURSOR" },
194
+ })
195
+ )
196
+ ).toMatchObject({ allow: false });
197
+ // Bare bot_id was not allowlisted, only the compound form.
198
+ expect(
199
+ g.evaluate(
200
+ botMention({
201
+ author: {
202
+ userId: "UCURSOR",
203
+ isBot: true,
204
+ botId: "BCURSOR",
205
+ userName: undefined,
206
+ },
207
+ })
208
+ )
209
+ ).toMatchObject({ allow: false });
210
+ });
211
+
162
212
  it("denies bots not in the allowlist", () => {
163
213
  const verdict = gate().evaluate(
164
214
  botMention({ author: { userId: "UOTHER", isBot: true, botId: "BOTHER" } })
@@ -159,6 +159,8 @@ interface ThreadBudget {
159
159
  */
160
160
  export class SlackBotMentionGate {
161
161
  private readonly allowFrom: Set<string>;
162
+ /** Compound entries: posting `bot_id` → allowed lowercase usernames. */
163
+ private readonly allowFromCompound: Map<string, Set<string>>;
162
164
  private readonly maxDepth: number;
163
165
  private readonly maxPerThreadPerHour: number;
164
166
  private readonly maxPerThreadTotal: number;
@@ -176,7 +178,20 @@ export class SlackBotMentionGate {
176
178
  "SlackBotMentionGate requires the agent's own bot identity (auth.test) for loop safety."
177
179
  );
178
180
  }
179
- this.allowFrom = new Set(normalizeBotMentionAllowlist(options.allowFrom));
181
+ this.allowFrom = new Set();
182
+ this.allowFromCompound = new Map();
183
+ for (const entry of normalizeBotMentionAllowlist(options.allowFrom)) {
184
+ const separator = entry.indexOf(":");
185
+ if (separator <= 0 || separator === entry.length - 1) {
186
+ this.allowFrom.add(entry);
187
+ continue;
188
+ }
189
+ const botId = entry.slice(0, separator);
190
+ const username = entry.slice(separator + 1).toLowerCase();
191
+ const usernames = this.allowFromCompound.get(botId) ?? new Set();
192
+ usernames.add(username);
193
+ this.allowFromCompound.set(botId, usernames);
194
+ }
180
195
  this.maxDepth = options.maxDepth ?? SLACK_BOT_MENTION_DEFAULTS.maxDepth;
181
196
  this.maxPerThreadPerHour =
182
197
  options.maxPerThreadPerHour ??
@@ -212,9 +227,18 @@ export class SlackBotMentionGate {
212
227
  return { allow: false, reason: "own post (loop safety)" };
213
228
  }
214
229
 
230
+ const compoundUsernames =
231
+ author.botId === undefined
232
+ ? undefined
233
+ : this.allowFromCompound.get(author.botId);
215
234
  const allowed =
216
235
  (author.botId !== undefined && this.allowFrom.has(author.botId)) ||
217
- (author.userId !== "" && this.allowFrom.has(author.userId));
236
+ (author.userId !== "" && this.allowFrom.has(author.userId)) ||
237
+ // Compound entry: shared app bot_id + server-pinned username. Fails
238
+ // closed when the event carries no username.
239
+ (compoundUsernames !== undefined &&
240
+ author.userName !== undefined &&
241
+ compoundUsernames.has(author.userName.toLowerCase()));
218
242
  if (!allowed) {
219
243
  return { allow: false, reason: "author not in botMentions.allowFrom" };
220
244
  }