@aleph-alpha/chat-kit 6.4.0 → 6.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/dist/{CkHistory.vue_vue_type_script_setup_true_lang-B0WUzTHa.js → CkHistory.vue_vue_type_script_setup_true_lang-BvRIp3m6.js} +71 -14
  2. package/dist/adapters/responses-api.js +1 -1
  3. package/dist/chat-kit.css +81 -11
  4. package/dist/{code-palette-DH_G7mZ5.js → code-palette-BWrZDi47.js} +71 -35
  5. package/dist/components/base/CkCodeEditor/CkCodeEditor.stories.d.ts +2 -1
  6. package/dist/components/base/CkCodeEditor/CkCodeEditor.stories.d.ts.map +1 -1
  7. package/dist/components/base/CkCodeEditor/CkCodeEditor.vue.d.ts +1 -0
  8. package/dist/components/base/CkCodeEditor/CkCodeEditor.vue.d.ts.map +1 -1
  9. package/dist/components/base/CkCodeEditor/badgeDecoration.d.ts +2 -2
  10. package/dist/components/base/CkCodeEditor/createCodeMirror.d.ts +15 -1
  11. package/dist/components/base/CkCodeEditor/createCodeMirror.d.ts.map +1 -1
  12. package/dist/components/base/CkCodeEditor/types.d.ts +12 -0
  13. package/dist/components/base/CkCodeEditor/types.d.ts.map +1 -1
  14. package/dist/components/base/CkMarkdownRenderer/CkMarkdownRenderer.stories.d.ts +7 -0
  15. package/dist/components/base/CkMarkdownRenderer/CkMarkdownRenderer.stories.d.ts.map +1 -1
  16. package/dist/components/base/CkMarkdownRenderer/CkMarkdownRenderer.vue.d.ts +9 -0
  17. package/dist/components/base/CkMarkdownRenderer/CkMarkdownRenderer.vue.d.ts.map +1 -1
  18. package/dist/components/base/CkMarkdownRenderer/types.d.ts +13 -0
  19. package/dist/components/base/CkMarkdownRenderer/types.d.ts.map +1 -1
  20. package/dist/components/index.js +1 -1
  21. package/dist/composables/index.js +1 -1
  22. package/dist/{createCodeMirror-5iswYetS.js → createCodeMirror-BO-TWTzn.js} +27 -9
  23. package/dist/{createCrepeEditor-C-AQ1w_e.js → createCrepeEditor-BGSlwmKn.js} +4 -4
  24. package/dist/handlers/index.js +2 -2
  25. package/dist/helpers/codemirror/theme.d.ts.map +1 -1
  26. package/dist/helpers/unified/remarkBreaks.d.ts +15 -0
  27. package/dist/helpers/unified/remarkBreaks.d.ts.map +1 -0
  28. package/dist/{index-DLjsqQHx.js → index--Yonjzfi.js} +3 -3
  29. package/dist/{index-Mh3WUU-6.js → index-2YPxXIaf.js} +1 -1
  30. package/dist/{index-CWp_t8Wl.js → index-B4uqe-fL.js} +2 -2
  31. package/dist/{index-hEJ_Bavx.js → index-Bfo4U-Al.js} +2 -2
  32. package/dist/{index-g2X42srv.js → index-Bw39pbRL.js} +3 -3
  33. package/dist/{index-CIF4qQzR.js → index-CGEgwupi.js} +4 -4
  34. package/dist/{index-Dbi75pKH.js → index-CZmdzLaU.js} +3 -3
  35. package/dist/{index-CR2kGrpY.js → index-CeaT_FBl.js} +3 -3
  36. package/dist/{index-DfLCrnVq.js → index-CefLTKmi.js} +2 -2
  37. package/dist/{index-CLdXUpL8.js → index-CfVHzirA.js} +5 -5
  38. package/dist/{index-D0IZW-Up.js → index-CrBanggA.js} +2 -2
  39. package/dist/{index-BlIc9r0r.js → index-Cx5ThXzs.js} +3 -3
  40. package/dist/{index-CZFx44C7.js → index-D0DQjdsq.js} +2 -2
  41. package/dist/{index-DPgw0Cf_.js → index-DH9e_hqJ.js} +2 -2
  42. package/dist/{index-hbS5PDHj.js → index-DTomeh-p.js} +3 -3
  43. package/dist/{index-GpSpJ3ti.js → index-DZGfsazg.js} +3 -3
  44. package/dist/{index-QAs789O5.js → index-DlLnTKv3.js} +2 -2
  45. package/dist/{index-ABUMl7H3.js → index-DqUiBDRo.js} +3 -3
  46. package/dist/{index-CFGO7LRz.js → index-GDUM7K5V.js} +2 -2
  47. package/dist/{index-Db5-PJG-.js → index-Hro6EPZS.js} +2 -2
  48. package/dist/{index-CG8e3146.js → index-KgumaL1c.js} +1 -1
  49. package/dist/{index-XZeturb3.js → index-TemHfU1M.js} +3 -3
  50. package/dist/{index-DKwEe_Tu.js → index-g_Bs6dNr.js} +4 -4
  51. package/dist/{index-S4ylc8JK.js → index-oO_X5wU0.js} +3 -3
  52. package/dist/{index-BqWO6mvz.js → index-ptbBQ53d.js} +4 -4
  53. package/dist/index.js +5 -5
  54. package/dist/{markdownToPlainText-BOtlQ_BY.js → markdownToPlainText-DN_G-I6g.js} +1 -1
  55. package/dist/{useChatKitLabels-CatQSpfL.js → useChatKitLabels-DxW0N5U-.js} +1 -1
  56. package/dist/{useMessageHandler-nnsort0-.js → useMessageHandler-Bkzrdgfj.js} +1 -1
  57. package/package.json +1 -1
  58. package/src/components/base/CkCodeEditor/CkCodeEditor.spec.ts +100 -1
  59. package/src/components/base/CkCodeEditor/CkCodeEditor.stories.ts +3 -1
  60. package/src/components/base/CkCodeEditor/CkCodeEditor.vue +127 -10
  61. package/src/components/base/CkCodeEditor/badgeDecoration.ts +2 -2
  62. package/src/components/base/CkCodeEditor/createCodeMirror.ts +45 -8
  63. package/src/components/base/CkCodeEditor/types.ts +12 -0
  64. package/src/components/base/CkMarkdownRenderer/CkMarkdownRenderer.spec.ts +40 -0
  65. package/src/components/base/CkMarkdownRenderer/CkMarkdownRenderer.stories.ts +31 -0
  66. package/src/components/base/CkMarkdownRenderer/CkMarkdownRenderer.vue +3 -0
  67. package/src/components/base/CkMarkdownRenderer/types.ts +13 -0
  68. package/src/components/base/CkMilkdownEditor/milkdown-theme.css +6 -3
  69. package/src/helpers/codemirror/code-palette.css +23 -3
  70. package/src/helpers/codemirror/theme.ts +44 -8
  71. package/src/helpers/unified/remarkBreaks.ts +32 -0
