@k2b/cloud 0.27.0 → 0.28.0

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 (79) hide show
  1. package/package.json +2 -2
  2. package/src/ai/browser-code-contracts.ts +33 -63
  3. package/src/ai/browser.ts +1 -0
  4. package/src/ai/chat/blocks.tsx +16 -7
  5. package/src/ai/chat/live-turn.browser-harness.tsx +6 -3
  6. package/src/ai/chat/message-actions.tsx +123 -101
  7. package/src/ai/chat/message-utils.ts +30 -1
  8. package/src/ai/chat/messages.ts +198 -0
  9. package/src/ai/chat/presentation.tsx +66 -20
  10. package/src/ai/chat/tool-groups.ts +1 -1
  11. package/src/ai/chat/turn-error.ts +21 -0
  12. package/src/ai/chat/turn-view.tsx +55 -4
  13. package/src/ai/chat/user-message.tsx +19 -14
  14. package/src/ai/chat/visual-tools.tsx +1 -1
  15. package/src/ai/client/controller.ts +23 -6
  16. package/src/ai/code-mode-skill.ts +21 -25
  17. package/src/ai/code-runtime-tools.ts +5 -1
  18. package/src/ai/code-source-contracts.ts +2 -2
  19. package/src/ai/data-analysis-skill.ts +3 -3
  20. package/src/ai/default-tools.ts +15 -16
  21. package/src/ai/executor.ts +135 -59
  22. package/src/ai/index.ts +2 -0
  23. package/src/ai/open-tool-calls.ts +87 -0
  24. package/src/ai/routes.ts +6 -0
  25. package/src/ai/run-timeout.ts +4 -5
  26. package/src/ai/runtime.ts +8 -0
  27. package/src/ai/skill-seeds.ts +4 -4
  28. package/src/ai/store.ts +46 -14
  29. package/src/ai/system-prompt.ts +4 -21
  30. package/src/ai/turn-failure.ts +100 -0
  31. package/src/ai/turn-policy.ts +2 -1
  32. package/src/ai/types.ts +28 -1
  33. package/src/api/admin-outgoing-mail.ts +185 -5
  34. package/src/browser/FileChooser.tsx +11 -0
  35. package/src/browser/file-chooser-messages.ts +2 -0
  36. package/src/cli/admin/index.ts +3 -1
  37. package/src/cli/admin/notifications.ts +6 -0
  38. package/src/cli/admin/outgoing-mail.ts +104 -7
  39. package/src/contracts/outgoing-mail.ts +189 -1
  40. package/src/services/help/store.ts +2 -1
  41. package/src/services/index.ts +11 -1
  42. package/src/services/notifications/batches.ts +139 -79
  43. package/src/services/notifications/channels.ts +33 -13
  44. package/src/services/notifications/dispatcher.ts +57 -5
  45. package/src/services/notifications/email-frame.fixture.html +51 -0
  46. package/src/services/notifications/{email.ts → email-frame.ts} +12 -35
  47. package/src/services/notifications/email-mail.ts +101 -0
  48. package/src/services/notifications/index.ts +49 -36
  49. package/src/services/notifications/observability.ts +9 -1
  50. package/src/services/notifications/platform.ts +1 -1
  51. package/src/services/notifications/runtime.ts +9 -3
  52. package/src/services/outgoing-mail/admin.ts +84 -0
  53. package/src/services/outgoing-mail/attachments.ts +135 -0
  54. package/src/services/outgoing-mail/bulk.ts +11 -0
  55. package/src/services/outgoing-mail/dispatcher.ts +231 -0
  56. package/src/services/outgoing-mail/drain.ts +60 -0
  57. package/src/services/outgoing-mail/enqueue.ts +180 -0
  58. package/src/services/outgoing-mail/index.ts +103 -10
  59. package/src/services/outgoing-mail/message.ts +14 -0
  60. package/src/services/outgoing-mail/messages.ts +431 -0
  61. package/src/services/outgoing-mail/retention.ts +48 -0
  62. package/src/services/outgoing-mail/runtime.ts +72 -0
  63. package/src/services/outgoing-mail/send.ts +130 -0
  64. package/src/services/outgoing-mail/store.ts +115 -4
  65. package/src/services/outgoing-mail/sync.ts +39 -0
  66. package/src/services/outgoing-mail/transport.ts +5 -1
  67. package/src/services/pdf/markdown.ts +22 -4
  68. package/src/services/postgres.ts +15 -0
  69. package/src/services/settings/core-settings.ts +18 -0
  70. package/src/shared/ai-platform-prompt.ts +48 -4
  71. package/src/shared/markdown/extensions/links.ts +28 -20
  72. package/src/shared/markdown/index.ts +14 -5
  73. package/src/shared/markdown/shared.ts +0 -7
  74. package/src/ssr/GlobalAnnouncements.island.tsx +1 -1
  75. package/src/ssr/platform-messages.ts +1 -1
  76. package/src/styles/effects.css +15 -17
  77. package/src/styles/tokens.css +2 -0
  78. package/src/styles/utilities-markdown-editor.css +4 -39
  79. package/src/styles/utilities-markdown-table.css +14 -17
