diff --git a/server/gateway-proxy.js b/server/gateway-proxy.js index 79f124f..40ffc15 100644 --- a/server/gateway-proxy.js +++ b/server/gateway-proxy.js @@ -87,11 +87,13 @@ function createGatewayProxy(options) { logError = (msg, err) => console.error(msg, err), } = options || {}; + const { verifyClient } = options || {}; + if (typeof loadUpstreamSettings !== "function") { throw new Error("createGatewayProxy requires loadUpstreamSettings()."); } - const wss = new WebSocketServer({ noServer: true }); + const wss = new WebSocketServer({ noServer: true, verifyClient }); wss.on("connection", (browserWs) => { let upstreamWs = null; diff --git a/server/index.js b/server/index.js index 1f689de..06c965d 100644 --- a/server/index.js +++ b/server/index.js @@ -50,9 +50,9 @@ async function main() { }, allowWs: (req) => { if (resolvePathname(req.url) !== "/api/gateway/ws") return false; - if (!accessGate.allowUpgrade(req)) return false; return true; }, + verifyClient: (info) => accessGate.allowUpgrade(info.req), }); await app.prepare(); diff --git a/src/lib/office/deskDirectives.ts b/src/lib/office/deskDirectives.ts index f20deac..5ec462b 100644 --- a/src/lib/office/deskDirectives.ts +++ b/src/lib/office/deskDirectives.ts @@ -6,7 +6,7 @@ import { stripUiMetadata } from "@/lib/text/message-extract"; // regex checks across chat, office, or scene code. export type OfficeDeskDirective = "desk" | "release"; export type OfficeGithubDirective = "github" | "release"; -export type OfficeGymDirective = "gym"; +export type OfficeGymDirective = "gym" | "release"; export type OfficeQaDirective = "qa_lab" | "release"; export type OfficeStandupDirective = "standup"; export type OfficeCallPhase = "needs_message" | "ready_to_call"; @@ -156,6 +156,16 @@ const resolveOfficeInteractionDirectiveFromNormalized = ( const resolveOfficeGymSkillDirectiveFromNormalized = ( normalized: string, ): OfficeGymDirective | null => { + const gymSkillReleasePatterns = [ + /\bleave\s+(?:the\s+)?gym\b/, + /\bexit\s+(?:the\s+)?gym\b/, + /\bdone\s+(?:with\s+(?:the\s+)?)?(?:gym|skill(?:\s+building)?)\b/, + /\bstop\s+(?:working\s+on\s+)?skills?\b/, + /\bleave\s+the\s+skill(?:\s+building)?(?:\s+room)?\b/, + ]; + if (gymSkillReleasePatterns.some((pattern) => pattern.test(normalized))) { + return "release"; + } const skillIntentPatterns = [ /\bskills?\b/, /\bskills?\s+marketplace\b/, @@ -177,6 +187,16 @@ const resolveOfficeGymSkillDirectiveFromNormalized = ( const resolveOfficeGymCommandDirectiveFromNormalized = ( normalized: string, ): OfficeGymDirective | null => { + const gymCommandReleasePatterns = [ + /\bleave\s+(?:the\s+)?gym\b/, + /\bexit\s+(?:the\s+)?gym\b/, + /\bdone\s+(?:with\s+(?:the\s+)?)?gym\b/, + /\bstop\s+gym(?:ning)?\b/, + /\bleave\s+skill(?:\s+building)?(?:\s+room)?\b/, + ]; + if (gymCommandReleasePatterns.some((pattern) => pattern.test(normalized))) { + return "release"; + } const gymCommandPatterns = [ /\b(?:lets|let's)\s+go\s+to\s+the\s+gym\b/, /\b(?:lets|let's)\s+go\s+to\s+gym\b/, diff --git a/src/lib/office/eventTriggers.ts b/src/lib/office/eventTriggers.ts index c132a8b..76b16f9 100644 --- a/src/lib/office/eventTriggers.ts +++ b/src/lib/office/eventTriggers.ts @@ -1133,7 +1133,7 @@ export const reconcileOfficeAnimationTriggerState = (params: { }); if (skillGymDirective) { skillGymDirectiveKeyByAgentId[agentId] = skillGymDirective.key; - if (skillGymDirective.directive !== "release") { + if (skillGymDirective.directive === "gym") { skillGymHoldByAgentId[agentId] = true; } } else if (next.skillGymHoldByAgentId[agentId]) {