@aifight/aifight 0.1.0-alpha.5 → 0.1.0-alpha.6

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
@@ -22,6 +22,8 @@ aifight start
22
22
  aifight start <texas_holdem|liars_dice|coup>
23
23
  aifight start <texas_holdem|liars_dice|coup> <N>
24
24
  aifight status
25
+ aifight update
26
+ aifight update --yes
25
27
  aifight service install
26
28
  aifight service status
27
29
  aifight service start
@@ -99,6 +101,26 @@ Bridge and does not consume the daily automatic match limit. Developers can run
99
101
  foreground Bridge debugging with `aifight run`; it refuses to start when
100
102
  `aifight.service` is already running unless `--force` is supplied.
101
103
 
104
+ ## Updating
105
+
106
+ To update the local AIFight CLI package without registering a new Agent or
107
+ rotating bridge credentials:
108
+
109
+ ```bash
110
+ aifight update
111
+ ```
112
+
113
+ In Agent-assisted setup, after the human has approved the local npm package
114
+ update, use the non-interactive form:
115
+
116
+ ```bash
117
+ aifight update --yes
118
+ ```
119
+
120
+ The update command installs the current `@aifight/aifight@alpha` package from
121
+ npm and restarts `aifight.service` when the service is installed and running.
122
+ It does not claim, re-pair, register, or create a new Agent.
123
+
102
124
  ## Runtime Providers
103
125
 
104
126
  OpenClaw default:
package/dist/bin.mjs CHANGED
@@ -64,7 +64,7 @@ CREATE INDEX IF NOT EXISTS idx_agents_name ON agents(name);
64
64
  ALTER TABLE agents_new RENAME TO agents;
65
65
  DROP INDEX IF EXISTS idx_agents_name;
66
66
  CREATE INDEX idx_agents_name ON agents(name);
