6ede33ccdb
Build and Push Docker Images / create_manifest (web, surfsense-web, , cpu) (push) Has been cancelled
Build and Push Docker Images / finalize_release (push) Has been cancelled
Obsidian Plugin Lint / lint (push) Has been cancelled
Build and Push Docker Images / build (./surfsense_web, cpu, ./surfsense_web/Dockerfile, web, surfsense-web, ubuntu-24.04-arm, linux/arm64, arm64, , runner, false, cpu) (push) Has been cancelled
Build and Push Docker Images / build (./surfsense_web, cpu, ./surfsense_web/Dockerfile, web, surfsense-web, ubuntu-latest, linux/amd64, amd64, , runner, false, cpu) (push) Has been cancelled
Build and Push Docker Images / compute_version (push) Has been cancelled
Build and Push Docker Images / build (./surfsense_backend, cpu, ./surfsense_backend/Dockerfile, backend, surfsense-backend, ubuntu-24.04-arm, linux/arm64, arm64, , production, false, cpu) (push) Has been cancelled
Build and Push Docker Images / build (./surfsense_backend, cpu, ./surfsense_backend/Dockerfile, backend, surfsense-backend, ubuntu-latest, linux/amd64, amd64, , production, false, cpu) (push) Has been cancelled
Build and Push Docker Images / build (./surfsense_backend, cu126, ./surfsense_backend/Dockerfile, backend, surfsense-backend, ubuntu-24.04-arm, linux/arm64, arm64, -cuda126, production, true, cuda126) (push) Has been cancelled
Build and Push Docker Images / build (./surfsense_backend, cu126, ./surfsense_backend/Dockerfile, backend, surfsense-backend, ubuntu-latest, linux/amd64, amd64, -cuda126, production, true, cuda126) (push) Has been cancelled
Build and Push Docker Images / build (./surfsense_backend, cu128, ./surfsense_backend/Dockerfile, backend, surfsense-backend, ubuntu-24.04-arm, linux/arm64, arm64, -cuda, production, true, cuda) (push) Has been cancelled
Build and Push Docker Images / build (./surfsense_backend, cu128, ./surfsense_backend/Dockerfile, backend, surfsense-backend, ubuntu-latest, linux/amd64, amd64, -cuda, production, true, cuda) (push) Has been cancelled
Build and Push Docker Images / verify_digests (push) Has been cancelled
Build and Push Docker Images / create_manifest (backend, surfsense-backend, , cpu) (push) Has been cancelled
Build and Push Docker Images / create_manifest (backend, surfsense-backend, -cuda, cuda) (push) Has been cancelled
Build and Push Docker Images / create_manifest (backend, surfsense-backend, -cuda126, cuda126) (push) Has been cancelled
55 lines
1.5 KiB
TypeScript
55 lines
1.5 KiB
TypeScript
import type { MentionedDocumentInfo } from "@/atoms/chat/mentioned-documents.atom";
|
|
|
|
export type MentionSegment =
|
|
| { type: "text"; value: string; start: number }
|
|
| { type: "mention"; doc: MentionedDocumentInfo; start: number };
|
|
|
|
/**
|
|
* Tokenizes a user message into text and `@mention` segments.
|
|
*
|
|
* Pure: no React, no DOM, no side effects. Safe to unit-test and reuse.
|
|
*
|
|
* Mentions are matched greedily by longest title first so that a longer title
|
|
* (e.g. `@Project Roadmap`) is never shadowed by a shorter prefix
|
|
* (e.g. `@Project`).
|
|
*/
|
|
export function parseMentionSegments(
|
|
text: string,
|
|
docs: ReadonlyArray<MentionedDocumentInfo>
|
|
): MentionSegment[] {
|
|
if (text.length === 0) return [];
|
|
if (docs.length === 0) return [{ type: "text", value: text, start: 0 }];
|
|
|
|
const tokens = docs
|
|
.map((doc) => ({ doc, token: `@${doc.title}` }))
|
|
.sort((a, b) => b.token.length - a.token.length);
|
|
|
|
const segments: MentionSegment[] = [];
|
|
let i = 0;
|
|
let buffer = "";
|
|
let bufferStart = 0;
|
|
|
|
while (i < text.length) {
|
|
const tokenMatch = tokens.find(({ token }) => text.startsWith(token, i));
|
|
if (tokenMatch) {
|
|
if (buffer) {
|
|
segments.push({ type: "text", value: buffer, start: bufferStart });
|
|
buffer = "";
|
|
}
|
|
segments.push({ type: "mention", doc: tokenMatch.doc, start: i });
|
|
i += tokenMatch.token.length;
|
|
bufferStart = i;
|
|
continue;
|
|
}
|
|
if (!buffer) bufferStart = i;
|
|
buffer += text[i];
|
|
i += 1;
|
|
}
|
|
|
|
if (buffer) {
|
|
segments.push({ type: "text", value: buffer, start: bufferStart });
|
|
}
|
|
|
|
return segments;
|
|
}
|