@@ -139,6 +139,17 @@ const plugins = [uppercasePlugin];
139
139
  <CkMarkdownRenderer :content="content" :plugins="plugins" />
140
140
  </template>`;
141
141
 
142
+ const withLineBreaksTemplateSource = `<script setup lang="ts">
143
+ import { CkMarkdownRenderer } from '@aleph-alpha/chat-kit';
144
+
145
+ // Typed in an editor as three separate lines.
146
+ const content = 'Roses are red\\nViolets are blue\\nMarkdown collapses these';
147
+ </script>
148
+
149
+ <template>
150
+ <CkMarkdownRenderer :content="content" breaks />
151
+ </template>`;
152
+
142
153
  /**
143
154
  * Renders inline Markdown with bold, italic, and inline code. Use as the
144
155
  * default way to display assistant prose replies.
@@ -553,3 +564,23 @@ export const WithUnsupportedAndCodeMarkers: Story = {
553
564
  '<CkMarkdownRenderer :content="content" :citations="citations" />',
554
565
  }),
555
566
  };
567
+
568
+ /**
569
+ * `breaks` keeps single newlines as line breaks. Without it CommonMark treats a
570
+ * lone newline as whitespace, so lines typed separately in an editor run
571
+ * together. A blank line still starts a new paragraph either way, and newlines
572
+ * inside fenced code are never touched.
573
+ */
574
+ export const WithLineBreaks: Story = {
575
+ args: {
576
+ content: [
577
+ 'Roses are red',
578
+ 'Violets are blue',
579
+ 'These three lines were typed separately.',
580
+ '',
581
+ 'This is a new paragraph.',
582
+ ].join('\n'),
583
+ breaks: true,
584
+ },
585
+ parameters: { docs: { source: { code: withLineBreaksTemplateSource } } },
586
+ };
@@ -14,6 +14,7 @@ import {
14
14
  defaultChatKitLabels,
15
15
  useChatKitLabels,
16
16
  } from '../../../handlers/useChatKitLabels';
17
+ import { remarkBreaks } from '../../../helpers/unified/remarkBreaks';
17
18
  import { useCitationRendering } from './useCitationRendering';
18
19
  import type { CkCitationSource } from '../CkCitation';
19
20
  import type { CkMarkdownElementClasses } from './types';
@@ -100,6 +101,7 @@ export default defineComponent({
100
101
  default: () => ({}),
101
102
  },
102
103
  plugins: { type: Array as PropType<PluggableList>, default: undefined },
104
+ breaks: { type: Boolean, default: false },
103
105
  citations: {
104
106
  type: Array as PropType<CkCitationSource[]>,
105
107
  default: undefined,
@@ -123,6 +125,7 @@ export default defineComponent({
123
125
 
124
126
  const effectivePlugins = computed<PluggableList>(() => [
125
127
  ...(props.plugins ?? []),
128
+ ...(props.breaks ? [remarkBreaks] : []),
126
129
  ...citationPlugins.value,
127
130
  ]);
128
131
 
@@ -49,6 +49,19 @@ export interface CkMarkdownRendererProps {
49
49
  * generated HTML elements (e.g. `h1`, `p`, `ul`).
50
50
  */
51
51
  classes?: CkMarkdownElementClasses;
52
+ /**
53
+ * Treat a single newline as a line break, so two lines typed in an editor
54
+ * render as two lines.
55
+ *
56
+ * Off by default, because CommonMark says a lone newline is only whitespace
57
+ * and existing content may rely on that. Turn it on wherever people type the
58
+ * markdown themselves and expect their line breaks to survive; a blank line
59
+ * still starts a new paragraph either way, and newlines inside code spans and
60
+ * fenced blocks are never affected.
61
+ *
62
+ * @default false
63
+ */
64
+ breaks?: boolean;
52
65
  /** Extra [unified](https://unifiedjs.com/) plugins to extend parsing. */
53
66
  plugins?: PluggableList;
54
67
  /**
@@ -412,9 +412,12 @@
412
412
  .milkdown-code-block
413
413
  .cm-lineNumbers
414
414
  .cm-gutterElement {
415
- min-width: 2.25rem;
416
- padding: 0 0.75rem 0 1rem;
417
- color: oklch(var(--content-on-surface-muted));
415
+ /* Geometry and colour come from `theme.ts`, which matches `UiCodeBlock`'s
416
+ * gutter; this rule only exists because Crepe's own code-block styles would
417
+ * otherwise win on specificity. */
418
+ min-width: 4rem;
419
+ padding: 0 1rem;
420
+ color: var(--ck-cm-line-number);
418
421
  text-align: right;
419
422
  }
420
423
 
@@ -15,11 +15,23 @@
15
15
  * Exact parity is not achievable for every token: Shiki classifies with
16
16
  * TextMate grammars and CodeMirror with Lezer, and the two disagree at the
17
17
  * edges. The mapping in `theme.ts` targets the classes that actually occur in
18
- * everyday code.
18
+ * everyday code. Where one Lezer tag covers cases the GitHub themes colour
19
+ * differently, the mapping follows the more common one, which leaves a few
20
+ * known gaps: YAML keys and plain scalars both arrive as tags that mean
21
+ * something else in JavaScript, so they stay unhighlighted; `typeName` is blue
22
+ * here because that is right for TypeScript's primitives, though Rust and Go
23
+ * would want purple and red; and a fenced code block inside a Markdown
24
+ * document is not highlighted in its own language the way Shiki's embedded
25
+ * grammars do it.
19
26
  */
20
27
 
21
28
  .ck-code-surface {
22
- --ck-cm-bg: #ffffff;
29
+ /* Held as bare oklch components, not a hex, because that is the form both
30
+ * `oklch()` and `UiFadeMask`'s surface variable need in order to fade the
31
+ * colour out to zero alpha. `--ck-cm-bg` is derived from it so there is one
32
+ * source of truth. */
33
+ --ck-cm-bg-components: 100% 0 89.88;
34
+ --ck-cm-bg: oklch(var(--ck-cm-bg-components));
23
35
  --ck-cm-foreground: #24292e;
24
36
  --ck-cm-keyword: #d73a49;
25
37
  --ck-cm-string: #032f62;
@@ -34,10 +46,18 @@
34
46
  --ck-cm-tag: #22863a;
35
47
  --ck-cm-error: #b31d28;
36
48
  --ck-cm-selection: oklch(var(--background-accent-soft));
49
+ /* Line numbers. `UiCodeBlock` draws its gutter as the code foreground at
50
+ * 40% opacity rather than as a colour of its own, so this is derived from
51
+ * `--ck-cm-foreground` and needs no dark-mode counterpart. */
52
+ --ck-cm-line-number: color-mix(
53
+ in oklab,
54
+ var(--ck-cm-foreground) 40%,
55
+ transparent
56
+ );
37
57
  }
38
58
 
39
59
  html.dark .ck-code-surface {
40
- --ck-cm-bg: #24292e;
60
+ --ck-cm-bg-components: 27.81% 0.0117 248.25;
41
61
  --ck-cm-foreground: #e1e4e8;
42
62
  --ck-cm-keyword: #f97583;
43
63
  --ck-cm-string: #9ecbff;
@@ -31,11 +31,21 @@ export const ckHighlightStyle = HighlightStyle.define([
31
31
  t.moduleKeyword,
32
32
  t.operatorKeyword,
33
33
  t.operator,
34
+ // CSS units (`px`, `rem`) are `keyword.other.unit` to a TextMate grammar.
35
+ t.unit,
34
36
  ],
35
37
  color: cssVar('keyword'),
36
38
  },
37
39
  {
38
- tag: [t.string, t.special(t.string), t.regexp, t.escape, t.character],
40
+ tag: [
41
+ t.string,
42
+ t.special(t.string),
43
+ t.regexp,
44
+ t.escape,
45
+ t.character,
46
+ // `class="card"` — the quoted value is a string, not a constant.
47
+ t.attributeValue,
48
+ ],
39
49
  color: cssVar('string'),
40
50
  },
41
51
  {
@@ -51,7 +61,8 @@ export const ckHighlightStyle = HighlightStyle.define([
51
61
  t.definition(t.typeName),
52
62
  t.className,
53
63
  t.namespace,
54
- t.self,
64
+ // `entity.other.attribute-name`, which GitHub colours like any entity.
65
+ t.attributeName,
55
66
  ],
56
67
  color: cssVar('function'),
57
68
  },
@@ -68,19 +79,35 @@ export const ckHighlightStyle = HighlightStyle.define([
68
79
  t.typeName,
69
80
  t.standard(t.typeName),
70
81
  t.propertyName,
71
- t.attributeName,
72
- t.attributeValue,
82
+ // `this` / `self` are `variable.language`, which GitHub paints blue.
83
+ t.self,
84
+ // CSS colour literals (`#ff0066`), `constant.other.color-*`.
85
+ t.color,
86
+ // Bare identifiers a grammar cannot classify further — SQL column and
87
+ // table names, for one. Every more specific name tag has its own rule
88
+ // above, so this only catches what would otherwise be unstyled.
89
+ t.name,
73
90
  ],
