ai: migrate docs-search to @crema/lexical-rag-ui
Replace the in-app docs-search.ts and build-docs-index.mjs with the
new sibling lib (@crema/lexical-rag-ui). Wire-up only — same index
shape, same tool response shape, same MiniSearch config, so the agent
sees no behavior change.
- tsconfig + app.css: wire the lib; alias minisearch to consumer's
node_modules so sibling-lib resolution works.
- admin-tools.ts: createRAGClient("/docs-index.json"), keep search_docs
tool's response shape unchanged (collapse tags[] back to category).
- ai.tsx: define DocHit locally — it's the tool-response shape, no
longer the lib's internal type.
- scripts/build-docs-index.mjs: thin wrapper that injects MiniSearch
and calls buildIndex. Per-app sources list and tags live here.
- package.json: add minisearch dep + build:docs script + prebuild hook.
- .gitignore: don't commit the generated /public/docs-index.json.
Delete: app/lib/docs-search.ts (was untracked; its logic moved to lib).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@@ -9,3 +9,7 @@
|
||||
.demo.log
|
||||
.demo.pid
|
||||
.boot.log
|
||||
|
||||
# Generated by `npm run build:docs` — regenerated on every full build
|
||||
# (prebuild) and on demand during dev. Don't commit the artifact.
|
||||
/public/docs-index.json
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
@source "../../lib-code-ui/src";
|
||||
@source "../../lib-diagram-ui/src";
|
||||
@source "../../lib-onboarding-ui/src";
|
||||
@source "../../lib-lexical-rag-ui/src";
|
||||
@source "../../lib-notification-ui/src";
|
||||
/* CREMA:SOURCES */
|
||||
|
||||
|
||||
@@ -15,9 +15,13 @@ import {
|
||||
suspendTenant,
|
||||
type Tenant,
|
||||
} from "~/lib/arcadia/tenants"
|
||||
import { searchDocs } from "~/lib/docs-search"
|
||||
import { createRAGClient } from "@crema/lexical-rag-ui"
|
||||
import { BLOCK_INDEX, getBlockSchema } from "~/lib/block-schemas"
|
||||
|
||||
// Lazy singleton — first tool call fetches /docs-index.json, subsequent
|
||||
// calls reuse the parsed MiniSearch instance.
|
||||
const docsClient = createRAGClient("/docs-index.json")
|
||||
|
||||
export type ToolCall = {
|
||||
name: string
|
||||
args: Record<string, unknown>
|
||||
@@ -253,8 +257,22 @@ const TOOLS: ToolDef[] = [
|
||||
10,
|
||||
Math.max(1, typeof args.limit === "number" ? args.limit : 5),
|
||||
)
|
||||
const hits = await searchDocs(query, limit)
|
||||
return { query, count: hits.length, hits }
|
||||
const hits = await docsClient.search(query, { limit })
|
||||
// Tool-shape parity with the previous searchDocs() return: collapse
|
||||
// tags[] back to category for now so the agent's prior expectations
|
||||
// and any cached examples still parse cleanly.
|
||||
return {
|
||||
query,
|
||||
count: hits.length,
|
||||
hits: hits.map((h) => ({
|
||||
id: h.id,
|
||||
title: h.title,
|
||||
sourcePath: h.sourcePath,
|
||||
category: h.tags[0] ?? "",
|
||||
excerpt: h.excerpt,
|
||||
score: h.score,
|
||||
})),
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@@ -69,7 +69,19 @@ import { Avatar, AvatarFallback } from "~/components/ui/avatar"
|
||||
import { pageTitle } from "~/lib/page-meta"
|
||||
import { useArcadiaClient } from "@crema/arcadia-client"
|
||||
import type { Message as LLMMessage, ToolCall } from "@crema/llm-ui"
|
||||
import type { DocHit } from "~/lib/docs-search"
|
||||
// Shape of a single hit returned by the `search_docs` tool. Defined here
|
||||
// rather than imported from the lib because the tool wrapper in
|
||||
// admin-tools.ts intentionally collapses the lib's `tags[]` back to a
|
||||
// single `category` for tool-response stability — this type matches
|
||||
// what the model actually sees.
|
||||
type DocHit = {
|
||||
id: string
|
||||
title: string
|
||||
sourcePath: string
|
||||
category: string
|
||||
excerpt: string
|
||||
score: number
|
||||
}
|
||||
import {
|
||||
AgentAvatar,
|
||||
ToolCallCard,
|
||||
|
||||
7
package-lock.json
generated
7
package-lock.json
generated
@@ -15,6 +15,7 @@
|
||||
"d3-geo": "^3.1.1",
|
||||
"isbot": "^5.1.36",
|
||||
"lucide-react": "^1.8.0",
|
||||
"minisearch": "^7.2.0",
|
||||
"motion": "^12.38.0",
|
||||
"openapi-fetch": "^0.17.0",
|
||||
"phoenix": "^1.8.5",
|
||||
@@ -7264,6 +7265,12 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/minisearch": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/minisearch/-/minisearch-7.2.0.tgz",
|
||||
"integrity": "sha512-dqT2XBYUOZOiC5t2HRnwADjhNS2cecp9u+TJRiJ1Qp/f5qjkeT5APcGPjHw+bz89Ms8Jp+cG4AlE+QZ/QnDglg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/morgan": {
|
||||
"version": "1.10.1",
|
||||
"resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.1.tgz",
|
||||
|
||||
@@ -3,13 +3,15 @@
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"prebuild": "npm run build:docs",
|
||||
"build": "react-router build",
|
||||
"dev": "react-router dev",
|
||||
"start": "react-router-serve ./build/server/index.js",
|
||||
"typecheck": "react-router typegen && tsc",
|
||||
"test": "vitest run",
|
||||
"test:watch": "vitest",
|
||||
"sync-libs": "node scripts/sync-libs.mjs"
|
||||
"sync-libs": "node scripts/sync-libs.mjs",
|
||||
"build:docs": "node scripts/build-docs-index.mjs"
|
||||
},
|
||||
"dependencies": {
|
||||
"@base-ui/react": "^1.4.0",
|
||||
@@ -21,6 +23,7 @@
|
||||
"d3-geo": "^3.1.1",
|
||||
"isbot": "^5.1.36",
|
||||
"lucide-react": "^1.8.0",
|
||||
"minisearch": "^7.2.0",
|
||||
"motion": "^12.38.0",
|
||||
"openapi-fetch": "^0.17.0",
|
||||
"phoenix": "^1.8.5",
|
||||
|
||||
39
scripts/build-docs-index.mjs
Normal file
39
scripts/build-docs-index.mjs
Normal file
@@ -0,0 +1,39 @@
|
||||
#!/usr/bin/env node
|
||||
// Build the /docs-index.json bundle consumed by @crema/lexical-rag-ui at
|
||||
// runtime. Thin wrapper — all engine logic lives in the lib's builder.ts;
|
||||
// this file owns the per-app config (which arcadia-app docs to index and
|
||||
// how to tag them).
|
||||
//
|
||||
// Run: npm run build:docs
|
||||
//
|
||||
// Allowlist is intentional. Excluded files are aspirational/stale and
|
||||
// would poison answers (TODO lists, design docs for unshipped features,
|
||||
// sub-app READMEs that aren't part of arcadia-core). To add a file,
|
||||
// append to SOURCES below — don't auto-discover.
|
||||
|
||||
import { resolve, dirname } from "node:path"
|
||||
import { fileURLToPath } from "node:url"
|
||||
|
||||
import MiniSearch from "minisearch"
|
||||
import { buildIndex } from "../../lib-lexical-rag-ui/src/builder.mjs"
|
||||
|
||||
const ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "..")
|
||||
const ARCADIA = resolve(ROOT, "../reference/arcadia-app")
|
||||
const OUT = resolve(ROOT, "public/docs-index.json")
|
||||
|
||||
const SOURCES = [
|
||||
{ path: "README.md", tags: ["core"] },
|
||||
{ path: "docs/ARCADIA.md", tags: ["core"] },
|
||||
{ path: "docs/MODULAR_MONOLITH.md", tags: ["core"] },
|
||||
{ path: "apps/arcadia_core/README.md", tags: ["core"] },
|
||||
{ path: "DEPLOY.md", tags: ["ops"] },
|
||||
{ path: "DEV_DEPLOY.md", tags: ["ops"] },
|
||||
{ path: "DEV_SETUP.md", tags: ["ops"] },
|
||||
]
|
||||
|
||||
buildIndex({
|
||||
miniSearch: MiniSearch,
|
||||
rootDir: ARCADIA,
|
||||
outPath: OUT,
|
||||
sources: SOURCES,
|
||||
})
|
||||
@@ -62,6 +62,8 @@
|
||||
"@crema/diagram-ui/*": ["../lib-diagram-ui/src/*"],
|
||||
"@crema/onboarding-ui": ["../lib-onboarding-ui/src/index.tsx"],
|
||||
"@crema/onboarding-ui/*": ["../lib-onboarding-ui/src/*"],
|
||||
"@crema/lexical-rag-ui": ["../lib-lexical-rag-ui/src/index.tsx"],
|
||||
"@crema/lexical-rag-ui/*": ["../lib-lexical-rag-ui/src/*"],
|
||||
"// CREMA:PATHS": [""],
|
||||
"react": ["./node_modules/@types/react"],
|
||||
"react/*": ["./node_modules/@types/react/*"],
|
||||
@@ -69,6 +71,7 @@
|
||||
"react-dom/*": ["./node_modules/@types/react-dom/*"],
|
||||
"clsx": ["./node_modules/clsx"],
|
||||
"tailwind-merge": ["./node_modules/tailwind-merge"],
|
||||
"minisearch": ["./node_modules/minisearch"],
|
||||
"lucide-react": ["./node_modules/lucide-react"],
|
||||
"openapi-fetch": ["./node_modules/openapi-fetch"],
|
||||
"openapi-fetch/*": ["./node_modules/openapi-fetch/*"],
|
||||
|
||||
Reference in New Issue
Block a user