@@ -112,7 +112,7 @@
112
112
  }
113
113
 
114
114
  .assistant-markdown-block :where(.md-table-wrap) {
115
- margin-block: 1.125rem;
115
+ margin-block: calc(1.125rem - var(--md-table-bleed)) 1.125rem;
116
116
  }
117
117
 
118
118
  .assistant-markdown-block :where(hr) {
@@ -155,19 +155,6 @@
155
155
  margin-block: 0.25rem;
156
156
  }
157
157
 
158
- .assistant-markdown-block :where(a) {
159
- @apply text-blue-600 underline underline-offset-2 dark:text-blue-300;
160
- }
161
-
162
- .assistant-markdown-block :where(a.md-link-widget) {
163
- color: inherit;
164
- text-decoration: none;
165
- }
166
-
167
- .assistant-markdown-block :where(a.md-link-widget:hover) {
168
- color: var(--ui-app-accent-text);
169
- }
170
-
171
158
  .assistant-markdown-block :where(code) {
172
159
  @apply rounded bg-zinc-100 px-1 py-0.5 text-[0.85em] text-primary dark:bg-zinc-900;
173
160
  }
@@ -669,9 +656,10 @@
669
656
  padding: 0;
670
657
  }
671
658
 
659
+ /* The shared wrapper clips without becoming a scroll box, so scrolling a cell
660
+ into view cannot shift the table under its column bands. */
672
661
  .help-document .md-table-wrap {
673
- overflow: hidden;
674
- margin-block: 0.875rem 1.5rem;
662
+ margin-block: calc(0.875rem - var(--md-table-bleed)) 1.5rem;
675
663
  }
676
664
 