74
91
  color: cssVar('constant'),
75
92
  },
76
93
  // A declared property name, which UiCodeBlock renders in the text token.
77
94
  { tag: t.definition(t.propertyName), color: cssVar('property') },
78
- { tag: [t.tagName, t.angleBracket], color: cssVar('tag') },
95
+ { tag: t.tagName, color: cssVar('tag') },
96
+ // Markdown blockquotes are `markup.quote`, the same green as a tag name.
97
+ { tag: t.quote, color: cssVar('tag') },
79
98
  {
80
- tag: [t.variableName, t.punctuation, t.bracket, t.separator],
99
+ tag: [
100
+ t.variableName,
101
+ t.punctuation,
102
+ t.bracket,
103
+ t.separator,
104
+ // `<`, `>` and `</` are plain text in the GitHub themes; only the tag
105
+ // name inside them is green.
106
+ t.angleBracket,
107
+ ],
81
108
  color: cssVar('foreground'),
82
109
  },
83
- { tag: t.heading, fontWeight: 'bold' },
110
+ { tag: t.heading, color: cssVar('constant'), fontWeight: 'bold' },
84
111
  { tag: t.strong, fontWeight: 'bold' },
85
112
  { tag: t.emphasis, fontStyle: 'italic' },
86
113
  { tag: t.link, textDecoration: 'underline' },
