File size: 2,132 Bytes
4e23b01
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
export type MediaPathTagKind = 'image' | 'video' | 'audio' | 'file';

export interface MediaPathTagMatch {
  readonly kind: MediaPathTagKind;
  readonly path: string;
}

const SINGLE_MEDIA_PATH_TAG_RE =
  /^\s*<(image|video|audio|file)\b[^>]*?\bpath="([^"]*)"[^>]*>(?:<\/\1>)?\s*$/;

export function matchMediaPathTagText(text: string): MediaPathTagMatch | undefined {
  const match = SINGLE_MEDIA_PATH_TAG_RE.exec(text);
  if (match === null) return undefined;
  return { kind: match[1] as MediaPathTagKind, path: unescapeMediaAttribute(match[2]!) };
}

function unescapeMediaAttribute(value: string): string {
  return value
    .replaceAll('&quot;', '"')
    .replaceAll('&lt;', '<')
    .replaceAll('&gt;', '>')
    .replaceAll('&amp;', '&');
}

const KIMI_FILE_SCHEME = 'kimi-file://';

export interface DaemonFileRef {
  readonly fileId: string;
}

export function parseDaemonFileRef(url: string): DaemonFileRef | undefined {
  if (!url.startsWith(KIMI_FILE_SCHEME)) return undefined;
  const rest = url.slice(KIMI_FILE_SCHEME.length);
  const queryAt = rest.indexOf('?');
  const fileId = queryAt === -1 ? rest : rest.slice(0, queryAt);
  return fileId.length > 0 ? { fileId } : undefined;
}

export function parseDaemonFileRefFileId(url: string): string | undefined {
  return parseDaemonFileRef(url)?.fileId;
}

export interface MediaRefPart {
  readonly type: string;
  readonly text?: string;
  readonly imageUrl?: { readonly url?: string; readonly name?: string };
  readonly videoUrl?: { readonly url?: string; readonly name?: string };
}

export function daemonFileRefFromPairingPart(
  part: MediaRefPart,
): { readonly kind: 'image' | 'video'; readonly ref: DaemonFileRef; readonly name?: string } | undefined {
  if (part.type !== 'image_url' && part.type !== 'video_url') return undefined;
  const media = part.type === 'image_url' ? part.imageUrl : part.videoUrl;
  const url = media?.url;
  if (typeof url !== 'string') return undefined;
  const ref = parseDaemonFileRef(url);
  if (ref === undefined) return undefined;
  return { kind: part.type === 'image_url' ? 'image' : 'video', ref, name: media?.name };
}