oc-hush 0.0.0-stage → 0.1.1

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/README.md CHANGED
@@ -1,3 +1,67 @@
1
- # Temporary Holding Version
1
+ # oc-hush
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ ![oc-hush: your agent uses the key, it never sees it](media/banner.png)
4
+
5
+ Credentials your agent can use without reading them.
6
+
7
+ When a command needs an API key or token, Hush asks you for it in a private prompt instead of the chat. The agent gets to use it in its command, but the key itself never reaches the model or the conversation.
8
+
9
+ **WIP.** Works in the OpenCode TUI and desktop app. Requires OpenCode 2.2.6 or newer.
10
+
11
+ ## Install
12
+
13
+ ```sh
14
+ opencode plugin add oc-hush
15
+ ```
16
+
17
+ Restart OpenCode after installing. In the desktop app, Hush only loads when installed this way (globally), not from a project’s config.
18
+
19
+ ## Usage
20
+
21
+ Just work as usual. When a command needs a credential, the agent asks through Hush, or you can ask it to:
22
+
23
+ ```
24
+ Use Hush to get my GitHub token, then run gh repo list with it.
25
+ ```
26
+
27
+ A **Temporary Credential** dialog opens and names what the agent needs, such as "GitHub token". Paste or type it there, never in the chat.
28
+
29
+ **In the TUI**
30
+
31
+ - The credential shows as dots and stays out of the prompt and its history.
32
+ - **Tab** shows what you typed; press it again to hide it.
33
+ - **Enter** approves, **Esc** denies.
34
+
35
+ **In the desktop app**
36
+
37
+ - The credential goes into a password field.
38
+ - The **eye button** shows what you typed; click it again to hide it.
39
+ - **Approve** sends it, **Deny** refuses. Esc just closes the dialog: the request waits in a lock pill above the composer, and clicking it reopens the dialog.
40
+
41
+ If the agent asks in a session you are not looking at, a toast lets you jump to it, and you get a system notification while OpenCode is in the background. Requests from subagents show up in the session you are watching.
42
+
43
+ Run `/hush-forget` to forget this session’s credentials right away and cancel any waiting requests.
44
+
45
+ ## Options
46
+
47
+ ```jsonc
48
+ { "plugins": [{ "package": "oc-hush", "options": { "ttlMinutes": 15 } }] }
49
+ ```
50
+
51
+ - `ttlMinutes`: how long Hush keeps a credential after you approve it. Default `15`, maximum `1440`. `0` forgets it after the first command that uses it.
52
+
53
+ ## How it keeps your credential safe
54
+
55
+ - **You never paste it into chat.** It goes into Hush’s own dialog, which starts hidden every time.
56
+ - **The agent only gets a file path.** Hush stores the credential in a private file only you can read, and the agent’s command reads it from there.
57
+ - **Output is scrubbed.** If a command prints the credential, even encoded, Hush replaces it with `[redacted by Hush]` before the model sees it or the session is saved.
58
+ - **It doesn’t stick around.** Credentials are deleted after 15 minutes (or your `ttlMinutes`), on `/hush-forget`, and when OpenCode exits. Unanswered requests expire after five minutes.
59
+
60
+ > [!NOTE]
61
+ > Commands run with your permissions, so they can read the file. Redaction catches the credential whole or encoded, but a command written to print it in pieces (such as `cut -c1-6 <file>`) would get past it. That takes a command you approve, and OpenCode’s permission prompt shows it in full first. Approve commands that use the file as you would any command that handles a secret.
62
+
63
+ Hush protects your credential from the agent and the conversation. It does not protect against malware, other plugins or programs running on your machine.
64
+
65
+ ## Contributing
66
+
67
+ See [DEVELOPMENT.md](DEVELOPMENT.md).
@@ -0,0 +1,20 @@
1
+ "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const y=require("solid-js/web"),B=require("@opencode/plugin/gui"),j=require("solid-js"),$e=require("solid-js/store"),wn=require("@opencode/plugin/rpc");function s(e,n,t){function r(u,a){var l;Object.defineProperty(u,"_zod",{value:u._zod??{},enumerable:!1}),(l=u._zod).traits??(l.traits=new Set),u._zod.traits.add(e),n(u,a);for(const h in i.prototype)h in u||Object.defineProperty(u,h,{value:i.prototype[h].bind(u)});u._zod.constr=i,u._zod.def=a}const o=t?.Parent??Object;class c extends o{}Object.defineProperty(c,"name",{value:e});function i(u){var a;const l=t?.Parent?new c:this;r(l,u),(a=l._zod).deferred??(a.deferred=[]);for(const h of l._zod.deferred)h();return l}return Object.defineProperty(i,"init",{value:r}),Object.defineProperty(i,Symbol.hasInstance,{value:u=>t?.Parent&&u instanceof t.Parent?!0:u?._zod?.traits?.has(e)}),Object.defineProperty(i,"name",{value:e}),i}class L extends Error{constructor(){super("Encountered Promise during synchronous parse. Use .parseAsync() instead.")}}class Ke extends Error{constructor(n){super(`Encountered unidirectional transform during encode: ${n}`),this.name="ZodEncodeError"}}const qe={};function R(e){return qe}function kn(e){const n=Object.values(e).filter(r=>typeof r=="number");return Object.entries(e).filter(([r,o])=>n.indexOf(+r)===-1).map(([r,o])=>o)}function ae(e,n){return typeof n=="bigint"?n.toString():n}function fe(e){return{get value(){{const n=e();return Object.defineProperty(this,"value",{value:n}),n}}}}function pe(e){return e==null}function he(e){const n=e.startsWith("^")?1:0,t=e.endsWith("$")?e.length-1:e.length;return e.slice(n,t)}function Zn(e,n){const t=(e.toString().split(".")[1]||"").length,r=n.toString();let o=(r.split(".")[1]||"").length;if(o===0&&/\d?e-\d?/.test(r)){const a=r.match(/\d?e-(\d?)/);a?.[1]&&(o=Number.parseInt(a[1]))}const c=t>o?t:o,i=Number.parseInt(e.toFixed(c).replace(".","")),u=Number.parseInt(n.toFixed(c).replace(".",""));return i%u/10**c}const ye=Symbol("evaluating");function m(e,n,t){let r;Object.defineProperty(e,n,{get(){if(r!==ye)return r===void 0&&(r=ye,r=t()),r},set(o){Object.defineProperty(e,n,{value:o})},configurable:!0})}function $n(e){return Object.create(Object.getPrototypeOf(e),Object.getOwnPropertyDescriptors(e))}function N(e,n,t){Object.defineProperty(e,n,{value:t,writable:!0,enumerable:!0,configurable:!0})}function V(...e){const n={};for(const t of e){const r=Object.getOwnPropertyDescriptors(t);Object.assign(n,r)}return Object.defineProperties({},n)}function Ie(e){return JSON.stringify(e)}const He="captureStackTrace"in Error?Error.captureStackTrace:(...e)=>{};function Q(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}const yn=fe(()=>{if(typeof navigator<"u"&&navigator?.userAgent?.includes("Cloudflare"))return!1;try{const e=Function;return new e(""),!0}catch{return!1}});function W(e){if(Q(e)===!1)return!1;const n=e.constructor;if(n===void 0)return!0;const t=n.prototype;return!(Q(t)===!1||Object.prototype.hasOwnProperty.call(t,"isPrototypeOf")===!1)}function Ye(e){return W(e)?{...e}:Array.isArray(e)?[...e]:e}const In=new Set(["string","number","symbol"]);function te(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function D(e,n,t){const r=new e._zod.constr(n??e._zod.def);return(!n||t?.parent)&&(r._zod.parent=e),r}function d(e){const n=e;if(!n)return{};if(typeof n=="string")return{error:()=>n};if(n?.message!==void 0){if(n?.error!==void 0)throw new Error("Cannot specify both `message` and `error` params");n.error=n.message}return delete n.message,typeof n.error=="string"?{...n,error:()=>n.error}:n}function En(e){return Object.keys(e).filter(n=>e[n]._zod.optin==="optional"&&e[n]._zod.optout==="optional")}const An={safeint:[Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER],int32:[-2147483648,2147483647],uint32:[0,4294967295],float32:[-34028234663852886e22,34028234663852886e22],float64:[-Number.MAX_VALUE,Number.MAX_VALUE]};function Pn(e,n){const t=e._zod.def,r=V(e._zod.def,{get shape(){const o={};for(const c in n){if(!(c in t.shape))throw new Error(`Unrecognized key: "${c}"`);n[c]&&(o[c]=t.shape[c])}return N(this,"shape",o),o},checks:[]});return D(e,r)}function Tn(e,n){const t=e._zod.def,r=V(e._zod.def,{get shape(){const o={...e._zod.def.shape};for(const c in n){if(!(c in t.shape))throw new Error(`Unrecognized key: "${c}"`);n[c]&&delete o[c]}return N(this,"shape",o),o},checks:[]});return D(e,r)}function On(e,n){if(!W(n))throw new Error("Invalid input to extend: expected a plain object");const t=e._zod.def.checks;if(t&&t.length>0)throw new Error("Object schemas containing refinements cannot be extended. Use `.safeExtend()` instead.");const o=V(e._zod.def,{get shape(){const c={...e._zod.def.shape,...n};return N(this,"shape",c),c},checks:[]});return D(e,o)}function Sn(e,n){if(!W(n))throw new Error("Invalid input to safeExtend: expected a plain object");const t={...e._zod.def,get shape(){const r={...e._zod.def.shape,...n};return N(this,"shape",r),r},checks:e._zod.def.checks};return D(e,t)}function Cn(e,n){const t=V(e._zod.def,{get shape(){const r={...e._zod.def.shape,...n._zod.def.shape};return N(this,"shape",r),r},get catchall(){return n._zod.def.catchall},checks:[]});return D(e,t)}function Nn(e,n,t){const r=V(n._zod.def,{get shape(){const o=n._zod.def.shape,c={...o};if(t)for(const i in t){if(!(i in o))throw new Error(`Unrecognized key: "${i}"`);t[i]&&(c[i]=e?new e({type:"optional",innerType:o[i]}):o[i])}else for(const i in o)c[i]=e?new e({type:"optional",innerType:o[i]}):o[i];return N(this,"shape",c),c},checks:[]});return D(n,r)}function Dn(e,n,t){const r=V(n._zod.def,{get shape(){const o=n._zod.def.shape,c={...o};if(t)for(const i in t){if(!(i in c))throw new Error(`Unrecognized key: "${i}"`);t[i]&&(c[i]=new e({type:"nonoptional",innerType:o[i]}))}else for(const i in o)c[i]=new e({type:"nonoptional",innerType:o[i]});return N(this,"shape",c),c},checks:[]});return D(n,r)}function U(e,n=0){if(e.aborted===!0)return!0;for(let t=n;t<e.issues.length;t++)if(e.issues[t]?.continue!==!0)return!0;return!1}function Xe(e,n){return n.map(t=>{var r;return(r=t).path??(r.path=[]),t.path.unshift(e),t})}function q(e){return typeof e=="string"?e:e?.message}function x(e,n,t){const r={...e,path:e.path??[]};if(!e.message){const o=q(e.inst?._zod.def?.error?.(e))??q(n?.error?.(e))??q(t.customError?.(e))??q(t.localeError?.(e))??"Invalid input";r.message=o}return delete r.inst,delete r.continue,n?.reportInput||delete r.input,r}function me(e){return Array.isArray(e)?"array":typeof e=="string"?"string":"unknown"}function G(...e){const[n,t,r]=e;return typeof n=="string"?{message:n,code:"custom",input:t,inst:r}:{...n}}const Qe=(e,n)=>{e.name="$ZodError",Object.defineProperty(e,"_zod",{value:e._zod,enumerable:!1}),Object.defineProperty(e,"issues",{value:n,enumerable:!1}),e.message=JSON.stringify(n,ae,2),Object.defineProperty(e,"toString",{value:()=>e.message,enumerable:!1})},en=s("$ZodError",Qe),nn=s("$ZodError",Qe,{Parent:Error});function jn(e,n=t=>t.message){const t={},r=[];for(const o of e.issues)o.path.length>0?(t[o.path[0]]=t[o.path[0]]||[],t[o.path[0]].push(n(o))):r.push(n(o));return{formErrors:r,fieldErrors:t}}function Rn(e,n){const t=n||function(c){return c.message},r={_errors:[]},o=c=>{for(const i of c.issues)if(i.code==="invalid_union"&&i.errors.length)i.errors.map(u=>o({issues:u}));else if(i.code==="invalid_key")o({issues:i.issues});else if(i.code==="invalid_element")o({issues:i.issues});else if(i.path.length===0)r._errors.push(t(i));else{let u=r,a=0;for(;a<i.path.length;){const l=i.path[a];a===i.path.length-1?(u[l]=u[l]||{_errors:[]},u[l]._errors.push(t(i))):u[l]=u[l]||{_errors:[]},u=u[l],a++}}};return o(e),r}const _e=e=>(n,t,r,o)=>{const c=r?Object.assign(r,{async:!1}):{async:!1},i=n._zod.run({value:t,issues:[]},c);if(i instanceof Promise)throw new L;if(i.issues.length){const u=new(o?.Err??e)(i.issues.map(a=>x(a,c,R())));throw He(u,o?.callee),u}return i.value},ge=e=>async(n,t,r,o)=>{const c=r?Object.assign(r,{async:!0}):{async:!0};let i=n._zod.run({value:t,issues:[]},c);if(i instanceof Promise&&(i=await i),i.issues.length){const u=new(o?.Err??e)(i.issues.map(a=>x(a,c,R())));throw He(u,o?.callee),u}return i.value},re=e=>(n,t,r)=>{const o=r?{...r,async:!1}:{async:!1},c=n._zod.run({value:t,issues:[]},o);if(c instanceof Promise)throw new L;return c.issues.length?{success:!1,error:new(e??en)(c.issues.map(i=>x(i,o,R())))}:{success:!0,data:c.value}},xn=re(nn),oe=e=>async(n,t,r)=>{const o=r?Object.assign(r,{async:!0}):{async:!0};let c=n._zod.run({value:t,issues:[]},o);return c instanceof Promise&&(c=await c),c.issues.length?{success:!1,error:new e(c.issues.map(i=>x(i,o,R())))}:{success:!0,data:c.value}},Fn=oe(nn),Un=e=>(n,t,r)=>{const o=r?Object.assign(r,{direction:"backward"}):{direction:"backward"};return _e(e)(n,t,o)},Ln=e=>(n,t,r)=>_e(e)(n,t,r),Mn=e=>async(n,t,r)=>{const o=r?Object.assign(r,{direction:"backward"}):{direction:"backward"};return ge(e)(n,t,o)},Vn=e=>async(n,t,r)=>ge(e)(n,t,r),Bn=e=>(n,t,r)=>{const o=r?Object.assign(r,{direction:"backward"}):{direction:"backward"};return re(e)(n,t,o)},Wn=e=>(n,t,r)=>re(e)(n,t,r),Gn=e=>async(n,t,r)=>{const o=r?Object.assign(r,{direction:"backward"}):{direction:"backward"};return oe(e)(n,t,o)},Jn=e=>async(n,t,r)=>oe(e)(n,t,r),Kn=/^[cC][^\s-]{8,}$/,qn=/^[0-9a-z]+$/,Hn=/^[0-9A-HJKMNP-TV-Za-hjkmnp-tv-z]{26}$/,Yn=/^[0-9a-vA-V]{20}$/,Xn=/^[A-Za-z0-9]{27}$/,Qn=/^[a-zA-Z0-9_-]{21}$/,et=/^P(?:(\d+W)|(?!.*W)(?=\d|T\d)(\d+Y)?(\d+M)?(\d+D)?(T(?=\d)(\d+H)?(\d+M)?(\d+([.,]\d+)?S)?)?)$/,nt=/^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$/,Ee=e=>e?new RegExp(`^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-${e}[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$`):/^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$/,tt=/^(?!\.)(?!.*\.\.)([A-Za-z0-9_'+\-\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\-]*\.)+[A-Za-z]{2,}$/,rt="^(\\p{Extended_Pictographic}|\\p{Emoji_Component})+$";function ot(){return new RegExp(rt,"u")}const it=/^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$/,ct=/^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))$/,st=/^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\/([0-9]|[1-2][0-9]|3[0-2])$/,ut=/^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|::|([0-9a-fA-F]{1,4})?::([0-9a-fA-F]{1,4}:?){0,6})\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$/,at=/^$|^(?:[0-9a-zA-Z+/]{4})*(?:(?:[0-9a-zA-Z+/]{2}==)|(?:[0-9a-zA-Z+/]{3}=))?$/,tn=/^[A-Za-z0-9_-]*$/,lt=/^(?=.{1,253}\.?$)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[-0-9a-zA-Z]{0,61}[0-9a-zA-Z])?)*\.?$/,dt=/^\+(?:[0-9]){6,14}[0-9]$/,rn="(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))",ft=new RegExp(`^${rn}$`);function on(e){const n="(?:[01]\\d|2[0-3]):[0-5]\\d";return typeof e.precision=="number"?e.precision===-1?`${n}`:e.precision===0?`${n}:[0-5]\\d`:`${n}:[0-5]\\d\\.\\d{${e.precision}}`:`${n}(?::[0-5]\\d(?:\\.\\d+)?)?`}function pt(e){return new RegExp(`^${on(e)}$`)}function ht(e){const n=on({precision:e.precision}),t=["Z"];e.local&&t.push(""),e.offset&&t.push("([+-](?:[01]\\d|2[0-3]):[0-5]\\d)");const r=`${n}(?:${t.join("|")})`;return new RegExp(`^${rn}T(?:${r})$`)}const mt=e=>{const n=e?`[\\s\\S]{${e?.minimum??0},${e?.maximum??""}}`:"[\\s\\S]*";return new RegExp(`^${n}$`)},_t=/^-?\d+$/,gt=/^-?\d+(?:\.\d+)?/,vt=/^(?:true|false)$/i,bt=/^[^A-Z]*$/,zt=/^[^a-z]*$/,A=s("$ZodCheck",(e,n)=>{var t;e._zod??(e._zod={}),e._zod.def=n,(t=e._zod).onattach??(t.onattach=[])}),cn={number:"number",bigint:"bigint",object:"date"},sn=s("$ZodCheckLessThan",(e,n)=>{A.init(e,n);const t=cn[typeof n.value];e._zod.onattach.push(r=>{const o=r._zod.bag,c=(n.inclusive?o.maximum:o.exclusiveMaximum)??Number.POSITIVE_INFINITY;n.value<c&&(n.inclusive?o.maximum=n.value:o.exclusiveMaximum=n.value)}),e._zod.check=r=>{(n.inclusive?r.value<=n.value:r.value<n.value)||r.issues.push({origin:t,code:"too_big",maximum:n.value,input:r.value,inclusive:n.inclusive,inst:e,continue:!n.abort})}}),un=s("$ZodCheckGreaterThan",(e,n)=>{A.init(e,n);const t=cn[typeof n.value];e._zod.onattach.push(r=>{const o=r._zod.bag,c=(n.inclusive?o.minimum:o.exclusiveMinimum)??Number.NEGATIVE_INFINITY;n.value>c&&(n.inclusive?o.minimum=n.value:o.exclusiveMinimum=n.value)}),e._zod.check=r=>{(n.inclusive?r.value>=n.value:r.value>n.value)||r.issues.push({origin:t,code:"too_small",minimum:n.value,input:r.value,inclusive:n.inclusive,inst:e,continue:!n.abort})}}),wt=s("$ZodCheckMultipleOf",(e,n)=>{A.init(e,n),e._zod.onattach.push(t=>{var r;(r=t._zod.bag).multipleOf??(r.multipleOf=n.value)}),e._zod.check=t=>{if(typeof t.value!=typeof n.value)throw new Error("Cannot mix number and bigint in multiple_of check.");(typeof t.value=="bigint"?t.value%n.value===BigInt(0):Zn(t.value,n.value)===0)||t.issues.push({origin:typeof t.value,code:"not_multiple_of",divisor:n.value,input:t.value,inst:e,continue:!n.abort})}}),kt=s("$ZodCheckNumberFormat",(e,n)=>{A.init(e,n),n.format=n.format||"float64";const t=n.format?.includes("int"),r=t?"int":"number",[o,c]=An[n.format];e._zod.onattach.push(i=>{const u=i._zod.bag;u.format=n.format,u.minimum=o,u.maximum=c,t&&(u.pattern=_t)}),e._zod.check=i=>{const u=i.value;if(t){if(!Number.isInteger(u)){i.issues.push({expected:r,format:n.format,code:"invalid_type",continue:!1,input:u,inst:e});return}if(!Number.isSafeInteger(u)){u>0?i.issues.push({input:u,code:"too_big",maximum:Number.MAX_SAFE_INTEGER,note:"Integers must be within the safe integer range.",inst:e,origin:r,continue:!n.abort}):i.issues.push({input:u,code:"too_small",minimum:Number.MIN_SAFE_INTEGER,note:"Integers must be within the safe integer range.",inst:e,origin:r,continue:!n.abort});return}}u<o&&i.issues.push({origin:"number",input:u,code:"too_small",minimum:o,inclusive:!0,inst:e,continue:!n.abort}),u>c&&i.issues.push({origin:"number",input:u,code:"too_big",maximum:c,inst:e})}}),Zt=s("$ZodCheckMaxLength",(e,n)=>{var t;A.init(e,n),(t=e._zod.def).when??(t.when=r=>{const o=r.value;return!pe(o)&&o.length!==void 0}),e._zod.onattach.push(r=>{const o=r._zod.bag.maximum??Number.POSITIVE_INFINITY;n.maximum<o&&(r._zod.bag.maximum=n.maximum)}),e._zod.check=r=>{const o=r.value;if(o.length<=n.maximum)return;const i=me(o);r.issues.push({origin:i,code:"too_big",maximum:n.maximum,inclusive:!0,input:o,inst:e,continue:!n.abort})}}),$t=s("$ZodCheckMinLength",(e,n)=>{var t;A.init(e,n),(t=e._zod.def).when??(t.when=r=>{const o=r.value;return!pe(o)&&o.length!==void 0}),e._zod.onattach.push(r=>{const o=r._zod.bag.minimum??Number.NEGATIVE_INFINITY;n.minimum>o&&(r._zod.bag.minimum=n.minimum)}),e._zod.check=r=>{const o=r.value;if(o.length>=n.minimum)return;const i=me(o);r.issues.push({origin:i,code:"too_small",minimum:n.minimum,inclusive:!0,input:o,inst:e,continue:!n.abort})}}),yt=s("$ZodCheckLengthEquals",(e,n)=>{var t;A.init(e,n),(t=e._zod.def).when??(t.when=r=>{const o=r.value;return!pe(o)&&o.length!==void 0}),e._zod.onattach.push(r=>{const o=r._zod.bag;o.minimum=n.length,o.maximum=n.length,o.length=n.length}),e._zod.check=r=>{const o=r.value,c=o.length;if(c===n.length)return;const i=me(o),u=c>n.length;r.issues.push({origin:i,...u?{code:"too_big",maximum:n.length}:{code:"too_small",minimum:n.length},inclusive:!0,exact:!0,input:r.value,inst:e,continue:!n.abort})}}),ie=s("$ZodCheckStringFormat",(e,n)=>{var t,r;A.init(e,n),e._zod.onattach.push(o=>{const c=o._zod.bag;c.format=n.format,n.pattern&&(c.patterns??(c.patterns=new Set),c.patterns.add(n.pattern))}),n.pattern?(t=e._zod).check??(t.check=o=>{n.pattern.lastIndex=0,!n.pattern.test(o.value)&&o.issues.push({origin:"string",code:"invalid_format",format:n.format,input:o.value,...n.pattern?{pattern:n.pattern.toString()}:{},inst:e,continue:!n.abort})}):(r=e._zod).check??(r.check=()=>{})}),It=s("$ZodCheckRegex",(e,n)=>{ie.init(e,n),e._zod.check=t=>{n.pattern.lastIndex=0,!n.pattern.test(t.value)&&t.issues.push({origin:"string",code:"invalid_format",format:"regex",input:t.value,pattern:n.pattern.toString(),inst:e,continue:!n.abort})}}),Et=s("$ZodCheckLowerCase",(e,n)=>{n.pattern??(n.pattern=bt),ie.init(e,n)}),At=s("$ZodCheckUpperCase",(e,n)=>{n.pattern??(n.pattern=zt),ie.init(e,n)}),Pt=s("$ZodCheckIncludes",(e,n)=>{A.init(e,n);const t=te(n.includes),r=new RegExp(typeof n.position=="number"?`^.{${n.position}}${t}`:t);n.pattern=r,e._zod.onattach.push(o=>{const c=o._zod.bag;c.patterns??(c.patterns=new Set),c.patterns.add(r)}),e._zod.check=o=>{o.value.includes(n.includes,n.position)||o.issues.push({origin:"string",code:"invalid_format",format:"includes",includes:n.includes,input:o.value,inst:e,continue:!n.abort})}}),Tt=s("$ZodCheckStartsWith",(e,n)=>{A.init(e,n);const t=new RegExp(`^${te(n.prefix)}.*`);n.pattern??(n.pattern=t),e._zod.onattach.push(r=>{const o=r._zod.bag;o.patterns??(o.patterns=new Set),o.patterns.add(t)}),e._zod.check=r=>{r.value.startsWith(n.prefix)||r.issues.push({origin:"string",code:"invalid_format",format:"starts_with",prefix:n.prefix,input:r.value,inst:e,continue:!n.abort})}}),Ot=s("$ZodCheckEndsWith",(e,n)=>{A.init(e,n);const t=new RegExp(`.*${te(n.suffix)}$`);n.pattern??(n.pattern=t),e._zod.onattach.push(r=>{const o=r._zod.bag;o.patterns??(o.patterns=new Set),o.patterns.add(t)}),e._zod.check=r=>{r.value.endsWith(n.suffix)||r.issues.push({origin:"string",code:"invalid_format",format:"ends_with",suffix:n.suffix,input:r.value,inst:e,continue:!n.abort})}}),St=s("$ZodCheckOverwrite",(e,n)=>{A.init(e,n),e._zod.check=t=>{t.value=n.tx(t.value)}});class Ct{constructor(n=[]){this.content=[],this.indent=0,this&&(this.args=n)}indented(n){this.indent+=1,n(this),this.indent-=1}write(n){if(typeof n=="function"){n(this,{execution:"sync"}),n(this,{execution:"async"});return}const r=n.split(`
2
+ `).filter(i=>i),o=Math.min(...r.map(i=>i.length-i.trimStart().length)),c=r.map(i=>i.slice(o)).map(i=>" ".repeat(this.indent*2)+i);for(const i of c)this.content.push(i)}compile(){const n=Function,t=this?.args,o=[...(this?.content??[""]).map(c=>` ${c}`)];return new n(...t,o.join(`
3
+ `))}}const Nt={major:4,minor:1,patch:8},z=s("$ZodType",(e,n)=>{var t;e??(e={}),e._zod.def=n,e._zod.bag=e._zod.bag||{},e._zod.version=Nt;const r=[...e._zod.def.checks??[]];e._zod.traits.has("$ZodCheck")&&r.unshift(e);for(const o of r)for(const c of o._zod.onattach)c(e);if(r.length===0)(t=e._zod).deferred??(t.deferred=[]),e._zod.deferred?.push(()=>{e._zod.run=e._zod.parse});else{const o=(i,u,a)=>{let l=U(i),h;for(const w of u){if(w._zod.def.when){if(!w._zod.def.when(i))continue}else if(l)continue;const k=i.issues.length,v=w._zod.check(i);if(v instanceof Promise&&a?.async===!1)throw new L;if(h||v instanceof Promise)h=(h??Promise.resolve()).then(async()=>{await v,i.issues.length!==k&&(l||(l=U(i,k)))});else{if(i.issues.length===k)continue;l||(l=U(i,k))}}return h?h.then(()=>i):i},c=(i,u,a)=>{if(U(i))return i.aborted=!0,i;const l=o(u,r,a);if(l instanceof Promise){if(a.async===!1)throw new L;return l.then(h=>e._zod.parse(h,a))}return e._zod.parse(l,a)};e._zod.run=(i,u)=>{if(u.skipChecks)return e._zod.parse(i,u);if(u.direction==="backward"){const l=e._zod.parse({value:i.value,issues:[]},{...u,skipChecks:!0});return l instanceof Promise?l.then(h=>c(h,i,u)):c(l,i,u)}const a=e._zod.parse(i,u);if(a instanceof Promise){if(u.async===!1)throw new L;return a.then(l=>o(l,r,u))}return o(a,r,u)}}e["~standard"]={validate:o=>{try{const c=xn(e,o);return c.success?{value:c.data}:{issues:c.error?.issues}}catch{return Fn(e,o).then(i=>i.success?{value:i.data}:{issues:i.error?.issues})}},vendor:"zod",version:1}}),ve=s("$ZodString",(e,n)=>{z.init(e,n),e._zod.pattern=[...e?._zod.bag?.patterns??[]].pop()??mt(e._zod.bag),e._zod.parse=(t,r)=>{if(n.coerce)try{t.value=String(t.value)}catch{}return typeof t.value=="string"||t.issues.push({expected:"string",code:"invalid_type",input:t.value,inst:e}),t}}),_=s("$ZodStringFormat",(e,n)=>{ie.init(e,n),ve.init(e,n)}),Dt=s("$ZodGUID",(e,n)=>{n.pattern??(n.pattern=nt),_.init(e,n)}),jt=s("$ZodUUID",(e,n)=>{if(n.version){const r={v1:1,v2:2,v3:3,v4:4,v5:5,v6:6,v7:7,v8:8}[n.version];if(r===void 0)throw new Error(`Invalid UUID version: "${n.version}"`);n.pattern??(n.pattern=Ee(r))}else n.pattern??(n.pattern=Ee());_.init(e,n)}),Rt=s("$ZodEmail",(e,n)=>{n.pattern??(n.pattern=tt),_.init(e,n)}),xt=s("$ZodURL",(e,n)=>{_.init(e,n),e._zod.check=t=>{try{const r=t.value.trim(),o=new URL(r);n.hostname&&(n.hostname.lastIndex=0,n.hostname.test(o.hostname)||t.issues.push({code:"invalid_format",format:"url",note:"Invalid hostname",pattern:lt.source,input:t.value,inst:e,continue:!n.abort})),n.protocol&&(n.protocol.lastIndex=0,n.protocol.test(o.protocol.endsWith(":")?o.protocol.slice(0,-1):o.protocol)||t.issues.push({code:"invalid_format",format:"url",note:"Invalid protocol",pattern:n.protocol.source,input:t.value,inst:e,continue:!n.abort})),n.normalize?t.value=o.href:t.value=r;return}catch{t.issues.push({code:"invalid_format",format:"url",input:t.value,inst:e,continue:!n.abort})}}}),Ft=s("$ZodEmoji",(e,n)=>{n.pattern??(n.pattern=ot()),_.init(e,n)}),Ut=s("$ZodNanoID",(e,n)=>{n.pattern??(n.pattern=Qn),_.init(e,n)}),Lt=s("$ZodCUID",(e,n)=>{n.pattern??(n.pattern=Kn),_.init(e,n)}),Mt=s("$ZodCUID2",(e,n)=>{n.pattern??(n.pattern=qn),_.init(e,n)}),Vt=s("$ZodULID",(e,n)=>{n.pattern??(n.pattern=Hn),_.init(e,n)}),Bt=s("$ZodXID",(e,n)=>{n.pattern??(n.pattern=Yn),_.init(e,n)}),Wt=s("$ZodKSUID",(e,n)=>{n.pattern??(n.pattern=Xn),_.init(e,n)}),Gt=s("$ZodISODateTime",(e,n)=>{n.pattern??(n.pattern=ht(n)),_.init(e,n)}),Jt=s("$ZodISODate",(e,n)=>{n.pattern??(n.pattern=ft),_.init(e,n)}),Kt=s("$ZodISOTime",(e,n)=>{n.pattern??(n.pattern=pt(n)),_.init(e,n)}),qt=s("$ZodISODuration",(e,n)=>{n.pattern??(n.pattern=et),_.init(e,n)}),Ht=s("$ZodIPv4",(e,n)=>{n.pattern??(n.pattern=it),_.init(e,n),e._zod.onattach.push(t=>{const r=t._zod.bag;r.format="ipv4"})}),Yt=s("$ZodIPv6",(e,n)=>{n.pattern??(n.pattern=ct),_.init(e,n),e._zod.onattach.push(t=>{const r=t._zod.bag;r.format="ipv6"}),e._zod.check=t=>{try{new URL(`http://[${t.value}]`)}catch{t.issues.push({code:"invalid_format",format:"ipv6",input:t.value,inst:e,continue:!n.abort})}}}),Xt=s("$ZodCIDRv4",(e,n)=>{n.pattern??(n.pattern=st),_.init(e,n)}),Qt=s("$ZodCIDRv6",(e,n)=>{n.pattern??(n.pattern=ut),_.init(e,n),e._zod.check=t=>{const r=t.value.split("/");try{if(r.length!==2)throw new Error;const[o,c]=r;if(!c)throw new Error;const i=Number(c);if(`${i}`!==c)throw new Error;if(i<0||i>128)throw new Error;new URL(`http://[${o}]`)}catch{t.issues.push({code:"invalid_format",format:"cidrv6",input:t.value,inst:e,continue:!n.abort})}}});function an(e){if(e==="")return!0;if(e.length%4!==0)return!1;try{return atob(e),!0}catch{return!1}}const er=s("$ZodBase64",(e,n)=>{n.pattern??(n.pattern=at),_.init(e,n),e._zod.onattach.push(t=>{t._zod.bag.contentEncoding="base64"}),e._zod.check=t=>{an(t.value)||t.issues.push({code:"invalid_format",format:"base64",input:t.value,inst:e,continue:!n.abort})}});function nr(e){if(!tn.test(e))return!1;const n=e.replace(/[-_]/g,r=>r==="-"?"+":"/"),t=n.padEnd(Math.ceil(n.length/4)*4,"=");return an(t)}const tr=s("$ZodBase64URL",(e,n)=>{n.pattern??(n.pattern=tn),_.init(e,n),e._zod.onattach.push(t=>{t._zod.bag.contentEncoding="base64url"}),e._zod.check=t=>{nr(t.value)||t.issues.push({code:"invalid_format",format:"base64url",input:t.value,inst:e,continue:!n.abort})}}),rr=s("$ZodE164",(e,n)=>{n.pattern??(n.pattern=dt),_.init(e,n)});function or(e,n=null){try{const t=e.split(".");if(t.length!==3)return!1;const[r]=t;if(!r)return!1;const o=JSON.parse(atob(r));return!("typ"in o&&o?.typ!=="JWT"||!o.alg||n&&(!("alg"in o)||o.alg!==n))}catch{return!1}}const ir=s("$ZodJWT",(e,n)=>{_.init(e,n),e._zod.check=t=>{or(t.value,n.alg)||t.issues.push({code:"invalid_format",format:"jwt",input:t.value,inst:e,continue:!n.abort})}}),ln=s("$ZodNumber",(e,n)=>{z.init(e,n),e._zod.pattern=e._zod.bag.pattern??gt,e._zod.parse=(t,r)=>{if(n.coerce)try{t.value=Number(t.value)}catch{}const o=t.value;if(typeof o=="number"&&!Number.isNaN(o)&&Number.isFinite(o))return t;const c=typeof o=="number"?Number.isNaN(o)?"NaN":Number.isFinite(o)?void 0:"Infinity":void 0;return t.issues.push({expected:"number",code:"invalid_type",input:o,inst:e,...c?{received:c}:{}}),t}}),cr=s("$ZodNumber",(e,n)=>{kt.init(e,n),ln.init(e,n)}),sr=s("$ZodBoolean",(e,n)=>{z.init(e,n),e._zod.pattern=vt,e._zod.parse=(t,r)=>{if(n.coerce)try{t.value=!!t.value}catch{}const o=t.value;return typeof o=="boolean"||t.issues.push({expected:"boolean",code:"invalid_type",input:o,inst:e}),t}}),ur=s("$ZodUnknown",(e,n)=>{z.init(e,n),e._zod.parse=t=>t}),ar=s("$ZodNever",(e,n)=>{z.init(e,n),e._zod.parse=(t,r)=>(t.issues.push({expected:"never",code:"invalid_type",input:t.value,inst:e}),t)});function Ae(e,n,t){e.issues.length&&n.issues.push(...Xe(t,e.issues)),n.value[t]=e.value}const lr=s("$ZodArray",(e,n)=>{z.init(e,n),e._zod.parse=(t,r)=>{const o=t.value;if(!Array.isArray(o))return t.issues.push({expected:"array",code:"invalid_type",input:o,inst:e}),t;t.value=Array(o.length);const c=[];for(let i=0;i<o.length;i++){const u=o[i],a=n.element._zod.run({value:u,issues:[]},r);a instanceof Promise?c.push(a.then(l=>Ae(l,t,i))):Ae(a,t,i)}return c.length?Promise.all(c).then(()=>t):t}});function ee(e,n,t,r){e.issues.length&&n.issues.push(...Xe(t,e.issues)),e.value===void 0?t in r&&(n.value[t]=void 0):n.value[t]=e.value}function dn(e){const n=Object.keys(e.shape);for(const r of n)if(!e.shape?.[r]?._zod?.traits?.has("$ZodType"))throw new Error(`Invalid element at key "${r}": expected a Zod schema`);const t=En(e.shape);return{...e,keys:n,keySet:new Set(n),numKeys:n.length,optionalKeys:new Set(t)}}function fn(e,n,t,r,o,c){const i=[],u=o.keySet,a=o.catchall._zod,l=a.def.type;for(const h of Object.keys(n)){if(u.has(h))continue;if(l==="never"){i.push(h);continue}const w=a.run({value:n[h],issues:[]},r);w instanceof Promise?e.push(w.then(k=>ee(k,t,h,n))):ee(w,t,h,n)}return i.length&&t.issues.push({code:"unrecognized_keys",keys:i,input:n,inst:c}),e.length?Promise.all(e).then(()=>t):t}const dr=s("$ZodObject",(e,n)=>{z.init(e,n);const t=fe(()=>dn(n));m(e._zod,"propValues",()=>{const i=n.shape,u={};for(const a in i){const l=i[a]._zod;if(l.values){u[a]??(u[a]=new Set);for(const h of l.values)u[a].add(h)}}return u});const r=Q,o=n.catchall;let c;e._zod.parse=(i,u)=>{c??(c=t.value);const a=i.value;if(!r(a))return i.issues.push({expected:"object",code:"invalid_type",input:a,inst:e}),i;i.value={};const l=[],h=c.shape;for(const w of c.keys){const v=h[w]._zod.run({value:a[w],issues:[]},u);v instanceof Promise?l.push(v.then(f=>ee(f,i,w,a))):ee(v,i,w,a)}return o?fn(l,a,i,u,t.value,e):l.length?Promise.all(l).then(()=>i):i}}),fr=s("$ZodObjectJIT",(e,n)=>{dr.init(e,n);const t=e._zod.parse,r=fe(()=>dn(n)),o=k=>{const v=new Ct(["shape","payload","ctx"]),f=r.value,p=$=>{const E=Ie($);return`shape[${E}]._zod.run({ value: input[${E}], issues: [] }, ctx)`};v.write("const input = payload.value;");const b=Object.create(null);let I=0;for(const $ of f.keys)b[$]=`key_${I++}`;v.write("const newResult = {};");for(const $ of f.keys){const E=b[$],P=Ie($);v.write(`const ${E} = ${p($)};`),v.write(`
4
+ if (${E}.issues.length) {
5
+ payload.issues = payload.issues.concat(${E}.issues.map(iss => ({
6
+ ...iss,
7
+ path: iss.path ? [${P}, ...iss.path] : [${P}]
8
+ })));
9
+ }
10
+
11
+
12
+ if (${E}.value === undefined) {
13
+ if (${P} in input) {
14
+ newResult[${P}] = undefined;
15
+ }
16
+ } else {
17
+ newResult[${P}] = ${E}.value;
18
+ }
19
+
20
+ `)}v.write("payload.value = newResult;"),v.write("return payload;");const O=v.compile();return($,E)=>O(k,$,E)};let c;const i=Q,u=!qe.jitless,l=u&&yn.value,h=n.catchall;let w;e._zod.parse=(k,v)=>{w??(w=r.value);const f=k.value;return i(f)?u&&l&&v?.async===!1&&v.jitless!==!0?(c||(c=o(n.shape)),k=c(k,v),h?fn([],f,k,v,w,e):k):t(k,v):(k.issues.push({expected:"object",code:"invalid_type",input:f,inst:e}),k)}});function Pe(e,n,t,r){for(const c of e)if(c.issues.length===0)return n.value=c.value,n;const o=e.filter(c=>!U(c));return o.length===1?(n.value=o[0].value,o[0]):(n.issues.push({code:"invalid_union",input:n.value,inst:t,errors:e.map(c=>c.issues.map(i=>x(i,r,R())))}),n)}const pr=s("$ZodUnion",(e,n)=>{z.init(e,n),m(e._zod,"optin",()=>n.options.some(o=>o._zod.optin==="optional")?"optional":void 0),m(e._zod,"optout",()=>n.options.some(o=>o._zod.optout==="optional")?"optional":void 0),m(e._zod,"values",()=>{if(n.options.every(o=>o._zod.values))return new Set(n.options.flatMap(o=>Array.from(o._zod.values)))}),m(e._zod,"pattern",()=>{if(n.options.every(o=>o._zod.pattern)){const o=n.options.map(c=>c._zod.pattern);return new RegExp(`^(${o.map(c=>he(c.source)).join("|")})$`)}});const t=n.options.length===1,r=n.options[0]._zod.run;e._zod.parse=(o,c)=>{if(t)return r(o,c);let i=!1;const u=[];for(const a of n.options){const l=a._zod.run({value:o.value,issues:[]},c);if(l instanceof Promise)u.push(l),i=!0;else{if(l.issues.length===0)return l;u.push(l)}}return i?Promise.all(u).then(a=>Pe(a,o,e,c)):Pe(u,o,e,c)}}),hr=s("$ZodIntersection",(e,n)=>{z.init(e,n),e._zod.parse=(t,r)=>{const o=t.value,c=n.left._zod.run({value:o,issues:[]},r),i=n.right._zod.run({value:o,issues:[]},r);return c instanceof Promise||i instanceof Promise?Promise.all([c,i]).then(([a,l])=>Te(t,a,l)):Te(t,c,i)}});function le(e,n){if(e===n)return{valid:!0,data:e};if(e instanceof Date&&n instanceof Date&&+e==+n)return{valid:!0,data:e};if(W(e)&&W(n)){const t=Object.keys(n),r=Object.keys(e).filter(c=>t.indexOf(c)!==-1),o={...e,...n};for(const c of r){const i=le(e[c],n[c]);if(!i.valid)return{valid:!1,mergeErrorPath:[c,...i.mergeErrorPath]};o[c]=i.data}return{valid:!0,data:o}}if(Array.isArray(e)&&Array.isArray(n)){if(e.length!==n.length)return{valid:!1,mergeErrorPath:[]};const t=[];for(let r=0;r<e.length;r++){const o=e[r],c=n[r],i=le(o,c);if(!i.valid)return{valid:!1,mergeErrorPath:[r,...i.mergeErrorPath]};t.push(i.data)}return{valid:!0,data:t}}return{valid:!1,mergeErrorPath:[]}}function Te(e,n,t){if(n.issues.length&&e.issues.push(...n.issues),t.issues.length&&e.issues.push(...t.issues),U(e))return e;const r=le(n.value,t.value);if(!r.valid)throw new Error(`Unmergable intersection. Error path: ${JSON.stringify(r.mergeErrorPath)}`);return e.value=r.data,e}const mr=s("$ZodEnum",(e,n)=>{z.init(e,n);const t=kn(n.entries),r=new Set(t);e._zod.values=r,e._zod.pattern=new RegExp(`^(${t.filter(o=>In.has(typeof o)).map(o=>typeof o=="string"?te(o):o.toString()).join("|")})$`),e._zod.parse=(o,c)=>{const i=o.value;return r.has(i)||o.issues.push({code:"invalid_value",values:t,input:i,inst:e}),o}}),_r=s("$ZodTransform",(e,n)=>{z.init(e,n),e._zod.parse=(t,r)=>{if(r.direction==="backward")throw new Ke(e.constructor.name);const o=n.transform(t.value,t);if(r.async)return(o instanceof Promise?o:Promise.resolve(o)).then(i=>(t.value=i,t));if(o instanceof Promise)throw new L;return t.value=o,t}});function Oe(e,n){return e.issues.length&&n===void 0?{issues:[],value:void 0}:e}const gr=s("$ZodOptional",(e,n)=>{z.init(e,n),e._zod.optin="optional",e._zod.optout="optional",m(e._zod,"values",()=>n.innerType._zod.values?new Set([...n.innerType._zod.values,void 0]):void 0),m(e._zod,"pattern",()=>{const t=n.innerType._zod.pattern;return t?new RegExp(`^(${he(t.source)})?$`):void 0}),e._zod.parse=(t,r)=>{if(n.innerType._zod.optin==="optional"){const o=n.innerType._zod.run(t,r);return o instanceof Promise?o.then(c=>Oe(c,t.value)):Oe(o,t.value)}return t.value===void 0?t:n.innerType._zod.run(t,r)}}),vr=s("$ZodNullable",(e,n)=>{z.init(e,n),m(e._zod,"optin",()=>n.innerType._zod.optin),m(e._zod,"optout",()=>n.innerType._zod.optout),m(e._zod,"pattern",()=>{const t=n.innerType._zod.pattern;return t?new RegExp(`^(${he(t.source)}|null)$`):void 0}),m(e._zod,"values",()=>n.innerType._zod.values?new Set([...n.innerType._zod.values,null]):void 0),e._zod.parse=(t,r)=>t.value===null?t:n.innerType._zod.run(t,r)}),br=s("$ZodDefault",(e,n)=>{z.init(e,n),e._zod.optin="optional",m(e._zod,"values",()=>n.innerType._zod.values),e._zod.parse=(t,r)=>{if(r.direction==="backward")return n.innerType._zod.run(t,r);if(t.value===void 0)return t.value=n.defaultValue,t;const o=n.innerType._zod.run(t,r);return o instanceof Promise?o.then(c=>Se(c,n)):Se(o,n)}});function Se(e,n){return e.value===void 0&&(e.value=n.defaultValue),e}const zr=s("$ZodPrefault",(e,n)=>{z.init(e,n),e._zod.optin="optional",m(e._zod,"values",()=>n.innerType._zod.values),e._zod.parse=(t,r)=>(r.direction==="backward"||t.value===void 0&&(t.value=n.defaultValue),n.innerType._zod.run(t,r))}),wr=s("$ZodNonOptional",(e,n)=>{z.init(e,n),m(e._zod,"values",()=>{const t=n.innerType._zod.values;return t?new Set([...t].filter(r=>r!==void 0)):void 0}),e._zod.parse=(t,r)=>{const o=n.innerType._zod.run(t,r);return o instanceof Promise?o.then(c=>Ce(c,e)):Ce(o,e)}});function Ce(e,n){return!e.issues.length&&e.value===void 0&&e.issues.push({code:"invalid_type",expected:"nonoptional",input:e.value,inst:n}),e}const kr=s("$ZodCatch",(e,n)=>{z.init(e,n),m(e._zod,"optin",()=>n.innerType._zod.optin),m(e._zod,"optout",()=>n.innerType._zod.optout),m(e._zod,"values",()=>n.innerType._zod.values),e._zod.parse=(t,r)=>{if(r.direction==="backward")return n.innerType._zod.run(t,r);const o=n.innerType._zod.run(t,r);return o instanceof Promise?o.then(c=>(t.value=c.value,c.issues.length&&(t.value=n.catchValue({...t,error:{issues:c.issues.map(i=>x(i,r,R()))},input:t.value}),t.issues=[]),t)):(t.value=o.value,o.issues.length&&(t.value=n.catchValue({...t,error:{issues:o.issues.map(c=>x(c,r,R()))},input:t.value}),t.issues=[]),t)}}),Zr=s("$ZodPipe",(e,n)=>{z.init(e,n),m(e._zod,"values",()=>n.in._zod.values),m(e._zod,"optin",()=>n.in._zod.optin),m(e._zod,"optout",()=>n.out._zod.optout),m(e._zod,"propValues",()=>n.in._zod.propValues),e._zod.parse=(t,r)=>{if(r.direction==="backward"){const c=n.out._zod.run(t,r);return c instanceof Promise?c.then(i=>H(i,n.in,r)):H(c,n.in,r)}const o=n.in._zod.run(t,r);return o instanceof Promise?o.then(c=>H(c,n.out,r)):H(o,n.out,r)}});function H(e,n,t){return e.issues.length?(e.aborted=!0,e):n._zod.run({value:e.value,issues:e.issues},t)}const $r=s("$ZodReadonly",(e,n)=>{z.init(e,n),m(e._zod,"propValues",()=>n.innerType._zod.propValues),m(e._zod,"values",()=>n.innerType._zod.values),m(e._zod,"optin",()=>n.innerType._zod.optin),m(e._zod,"optout",()=>n.innerType._zod.optout),e._zod.parse=(t,r)=>{if(r.direction==="backward")return n.innerType._zod.run(t,r);const o=n.innerType._zod.run(t,r);return o instanceof Promise?o.then(Ne):Ne(o)}});function Ne(e){return e.value=Object.freeze(e.value),e}const yr=s("$ZodCustom",(e,n)=>{A.init(e,n),z.init(e,n),e._zod.parse=(t,r)=>t,e._zod.check=t=>{const r=t.value,o=n.fn(r);if(o instanceof Promise)return o.then(c=>De(c,t,r,e));De(o,t,r,e)}});function De(e,n,t,r){if(!e){const o={code:"custom",input:t,inst:r,path:[...r._zod.def.path??[]],continue:!r._zod.def.abort};r._zod.def.params&&(o.params=r._zod.def.params),n.issues.push(G(o))}}class Ir{constructor(){this._map=new WeakMap,this._idmap=new Map}add(n,...t){const r=t[0];if(this._map.set(n,r),r&&typeof r=="object"&&"id"in r){if(this._idmap.has(r.id))throw new Error(`ID ${r.id} already exists in the registry`);this._idmap.set(r.id,n)}return this}clear(){return this._map=new WeakMap,this._idmap=new Map,this}remove(n){const t=this._map.get(n);return t&&typeof t=="object"&&"id"in t&&this._idmap.delete(t.id),this._map.delete(n),this}get(n){const t=n._zod.parent;if(t){const r={...this.get(t)??{}};delete r.id;const o={...r,...this._map.get(n)};return Object.keys(o).length?o:void 0}return this._map.get(n)}has(n){return this._map.has(n)}}function Er(){return new Ir}const Y=Er();function Ar(e,n){return new e({type:"string",...d(n)})}function Pr(e,n){return new e({type:"string",format:"email",check:"string_format",abort:!1,...d(n)})}function je(e,n){return new e({type:"string",format:"guid",check:"string_format",abort:!1,...d(n)})}function Tr(e,n){return new e({type:"string",format:"uuid",check:"string_format",abort:!1,...d(n)})}function Or(e,n){return new e({type:"string",format:"uuid",check:"string_format",abort:!1,version:"v4",...d(n)})}function Sr(e,n){return new e({type:"string",format:"uuid",check:"string_format",abort:!1,version:"v6",...d(n)})}function Cr(e,n){return new e({type:"string",format:"uuid",check:"string_format",abort:!1,version:"v7",...d(n)})}function Nr(e,n){return new e({type:"string",format:"url",check:"string_format",abort:!1,...d(n)})}function Dr(e,n){return new e({type:"string",format:"emoji",check:"string_format",abort:!1,...d(n)})}function jr(e,n){return new e({type:"string",format:"nanoid",check:"string_format",abort:!1,...d(n)})}function Rr(e,n){return new e({type:"string",format:"cuid",check:"string_format",abort:!1,...d(n)})}function xr(e,n){return new e({type:"string",format:"cuid2",check:"string_format",abort:!1,...d(n)})}function Fr(e,n){return new e({type:"string",format:"ulid",check:"string_format",abort:!1,...d(n)})}function Ur(e,n){return new e({type:"string",format:"xid",check:"string_format",abort:!1,...d(n)})}function Lr(e,n){return new e({type:"string",format:"ksuid",check:"string_format",abort:!1,...d(n)})}function Mr(e,n){return new e({type:"string",format:"ipv4",check:"string_format",abort:!1,...d(n)})}function Vr(e,n){return new e({type:"string",format:"ipv6",check:"string_format",abort:!1,...d(n)})}function Br(e,n){return new e({type:"string",format:"cidrv4",check:"string_format",abort:!1,...d(n)})}function Wr(e,n){return new e({type:"string",format:"cidrv6",check:"string_format",abort:!1,...d(n)})}function Gr(e,n){return new e({type:"string",format:"base64",check:"string_format",abort:!1,...d(n)})}function Jr(e,n){return new e({type:"string",format:"base64url",check:"string_format",abort:!1,...d(n)})}function Kr(e,n){return new e({type:"string",format:"e164",check:"string_format",abort:!1,...d(n)})}function qr(e,n){return new e({type:"string",format:"jwt",check:"string_format",abort:!1,...d(n)})}function Hr(e,n){return new e({type:"string",format:"datetime",check:"string_format",offset:!1,local:!1,precision:null,...d(n)})}function Yr(e,n){return new e({type:"string",format:"date",check:"string_format",...d(n)})}function Xr(e,n){return new e({type:"string",format:"time",check:"string_format",precision:null,...d(n)})}function Qr(e,n){return new e({type:"string",format:"duration",check:"string_format",...d(n)})}function eo(e,n){return new e({type:"number",checks:[],...d(n)})}function no(e,n){return new e({type:"number",check:"number_format",abort:!1,format:"safeint",...d(n)})}function to(e,n){return new e({type:"boolean",...d(n)})}function ro(e){return new e({type:"unknown"})}function oo(e,n){return new e({type:"never",...d(n)})}function Re(e,n){return new sn({check:"less_than",...d(n),value:e,inclusive:!1})}function se(e,n){return new sn({check:"less_than",...d(n),value:e,inclusive:!0})}function xe(e,n){return new un({check:"greater_than",...d(n),value:e,inclusive:!1})}function ue(e,n){return new un({check:"greater_than",...d(n),value:e,inclusive:!0})}function Fe(e,n){return new wt({check:"multiple_of",...d(n),value:e})}function pn(e,n){return new Zt({check:"max_length",...d(n),maximum:e})}function ne(e,n){return new $t({check:"min_length",...d(n),minimum:e})}function hn(e,n){return new yt({check:"length_equals",...d(n),length:e})}function io(e,n){return new It({check:"string_format",format:"regex",...d(n),pattern:e})}function co(e){return new Et({check:"string_format",format:"lowercase",...d(e)})}function so(e){return new At({check:"string_format",format:"uppercase",...d(e)})}function uo(e,n){return new Pt({check:"string_format",format:"includes",...d(n),includes:e})}function ao(e,n){return new Tt({check:"string_format",format:"starts_with",...d(n),prefix:e})}function lo(e,n){return new Ot({check:"string_format",format:"ends_with",...d(n),suffix:e})}function J(e){return new St({check:"overwrite",tx:e})}function fo(e){return J(n=>n.normalize(e))}function po(){return J(e=>e.trim())}function ho(){return J(e=>e.toLowerCase())}function mo(){return J(e=>e.toUpperCase())}function _o(e,n,t){return new e({type:"array",element:n,...d(t)})}function go(e,n,t){return new e({type:"custom",check:"custom",fn:n,...d(t)})}function vo(e){const n=bo(t=>(t.addIssue=r=>{if(typeof r=="string")t.issues.push(G(r,t.value,n._zod.def));else{const o=r;o.fatal&&(o.continue=!1),o.code??(o.code="custom"),o.input??(o.input=t.value),o.inst??(o.inst=n),o.continue??(o.continue=!n._zod.def.abort),t.issues.push(G(o))}},e(t.value,t)));return n}function bo(e,n){const t=new A({check:"custom",...d(n)});return t._zod.check=e,t}const zo=s("ZodISODateTime",(e,n)=>{Gt.init(e,n),g.init(e,n)});function wo(e){return Hr(zo,e)}const ko=s("ZodISODate",(e,n)=>{Jt.init(e,n),g.init(e,n)});function Zo(e){return Yr(ko,e)}const $o=s("ZodISOTime",(e,n)=>{Kt.init(e,n),g.init(e,n)});function yo(e){return Xr($o,e)}const Io=s("ZodISODuration",(e,n)=>{qt.init(e,n),g.init(e,n)});function Eo(e){return Qr(Io,e)}const Ao=(e,n)=>{en.init(e,n),e.name="ZodError",Object.defineProperties(e,{format:{value:t=>Rn(e,t)},flatten:{value:t=>jn(e,t)},addIssue:{value:t=>{e.issues.push(t),e.message=JSON.stringify(e.issues,ae,2)}},addIssues:{value:t=>{e.issues.push(...t),e.message=JSON.stringify(e.issues,ae,2)}},isEmpty:{get(){return e.issues.length===0}}})},T=s("ZodError",Ao,{Parent:Error}),Po=_e(T),To=ge(T),Oo=re(T),So=oe(T),Co=Un(T),No=Ln(T),Do=Mn(T),jo=Vn(T),Ro=Bn(T),xo=Wn(T),Fo=Gn(T),Uo=Jn(T),Z=s("ZodType",(e,n)=>(z.init(e,n),e.def=n,e.type=n.type,Object.defineProperty(e,"_def",{value:n}),e.check=(...t)=>e.clone({...n,checks:[...n.checks??[],...t.map(r=>typeof r=="function"?{_zod:{check:r,def:{check:"custom"},onattach:[]}}:r)]}),e.clone=(t,r)=>D(e,t,r),e.brand=()=>e,e.register=((t,r)=>(t.add(e,r),e)),e.parse=(t,r)=>Po(e,t,r,{callee:e.parse}),e.safeParse=(t,r)=>Oo(e,t,r),e.parseAsync=async(t,r)=>To(e,t,r,{callee:e.parseAsync}),e.safeParseAsync=async(t,r)=>So(e,t,r),e.spa=e.safeParseAsync,e.encode=(t,r)=>Co(e,t,r),e.decode=(t,r)=>No(e,t,r),e.encodeAsync=async(t,r)=>Do(e,t,r),e.decodeAsync=async(t,r)=>jo(e,t,r),e.safeEncode=(t,r)=>Ro(e,t,r),e.safeDecode=(t,r)=>xo(e,t,r),e.safeEncodeAsync=async(t,r)=>Fo(e,t,r),e.safeDecodeAsync=async(t,r)=>Uo(e,t,r),e.refine=(t,r)=>e.check(Ci(t,r)),e.superRefine=t=>e.check(Ni(t)),e.overwrite=t=>e.check(J(t)),e.optional=()=>Ve(e),e.nullable=()=>Be(e),e.nullish=()=>Ve(Be(e)),e.nonoptional=t=>Ii(e,t),e.array=()=>be(e),e.or=t=>mi([e,t]),e.and=t=>gi(e,t),e.transform=t=>We(e,zi(t)),e.default=t=>Zi(e,t),e.prefault=t=>yi(e,t),e.catch=t=>Ai(e,t),e.pipe=t=>We(e,t),e.readonly=()=>Oi(e),e.describe=t=>{const r=e.clone();return Y.add(r,{description:t}),r},Object.defineProperty(e,"description",{get(){return Y.get(e)?.description},configurable:!0}),e.meta=(...t)=>{if(t.length===0)return Y.get(e);const r=e.clone();return Y.add(r,t[0]),r},e.isOptional=()=>e.safeParse(void 0).success,e.isNullable=()=>e.safeParse(null).success,e)),mn=s("_ZodString",(e,n)=>{ve.init(e,n),Z.init(e,n);const t=e._zod.bag;e.format=t.format??null,e.minLength=t.minimum??null,e.maxLength=t.maximum??null,e.regex=(...r)=>e.check(io(...r)),e.includes=(...r)=>e.check(uo(...r)),e.startsWith=(...r)=>e.check(ao(...r)),e.endsWith=(...r)=>e.check(lo(...r)),e.min=(...r)=>e.check(ne(...r)),e.max=(...r)=>e.check(pn(...r)),e.length=(...r)=>e.check(hn(...r)),e.nonempty=(...r)=>e.check(ne(1,...r)),e.lowercase=r=>e.check(co(r)),e.uppercase=r=>e.check(so(r)),e.trim=()=>e.check(po()),e.normalize=(...r)=>e.check(fo(...r)),e.toLowerCase=()=>e.check(ho()),e.toUpperCase=()=>e.check(mo())}),Lo=s("ZodString",(e,n)=>{ve.init(e,n),mn.init(e,n),e.email=t=>e.check(Pr(Mo,t)),e.url=t=>e.check(Nr(Vo,t)),e.jwt=t=>e.check(qr(oi,t)),e.emoji=t=>e.check(Dr(Bo,t)),e.guid=t=>e.check(je(Ue,t)),e.uuid=t=>e.check(Tr(X,t)),e.uuidv4=t=>e.check(Or(X,t)),e.uuidv6=t=>e.check(Sr(X,t)),e.uuidv7=t=>e.check(Cr(X,t)),e.nanoid=t=>e.check(jr(Wo,t)),e.guid=t=>e.check(je(Ue,t)),e.cuid=t=>e.check(Rr(Go,t)),e.cuid2=t=>e.check(xr(Jo,t)),e.ulid=t=>e.check(Fr(Ko,t)),e.base64=t=>e.check(Gr(ni,t)),e.base64url=t=>e.check(Jr(ti,t)),e.xid=t=>e.check(Ur(qo,t)),e.ksuid=t=>e.check(Lr(Ho,t)),e.ipv4=t=>e.check(Mr(Yo,t)),e.ipv6=t=>e.check(Vr(Xo,t)),e.cidrv4=t=>e.check(Br(Qo,t)),e.cidrv6=t=>e.check(Wr(ei,t)),e.e164=t=>e.check(Kr(ri,t)),e.datetime=t=>e.check(wo(t)),e.date=t=>e.check(Zo(t)),e.time=t=>e.check(yo(t)),e.duration=t=>e.check(Eo(t))});function F(e){return Ar(Lo,e)}const g=s("ZodStringFormat",(e,n)=>{_.init(e,n),mn.init(e,n)}),Mo=s("ZodEmail",(e,n)=>{Rt.init(e,n),g.init(e,n)}),Ue=s("ZodGUID",(e,n)=>{Dt.init(e,n),g.init(e,n)}),X=s("ZodUUID",(e,n)=>{jt.init(e,n),g.init(e,n)}),Vo=s("ZodURL",(e,n)=>{xt.init(e,n),g.init(e,n)}),Bo=s("ZodEmoji",(e,n)=>{Ft.init(e,n),g.init(e,n)}),Wo=s("ZodNanoID",(e,n)=>{Ut.init(e,n),g.init(e,n)}),Go=s("ZodCUID",(e,n)=>{Lt.init(e,n),g.init(e,n)}),Jo=s("ZodCUID2",(e,n)=>{Mt.init(e,n),g.init(e,n)}),Ko=s("ZodULID",(e,n)=>{Vt.init(e,n),g.init(e,n)}),qo=s("ZodXID",(e,n)=>{Bt.init(e,n),g.init(e,n)}),Ho=s("ZodKSUID",(e,n)=>{Wt.init(e,n),g.init(e,n)}),Yo=s("ZodIPv4",(e,n)=>{Ht.init(e,n),g.init(e,n)}),Xo=s("ZodIPv6",(e,n)=>{Yt.init(e,n),g.init(e,n)}),Qo=s("ZodCIDRv4",(e,n)=>{Xt.init(e,n),g.init(e,n)}),ei=s("ZodCIDRv6",(e,n)=>{Qt.init(e,n),g.init(e,n)}),ni=s("ZodBase64",(e,n)=>{er.init(e,n),g.init(e,n)}),ti=s("ZodBase64URL",(e,n)=>{tr.init(e,n),g.init(e,n)}),ri=s("ZodE164",(e,n)=>{rr.init(e,n),g.init(e,n)}),oi=s("ZodJWT",(e,n)=>{ir.init(e,n),g.init(e,n)}),_n=s("ZodNumber",(e,n)=>{ln.init(e,n),Z.init(e,n),e.gt=(r,o)=>e.check(xe(r,o)),e.gte=(r,o)=>e.check(ue(r,o)),e.min=(r,o)=>e.check(ue(r,o)),e.lt=(r,o)=>e.check(Re(r,o)),e.lte=(r,o)=>e.check(se(r,o)),e.max=(r,o)=>e.check(se(r,o)),e.int=r=>e.check(Le(r)),e.safe=r=>e.check(Le(r)),e.positive=r=>e.check(xe(0,r)),e.nonnegative=r=>e.check(ue(0,r)),e.negative=r=>e.check(Re(0,r)),e.nonpositive=r=>e.check(se(0,r)),e.multipleOf=(r,o)=>e.check(Fe(r,o)),e.step=(r,o)=>e.check(Fe(r,o)),e.finite=()=>e;const t=e._zod.bag;e.minValue=Math.max(t.minimum??Number.NEGATIVE_INFINITY,t.exclusiveMinimum??Number.NEGATIVE_INFINITY)??null,e.maxValue=Math.min(t.maximum??Number.POSITIVE_INFINITY,t.exclusiveMaximum??Number.POSITIVE_INFINITY)??null,e.isInt=(t.format??"").includes("int")||Number.isSafeInteger(t.multipleOf??.5),e.isFinite=!0,e.format=t.format??null});function ii(e){return eo(_n,e)}const ci=s("ZodNumberFormat",(e,n)=>{cr.init(e,n),_n.init(e,n)});function Le(e){return no(ci,e)}const si=s("ZodBoolean",(e,n)=>{sr.init(e,n),Z.init(e,n)});function ui(e){return to(si,e)}const ai=s("ZodUnknown",(e,n)=>{ur.init(e,n),Z.init(e,n)});function Me(){return ro(ai)}const li=s("ZodNever",(e,n)=>{ar.init(e,n),Z.init(e,n)});function di(e){return oo(li,e)}const fi=s("ZodArray",(e,n)=>{lr.init(e,n),Z.init(e,n),e.element=n.element,e.min=(t,r)=>e.check(ne(t,r)),e.nonempty=t=>e.check(ne(1,t)),e.max=(t,r)=>e.check(pn(t,r)),e.length=(t,r)=>e.check(hn(t,r)),e.unwrap=()=>e.element});function be(e,n){return _o(fi,e,n)}const pi=s("ZodObject",(e,n)=>{fr.init(e,n),Z.init(e,n),m(e,"shape",()=>n.shape),e.keyof=()=>vi(Object.keys(e._zod.def.shape)),e.catchall=t=>e.clone({...e._zod.def,catchall:t}),e.passthrough=()=>e.clone({...e._zod.def,catchall:Me()}),e.loose=()=>e.clone({...e._zod.def,catchall:Me()}),e.strict=()=>e.clone({...e._zod.def,catchall:di()}),e.strip=()=>e.clone({...e._zod.def,catchall:void 0}),e.extend=t=>On(e,t),e.safeExtend=t=>Sn(e,t),e.merge=t=>Cn(e,t),e.pick=t=>Pn(e,t),e.omit=t=>Tn(e,t),e.partial=(...t)=>Nn(gn,e,t[0]),e.required=(...t)=>Dn(vn,e,t[0])});function M(e,n){const t={type:"object",get shape(){return N(this,"shape",e?$n(e):{}),this.shape},...d(n)};return new pi(t)}const hi=s("ZodUnion",(e,n)=>{pr.init(e,n),Z.init(e,n),e.options=n.options});function mi(e,n){return new hi({type:"union",options:e,...d(n)})}const _i=s("ZodIntersection",(e,n)=>{hr.init(e,n),Z.init(e,n)});function gi(e,n){return new _i({type:"intersection",left:e,right:n})}const de=s("ZodEnum",(e,n)=>{mr.init(e,n),Z.init(e,n),e.enum=n.entries,e.options=Object.values(n.entries);const t=new Set(Object.keys(n.entries));e.extract=(r,o)=>{const c={};for(const i of r)if(t.has(i))c[i]=n.entries[i];else throw new Error(`Key ${i} not found in enum`);return new de({...n,checks:[],...d(o),entries:c})},e.exclude=(r,o)=>{const c={...n.entries};for(const i of r)if(t.has(i))delete c[i];else throw new Error(`Key ${i} not found in enum`);return new de({...n,checks:[],...d(o),entries:c})}});function vi(e,n){const t=Array.isArray(e)?Object.fromEntries(e.map(r=>[r,r])):e;return new de({type:"enum",entries:t,...d(n)})}const bi=s("ZodTransform",(e,n)=>{_r.init(e,n),Z.init(e,n),e._zod.parse=(t,r)=>{if(r.direction==="backward")throw new Ke(e.constructor.name);t.addIssue=c=>{if(typeof c=="string")t.issues.push(G(c,t.value,n));else{const i=c;i.fatal&&(i.continue=!1),i.code??(i.code="custom"),i.input??(i.input=t.value),i.inst??(i.inst=e),t.issues.push(G(i))}};const o=n.transform(t.value,t);return o instanceof Promise?o.then(c=>(t.value=c,t)):(t.value=o,t)}});function zi(e){return new bi({type:"transform",transform:e})}const gn=s("ZodOptional",(e,n)=>{gr.init(e,n),Z.init(e,n),e.unwrap=()=>e._zod.def.innerType});function Ve(e){return new gn({type:"optional",innerType:e})}const wi=s("ZodNullable",(e,n)=>{vr.init(e,n),Z.init(e,n),e.unwrap=()=>e._zod.def.innerType});function Be(e){return new wi({type:"nullable",innerType:e})}const ki=s("ZodDefault",(e,n)=>{br.init(e,n),Z.init(e,n),e.unwrap=()=>e._zod.def.innerType,e.removeDefault=e.unwrap});function Zi(e,n){return new ki({type:"default",innerType:e,get defaultValue(){return typeof n=="function"?n():Ye(n)}})}const $i=s("ZodPrefault",(e,n)=>{zr.init(e,n),Z.init(e,n),e.unwrap=()=>e._zod.def.innerType});function yi(e,n){return new $i({type:"prefault",innerType:e,get defaultValue(){return typeof n=="function"?n():Ye(n)}})}const vn=s("ZodNonOptional",(e,n)=>{wr.init(e,n),Z.init(e,n),e.unwrap=()=>e._zod.def.innerType});function Ii(e,n){return new vn({type:"nonoptional",innerType:e,...d(n)})}const Ei=s("ZodCatch",(e,n)=>{kr.init(e,n),Z.init(e,n),e.unwrap=()=>e._zod.def.innerType,e.removeCatch=e.unwrap});function Ai(e,n){return new Ei({type:"catch",innerType:e,catchValue:typeof n=="function"?n:()=>n})}const Pi=s("ZodPipe",(e,n)=>{Zr.init(e,n),Z.init(e,n),e.in=n.in,e.out=n.out});function We(e,n){return new Pi({type:"pipe",in:e,out:n})}const Ti=s("ZodReadonly",(e,n)=>{$r.init(e,n),Z.init(e,n),e.unwrap=()=>e._zod.def.innerType});function Oi(e){return new Ti({type:"readonly",innerType:e})}const Si=s("ZodCustom",(e,n)=>{yr.init(e,n),Z.init(e,n)});function Ci(e,n={}){return go(Si,e,n)}function Ni(e){return vo(e)}const Di=M({label:F().min(1).max(80).describe('A short name for the credential, such as "GitHub token" or "Stripe API key". The user sees it when asked.')}).strict(),bn=Di.extend({id:F(),sessionID:F()}),Ge=M({sessionID:F().min(1)}).strict(),ji=M({sessionIDs:be(F()),added:bn.optional()}),Je=wn.Rpc.define({id:"oc-hush",events:{changed:{schema:ji}},methods:{pending:{input:Ge,output:be(bn)},reply:{input:M({id:F(),secret:F().min(1).max(8192).regex(/^[\x21-\x7e]+$/).optional()}).strict(),output:M({accepted:ui()})},forget:{input:Ge,output:M({forgotten:ii()})}}});var Ri=y.template("<style>.oc-hush-field[data-component]{width:auto;flex:1;min-width:0}"),xi=y.template("<div style=display:flex;flex-direction:column;gap:12px;padding-bottom:16px><span></span><div style=display:flex;gap:8px;align-items:center>"),Fi=y.template("<span>Credentials cannot contain spaces or line breaks.");const Ui=B.Plugin.define({setup(e){const[n,t]=$e.createStore({}),r=new Set,o=new Set,c=f=>{const p="directory"in f&&typeof f.directory=="string"?f.directory:f.location?.directory;return p?{server:f.server,directory:p}:void 0},i=f=>f.server.client.rpc(Je),u=f=>({location:{directory:f.directory},signal:e.signal}),a=()=>e.toast.show({title:"Could not reach Hush",description:"Check that its server plugin is loaded.",variant:"error"}),l=async f=>{const p=c(f);if(p)try{const b=await i(p).pending({sessionID:f.id},u(p));if(e.signal.aborted)return;t(f.key,$e.reconcile(b));const I=b.find(O=>!o.has(O.id));I&&!r.size&&e.sessions.current()?.key===f.key&&(o.add(I.id),w(p,I))}catch{e.signal.aborted||t(f.key,[])}},h=f=>{const[p,b]=j.createSignal(""),[I,O]=j.createSignal(!1),[$,E]=j.createSignal(!1),P=()=>!/^[\x21-\x7e]*$/.test(p().trim())||p().length>8192;j.onCleanup(()=>{b(""),r.delete(f.item.id)});const S=async C=>{O(!0);try{(await i(f.at).reply({id:f.item.id,secret:C},u(f.at))).accepted||e.toast.show({title:"This credential request has expired."}),f.close()}catch{e.signal.aborted||a(),O(!1)}},ze=()=>{const C=p().trim();C&&!P()&&!I()&&S(C)},we={opacity:.7};return y.createComponent(e.ui.Dialog,{title:"Temporary Credential",get footer(){return[y.createComponent(e.ui.Button,{variant:"ghost",get disabled(){return I()},onClick:()=>{S()},children:"Deny"}),y.createComponent(e.ui.Button,{variant:"contrast",get busy(){return I()},get disabled(){return!p().trim()||P()},onClick:ze,children:"Approve"})]},get children(){return[Ri(),(()=>{var C=xi(),K=C.firstChild,ke=K.nextSibling;return y.insert(K,()=>f.item.label),y.insert(ke,y.createComponent(e.ui.TextInput,{class:"oc-hush-field",get type(){return $()?"text":"password"},size:"large",label:"Credential",placeholder:"Credential",get value(){return p()},onInput:b,onSubmit:ze,get invalid(){return P()},autofocus:!0}),null),y.insert(ke,y.createComponent(e.ui.IconButton,{get icon(){return $()?"outline-eye-slash":"outline-eye"},get label(){return $()?"Hide credential":"Show credential"},size:"large",get pressed(){return $()},onClick:()=>E(!$())}),null),y.insert(C,(()=>{var ce=y.memo(()=>!!P());return()=>ce()&&(()=>{var Ze=Fi();return y.effect(zn=>y.style(Ze,we,zn)),Ze})()})(),null),y.effect(ce=>y.style(K,we,ce)),C})()]}})},w=(f,p)=>{r.has(p.id)||(r.add(p.id),e.dialogs.open(b=>y.createComponent(h,{at:f,item:p,get close(){return b.close}})))},k=(f,p,b)=>{const I=e.sessions.list().filter(S=>S.server.id===f.id&&p.sessionIDs.includes(S.id));I.forEach(S=>{l(S)});const O=p.added;if(!O)return;const $="Hush needs a credential",E=O.label,P=p.sessionIDs[p.sessionIDs.length-1];e.attention.notify({title:$,message:E,session:{server:f.id,id:P},id:O.id}),I.length&&!I.some(S=>S.key===e.sessions.current()?.key)&&e.toast.show({title:$,description:E,icon:"lock",duration:1e4,actions:[{label:"Review",run:()=>w({server:f,directory:b},O)}]})};j.createMemo(j.mapArray(()=>e.servers.list(),f=>{B.createKeyed(()=>{const p=e.servers.get(f);return p?.connected?p:void 0},p=>{j.onCleanup(p.client.rpc(Je).events.on("changed",b=>k(p,b.data,b.location.directory),{signal:e.signal})),e.sessions.list().filter(b=>b.server.id===p.id).forEach(b=>{l(b)})})}))(),B.createKeyed(()=>e.sessions.current(),f=>{l(f)}),e.add(B.ComposerPill,{id:"requests",show:f=>{const p=n[f.session.key]??[],b=c(f.session);if(!(!p.length||!b))return{icon:"lock",tone:"warning",label:p.length===1?`Hush · ${p[0].label}`:`Hush · ${p.length} waiting`,title:"Credential requests",rows:p.map(I=>({id:I.id,label:I.label,icon:"lock",run:()=>w(b,I)}))}}}),e.add(B.Command,{id:"forget",title:"Forget Hush credentials for this session",group:"Hush",section:"session",slash:{name:"hush-forget"},run:async()=>{const f=e.sessions.current(),p=f&&c(f);if(!(!f||!p))try{await i(p).forget({sessionID:f.id},u(p)),e.toast.show({title:"Session credentials forgotten.",variant:"success"})}catch{e.signal.aborted||a()}}})}});exports.default=Ui;
package/dist/hush.js ADDED
@@ -0,0 +1,145 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { mkdirSync, mkdtempSync, readdirSync, rmSync, writeFileSync } from "node:fs";
3
+ import { tmpdir } from "node:os";
4
+ import { join } from "node:path";
5
+ const ended = {
6
+ denied: "The user declined this Hush credential request. Do not request it again unless they ask you to.",
7
+ expired: "The Hush credential request expired before the user answered. Request it again if it is still needed.",
8
+ interrupted: "The Hush credential request was interrupted before the user could answer. Request it again."
9
+ };
10
+ const REDACTED = "[redacted by Hush]";
11
+ const forms = (secret) => {
12
+ const bytes = Buffer.from(secret);
13
+ const encoded = secret.length < 8 ? [] : [
14
+ bytes.toString("base64"),
15
+ bytes.toString("base64").replace(/=+$/, ""),
16
+ bytes.toString("base64url"),
17
+ bytes.toString("hex"),
18
+ bytes.toString("hex").toUpperCase(),
19
+ encodeURIComponent(secret),
20
+ [...secret].reverse().join("")
21
+ ];
22
+ return [.../* @__PURE__ */ new Set([secret, ...encoded])].sort((a, b) => b.length - a.length);
23
+ };
24
+ const sweep = () => {
25
+ for (const name of readdirSync(tmpdir())) {
26
+ const pid = Number(/^oc-hush-(\d+)(-|$)/.exec(name)?.[1]);
27
+ if (!pid || pid === process.pid) continue;
28
+ try {
29
+ process.kill(pid, 0);
30
+ } catch (error) {
31
+ if (error.code === "ESRCH") rmSync(join(tmpdir(), name), { recursive: true, force: true });
32
+ }
33
+ }
34
+ };
35
+ function createHush(onChange = () => {
36
+ }, ttlMs = 15 * 60 * 1e3) {
37
+ const waiting = /* @__PURE__ */ new Map();
38
+ const entries = /* @__PURE__ */ new Map();
39
+ let directory;
40
+ let files = 0;
41
+ const clear = () => {
42
+ if (directory) rmSync(directory, { recursive: true, force: true });
43
+ };
44
+ try {
45
+ sweep();
46
+ } catch {
47
+ }
48
+ const remove = (file) => {
49
+ const entry = entries.get(file);
50
+ if (!entry) return;
51
+ clearTimeout(entry.timer);
52
+ rmSync(file, { force: true });
53
+ entries.delete(file);
54
+ };
55
+ const write = (secret) => {
56
+ if (!directory) {
57
+ const preferred = join(tmpdir(), `oc-hush-${process.pid}`);
58
+ try {
59
+ mkdirSync(preferred, { mode: 448 });
60
+ directory = preferred;
61
+ } catch {
62
+ directory = mkdtempSync(`${preferred}-`);
63
+ }
64
+ process.once("exit", clear);
65
+ }
66
+ const file = join(directory, String(++files));
67
+ writeFileSync(file, secret, { mode: 384, flag: "wx" });
68
+ return file;
69
+ };
70
+ return {
71
+ request(input, signal, lineage = [input.sessionID]) {
72
+ signal.throwIfAborted();
73
+ return new Promise((resolve, reject) => {
74
+ const id = randomUUID();
75
+ const finish = (secret, why = "denied") => {
76
+ if (!waiting.delete(id)) return;
77
+ clearTimeout(timer);
78
+ signal.removeEventListener("abort", cancel);
79
+ onChange({ sessionIDs: lineage });
80
+ if (!secret) {
81
+ reject(new Error(ended[why]));
82
+ return;
83
+ }
84
+ const file = write(secret);
85
+ const expiry = setTimeout(() => remove(file), ttlMs || 5 * 60 * 1e3);
86
+ expiry.unref?.();
87
+ entries.set(file, { lineage, secret, timer: expiry });
88
+ resolve({ file });
89
+ };
90
+ const cancel = () => finish(void 0, "interrupted");
91
+ const timer = setTimeout(() => finish(void 0, "expired"), 5 * 60 * 1e3);
92
+ timer.unref?.();
93
+ const info = { label: input.label, sessionID: input.sessionID, id };
94
+ waiting.set(id, { info, lineage, finish });
95
+ signal.addEventListener("abort", cancel, { once: true });
96
+ onChange({ sessionIDs: lineage, added: info });
97
+ });
98
+ },
99
+ pending(sessionID) {
100
+ return [...waiting.values()].filter((item) => item.lineage.includes(sessionID)).map((item) => item.info);
101
+ },
102
+ reply(id, secret) {
103
+ const item = waiting.get(id);
104
+ if (!item) return { accepted: false };
105
+ item.finish(secret);
106
+ return { accepted: true };
107
+ },
108
+ /** Replaces every live credential, and its common encodings, in any string inside `value`. */
109
+ redact(value) {
110
+ const patterns = [...entries.values()].flatMap((entry) => forms(entry.secret));
111
+ if (!patterns.length) return value;
112
+ const scrub = (item) => {
113
+ if (typeof item === "string") return patterns.reduce((text, form) => text.split(form).join(REDACTED), item);
114
+ if (Array.isArray(item)) return item.map(scrub);
115
+ if (item && typeof item === "object" && Object.getPrototypeOf(item) === Object.prototype) {
116
+ return Object.fromEntries(Object.entries(item).map(([key, field]) => [key, scrub(field)]));
117
+ }
118
+ return item;
119
+ };
120
+ return scrub(value);
121
+ },
122
+ /** Single-use credentials are forgotten once a tool call has read their file. */
123
+ used(input) {
124
+ if (ttlMs) return;
125
+ for (const file of [...entries.keys()]) if (input.includes(file)) remove(file);
126
+ },
127
+ forget(sessionID) {
128
+ const files2 = [...entries].filter(([, entry]) => entry.lineage.includes(sessionID)).map(([file]) => file);
129
+ files2.forEach(remove);
130
+ [...waiting.values()].filter((item) => item.lineage.includes(sessionID)).forEach((item) => item.finish());
131
+ return { forgotten: files2.length };
132
+ },
133
+ dispose() {
134
+ ;
135
+ [...waiting.values()].forEach((item) => item.finish(void 0, "interrupted"));
136
+ [...entries.keys()].forEach(remove);
137
+ clear();
138
+ process.off("exit", clear);
139
+ }
140
+ };
141
+ }
142
+ export {
143
+ createHush
144
+ };
145
+ //# sourceMappingURL=hush.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/hush.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto'\nimport { mkdirSync, mkdtempSync, readdirSync, rmSync, writeFileSync } from 'node:fs'\nimport { tmpdir } from 'node:os'\nimport { join } from 'node:path'\nimport type { Changed, Pending } from './rpc.js'\n\n// `lineage` is the requesting session followed by its ancestors, so a parent session can review and revoke what\n// its subagents requested.\ntype Entry = { lineage: string[]; secret: string; timer: ReturnType<typeof setTimeout> }\ntype Waiting = { info: Pending; lineage: string[]; finish: (secret?: string, why?: keyof typeof ended) => void }\n\n// What the agent is told when a request ends without a credential. Only a refusal by the user is final.\nconst ended = {\n denied: 'The user declined this Hush credential request. Do not request it again unless they ask you to.',\n expired: 'The Hush credential request expired before the user answered. Request it again if it is still needed.',\n interrupted: 'The Hush credential request was interrupted before the user could answer. Request it again.',\n}\n\nconst REDACTED = '[redacted by Hush]'\n// The secret as a command might print it. Short secrets only match exactly, to avoid redacting ordinary text.\nconst forms = (secret: string) => {\n const bytes = Buffer.from(secret)\n const encoded = secret.length < 8 ? [] : [\n bytes.toString('base64'), bytes.toString('base64').replace(/=+$/, ''), bytes.toString('base64url'),\n bytes.toString('hex'), bytes.toString('hex').toUpperCase(), encodeURIComponent(secret), [...secret].reverse().join(''),\n ]\n return [...new Set([secret, ...encoded])].sort((a, b) => b.length - a.length)\n}\n\n// Files of Hush instances whose process ended without cleaning up (killed, crashed). Directories are named after the pid.\nconst sweep = () => {\n for (const name of readdirSync(tmpdir())) {\n const pid = Number(/^oc-hush-(\\d+)(-|$)/.exec(name)?.[1])\n if (!pid || pid === process.pid) continue\n try { process.kill(pid, 0) } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ESRCH') rmSync(join(tmpdir(), name), { recursive: true, force: true })\n }\n }\n}\n\n/** `ttlMs` is how long an approved credential is kept; 0 forgets it after its first use. */\nexport function createHush(onChange: (change: Changed) => void = () => {}, ttlMs = 15 * 60 * 1000) {\n const waiting = new Map<string, Waiting>()\n // Approved credentials by the path of their file.\n const entries = new Map<string, Entry>()\n let directory: string | undefined\n let files = 0\n const clear = () => { if (directory) rmSync(directory, { recursive: true, force: true }) }\n try { sweep() } catch {}\n\n const remove = (file: string) => {\n const entry = entries.get(file)\n if (!entry) return\n clearTimeout(entry.timer)\n rmSync(file, { force: true })\n entries.delete(file)\n }\n // Short paths (…/oc-hush-<pid>/1), because agents copy them into commands. The directory is created on first use,\n // readable only by this user; if the name is taken, by another instance or anyone else, a random one is used.\n const write = (secret: string) => {\n if (!directory) {\n const preferred = join(tmpdir(), `oc-hush-${process.pid}`)\n try { mkdirSync(preferred, { mode: 0o700 }); directory = preferred } catch {\n directory = mkdtempSync(`${preferred}-`)\n }\n process.once('exit', clear)\n }\n const file = join(directory, String(++files))\n writeFileSync(file, secret, { mode: 0o600, flag: 'wx' })\n return file\n }\n\n return {\n request(input: Omit<Pending, 'id'>, signal: AbortSignal, lineage = [input.sessionID]) {\n signal.throwIfAborted()\n return new Promise<{ file: string }>((resolve, reject) => {\n const id = randomUUID()\n const finish = (secret?: string, why: keyof typeof ended = 'denied') => {\n if (!waiting.delete(id)) return\n clearTimeout(timer)\n signal.removeEventListener('abort', cancel)\n onChange({ sessionIDs: lineage })\n if (!secret) {\n reject(new Error(ended[why]))\n return\n }\n const file = write(secret)\n // A single-use credential still expires if it is never used.\n const expiry = setTimeout(() => remove(file), ttlMs || 5 * 60 * 1000)\n expiry.unref?.()\n entries.set(file, { lineage, secret, timer: expiry })\n resolve({ file })\n }\n const cancel = () => finish(undefined, 'interrupted')\n const timer = setTimeout(() => finish(undefined, 'expired'), 5 * 60 * 1000)\n timer.unref?.()\n const info = { label: input.label, sessionID: input.sessionID, id }\n waiting.set(id, { info, lineage, finish })\n signal.addEventListener('abort', cancel, { once: true })\n onChange({ sessionIDs: lineage, added: info })\n })\n },\n pending(sessionID: string) {\n return [...waiting.values()].filter(item => item.lineage.includes(sessionID)).map(item => item.info)\n },\n reply(id: string, secret?: string) {\n const item = waiting.get(id)\n if (!item) return { accepted: false }\n item.finish(secret)\n return { accepted: true }\n },\n /** Replaces every live credential, and its common encodings, in any string inside `value`. */\n redact<T>(value: T): T {\n const patterns = [...entries.values()].flatMap(entry => forms(entry.secret))\n if (!patterns.length) return value\n const scrub = (item: unknown): unknown => {\n if (typeof item === 'string') return patterns.reduce((text, form) => text.split(form).join(REDACTED), item)\n if (Array.isArray(item)) return item.map(scrub)\n if (item && typeof item === 'object' && Object.getPrototypeOf(item) === Object.prototype) {\n return Object.fromEntries(Object.entries(item).map(([key, field]) => [key, scrub(field)]))\n }\n return item\n }\n return scrub(value) as T\n },\n /** Single-use credentials are forgotten once a tool call has read their file. */\n used(input: string) {\n if (ttlMs) return\n for (const file of [...entries.keys()]) if (input.includes(file)) remove(file)\n },\n forget(sessionID: string) {\n const files = [...entries].filter(([, entry]) => entry.lineage.includes(sessionID)).map(([file]) => file)\n files.forEach(remove)\n ;[...waiting.values()].filter(item => item.lineage.includes(sessionID)).forEach(item => item.finish())\n return { forgotten: files.length }\n },\n dispose() {\n ;[...waiting.values()].forEach(item => item.finish(undefined, 'interrupted'))\n ;[...entries.keys()].forEach(remove)\n clear()\n process.off('exit', clear)\n },\n }\n}\n"],"mappings":"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","names":["files"]}
package/dist/index.js ADDED
@@ -0,0 +1,61 @@
1
+ import { Plugin } from "@opencode/plugin";
2
+ import { z } from "zod";
3
+ import { createHush } from "./hush.js";
4
+ import { Hush, request } from "./rpc.js";
5
+ var index_default = Plugin.define({
6
+ id: "oc-hush",
7
+ async setup(ctx) {
8
+ const minutes = ctx.options.ttlMinutes ?? 15;
9
+ if (typeof minutes !== "number" || !(minutes >= 0 && minutes <= 1440)) throw new Error("oc-hush: ttlMinutes must be a number from 0 to 1440.");
10
+ const lifetime = minutes ? `valid for ${minutes} minute${minutes === 1 ? "" : "s"}` : "valid for one use";
11
+ let registration;
12
+ const hush = createHush((change) => void registration?.events.emit("changed", change).catch(() => {
13
+ }), minutes * 6e4);
14
+ const lineage = async (sessionID) => {
15
+ const ids = [sessionID];
16
+ while (ids.length < 16) {
17
+ const parent = await ctx.session.get({ sessionID: ids[ids.length - 1] }).then((info) => info.parentID, () => void 0);
18
+ if (!parent || ids.includes(parent)) break;
19
+ ids.push(parent);
20
+ }
21
+ return ids;
22
+ };
23
+ registration = await ctx.rpc.register(Hush, {
24
+ pending: async (input) => hush.pending(input.sessionID),
25
+ reply: async (input) => hush.reply(input.id, input.secret),
26
+ forget: async (input) => hush.forget(input.sessionID)
27
+ });
28
+ await ctx.tool.hook("execute.after", (call) => {
29
+ if (call.status === "completed") call.result = hush.redact(call.result);
30
+ if (call.status === "error") {
31
+ const error = call.error;
32
+ const message = hush.redact(error.message);
33
+ if (message !== error.message) call.error = new error.constructor({ message });
34
+ }
35
+ hush.used(JSON.stringify(call.input ?? ""));
36
+ });
37
+ await ctx.tool.transform((editor) => {
38
+ editor.namespace({ name: "hush", description: "Request credentials privately for shell commands. Never ask for credentials in chat." });
39
+ editor.add({
40
+ name: "request_secret",
41
+ options: { namespace: "hush" },
42
+ description: [
43
+ "Ask the user for a credential through a private prompt OpenCode shows them; wait for the result, and do not tell them to run a command. Never ask the user to paste a credential into chat.",
44
+ `Returns { file }: a private file holding the credential. Read it inside the command that needs it, e.g. GH_TOKEN="$(cat '<file>')" gh repo list, or curl -H "Authorization: Bearer $(cat '<file>')" <url>. Never print, copy, or move the file; command output is redacted anyway.`,
45
+ `The credential is ${lifetime}; request it again after that. Available in Code Mode and as a normal tool.`
46
+ ].join(" "),
47
+ input: request,
48
+ output: z.object({ file: z.string() }),
49
+ execute: async (input, context) => {
50
+ const output = await hush.request({ ...input, sessionID: context.sessionID }, context.signal, await lineage(context.sessionID));
51
+ return { output, content: JSON.stringify(output) };
52
+ }
53
+ });
54
+ });
55
+ return () => hush.dispose();
56
+ }
57
+ });
58
+ export {
59
+ index_default as default
60
+ };
61
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { Plugin } from '@opencode/plugin'\nimport { z } from 'zod'\nimport { createHush } from './hush.js'\nimport { Hush, request } from './rpc.js'\n\nexport default Plugin.define({\n id: 'oc-hush',\n async setup(ctx) {\n const minutes = ctx.options.ttlMinutes ?? 15\n if (typeof minutes !== 'number' || !(minutes >= 0 && minutes <= 1440)) throw new Error('oc-hush: ttlMinutes must be a number from 0 to 1440.')\n const lifetime = minutes ? `valid for ${minutes} minute${minutes === 1 ? '' : 's'}` : 'valid for one use'\n let registration: Awaited<ReturnType<typeof ctx.rpc.register<typeof Hush>>> | undefined\n const hush = createHush(change => void registration?.events.emit('changed', change).catch(() => {}), minutes * 60_000)\n // The session and its ancestors, so requests made by subagents surface in the session the user is looking at.\n const lineage = async (sessionID: string) => {\n const ids = [sessionID]\n while (ids.length < 16) {\n const parent = await ctx.session.get({ sessionID: ids[ids.length - 1] }).then(info => info.parentID, () => undefined)\n if (!parent || ids.includes(parent)) break\n ids.push(parent)\n }\n return ids\n }\n registration = await ctx.rpc.register(Hush, {\n pending: async input => hush.pending(input.sessionID),\n reply: async input => hush.reply(input.id, input.secret),\n forget: async input => hush.forget(input.sessionID),\n })\n // Every tool result passes through here before the model sees it, so a command that prints a credential, or an\n // encoding of it, shows the model a placeholder instead.\n await ctx.tool.hook('execute.after', call => {\n if (call.status === 'completed') call.result = hush.redact(call.result)\n if (call.status === 'error') {\n const error = call.error\n const message = hush.redact(error.message)\n // Tool errors are schema classes; rebuild one with the redacted message.\n if (message !== error.message) call.error = new (error.constructor as new (fields: { message: string }) => typeof error)({ message })\n }\n hush.used(JSON.stringify(call.input ?? ''))\n })\n await ctx.tool.transform(editor => {\n editor.namespace({ name: 'hush', description: 'Request credentials privately for shell commands. Never ask for credentials in chat.' })\n editor.add({\n name: 'request_secret',\n options: { namespace: 'hush' },\n description: [\n 'Ask the user for a credential through a private prompt OpenCode shows them; wait for the result, and do not tell them to run a command. Never ask the user to paste a credential into chat.',\n `Returns { file }: a private file holding the credential. Read it inside the command that needs it, e.g. GH_TOKEN=\"$(cat '<file>')\" gh repo list, or curl -H \"Authorization: Bearer $(cat '<file>')\" <url>. Never print, copy, or move the file; command output is redacted anyway.`,\n `The credential is ${lifetime}; request it again after that. Available in Code Mode and as a normal tool.`,\n ].join(' '),\n input: request,\n output: z.object({ file: z.string() }),\n execute: async (input, context) => {\n const output = await hush.request({ ...input, sessionID: context.sessionID }, context.signal, await lineage(context.sessionID))\n return { output, content: JSON.stringify(output) }\n },\n })\n })\n return () => hush.dispose()\n },\n})\n"],"mappings":"AAAA,SAAS,cAAc;AACvB,SAAS,SAAS;AAClB,SAAS,kBAAkB;AAC3B,SAAS,MAAM,eAAe;AAE9B,IAAO,gBAAQ,OAAO,OAAO;AAAA,EAC3B,IAAI;AAAA,EACJ,MAAM,MAAM,KAAK;AACf,UAAM,UAAU,IAAI,QAAQ,cAAc;AAC1C,QAAI,OAAO,YAAY,YAAY,EAAE,WAAW,KAAK,WAAW,MAAO,OAAM,IAAI,MAAM,sDAAsD;AAC7I,UAAM,WAAW,UAAU,aAAa,OAAO,UAAU,YAAY,IAAI,KAAK,GAAG,KAAK;AACtF,QAAI;AACJ,UAAM,OAAO,WAAW,YAAU,KAAK,cAAc,OAAO,KAAK,WAAW,MAAM,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC,GAAG,UAAU,GAAM;AAErH,UAAM,UAAU,OAAO,cAAsB;AAC3C,YAAM,MAAM,CAAC,SAAS;AACtB,aAAO,IAAI,SAAS,IAAI;AACtB,cAAM,SAAS,MAAM,IAAI,QAAQ,IAAI,EAAE,WAAW,IAAI,IAAI,SAAS,CAAC,EAAE,CAAC,EAAE,KAAK,UAAQ,KAAK,UAAU,MAAM,MAAS;AACpH,YAAI,CAAC,UAAU,IAAI,SAAS,MAAM,EAAG;AACrC,YAAI,KAAK,MAAM;AAAA,MACjB;AACA,aAAO;AAAA,IACT;AACA,mBAAe,MAAM,IAAI,IAAI,SAAS,MAAM;AAAA,MAC1C,SAAS,OAAM,UAAS,KAAK,QAAQ,MAAM,SAAS;AAAA,MACpD,OAAO,OAAM,UAAS,KAAK,MAAM,MAAM,IAAI,MAAM,MAAM;AAAA,MACvD,QAAQ,OAAM,UAAS,KAAK,OAAO,MAAM,SAAS;AAAA,IACpD,CAAC;AAGD,UAAM,IAAI,KAAK,KAAK,iBAAiB,UAAQ;AAC3C,UAAI,KAAK,WAAW,YAAa,MAAK,SAAS,KAAK,OAAO,KAAK,MAAM;AACtE,UAAI,KAAK,WAAW,SAAS;AAC3B,cAAM,QAAQ,KAAK;AACnB,cAAM,UAAU,KAAK,OAAO,MAAM,OAAO;AAEzC,YAAI,YAAY,MAAM,QAAS,MAAK,QAAQ,IAAK,MAAM,YAAkE,EAAE,QAAQ,CAAC;AAAA,MACtI;AACA,WAAK,KAAK,KAAK,UAAU,KAAK,SAAS,EAAE,CAAC;AAAA,IAC5C,CAAC;AACD,UAAM,IAAI,KAAK,UAAU,YAAU;AACjC,aAAO,UAAU,EAAE,MAAM,QAAQ,aAAa,uFAAuF,CAAC;AACtI,aAAO,IAAI;AAAA,QACT,MAAM;AAAA,QACN,SAAS,EAAE,WAAW,OAAO;AAAA,QAC7B,aAAa;AAAA,UACX;AAAA,UACA;AAAA,UACA,qBAAqB,QAAQ;AAAA,QAC/B,EAAE,KAAK,GAAG;AAAA,QACV,OAAO;AAAA,QACP,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;AAAA,QACrC,SAAS,OAAO,OAAO,YAAY;AACjC,gBAAM,SAAS,MAAM,KAAK,QAAQ,EAAE,GAAG,OAAO,WAAW,QAAQ,UAAU,GAAG,QAAQ,QAAQ,MAAM,QAAQ,QAAQ,SAAS,CAAC;AAC9H,iBAAO,EAAE,QAAQ,SAAS,KAAK,UAAU,MAAM,EAAE;AAAA,QACnD;AAAA,MACF,CAAC;AAAA,IACH,CAAC;AACD,WAAO,MAAM,KAAK,QAAQ;AAAA,EAC5B;AACF,CAAC;","names":[]}
@@ -0,0 +1,21 @@
1
+ {
2
+ "name": "oc-hush",
3
+ "version": "0.1.1",
4
+ "type": "module",
5
+ "main": "./index.js",
6
+ "exports": {
7
+ ".": "./index.js",
8
+ "./tui": "./tui.js",
9
+ "./rpc": "./rpc.js",
10
+ "./gui-experimental": "./gui-experimental.cjs"
11
+ },
12
+ "dependencies": {
13
+ "@opencode/plugin": "2.2.6",
14
+ "zod": "4.1.8"
15
+ },
16
+ "peerDependencies": {
17
+ "@opentui/core": ">=0.8.1",
18
+ "@opentui/solid": ">=0.8.1",
19
+ "solid-js": ">=1.9.0"
20
+ }
21
+ }
package/dist/rpc.js ADDED
@@ -0,0 +1,35 @@
1
+ import { Rpc } from "@opencode/plugin/rpc";
2
+ import { z } from "zod";
3
+ const request = z.object({
4
+ label: z.string().min(1).max(80).describe('A short name for the credential, such as "GitHub token" or "Stripe API key". The user sees it when asked.')
5
+ }).strict();
6
+ const pending = request.extend({ id: z.string(), sessionID: z.string() });
7
+ const session = z.object({ sessionID: z.string().min(1) }).strict();
8
+ const changed = z.object({
9
+ /** The requesting session and its ancestors, so a parent session sees its subagents' requests. */
10
+ sessionIDs: z.array(z.string()),
11
+ /** Set when this change added a request. */
12
+ added: pending.optional()
13
+ });
14
+ const Hush = Rpc.define({
15
+ id: "oc-hush",
16
+ events: { changed: { schema: changed } },
17
+ methods: {
18
+ pending: { input: session, output: z.array(pending) },
19
+ reply: {
20
+ input: z.object({
21
+ id: z.string(),
22
+ secret: z.string().min(1).max(8192).regex(/^[\x21-\x7e]+$/).optional()
23
+ }).strict(),
24
+ output: z.object({ accepted: z.boolean() })
25
+ },
26
+ forget: { input: session, output: z.object({ forgotten: z.number() }) }
27
+ }
28
+ });
29
+ export {
30
+ Hush,
31
+ changed,
32
+ pending,
33
+ request
34
+ };
35
+ //# sourceMappingURL=rpc.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/rpc.ts"],"sourcesContent":["import { Rpc } from '@opencode/plugin/rpc'\nimport { z } from 'zod'\n\nexport const request = z.object({\n label: z.string().min(1).max(80).describe('A short name for the credential, such as \"GitHub token\" or \"Stripe API key\". The user sees it when asked.'),\n}).strict()\n\nexport const pending = request.extend({ id: z.string(), sessionID: z.string() })\nexport type Pending = z.infer<typeof pending>\n\nconst session = z.object({ sessionID: z.string().min(1) }).strict()\n\n// Metadata only: never add the credential or a reference to an event, since every client of the server receives it.\nexport const changed = z.object({\n /** The requesting session and its ancestors, so a parent session sees its subagents' requests. */\n sessionIDs: z.array(z.string()),\n /** Set when this change added a request. */\n added: pending.optional(),\n})\nexport type Changed = z.infer<typeof changed>\n\nexport const Hush = Rpc.define({\n id: 'oc-hush',\n events: { changed: { schema: changed } },\n methods: {\n pending: { input: session, output: z.array(pending) },\n reply: {\n input: z.object({\n id: z.string(),\n secret: z.string().min(1).max(8192).regex(/^[\\x21-\\x7e]+$/).optional(),\n }).strict(),\n output: z.object({ accepted: z.boolean() }),\n },\n forget: { input: session, output: z.object({ forgotten: z.number() }) },\n },\n})\n"],"mappings":"AAAA,SAAS,WAAW;AACpB,SAAS,SAAS;AAEX,MAAM,UAAU,EAAE,OAAO;AAAA,EAC9B,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,SAAS,2GAA2G;AACvJ,CAAC,EAAE,OAAO;AAEH,MAAM,UAAU,QAAQ,OAAO,EAAE,IAAI,EAAE,OAAO,GAAG,WAAW,EAAE,OAAO,EAAE,CAAC;AAG/E,MAAM,UAAU,EAAE,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,OAAO;AAG3D,MAAM,UAAU,EAAE,OAAO;AAAA;AAAA,EAE9B,YAAY,EAAE,MAAM,EAAE,OAAO,CAAC;AAAA;AAAA,EAE9B,OAAO,QAAQ,SAAS;AAC1B,CAAC;AAGM,MAAM,OAAO,IAAI,OAAO;AAAA,EAC7B,IAAI;AAAA,EACJ,QAAQ,EAAE,SAAS,EAAE,QAAQ,QAAQ,EAAE;AAAA,EACvC,SAAS;AAAA,IACP,SAAS,EAAE,OAAO,SAAS,QAAQ,EAAE,MAAM,OAAO,EAAE;AAAA,IACpD,OAAO;AAAA,MACL,OAAO,EAAE,OAAO;AAAA,QACd,IAAI,EAAE,OAAO;AAAA,QACb,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,IAAI,EAAE,MAAM,gBAAgB,EAAE,SAAS;AAAA,MACvE,CAAC,EAAE,OAAO;AAAA,MACV,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAC;AAAA,IAC5C;AAAA,IACA,QAAQ,EAAE,OAAO,SAAS,QAAQ,EAAE,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC,EAAE;AAAA,EACxE;AACF,CAAC;","names":[]}
package/dist/tui.js ADDED
@@ -0,0 +1,331 @@
1
+ import { use as _$use } from "@opentui/solid";
2
+ import { effect as _$effect } from "@opentui/solid";
3
+ import { memo as _$memo } from "@opentui/solid";
4
+ import { insert as _$insert } from "@opentui/solid";
5
+ import { createComponent as _$createComponent } from "@opentui/solid";
6
+ import { createTextNode as _$createTextNode } from "@opentui/solid";
7
+ import { insertNode as _$insertNode } from "@opentui/solid";
8
+ import { setProp as _$setProp } from "@opentui/solid";
9
+ import { createElement as _$createElement } from "@opentui/solid";
10
+ import { Plugin } from "@opencode/plugin/tui";
11
+ import { createEffect, createSignal, on, Show } from "solid-js";
12
+ import { Hush } from "./rpc.js";
13
+ const bar = {
14
+ topLeft: "\u2503",
15
+ topRight: " ",
16
+ bottomLeft: "\u2503",
17
+ bottomRight: " ",
18
+ horizontal: " ",
19
+ vertical: "\u2503",
20
+ topT: " ",
21
+ bottomT: " ",
22
+ leftT: " ",
23
+ rightT: " ",
24
+ cross: " "
25
+ };
26
+ var tui_default = Plugin.define({
27
+ id: "oc-hush.tui",
28
+ setup(ctx) {
29
+ const controller = new AbortController();
30
+ const options = () => ({
31
+ location: ctx.location ?? ctx.data.location.default(),
32
+ signal: controller.signal
33
+ });
34
+ const session = () => {
35
+ const route = ctx.ui.router.current();
36
+ return route.type === "session" ? route.sessionID : void 0;
37
+ };
38
+ const report = () => ctx.ui.toast.show({
39
+ title: "oc-hush",
40
+ message: "Could not reach Hush. Check that its server plugin is loaded.",
41
+ variant: "error"
42
+ });
43
+ let open;
44
+ const reply = async (id, secret) => {
45
+ try {
46
+ const result = await ctx.client.rpc(Hush).reply({
47
+ id,
48
+ secret
49
+ }, options());
50
+ if (!result.accepted) ctx.ui.toast.show({
51
+ title: "oc-hush",
52
+ message: "This credential request has expired.",
53
+ variant: "warning"
54
+ });
55
+ } catch {
56
+ if (!controller.signal.aborted) report();
57
+ }
58
+ };
59
+ const ask = (item) => {
60
+ let answered = false;
61
+ const answer = (secret, send = true) => {
62
+ if (answered) return;
63
+ answered = true;
64
+ open = void 0;
65
+ if (send) void reply(item.id, secret).then(refresh);
66
+ };
67
+ const Dialog = () => {
68
+ const [value, setValue] = createSignal("");
69
+ const length = () => value().length;
70
+ const [shown, setShown] = createSignal(false);
71
+ const [error, setError] = createSignal("");
72
+ let field;
73
+ const invalid = (value2) => !/^[\x21-\x7e]*$/.test(value2) || value2.length > 8192;
74
+ const input = (text) => {
75
+ setValue(text);
76
+ setError(invalid(text.trim()) ? "Credentials cannot contain spaces or line breaks." : "");
77
+ };
78
+ const submit = () => {
79
+ const secret = (field?.value ?? "").trim();
80
+ if (!secret || invalid(secret)) return;
81
+ answer(secret);
82
+ ctx.ui.dialog.clear();
83
+ };
84
+ const Space = () => (() => {
85
+ var _el$ = _$createElement("box");
86
+ _$setProp(_el$, "height", 1);
87
+ _$setProp(_el$, "flexShrink", 0);
88
+ return _el$;
89
+ })();
90
+ return (() => {
91
+ var _el$2 = _$createElement("box"), _el$3 = _$createElement("box"), _el$4 = _$createElement("text"), _el$5 = _$createElement("b"), _el$7 = _$createElement("text"), _el$9 = _$createElement("text"), _el$0 = _$createElement("box"), _el$10 = _$createElement("input"), _el$12 = _$createElement("box"), _el$13 = _$createElement("text"), _el$14 = _$createElement("span"), _el$16 = _$createTextNode(` approve`), _el$17 = _$createElement("text"), _el$18 = _$createElement("span"), _el$20 = _$createTextNode(` deny`), _el$21 = _$createElement("text"), _el$22 = _$createElement("span"), _el$24 = _$createTextNode(` `);
92
+ _$insertNode(_el$2, _el$3);
93
+ _$insertNode(_el$2, _el$9);
94
+ _$insertNode(_el$2, _el$0);
95
+ _$insertNode(_el$2, _el$12);
96
+ _$setProp(_el$2, "paddingLeft", 2);
97
+ _$setProp(_el$2, "paddingRight", 2);
98
+ _$setProp(_el$2, "paddingBottom", 1);
99
+ _$insertNode(_el$3, _el$4);
100
+ _$insertNode(_el$3, _el$7);
101
+ _$setProp(_el$3, "flexDirection", "row");
102
+ _$setProp(_el$3, "justifyContent", "space-between");
103
+ _$setProp(_el$3, "flexShrink", 0);
104
+ _$insertNode(_el$4, _el$5);
105
+ _$insertNode(_el$5, _$createTextNode(`Temporary Credential`));
106
+ _$insertNode(_el$7, _$createTextNode(`esc`));
107
+ _$insert(_el$2, _$createComponent(Space, {}), _el$9);
108
+ _$setProp(_el$9, "flexShrink", 0);
109
+ _$insert(_el$9, () => item.label);
110
+ _$insert(_el$2, _$createComponent(Space, {}), _el$0);
111
+ _$insertNode(_el$0, _el$10);
112
+ _$setProp(_el$0, "flexDirection", "row");
113
+ _$setProp(_el$0, "flexShrink", 0);
114
+ _$setProp(_el$0, "border", ["left"]);
115
+ _$setProp(_el$0, "customBorderChars", bar);
116
+ _$setProp(_el$0, "paddingLeft", 1);
117
+ _$setProp(_el$0, "paddingRight", 1);
118
+ _$setProp(_el$0, "paddingTop", 1);
119
+ _$setProp(_el$0, "paddingBottom", 1);
120
+ _$setProp(_el$0, "overflow", "hidden");
121
+ _$insert(_el$0, _$createComponent(Show, {
122
+ get when() {
123
+ return length();
124
+ },
125
+ get children() {
126
+ var _el$1 = _$createElement("text");
127
+ _$setProp(_el$1, "flexShrink", 1);
128
+ _$setProp(_el$1, "minWidth", 0);
129
+ _$setProp(_el$1, "wrapMode", "none");
130
+ _$insert(_el$1, (() => {
131
+ var _c$ = _$memo(() => !!shown());
132
+ return () => _c$() ? value() : "\u2022".repeat(Math.min(length(), 200));
133
+ })());
134
+ _$effect((_$p) => _$setProp(_el$1, "fg", ctx.theme.text.base, _$p));
135
+ return _el$1;
136
+ }
137
+ }), _el$10);
138
+ _$use((element) => {
139
+ field = element;
140
+ }, _el$10);
141
+ _$setProp(_el$10, "focused", true);
142
+ _$setProp(_el$10, "flexShrink", 0);
143
+ _$setProp(_el$10, "placeholder", "Paste or type credential");
144
+ _$setProp(_el$10, "textColor", "transparent");
145
+ _$setProp(_el$10, "focusedTextColor", "transparent");
146
+ _$setProp(_el$10, "backgroundColor", "transparent");
147
+ _$setProp(_el$10, "focusedBackgroundColor", "transparent");
148
+ _$setProp(_el$10, "onInput", input);
149
+ _$setProp(_el$10, "onSubmit", submit);
150
+ _$setProp(_el$10, "onKeyDown", (key) => {
151
+ if (key.name !== "tab") return;
152
+ key.preventDefault();
153
+ setShown(!shown());
154
+ });
155
+ _$insert(_el$2, _$createComponent(Show, {
156
+ get when() {
157
+ return error();
158
+ },
159
+ get children() {
160
+ var _el$11 = _$createElement("text");
161
+ _$setProp(_el$11, "flexShrink", 0);
162
+ _$insert(_el$11, error);
163
+ _$effect((_$p) => _$setProp(_el$11, "fg", ctx.theme.text.feedback.error.base, _$p));
164
+ return _el$11;
165
+ }
166
+ }), _el$12);
167
+ _$insert(_el$2, _$createComponent(Space, {}), _el$12);
168
+ _$insertNode(_el$12, _el$13);
169
+ _$insertNode(_el$12, _el$17);
170
+ _$insertNode(_el$12, _el$21);
171
+ _$setProp(_el$12, "flexDirection", "row");
172
+ _$setProp(_el$12, "gap", 3);
173
+ _$setProp(_el$12, "flexShrink", 0);
174
+ _$insertNode(_el$13, _el$14);
175
+ _$insertNode(_el$13, _el$16);
176
+ _$insertNode(_el$14, _$createTextNode(`enter`));
177
+ _$insertNode(_el$17, _el$18);
178
+ _$insertNode(_el$17, _el$20);
179
+ _$insertNode(_el$18, _$createTextNode(`esc`));
180
+ _$insertNode(_el$21, _el$22);
181
+ _$insertNode(_el$21, _el$24);
182
+ _$insertNode(_el$22, _$createTextNode(`tab`));
183
+ _$insert(_el$21, () => shown() ? "hide" : "show", null);
184
+ _$effect((_p$) => {
185
+ var _v$ = ctx.theme.text.base, _v$2 = ctx.theme.text.muted, _v$3 = ctx.theme.text.muted, _v$4 = error() ? ctx.theme.text.feedback.error.base : ctx.theme.background.action.primary.focused, _v$5 = ctx.theme.background.raised.high, _v$6 = length() ? 0 : 1, _v$7 = length() ? 1 : void 0, _v$8 = ctx.theme.text.muted, _v$9 = ctx.theme.text.muted, _v$0 = {
186
+ fg: ctx.theme.text.base
187
+ }, _v$1 = ctx.theme.text.muted, _v$10 = {
188
+ fg: ctx.theme.text.base
189
+ }, _v$11 = ctx.theme.text.muted, _v$12 = {
190
+ fg: ctx.theme.text.base
191
+ };
192
+ _v$ !== _p$.e && (_p$.e = _$setProp(_el$4, "fg", _v$, _p$.e));
193
+ _v$2 !== _p$.t && (_p$.t = _$setProp(_el$7, "fg", _v$2, _p$.t));
194
+ _v$3 !== _p$.a && (_p$.a = _$setProp(_el$9, "fg", _v$3, _p$.a));
195
+ _v$4 !== _p$.o && (_p$.o = _$setProp(_el$0, "borderColor", _v$4, _p$.o));
196
+ _v$5 !== _p$.i && (_p$.i = _$setProp(_el$0, "backgroundColor", _v$5, _p$.i));
197
+ _v$6 !== _p$.n && (_p$.n = _$setProp(_el$10, "flexGrow", _v$6, _p$.n));
198
+ _v$7 !== _p$.s && (_p$.s = _$setProp(_el$10, "width", _v$7, _p$.s));
199
+ _v$8 !== _p$.h && (_p$.h = _$setProp(_el$10, "placeholderColor", _v$8, _p$.h));
200
+ _v$9 !== _p$.r && (_p$.r = _$setProp(_el$13, "fg", _v$9, _p$.r));
201
+ _v$0 !== _p$.d && (_p$.d = _$setProp(_el$14, "style", _v$0, _p$.d));
202
+ _v$1 !== _p$.l && (_p$.l = _$setProp(_el$17, "fg", _v$1, _p$.l));
203
+ _v$10 !== _p$.u && (_p$.u = _$setProp(_el$18, "style", _v$10, _p$.u));
204
+ _v$11 !== _p$.c && (_p$.c = _$setProp(_el$21, "fg", _v$11, _p$.c));
205
+ _v$12 !== _p$.w && (_p$.w = _$setProp(_el$22, "style", _v$12, _p$.w));
206
+ return _p$;
207
+ }, {
208
+ e: void 0,
209
+ t: void 0,
210
+ a: void 0,
211
+ o: void 0,
212
+ i: void 0,
213
+ n: void 0,
214
+ s: void 0,
215
+ h: void 0,
216
+ r: void 0,
217
+ d: void 0,
218
+ l: void 0,
219
+ u: void 0,
220
+ c: void 0,
221
+ w: void 0
222
+ });
223
+ return _el$2;
224
+ })();
225
+ };
226
+ open = {
227
+ id: item.id,
228
+ close: () => {
229
+ answer(void 0, false);
230
+ ctx.ui.dialog.clear();
231
+ }
232
+ };
233
+ ctx.ui.dialog.show(Dialog, () => answer());
234
+ };
235
+ const refresh = async () => {
236
+ const sessionID = session();
237
+ if (!sessionID) return;
238
+ try {
239
+ const items = await ctx.client.rpc(Hush).pending({
240
+ sessionID
241
+ }, options());
242
+ if (session() !== sessionID || controller.signal.aborted) return;
243
+ if (open && !items.some((item) => item.id === open?.id)) open.close();
244
+ if (!open && items.length) ask(items[0]);
245
+ } catch {
246
+ if (!controller.signal.aborted) report();
247
+ }
248
+ };
249
+ ctx.keymap.layer(() => ({
250
+ mode: "global",
251
+ commands: [{
252
+ id: "oc-hush.forget",
253
+ title: "Forget Hush credentials for this session",
254
+ group: "oc-hush",
255
+ palette: true,
256
+ slash: {
257
+ name: "hush-forget"
258
+ },
259
+ run: async () => {
260
+ const sessionID = session();
261
+ if (!sessionID) return;
262
+ try {
263
+ await ctx.client.rpc(Hush).forget({
264
+ sessionID
265
+ }, options());
266
+ ctx.ui.toast.show({
267
+ title: "oc-hush",
268
+ message: "Session credentials forgotten.",
269
+ variant: "success"
270
+ });
271
+ } catch {
272
+ report();
273
+ }
274
+ }
275
+ }]
276
+ }));
277
+ let stopEvents = () => {
278
+ };
279
+ const subscribe = () => {
280
+ stopEvents();
281
+ stopEvents = ctx.client.rpc(Hush).events.on("changed", (event) => {
282
+ if (event.location.directory !== options().location.directory) return;
283
+ const current = session();
284
+ const here = !!current && event.data.sessionIDs.includes(current);
285
+ if (here) void refresh();
286
+ const added = event.data.added;
287
+ if (!added) return;
288
+ const message = added.label;
289
+ if (!here) {
290
+ const root = event.data.sessionIDs[event.data.sessionIDs.length - 1];
291
+ ctx.ui.toast.show({
292
+ title: "Hush needs a credential",
293
+ message,
294
+ variant: "warning",
295
+ duration: 1e4,
296
+ sessionID: root
297
+ });
298
+ }
299
+ void ctx.attention.notify({
300
+ title: "Hush needs a credential",
301
+ message,
302
+ notification: {
303
+ when: "blurred"
304
+ },
305
+ sound: {
306
+ name: "question",
307
+ when: "blurred"
308
+ }
309
+ });
310
+ }, {
311
+ signal: controller.signal
312
+ });
313
+ void refresh();
314
+ };
315
+ const stopReconnect = ctx.data.on("server.connected", subscribe);
316
+ subscribe();
317
+ createEffect(on(session, () => void refresh(), {
318
+ defer: true
319
+ }));
320
+ return () => {
321
+ controller.abort();
322
+ stopEvents();
323
+ stopReconnect();
324
+ open?.close();
325
+ };
326
+ }
327
+ });
328
+ export {
329
+ tui_default as default
330
+ };
331
+ //# sourceMappingURL=tui.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/tui.tsx"],"sourcesContent":["import { use as _$use } from \"@opentui/solid\";\nimport { effect as _$effect } from \"@opentui/solid\";\nimport { memo as _$memo } from \"@opentui/solid\";\nimport { insert as _$insert } from \"@opentui/solid\";\nimport { createComponent as _$createComponent } from \"@opentui/solid\";\nimport { createTextNode as _$createTextNode } from \"@opentui/solid\";\nimport { insertNode as _$insertNode } from \"@opentui/solid\";\nimport { setProp as _$setProp } from \"@opentui/solid\";\nimport { createElement as _$createElement } from \"@opentui/solid\";\nimport { Plugin } from '@opencode/plugin/tui';\nimport { createEffect, createSignal, on, Show } from 'solid-js';\nimport { Hush } from './rpc.js';\n\n// OpenCode's prompt bar: only the left side is drawn, as a heavy vertical line.\nconst bar = {\n topLeft: '┃',\n topRight: ' ',\n bottomLeft: '┃',\n bottomRight: ' ',\n horizontal: ' ',\n vertical: '┃',\n topT: ' ',\n bottomT: ' ',\n leftT: ' ',\n rightT: ' ',\n cross: ' '\n};\nexport default Plugin.define({\n id: 'oc-hush.tui',\n setup(ctx) {\n const controller = new AbortController();\n const options = () => ({\n location: ctx.location ?? ctx.data.location.default(),\n signal: controller.signal\n });\n const session = () => {\n const route = ctx.ui.router.current();\n return route.type === 'session' ? route.sessionID : undefined;\n };\n const report = () => ctx.ui.toast.show({\n title: 'oc-hush',\n message: 'Could not reach Hush. Check that its server plugin is loaded.',\n variant: 'error'\n });\n // The request whose dialog is open, and a way to close it when the plugin goes away.\n let open;\n const reply = async (id, secret) => {\n try {\n const result = await ctx.client.rpc(Hush).reply({\n id,\n secret\n }, options());\n if (!result.accepted) ctx.ui.toast.show({\n title: 'oc-hush',\n message: 'This credential request has expired.',\n variant: 'warning'\n });\n } catch {\n if (!controller.signal.aborted) report();\n }\n };\n\n // Asks as soon as the agent does. Typing goes to a focused input whose text is invisible; the dialog draws a mask\n // from its length. Nothing reaches the prompt or its history. Enter approves; closing the dialog denies.\n const ask = item => {\n let answered = false;\n // `send: false` only closes the dialog: the request keeps waiting and is asked again.\n const answer = (secret, send = true) => {\n if (answered) return;\n answered = true;\n open = undefined;\n if (send) void reply(item.id, secret).then(refresh);\n };\n const Dialog = () => {\n const [value, setValue] = createSignal('');\n const length = () => value().length;\n // Tab shows what was typed until it is pressed again. Each dialog starts hidden.\n const [shown, setShown] = createSignal(false);\n const [error, setError] = createSignal('');\n let field;\n // Credentials are header values: printable ASCII without spaces.\n const invalid = value => !/^[\\x21-\\x7e]*$/.test(value) || value.length > 8192;\n const input = text => {\n setValue(text);\n setError(invalid(text.trim()) ? 'Credentials cannot contain spaces or line breaks.' : '');\n };\n const submit = () => {\n const secret = (field?.value ?? '').trim();\n if (!secret || invalid(secret)) return;\n answer(secret);\n ctx.ui.dialog.clear();\n };\n // Laid out like OpenCode's own dialogs: bold title with `esc` opposite, muted detail, field, key hints.\n const Space = () => (() => {\n var _el$ = _$createElement(\"box\");\n _$setProp(_el$, \"height\", 1);\n _$setProp(_el$, \"flexShrink\", 0);\n return _el$;\n })();\n return (() => {\n var _el$2 = _$createElement(\"box\"),\n _el$3 = _$createElement(\"box\"),\n _el$4 = _$createElement(\"text\"),\n _el$5 = _$createElement(\"b\"),\n _el$7 = _$createElement(\"text\"),\n _el$9 = _$createElement(\"text\"),\n _el$0 = _$createElement(\"box\"),\n _el$10 = _$createElement(\"input\"),\n _el$12 = _$createElement(\"box\"),\n _el$13 = _$createElement(\"text\"),\n _el$14 = _$createElement(\"span\"),\n _el$16 = _$createTextNode(` approve`),\n _el$17 = _$createElement(\"text\"),\n _el$18 = _$createElement(\"span\"),\n _el$20 = _$createTextNode(` deny`),\n _el$21 = _$createElement(\"text\"),\n _el$22 = _$createElement(\"span\"),\n _el$24 = _$createTextNode(` `);\n _$insertNode(_el$2, _el$3);\n _$insertNode(_el$2, _el$9);\n _$insertNode(_el$2, _el$0);\n _$insertNode(_el$2, _el$12);\n _$setProp(_el$2, \"paddingLeft\", 2);\n _$setProp(_el$2, \"paddingRight\", 2);\n _$setProp(_el$2, \"paddingBottom\", 1);\n _$insertNode(_el$3, _el$4);\n _$insertNode(_el$3, _el$7);\n _$setProp(_el$3, \"flexDirection\", \"row\");\n _$setProp(_el$3, \"justifyContent\", \"space-between\");\n _$setProp(_el$3, \"flexShrink\", 0);\n _$insertNode(_el$4, _el$5);\n _$insertNode(_el$5, _$createTextNode(`Temporary Credential`));\n _$insertNode(_el$7, _$createTextNode(`esc`));\n _$insert(_el$2, _$createComponent(Space, {}), _el$9);\n _$setProp(_el$9, \"flexShrink\", 0);\n _$insert(_el$9, () => item.label);\n _$insert(_el$2, _$createComponent(Space, {}), _el$0);\n _$insertNode(_el$0, _el$10);\n _$setProp(_el$0, \"flexDirection\", \"row\");\n _$setProp(_el$0, \"flexShrink\", 0);\n _$setProp(_el$0, \"border\", ['left']);\n _$setProp(_el$0, \"customBorderChars\", bar);\n _$setProp(_el$0, \"paddingLeft\", 1);\n _$setProp(_el$0, \"paddingRight\", 1);\n _$setProp(_el$0, \"paddingTop\", 1);\n _$setProp(_el$0, \"paddingBottom\", 1);\n _$setProp(_el$0, \"overflow\", \"hidden\");\n _$insert(_el$0, _$createComponent(Show, {\n get when() {\n return length();\n },\n get children() {\n var _el$1 = _$createElement(\"text\");\n _$setProp(_el$1, \"flexShrink\", 1);\n _$setProp(_el$1, \"minWidth\", 0);\n _$setProp(_el$1, \"wrapMode\", \"none\");\n _$insert(_el$1, (() => {\n var _c$ = _$memo(() => !!shown());\n return () => _c$() ? value() : '•'.repeat(Math.min(length(), 200));\n })());\n _$effect(_$p => _$setProp(_el$1, \"fg\", ctx.theme.text.base, _$p));\n return _el$1;\n }\n }), _el$10);\n _$use(element => {\n field = element;\n }, _el$10);\n _$setProp(_el$10, \"focused\", true);\n _$setProp(_el$10, \"flexShrink\", 0);\n _$setProp(_el$10, \"placeholder\", \"Paste or type credential\");\n _$setProp(_el$10, \"textColor\", \"transparent\");\n _$setProp(_el$10, \"focusedTextColor\", \"transparent\");\n _$setProp(_el$10, \"backgroundColor\", \"transparent\");\n _$setProp(_el$10, \"focusedBackgroundColor\", \"transparent\");\n _$setProp(_el$10, \"onInput\", input);\n _$setProp(_el$10, \"onSubmit\", submit);\n _$setProp(_el$10, \"onKeyDown\", key => {\n if (key.name !== 'tab') return;\n key.preventDefault();\n setShown(!shown());\n });\n _$insert(_el$2, _$createComponent(Show, {\n get when() {\n return error();\n },\n get children() {\n var _el$11 = _$createElement(\"text\");\n _$setProp(_el$11, \"flexShrink\", 0);\n _$insert(_el$11, error);\n _$effect(_$p => _$setProp(_el$11, \"fg\", ctx.theme.text.feedback.error.base, _$p));\n return _el$11;\n }\n }), _el$12);\n _$insert(_el$2, _$createComponent(Space, {}), _el$12);\n _$insertNode(_el$12, _el$13);\n _$insertNode(_el$12, _el$17);\n _$insertNode(_el$12, _el$21);\n _$setProp(_el$12, \"flexDirection\", \"row\");\n _$setProp(_el$12, \"gap\", 3);\n _$setProp(_el$12, \"flexShrink\", 0);\n _$insertNode(_el$13, _el$14);\n _$insertNode(_el$13, _el$16);\n _$insertNode(_el$14, _$createTextNode(`enter`));\n _$insertNode(_el$17, _el$18);\n _$insertNode(_el$17, _el$20);\n _$insertNode(_el$18, _$createTextNode(`esc`));\n _$insertNode(_el$21, _el$22);\n _$insertNode(_el$21, _el$24);\n _$insertNode(_el$22, _$createTextNode(`tab`));\n _$insert(_el$21, () => shown() ? 'hide' : 'show', null);\n _$effect(_p$ => {\n var _v$ = ctx.theme.text.base,\n _v$2 = ctx.theme.text.muted,\n _v$3 = ctx.theme.text.muted,\n _v$4 = error() ? ctx.theme.text.feedback.error.base : ctx.theme.background.action.primary.focused,\n _v$5 = ctx.theme.background.raised.high,\n _v$6 = length() ? 0 : 1,\n _v$7 = length() ? 1 : undefined,\n _v$8 = ctx.theme.text.muted,\n _v$9 = ctx.theme.text.muted,\n _v$0 = {\n fg: ctx.theme.text.base\n },\n _v$1 = ctx.theme.text.muted,\n _v$10 = {\n fg: ctx.theme.text.base\n },\n _v$11 = ctx.theme.text.muted,\n _v$12 = {\n fg: ctx.theme.text.base\n };\n _v$ !== _p$.e && (_p$.e = _$setProp(_el$4, \"fg\", _v$, _p$.e));\n _v$2 !== _p$.t && (_p$.t = _$setProp(_el$7, \"fg\", _v$2, _p$.t));\n _v$3 !== _p$.a && (_p$.a = _$setProp(_el$9, \"fg\", _v$3, _p$.a));\n _v$4 !== _p$.o && (_p$.o = _$setProp(_el$0, \"borderColor\", _v$4, _p$.o));\n _v$5 !== _p$.i && (_p$.i = _$setProp(_el$0, \"backgroundColor\", _v$5, _p$.i));\n _v$6 !== _p$.n && (_p$.n = _$setProp(_el$10, \"flexGrow\", _v$6, _p$.n));\n _v$7 !== _p$.s && (_p$.s = _$setProp(_el$10, \"width\", _v$7, _p$.s));\n _v$8 !== _p$.h && (_p$.h = _$setProp(_el$10, \"placeholderColor\", _v$8, _p$.h));\n _v$9 !== _p$.r && (_p$.r = _$setProp(_el$13, \"fg\", _v$9, _p$.r));\n _v$0 !== _p$.d && (_p$.d = _$setProp(_el$14, \"style\", _v$0, _p$.d));\n _v$1 !== _p$.l && (_p$.l = _$setProp(_el$17, \"fg\", _v$1, _p$.l));\n _v$10 !== _p$.u && (_p$.u = _$setProp(_el$18, \"style\", _v$10, _p$.u));\n _v$11 !== _p$.c && (_p$.c = _$setProp(_el$21, \"fg\", _v$11, _p$.c));\n _v$12 !== _p$.w && (_p$.w = _$setProp(_el$22, \"style\", _v$12, _p$.w));\n return _p$;\n }, {\n e: undefined,\n t: undefined,\n a: undefined,\n o: undefined,\n i: undefined,\n n: undefined,\n s: undefined,\n h: undefined,\n r: undefined,\n d: undefined,\n l: undefined,\n u: undefined,\n c: undefined,\n w: undefined\n });\n return _el$2;\n })();\n };\n open = {\n id: item.id,\n close: () => {\n answer(undefined, false);\n ctx.ui.dialog.clear();\n }\n };\n ctx.ui.dialog.show(Dialog, () => answer());\n };\n const refresh = async () => {\n const sessionID = session();\n if (!sessionID) return;\n try {\n const items = await ctx.client.rpc(Hush).pending({\n sessionID\n }, options());\n if (session() !== sessionID || controller.signal.aborted) return;\n // The request on screen expired, was interrupted, or was answered elsewhere: its dialog can no longer answer it.\n if (open && !items.some(item => item.id === open?.id)) open.close();\n if (!open && items.length) ask(items[0]);\n } catch {\n if (!controller.signal.aborted) report();\n }\n };\n ctx.keymap.layer(() => ({\n mode: 'global',\n commands: [{\n id: 'oc-hush.forget',\n title: 'Forget Hush credentials for this session',\n group: 'oc-hush',\n palette: true,\n slash: {\n name: 'hush-forget'\n },\n run: async () => {\n const sessionID = session();\n if (!sessionID) return;\n try {\n await ctx.client.rpc(Hush).forget({\n sessionID\n }, options());\n ctx.ui.toast.show({\n title: 'oc-hush',\n message: 'Session credentials forgotten.',\n variant: 'success'\n });\n } catch {\n report();\n }\n }\n }]\n }));\n let stopEvents = () => {};\n const subscribe = () => {\n stopEvents();\n stopEvents = ctx.client.rpc(Hush).events.on('changed', event => {\n if (event.location.directory !== options().location.directory) return;\n const current = session();\n const here = !!current && event.data.sessionIDs.includes(current);\n if (here) void refresh();\n const added = event.data.added;\n if (!added) return;\n const message = added.label;\n // On screen, the dialog is the alert. Elsewhere, the toast offers to open the top-level session.\n if (!here) {\n const root = event.data.sessionIDs[event.data.sessionIDs.length - 1];\n ctx.ui.toast.show({\n title: 'Hush needs a credential',\n message,\n variant: 'warning',\n duration: 10_000,\n sessionID: root\n });\n }\n void ctx.attention.notify({\n title: 'Hush needs a credential',\n message,\n notification: {\n when: 'blurred'\n },\n sound: {\n name: 'question',\n when: 'blurred'\n }\n });\n }, {\n signal: controller.signal\n });\n void refresh();\n };\n const stopReconnect = ctx.data.on('server.connected', subscribe);\n subscribe();\n createEffect(on(session, () => void refresh(), {\n defer: true\n }));\n return () => {\n controller.abort();\n stopEvents();\n stopReconnect();\n open?.close();\n };\n }\n});"],"mappings":"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","names":["value"]}
package/package.json CHANGED
@@ -1,6 +1,70 @@
1
1
  {
2
2
  "name": "oc-hush",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.1",
4
+ "description": "Let OpenCode use credentials without putting them in the conversation.",
5
+ "keywords": [
6
+ "opencode",
7
+ "opencode-plugin",
8
+ "secrets",
9
+ "credentials",
10
+ "codemode"
11
+ ],
12
+ "author": "Ope Oginni",
13
+ "license": "MIT",
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "git+https://github.com/OpeOginni/oc-plugins.git",
17
+ "directory": "packages/oc-hush"
18
+ },
19
+ "homepage": "https://github.com/OpeOginni/oc-plugins/tree/main/packages/oc-hush#readme",
20
+ "bugs": {
21
+ "url": "https://github.com/OpeOginni/oc-plugins/issues"
22
+ },
23
+ "type": "module",
24
+ "exports": {
25
+ ".": "./dist/index.js",
26
+ "./tui": "./dist/tui.js",
27
+ "./rpc": "./dist/rpc.js",
28
+ "./gui-experimental": "./dist/gui-experimental.cjs"
29
+ },
30
+ "files": [
31
+ "dist",
32
+ "README.md"
33
+ ],
34
+ "publishConfig": {
35
+ "access": "public",
36
+ "registry": "https://registry.npmjs.org/"
37
+ },
38
+ "scripts": {
39
+ "build": "tsup && vite build",
40
+ "prepack": "bun run build",
41
+ "check": "tsc --noEmit && tsc --noEmit -p tsconfig.gui.json",
42
+ "test": "bun test test/*.test.ts",
43
+ "prepublishOnly": "bun run check && bun run test",
44
+ "publish:dry-run": "bun publish --dry-run",
45
+ "release": "bun publish"
46
+ },
47
+ "dependencies": {
48
+ "@opencode/plugin": "2.2.6",
49
+ "zod": "4.1.8"
50
+ },
51
+ "peerDependencies": {
52
+ "@opentui/core": ">=0.8.1",
53
+ "@opentui/solid": ">=0.8.1",
54
+ "solid-js": ">=1.9.0"
55
+ },
56
+ "devDependencies": {
57
+ "@babel/core": "^7.28.0",
58
+ "@babel/preset-typescript": "^7.27.1",
59
+ "@opentui/core": "0.8.3",
60
+ "@opentui/solid": "0.8.3",
61
+ "@types/bun": "^1.4.2",
62
+ "@types/node": "^22",
63
+ "babel-preset-solid": "^1.9.12",
64
+ "solid-js": "1.9.15",
65
+ "tsup": "^8.5.1",
66
+ "typescript": "^5.9.0",
67
+ "vite": "7.3.7",
68
+ "vite-plugin-solid": "2.11.10"
69
+ }
70
+ }