67
- `)}}],wP=xd[xd.length-1].version;import{Entry as SP}from"@napi-rs/keyring";var Cd="AIFIGHT_KEYCHAIN_V1:",Id="AIFIGHT_CRYPTO_V1:";var $P=Buffer.byteLength(Cd,"ascii"),RP=Buffer.byteLength(Id,"ascii");var uS=xe(Af(),1),dS=xe(Yo(),1),fS=xe(Un(),1),mS=xe(ka(),1),pS=xe(Pa(),1),hS=xe(Oa(),1),La=xe(ei(),1),gS=xe(Mf(),1);var me=class extends Error{},Nt=class extends me{kind="connect";cause;constructor(e,n){super(e),this.name="WSConnectError",this.cause=n}},Lt=class extends me{kind="handshake";statusCode;responseBody;cause;constructor(e,n,r,o){super(r),this.name="WSHandshakeError",this.statusCode=e,this.responseBody=n,this.cause=o}},cn=class extends me{kind="welcome-timeout";constructor(e){super(e),this.name="WSWelcomeTimeoutError"}},Mt=class extends me{kind="welcome-invalid";ajvErrors;constructor(e,n){super(n),this.name="WSWelcomeInvalidError",this.ajvErrors=e}},ln=class extends me{kind="protocol-version";clientVersion;serverVersion;constructor(e,n,r){super(r),this.name="WSProtocolVersionError",this.clientVersion=e,this.serverVersion=n}},un=class extends me{kind="closed";constructor(e){super(e),this.name="WSClosedError"}},Re=class extends me{kind="schema";messageType;ajvErrors;constructor(e,n,r){super(r),this.name="WSSchemaError",this.messageType=e,this.ajvErrors=n}},rt=class extends me{kind="outbound-schema";messageType;ajvErrors;constructor(e,n,r){super(r),this.name="WSOutboundSchemaError",this.messageType=e,this.ajvErrors=n}},wt=class extends me{kind="unknown-message";messageType;constructor(e,n){super(n),this.name="WSUnknownMessageError",this.messageType=e}},vt=class extends me{kind="aborted";cause;constructor(e,n){super(e),this.name="WSAbortedError",this.cause=n}};var jf=xe(Bo(),1),Df=xe(fa(),1);var ja=new Set(["join_queue","leave_queue","match_confirm","action","runtime_status"]),Da=new Set(["welcome","queue_joined","queue_left","match_confirm_request","match_cancelled","game_start","readiness_check","action_request","event","game_state","game_over","error"]),Ff="https://aifight.ai/protocol/v1/messages/";function yS(t){return`${Ff}client_${t}.schema.json`}function _S(t){return`${Ff}server_${t}.schema.json`}var Ma=null;function Bf(){if(Ma)return Ma;let t=new jf.default({strict:!1,allErrors:!0});(0,Df.default)(t);for(let[e,n]of qt())t.getSchema(e)||t.addSchema(n,e);return Ma=t,t}function Uf(t){return(t.errors??[]).map(n=>({instancePath:n.instancePath,message:n.message??void 0}))}function qf(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)}function Hf(t){if(!qf(t))throw new rt("<unknown>",[],"serializeClientMessage: envelope must be a plain object");let e=t.type;if(typeof e!="string"||e.length===0)throw new rt("<unknown>",[],"serializeClientMessage: envelope is missing a string `type` field");if(Da.has(e))throw new rt(e,[],`serializeClientMessage: '${e}' is a server-only message type and cannot be sent by the client`);if(!ja.has(e))throw new rt(e,[],`serializeClientMessage: unknown client message type '${e}' (known: ${[...ja].join(", ")})`);let n=Bf(),r=yS(e),o=n.getSchema(r);if(!o)throw new rt(e,[],`serializeClientMessage: schema not registered for $id ${r} (packaging bug \u2014 loadAllSchemas did not include this file)`);if(!o(t))throw new rt(e,Uf(o),`serializeClientMessage: '${e}' envelope failed schema validation`);return JSON.stringify(t)}function Fa(t){let e=typeof t=="string"?t:t.toString("utf8"),n;try{n=JSON.parse(e)}catch(c){let l=c instanceof Error?c.message:String(c);throw new Re("<unknown>",[],`parseServerFrame: malformed JSON: ${l}`)}if(!qf(n))throw new Re("<unknown>",[],"parseServerFrame: frame must be a JSON object");let r=n.type;if(typeof r!="string"||r.length===0)throw new Re("<unknown>",[],"parseServerFrame: frame is missing a string `type` field");if(!Da.has(r))throw ja.has(r)?new wt(r,`parseServerFrame: '${r}' is a client-only message type and was not expected on the inbound channel`):new wt(r,`parseServerFrame: unknown server message type '${r}' (known: ${[...Da].join(", ")})`);let o=Bf(),i=_S(r),s=o.getSchema(i);if(!s)throw new Re(r,[],`parseServerFrame: schema not registered for $id ${i} (packaging bug)`);if(!s(n))throw new Re(r,Uf(s),`parseServerFrame: '${r}' frame failed schema validation`);return n}var wS=1e4,vS=25e3;function Gf(t){if(t===void 0)return"(no reason)";if(t instanceof Error)return t.message;if(typeof t=="string")return t;try{return String(t)}catch{return"(unstringifiable reason)"}}var Ba=class{#e;#t="connected";#n=null;#r=null;#o=null;#a=new Set;#c=new Set;#u=new Set;#g=!1;#d=null;#l=null;#i=null;welcome;constructor(e,n,r){this.#e=e,this.welcome=n,this.#e.on("message",i=>{this.#s(i)}),this.#e.on("error",()=>{}),this.#e.once("close",(i,s)=>{let a=s?.toString("utf8")??"",c=this.#d??"server";this.#y({code:i,reason:a,initiator:c}),this.#t="closed",this.#_(),this.#i&&(this.#i(),this.#i=null)});let o=r.pingIntervalMs??vS;o>0&&(this.#n=setInterval(()=>{try{this.#e.ping()}catch{this.#n&&(clearInterval(this.#n),this.#n=null)}},o)),r.signal&&(this.#r=r.signal,this.#o=()=>{if(this.#t!=="closed"){this.#d="abort",this.#y({code:0,reason:"aborted",initiator:"abort"}),this.#t="closed",this.#_();try{this.#e.terminate()}catch{}}},r.signal.addEventListener("abort",this.#o,{once:!0}))}get state(){return this.#t}onMessage(e){return this.#a.add(e),()=>{this.#a.delete(e)}}onError(e){return this.#c.add(e),()=>{this.#c.delete(e)}}onClose(e){return this.#u.add(e),()=>{this.#u.delete(e)}}#s(e){if(this.#t!=="connected")return;let n=typeof e=="string"||Buffer.isBuffer(e)?e:Buffer.from(e),r;try{r=Fa(n)}catch(o){if(o instanceof Re||o instanceof wt)this.#m(o);else{let i=o instanceof Error?o.message:String(o);this.#m(new Re("<unknown>",[],`unexpected frame parse error: ${i}`))}return}this.#h(r)}#h(e){let n=[...this.#a];for(let r of n)this.#p(()=>r(e))}#m(e){let n=[...this.#c];for(let r of n)this.#p(()=>r(e))}#y(e){if(this.#g)return;this.#g=!0;let n=[...this.#u];for(let r of n)this.#p(()=>r(e))}#p(e){try{let n=e();n&&typeof n.then=="function"&&n.then(void 0,()=>{})}catch{}}send(e){if(this.#t!=="connected")throw new un(`cannot send: client state is "${this.#t}" (expected "connected")`);let n=Hf(e);this.#e.send(n)}#_(){this.#n&&(clearInterval(this.#n),this.#n=null),this.#r&&this.#o&&(this.#r.removeEventListener("abort",this.#o),this.#r=null,this.#o=null)}async close(e=1e3,n=""){if(this.#t!=="closed"){if(this.#t==="closing"){this.#l&&await this.#l;return}this.#d="client",this.#t="closing",this.#_(),this.#l=new Promise(r=>{this.#i=r});try{this.#e.close(e,n)}catch{this.#y({code:e,reason:n,initiator:"client"}),this.#t="closed",this.#i&&(this.#i(),this.#i=null)}await this.#l}}};async function Ua(t){let e=t.welcomeTimeoutMs??wS;return t.signal?.aborted?Promise.reject(new vt(`createWSClient aborted before start: ${Gf(t.signal.reason)}`,t.signal.reason)):new Promise((n,r)=>{let o;try{o=new La.default(t.url,{headers:{"X-API-Key":t.apiKey}})}catch(u){let d=u instanceof Error?u.message:String(u);r(new Nt(`failed to construct WebSocket for ${t.url}: ${d}`,u));return}let i=!1,s=null,a=null,c=()=>{s&&(clearTimeout(s),s=null),t.signal&&a&&(t.signal.removeEventListener("abort",a),a=null),o.removeAllListeners(),o.on("error",()=>{})},l=u=>{i||(i=!0,c(),u())};t.signal&&(a=()=>{l(()=>{try{o.terminate()}catch{}r(new vt(`createWSClient aborted during handshake: ${Gf(t.signal.reason)}`,t.signal.reason))})},t.signal.addEventListener("abort",a,{once:!0})),o.once("error",u=>{l(()=>{try{o.terminate()}catch{}r(new Nt(`WebSocket connect failed for ${t.url}: ${u.message}`,u))})}),o.once("unexpected-response",(u,d)=>{let h="";d.setEncoding("utf8"),d.on("data",p=>{h+=p}),d.on("end",()=>{let p=d.statusCode??0,f=d.statusMessage??"";try{u.destroy()}catch{}l(()=>r(new Lt(p,h,`HTTP upgrade rejected: ${p} ${f}`.trim())))}),d.on("error",p=>{let f=d.statusCode??0;l(()=>r(new Lt(f,h,`HTTP upgrade response read failed: ${p.message}`,p)))})}),o.once("open",()=>{s=setTimeout(()=>{l(()=>{try{o.terminate()}catch{}r(new cn(`welcome did not arrive within ${e}ms after WebSocket open`))})},e)}),o.once("message",u=>{let d=typeof u=="string"||Buffer.isBuffer(u)?u:Buffer.from(u),h;try{h=Fa(d)}catch(v){let S=[],R="first frame failed to parse";v instanceof Re?(S=v.ajvErrors,R=v.messageType==="welcome"?`welcome failed schema validation: ${v.message}`:`first frame parse failure (${v.messageType}): ${v.message}`):v instanceof wt?R=`first frame had unknown server message type '${v.messageType}': ${v.message}`:v instanceof Error&&(R=`first frame parse error: ${v.message}`),l(()=>{try{o.terminate()}catch{}r(new Mt(S,R))});return}if(h.type!=="welcome"){l(()=>{try{o.terminate()}catch{}r(new Mt([],`expected first frame to be 'welcome', got '${h.type}'`))});return}let p=h,f=p.data.server_protocol_version,m=v=>v.startsWith("v")?v.slice(1):v,g=m(t.expectedProtocolVersion).split(".")[0],y=m(f).split(".")[0];if(g!==y){l(()=>{try{o.terminate()}catch{}r(new ln(t.expectedProtocolVersion,f,`protocol major version mismatch: client expected '${t.expectedProtocolVersion}', server is '${f}'`))});return}l(()=>{let v=new Ba(o,p,{pingIntervalMs:t.pingIntervalMs,signal:t.signal});n(v)})})})}var zn=class extends Error{name="ReconnectStoppedError";kind;cause;constructor(e,n,r){super(r),this.kind=e,this.cause=n}},bS=1e3,SS=2,ES=3e4,kS="full",$S=5*60*1e3,RS=15*60*1e3,PS=new Set([1001,1006,1011,1012]);function AS(t,e,n,r){let o=e*Math.pow(n,Math.max(0,t-1));return Math.min(o,r)}function TS(t,e){switch(e){case"none":return t;case"full":return Math.floor(Math.random()*t);case"equal":return Math.floor(t/2+Math.random()*t/2)}}function xS(t){return t.code>=4e3&&t.code<5e3?!1:PS.has(t.code)}function CS(t){if(t instanceof vt||t instanceof Mt||t instanceof ln)return!1;if(t instanceof Nt||t instanceof cn)return!0;if(t instanceof Lt){let e=t.statusCode;return e===401||e===403||e===404?!1:e===408||e===429||e>=500&&e<600}return!1}function IS(t){return t>=RS?"error":t>=$S?"warning":"info"}var qa=class{state="connecting";attempt=0;welcome=null;#e;#t=null;#n=new Set;#r=new Set;#o=new Set;#a=new Set;#c=0;#u=0;#g=null;#d=null;#l=!1;#i=null;#s=!1;#h=null;#m=[];constructor(e){this.#e=e}send(e){if(this.state!=="connected"||this.#t===null)throw new un(`cannot send while ReconnectingWSClient.state="${this.state}"`);this.#t.send(e)}onMessage(e){this.#n.add(e);let n=null;return this.#t!==null&&this.state==="connected"&&(n=this.#t.onMessage(e)),()=>{this.#n.delete(e),n&&n()}}onError(e){this.#r.add(e);let n=null;return this.#t!==null&&this.state==="connected"&&(n=this.#t.onError(e)),()=>{this.#r.delete(e),n&&n()}}onClose(e){return this.#o.add(e),()=>{this.#o.delete(e)}}onReconnect(e){return this.#a.add(e),()=>{this.#a.delete(e)}}async close(e,n){this.state!=="closed"&&(this.#i={code:e,reason:n},this.#h&&this.#h("close"),this.#t!==null?await this.#t.close(e,n).catch(()=>{}):this.#s||this.#f({kind:"caller-close",code:e??1e3,closeReason:n,cause:void 0}))}begin(e,n){this.#g=e,this.#d=n,this.#y()}async#y(){if(this.#c=Date.now(),this.#e.signal?.aborted){this.#S("signal",void 0,"ReconnectingWSClient pre-aborted by signal");return}for(;this.state!=="closed";){this.attempt++,this.state="connecting",this.#b("attempt-start",this.attempt);let e,n=!1;try{let a=await Ua({url:this.#e.url,apiKey:this.#e.apiKey,expectedProtocolVersion:this.#e.expectedProtocolVersion,welcomeTimeoutMs:this.#e.welcomeTimeoutMs,pingIntervalMs:this.#e.pingIntervalMs,signal:this.#e.signal});n=!0,this.#t=a,this.welcome=a.welcome,this.#E(a),this.state="connected";let c=this.attempt;this.attempt=0,this.#u=0,this.#b("attempt-success",c),this.#l||(this.#l=!0,this.#g?.());let l=await this.#_(a);if(this.#w(),this.#t=null,this.#i){this.#f({kind:"caller-close",code:this.#i.code??l.code,closeReason:this.#i.reason??l.reason,cause:void 0});return}if(this.#e.signal?.aborted){this.#f({kind:"signal",cause:void 0});return}if(!xS(l)){let u=new zn("fatal-close",void 0,`close code ${l.code} not in retry whitelist`);this.#f({kind:"fatal-close",code:l.code,closeReason:l.reason,cause:u});return}this.#u=1,this.state="backoff",this.#c=Date.now()}catch(a){if(n)throw a;if(a instanceof me&&(e=a),!CS(a)){let c=a instanceof me?a:void 0,l=a instanceof vt?"signal":"fatal-error",u=a instanceof Error?a.message:"non-retriable error";this.#S(l,c,u);return}this.#u++,this.state="backoff"}let r=AS(this.#u,this.#e.initialBackoffMs??bS,this.#e.backoffFactor??SS,this.#e.maxBackoffMs??ES),o=TS(r,this.#e.jitter??kS),i=this.attempt===0?1:this.attempt;if(this.#b("attempt-failure",i,o,e),this.#e.maxAttempts!==void 0&&this.#u>=this.#e.maxAttempts){this.#S("max-attempts",e,`exhausted maxAttempts=${this.#e.maxAttempts}`);return}let s=await this.#p(o);if(s==="abort"){this.#f({kind:"signal",cause:void 0}),this.#l||(this.#l=!0,this.#d?.(new zn("signal",void 0,"ReconnectingWSClient aborted during backoff")));return}if(s==="close"){this.#f({kind:"caller-close",code:this.#i?.code??1e3,closeReason:this.#i?.reason,cause:void 0});return}}}#p(e){return new Promise(n=>{let r=!1,o=c=>{r||(r=!0,clearTimeout(i),s&&a&&s.removeEventListener("abort",a),this.#h=null,n(c))},i=setTimeout(()=>o("timeout"),e),s=this.#e.signal,a=null;if(s){if(s.aborted){o("abort");return}a=()=>o("abort"),s.addEventListener("abort",a)}this.#h=c=>o(c)})}#_(e){return new Promise(n=>{let r=e.onClose(o=>{try{r()}catch{}n(o)})})}#E(e){this.#w();for(let n of this.#n)this.#m.push(e.onMessage(n));for(let n of this.#r)this.#m.push(e.onError(n))}#w(){for(let e of this.#m)try{e()}catch{}this.#m.length=0}#b(e,n,r,o){let i=Date.now()-this.#c,s=e==="give-up"?"error":e==="attempt-failure"?IS(i):"info",a={type:e,attempt:n,nextDelayMs:r,cause:o,elapsedMs:i,severity:s},c=[...this.#a];for(let l of c)try{l(a)}catch{}}#S(e,n,r){let o=new zn(e,n,r);this.#f({kind:e,cause:e==="fatal-error"||e==="max-attempts"?o:void 0}),this.#l||(this.#l=!0,this.#d?.(o))}#f(e){if(this.#s)return;this.#s=!0,this.state="closed",this.#w(),this.#t=null,this.#b("give-up",this.attempt,void 0,e.cause);let n=[...this.#o];for(let r of n)try{r(e)}catch{}}};async function Ha(t){let e=new qa(t);return await new Promise((n,r)=>{e.begin(n,r)}),e}var OS=["check","call","fold","raise","allin"];function Ga(t){let{legalActions:e}=t;if(e.length===0)throw new Error("Texas Hold'em fallback requires at least one legal action");for(let n of OS){let r=e.find(o=>o.type===n);if(r)return r}return e[0]}function Wa(t){let{publicState:e,legalActions:n}=t;if(n.length===0)throw new Error("Liar's Dice fallback requires at least one legal action");let r=n.find(i=>i.type==="bid"),o=n.find(i=>i.type==="challenge");if(r){let i=NS(r.data);if(i)return i.maxQuantity!==void 0&&i.minQuantity>i.maxQuantity?o??n[0]:{type:"bid",data:{quantity:i.minQuantity,face:i.minFace}};let s=LS(e);if(s)return typeof e.total_dice=="number"&&s.quantity>e.total_dice?o??n[0]:{type:"bid",data:s}}return o||n[0]}function NS(t){let e=MS(t);if(!e)return;let n=Va(e,"min_quantity"),r=Va(e,"min_face");if(!(n===void 0||r===void 0))return{minQuantity:n,minFace:r,maxQuantity:Va(e,"max_quantity")}}function LS(t){let e=t.current_bid;if(!e)return typeof t.total_dice!="number"?void 0:{quantity:1,face:1};if(!(typeof e.quantity!="number"||typeof e.face!="number"))return e.face<6?{quantity:e.quantity,face:e.face+1}:{quantity:e.quantity+1,face:1}}function MS(t){return t!==null&&typeof t=="object"?t:void 0}function Va(t,e){let n=t[e];return typeof n=="number"?n:void 0}var jS=["income","foreign_aid","coup","tax","steal","assassinate","exchange"],DS=["pass","challenge"],FS=["pass","block"],BS=["lose_card"],US=["return_cards"];function za(t){let{publicState:e,legalActions:n}=t;if(n.length===0)throw new Error("Coup fallback requires at least one legal action");switch(e.phase){case"action":return qr(n,jS);case"challenge_action":case"challenge_block":return qr(n,DS);case"block":return qr(n,FS);case"lose_influence":return qr(n,BS);case"exchange_return":return qr(n,US);case"done":throw new Error("Coup fallback should not run when phase is done");default:return n[0]}}function qr(t,e){for(let n of e){let r=t.find(o=>o.type===n);if(r)return r}return t[0]}var qS=/^```(?:json)?\s*\n?([\s\S]*?)\n?```\s*$/;function Ja(t,e,n=500){let r=t.trim(),o=VS(r),i;try{i=JSON.parse(o)}catch{return dn("json_parse",r,n)}if(!ni(i))return dn("missing_fields",r,n);let s=i.action;if(typeof s!="string")return dn("missing_fields",r,n);let a=typeof i.summary=="string"?i.summary:void 0,c=i.data;if(c!=null&&!ni(c))return dn("missing_fields",r,n);let l=ni(c)?c:void 0;if(!HS.has(s))return dn("unknown_action_type",r,n);let u=e.find(d=>d.type===s);if(!u)return dn("action_not_legal",r,n);if(s==="raise"){let d=GS(u,l);return d?a!==void 0?{kind:"ok",action:d,summary:a}:{kind:"ok",action:d}:dn("data_validation",r,n)}return a!==void 0?{kind:"ok",action:u,summary:a}:{kind:"ok",action:u}}var HS=new Set(["fold","check","call","raise","allin"]);function GS(t,e){if(!e)return;let n=e.amount;if(typeof n!="number"||!Number.isFinite(n))return;let r=ni(t.data)?t.data:void 0,o=Ka(r,"amount"),i=Ka(r,"min")??o,s=Ka(r,"max")??o;if(!(i!==void 0&&n<i)&&!(s!==void 0&&n>s))return{type:"raise",data:{amount:n}}}function VS(t){let e=t.match(qS);return e?e[1].trim():t}function ni(t){return t!==null&&typeof t=="object"&&!Array.isArray(t)}function Ka(t,e){if(!t)return;let n=t[e];return typeof n=="number"&&Number.isFinite(n)?n:void 0}function dn(t,e,n){return{kind:"invalid",reason:t,rawSnippet:e.length>n?e.slice(0,n):e}}var WS=/^```(?:json)?\s*\n?([\s\S]*?)\n?```\s*$/;function Qa(t,e,n=500){let r=t.trim(),o=JS(r),i;try{i=JSON.parse(o)}catch{return fn("json_parse",r,n)}if(!ri(i))return fn("missing_fields",r,n);let s=i.action;if(typeof s!="string")return fn("missing_fields",r,n);let a=typeof i.summary=="string"?i.summary:void 0,c=i.data;if(c!=null&&!ri(c))return fn("missing_fields",r,n);let l=ri(c)?c:void 0;if(!zS.has(s))return fn("unknown_action_type",r,n);let u=e.find(d=>d.type===s);if(!u)return fn("action_not_legal",r,n);if(s==="bid"){let d=KS(u,l);return d?a!==void 0?{kind:"ok",action:d,summary:a}:{kind:"ok",action:d}:fn("data_validation",r,n)}return a!==void 0?{kind:"ok",action:u,summary:a}:{kind:"ok",action:u}}var zS=new Set(["bid","challenge"]);function KS(t,e){if(!e)return;let n=e.quantity,r=e.face;if(typeof n!="number"||!Number.isFinite(n)||!Number.isInteger(n)||typeof r!="number"||!Number.isFinite(r)||!Number.isInteger(r)||r<1||r>6||n<1)return;let o=ri(t.data)?t.data:void 0,i=Ya(o,"min_quantity"),s=Ya(o,"min_face"),a=Ya(o,"max_quantity");if(!(i!==void 0&&n<i)&&!(a!==void 0&&n>a)&&!(i!==void 0&&s!==void 0&&n===i&&r<s))return{type:"bid",data:{quantity:n,face:r}}}function JS(t){let e=t.match(WS);return e?e[1].trim():t}function ri(t){return t!==null&&typeof t=="object"&&!Array.isArray(t)}function Ya(t,e){if(!t)return;let n=t[e];return typeof n=="number"&&Number.isFinite(n)?n:void 0}function fn(t,e,n){return{kind:"invalid",reason:t,rawSnippet:e.length>n?e.slice(0,n):e}}var YS=/^```(?:json)?\s*\n?([\s\S]*?)\n?```\s*$/,QS=new Set(["income","foreign_aid","coup","tax","assassinate","steal","exchange","challenge","pass","block","lose_card","return_cards"]);function Xa(t,e,n=500){let r=t.trim(),o=ZS(r),i;try{i=JSON.parse(o)}catch{return mn("json_parse",r,n)}if(!Kn(i))return mn("missing_fields",r,n);let s=i.action;if(typeof s!="string")return mn("missing_fields",r,n);let a=typeof i.summary=="string"?i.summary:void 0,c=i.data;if(c!=null&&!Kn(c))return mn("missing_fields",r,n);let l=Kn(c)?c:void 0;if(!QS.has(s))return mn("unknown_action_type",r,n);let u=e.filter(h=>h.type===s);if(u.length===0)return mn("action_not_legal",r,n);let d=XS(s,u,l);return d?a!==void 0?{kind:"ok",action:d,summary:a}:{kind:"ok",action:d}:mn("data_validation",r,n)}function XS(t,e,n){switch(t){case"coup":case"assassinate":case"steal":{let r=n?.target;return typeof r!="string"?void 0:e.find(o=>Vf(o.data,"target")===r)}case"block":{let r=n?.role;return typeof r!="string"?void 0:e.find(o=>Vf(o.data,"role")===r)}case"lose_card":{let r=n?.card_index;return typeof r!="number"||!Number.isFinite(r)||!Number.isInteger(r)?void 0:e.find(o=>e0(o.data,"card_index")===r)}case"return_cards":{let r=n?.return_indices;return!Array.isArray(r)||!r.every(o=>typeof o=="number"&&Number.isFinite(o)&&Number.isInteger(o))?void 0:e.find(o=>{let i=t0(o.data,"return_indices");return i!==void 0&&n0(i,r)})}default:return e[0]}}function ZS(t){let e=t.match(YS);return e?e[1].trim():t}function Kn(t){return t!==null&&typeof t=="object"&&!Array.isArray(t)}function Vf(t,e){if(!Kn(t))return;let n=t[e];return typeof n=="string"?n:void 0}function e0(t,e){if(!Kn(t))return;let n=t[e];return typeof n=="number"&&Number.isFinite(n)?n:void 0}function t0(t,e){if(!Kn(t))return;let n=t[e];if(Array.isArray(n)&&n.every(r=>typeof r=="number"&&Number.isFinite(r)))return n}function n0(t,e){if(t.length!==e.length)return!1;for(let n=0;n<t.length;n++)if(t[n]!==e[n])return!1;return!0}function mn(t,e,n){return{kind:"invalid",reason:t,rawSnippet:e.length>n?e.slice(0,n):e}}var se="0.1.0-alpha.5",Xf="v1.0.0";function Zf(){let t=ir(),e=qt(),n=wi();return{ok:!0,runtimeVersion:se,schemaCount:e.size,messageTypeCount:n.length,schemasRoot:t}}async function Za(t,e){return W(t,0,0,"usage: aifight version"),t.jsonMode?e.stdout(JSON.stringify({version:se})+`
67
+ `)}}],wP=xd[xd.length-1].version;import{Entry as SP}from"@napi-rs/keyring";var Cd="AIFIGHT_KEYCHAIN_V1:",Id="AIFIGHT_CRYPTO_V1:";var $P=Buffer.byteLength(Cd,"ascii"),RP=Buffer.byteLength(Id,"ascii");var uS=xe(Af(),1),dS=xe(Yo(),1),fS=xe(Un(),1),mS=xe(ka(),1),pS=xe(Pa(),1),hS=xe(Oa(),1),La=xe(ei(),1),gS=xe(Mf(),1);var me=class extends Error{},Nt=class extends me{kind="connect";cause;constructor(e,n){super(e),this.name="WSConnectError",this.cause=n}},Lt=class extends me{kind="handshake";statusCode;responseBody;cause;constructor(e,n,r,o){super(r),this.name="WSHandshakeError",this.statusCode=e,this.responseBody=n,this.cause=o}},cn=class extends me{kind="welcome-timeout";constructor(e){super(e),this.name="WSWelcomeTimeoutError"}},Mt=class extends me{kind="welcome-invalid";ajvErrors;constructor(e,n){super(n),this.name="WSWelcomeInvalidError",this.ajvErrors=e}},ln=class extends me{kind="protocol-version";clientVersion;serverVersion;constructor(e,n,r){super(r),this.name="WSProtocolVersionError",this.clientVersion=e,this.serverVersion=n}},un=class extends me{kind="closed";constructor(e){super(e),this.name="WSClosedError"}},Re=class extends me{kind="schema";messageType;ajvErrors;constructor(e,n,r){super(r),this.name="WSSchemaError",this.messageType=e,this.ajvErrors=n}},rt=class extends me{kind="outbound-schema";messageType;ajvErrors;constructor(e,n,r){super(r),this.name="WSOutboundSchemaError",this.messageType=e,this.ajvErrors=n}},wt=class extends me{kind="unknown-message";messageType;constructor(e,n){super(n),this.name="WSUnknownMessageError",this.messageType=e}},vt=class extends me{kind="aborted";cause;constructor(e,n){super(e),this.name="WSAbortedError",this.cause=n}};var jf=xe(Bo(),1),Df=xe(fa(),1);var ja=new Set(["join_queue","leave_queue","match_confirm","action","runtime_status"]),Da=new Set(["welcome","queue_joined","queue_left","match_confirm_request","match_cancelled","game_start","readiness_check","action_request","event","game_state","game_over","error"]),Ff="https://aifight.ai/protocol/v1/messages/";function yS(t){return`${Ff}client_${t}.schema.json`}function _S(t){return`${Ff}server_${t}.schema.json`}var Ma=null;function Bf(){if(Ma)return Ma;let t=new jf.default({strict:!1,allErrors:!0});(0,Df.default)(t);for(let[e,n]of qt())t.getSchema(e)||t.addSchema(n,e);return Ma=t,t}function Uf(t){return(t.errors??[]).map(n=>({instancePath:n.instancePath,message:n.message??void 0}))}function qf(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)}function Hf(t){if(!qf(t))throw new rt("<unknown>",[],"serializeClientMessage: envelope must be a plain object");let e=t.type;if(typeof e!="string"||e.length===0)throw new rt("<unknown>",[],"serializeClientMessage: envelope is missing a string `type` field");if(Da.has(e))throw new rt(e,[],`serializeClientMessage: '${e}' is a server-only message type and cannot be sent by the client`);if(!ja.has(e))throw new rt(e,[],`serializeClientMessage: unknown client message type '${e}' (known: ${[...ja].join(", ")})`);let n=Bf(),r=yS(e),o=n.getSchema(r);if(!o)throw new rt(e,[],`serializeClientMessage: schema not registered for $id ${r} (packaging bug \u2014 loadAllSchemas did not include this file)`);if(!o(t))throw new rt(e,Uf(o),`serializeClientMessage: '${e}' envelope failed schema validation`);return JSON.stringify(t)}function Fa(t){let e=typeof t=="string"?t:t.toString("utf8"),n;try{n=JSON.parse(e)}catch(c){let l=c instanceof Error?c.message:String(c);throw new Re("<unknown>",[],`parseServerFrame: malformed JSON: ${l}`)}if(!qf(n))throw new Re("<unknown>",[],"parseServerFrame: frame must be a JSON object");let r=n.type;if(typeof r!="string"||r.length===0)throw new Re("<unknown>",[],"parseServerFrame: frame is missing a string `type` field");if(!Da.has(r))throw ja.has(r)?new wt(r,`parseServerFrame: '${r}' is a client-only message type and was not expected on the inbound channel`):new wt(r,`parseServerFrame: unknown server message type '${r}' (known: ${[...Da].join(", ")})`);let o=Bf(),i=_S(r),s=o.getSchema(i);if(!s)throw new Re(r,[],`parseServerFrame: schema not registered for $id ${i} (packaging bug)`);if(!s(n))throw new Re(r,Uf(s),`parseServerFrame: '${r}' frame failed schema validation`);return n}var wS=1e4,vS=25e3;function Gf(t){if(t===void 0)return"(no reason)";if(t instanceof Error)return t.message;if(typeof t=="string")return t;try{return String(t)}catch{return"(unstringifiable reason)"}}var Ba=class{#e;#t="connected";#n=null;#r=null;#o=null;#a=new Set;#c=new Set;#u=new Set;#g=!1;#d=null;#l=null;#i=null;welcome;constructor(e,n,r){this.#e=e,this.welcome=n,this.#e.on("message",i=>{this.#s(i)}),this.#e.on("error",()=>{}),this.#e.once("close",(i,s)=>{let a=s?.toString("utf8")??"",c=this.#d??"server";this.#y({code:i,reason:a,initiator:c}),this.#t="closed",this.#_(),this.#i&&(this.#i(),this.#i=null)});let o=r.pingIntervalMs??vS;o>0&&(this.#n=setInterval(()=>{try{this.#e.ping()}catch{this.#n&&(clearInterval(this.#n),this.#n=null)}},o)),r.signal&&(this.#r=r.signal,this.#o=()=>{if(this.#t!=="closed"){this.#d="abort",this.#y({code:0,reason:"aborted",initiator:"abort"}),this.#t="closed",this.#_();try{this.#e.terminate()}catch{}}},r.signal.addEventListener("abort",this.#o,{once:!0}))}get state(){return this.#t}onMessage(e){return this.#a.add(e),()=>{this.#a.delete(e)}}onError(e){return this.#c.add(e),()=>{this.#c.delete(e)}}onClose(e){return this.#u.add(e),()=>{this.#u.delete(e)}}#s(e){if(this.#t!=="connected")return;let n=typeof e=="string"||Buffer.isBuffer(e)?e:Buffer.from(e),r;try{r=Fa(n)}catch(o){if(o instanceof Re||o instanceof wt)this.#m(o);else{let i=o instanceof Error?o.message:String(o);this.#m(new Re("<unknown>",[],`unexpected frame parse error: ${i}`))}return}this.#h(r)}#h(e){let n=[...this.#a];for(let r of n)this.#p(()=>r(e))}#m(e){let n=[...this.#c];for(let r of n)this.#p(()=>r(e))}#y(e){if(this.#g)return;this.#g=!0;let n=[...this.#u];for(let r of n)this.#p(()=>r(e))}#p(e){try{let n=e();n&&typeof n.then=="function"&&n.then(void 0,()=>{})}catch{}}send(e){if(this.#t!=="connected")throw new un(`cannot send: client state is "${this.#t}" (expected "connected")`);let n=Hf(e);this.#e.send(n)}#_(){this.#n&&(clearInterval(this.#n),this.#n=null),this.#r&&this.#o&&(this.#r.removeEventListener("abort",this.#o),this.#r=null,this.#o=null)}async close(e=1e3,n=""){if(this.#t!=="closed"){if(this.#t==="closing"){this.#l&&await this.#l;return}this.#d="client",this.#t="closing",this.#_(),this.#l=new Promise(r=>{this.#i=r});try{this.#e.close(e,n)}catch{this.#y({code:e,reason:n,initiator:"client"}),this.#t="closed",this.#i&&(this.#i(),this.#i=null)}await this.#l}}};async function Ua(t){let e=t.welcomeTimeoutMs??wS;return t.signal?.aborted?Promise.reject(new vt(`createWSClient aborted before start: ${Gf(t.signal.reason)}`,t.signal.reason)):new Promise((n,r)=>{let o;try{o=new La.default(t.url,{headers:{"X-API-Key":t.apiKey}})}catch(u){let d=u instanceof Error?u.message:String(u);r(new Nt(`failed to construct WebSocket for ${t.url}: ${d}`,u));return}let i=!1,s=null,a=null,c=()=>{s&&(clearTimeout(s),s=null),t.signal&&a&&(t.signal.removeEventListener("abort",a),a=null),o.removeAllListeners(),o.on("error",()=>{})},l=u=>{i||(i=!0,c(),u())};t.signal&&(a=()=>{l(()=>{try{o.terminate()}catch{}r(new vt(`createWSClient aborted during handshake: ${Gf(t.signal.reason)}`,t.signal.reason))})},t.signal.addEventListener("abort",a,{once:!0})),o.once("error",u=>{l(()=>{try{o.terminate()}catch{}r(new Nt(`WebSocket connect failed for ${t.url}: ${u.message}`,u))})}),o.once("unexpected-response",(u,d)=>{let h="";d.setEncoding("utf8"),d.on("data",p=>{h+=p}),d.on("end",()=>{let p=d.statusCode??0,f=d.statusMessage??"";try{u.destroy()}catch{}l(()=>r(new Lt(p,h,`HTTP upgrade rejected: ${p} ${f}`.trim())))}),d.on("error",p=>{let f=d.statusCode??0;l(()=>r(new Lt(f,h,`HTTP upgrade response read failed: ${p.message}`,p)))})}),o.once("open",()=>{s=setTimeout(()=>{l(()=>{try{o.terminate()}catch{}r(new cn(`welcome did not arrive within ${e}ms after WebSocket open`))})},e)}),o.once("message",u=>{let d=typeof u=="string"||Buffer.isBuffer(u)?u:Buffer.from(u),h;try{h=Fa(d)}catch(v){let S=[],R="first frame failed to parse";v instanceof Re?(S=v.ajvErrors,R=v.messageType==="welcome"?`welcome failed schema validation: ${v.message}`:`first frame parse failure (${v.messageType}): ${v.message}`):v instanceof wt?R=`first frame had unknown server message type '${v.messageType}': ${v.message}`:v instanceof Error&&(R=`first frame parse error: ${v.message}`),l(()=>{try{o.terminate()}catch{}r(new Mt(S,R))});return}if(h.type!=="welcome"){l(()=>{try{o.terminate()}catch{}r(new Mt([],`expected first frame to be 'welcome', got '${h.type}'`))});return}let p=h,f=p.data.server_protocol_version,m=v=>v.startsWith("v")?v.slice(1):v,g=m(t.expectedProtocolVersion).split(".")[0],y=m(f).split(".")[0];if(g!==y){l(()=>{try{o.terminate()}catch{}r(new ln(t.expectedProtocolVersion,f,`protocol major version mismatch: client expected '${t.expectedProtocolVersion}', server is '${f}'`))});return}l(()=>{let v=new Ba(o,p,{pingIntervalMs:t.pingIntervalMs,signal:t.signal});n(v)})})})}var zn=class extends Error{name="ReconnectStoppedError";kind;cause;constructor(e,n,r){super(r),this.kind=e,this.cause=n}},bS=1e3,SS=2,ES=3e4,kS="full",$S=5*60*1e3,RS=15*60*1e3,PS=new Set([1001,1006,1011,1012]);function AS(t,e,n,r){let o=e*Math.pow(n,Math.max(0,t-1));return Math.min(o,r)}function TS(t,e){switch(e){case"none":return t;case"full":return Math.floor(Math.random()*t);case"equal":return Math.floor(t/2+Math.random()*t/2)}}function xS(t){return t.code>=4e3&&t.code<5e3?!1:PS.has(t.code)}function CS(t){if(t instanceof vt||t instanceof Mt||t instanceof ln)return!1;if(t instanceof Nt||t instanceof cn)return!0;if(t instanceof Lt){let e=t.statusCode;return e===401||e===403||e===404?!1:e===408||e===429||e>=500&&e<600}return!1}function IS(t){return t>=RS?"error":t>=$S?"warning":"info"}var qa=class{state="connecting";attempt=0;welcome=null;#e;#t=null;#n=new Set;#r=new Set;#o=new Set;#a=new Set;#c=0;#u=0;#g=null;#d=null;#l=!1;#i=null;#s=!1;#h=null;#m=[];constructor(e){this.#e=e}send(e){if(this.state!=="connected"||this.#t===null)throw new un(`cannot send while ReconnectingWSClient.state="${this.state}"`);this.#t.send(e)}onMessage(e){this.#n.add(e);let n=null;return this.#t!==null&&this.state==="connected"&&(n=this.#t.onMessage(e)),()=>{this.#n.delete(e),n&&n()}}onError(e){this.#r.add(e);let n=null;return this.#t!==null&&this.state==="connected"&&(n=this.#t.onError(e)),()=>{this.#r.delete(e),n&&n()}}onClose(e){return this.#o.add(e),()=>{this.#o.delete(e)}}onReconnect(e){return this.#a.add(e),()=>{this.#a.delete(e)}}async close(e,n){this.state!=="closed"&&(this.#i={code:e,reason:n},this.#h&&this.#h("close"),this.#t!==null?await this.#t.close(e,n).catch(()=>{}):this.#s||this.#f({kind:"caller-close",code:e??1e3,closeReason:n,cause:void 0}))}begin(e,n){this.#g=e,this.#d=n,this.#y()}async#y(){if(this.#c=Date.now(),this.#e.signal?.aborted){this.#S("signal",void 0,"ReconnectingWSClient pre-aborted by signal");return}for(;this.state!=="closed";){this.attempt++,this.state="connecting",this.#b("attempt-start",this.attempt);let e,n=!1;try{let a=await Ua({url:this.#e.url,apiKey:this.#e.apiKey,expectedProtocolVersion:this.#e.expectedProtocolVersion,welcomeTimeoutMs:this.#e.welcomeTimeoutMs,pingIntervalMs:this.#e.pingIntervalMs,signal:this.#e.signal});n=!0,this.#t=a,this.welcome=a.welcome,this.#E(a),this.state="connected";let c=this.attempt;this.attempt=0,this.#u=0,this.#b("attempt-success",c),this.#l||(this.#l=!0,this.#g?.());let l=await this.#_(a);if(this.#w(),this.#t=null,this.#i){this.#f({kind:"caller-close",code:this.#i.code??l.code,closeReason:this.#i.reason??l.reason,cause:void 0});return}if(this.#e.signal?.aborted){this.#f({kind:"signal",cause:void 0});return}if(!xS(l)){let u=new zn("fatal-close",void 0,`close code ${l.code} not in retry whitelist`);this.#f({kind:"fatal-close",code:l.code,closeReason:l.reason,cause:u});return}this.#u=1,this.state="backoff",this.#c=Date.now()}catch(a){if(n)throw a;if(a instanceof me&&(e=a),!CS(a)){let c=a instanceof me?a:void 0,l=a instanceof vt?"signal":"fatal-error",u=a instanceof Error?a.message:"non-retriable error";this.#S(l,c,u);return}this.#u++,this.state="backoff"}let r=AS(this.#u,this.#e.initialBackoffMs??bS,this.#e.backoffFactor??SS,this.#e.maxBackoffMs??ES),o=TS(r,this.#e.jitter??kS),i=this.attempt===0?1:this.attempt;if(this.#b("attempt-failure",i,o,e),this.#e.maxAttempts!==void 0&&this.#u>=this.#e.maxAttempts){this.#S("max-attempts",e,`exhausted maxAttempts=${this.#e.maxAttempts}`);return}let s=await this.#p(o);if(s==="abort"){this.#f({kind:"signal",cause:void 0}),this.#l||(this.#l=!0,this.#d?.(new zn("signal",void 0,"ReconnectingWSClient aborted during backoff")));return}if(s==="close"){this.#f({kind:"caller-close",code:this.#i?.code??1e3,closeReason:this.#i?.reason,cause:void 0});return}}}#p(e){return new Promise(n=>{let r=!1,o=c=>{r||(r=!0,clearTimeout(i),s&&a&&s.removeEventListener("abort",a),this.#h=null,n(c))},i=setTimeout(()=>o("timeout"),e),s=this.#e.signal,a=null;if(s){if(s.aborted){o("abort");return}a=()=>o("abort"),s.addEventListener("abort",a)}this.#h=c=>o(c)})}#_(e){return new Promise(n=>{let r=e.onClose(o=>{try{r()}catch{}n(o)})})}#E(e){this.#w();for(let n of this.#n)this.#m.push(e.onMessage(n));for(let n of this.#r)this.#m.push(e.onError(n))}#w(){for(let e of this.#m)try{e()}catch{}this.#m.length=0}#b(e,n,r,o){let i=Date.now()-this.#c,s=e==="give-up"?"error":e==="attempt-failure"?IS(i):"info",a={type:e,attempt:n,nextDelayMs:r,cause:o,elapsedMs:i,severity:s},c=[...this.#a];for(let l of c)try{l(a)}catch{}}#S(e,n,r){let o=new zn(e,n,r);this.#f({kind:e,cause:e==="fatal-error"||e==="max-attempts"?o:void 0}),this.#l||(this.#l=!0,this.#d?.(o))}#f(e){if(this.#s)return;this.#s=!0,this.state="closed",this.#w(),this.#t=null,this.#b("give-up",this.attempt,void 0,e.cause);let n=[...this.#o];for(let r of n)try{r(e)}catch{}}};async function Ha(t){let e=new qa(t);return await new Promise((n,r)=>{e.begin(n,r)}),e}var OS=["check","call","fold","raise","allin"];function Ga(t){let{legalActions:e}=t;if(e.length===0)throw new Error("Texas Hold'em fallback requires at least one legal action");for(let n of OS){let r=e.find(o=>o.type===n);if(r)return r}return e[0]}function Wa(t){let{publicState:e,legalActions:n}=t;if(n.length===0)throw new Error("Liar's Dice fallback requires at least one legal action");let r=n.find(i=>i.type==="bid"),o=n.find(i=>i.type==="challenge");if(r){let i=NS(r.data);if(i)return i.maxQuantity!==void 0&&i.minQuantity>i.maxQuantity?o??n[0]:{type:"bid",data:{quantity:i.minQuantity,face:i.minFace}};let s=LS(e);if(s)return typeof e.total_dice=="number"&&s.quantity>e.total_dice?o??n[0]:{type:"bid",data:s}}return o||n[0]}function NS(t){let e=MS(t);if(!e)return;let n=Va(e,"min_quantity"),r=Va(e,"min_face");if(!(n===void 0||r===void 0))return{minQuantity:n,minFace:r,maxQuantity:Va(e,"max_quantity")}}function LS(t){let e=t.current_bid;if(!e)return typeof t.total_dice!="number"?void 0:{quantity:1,face:1};if(!(typeof e.quantity!="number"||typeof e.face!="number"))return e.face<6?{quantity:e.quantity,face:e.face+1}:{quantity:e.quantity+1,face:1}}function MS(t){return t!==null&&typeof t=="object"?t:void 0}function Va(t,e){let n=t[e];return typeof n=="number"?n:void 0}var jS=["income","foreign_aid","coup","tax","steal","assassinate","exchange"],DS=["pass","challenge"],FS=["pass","block"],BS=["lose_card"],US=["return_cards"];function za(t){let{publicState:e,legalActions:n}=t;if(n.length===0)throw new Error("Coup fallback requires at least one legal action");switch(e.phase){case"action":return qr(n,jS);case"challenge_action":case"challenge_block":return qr(n,DS);case"block":return qr(n,FS);case"lose_influence":return qr(n,BS);case"exchange_return":return qr(n,US);case"done":throw new Error("Coup fallback should not run when phase is done");default:return n[0]}}function qr(t,e){for(let n of e){let r=t.find(o=>o.type===n);if(r)return r}return t[0]}var qS=/^```(?:json)?\s*\n?([\s\S]*?)\n?```\s*$/;function Ja(t,e,n=500){let r=t.trim(),o=VS(r),i;try{i=JSON.parse(o)}catch{return dn("json_parse",r,n)}if(!ni(i))return dn("missing_fields",r,n);let s=i.action;if(typeof s!="string")return dn("missing_fields",r,n);let a=typeof i.summary=="string"?i.summary:void 0,c=i.data;if(c!=null&&!ni(c))return dn("missing_fields",r,n);let l=ni(c)?c:void 0;if(!HS.has(s))return dn("unknown_action_type",r,n);let u=e.find(d=>d.type===s);if(!u)return dn("action_not_legal",r,n);if(s==="raise"){let d=GS(u,l);return d?a!==void 0?{kind:"ok",action:d,summary:a}:{kind:"ok",action:d}:dn("data_validation",r,n)}return a!==void 0?{kind:"ok",action:u,summary:a}:{kind:"ok",action:u}}var HS=new Set(["fold","check","call","raise","allin"]);function GS(t,e){if(!e)return;let n=e.amount;if(typeof n!="number"||!Number.isFinite(n))return;let r=ni(t.data)?t.data:void 0,o=Ka(r,"amount"),i=Ka(r,"min")??o,s=Ka(r,"max")??o;if(!(i!==void 0&&n<i)&&!(s!==void 0&&n>s))return{type:"raise",data:{amount:n}}}function VS(t){let e=t.match(qS);return e?e[1].trim():t}function ni(t){return t!==null&&typeof t=="object"&&!Array.isArray(t)}function Ka(t,e){if(!t)return;let n=t[e];return typeof n=="number"&&Number.isFinite(n)?n:void 0}function dn(t,e,n){return{kind:"invalid",reason:t,rawSnippet:e.length>n?e.slice(0,n):e}}var WS=/^```(?:json)?\s*\n?([\s\S]*?)\n?```\s*$/;function Qa(t,e,n=500){let r=t.trim(),o=JS(r),i;try{i=JSON.parse(o)}catch{return fn("json_parse",r,n)}if(!ri(i))return fn("missing_fields",r,n);let s=i.action;if(typeof s!="string")return fn("missing_fields",r,n);let a=typeof i.summary=="string"?i.summary:void 0,c=i.data;if(c!=null&&!ri(c))return fn("missing_fields",r,n);let l=ri(c)?c:void 0;if(!zS.has(s))return fn("unknown_action_type",r,n);let u=e.find(d=>d.type===s);if(!u)return fn("action_not_legal",r,n);if(s==="bid"){let d=KS(u,l);return d?a!==void 0?{kind:"ok",action:d,summary:a}:{kind:"ok",action:d}:fn("data_validation",r,n)}return a!==void 0?{kind:"ok",action:u,summary:a}:{kind:"ok",action:u}}var zS=new Set(["bid","challenge"]);function KS(t,e){if(!e)return;let n=e.quantity,r=e.face;if(typeof n!="number"||!Number.isFinite(n)||!Number.isInteger(n)||typeof r!="number"||!Number.isFinite(r)||!Number.isInteger(r)||r<1||r>6||n<1)return;let o=ri(t.data)?t.data:void 0,i=Ya(o,"min_quantity"),s=Ya(o,"min_face"),a=Ya(o,"max_quantity");if(!(i!==void 0&&n<i)&&!(a!==void 0&&n>a)&&!(i!==void 0&&s!==void 0&&n===i&&r<s))return{type:"bid",data:{quantity:n,face:r}}}function JS(t){let e=t.match(WS);return e?e[1].trim():t}function ri(t){return t!==null&&typeof t=="object"&&!Array.isArray(t)}function Ya(t,e){if(!t)return;let n=t[e];return typeof n=="number"&&Number.isFinite(n)?n:void 0}function fn(t,e,n){return{kind:"invalid",reason:t,rawSnippet:e.length>n?e.slice(0,n):e}}var YS=/^```(?:json)?\s*\n?([\s\S]*?)\n?```\s*$/,QS=new Set(["income","foreign_aid","coup","tax","assassinate","steal","exchange","challenge","pass","block","lose_card","return_cards"]);function Xa(t,e,n=500){let r=t.trim(),o=ZS(r),i;try{i=JSON.parse(o)}catch{return mn("json_parse",r,n)}if(!Kn(i))return mn("missing_fields",r,n);let s=i.action;if(typeof s!="string")return mn("missing_fields",r,n);let a=typeof i.summary=="string"?i.summary:void 0,c=i.data;if(c!=null&&!Kn(c))return mn("missing_fields",r,n);let l=Kn(c)?c:void 0;if(!QS.has(s))return mn("unknown_action_type",r,n);let u=e.filter(h=>h.type===s);if(u.length===0)return mn("action_not_legal",r,n);let d=XS(s,u,l);return d?a!==void 0?{kind:"ok",action:d,summary:a}:{kind:"ok",action:d}:mn("data_validation",r,n)}function XS(t,e,n){switch(t){case"coup":case"assassinate":case"steal":{let r=n?.target;return typeof r!="string"?void 0:e.find(o=>Vf(o.data,"target")===r)}case"block":{let r=n?.role;return typeof r!="string"?void 0:e.find(o=>Vf(o.data,"role")===r)}case"lose_card":{let r=n?.card_index;return typeof r!="number"||!Number.isFinite(r)||!Number.isInteger(r)?void 0:e.find(o=>e0(o.data,"card_index")===r)}case"return_cards":{let r=n?.return_indices;return!Array.isArray(r)||!r.every(o=>typeof o=="number"&&Number.isFinite(o)&&Number.isInteger(o))?void 0:e.find(o=>{let i=t0(o.data,"return_indices");return i!==void 0&&n0(i,r)})}default:return e[0]}}function ZS(t){let e=t.match(YS);return e?e[1].trim():t}function Kn(t){return t!==null&&typeof t=="object"&&!Array.isArray(t)}function Vf(t,e){if(!Kn(t))return;let n=t[e];return typeof n=="string"?n:void 0}function e0(t,e){if(!Kn(t))return;let n=t[e];return typeof n=="number"&&Number.isFinite(n)?n:void 0}function t0(t,e){if(!Kn(t))return;let n=t[e];if(Array.isArray(n)&&n.every(r=>typeof r=="number"&&Number.isFinite(r)))return n}function n0(t,e){if(t.length!==e.length)return!1;for(let n=0;n<t.length;n++)if(t[n]!==e[n])return!1;return!0}function mn(t,e,n){return{kind:"invalid",reason:t,rawSnippet:e.length>n?e.slice(0,n):e}}var se="0.1.0-alpha.6",Xf="v1.0.0";function Zf(){let t=ir(),e=qt(),n=wi();return{ok:!0,runtimeVersion:se,schemaCount:e.size,messageTypeCount:n.length,schemasRoot:t}}async function Za(t,e){return W(t,0,0,"usage: aifight version"),t.jsonMode?e.stdout(JSON.stringify({version:se})+`
68
68
  `):e.stdout(`${se}
69
69
  `),0}import Hr from"node:fs";import i0 from"node:path";var Ge=class extends Error{name="RuntimeLocalUrlError"};function Jn(t){switch(t){case"openclaw":return"http://127.0.0.1:18789";case"hermes":return"http://127.0.0.1:8642";case"mock":return"mock://local"}}function Gr(t,e){let n=t.trim();if(e==="mock"&&n==="mock://local")return n;let r;try{r=new URL(n)}catch{throw new Ge("runtime URL must be a valid localhost HTTP URL")}if(r.protocol!=="http:"&&r.protocol!=="https:")throw new Ge("runtime URL must use http:// or https://");if(!l0(r.hostname))throw new Ge("runtime URL must point to localhost, 127.0.0.1, or [::1]");if(r.username!==""||r.password!=="")throw new Ge("runtime URL must not include credentials");if(r.pathname!==""&&r.pathname!=="/"||r.search!==""||r.hash!=="")throw new Ge("runtime URL must be a base URL without path, query, or fragment");return r.pathname="",r.search="",r.hash="",r.toString().replace(/\/$/,"")}function jt(t){switch(t){case"openclaw":return"openclaw/default";case"hermes":return"hermes-agent";case"mock":return"mock"}}function tc(){return i0.join(oe(),"bridge.json")}function em(){Hr.rmSync(tc(),{force:!0})}function pn(t){at();let e=tc(),n=`${e}.tmp`;if(Hr.writeFileSync(n,JSON.stringify(t,null,2)+`
70
70
  `,{mode:384}),Hr.renameSync(n,e),process.platform!=="win32")try{Hr.chmodSync(e,384)}catch{}}function ne(){let t=tc(),e;try{e=Hr.readFileSync(t,"utf8")}catch(r){throw r.code==="ENOENT"?new Error("bridge is not configured; run `aifight register` for a new agent or `aifight connect <PAIRING_CODE>` for an existing agent"):r}let n=JSON.parse(e);if(!a0(n))throw new Error("bridge config is invalid; run connect again");return n}function Dt(t){return{...t,apiKey:ec(t.apiKey),...t.claimUrl!==void 0?{claimUrl:s0(t.claimUrl)}:{},...t.claimToken!==void 0?{claimToken:ec(t.claimToken)}:{},...t.runtimeLocalToken!==void 0?{runtimeLocalToken:ec(t.runtimeLocalToken)}:{}}}function ec(t){return t.length<=8?"***":`${t.slice(0,4)}...${t.slice(-4)}`}function s0(t){try{let e=new URL(t),n=e.pathname.split("/"),r=n.at(-1);return r&&r.length>0&&(n[n.length-1]="<redacted>",e.pathname=n.join("/")),e.toString()}catch{return"<redacted>"}}function a0(t){if(!t||typeof t!="object")return!1;let e=t;return e.version===1&&typeof e.baseUrl=="string"&&typeof e.wsUrl=="string"&&typeof e.agentId=="string"&&typeof e.agentName=="string"&&(e.suggestedName===void 0||typeof e.suggestedName=="string")&&typeof e.apiKey=="string"&&(e.claimUrl===void 0||typeof e.claimUrl=="string")&&(e.claimToken===void 0||typeof e.claimToken=="string")&&(e.runtimeType==="openclaw"||e.runtimeType==="hermes"||e.runtimeType==="mock")&&typeof e.runtimeLocalUrl=="string"&&c0(e.runtimeLocalUrl,e.runtimeType)&&typeof e.updatedAt=="string"&&(e.runtimeLocalToken===void 0||typeof e.runtimeLocalToken=="string")&&(e.runtimeModel===void 0||typeof e.runtimeModel=="string")&&(e.autoDailyLimit===void 0||typeof e.autoDailyLimit=="number"&&Number.isInteger(e.autoDailyLimit)&&e.autoDailyLimit>=0)&&(e.autoGames===void 0||Array.isArray(e.autoGames)&&e.autoGames.every(n=>typeof n=="string"))}function c0(t,e){if(e!=="openclaw"&&e!=="hermes"&&e!=="mock")return!1;try{return Gr(t,e),!0}catch{return!1}}function l0(t){let e=t.toLowerCase();return e==="localhost"||e==="127.0.0.1"||e==="::1"||e==="[::1]"}var u0="npm install -g @aifight/aifight@alpha";async function je(t){let e=t.fetchImpl??globalThis.fetch,n=t.timeoutMs??1500,r=new AbortController,o=setTimeout(()=>r.abort(),n);try{let i=await e(`${f0(t.baseUrl)}/api/bridge/version`,{method:"GET",signal:r.signal});if(!i.ok)return nc(t.currentVersion,`version check returned HTTP ${i.status}`);let s=await i.json().catch(()=>{}),a=m0(s);return a===null?nc(t.currentVersion,"version check returned invalid policy"):d0(t.currentVersion,a)}catch(i){let s=i?.name;return nc(t.currentVersion,s==="AbortError"?"version check timed out":"version check unavailable")}finally{clearTimeout(o)}}function d0(t,e){let n=tm(t,e.minimumSupportedVersion);if(n!==null&&n<0)return{status:"unsupported",currentVersion:t,policy:e,message:`Bridge ${t} is below the minimum supported version ${e.minimumSupportedVersion}. Update before joining matches.`};let r=tm(t,e.recommendedVersion);return r!==null&&r<0?{status:"update_recommended",currentVersion:t,policy:e,message:`Bridge ${t} works, but ${e.recommendedVersion} is recommended.`}:n===null||r===null?{status:"unknown",currentVersion:t,policy:e,message:"Bridge version could not be compared with the platform policy."}:{status:"current",currentVersion:t,policy:e,message:`Bridge ${t} is current enough for AIFight.`}}function nc(t,e){return{status:"unknown",currentVersion:t,message:e}}function f0(t){return t.replace(/\/+$/,"")}function m0(t){if(!t||typeof t!="object")return null;let e=t,n=e.minimum_supported_version,r=e.recommended_version,o=e.latest_version;return typeof n!="string"||typeof r!="string"||typeof o!="string"?null:{minimumSupportedVersion:n,recommendedVersion:r,latestVersion:o,updateCommand:typeof e.update_command=="string"&&e.update_command.trim()!==""?e.update_command:u0,...typeof e.release_notes_url=="string"?{releaseNotesUrl:e.release_notes_url}:{},...typeof e.policy=="string"?{policy:e.policy}:{}}}function tm(t,e){let n=nm(t),r=nm(e);if(n===null||r===null)return null;for(let o of["major","minor","patch"])if(n[o]!==r[o])return n[o]>r[o]?1:-1;return p0(n.prerelease,r.prerelease)}function nm(t){let e=t.trim().replace(/^v/,"").match(/^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/);return e===null?null:{major:Number.parseInt(e[1],10),minor:Number.parseInt(e[2],10),patch:Number.parseInt(e[3],10),prerelease:e[4]===void 0?[]:e[4].split(".")}}function p0(t,e){if(t.length===0&&e.length===0)return 0;if(t.length===0)return 1;if(e.length===0)return-1;let n=Math.max(t.length,e.length);for(let r=0;r<n;r++){let o=t[r],i=e[r];if(o===void 0)return-1;if(i===void 0)return 1;if(o===i)continue;let s=/^\d+$/.test(o)?Number.parseInt(o,10):null,a=/^\d+$/.test(i)?Number.parseInt(i,10):null;return s!==null&&a!==null?s>a?1:-1:s!==null?-1:a!==null||o>i?1:-1}return 0}var h0=1500;async function rm(t,e){W(t,0,0,"usage: aifight doctor");let n;try{n=(e.hello??Zf)()}catch(i){return t.jsonMode?e.stderr(JSON.stringify({error:{code:"client_doctor_schema",message:i.message}})+`
@@ -207,7 +207,7 @@ ${t.stderr}`)}function B0(t){return t==="openclaw"?"`openclaw gateway restart --
207
207
  `));try{await Dc(e).post(`/v1/agents/${encodeURIComponent(n.agentName)}/join`,{game:r.game,mode:"ranked",one_shot:!0,count:r.count})}catch(i){throw i instanceof pe?new U(wE(i),vE(i),{hint:await bE(e)}):i}if(t.jsonMode)e.stdout(JSON.stringify({status:"queued",agent:n.agentName,game:r.game,count:r.count,mode:"ranked",manual:!0})+`
208
208
  `);else{let i=r.count===1?"match":"matches";e.stdout(`Requested ${r.count} manual ranked ${SE(r.game)} ${i} for ${n.agentName}.
209
209
  `),e.stdout(`The running Bridge will keep your Agent online and handle the match when AIFight pairs it.
210
- `)}return 0}function yE(){try{return ne()}catch(t){throw(t instanceof Error?t.message:String(t)).includes("bridge is not configured")?new U("bridge_not_configured","AIFight Bridge is not configured.",{hint:"Run `aifight register` for a new agent, or `aifight connect <PAIRING_CODE>` for an existing agent. Then install `aifight.service` before requesting manual matches."}):t}}function _E(t,e){if(t.length===0)return{game:xm(e.autoGames),count:1};let n=t[0];if(t.length===1){let i=Tm(n);if(i!==null)return{game:xm(e.autoGames),count:i};if(ct(n))return{game:n,count:1};throw new O(`unsupported game or count '${n}'`,ci)}let r=t[1];if(!ct(n))throw new O(`unsupported game '${n}'`,ci);let o=Tm(r);if(o===null)throw new O(`N must be an integer between 1 and ${mc}`,ci);return{game:n,count:o}}function Tm(t){if(!/^\d+$/.test(t))return null;let e=Number.parseInt(t,10);return!Number.isInteger(e)||e<1||e>mc?null:e}function xm(t){let e=(t??he).filter(ct),n=e.length>0?e:he;return n[Math.floor(Math.random()*n.length)]}function wE(t){return t.kind==="daemon_unreachable"?"bridge_not_running":t.kind==="runtime_files_corrupt"?"bridge_runtime_files_invalid":t.kind==="auth_failed"?"bridge_control_auth_failed":t.kind==="request_timeout"?"bridge_control_timeout":"bridge_control_failed"}function vE(t){return t.kind==="daemon_unreachable"?"AIFight Bridge is not running.":t.kind==="runtime_files_corrupt"?"AIFight Bridge runtime files are invalid.":t.kind==="auth_failed"?"AIFight Bridge rejected the local control token.":t.kind==="request_timeout"?"AIFight Bridge did not answer the local control request in time.":t.message}async function bE(t){try{let e=await St(t.bridgeService);if(e.installed&&e.running===!1)return"Start it with `aifight service start`, then run this command again.";if(e.installed&&e.running===!0)return"The service appears to be running, but its local control API did not answer. Try `aifight service restart` when no match is in progress."}catch(e){if(!(e instanceof Q))throw e}return"Install the background service with `aifight service install`, or self-manage `aifight run` as an advanced path."}function SE(t){switch(t){case"texas_holdem":return"Texas Hold'em";case"liars_dice":return"Liar's Dice";case"coup":return"Coup"}}import Bt from"node:path";import te from"node:fs";import EE from"node:crypto";var _e=class extends Error{name="RuntimeFilesWriteError";kind;filePath;heldByPid;cause;constructor(e,n,r,o){super(r),this.kind=e,this.filePath=n,o?.heldByPid!==void 0&&(this.heldByPid=o.heldByPid),o?.cause!==void 0&&(this.cause=o.cause)}};function Om(){return Bt.join(oe(),"token")}function Nm(){return Bt.join(oe(),"port")}function hc(){return Bt.join(oe(),"pid")}function kE(){return Bt.join(oe(),"lock")}var Im=0,$E=/^[0-9a-f]{64}$/;function gc(t,e,n){let r=Bt.dirname(t),o=Bt.basename(t);Im+=1;let i=Bt.join(r,`${o}.${process.pid}.${Im}.tmp`),s;try{if(s=te.openSync(i,"w",n),te.writeSync(s,e),te.closeSync(s),s=void 0,process.platform!=="win32")try{te.chmodSync(i,n)}catch{}te.renameSync(i,t)}catch(a){if(s!==void 0)try{te.closeSync(s)}catch{}try{te.unlinkSync(i)}catch{}throw new _e("write_failed",t,`failed to write ${t}: ${a.message}`,{cause:a})}}function Lm(){return EE.randomBytes(32).toString("hex")}function Mm(t){let e=Om();if(!$E.test(t))throw new _e("write_failed",e,`token must match /^[0-9a-f]{64}$/ but received "${t}" (length ${t.length})`);gc(e,t,384)}function jm(t){let e=Nm();if(!Number.isInteger(t)||t<1||t>65535)throw new _e("write_failed",e,`port must be an integer in [1, 65535] but received ${t}`);gc(e,String(t),420)}function Dm(t){let e=hc();if(!Number.isInteger(t)||t<1)throw new _e("write_failed",e,`pid must be a positive integer but received ${t}`);gc(e,String(t),420)}function yc(t){for(let e of[Om(),Nm(),hc()])try{te.unlinkSync(e)}catch(n){if(n.code==="ENOENT")continue;t.onLog?.(`failed to unlink ${e}: ${n.message}`)}}function Fm(){let t=oe(),e;try{e=te.readdirSync(t)}catch{return}for(let n of e)if(n.endsWith(".tmp"))try{te.unlinkSync(Bt.join(t,n))}catch{}}var pc=new Set;function RE(t){try{return process.kill(t,0),!0}catch(e){return e.code!=="ESRCH"}}function PE(t){let e;try{e=te.readFileSync(t,"utf8")}catch(o){return o.code==="ENOENT"?{kind:"missing"}:{kind:"read_error",cause:o}}let n=e.trim();if(n.length===0)return{kind:"invalid",raw:n};if(!/^\d+$/.test(n))return{kind:"invalid",raw:n};let r=Number.parseInt(n,10);return!Number.isFinite(r)||r<1?{kind:"invalid",raw:n}:{kind:"valid",pid:r}}function Bm(t){let e=kE(),n=hc(),r=t?.processIsAlive??RE;if(pc.has(e))throw new _e("lock_acquire_failed",e,`lock at ${e} already held by this process; release the existing handle first (reentrancy guard)`);for(let o=0;o<2;o+=1)try{let i=te.openSync(e,te.constants.O_WRONLY|te.constants.O_CREAT|te.constants.O_EXCL,384);if(te.closeSync(i),process.platform!=="win32")try{te.chmodSync(e,384)}catch{}return pc.add(e),AE(e)}catch(i){if(i.code!=="EEXIST")throw new _e("lock_acquire_failed",e,`failed to acquire lock at ${e}: ${i.message}`,{cause:i});let a=PE(n);if(a.kind==="missing")throw new _e("lock_acquire_failed",e,`lock at ${e} exists but pid file ${n} is missing \u2014 ambiguous (possibly a racing daemon between acquireDaemonLock and writePid); refusing to steal lock. If the previous daemon truly crashed, manually remove ${e}.`);if(a.kind==="invalid")throw new _e("lock_acquire_failed",e,`lock at ${e} exists but pid file ${n} content is invalid (raw="${a.raw}") \u2014 ambiguous; refusing to steal lock. Manually remove both files if you confirm no daemon is running.`);if(a.kind==="read_error")throw new _e("lock_acquire_failed",e,`lock at ${e} exists but pid file ${n} could not be read (${a.cause.code??"unknown"}: ${a.cause.message}) \u2014 ambiguous; refusing to steal lock.`,{cause:a.cause});if(r(a.pid))throw new _e("lock_held_by_other",e,`lock at ${e} held by live PID ${a.pid}`,{heldByPid:a.pid});try{te.unlinkSync(e)}catch{}try{te.unlinkSync(n)}catch{}}throw new _e("lock_acquire_failed",e,`failed to acquire lock at ${e} after stale-cleanup retry; another daemon may be racing`)}function AE(t){let e=!1;return{release(){if(!e){e=!0,pc.delete(t);try{te.unlinkSync(t)}catch{}}}}}import*as Wm from"node:http";import{Buffer as vc}from"node:buffer";import*as zm from"node:crypto";var _n=class extends Error{name="ControlServerError";kind;cause;constructor(e,n,r){super(n),this.kind=e,this.cause=r}};var Km="0.1.0-alpha.5",Um=`aifight-runtime/${Km}`,TE="127.0.0.1",xE=0,CE=1048576,IE=5e3,B=class extends Error{name="HttpError";status;code;details;constructor(e,n,r,o){super(r),this.status=e,this.code=n,this.details=o}};function Jm(t){return t.split("/").filter(e=>e.length>0)}function Te(t){let e=Jm(t).map(n=>n.startsWith(":")?{param:n.slice(1)}:{literal:n});return{raw:t,segments:e}}function OE(t,e){if(t.segments.length!==e.length)return null;let n={};for(let r=0;r<t.segments.length;r++){let o=t.segments[r],i=e[r];if(o.literal!==void 0){if(o.literal!==i)return null}else if(o.param!==void 0)try{n[o.param]=decodeURIComponent(i)}catch{return null}}return n}async function qm(t,e){if(((t.headers["content-type"]??"").toString().split(";")[0]?.trim().toLowerCase()??"")!=="application/json")throw new B(415,"unsupported_media_type","Content-Type must be application/json");let o=[],i=0,s=!1;for await(let c of t){if(s)continue;let l=c;if(i+=l.length,i>e)throw s=!0,new B(413,"payload_too_large",`request body exceeds ${e} bytes`);o.push(l)}let a=vc.concat(o).toString("utf8");if(a.length===0)throw new B(400,"bad_request","request body required");try{return JSON.parse(a)}catch(c){throw new B(400,"bad_request",`invalid JSON: ${c instanceof Error?c.message:String(c)}`)}}function Hm(t,e,n){if(typeof t!="object"||t===null||Array.isArray(t))throw new B(400,"bad_request",`${n} body must be a JSON object`,{missing_fields:[...e]});let r=t,o=e.filter(i=>!Object.prototype.hasOwnProperty.call(r,i));if(o.length>0)throw new B(400,"bad_request",`missing required fields: ${o.join(", ")}`,{missing_fields:o})}function _c(t){return typeof t=="object"&&t!==null&&"kind"in t&&t.kind==="router_agent_not_found"}function Gm(t){if(typeof t!="object"||t===null||!("kind"in t))return null;let e=t.kind,n=t instanceof Error?t.message:"schedule operation failed";return e==="invalid_timezone"||e==="invalid_count"||e==="invalid_min_interval"?new B(400,"bad_request",n,{validation:e}):e==="invalid_state"?new B(503,"service_unavailable","scheduler stopped"):null}function Vm(t){if(t.state===null)return{name:t.name,started:t.started,stopped:t.stopped,transport:t.transport,state:null};let e=t.state,n={phase:e.phase,agentId:e.agentId,agentName:e.agentName,availableGames:e.availableGames,autoConfirmMatches:e.autoConfirmMatches,...e.queue!==void 0?{queue:e.queue}:{},...e.activeMatch!==void 0?{activeMatch:e.activeMatch}:{}};return{name:t.name,started:t.started,stopped:t.stopped,transport:t.transport,state:n}}function NE(t){let e=t.lastAttempt===null?null:{atMs:t.lastAttempt.atMs,game:t.lastAttempt.game,outcome:t.lastAttempt.outcome};return{running:t.running,today:t.today,remaining:t.remaining,nextFireInMs:t.nextFireInMs,lastAttempt:e}}function Ym(t){let e=t.host??TE,n=t.port??xE,r=t.bodyLimitBytes??CE,o=t.clock??{now:()=>Date.now()},i=o.now(),s=[{method:"GET",pattern:Te("/v1/health"),handler:h},{method:"GET",pattern:Te("/v1/agents"),handler:y},{method:"GET",pattern:Te("/v1/agents/:name/status"),handler:v},{method:"POST",pattern:Te("/v1/agents/:name/join"),handler:S},{method:"POST",pattern:Te("/v1/agents/:name/leave"),handler:R},{method:"GET",pattern:Te("/v1/agents/:name/schedule"),handler:$},{method:"POST",pattern:Te("/v1/agents/:name/schedule"),handler:K},{method:"POST",pattern:Te("/v1/agents/:name/schedule/pause"),handler:X},{method:"POST",pattern:Te("/v1/agents/:name/schedule/resume"),handler:ae},{method:"POST",pattern:Te("/v1/shutdown"),handler:st},{method:"POST",pattern:Te("/v1/agents"),handler:p("M1-18")},{method:"DELETE",pattern:Te("/v1/agents/:name"),handler:p("M1-18")},{method:"POST",pattern:Te("/v1/agents/:name/setup"),handler:p("M1-18")}],a=new Map;function c(w){if(t.onLog)try{t.onLog(w)}catch{}}function l(w){let E=w.headers.authorization;if(!E)return{ok:!1,reason:"missing_header"};if(!E.startsWith("Bearer "))return{ok:!1,reason:"invalid_format"};let x=E.slice(7),k=t.tokenSource();if(k===null)return{ok:!1,reason:"token_unset"};let j=vc.from(x,"utf8"),Z=vc.from(k,"utf8");return j.length!==Z.length?{ok:!1,reason:"token_mismatch"}:zm.timingSafeEqual(j,Z)?{ok:!0}:{ok:!1,reason:"token_mismatch"}}function u(w,E,x){w.headersSent||(w.setHeader("Content-Type","application/json; charset=utf-8"),w.setHeader("Server",Um),w.statusCode=E,w.end(JSON.stringify(x)))}function d(w,E,x,k,j){u(w,E,j===void 0?{error:{code:x,message:k}}:{error:{code:x,message:k,details:j}})}function h(w){u(w.res,200,{status:"ok",version:Km,uptimeMs:o.now()-i})}function p(w){return E=>{let x=E.url.pathname;throw new B(501,"not_implemented",`${x} deferred to ${w} daemon lifecycle wiring`,{retry_after_milestone:w})}}function f(w){let E=t.schedulerLookup?.(w)??null;if(!E)throw new B(404,"not_found",`agent '${w}' has no scheduler`);return E}function m(w){return a.has(w)?a.get(w)??null:t.scheduleConfigLookup?.(w)??null}function g(w){w.headersSent||(w.setHeader("Server",Um),w.statusCode=204,w.end())}function y(w){let E=t.router.listAgents().map(Vm);u(w.res,200,{agents:E})}function v(w){let E=w.params.name,x;try{x=t.router.getAgent({name:E})}catch(j){throw _c(j)?new B(404,"not_found",`agent '${E}' not found`):j}let k=x.snapshot();u(w.res,200,{agent:Vm(k)})}async function S(w){let E=w.params.name,x=await qm(w.req,r);Hm(x,["game"],"/v1/agents/:name/join");let k=x;if(typeof k.game!="string"||k.game.length===0)throw new B(400,"bad_request","field 'game' must be a non-empty string",{invalid_field:"game"});if(k.mode!==void 0&&typeof k.mode!="string")throw new B(400,"bad_request","field 'mode' must be a string when present",{invalid_field:"mode"});if(k.one_shot!==void 0&&typeof k.one_shot!="boolean")throw new B(400,"bad_request","field 'one_shot' must be a boolean when present",{invalid_field:"one_shot"});if(k.oneShot!==void 0&&typeof k.oneShot!="boolean")throw new B(400,"bad_request","field 'oneShot' must be a boolean when present",{invalid_field:"oneShot"});let j=k.count;if(j!==void 0&&(typeof j!="number"||!Number.isInteger(j)||j<1||j>20))throw new B(400,"bad_request","field 'count' must be an integer between 1 and 20 when present",{invalid_field:"count"});let Z=k.one_shot??k.oneShot;try{t.router.joinQueue({name:E},k.game,k.mode,{...Z!==void 0?{oneShot:Z}:{},...typeof j=="number"?{count:j}:{}})}catch(J){throw _c(J)?new B(404,"not_found",`agent '${E}' not found`):J}g(w.res)}function R(w){let E=w.params.name;try{t.router.leaveQueue({name:E})}catch(x){throw _c(x)?new B(404,"not_found",`agent '${E}' not found`):x}g(w.res)}function $(w){let E=w.params.name,x=f(E),k=m(E),j=NE(x.snapshot());u(w.res,200,{schedule:k,snapshot:j})}async function K(w){let E=w.params.name,x=f(E),k=await qm(w.req,r),j;if(k===null)j=null;else{Hm(k,["enabled","timezone","days"],"/v1/agents/:name/schedule");let Z=k;if(typeof Z.enabled!="boolean")throw new B(400,"bad_request","field 'enabled' must be a boolean",{invalid_field:"enabled"});if(typeof Z.timezone!="string")throw new B(400,"bad_request","field 'timezone' must be a string",{invalid_field:"timezone"});if(typeof Z.days!="object"||Z.days===null||Array.isArray(Z.days))throw new B(400,"bad_request","field 'days' must be an object",{invalid_field:"days"});j=k}try{x.setSchedule(j)}catch(Z){let J=Gm(Z);throw J||Z}a.set(E,j),g(w.res)}function X(w){Ke(w,!1)}function ae(w){Ke(w,!0)}function Ke(w,E){let x=w.params.name,k=f(x),j=m(x);if(j===null){let J=E?"resume":"pause";throw new B(400,"bad_request",`no schedule to ${J}; POST /schedule first or configure initial schedule`)}let Z={...j,enabled:E};try{k.setSchedule(Z)}catch(J){let to=Gm(J);throw to||J}a.set(x,Z),g(w.res)}function st(w){c({level:"info",code:"shutdown_requested",message:"shutdown requested via POST /v1/shutdown",method:"POST",path:"/v1/shutdown"}),u(w.res,200,{status:"shutting_down"}),setImmediate(()=>{Promise.resolve().then(()=>t.onShutdown?.()).catch(E=>{c({level:"error",code:"handler_threw",message:`onShutdown threw/rejected: ${wc(E)}`,cause:E,method:"POST",path:"/v1/shutdown"})})})}async function nr(w,E){let x=o.now(),k=w.method??"GET",j=w.url??"/",Z=`http://${w.headers.host??"localhost"}`,J;try{J=new URL(j,Z)}catch{d(E,400,"bad_request","invalid request URL"),c({level:"info",code:"request_completed",message:`${k} ${j} -> 400 (${o.now()-x}ms)`,method:k,path:j,status:400,durationMs:o.now()-x});return}let to=Jm(J.pathname),rr=0;try{let Ee=l(w);if(!Ee.ok)throw c({level:"warn",code:"auth_failed",message:`${k} ${J.pathname}: auth failed (${Ee.reason})`,method:k,path:J.pathname,reason:Ee.reason}),new B(401,"unauthorized",`authentication required: ${Ee.reason}`);let gi=s.map(Et=>({route:Et,params:OE(Et.pattern,to)})).filter(Et=>Et.params!==null);if(gi.length===0)throw new B(404,"not_found","path not found");let yi=gi.find(Et=>Et.route.method===k);if(!yi){let Et=gi.map(_i=>_i.route.method).filter((_i,Ep,kp)=>kp.indexOf(_i)===Ep).join(", ");throw E.headersSent||E.setHeader("Allow",Et),new B(405,"method_not_allowed",`method ${k} not allowed`)}c({level:"info",code:"request_received",message:`${k} ${J.pathname}`,method:k,path:J.pathname}),await yi.route.handler({req:w,res:E,url:J,params:yi.params}),rr=E.statusCode}catch(Ee){Ee instanceof B?(d(E,Ee.status,Ee.code,Ee.message,Ee.details),rr=Ee.status):(c({level:"error",code:"handler_threw",message:`handler threw on ${k} ${J.pathname}: ${wc(Ee)}`,method:k,path:J.pathname,cause:Ee}),d(E,500,"internal_error","internal server error"),rr=500)}finally{w.complete||(w.on("data",()=>{}),w.on("error",()=>{})),c({level:"info",code:"request_completed",message:`${k} ${J.pathname} -> ${rr} (${o.now()-x}ms)`,method:k,path:J.pathname,status:rr,durationMs:o.now()-x})}}let Je=Wm.createServer((w,E)=>{nr(w,E).catch(x=>{if(c({level:"error",code:"handler_threw",message:`dispatch escaped: ${wc(x)}`,method:w.method,path:w.url,cause:x}),!E.headersSent)try{d(E,500,"internal_error","internal server error")}catch{try{E.end()}catch{}}})}),re="pre-listen",Ut=null,wn=null,eo=null;function vp(){return re==="listening"?Promise.reject(new _n("invalid_state","server already listening")):re==="closing"||re==="closed"||re==="bind-failed"?Promise.reject(new _n("invalid_state","server has been closed; create a new ControlServer")):new Promise((w,E)=>{let x=k=>{re="bind-failed",E(new _n("bind_failed",`failed to bind ${e}:${n}: ${k.message}`,k))};Je.once("error",x),Je.listen({host:e,port:n},()=>{Je.off("error",x);let k=Je.address();if(typeof k=="string"||k===null){re="bind-failed",E(new _n("bind_failed","unexpected listen address shape from server.address()"));return}Ut=k.address,wn=k.port,re="listening",c({level:"info",code:"server_listening",message:`control API server listening on ${Ut}:${wn}`,host:Ut,port:wn}),w(wn)})})}function bp(){return re!=="listening"||Ut===null||wn===null?null:{host:Ut,port:wn}}function Sp(){return re==="pre-listen"||re==="bind-failed"?(re="closed",Promise.resolve()):re==="closed"?Promise.resolve():(re==="closing"&&eo||(re="closing",eo=new Promise(w=>{let E=!1,x=()=>{E||(E=!0,clearTimeout(j),re="closed",c({level:"info",code:"server_closed",message:"control API server closed"}),w())},k=Je.closeAllConnections,j=setTimeout(()=>{if(typeof k=="function")try{k.call(Je)}catch{}x()},IE);j.unref(),Je.close(()=>x())})),eo)}return{listen:vp,address:bp,close:Sp}}function wc(t){if(t instanceof Error)return`${t.name}: ${t.message}`;if(typeof t=="string")return t;try{return JSON.stringify(t)}catch{return String(t)}}function bc(t){return{phase:"connected",transport:"connected",agentId:t.welcome.data.agent_id,agentName:t.welcome.data.agent_name,availableGames:[...t.welcome.data.games],autoConfirmMatches:t.autoConfirmMatches??!0}}function Qm(t,e){if(e.type==="start")return H(bc(e));if(t.phase==="closed")return e.type==="stop"?H(t):ze(t,"fsm.closed",`Ignoring ${e.type} because agent FSM is closed`);switch(e.type){case"command.join_queue":return LE(t,e.game,e.mode,e.oneShot);case"command.leave_queue":return ME(t);case"command.confirm_match":return jE(t,e.confirmId);case"ws.message":return DE(t,e.message,e.now);case"decision.ready":return VE(t,e.action);case"decision.failed":return WE(t,e.reason);case"reconnect.event":return YE(t,e.event);case"reconnect.close":return QE(t,e.info);case"stop":return H({...t,phase:"closed",transport:"closed"})}}function LE(t,e,n,r){if(!t.availableGames.includes(e))return ze(t,"fsm.unknown_game",`Cannot join unavailable game '${e}'`);let o={game:e,mode:Qr(n),...r===!0?{one_shot:!0}:{}};return H({...t,phase:"queuing",queue:o,pendingConfirm:void 0,activeMatch:void 0,pendingAction:void 0,lastGameOver:void 0},[{type:"send",message:{type:"join_queue",data:o}}])}function ME(t){return t.phase!=="queuing"&&t.phase!=="confirming"&&t.phase!=="matching"?ze(t,"fsm.not_queued","Ignoring leave_queue because agent is not queued"):H({...t,phase:"connected",queue:void 0,pendingConfirm:void 0},[{type:"send",message:{type:"leave_queue"}}])}function jE(t,e){let n=e??t.pendingConfirm?.confirm_id;return!n||t.phase!=="confirming"?ze(t,"fsm.no_pending_confirm","Ignoring match confirmation without a pending confirm request"):H({...t,phase:"matching",pendingConfirm:void 0},[{type:"send",message:{type:"match_confirm",data:{confirm_id:n}}}])}function DE(t,e,n){switch(e.type){case"queue_joined":return FE(t,e);case"queue_left":return H({...t,phase:"connected",queue:void 0,pendingConfirm:void 0});case"match_confirm_request":return BE(t,e);case"match_cancelled":return UE(t,e);case"game_start":return qE(t,e,n);case"game_state":return HE(t,e);case"action_request":return GE(t,e);case"game_over":return zE(t,e);case"error":return KE(t,e);case"event":return JE(t,e);default:return ze(t,"fsm.unknown_server_message",`Ignoring unknown server message '${e.type}'`)}}function FE(t,e){return H({...t,phase:"queuing",queue:{game:e.data.game,mode:Qr(e.data.mode),...e.data.one_shot===!0?{one_shot:!0}:{}}})}function BE(t,e){let n={game:e.data.game,mode:Qr(e.data.mode),...t.queue?.one_shot===!0?{one_shot:!0}:{}};return t.autoConfirmMatches?H({...t,phase:"matching",queue:n,pendingConfirm:void 0},[{type:"send",message:{type:"match_confirm",data:{confirm_id:e.data.confirm_id}}}]):H({...t,phase:"confirming",queue:n,pendingConfirm:e.data},[We("info","fsm.match_confirm_required",`Match confirmation required for ${e.data.game}/${e.data.mode}`)])}function UE(t,e){if(e.data.action==="re_queued"){let n=t.pendingConfirm?{game:t.pendingConfirm.game,mode:Qr(t.pendingConfirm.mode)}:t.queue,r=e.data.reason==="opponent_disconnected"?{game:e.data.game,mode:Qr(e.data.mode)}:n;return H({...t,phase:r?"queuing":"connected",queue:r,pendingConfirm:void 0,activeMatch:void 0,pendingAction:void 0},[We("warning","fsm.match_cancelled",`Match cancelled: ${e.data.reason}`)])}return H({...t,phase:"connected",queue:void 0,pendingConfirm:void 0,activeMatch:void 0,pendingAction:void 0},[We("warning","fsm.match_cancelled",`Match cancelled: ${e.data.reason}`)])}function qE(t,e,n){return H({...t,phase:"in_match",queue:void 0,pendingConfirm:void 0,pendingAction:void 0,activeMatch:{sessionId:e.data.match_id,game:e.data.game,startedAt:n??0}})}function HE(t,e){return t.activeMatch&&t.activeMatch.sessionId!==e.data.match_id?ze(t,"fsm.game_state_mismatch",`Ignoring game_state for session ${e.data.match_id}; active session is ${t.activeMatch.sessionId}`):H({...t,phase:t.activeMatch?"in_match":t.phase},[We("info","fsm.game_state","Received game state update")])}function GE(t,e){return t.phase!=="in_match"&&t.phase!=="deciding"?ze(t,"fsm.action_request_out_of_phase","Ignoring action_request outside an active match"):t.activeMatch&&t.activeMatch.sessionId!==e.data.match_id?ze(t,"fsm.action_request_mismatch",`Ignoring action_request for session ${e.data.match_id}; active session is ${t.activeMatch.sessionId}`):H({...t,phase:"deciding",pendingAction:e},[{type:"request_decision",actionRequest:e,matchId:e.data.match_id,game:t.activeMatch?.game}])}function VE(t,e){return t.phase!=="deciding"||!t.pendingAction?ze(t,"fsm.no_pending_action","Ignoring decision result without a pending action_request"):H({...t,phase:"in_match",pendingAction:void 0},[{type:"send",message:{type:"action",match_id:t.pendingAction.data.match_id,data:e}}])}function WE(t,e){return t.phase!=="deciding"||!t.pendingAction?ze(t,"fsm.no_pending_action","Ignoring decision failure without a pending action_request"):H(t,[{type:"fallback_required",actionRequest:t.pendingAction,reason:e}])}function zE(t,e){return t.activeMatch&&t.activeMatch.sessionId!==e.data.session_id?ze(t,"fsm.game_over_mismatch",`Ignoring game_over for session ${e.data.session_id}; active session is ${t.activeMatch.sessionId}`):H({...t,phase:"connected",queue:void 0,pendingConfirm:void 0,activeMatch:void 0,pendingAction:void 0,lastGameOver:e},[{type:"record_result",gameOver:e,...t.activeMatch?.game!==void 0?{game:t.activeMatch.game}:{}}])}function KE(t,e){let n=typeof e.data.message=="string"?e.data.message:"Server error";return H({...t,lastError:n},[We("error","server.error",n)])}function JE(t,e){return H(t,[We("info","server.event",`Received server event batch (${e.data.events.length} events)`)])}function YE(t,e){return e.type==="attempt-success"?H({...t,transport:"connected"}):e.type==="attempt-start"?H({...t,transport:"backoff"},[We("info","reconnect.attempt_start",`Reconnect attempt ${e.attempt} started`)]):e.type==="attempt-failure"?H({...t,transport:"backoff"},[We(e.severity,"reconnect.attempt_failure",`Reconnect attempt ${e.attempt} failed`)]):H({...t,phase:"closed",transport:"closed"},[We(e.severity,"reconnect.give_up","Reconnect gave up")])}function QE(t,e){return H({...t,phase:"closed",transport:"closed"},[We("error","reconnect.closed",`Reconnect closed: ${e.kind}`)])}function H(t,e=[]){return{state:t,effects:e}}function ze(t,e,n){return H(t,[We("warning",e,n)])}function We(t,e,n){return{type:"notify",level:t,code:e,message:n}}function Qr(t){return t&&t.length>0?t:"ranked"}var tr=class extends Error{cause;constructor(e,n){super(e),this.cause=n}},Xr=class extends tr{name="AgentInstanceStartError";kind="agent_start";constructor(e,n){super(e,n)}},Zr=class extends tr{name="AgentInstanceNotStartedError";kind="agent_not_started";constructor(e,n){super(e,n)}},ui=class extends tr{name="AgentInstanceStoppedError";kind="agent_stopped";constructor(e,n){super(e,n)}},Sc=class extends tr{name="AgentInstanceEffectError";kind="agent_effect";constructor(e,n){super(e,n)}},di=class{#e;#t=null;#n=null;#r=!1;#o=!1;#a=[];#c=new Set;#u=Promise.resolve();#g=0;#d=null;constructor(e){this.#e=e}async start(){if(this.#o)throw new ui(`agent '${this.#e.name}' has been stopped`);if(this.#r)throw new Xr(`agent '${this.#e.name}' is already started`);let e=this.#e.connect??Ha,n;try{n=await e(this.#e.ws)}catch(r){throw new Xr(`failed to start agent '${this.#e.name}': ${li(r)}`,r)}if(n.welcome===null)throw new Xr(`failed to start agent '${this.#e.name}': reconnect client returned without welcome`);return this.#t=n,this.#n=bc({welcome:n.welcome,autoConfirmMatches:this.#e.autoConfirmMatches,now:this.#k()}),this.#r=!0,this.#l(n),this.#f(),this.snapshot()}async stop(e="agent stop"){if(this.#o)return;this.#o=!0,this.#$();let n=this.#t;n!==null&&n.state!=="closed"&&await n.close(1e3,e),this.#n!==null&&this.#s({type:"stop",reason:e})}joinQueue(e,n,r={}){this.#w(),this.#s({type:"command.join_queue",game:e,mode:n,oneShot:r.oneShot})}leaveQueue(){this.#w(),this.#s({type:"command.leave_queue"})}confirmMatch(e){this.#w(),this.#s({type:"command.confirm_match",confirmId:e})}snapshot(){return{name:this.#e.name,state:this.#n,transport:this.#t?.state??"idle",started:this.#r,stopped:this.#o}}onState(e){return this.#c.add(e),()=>{this.#c.delete(e)}}#l(e){this.#a.push(e.onMessage(n=>{if(n.type==="readiness_check"){this.#i(n.data);return}this.#s({type:"ws.message",message:n,now:this.#k()})}),e.onReconnect(n=>{this.#s({type:"reconnect.event",event:n})}),e.onClose(n=>{this.#s({type:"reconnect.close",info:n})}),e.onError(n=>{this.#R(n)}))}async#i(e){let n=XE(e);try{let r=this.#e.onReadinessCheck?await this.#e.onReadinessCheck(e):{request_id:n,ready:!1,runtime_type:"mock",checked_at:new Date().toISOString(),detail:"readiness check handler is not configured"};this.#p({type:"runtime_status",data:ZE(r,n)})}catch(r){this.#p({type:"runtime_status",data:{request_id:n,ready:!1,runtime_type:"mock",checked_at:new Date().toISOString(),detail:Xm(`readiness check failed: ${li(r)}`)}})}}#s(e){let n=this.#S(),r=Qm(n,e);this.#n=r.state,this.#f(),this.#h(r.effects)}#h(e){e.length!==0&&(this.#u=this.#u.then(()=>this.#m(e)).catch(n=>{this.#v({level:"error",code:"agent.effect_queue",message:`Agent effect queue failed: ${li(n)}`,cause:n})}))}async#m(e){for(let n of e)await this.#y(n)}async#y(e){switch(e.type){case"send":this.#p(e.message);return;case"request_decision":await this.#_(e);return;case"fallback_required":this.#e.onFallbackRequired?.(e),this.#v({level:"warning",code:"agent.fallback_required",message:`Decision failed for match ${e.actionRequest.data.match_id}; fallback required`,cause:e.reason});return;case"record_result":this.#e.onResult?.(e.gameOver,e.game!==void 0?{game:e.game}:{});return;case"notify":this.#v(e);return}}#p(e){let n=this.#b();try{n.send(e)}catch(r){this.#v({level:"error",code:"agent.send_failed",message:`Failed to send ${e.type}: ${li(r)}`,cause:new Sc(`send ${e.type} failed`,r)})}}async#_(e){let n=++this.#g;this.#d={token:n,matchId:e.matchId};let r=this.#S();try{let o=await this.#e.decisionProvider.decide({actionRequest:e.actionRequest,matchId:e.matchId,game:e.game,state:r});if(!this.#E(n,e.matchId)){this.#v({level:"warning",code:"agent.stale_decision",message:`Ignoring stale decision for match ${e.matchId}`});return}this.#s({type:"decision.ready",action:o})}catch(o){if(!this.#E(n,e.matchId)){this.#v({level:"warning",code:"agent.stale_decision",message:`Ignoring stale decision failure for match ${e.matchId}`,cause:o});return}this.#s({type:"decision.failed",reason:o})}}#E(e,n){let r=this.#n;return this.#d?.token===e&&this.#d.matchId===n&&r?.phase==="deciding"&&r.pendingAction?.data.match_id===n}#w(){if(!this.#r||this.#n===null||this.#t===null)throw new Zr(`agent '${this.#e.name}' is not started`);if(this.#o||this.#n.phase==="closed")throw new ui(`agent '${this.#e.name}' is stopped`)}#b(){if(this.#t===null)throw new Zr(`agent '${this.#e.name}' is not started`);return this.#t}#S(){if(this.#n===null)throw new Zr(`agent '${this.#e.name}' is not started`);return this.#n}#f(){let e=this.snapshot();for(let n of[...this.#c])n(e)}#$(){let e=this.#a;this.#a=[];for(let n of e)n()}#R(e){this.#v({level:"error",code:"agent.ws_error",message:e.message,cause:e})}#v(e){this.#e.onNotify?.(e)}#k(){return this.#e.now?.()??Date.now()}};function li(t){if(t instanceof Error)return t.message;if(typeof t=="string")return t;try{return JSON.stringify(t)}catch{return String(t)}}function XE(t){if(!t||typeof t!="object")return"";let e=t.request_id;return typeof e=="string"?e:""}function ZE(t,e){let n=t&&typeof t=="object"?{...t}:{};return typeof n.request_id!="string"&&(n.request_id=e),typeof n.ready!="boolean"&&(n.ready=!1),n.runtime_type!=="openclaw"&&n.runtime_type!=="hermes"&&n.runtime_type!=="mock"&&(n.runtime_type="mock"),typeof n.checked_at!="string"&&(n.checked_at=new Date().toISOString()),typeof n.detail=="string"&&(n.detail=Xm(n.detail)),n}function Xm(t){return t.length>240?t.slice(0,240):t}function Zm(t){return{async decide(e){let n=ok(e.game),r=e.actionRequest.data,o=r.legal_actions??[];if(o.length===0)throw new Error("action_request had no legal actions");let i={game:n,matchId:e.matchId,playerId:ik(r.state),legalActions:o,publicState:r.state,timeoutMs:typeof r.timeout_ms=="number"?r.timeout_ms:0},s;try{s=await t.decide(i)}catch{try{s=await t.decide(i)}catch{return fi(n,o,r.state)}}return ek({game:n,raw:s,legalActions:o,publicState:r.state})}}}function ep(){return{name:"mock",async decide(t){return fi(t.game,t.legalActions,t.publicState)},async healthCheck(){return!0}}}function ek(t){if(typeof t.raw!="string")return rk(t.raw,t.legalActions)??fi(t.game,t.legalActions,t.publicState);let e=tk(t.game,t.raw,t.legalActions);return e!==null?e:fi(t.game,t.legalActions,t.publicState)}function tk(t,e,n){let r=nk(e),o=t==="texas_holdem"?Ja(r,n):t==="liars_dice"?Qa(r,n):Xa(r,n);return o.kind==="ok"?o.action:null}function nk(t){let e=t.trim();if(e.startsWith("{"))return e;let n=e.toLowerCase();return JSON.stringify({action:n})}function rk(t,e){let n=e.find(o=>sk(o,t));if(n)return n;let r=e.find(o=>o.type===t.type);return!t.data&&r?r:null}function fi(t,e,n){return t==="texas_holdem"?Ga({publicState:n,legalActions:e,yourPlayerId:"p0"}):t==="liars_dice"?Wa({publicState:n,legalActions:e,yourPlayerId:"p0"}):za({publicState:n,legalActions:e,yourPlayerId:"p0"})}function ok(t){if(t==="texas_holdem"||t==="liars_dice"||t==="coup")return t;throw new Error(`unsupported game: ${String(t)}`)}function ik(t){if(!t||typeof t!="object")return;let e=t.your_player_id;return typeof e=="string"?e:void 0}function sk(t,e){return JSON.stringify(t)===JSON.stringify(e)}var ak="http://127.0.0.1:18789",ck="openclaw/default";function tp(t){let e=(t.baseUrl??ak).replace(/\/+$/,""),n=t.model??ck,r=t.fetchImpl??globalThis.fetch;return{name:"openclaw",async decide(o){let i=await r(`${e}/v1/responses`,{method:"POST",headers:lk(t,o),body:JSON.stringify({model:n,input:uk(o)})});if(!i.ok)throw new Error(`OpenClaw request failed with HTTP ${i.status}`);let s=await i.text(),a=dk(s);return fk(a)},async healthCheck(){try{return(await r(`${e}/v1/responses`,{method:"POST",headers:{"Content-Type":"application/json",...t.token?{Authorization:`Bearer ${t.token}`}:{}},body:JSON.stringify({model:n,input:'health check: answer with {"action":"pass"}'})})).ok}catch{return!1}}}}function lk(t,e){return{"Content-Type":"application/json","x-openclaw-session-key":`aifight:${t.agentId}:${e.matchId}:${e.playerId??"unknown"}`,...t.token?{Authorization:`Bearer ${t.token}`}:{}}}function uk(t){return["You are an AIFight game-playing agent runtime.","Choose exactly one legal action. Return only JSON in this shape:",'{"action":"<type>","data":{},"summary":"short reason"}',"",JSON.stringify({game:t.game,match_id:t.matchId,player_id:t.playerId??null,state:t.publicState,legal_actions:t.legalActions,timeout_ms:t.timeoutMs})].join(`
210
+ `)}return 0}function yE(){try{return ne()}catch(t){throw(t instanceof Error?t.message:String(t)).includes("bridge is not configured")?new U("bridge_not_configured","AIFight Bridge is not configured.",{hint:"Run `aifight register` for a new agent, or `aifight connect <PAIRING_CODE>` for an existing agent. Then install `aifight.service` before requesting manual matches."}):t}}function _E(t,e){if(t.length===0)return{game:xm(e.autoGames),count:1};let n=t[0];if(t.length===1){let i=Tm(n);if(i!==null)return{game:xm(e.autoGames),count:i};if(ct(n))return{game:n,count:1};throw new O(`unsupported game or count '${n}'`,ci)}let r=t[1];if(!ct(n))throw new O(`unsupported game '${n}'`,ci);let o=Tm(r);if(o===null)throw new O(`N must be an integer between 1 and ${mc}`,ci);return{game:n,count:o}}function Tm(t){if(!/^\d+$/.test(t))return null;let e=Number.parseInt(t,10);return!Number.isInteger(e)||e<1||e>mc?null:e}function xm(t){let e=(t??he).filter(ct),n=e.length>0?e:he;return n[Math.floor(Math.random()*n.length)]}function wE(t){return t.kind==="daemon_unreachable"?"bridge_not_running":t.kind==="runtime_files_corrupt"?"bridge_runtime_files_invalid":t.kind==="auth_failed"?"bridge_control_auth_failed":t.kind==="request_timeout"?"bridge_control_timeout":"bridge_control_failed"}function vE(t){return t.kind==="daemon_unreachable"?"AIFight Bridge is not running.":t.kind==="runtime_files_corrupt"?"AIFight Bridge runtime files are invalid.":t.kind==="auth_failed"?"AIFight Bridge rejected the local control token.":t.kind==="request_timeout"?"AIFight Bridge did not answer the local control request in time.":t.message}async function bE(t){try{let e=await St(t.bridgeService);if(e.installed&&e.running===!1)return"Start it with `aifight service start`, then run this command again.";if(e.installed&&e.running===!0)return"The service appears to be running, but its local control API did not answer. Try `aifight service restart` when no match is in progress."}catch(e){if(!(e instanceof Q))throw e}return"Install the background service with `aifight service install`, or self-manage `aifight run` as an advanced path."}function SE(t){switch(t){case"texas_holdem":return"Texas Hold'em";case"liars_dice":return"Liar's Dice";case"coup":return"Coup"}}import Bt from"node:path";import te from"node:fs";import EE from"node:crypto";var _e=class extends Error{name="RuntimeFilesWriteError";kind;filePath;heldByPid;cause;constructor(e,n,r,o){super(r),this.kind=e,this.filePath=n,o?.heldByPid!==void 0&&(this.heldByPid=o.heldByPid),o?.cause!==void 0&&(this.cause=o.cause)}};function Om(){return Bt.join(oe(),"token")}function Nm(){return Bt.join(oe(),"port")}function hc(){return Bt.join(oe(),"pid")}function kE(){return Bt.join(oe(),"lock")}var Im=0,$E=/^[0-9a-f]{64}$/;function gc(t,e,n){let r=Bt.dirname(t),o=Bt.basename(t);Im+=1;let i=Bt.join(r,`${o}.${process.pid}.${Im}.tmp`),s;try{if(s=te.openSync(i,"w",n),te.writeSync(s,e),te.closeSync(s),s=void 0,process.platform!=="win32")try{te.chmodSync(i,n)}catch{}te.renameSync(i,t)}catch(a){if(s!==void 0)try{te.closeSync(s)}catch{}try{te.unlinkSync(i)}catch{}throw new _e("write_failed",t,`failed to write ${t}: ${a.message}`,{cause:a})}}function Lm(){return EE.randomBytes(32).toString("hex")}function Mm(t){let e=Om();if(!$E.test(t))throw new _e("write_failed",e,`token must match /^[0-9a-f]{64}$/ but received "${t}" (length ${t.length})`);gc(e,t,384)}function jm(t){let e=Nm();if(!Number.isInteger(t)||t<1||t>65535)throw new _e("write_failed",e,`port must be an integer in [1, 65535] but received ${t}`);gc(e,String(t),420)}function Dm(t){let e=hc();if(!Number.isInteger(t)||t<1)throw new _e("write_failed",e,`pid must be a positive integer but received ${t}`);gc(e,String(t),420)}function yc(t){for(let e of[Om(),Nm(),hc()])try{te.unlinkSync(e)}catch(n){if(n.code==="ENOENT")continue;t.onLog?.(`failed to unlink ${e}: ${n.message}`)}}function Fm(){let t=oe(),e;try{e=te.readdirSync(t)}catch{return}for(let n of e)if(n.endsWith(".tmp"))try{te.unlinkSync(Bt.join(t,n))}catch{}}var pc=new Set;function RE(t){try{return process.kill(t,0),!0}catch(e){return e.code!=="ESRCH"}}function PE(t){let e;try{e=te.readFileSync(t,"utf8")}catch(o){return o.code==="ENOENT"?{kind:"missing"}:{kind:"read_error",cause:o}}let n=e.trim();if(n.length===0)return{kind:"invalid",raw:n};if(!/^\d+$/.test(n))return{kind:"invalid",raw:n};let r=Number.parseInt(n,10);return!Number.isFinite(r)||r<1?{kind:"invalid",raw:n}:{kind:"valid",pid:r}}function Bm(t){let e=kE(),n=hc(),r=t?.processIsAlive??RE;if(pc.has(e))throw new _e("lock_acquire_failed",e,`lock at ${e} already held by this process; release the existing handle first (reentrancy guard)`);for(let o=0;o<2;o+=1)try{let i=te.openSync(e,te.constants.O_WRONLY|te.constants.O_CREAT|te.constants.O_EXCL,384);if(te.closeSync(i),process.platform!=="win32")try{te.chmodSync(e,384)}catch{}return pc.add(e),AE(e)}catch(i){if(i.code!=="EEXIST")throw new _e("lock_acquire_failed",e,`failed to acquire lock at ${e}: ${i.message}`,{cause:i});let a=PE(n);if(a.kind==="missing")throw new _e("lock_acquire_failed",e,`lock at ${e} exists but pid file ${n} is missing \u2014 ambiguous (possibly a racing daemon between acquireDaemonLock and writePid); refusing to steal lock. If the previous daemon truly crashed, manually remove ${e}.`);if(a.kind==="invalid")throw new _e("lock_acquire_failed",e,`lock at ${e} exists but pid file ${n} content is invalid (raw="${a.raw}") \u2014 ambiguous; refusing to steal lock. Manually remove both files if you confirm no daemon is running.`);if(a.kind==="read_error")throw new _e("lock_acquire_failed",e,`lock at ${e} exists but pid file ${n} could not be read (${a.cause.code??"unknown"}: ${a.cause.message}) \u2014 ambiguous; refusing to steal lock.`,{cause:a.cause});if(r(a.pid))throw new _e("lock_held_by_other",e,`lock at ${e} held by live PID ${a.pid}`,{heldByPid:a.pid});try{te.unlinkSync(e)}catch{}try{te.unlinkSync(n)}catch{}}throw new _e("lock_acquire_failed",e,`failed to acquire lock at ${e} after stale-cleanup retry; another daemon may be racing`)}function AE(t){let e=!1;return{release(){if(!e){e=!0,pc.delete(t);try{te.unlinkSync(t)}catch{}}}}}import*as Wm from"node:http";import{Buffer as vc}from"node:buffer";import*as zm from"node:crypto";var _n=class extends Error{name="ControlServerError";kind;cause;constructor(e,n,r){super(n),this.kind=e,this.cause=r}};var Km="0.1.0-alpha.6",Um=`aifight-runtime/${Km}`,TE="127.0.0.1",xE=0,CE=1048576,IE=5e3,B=class extends Error{name="HttpError";status;code;details;constructor(e,n,r,o){super(r),this.status=e,this.code=n,this.details=o}};function Jm(t){return t.split("/").filter(e=>e.length>0)}function Te(t){let e=Jm(t).map(n=>n.startsWith(":")?{param:n.slice(1)}:{literal:n});return{raw:t,segments:e}}function OE(t,e){if(t.segments.length!==e.length)return null;let n={};for(let r=0;r<t.segments.length;r++){let o=t.segments[r],i=e[r];if(o.literal!==void 0){if(o.literal!==i)return null}else if(o.param!==void 0)try{n[o.param]=decodeURIComponent(i)}catch{return null}}return n}async function qm(t,e){if(((t.headers["content-type"]??"").toString().split(";")[0]?.trim().toLowerCase()??"")!=="application/json")throw new B(415,"unsupported_media_type","Content-Type must be application/json");let o=[],i=0,s=!1;for await(let c of t){if(s)continue;let l=c;if(i+=l.length,i>e)throw s=!0,new B(413,"payload_too_large",`request body exceeds ${e} bytes`);o.push(l)}let a=vc.concat(o).toString("utf8");if(a.length===0)throw new B(400,"bad_request","request body required");try{return JSON.parse(a)}catch(c){throw new B(400,"bad_request",`invalid JSON: ${c instanceof Error?c.message:String(c)}`)}}function Hm(t,e,n){if(typeof t!="object"||t===null||Array.isArray(t))throw new B(400,"bad_request",`${n} body must be a JSON object`,{missing_fields:[...e]});let r=t,o=e.filter(i=>!Object.prototype.hasOwnProperty.call(r,i));if(o.length>0)throw new B(400,"bad_request",`missing required fields: ${o.join(", ")}`,{missing_fields:o})}function _c(t){return typeof t=="object"&&t!==null&&"kind"in t&&t.kind==="router_agent_not_found"}function Gm(t){if(typeof t!="object"||t===null||!("kind"in t))return null;let e=t.kind,n=t instanceof Error?t.message:"schedule operation failed";return e==="invalid_timezone"||e==="invalid_count"||e==="invalid_min_interval"?new B(400,"bad_request",n,{validation:e}):e==="invalid_state"?new B(503,"service_unavailable","scheduler stopped"):null}function Vm(t){if(t.state===null)return{name:t.name,started:t.started,stopped:t.stopped,transport:t.transport,state:null};let e=t.state,n={phase:e.phase,agentId:e.agentId,agentName:e.agentName,availableGames:e.availableGames,autoConfirmMatches:e.autoConfirmMatches,...e.queue!==void 0?{queue:e.queue}:{},...e.activeMatch!==void 0?{activeMatch:e.activeMatch}:{}};return{name:t.name,started:t.started,stopped:t.stopped,transport:t.transport,state:n}}function NE(t){let e=t.lastAttempt===null?null:{atMs:t.lastAttempt.atMs,game:t.lastAttempt.game,outcome:t.lastAttempt.outcome};return{running:t.running,today:t.today,remaining:t.remaining,nextFireInMs:t.nextFireInMs,lastAttempt:e}}function Ym(t){let e=t.host??TE,n=t.port??xE,r=t.bodyLimitBytes??CE,o=t.clock??{now:()=>Date.now()},i=o.now(),s=[{method:"GET",pattern:Te("/v1/health"),handler:h},{method:"GET",pattern:Te("/v1/agents"),handler:y},{method:"GET",pattern:Te("/v1/agents/:name/status"),handler:v},{method:"POST",pattern:Te("/v1/agents/:name/join"),handler:S},{method:"POST",pattern:Te("/v1/agents/:name/leave"),handler:R},{method:"GET",pattern:Te("/v1/agents/:name/schedule"),handler:$},{method:"POST",pattern:Te("/v1/agents/:name/schedule"),handler:K},{method:"POST",pattern:Te("/v1/agents/:name/schedule/pause"),handler:X},{method:"POST",pattern:Te("/v1/agents/:name/schedule/resume"),handler:ae},{method:"POST",pattern:Te("/v1/shutdown"),handler:st},{method:"POST",pattern:Te("/v1/agents"),handler:p("M1-18")},{method:"DELETE",pattern:Te("/v1/agents/:name"),handler:p("M1-18")},{method:"POST",pattern:Te("/v1/agents/:name/setup"),handler:p("M1-18")}],a=new Map;function c(w){if(t.onLog)try{t.onLog(w)}catch{}}function l(w){let E=w.headers.authorization;if(!E)return{ok:!1,reason:"missing_header"};if(!E.startsWith("Bearer "))return{ok:!1,reason:"invalid_format"};let x=E.slice(7),k=t.tokenSource();if(k===null)return{ok:!1,reason:"token_unset"};let j=vc.from(x,"utf8"),Z=vc.from(k,"utf8");return j.length!==Z.length?{ok:!1,reason:"token_mismatch"}:zm.timingSafeEqual(j,Z)?{ok:!0}:{ok:!1,reason:"token_mismatch"}}function u(w,E,x){w.headersSent||(w.setHeader("Content-Type","application/json; charset=utf-8"),w.setHeader("Server",Um),w.statusCode=E,w.end(JSON.stringify(x)))}function d(w,E,x,k,j){u(w,E,j===void 0?{error:{code:x,message:k}}:{error:{code:x,message:k,details:j}})}function h(w){u(w.res,200,{status:"ok",version:Km,uptimeMs:o.now()-i})}function p(w){return E=>{let x=E.url.pathname;throw new B(501,"not_implemented",`${x} deferred to ${w} daemon lifecycle wiring`,{retry_after_milestone:w})}}function f(w){let E=t.schedulerLookup?.(w)??null;if(!E)throw new B(404,"not_found",`agent '${w}' has no scheduler`);return E}function m(w){return a.has(w)?a.get(w)??null:t.scheduleConfigLookup?.(w)??null}function g(w){w.headersSent||(w.setHeader("Server",Um),w.statusCode=204,w.end())}function y(w){let E=t.router.listAgents().map(Vm);u(w.res,200,{agents:E})}function v(w){let E=w.params.name,x;try{x=t.router.getAgent({name:E})}catch(j){throw _c(j)?new B(404,"not_found",`agent '${E}' not found`):j}let k=x.snapshot();u(w.res,200,{agent:Vm(k)})}async function S(w){let E=w.params.name,x=await qm(w.req,r);Hm(x,["game"],"/v1/agents/:name/join");let k=x;if(typeof k.game!="string"||k.game.length===0)throw new B(400,"bad_request","field 'game' must be a non-empty string",{invalid_field:"game"});if(k.mode!==void 0&&typeof k.mode!="string")throw new B(400,"bad_request","field 'mode' must be a string when present",{invalid_field:"mode"});if(k.one_shot!==void 0&&typeof k.one_shot!="boolean")throw new B(400,"bad_request","field 'one_shot' must be a boolean when present",{invalid_field:"one_shot"});if(k.oneShot!==void 0&&typeof k.oneShot!="boolean")throw new B(400,"bad_request","field 'oneShot' must be a boolean when present",{invalid_field:"oneShot"});let j=k.count;if(j!==void 0&&(typeof j!="number"||!Number.isInteger(j)||j<1||j>20))throw new B(400,"bad_request","field 'count' must be an integer between 1 and 20 when present",{invalid_field:"count"});let Z=k.one_shot??k.oneShot;try{t.router.joinQueue({name:E},k.game,k.mode,{...Z!==void 0?{oneShot:Z}:{},...typeof j=="number"?{count:j}:{}})}catch(J){throw _c(J)?new B(404,"not_found",`agent '${E}' not found`):J}g(w.res)}function R(w){let E=w.params.name;try{t.router.leaveQueue({name:E})}catch(x){throw _c(x)?new B(404,"not_found",`agent '${E}' not found`):x}g(w.res)}function $(w){let E=w.params.name,x=f(E),k=m(E),j=NE(x.snapshot());u(w.res,200,{schedule:k,snapshot:j})}async function K(w){let E=w.params.name,x=f(E),k=await qm(w.req,r),j;if(k===null)j=null;else{Hm(k,["enabled","timezone","days"],"/v1/agents/:name/schedule");let Z=k;if(typeof Z.enabled!="boolean")throw new B(400,"bad_request","field 'enabled' must be a boolean",{invalid_field:"enabled"});if(typeof Z.timezone!="string")throw new B(400,"bad_request","field 'timezone' must be a string",{invalid_field:"timezone"});if(typeof Z.days!="object"||Z.days===null||Array.isArray(Z.days))throw new B(400,"bad_request","field 'days' must be an object",{invalid_field:"days"});j=k}try{x.setSchedule(j)}catch(Z){let J=Gm(Z);throw J||Z}a.set(E,j),g(w.res)}function X(w){Ke(w,!1)}function ae(w){Ke(w,!0)}function Ke(w,E){let x=w.params.name,k=f(x),j=m(x);if(j===null){let J=E?"resume":"pause";throw new B(400,"bad_request",`no schedule to ${J}; POST /schedule first or configure initial schedule`)}let Z={...j,enabled:E};try{k.setSchedule(Z)}catch(J){let to=Gm(J);throw to||J}a.set(x,Z),g(w.res)}function st(w){c({level:"info",code:"shutdown_requested",message:"shutdown requested via POST /v1/shutdown",method:"POST",path:"/v1/shutdown"}),u(w.res,200,{status:"shutting_down"}),setImmediate(()=>{Promise.resolve().then(()=>t.onShutdown?.()).catch(E=>{c({level:"error",code:"handler_threw",message:`onShutdown threw/rejected: ${wc(E)}`,cause:E,method:"POST",path:"/v1/shutdown"})})})}async function nr(w,E){let x=o.now(),k=w.method??"GET",j=w.url??"/",Z=`http://${w.headers.host??"localhost"}`,J;try{J=new URL(j,Z)}catch{d(E,400,"bad_request","invalid request URL"),c({level:"info",code:"request_completed",message:`${k} ${j} -> 400 (${o.now()-x}ms)`,method:k,path:j,status:400,durationMs:o.now()-x});return}let to=Jm(J.pathname),rr=0;try{let Ee=l(w);if(!Ee.ok)throw c({level:"warn",code:"auth_failed",message:`${k} ${J.pathname}: auth failed (${Ee.reason})`,method:k,path:J.pathname,reason:Ee.reason}),new B(401,"unauthorized",`authentication required: ${Ee.reason}`);let gi=s.map(Et=>({route:Et,params:OE(Et.pattern,to)})).filter(Et=>Et.params!==null);if(gi.length===0)throw new B(404,"not_found","path not found");let yi=gi.find(Et=>Et.route.method===k);if(!yi){let Et=gi.map(_i=>_i.route.method).filter((_i,Ep,kp)=>kp.indexOf(_i)===Ep).join(", ");throw E.headersSent||E.setHeader("Allow",Et),new B(405,"method_not_allowed",`method ${k} not allowed`)}c({level:"info",code:"request_received",message:`${k} ${J.pathname}`,method:k,path:J.pathname}),await yi.route.handler({req:w,res:E,url:J,params:yi.params}),rr=E.statusCode}catch(Ee){Ee instanceof B?(d(E,Ee.status,Ee.code,Ee.message,Ee.details),rr=Ee.status):(c({level:"error",code:"handler_threw",message:`handler threw on ${k} ${J.pathname}: ${wc(Ee)}`,method:k,path:J.pathname,cause:Ee}),d(E,500,"internal_error","internal server error"),rr=500)}finally{w.complete||(w.on("data",()=>{}),w.on("error",()=>{})),c({level:"info",code:"request_completed",message:`${k} ${J.pathname} -> ${rr} (${o.now()-x}ms)`,method:k,path:J.pathname,status:rr,durationMs:o.now()-x})}}let Je=Wm.createServer((w,E)=>{nr(w,E).catch(x=>{if(c({level:"error",code:"handler_threw",message:`dispatch escaped: ${wc(x)}`,method:w.method,path:w.url,cause:x}),!E.headersSent)try{d(E,500,"internal_error","internal server error")}catch{try{E.end()}catch{}}})}),re="pre-listen",Ut=null,wn=null,eo=null;function vp(){return re==="listening"?Promise.reject(new _n("invalid_state","server already listening")):re==="closing"||re==="closed"||re==="bind-failed"?Promise.reject(new _n("invalid_state","server has been closed; create a new ControlServer")):new Promise((w,E)=>{let x=k=>{re="bind-failed",E(new _n("bind_failed",`failed to bind ${e}:${n}: ${k.message}`,k))};Je.once("error",x),Je.listen({host:e,port:n},()=>{Je.off("error",x);let k=Je.address();if(typeof k=="string"||k===null){re="bind-failed",E(new _n("bind_failed","unexpected listen address shape from server.address()"));return}Ut=k.address,wn=k.port,re="listening",c({level:"info",code:"server_listening",message:`control API server listening on ${Ut}:${wn}`,host:Ut,port:wn}),w(wn)})})}function bp(){return re!=="listening"||Ut===null||wn===null?null:{host:Ut,port:wn}}function Sp(){return re==="pre-listen"||re==="bind-failed"?(re="closed",Promise.resolve()):re==="closed"?Promise.resolve():(re==="closing"&&eo||(re="closing",eo=new Promise(w=>{let E=!1,x=()=>{E||(E=!0,clearTimeout(j),re="closed",c({level:"info",code:"server_closed",message:"control API server closed"}),w())},k=Je.closeAllConnections,j=setTimeout(()=>{if(typeof k=="function")try{k.call(Je)}catch{}x()},IE);j.unref(),Je.close(()=>x())})),eo)}return{listen:vp,address:bp,close:Sp}}function wc(t){if(t instanceof Error)return`${t.name}: ${t.message}`;if(typeof t=="string")return t;try{return JSON.stringify(t)}catch{return String(t)}}function bc(t){return{phase:"connected",transport:"connected",agentId:t.welcome.data.agent_id,agentName:t.welcome.data.agent_name,availableGames:[...t.welcome.data.games],autoConfirmMatches:t.autoConfirmMatches??!0}}function Qm(t,e){if(e.type==="start")return H(bc(e));if(t.phase==="closed")return e.type==="stop"?H(t):ze(t,"fsm.closed",`Ignoring ${e.type} because agent FSM is closed`);switch(e.type){case"command.join_queue":return LE(t,e.game,e.mode,e.oneShot);case"command.leave_queue":return ME(t);case"command.confirm_match":return jE(t,e.confirmId);case"ws.message":return DE(t,e.message,e.now);case"decision.ready":return VE(t,e.action);case"decision.failed":return WE(t,e.reason);case"reconnect.event":return YE(t,e.event);case"reconnect.close":return QE(t,e.info);case"stop":return H({...t,phase:"closed",transport:"closed"})}}function LE(t,e,n,r){if(!t.availableGames.includes(e))return ze(t,"fsm.unknown_game",`Cannot join unavailable game '${e}'`);let o={game:e,mode:Qr(n),...r===!0?{one_shot:!0}:{}};return H({...t,phase:"queuing",queue:o,pendingConfirm:void 0,activeMatch:void 0,pendingAction:void 0,lastGameOver:void 0},[{type:"send",message:{type:"join_queue",data:o}}])}function ME(t){return t.phase!=="queuing"&&t.phase!=="confirming"&&t.phase!=="matching"?ze(t,"fsm.not_queued","Ignoring leave_queue because agent is not queued"):H({...t,phase:"connected",queue:void 0,pendingConfirm:void 0},[{type:"send",message:{type:"leave_queue"}}])}function jE(t,e){let n=e??t.pendingConfirm?.confirm_id;return!n||t.phase!=="confirming"?ze(t,"fsm.no_pending_confirm","Ignoring match confirmation without a pending confirm request"):H({...t,phase:"matching",pendingConfirm:void 0},[{type:"send",message:{type:"match_confirm",data:{confirm_id:n}}}])}function DE(t,e,n){switch(e.type){case"queue_joined":return FE(t,e);case"queue_left":return H({...t,phase:"connected",queue:void 0,pendingConfirm:void 0});case"match_confirm_request":return BE(t,e);case"match_cancelled":return UE(t,e);case"game_start":return qE(t,e,n);case"game_state":return HE(t,e);case"action_request":return GE(t,e);case"game_over":return zE(t,e);case"error":return KE(t,e);case"event":return JE(t,e);default:return ze(t,"fsm.unknown_server_message",`Ignoring unknown server message '${e.type}'`)}}function FE(t,e){return H({...t,phase:"queuing",queue:{game:e.data.game,mode:Qr(e.data.mode),...e.data.one_shot===!0?{one_shot:!0}:{}}})}function BE(t,e){let n={game:e.data.game,mode:Qr(e.data.mode),...t.queue?.one_shot===!0?{one_shot:!0}:{}};return t.autoConfirmMatches?H({...t,phase:"matching",queue:n,pendingConfirm:void 0},[{type:"send",message:{type:"match_confirm",data:{confirm_id:e.data.confirm_id}}}]):H({...t,phase:"confirming",queue:n,pendingConfirm:e.data},[We("info","fsm.match_confirm_required",`Match confirmation required for ${e.data.game}/${e.data.mode}`)])}function UE(t,e){if(e.data.action==="re_queued"){let n=t.pendingConfirm?{game:t.pendingConfirm.game,mode:Qr(t.pendingConfirm.mode)}:t.queue,r=e.data.reason==="opponent_disconnected"?{game:e.data.game,mode:Qr(e.data.mode)}:n;return H({...t,phase:r?"queuing":"connected",queue:r,pendingConfirm:void 0,activeMatch:void 0,pendingAction:void 0},[We("warning","fsm.match_cancelled",`Match cancelled: ${e.data.reason}`)])}return H({...t,phase:"connected",queue:void 0,pendingConfirm:void 0,activeMatch:void 0,pendingAction:void 0},[We("warning","fsm.match_cancelled",`Match cancelled: ${e.data.reason}`)])}function qE(t,e,n){return H({...t,phase:"in_match",queue:void 0,pendingConfirm:void 0,pendingAction:void 0,activeMatch:{sessionId:e.data.match_id,game:e.data.game,startedAt:n??0}})}function HE(t,e){return t.activeMatch&&t.activeMatch.sessionId!==e.data.match_id?ze(t,"fsm.game_state_mismatch",`Ignoring game_state for session ${e.data.match_id}; active session is ${t.activeMatch.sessionId}`):H({...t,phase:t.activeMatch?"in_match":t.phase},[We("info","fsm.game_state","Received game state update")])}function GE(t,e){return t.phase!=="in_match"&&t.phase!=="deciding"?ze(t,"fsm.action_request_out_of_phase","Ignoring action_request outside an active match"):t.activeMatch&&t.activeMatch.sessionId!==e.data.match_id?ze(t,"fsm.action_request_mismatch",`Ignoring action_request for session ${e.data.match_id}; active session is ${t.activeMatch.sessionId}`):H({...t,phase:"deciding",pendingAction:e},[{type:"request_decision",actionRequest:e,matchId:e.data.match_id,game:t.activeMatch?.game}])}function VE(t,e){return t.phase!=="deciding"||!t.pendingAction?ze(t,"fsm.no_pending_action","Ignoring decision result without a pending action_request"):H({...t,phase:"in_match",pendingAction:void 0},[{type:"send",message:{type:"action",match_id:t.pendingAction.data.match_id,data:e}}])}function WE(t,e){return t.phase!=="deciding"||!t.pendingAction?ze(t,"fsm.no_pending_action","Ignoring decision failure without a pending action_request"):H(t,[{type:"fallback_required",actionRequest:t.pendingAction,reason:e}])}function zE(t,e){return t.activeMatch&&t.activeMatch.sessionId!==e.data.session_id?ze(t,"fsm.game_over_mismatch",`Ignoring game_over for session ${e.data.session_id}; active session is ${t.activeMatch.sessionId}`):H({...t,phase:"connected",queue:void 0,pendingConfirm:void 0,activeMatch:void 0,pendingAction:void 0,lastGameOver:e},[{type:"record_result",gameOver:e,...t.activeMatch?.game!==void 0?{game:t.activeMatch.game}:{}}])}function KE(t,e){let n=typeof e.data.message=="string"?e.data.message:"Server error";return H({...t,lastError:n},[We("error","server.error",n)])}function JE(t,e){return H(t,[We("info","server.event",`Received server event batch (${e.data.events.length} events)`)])}function YE(t,e){return e.type==="attempt-success"?H({...t,transport:"connected"}):e.type==="attempt-start"?H({...t,transport:"backoff"},[We("info","reconnect.attempt_start",`Reconnect attempt ${e.attempt} started`)]):e.type==="attempt-failure"?H({...t,transport:"backoff"},[We(e.severity,"reconnect.attempt_failure",`Reconnect attempt ${e.attempt} failed`)]):H({...t,phase:"closed",transport:"closed"},[We(e.severity,"reconnect.give_up","Reconnect gave up")])}function QE(t,e){return H({...t,phase:"closed",transport:"closed"},[We("error","reconnect.closed",`Reconnect closed: ${e.kind}`)])}function H(t,e=[]){return{state:t,effects:e}}function ze(t,e,n){return H(t,[We("warning",e,n)])}function We(t,e,n){return{type:"notify",level:t,code:e,message:n}}function Qr(t){return t&&t.length>0?t:"ranked"}var tr=class extends Error{cause;constructor(e,n){super(e),this.cause=n}},Xr=class extends tr{name="AgentInstanceStartError";kind="agent_start";constructor(e,n){super(e,n)}},Zr=class extends tr{name="AgentInstanceNotStartedError";kind="agent_not_started";constructor(e,n){super(e,n)}},ui=class extends tr{name="AgentInstanceStoppedError";kind="agent_stopped";constructor(e,n){super(e,n)}},Sc=class extends tr{name="AgentInstanceEffectError";kind="agent_effect";constructor(e,n){super(e,n)}},di=class{#e;#t=null;#n=null;#r=!1;#o=!1;#a=[];#c=new Set;#u=Promise.resolve();#g=0;#d=null;constructor(e){this.#e=e}async start(){if(this.#o)throw new ui(`agent '${this.#e.name}' has been stopped`);if(this.#r)throw new Xr(`agent '${this.#e.name}' is already started`);let e=this.#e.connect??Ha,n;try{n=await e(this.#e.ws)}catch(r){throw new Xr(`failed to start agent '${this.#e.name}': ${li(r)}`,r)}if(n.welcome===null)throw new Xr(`failed to start agent '${this.#e.name}': reconnect client returned without welcome`);return this.#t=n,this.#n=bc({welcome:n.welcome,autoConfirmMatches:this.#e.autoConfirmMatches,now:this.#k()}),this.#r=!0,this.#l(n),this.#f(),this.snapshot()}async stop(e="agent stop"){if(this.#o)return;this.#o=!0,this.#$();let n=this.#t;n!==null&&n.state!=="closed"&&await n.close(1e3,e),this.#n!==null&&this.#s({type:"stop",reason:e})}joinQueue(e,n,r={}){this.#w(),this.#s({type:"command.join_queue",game:e,mode:n,oneShot:r.oneShot})}leaveQueue(){this.#w(),this.#s({type:"command.leave_queue"})}confirmMatch(e){this.#w(),this.#s({type:"command.confirm_match",confirmId:e})}snapshot(){return{name:this.#e.name,state:this.#n,transport:this.#t?.state??"idle",started:this.#r,stopped:this.#o}}onState(e){return this.#c.add(e),()=>{this.#c.delete(e)}}#l(e){this.#a.push(e.onMessage(n=>{if(n.type==="readiness_check"){this.#i(n.data);return}this.#s({type:"ws.message",message:n,now:this.#k()})}),e.onReconnect(n=>{this.#s({type:"reconnect.event",event:n})}),e.onClose(n=>{this.#s({type:"reconnect.close",info:n})}),e.onError(n=>{this.#R(n)}))}async#i(e){let n=XE(e);try{let r=this.#e.onReadinessCheck?await this.#e.onReadinessCheck(e):{request_id:n,ready:!1,runtime_type:"mock",checked_at:new Date().toISOString(),detail:"readiness check handler is not configured"};this.#p({type:"runtime_status",data:ZE(r,n)})}catch(r){this.#p({type:"runtime_status",data:{request_id:n,ready:!1,runtime_type:"mock",checked_at:new Date().toISOString(),detail:Xm(`readiness check failed: ${li(r)}`)}})}}#s(e){let n=this.#S(),r=Qm(n,e);this.#n=r.state,this.#f(),this.#h(r.effects)}#h(e){e.length!==0&&(this.#u=this.#u.then(()=>this.#m(e)).catch(n=>{this.#v({level:"error",code:"agent.effect_queue",message:`Agent effect queue failed: ${li(n)}`,cause:n})}))}async#m(e){for(let n of e)await this.#y(n)}async#y(e){switch(e.type){case"send":this.#p(e.message);return;case"request_decision":await this.#_(e);return;case"fallback_required":this.#e.onFallbackRequired?.(e),this.#v({level:"warning",code:"agent.fallback_required",message:`Decision failed for match ${e.actionRequest.data.match_id}; fallback required`,cause:e.reason});return;case"record_result":this.#e.onResult?.(e.gameOver,e.game!==void 0?{game:e.game}:{});return;case"notify":this.#v(e);return}}#p(e){let n=this.#b();try{n.send(e)}catch(r){this.#v({level:"error",code:"agent.send_failed",message:`Failed to send ${e.type}: ${li(r)}`,cause:new Sc(`send ${e.type} failed`,r)})}}async#_(e){let n=++this.#g;this.#d={token:n,matchId:e.matchId};let r=this.#S();try{let o=await this.#e.decisionProvider.decide({actionRequest:e.actionRequest,matchId:e.matchId,game:e.game,state:r});if(!this.#E(n,e.matchId)){this.#v({level:"warning",code:"agent.stale_decision",message:`Ignoring stale decision for match ${e.matchId}`});return}this.#s({type:"decision.ready",action:o})}catch(o){if(!this.#E(n,e.matchId)){this.#v({level:"warning",code:"agent.stale_decision",message:`Ignoring stale decision failure for match ${e.matchId}`,cause:o});return}this.#s({type:"decision.failed",reason:o})}}#E(e,n){let r=this.#n;return this.#d?.token===e&&this.#d.matchId===n&&r?.phase==="deciding"&&r.pendingAction?.data.match_id===n}#w(){if(!this.#r||this.#n===null||this.#t===null)throw new Zr(`agent '${this.#e.name}' is not started`);if(this.#o||this.#n.phase==="closed")throw new ui(`agent '${this.#e.name}' is stopped`)}#b(){if(this.#t===null)throw new Zr(`agent '${this.#e.name}' is not started`);return this.#t}#S(){if(this.#n===null)throw new Zr(`agent '${this.#e.name}' is not started`);return this.#n}#f(){let e=this.snapshot();for(let n of[...this.#c])n(e)}#$(){let e=this.#a;this.#a=[];for(let n of e)n()}#R(e){this.#v({level:"error",code:"agent.ws_error",message:e.message,cause:e})}#v(e){this.#e.onNotify?.(e)}#k(){return this.#e.now?.()??Date.now()}};function li(t){if(t instanceof Error)return t.message;if(typeof t=="string")return t;try{return JSON.stringify(t)}catch{return String(t)}}function XE(t){if(!t||typeof t!="object")return"";let e=t.request_id;return typeof e=="string"?e:""}function ZE(t,e){let n=t&&typeof t=="object"?{...t}:{};return typeof n.request_id!="string"&&(n.request_id=e),typeof n.ready!="boolean"&&(n.ready=!1),n.runtime_type!=="openclaw"&&n.runtime_type!=="hermes"&&n.runtime_type!=="mock"&&(n.runtime_type="mock"),typeof n.checked_at!="string"&&(n.checked_at=new Date().toISOString()),typeof n.detail=="string"&&(n.detail=Xm(n.detail)),n}function Xm(t){return t.length>240?t.slice(0,240):t}function Zm(t){return{async decide(e){let n=ok(e.game),r=e.actionRequest.data,o=r.legal_actions??[];if(o.length===0)throw new Error("action_request had no legal actions");let i={game:n,matchId:e.matchId,playerId:ik(r.state),legalActions:o,publicState:r.state,timeoutMs:typeof r.timeout_ms=="number"?r.timeout_ms:0},s;try{s=await t.decide(i)}catch{try{s=await t.decide(i)}catch{return fi(n,o,r.state)}}return ek({game:n,raw:s,legalActions:o,publicState:r.state})}}}function ep(){return{name:"mock",async decide(t){return fi(t.game,t.legalActions,t.publicState)},async healthCheck(){return!0}}}function ek(t){if(typeof t.raw!="string")return rk(t.raw,t.legalActions)??fi(t.game,t.legalActions,t.publicState);let e=tk(t.game,t.raw,t.legalActions);return e!==null?e:fi(t.game,t.legalActions,t.publicState)}function tk(t,e,n){let r=nk(e),o=t==="texas_holdem"?Ja(r,n):t==="liars_dice"?Qa(r,n):Xa(r,n);return o.kind==="ok"?o.action:null}function nk(t){let e=t.trim();if(e.startsWith("{"))return e;let n=e.toLowerCase();return JSON.stringify({action:n})}function rk(t,e){let n=e.find(o=>sk(o,t));if(n)return n;let r=e.find(o=>o.type===t.type);return!t.data&&r?r:null}function fi(t,e,n){return t==="texas_holdem"?Ga({publicState:n,legalActions:e,yourPlayerId:"p0"}):t==="liars_dice"?Wa({publicState:n,legalActions:e,yourPlayerId:"p0"}):za({publicState:n,legalActions:e,yourPlayerId:"p0"})}function ok(t){if(t==="texas_holdem"||t==="liars_dice"||t==="coup")return t;throw new Error(`unsupported game: ${String(t)}`)}function ik(t){if(!t||typeof t!="object")return;let e=t.your_player_id;return typeof e=="string"?e:void 0}function sk(t,e){return JSON.stringify(t)===JSON.stringify(e)}var ak="http://127.0.0.1:18789",ck="openclaw/default";function tp(t){let e=(t.baseUrl??ak).replace(/\/+$/,""),n=t.model??ck,r=t.fetchImpl??globalThis.fetch;return{name:"openclaw",async decide(o){let i=await r(`${e}/v1/responses`,{method:"POST",headers:lk(t,o),body:JSON.stringify({model:n,input:uk(o)})});if(!i.ok)throw new Error(`OpenClaw request failed with HTTP ${i.status}`);let s=await i.text(),a=dk(s);return fk(a)},async healthCheck(){try{return(await r(`${e}/v1/responses`,{method:"POST",headers:{"Content-Type":"application/json",...t.token?{Authorization:`Bearer ${t.token}`}:{}},body:JSON.stringify({model:n,input:'health check: answer with {"action":"pass"}'})})).ok}catch{return!1}}}}function lk(t,e){return{"Content-Type":"application/json","x-openclaw-session-key":`aifight:${t.agentId}:${e.matchId}:${e.playerId??"unknown"}`,...t.token?{Authorization:`Bearer ${t.token}`}:{}}}function uk(t){return["You are an AIFight game-playing agent runtime.","Choose exactly one legal action. Return only JSON in this shape:",'{"action":"<type>","data":{},"summary":"short reason"}',"",JSON.stringify({game:t.game,match_id:t.matchId,player_id:t.playerId??null,state:t.publicState,legal_actions:t.legalActions,timeout_ms:t.timeoutMs})].join(`
211
211
  `)}function dk(t){if(t.trim()==="")return"";try{return JSON.parse(t)}catch{return t}}function fk(t){if(typeof t=="string")return t;if(!t||typeof t!="object")throw new Error("OpenClaw response was not an object");let e=t;if(typeof e.output_text=="string")return e.output_text;if(typeof e.content=="string")return e.content;let n=e.output,r=mk(n);if(r)return r;let o=e.choices,i=pk(o);if(i)return i;throw new Error("OpenClaw response did not contain text")}function mk(t){if(!Array.isArray(t))return null;let e=[];for(let n of t){if(!n||typeof n!="object")continue;let r=n.content;if(Array.isArray(r))for(let o of r){if(!o||typeof o!="object")continue;let i=o.text;typeof i=="string"&&e.push(i)}}return e.length>0?e.join(`
212
212
  `):null}function pk(t){if(!Array.isArray(t)||t.length===0)return null;let e=t[0];if(typeof e.text=="string")return e.text;let n=e.message;if(n&&typeof n=="object"){let r=n.content;if(typeof r=="string")return r}return null}var hk="http://127.0.0.1:8642",gk="hermes-agent";function np(t){let e=(t.baseUrl??hk).replace(/\/+$/,""),n=t.model??gk,r=t.fetchImpl??globalThis.fetch;return{name:"hermes",async decide(o){let i=await r(`${e}/v1/responses`,{method:"POST",headers:yk(t,o),body:JSON.stringify({model:n,input:_k(o)})});if(!i.ok)throw new Error(`Hermes request failed with HTTP ${i.status}`);let s=await i.text(),a=wk(s);return vk(a)},async healthCheck(){try{return(await r(`${e}/v1/responses`,{method:"POST",headers:{"Content-Type":"application/json",...t.token?{Authorization:`Bearer ${t.token}`}:{}},body:JSON.stringify({model:n,input:'health check: answer with {"action":"pass"}'})})).ok}catch{return!1}}}}function yk(t,e){return{"Content-Type":"application/json",...t.token?{Authorization:`Bearer ${t.token}`,"X-Hermes-Session-Key":`aifight:${t.agentId}:${e.matchId}:${e.playerId??"unknown"}`}:{}}}function _k(t){return["You are an AIFight game-playing Hermes Agent runtime.","Choose exactly one legal action. Return only JSON in this shape:",'{"action":"<type>","data":{},"summary":"short reason"}',"",JSON.stringify({game:t.game,match_id:t.matchId,player_id:t.playerId??null,state:t.publicState,legal_actions:t.legalActions,timeout_ms:t.timeoutMs})].join(`
213
213
  `)}function wk(t){if(t.trim()==="")return"";try{return JSON.parse(t)}catch{return t}}function vk(t){if(typeof t=="string")return t;if(!t||typeof t!="object")throw new Error("Hermes response was not an object");let e=t;if(typeof e.output_text=="string")return e.output_text;if(typeof e.content=="string")return e.content;if(typeof e.text=="string")return e.text;let n=e.output,r=bk(n);if(r)return r;let o=e.choices,i=Sk(o);if(i)return i;throw new Error("Hermes response did not contain text")}function bk(t){if(!Array.isArray(t))return null;let e=[];for(let n of t){if(!n||typeof n!="object")continue;let r=n.content;if(typeof r=="string"){e.push(r);continue}if(Array.isArray(r))for(let o of r){if(!o||typeof o!="object")continue;let i=o.text;typeof i=="string"&&e.push(i)}}return e.length>0?e.join(`
package/dist/index.mjs CHANGED
@@ -104,4 +104,4 @@ ${vs}`:vs;if(c=a(l,y),c.length<=n)return c}return c=a(l,""),c.length<=n||(c=a(""
104
104
  `)}function nb(t){switch(t){case"texas_holdem":return["Phase:","Hand ","Your hand:","Board:","Your chips:","Pot:"];case"liars_dice":return["Phase:","Round ","Your dice:","Current bid:"];case"coup":return["Phase:","Your unrevealed cards:","Your coins:","Pending action:"]}}var jt=class extends Error{provider;cause;constructor(e,r,n){super(r),this.provider=e,this.cause=n}},ut=class extends jt{name="DirectModelNetworkError";kind="direct_model_network";constructor(e,r,n){super(e,r,n)}},Me=class extends jt{name="DirectModelHttpError";kind="direct_model_http";status;bodySnippet;constructor(e,r,n,s,o){super(e,n,o),this.status=r,this.bodySnippet=s}},be=class extends jt{name="DirectModelAbortedError";kind="direct_model_aborted";constructor(e,r,n){super(e,r,n)}},we=class extends jt{name="DirectModelInvalidResponseError";kind="direct_model_invalid_response";responseSnippet;constructor(e,r,n,s){super(e,r,s),this.responseSnippet=n}},J=class extends jt{name="DirectModelUnsupportedError";kind="direct_model_unsupported";field;constructor(e,r,n){super(e,n),this.field=r}},Md=2048,Id="[REDACTED]";function fn(t,e){let r=t;for(let n of e){if(!n)continue;let s=r.indexOf(n);for(;s>=0;)r=r.slice(0,s)+Id+r.slice(s+n.length),s=r.indexOf(n,s+Id.length)}return r}function sb(t,e=Md){if(e<=0)return"";if(t.length<=e)return t;let r=e,n="";for(let s=0;s<8;s++){let i=`...[truncated ${t.length-r} chars]`,a=Math.max(0,e-i.length);if(i===n&&a===r)break;n=i,r=a}return e<n.length?n.slice(0,e):t.slice(0,r)+n}function dt(t,e){if(t===void 0||t==="")return;let r=fn(t,e);return sb(r,Md)}var Ee="anthropic",ob="https://api.anthropic.com",ib="2023-06-01";function Dd(t){if(!t.apiKey)throw new J(Ee,"apiKey","apiKey must be a non-empty string");if(!t.model)throw new J(Ee,"model","model must be a non-empty string");let e=t.apiKey,r=t.model,n=(t.baseURL??ob).replace(/\/+$/,""),s=t.anthropicVersion??ib,o=t.fetchImpl??globalThis.fetch;if(typeof o!="function")throw new J(Ee,"fetchImpl","fetch is unavailable; pass fetchImpl explicitly");let i=`${n}/v1/messages`,a=[e];return{provider:Ee,model:r,generate:async l=>{if(!Number.isFinite(l.maxTokens)||l.maxTokens<=0)throw new J(Ee,"maxTokens","maxTokens must be a positive integer");let u=l.signal;if(u?.aborted)throw new be(Ee,"request aborted before send",u.reason);let d={model:r,system:l.systemPrompt,messages:[{role:"user",content:l.userPrompt}],max_tokens:l.maxTokens};l.temperature!==void 0&&(d.temperature=l.temperature);let f={"x-api-key":e,"anthropic-version":s,"content-type":"application/json"},p=performance.now(),h;try{h=await o(i,{method:"POST",headers:f,body:JSON.stringify(d),signal:u})}catch(v){if(ab(v))throw new be(Ee,"request aborted",v);let D=fn(cb(v),a);throw new ut(Ee,`fetch failed: ${D}`,v)}let m=Math.max(0,performance.now()-p);if(!h.ok){let v=await Ld(h),D=dt(v,a);throw new Me(Ee,h.status,`Anthropic returned HTTP ${h.status}`,D,h)}let y=await Ld(h),g;try{g=JSON.parse(y)}catch(v){throw new we(Ee,"response body is not valid JSON",dt(y,a),v)}let b=lb(g);if(b===null)throw new we(Ee,"response missing content[0].text or content[0].type !== 'text'",dt(y,a));let{inputTokens:E,outputTokens:S}=ub(g);return{text:b,inputTokens:E,outputTokens:S,latencyMs:m,raw:g}}}}function ab(t){if(t===null||typeof t!="object")return!1;let e=t;return e.name==="AbortError"||e.code==="ABORT_ERR"||e.code===20}function cb(t){if(t instanceof Error)return t.message;if(typeof t=="string")return t;try{return String(t)}catch{return"unknown"}}async function Ld(t){try{return await t.text()}catch{return""}}function lb(t){if(!bs(t))return null;let e=t.content;if(!Array.isArray(e)||e.length===0)return null;let r=e[0];if(!bs(r)||r.type!=="text")return null;let n=r.text;return typeof n!="string"?null:n}function ub(t){if(!bs(t))return{};let e=t.usage;if(!bs(e))return{};let r=e.input_tokens,n=e.output_tokens;return{inputTokens:typeof r=="number"?r:void 0,outputTokens:typeof n=="number"?n:void 0}}function bs(t){return typeof t=="object"&&t!==null}var Se="openai",db="https://api.openai.com/v1";function qd(t){if(!t.apiKey)throw new J(Se,"apiKey","apiKey must be a non-empty string");if(!t.model)throw new J(Se,"model","model must be a non-empty string");let e=t.apiKey,r=t.model,n=(t.baseURL??db).replace(/\/+$/,""),s=t.organization,o=t.fetchImpl??globalThis.fetch;if(typeof o!="function")throw new J(Se,"fetchImpl","fetch is unavailable; pass fetchImpl explicitly");let i=`${n}/chat/completions`,a=[e];return{provider:Se,model:r,generate:async l=>{if(!Number.isFinite(l.maxTokens)||l.maxTokens<=0)throw new J(Se,"maxTokens","maxTokens must be a positive integer");let u=l.signal;if(u?.aborted)throw new be(Se,"request aborted before send",u.reason);let d={model:r,messages:[{role:"system",content:l.systemPrompt},{role:"user",content:l.userPrompt}],max_completion_tokens:l.maxTokens};l.temperature!==void 0&&(d.temperature=l.temperature);let f={Authorization:`Bearer ${e}`,"content-type":"application/json"};s&&(f["OpenAI-Organization"]=s);let p=performance.now(),h;try{h=await o(i,{method:"POST",headers:f,body:JSON.stringify(d),signal:u})}catch(v){if(fb(v))throw new be(Se,"request aborted",v);let D=fn(hb(v),a);throw new ut(Se,`fetch failed: ${D}`,v)}let m=Math.max(0,performance.now()-p);if(!h.ok){let v=await jd(h),D=dt(v,a);throw new Me(Se,h.status,`OpenAI returned HTTP ${h.status}`,D,h)}let y=await jd(h),g;try{g=JSON.parse(y)}catch(v){throw new we(Se,"response body is not valid JSON",dt(y,a),v)}let b=pb(g);if(b===null)throw new we(Se,"response missing choices[0].message.content (or content is not a string)",dt(y,a));let{inputTokens:E,outputTokens:S}=mb(g);return{text:b,inputTokens:E,outputTokens:S,latencyMs:m,raw:g}}}}function fb(t){if(t===null||typeof t!="object")return!1;let e=t;return e.name==="AbortError"||e.code==="ABORT_ERR"||e.code===20}function hb(t){if(t instanceof Error)return t.message;if(typeof t=="string")return t;try{return String(t)}catch{return"unknown"}}async function jd(t){try{return await t.text()}catch{return""}}function pb(t){if(!hn(t))return null;let e=t.choices;if(!Array.isArray(e)||e.length===0)return null;let r=e[0];if(!hn(r))return null;let n=r.message;if(!hn(n))return null;let s=n.content;return typeof s!="string"?null:s}function mb(t){if(!hn(t))return{};let e=t.usage;if(!hn(e))return{};let r=e.prompt_tokens,n=e.completion_tokens;return{inputTokens:typeof r=="number"?r:void 0,outputTokens:typeof n=="number"?n:void 0}}function hn(t){return typeof t=="object"&&t!==null}var W=class extends Error{name="DecisionProviderError";kind;cause;constructor(e,r,n){super(r),this.kind=e,this.cause=n}},yb=2,gb=500;function _b(t){let e=t.retryBudget??yb,r=t.parseRetryHintCharCap??gb;if(!Number.isFinite(e)||!Number.isInteger(e)||e<0)throw new W("fatal_caller_bug",`retryBudget must be a non-negative integer (got ${String(t.retryBudget)})`);if(!Number.isFinite(r)||!Number.isInteger(r)||r<=0)throw new W("fatal_caller_bug",`parseRetryHintCharCap must be a positive integer (got ${String(t.parseRetryHintCharCap)})`);let n=new Map;function s(c,l){let u=`${c}:${l}`,d=n.get(u);if(d)return d;let f;try{f=t.apiKeyResolver(c,l)}catch(h){throw new W("fatal_unsupported",`apiKeyResolver threw for ${c}:${l}`,h)}if(typeof f!="string"||!f)throw new W("fatal_unsupported",`apiKeyResolver returned empty key for ${c}:${l}`);let p;try{c==="anthropic"?p=(t.clientFactory?.anthropic??Dd)({apiKey:f,model:l,fetchImpl:t.fetchImpl}):p=(t.clientFactory?.openai??qd)({apiKey:f,model:l,fetchImpl:t.fetchImpl})}catch(h){throw h instanceof J?new W("fatal_unsupported",h.message,h):new W("fatal_caller_bug",`clientFactory.${c} threw unexpected error`,h)}return n.set(u,p),p}async function o(c){if(typeof c.decisionBudgetMs!="number"||!Number.isFinite(c.decisionBudgetMs)||c.decisionBudgetMs<=0)throw new W("fatal_caller_bug","decisionBudgetMs must be a positive finite number");if(!bb(c.game))throw new W("fatal_caller_bug",`unsupported game: ${String(c.game)}`);let l=new AbortController,u=setTimeout(()=>{l.abort()},c.decisionBudgetMs);try{return await i(c,l.signal)}finally{clearTimeout(u)}}async function i(c,l){if(l.aborted)throw new W("fatal_aborted","decisionBudgetMs already elapsed before decide started");let u=s(c.strategyProfile.provider,c.strategyProfile.model),d=Cd(c),f,p,h=0,m;for(let g=0;g<=e;g++){if(l.aborted)throw new W("fatal_aborted","decisionBudgetMs elapsed mid-attempt");let b=g===0?d.userPrompt:d.userPrompt+`
105
105
 
106
106
  `+Tb(g,f,p,r),E;try{E=await u.generate({systemPrompt:d.systemPrompt,userPrompt:b,temperature:c.strategyProfile.temperature,maxTokens:c.strategyProfile.maxTokens,signal:l})}catch(v){if($b(v))throw kb(v);if(Sb(v)){f=`direct_model_${v.kind}`,p=Pb(v);continue}throw new W("fatal_caller_bug","client.generate threw unexpected error",v)}h+=E.latencyMs,m=E;let S=wb(c.game,E.text,c.legalActions,r);if(S.kind==="ok")return vb(c,S,E,h,g);f=`parse_${S.reason}`,p=S.rawSnippet}let y;try{y=Eb(c)}catch(g){throw new W("fatal_caller_bug",g instanceof Error?`fallback dispatch failed: ${g.message}`:"fallback dispatch failed",g)}return{action:y.type,params:Fd(y.data),summary:`(fallback: ${f??"unknown"})`,providerMetadata:{provider:c.strategyProfile.provider,model:c.strategyProfile.model,inputTokens:m?.inputTokens,outputTokens:m?.outputTokens,latencyMs:h,retries:e,fallback:!0}}}async function a(){if(!t.healthCheckProfile)return!1;try{return await s(t.healthCheckProfile.provider,t.healthCheckProfile.model).generate({systemPrompt:"ping",userPrompt:"respond with the word OK",maxTokens:10}),!0}catch{return!1}}return{name:t.name,decide:o,healthCheck:a}}function vb(t,e,r,n,s){let o=Fd(e.action.data),i={action:e.action.type,providerMetadata:{provider:t.strategyProfile.provider,model:t.strategyProfile.model,inputTokens:r.inputTokens,outputTokens:r.outputTokens,latencyMs:n,retries:s,fallback:!1}};return o!==void 0&&e.summary!==void 0?{...i,params:o,summary:e.summary}:o!==void 0?{...i,params:o}:e.summary!==void 0?{...i,summary:e.summary}:i}function bb(t){return t==="texas_holdem"||t==="liars_dice"||t==="coup"}function wb(t,e,r,n){switch(t){case"texas_holdem":return Sd(e,r,n);case"liars_dice":return $d(e,r,n);case"coup":return Pd(e,r,n)}}function Eb(t){switch(t.game){case"texas_holdem":return bd({publicState:t.publicState,legalActions:t.legalActions,yourPlayerId:t.playerId});case"liars_dice":return wd({publicState:t.publicState,legalActions:t.legalActions,yourPlayerId:t.playerId});case"coup":return Ed({publicState:t.publicState,legalActions:t.legalActions,yourPlayerId:t.playerId})}}function Fd(t){if(t!=null&&typeof t=="object"&&!Array.isArray(t))return t}function Sb(t){return t instanceof we||t instanceof ut?!0:t instanceof Me?t.status===429||t.status>=500:!1}function $b(t){return t instanceof be||t instanceof J?!0:t instanceof Me?!(t.status===429||t.status>=500):!1}function kb(t){return t instanceof be?new W("fatal_aborted",t.message,t):t instanceof J?new W("fatal_unsupported",t.message,t):new W("fatal_http",t.message,t)}function Pb(t){if(t instanceof Me)return t.bodySnippet;if(t instanceof we)return t.responseSnippet}function Tb(t,e,r,n){let s=[];if(s.push(`Retry attempt ${t}: previous output failed validation.`),e&&s.push(`Reason: ${e}.`),r!==void 0&&r!==""){let o=r.length>n?r.slice(0,n):r;s.push(`Previous output (truncated to ${n} chars): ${o}`)}return s.push("Please retry. Respond with a single JSON object exactly matching the schema in the system prompt."),s.join(`
107
- `)}var Rb="0.1.0-alpha.5",TS="v1.0.0";function xS(){let t=Ft(),e=ft(),r=Es();return{ok:!0,runtimeVersion:Rb,schemaCount:e.size,messageTypeCount:r.length,schemasRoot:t}}export{tn as AIFIGHT_CRYPTO_V1_PREFIX,en as AIFIGHT_KEYCHAIN_V1_PREFIX,nu as AIFIGHT_RUNTIME_SERVICE,Ae as CredentialsCorruptError,ue as CredentialsCryptoError,or as CredentialsError,ir as CredentialsKeychainUnavailableError,W as DecisionProviderError,TS as PROTOCOL_VERSION,Rb as RUNTIME_VERSION,_r as ReconnectStoppedError,sr as RegisterError,Xr as RegisterHttpError,St as RegisterNetworkError,$t as RegisterSchemaError,rt as StoreError,lr as StoreMigrationError,cr as StoreOpenError,nt as StoreQueryError,Ke as WSAbortedError,Y as WSClientError,Ct as WSClosedError,it as WSConnectError,at as WSHandshakeError,Ie as WSOutboundSchemaError,At as WSProtocolVersionError,se as WSSchemaError,ze as WSUnknownMessageError,ct as WSWelcomeInvalidError,Nt as WSWelcomeTimeoutError,_b as createDirectModelProvider,rv as createReconnectingWSClient,Xi as createWSClient,f_ as decryptFromStorage,h_ as deleteFromStorage,l_ as encryptForStorage,Zr as ensureRuntimeHome,Ft as findSchemasRoot,ou as getCredentialsBackend,_i as getDefaultDbPath,Qr as getRuntimeHome,xS as hello,iu as isKeychainAvailable,ft as loadAllSchemas,Ss as loadRestSchema,Jd as loadSchema,Es as messageTypes,Xg as openDatabase,Hg as registerAgent};
107
+ `)}var Rb="0.1.0-alpha.6",TS="v1.0.0";function xS(){let t=Ft(),e=ft(),r=Es();return{ok:!0,runtimeVersion:Rb,schemaCount:e.size,messageTypeCount:r.length,schemasRoot:t}}export{tn as AIFIGHT_CRYPTO_V1_PREFIX,en as AIFIGHT_KEYCHAIN_V1_PREFIX,nu as AIFIGHT_RUNTIME_SERVICE,Ae as CredentialsCorruptError,ue as CredentialsCryptoError,or as CredentialsError,ir as CredentialsKeychainUnavailableError,W as DecisionProviderError,TS as PROTOCOL_VERSION,Rb as RUNTIME_VERSION,_r as ReconnectStoppedError,sr as RegisterError,Xr as RegisterHttpError,St as RegisterNetworkError,$t as RegisterSchemaError,rt as StoreError,lr as StoreMigrationError,cr as StoreOpenError,nt as StoreQueryError,Ke as WSAbortedError,Y as WSClientError,Ct as WSClosedError,it as WSConnectError,at as WSHandshakeError,Ie as WSOutboundSchemaError,At as WSProtocolVersionError,se as WSSchemaError,ze as WSUnknownMessageError,ct as WSWelcomeInvalidError,Nt as WSWelcomeTimeoutError,_b as createDirectModelProvider,rv as createReconnectingWSClient,Xi as createWSClient,f_ as decryptFromStorage,h_ as deleteFromStorage,l_ as encryptForStorage,Zr as ensureRuntimeHome,Ft as findSchemasRoot,ou as getCredentialsBackend,_i as getDefaultDbPath,Qr as getRuntimeHome,xS as hello,iu as isKeychainAvailable,ft as loadAllSchemas,Ss as loadRestSchema,Jd as loadSchema,Es as messageTypes,Xg as openDatabase,Hg as registerAgent};
@@ -18,7 +18,7 @@ export { createDirectModelProvider, DecisionProviderError, } from "./decision/pr
18
18
  export type { DecisionProvider, DirectModelProviderOptions, DirectModelProviderName, DecisionProviderErrorKind, } from "./decision/provider";
19
19
  export type { DecisionRequest, DecisionResponse, DecisionResponseProviderMetadata, StrategyProfile, GameSpecificProfile, GameType, GameRules, LegalAction, } from "./decision/types";
20
20
  export type { ParseResult, ParseInvalidReason, } from "./decision/parser-types";
21
- export declare const RUNTIME_VERSION = "0.1.0-alpha.5";
21
+ export declare const RUNTIME_VERSION = "0.1.0-alpha.6";
22
22
  export declare const PROTOCOL_VERSION = "v1.0.0";
23
23
  export interface HelloResult {
24
24
  ok: true;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aifight/aifight",
3
- "version": "0.1.0-alpha.5",
3
+ "version": "0.1.0-alpha.6",
4
4
  "description": "AIFight CLI — local outbound bridge that connects AIFight to user-selected Agent runtimes.",
5
5
  "license": "MIT-0",
6
6
  "type": "module",