677
665
  .help-document .md-table-wrap > .md-table {
@@ -701,7 +689,8 @@
701
689
  background: transparent;
702
690
  box-shadow: none;
703
691
  overflow-wrap: break-word;
704
- padding: 0.65rem 0.75rem;
692
+ /* The row fill and column band reach as far past the text on every side. */
693
+ padding: var(--md-table-bleed);
705
694
  font-size: 0.78rem;
706
695
  line-height: 1.45;
707
696
  word-break: normal;
@@ -894,3 +883,12 @@ dialog:has(.launchpad-panel)::backdrop {
894
883
  linear-gradient(180deg, var(--rim-top-hover), var(--rim-bottom-hover)) border-box;
895
884
  color: var(--glyph-hover);
896
885
  }
886
+
887
+ /* Response details: one quiet label/value list per section, one type size, no grid lines. */
888
+ .k2b-ui .ai-response-info__rows { display: grid; gap: 0.375rem; margin: 0; font-size: 0.8125rem; }
889
+ .k2b-ui .ai-response-info__rows > div { display: flex; min-width: 0; align-items: baseline; justify-content: space-between; gap: 1.5rem; }
890
+ .k2b-ui .ai-response-info__rows dt { display: flex; min-width: 0; flex-direction: column; color: var(--k2b-text-muted); }
891
+ .k2b-ui .ai-response-info__rows dt > span { font-size: 0.75rem; }
892
+ .k2b-ui .ai-response-info__rows dd { min-width: 0; margin: 0; overflow: hidden; color: var(--k2b-text); text-align: end; text-overflow: ellipsis; white-space: nowrap; font-variant-numeric: tabular-nums; }
893
+ .k2b-ui .ai-response-info__tools { display: flex; flex-wrap: wrap; gap: 0.25rem 1rem; margin: 0; padding: 0; list-style: none; font-size: 0.8125rem; color: var(--k2b-text-secondary); }
894
+ .k2b-ui .ai-response-info__tools > li { display: inline-flex; align-items: center; gap: 0.375rem; }
@@ -198,6 +198,7 @@
198
198
  it to the active app appearance. */
199
199
  --k2b-app-workspace-active: var(--ui-app-accent-text);
200
200
  --k2b-detail-panel-accent: var(--ui-app-accent-text);
201
+ --k2b-link-accent: var(--ui-app-accent-text);
201
202
  }
202
203
 
203
204
  .dark :is(.cloud-app-canvas, .app-accent-scope) {
@@ -205,6 +206,7 @@
205
206
  --ui-app-accent-border: color-mix(in srgb, var(--app-accent, var(--color-blue-400)) 58%, white);
206
207
  --k2b-app-workspace-active: var(--ui-app-accent-text);
207
208
  --k2b-detail-panel-accent: var(--ui-app-accent-text);
209
+ --k2b-link-accent: var(--ui-app-accent-text);
208
210
  }
209
211
 
210
212
  @utility slider-track-colors {
@@ -410,49 +410,14 @@
410
410
  @apply bg-zinc-200/60 dark:bg-zinc-700/50 rounded-sm;
411
411
  }
412
412
 
413
- /* Links — color + underline, both width-safe */
413
+ /* Links — the rendered web link's thin accent underline, width-safe */
414
414
  .md-link {
415
- @apply text-blue-600 dark:text-blue-400 underline;
415
+ text-decoration-line: underline;
416
+ text-decoration-thickness: 1px;
417
+ text-decoration-color: color-mix(in srgb, var(--k2b-link-accent) 55%, transparent);
416
418
  text-underline-offset: 2px;
417
419
  }
418
420
 
419
- /* Rendered links use one anchor for their complete visible hit area. */
420
- .md-link-widget {
421
- display: inline-flex;
422
- align-items: baseline;
423
- gap: 0.125rem;
424
- color: inherit;
425
- font-weight: 600;
426
- text-decoration: none;
427
- transition: color 150ms ease;
428
- }
429
-
430
- .md-link-widget:hover {
431
- color: var(--ui-app-accent-text);
432
- }
433
-
434
- /* The brackets, weight and icon already mark the widget as a link, so it
435
- keeps no underline inside MarkdownView, the same as in Assistant chat. */
436
- .k2b-ui .k2b-content-markdown a.md-link-widget {
437
- text-decoration: none;
438
- }
439
-
440
- .md-link-widget:focus-visible {
441
- border-radius: 0.125rem;
442
- outline: var(--k2b-focus-width) solid var(--ui-app-accent-border);
443
- outline-offset: var(--k2b-focus-offset);
444
- }
445
-
446
- .md-link-icon {
447
- opacity: 0.7;
448
- transition: opacity 150ms ease;
449
- }
450
-
451
- .md-link-widget:hover .md-link-icon,
452
- .md-link-widget:focus-visible .md-link-icon {
453
- opacity: 1;
454
- }
455
-
456
421
  /* Blockquote — color + inset box-shadow for the left bar (box-shadow
457
422
  doesn't affect layout, unlike border-left or padding-left). The bar
458
423
  sits visually outside the text column edge so prose stays aligned. */
