fix(ai-chat): resolve the current page for agent context (#43, hardness #1)

AiChatWindow derived the open page via useParams(), but it's mounted in a
pathless parent layout route where :pageSlug isn't matched, so useParams()
returned {} and openPage was ALWAYS null — the agent never received current-page
context (couldn't resolve 'this page'/'the current page'). Derive pageSlug from
useMatch('/s/:spaceSlug/p/:pageSlug') against the full pathname instead, so it
resolves regardless of where the component sits in the route tree. No-match
behavior is unchanged (undefined -> query disabled -> openPage null).

Addresses Hardness #1 of #43. Hardness #2 (proxy resilience: a get_current_page
tool / hidden user-message context so identity doesn't depend on the system
prompt surviving CLIProxyAPI) remains open.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
claude code agent 227
2026-06-20 21:57:03 +03:00
parent b53b0c651e
commit ada1dce739

View File

@@ -18,7 +18,7 @@ import {
IconX, IconX,
} from "@tabler/icons-react"; } from "@tabler/icons-react";
import { useAtom, useSetAtom } from "jotai"; import { useAtom, useSetAtom } from "jotai";
import { useParams } from "react-router-dom"; import { useMatch } from "react-router-dom";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useQueryClient } from "@tanstack/react-query"; import { useQueryClient } from "@tanstack/react-query";
import { import {
@@ -140,13 +140,16 @@ export default function AiChatWindow() {
const { data: messageRows, isLoading: messagesLoading } = const { data: messageRows, isLoading: messagesLoading } =
useAiChatMessagesQuery(activeChatId ?? undefined); useAiChatMessagesQuery(activeChatId ?? undefined);
// The page the user is currently viewing, derived from the route (same // The page the user is currently viewing. AiChatWindow lives in a pathless
// source the breadcrumb uses). On a non-page route `pageSlug` is undefined, // parent layout route, so useParams() can't see :pageSlug. Match the full
// so the query is disabled and `openPage` is null. This is passed to the // pathname against the authenticated page route instead so "the current page"
// chat thread as context so the agent knows what "this page"/"the current // resolves regardless of where this component is mounted. On a non-page route
// page" refers to; the agent still reads/writes via its CASL-enforced page // the match is null, so `pageSlug` is undefined, the query is disabled and
// tools using the id. // `openPage` is null. This is passed to the chat thread as context so the
const { pageSlug } = useParams(); // agent knows what "this page"/"the current page" refers to; the agent still
// reads/writes via its CASL-enforced page tools using the id.
const pageRouteMatch = useMatch("/s/:spaceSlug/p/:pageSlug");
const pageSlug = pageRouteMatch?.params?.pageSlug;
const { data: openPageData } = usePageQuery({ const { data: openPageData } = usePageQuery({
pageId: extractPageSlugId(pageSlug), pageId: extractPageSlugId(pageSlug),
}); });