1import{r as e,n as t,aa as n,e as o,d as a,f as r}from"./index-DCpYiqWz.js";let i=null,s=!1;const u=new Set;function l(){for(const e of u)e()}function c(){return i}function m(){return s}function p(){s=!0}function d(){null!==i&&(i=null,l())}const h={human:"H",ai:"A"};function y(e,t,n,o){if(0===o)return null;const a=[[0,1],[1,0],[1,1],[1,-1]];for(const[r,i]of a){const a=[[t,n]];for(let s=1;s<4;s++){const u=t+r*s,l=n+i*s;if(u<0||u>=6||l<0||l>=7)break;if(e[u][l]!==o)break;a.push([u,l])}for(let s=1;s<4;s++){const u=t-r*s,l=n-i*s;if(u<0||u>=6||l<0||l>=7)break;if(e[u][l]!==o)break;a.unshift([u,l])}if(a.length>=4)return a.slice(0,4)}return null}function f(e,t){for(let n=5;n>=0;n--)if(0===e[n][t])return n;return-1}function g(e){return 0===e?"0":e}function b(e){const t="playing"===e.status?"Turn: "+("human"===e.turn?"human (H)":"ai (A)"):"human_won"===e.status?"Status: human (H) won":"ai_won"===e.status?"Status: ai (A) won":"Status: draw",n=e.board.map(e=>e.map(g).join(" ")),o=Array.from({length:7},(e,t)=>String(t+1)).join(" "),a=["# Connect Four â in progress",t,`Move ${e.moveCount}`,"Board (top row = 0):",...n,o];if(e.winningLine){const t="human_won"===e.status?"human":"ai",n=e.winningLine.map(([e,t])=>`row ${e}, col ${t+1}`).join(" â ");a.push(`Winner: ${t} (line: ${n})`)}return a.join("\n")}function v(){return null===i?null:{...i,board:i.board.map(e=>e.slice()),winningLine:i.winningLine?i.winningLine.map(e=>[e[0],e[1]]):void 0}}function w(){const[t,n]=e.useState(v);return e.useEffect(()=>{const e=()=>n(v());return u.add(e),e(),()=>{u.delete(e)}},[]),t}function x(e,t){const n="aspect-square rounded-full border transition-colors";return"H"===e?`${n} bg-rose-500 border-rose-300 ${t?"ring-2 ring-rose-200 shadow-lg shadow-rose-500/40":""}`:"A"===e?`${n} bg-amber-400 border-amber-200 ${t?"ring-2 ring-amber-100 shadow-lg shadow-amber-400/40":""}`:`${n} bg-bg-deepest/80 border-orchid-500/15`}const _={playEnabled:!0,proactivePrompt:!0,teaseDuringPlay:!0,customInviteGuidance:"",customTeaseGuidance:""},A={apiVersion:6,version:"1.0.0",source:"builtin",key:"connect-four",name:"Connect Four",category:"utility",icon:"Grid3x3",description:"Play Connect Four with the AI through chat.",showInTopBar:!0,supportsPromptContributions:!0,supportsLifecycleHooks:!0,supportsEmergencyStop:!1,chatPanel:{order:50},PanelComponent:({onManage:e})=>{const o=w();if(!o)return t.jsx("div",{className:"rounded-xl border border-orchid-500/15 bg-bg-deepest/60 p-4",children:t.jsx("p",{className:"text-xs text-text-secondary",children:"No game in progress. Ask the AI to play Connect Four."})});const a="playing"===o.status?"human"===o.turn?{label:"Your turn (H)",tone:"text-rose-300"}:{label:"AI's turn (A)",tone:"text-amber-300"}:"human_won"===o.status?{label:"You won!",tone:"text-rose-300"}:"ai_won"===o.status?{label:"AI won.",tone:"text-amber-300"}:{label:"Draw.",tone:"text-text-secondary"};return t.jsx("div",{className:"space-y-3",children:t.jsxs("div",{className:"rounded-xl border border-orchid-500/15 bg-bg-deepest/60 p-4 space-y-3",children:[t.jsxs("div",{className:"flex items-center justify-between gap-2",children:[t.jsxs("div",{children:[t.jsx("h4",{className:"text-sm font-semibold text-text-primary",children:"Connect Four"}),t.jsx("p",{className:`text-xs ${a.tone}`,children:a.label})]}),e&&t.jsxs("button",{type:"button",className:"inline-flex items-center gap-1 text-xs text-text-tertiary hover:text-text-primary transition-colors",onClick:()=>e(),children:[t.jsx(n,{className:"w-3.5 h-3.5"}),"Settings"]})]}),t.jsx("div",{className:"rounded-lg bg-bg-deepest p-2",style:{display:"grid",gridTemplateColumns:"repeat(7, minmax(0, 1fr))",gap:"4px"},children:Array.from({length:6}).map((e,n)=>Array.from({length:7}).map((e,a)=>{const r=o.board[n][a],i=(s=o.winningLine,u=n,l=a,!!s&&s.some(([e,t])=>e===u&&t===l));var s,u,l;return t.jsx("div",{className:x(r,i),"aria-label":`row ${n} column ${a+1} ${0===r?"empty":r}`},`${n}-${a}`)}))}),t.jsx("div",{className:"px-2 text-[10px] text-text-tertiary",style:{display:"grid",gridTemplateColumns:"repeat(7, minmax(0, 1fr))",gap:"4px"},children:Array.from({length:7}).map((e,n)=>t.jsx("div",{className:"text-center",children:n+1},n))}),t.jsxs("p",{className:"text-[11px] text-text-tertiary",children:["Move ",o.moveCount,". The user is H (red), the AI is A (yellow)."]})]})})},settings:{fields:{playEnabled:{id:"playEnabled",type:"toggle",scope:"global",allowPersonaOverride:!1,title:"Enabled",description:"When off, the AI can't play Connect Four and is told to ask you to switch it back on.",default:_.playEnabled},proactivePrompt:{id:"proactivePrompt",type:"toggle",scope:"global",title:"Proactive invite",description:"Let the AI invite you to play in-character when idle.",default:_.proactivePrompt},teaseDuringPlay:{id:"teaseDuringPlay",type:"toggle",scope:"global",title:"Tease between moves",description:"Let the AI taunt and tease you in-character while playing.",default:_.teaseDuringPlay},customInviteGuidance:{id:"customInviteGuidance",type:"textarea",scope:"persona",title:"Custom invite instructions (advanced)",description:"Replaces the default in-character invite phrasing. Leave blank for the canned default.",default:_.customInviteGuidance,rows:3},customTeaseGuidance:{id:"customTeaseGuidance",type:"textarea",scope:"persona",title:"Custom tease instructions (advanced)",description:"Replaces the default tease guidance. Leave blank for the canned default.",default:_.customTeaseGuidance,rows:3}},mainLayout:["playEnabled","proactivePrompt","teaseDuringPlay","customInviteGuidance","customTeaseGuidance"],quickLayout:["playEnabled","proactivePrompt","teaseDuringPlay"]}};let k=!1;function P(e){const t=e.extensionState?.resolvedSettings??{};if(!1===t.playEnabled)return k=!1,[{id:"connect-four:off",placement:"system_post",priority:5,text:"The player has Connect Four available, but it's switched off right now â you cannot start a game or use any of its tools. If you would like to play, ask the player to switch Connect Four back on from its menu in the top bar."}];const n=!1!==t.proactivePrompt,o=!1!==t.teaseDuringPlay,a="string"==typeof t.customInviteGuidance?t.customInviteGuidance:"",r="string"==typeof t.customTeaseGuidance?t.customTeaseGuidance:"",s=c();if(null===s)return!n||m()?(k=!1,[]):(k=!0,[{id:"connect-four:invite",placement:"tool_guidance",priority:45,text:(u=a,`You can play Connect Four with the user. They have not started a game with you yet. Naturally invite them to play when there's a lull in the conversation, or as an opener if the chat is fresh. Stay in character â don't break the scene to announce a "mini-game." Frame it as something *you* want from them: a wager, a challenge, a tease. Once they accept, call play_connect_four. Don't pester â inv
1ite at most once per session unless they bring it up.\n${u.trim()||"Phrase the invitation in character â a command, a wager, a tease."}`)}]);var u;k=!1;let l=function(e,t){const n='A Connect Four game is in progress. The user is H (human), you are A (AI). Columns are numbered 1-7 (leftmost = 1). Take turns like this: (1) When the user declares their move ("column 4", "the middle", "left edge"), call play_connect_four_move_human with that column number â you place their piece for them. (2) The tool response tells you what to do next: decide your own move, announce to the player in character which column you choose, then call play_connect_four_move_ai with it â play to win, but keep your strategy to yourself. (3) Wait for the player to declare their next move. The game ends automatically on a win or a draw â the move tool will tell you who won. After that, narrate the result to the user in-character and offer a rematch if it fits the scene. Don\'t call any "end" tool â there isn\'t one.',o=t.trim()||(e?"Between moves, tease the user in character â mock weak openings, gloat over near-misses, taunt them when you set up a trap. Keep it short and conversational, never longer than the move itself.":"");return o?`${n}\n${o}`:n}(o,r);if("ai"===s.turn){const e=function(e){if(null===i||"playing"!==i.status)return null;const t=h[e];for(let n=0;n<7;n++){const e=f(i.board,n);if(-1===e)continue;i.board[e][n]=t;const o=y(i.board,e,n,t);if(i.board[e][n]=0,o)return n}return null}("ai");null!==e&&(l+=`\nWINNING MOVE AVAILABLE: dropping your A piece in column ${e+1} completes four-in-a-row and wins the game immediately. Play it to win â or, if drawing the game out and teasing the player suits the scene better, hold off. Your call.`)}return[{id:"connect-four:play",placement:"tool_guidance",priority:40,text:l},{id:"connect-four:board",placement:"persona_post",priority:25,text:b(s)}]}let C={..._};function I(e){e&&("boolean"==typeof e.playEnabled&&(C.playEnabled=e.playEnabled),"boolean"==typeof e.proactivePrompt&&(C.proactivePrompt=e.proactivePrompt),"boolean"==typeof e.teaseDuringPlay&&(C.teaseDuringPlay=e.teaseDuringPlay),"string"==typeof e.customInviteGuidance&&(C.customInviteGuidance=e.customInviteGuidance),"string"==typeof e.customTeaseGuidance&&(C.customTeaseGuidance=e.customTeaseGuidance))}const G={type:"function",displayLabels:{pending:"Starting gameâ¦",success:"Game started",error:"Couldn't start game"},function:{name:"play_connect_four",description:"Start a new Connect Four game with the user. The user plays H (human), you play A (AI). Call this when the user accepts a game or asks to start one. Calling mid-game resets the board.",parameters:{type:"object",properties:{first_player:{type:"string",enum:["human","ai"],description:"Who moves first. Default: human."}}}}},$={...G,displayLabels:{pending:"Restartingâ¦",success:"New game",error:"Couldn't restart"},function:{...G.function,description:"Start a new Connect Four game, resetting the current board."}},N={type:"function",displayLabels:{pending:"Placing Hâ¦",success:"Placed H",error:"Couldn't place H"},function:{name:"play_connect_four_move_human",description:"Drop the human player's H piece in the given column (1-7, leftmost = 1). Call this when the user declares their move â you place their piece for them.",parameters:{type:"object",properties:{column:{type:"integer",minimum:1,maximum:7,description:"Column 1-7 (leftmost = 1)."}},required:["column"]}}},T={type:"function",displayLabels:{pending:"Placing Aâ¦",success:"Placed A",error:"Couldn't place A"},function:{name:"play_connect_four_move_ai",description:"Drop your A piece in the given column (1-7, leftmost = 1). Announce the column you choose to the player first, then call this. Play strategically â block the human's threats and build your own.",parameters:{type:"object",properties:{column:{type:"integer",minimum:1,maximum:7,description:"Column 1-7 (leftmost = 1)."}},required:["column"]}}};function j(e,t){const n=function(e,t){if(null===i)return{ok:!1,error:"No game in progress."};if("playing"!==i.status)return{ok:!1,error:"Game is already over."};if(i.turn!==e)return{ok:!1,error:`Not ${e}'s turn â it is ${i.turn}'s turn.`};if(!Number.isInteger(t)||t<0||t>=7)return{ok:!1,error:"Column must be an integer 1-7."};const n=f(i.board,t);if(-1===n)return{ok:!1,error:`Column ${t+1} is full.`};const o=h[e];i.board[n][t]=o,i.moveCount+=1;const a=y(i.board,n,t,o);return a?(i.status="human"===e?"human_won":"ai_won",i.winningLine=a):function(e){for(let t=0;t<7;t++)if(0===e[0][t])return!1;return!0}
1(i.board)?i.status="draw":i.turn="human"===e?"ai":"human",l(),{ok:!0,row:n,status:i.status,winningLine:i.winningLine}}(e,t);if(!n.ok)return{ok:!1,error:n.error};const o=c(),a=b(o),r=o.status,s=t+1;let u;u="playing"!==r?function(e){return"human_won"===e?"Game over â Human (H) won.":"ai_won"===e?"Game over â AI (A) won.":"Game over â draw, board full."}(r):"human"===e?`Played column ${s} for the human. Now tell the player which column you choose, then call play_connect_four_move_ai to play it. Call any toys/vibrators/shockers as you please, then wait for the player.`:`Played column ${s} for the AI. Now wait for the player to declare their next move.`;const m={ok:!0,board:a,status:r,turn:"playing"===r?o.turn:null,winner:"human_won"===r?"human":"ai_won"===r?"ai":null,winning_line:o.winningLine??null,message:u};return"playing"!==r&&d(),m}const S={manifest:A,useExtension:()=>{const t=w(),[n,i]=e.useState(!0),[s,u]=e.useState(()=>({...C})),l=o(e=>e.currentPersonaId),c=a(e=>e.isAuthenticated);e.useEffect(()=>{if(!c)return;let e=!1;const t=t=>{if(e)return;const n=t?.runtime?.resolved_settings;n&&(I(n),u({...C}))};return r.ensure("connect-four",l??void 0,{onUpdate:t}).then(t).catch(t=>{e||console.error("[ConnectFour] Failed to load extension state:",t)}),()=>{e=!0}},[c,l]);const m=null!==t;return{isInstalled:!0,isAvailable:m,isEnabled:n,isActive:m,statusIndicator:m?{color:"green",label:`Turn: ${t.turn}`,description:`Move ${t.moveCount}`}:{color:"white",label:"Idle"},globalSettings:{playEnabled:s.playEnabled,proactivePrompt:s.proactivePrompt,teaseDuringPlay:s.teaseDuringPlay},personaSettings:{customInviteGuidance:s.customInviteGuidance,customTeaseGuidance:s.customTeaseGuidance},resolvedSettings:{...s},enable:async()=>{i(!0)},disable:async()=>{i(!1),d()},updateGlobalSettings:async e=>{I(e),u({...C})},updatePersonaSettings:async e=>{I(e),u({...C})},updateSettings:async e=>{I(e),u({...C})}}},getTools:function(){return C.playEnabled?null===c()?[G]:[N,T,$]:[]},executeTool:async(e,t,n)=>{const o=t||{};if(!C.playEnabled)return{ok:!1,error:"Connect Four is switched off. Ask the player to switch it back on from the top bar before playing."};if("play_connect_four"===e){const e="ai"===o.first_player?"ai":"human";a=e,i={board:Array.from({length:6},()=>Array(7).fill(0)),turn:a,status:"playing",moveCount:0},l(),p();const t=c();return{ok:!0,board:b(t),turn:t.turn,message:`New game started. ${"human"===e?"Human (H)":"AI (A)"}
1 moves first.`}}var a;return"play_connect_four_move_human"===e?"number"!=typeof o.column||!Number.isInteger(o.column)||o.column<1||o.column>7?{ok:!1,error:"column must be an integer 1-7."}:j("human",o.column-1):"play_connect_four_move_ai"===e?"number"!=typeof o.column||!Number.isInteger(o.column)||o.column<1||o.column>7?{ok:!1,error:"column must be an integer 1-7."}:j("ai",o.column-1):{ok:!1,error:`Unknown Connect Four tool "${e}".`}},getPromptContributions:e=>(I(e.extensionState?.resolvedSettings),P(e)),onAfterAssistantMessage:async e=>{(function(){const e=k;return k=!1,e})()&&!m()&&p()}};export{S as connectFourExtension};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.