@@ -1,9 +1,14 @@
1
1
  /* Markdown tables use the same hairline language as @k2b/ui MarkdownView:
2
2
  no frame or header fill, a stronger line under the header, hairline row
3
- separators, and the outer columns flush with the prose. Used by both the
3
+ separators, and the outer text flush with the prose. Used by both the
4
4
  server-side `marked` renderer and the CodeMirror table widget so read-mode
5
5
  and edit-mode look identical.
6
6
 
7
+ The table bleeds `--md-table-bleed` past the prose on both sides, and every
8
+ cell pads its text by the same amount. So the outer text stays flush, the
9
+ columns sit twice the bleed apart, and the header line, row lines, row hover
10
+ and column band all share one width: text plus the bleed on every side.
11
+
7
12
  Three-layer markup:
8
13
  <div class="md-table-wrap"> ← horizontal scroll owner
9
14
  <table class="md-table"> ← table layout
@@ -11,16 +16,17 @@
11
16
  <span class="md-table-cell"> ← content + alignment owner */
12
17
 
13
18
  .md-table-wrap {
19
+ --md-table-bleed: 0.5rem;
14
20
  overflow: clip;
15
- margin-top: 0.5rem;
16
- margin-bottom: 0.5rem;
21
+ /* The header cell's top padding takes the place of a top margin. */
22
+ margin: 0 calc(-1 * var(--md-table-bleed)) 0.5rem;
17
23
  }
18
24
 
19
25
  /* Inside MarkdownView a table takes the same block spacing as its own
20
26
  tables, so two tables in a row do not read as one. Hosts such as Help keep
21
27
  their own spacing. */
22
28
  :where(.k2b-ui .k2b-content-markdown) .md-table-wrap {
23
- margin-block: 1em;
29
+ margin-block: calc(1em - var(--md-table-bleed)) 1em;
24
30
  }
25
31
 
26
32
  .md-table {
@@ -70,7 +76,7 @@
70
76
  gap: 0.35rem;
71
77
  box-sizing: border-box;
72
78
  min-height: 2rem;
73
- padding: 0.5rem 0.75rem;
79
+ padding: 0.5rem var(--md-table-bleed, 0.5rem);
74
80
  border: 0;
75
81
  border-radius: 0;
76
82
  background: transparent;
@@ -88,21 +94,10 @@
88
94
  }
89
95
 
90
96
  .md-table thead .md-table-cell {
91
- padding-top: 0;
92
97
  background: transparent;
93
98
  font-weight: 600;
94
99
  }
95
100
 
96
- .md-table th:first-child > .md-table-cell,
97
- .md-table td:first-child > .md-table-cell {
98
- padding-left: 0;
99
- }
100
-
101
- .md-table th:last-child > .md-table-cell,
102
- .md-table td:last-child > .md-table-cell {
103
- padding-right: 0;
104
- }
105
-
106
101
  /* Inside MarkdownView the span stays the only padding owner. */
107
102
  .k2b-ui .k2b-content-markdown .md-table th,
108
103
  .k2b-ui .k2b-content-markdown .md-table td {
@@ -147,7 +142,9 @@
147
142
  }
148
143
 
149
144
  /* A cell-sized pseudo-element can span the table vertically without
150
- changing its layout. The scroll wrapper clips it to the table frame. */
145
+ changing its layout. The scroll wrapper clips it to the table frame, so
146
+ the band, like the row, reaches the bleed above the header text and
147
+ below the last row. */
151
148
  .md-table :is(th, td)::after {
152
149
  content: "";
153
150
  position: absolute;