@@ -116,7 +143,16 @@ export const ckCodeMirrorTheme: Extension = [
116
143
  '.cm-gutters': {
117
144
  backgroundColor: 'transparent',
118
145
  borderRight: 'none',
119
- color: cssVar('comment'),
146
+ color: cssVar('line-number'),
147
+ },
148
+ // `UiCodeBlock` draws its numbers as a 2rem right-aligned column inside the
149
+ // block's 1rem padding, with a 1rem gap before the code. CodeMirror puts
150
+ // the gutter outside `.cm-content`, so the same geometry is expressed as
151
+ // padding on the number cell.
152
+ '.cm-lineNumbers .cm-gutterElement': {
153
+ minWidth: '4rem',
154
+ padding: '0 1rem',
155
+ textAlign: 'right',
120
156
  },
121
157
  '.cm-activeLineGutter': {
122
158
  backgroundColor: 'transparent',
@@ -0,0 +1,32 @@
1
+ import type { Plugin } from 'unified';
2
+ import { findAndReplace } from 'mdast-util-find-and-replace';
3
+
4
+ // A newline that a writer typed inside a paragraph. In CommonMark this is a
5
+ // "soft break", which renders as nothing more than whitespace, so two lines
6
+ // typed in an editor arrive as one flowing line. Block structure (paragraphs,
7
+ // list items, code fences) is already separate nodes by the time this runs, so
8
+ // the only newlines left inside `text` nodes are these soft breaks.
9
+ const SOFT_BREAK_RE = /\r?\n/g;
10
+
11
+ /**
12
+ * Turns every soft line break into a hard one, so a single press of Enter shows
13
+ * up as a line break rather than being collapsed into the previous line.
14
+ *
15
+ * This is what chat interfaces usually want: people type a message the way they
16
+ * would in any other text box and expect the lines they made to survive. Strict
17
+ * CommonMark instead requires two trailing spaces, a backslash, or a blank line
18
+ * to force a break.
19
+ *
20
+ * `findAndReplace` only visits `text` nodes, so newlines inside code spans and
21
+ * fenced code blocks are untouched and keep their literal meaning.
22
+ */
23
+ // The tree type is left as unified's default (a unist `Node`) so the published
24
+ // `.d.ts` does not depend on `mdast` types; the cast keeps the call typed.
25
+ export const remarkBreaks: Plugin<[]> = () => {
26
+ return (tree) => {
27
+ findAndReplace(tree as Parameters<typeof findAndReplace>[0], [
28
+ SOFT_BREAK_RE,
29
+ () => ({ type: 'break' }),
30
+ ]);
31
+ };
32
+ };