@k2b/cloud 0.31.0 → 0.32.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 (119) hide show
  1. package/package.json +6 -4
  2. package/src/_internal/define-app.ts +3 -1
  3. package/src/ai/app-skills.ts +1 -7
  4. package/src/ai/audio-tool.ts +2 -1
  5. package/src/ai/browser.ts +109 -0
  6. package/src/ai/capabilities.ts +6 -2
  7. package/src/ai/chart-block.ts +431 -81
  8. package/src/ai/chat/action-sentences.ts +13 -7
  9. package/src/ai/chat/blocks.tsx +11 -7
  10. package/src/ai/chat/builtin-tools.tsx +9 -7
  11. package/src/ai/chat/chart-block.tsx +218 -44
  12. package/src/ai/chat/explorer-block.tsx +276 -0
  13. package/src/ai/chat/file-tools.tsx +40 -1
  14. package/src/ai/chat/message-actions.tsx +6 -0
  15. package/src/ai/chat/message-utils.ts +7 -0
  16. package/src/ai/chat/messages.ts +16 -0
  17. package/src/ai/chat/presentation.tsx +13 -3
  18. package/src/ai/chat/reference-text.tsx +34 -0
  19. package/src/ai/chat/tool-groups.ts +1 -0
  20. package/src/ai/chat/tool-names.ts +14 -0
  21. package/src/ai/chat/turn-view.tsx +17 -7
  22. package/src/ai/chat/view-block.browser-harness.tsx +35 -0
  23. package/src/ai/chat/view-block.tsx +417 -0
  24. package/src/ai/chat/visual-tools.tsx +32 -53
  25. package/src/ai/client-tool-results.ts +9 -0
  26. package/src/ai/default-tool-contracts.ts +334 -91
  27. package/src/ai/default-tools.ts +87 -11
  28. package/src/ai/executor.ts +173 -31
  29. package/src/ai/file-error.ts +2 -0
  30. package/src/ai/file-tools.ts +27 -7
  31. package/src/ai/files-store.ts +60 -0
  32. package/src/ai/html-pdf-tool.ts +3 -2
  33. package/src/ai/http.ts +37 -12
  34. package/src/ai/index.ts +90 -0
  35. package/src/ai/local-tool-contracts.ts +244 -0
  36. package/src/ai/malformed-tool-call-repair.ts +144 -0
  37. package/src/ai/markdown-pdf-tool.ts +2 -1
  38. package/src/ai/migrate.ts +7 -0
  39. package/src/ai/openai-api-messages.ts +53 -0
  40. package/src/ai/openai-api-slots.ts +40 -0
  41. package/src/ai/openai-api.ts +383 -0
  42. package/src/ai/protocol.ts +6 -2
  43. package/src/ai/provider.ts +16 -4
  44. package/src/ai/request-context.ts +33 -0
  45. package/src/ai/routes.ts +96 -57
  46. package/src/ai/runtime.ts +48 -12
  47. package/src/ai/settings.ts +5 -0
  48. package/src/ai/skill-catalog.ts +20 -5
  49. package/src/ai/skill-format.ts +17 -7
  50. package/src/ai/skill-tool.ts +15 -5
  51. package/src/ai/skills-routes.ts +20 -6
  52. package/src/ai/skills.ts +26 -7
  53. package/src/ai/store.ts +25 -0
  54. package/src/ai/system-prompt.ts +69 -10
  55. package/src/ai/timeline.ts +3 -1
  56. package/src/ai/tools.ts +3 -0
  57. package/src/ai/types.ts +9 -0
  58. package/src/ai/view-block.ts +941 -0
  59. package/src/ai/vision-tool.ts +2 -1
  60. package/src/api/admin-identity.ts +6 -1
  61. package/src/api/app-approval-actions.ts +36 -0
  62. package/src/api/app-approval.ts +10 -2
  63. package/src/api/approvals-loader.ts +15 -0
  64. package/src/api/approvals.ts +120 -0
  65. package/src/api/index.ts +3 -0
  66. package/src/api/me.ts +12 -3
  67. package/src/approvals/Approvals.browser-harness.tsx +16 -0
  68. package/src/approvals/Approvals.tsx +621 -0
  69. package/src/approvals/ApprovalsNavStatus.tsx +20 -0
  70. package/src/approvals/messages.ts +95 -0
  71. package/src/approvals/ui.ts +8 -0
  72. package/src/browser/app-approval.ts +32 -0
  73. package/src/browser/choose-files.tsx +26 -13
  74. package/src/browser/commands.ts +13 -4
  75. package/src/browser/file-provider-error.ts +11 -0
  76. package/src/browser/file-providers.ts +3 -12
  77. package/src/browser/files.tsx +1 -2
  78. package/src/browser/live-connection.ts +2 -3
  79. package/src/browser/provider-list.ts +2 -1
  80. package/src/browser/save-files.tsx +13 -2
  81. package/src/cli/account.ts +21 -2
  82. package/src/cli/commands.ts +4 -2
  83. package/src/contracts/app-approval.ts +120 -0
  84. package/src/contracts/approval-paths.ts +4 -0
  85. package/src/contracts/approvals.ts +81 -0
  86. package/src/contracts/command-path.ts +17 -0
  87. package/src/contracts/commands.ts +5 -15
  88. package/src/contracts/shared.ts +5 -0
  89. package/src/events/live-protocol.ts +2 -1
  90. package/src/events/live-server-message.ts +40 -0
  91. package/src/events/testing.ts +88 -0
  92. package/src/server/index.ts +2 -0
  93. package/src/server/middleware/auth.ts +11 -1
  94. package/src/server/request-timeout.ts +22 -0
  95. package/src/server/services/access.ts +4 -3
  96. package/src/services/app-approval.ts +103 -15
  97. package/src/services/approvals/cursor.ts +15 -0
  98. package/src/services/approvals/device.ts +112 -0
  99. package/src/services/approvals/index.ts +27 -11
  100. package/src/services/approvals/list.ts +120 -0
  101. package/src/services/approvals/migrate.ts +9 -1
  102. package/src/services/identity/models-only-auth.ts +25 -0
  103. package/src/services/notifications/email-frame.ts +16 -3
  104. package/src/services/service-account-credentials.ts +22 -10
  105. package/src/services/settings/core-settings.ts +27 -0
  106. package/src/shared/ai-platform-prompt.ts +26 -1
  107. package/src/shared/email-html.ts +4 -0
  108. package/src/shared/index.ts +6 -1
  109. package/src/shared/markdown/extensions/code.ts +14 -0
  110. package/src/shared/markdown/index.ts +4 -4
  111. package/src/ssr/AppBadge.tsx +4 -4
  112. package/src/ssr/AppLaunchpadPanel.tsx +4 -4
  113. package/src/ssr/RailApps.island.tsx +2 -2
  114. package/src/ssr/app-badges.ts +50 -6
  115. package/src/ssr/page-trail.browser-harness.tsx +52 -3
  116. package/src/ssr/rail-navigation.ts +5 -3
  117. package/src/ssr/runtime.ts +6 -1
  118. package/src/styles/approvals.css +390 -0
  119. package/src/styles/global.css +5 -2
@@ -0,0 +1,390 @@
1
+ /* Pending Action approvals (`@k2b/cloud/approvals/ui`). A flat list: rows are set apart by space, not by lines or
2
+ boxes. A decided row keeps its content and height and turns its decision into a receipt in the same slot. */
3
+ .k2b-ui .cloud-approvals {
4
+ display: grid;
5
+ min-width: 0;
6
+ gap: 1rem;
7
+ }
8
+
9
+ .k2b-ui .cloud-approvals__toolbar {
10
+ display: flex;
11
+ min-height: 1.75rem;
12
+ align-items: center;
13
+ justify-content: space-between;
14
+ gap: 0.75rem;
15
+ color: var(--k2b-text-muted);
16
+ font-size: 0.75rem;
17
+ }
18
+
19
+ .k2b-ui .cloud-approvals__list {
20
+ display: grid;
21
+ min-width: 0;
22
+ gap: 2rem;
23
+ }
24
+
25
+ .k2b-ui .cloud-approvals__group {
26
+ display: grid;
27
+ min-width: 0;
28
+ gap: 1rem;
29
+ }
30
+
31
+ .k2b-ui .cloud-approvals__group + .cloud-approvals__group {
32
+ margin-top: 1rem;
33
+ }
34
+
35
+ .k2b-ui .cloud-approvals__group-title {
36
+ display: flex;
37
+ align-items: center;
38
+ gap: 0.5rem;
39
+ margin: 0;
40
+ color: var(--k2b-text);
41
+ font-size: 0.8125rem;
42
+ font-weight: 600;
43
+ }
44
+
45
+ .k2b-ui .cloud-approvals__more {
46
+ display: flex;
47
+ flex-wrap: wrap;
48
+ align-items: center;
49
+ justify-content: center;
50
+ gap: 0.5rem 0.75rem;
51
+ }
52
+
53
+ .k2b-ui .cloud-approvals__more-error {
54
+ display: inline-flex;
55
+ align-items: center;
56
+ gap: 0.375rem;
57
+ margin: 0;
58
+ color: var(--k2b-danger-text);
59
+ font-size: 0.75rem;
60
+ }
61
+
62
+ .k2b-ui .cloud-approvals__elsewhere {
63
+ display: flex;
64
+ flex-wrap: wrap;
65
+ align-items: center;
66
+ justify-content: space-between;
67
+ gap: 0.5rem 1rem;
68
+ margin: 0.5rem 0 0;
69
+ color: var(--k2b-text-muted);
70
+ font-size: 0.75rem;
71
+ }
72
+
73
+ .k2b-ui .cloud-approvals__elsewhere a {
74
+ display: inline-flex;
75
+ align-items: center;
76
+ gap: 0.25rem;
77
+ color: var(--k2b-link-accent);
78
+ font-weight: 500;
79
+ }
80
+
81
+ .k2b-ui .cloud-approval {
82
+ display: grid;
83
+ min-width: 0;
84
+ gap: 0.875rem;
85
+ grid-template-columns: 2rem minmax(0, 1fr);
86
+ }
87
+
88
+ .k2b-ui .cloud-approval__icon {
89
+ display: grid;
90
+ width: 2rem;
91
+ height: 2rem;
92
+ place-items: center;
93
+ border-radius: var(--k2b-radius-control);
94
+ color: var(--k2b-text-secondary);
95
+ background: var(--k2b-surface-muted);
96
+ font-size: 1rem;
97
+ }
98
+
99
+ /* Only an approval is a success; a rejection or a decision that did not apply keeps the neutral icon tile. */
100
+ .k2b-ui .cloud-approval[data-decided="approved"] .cloud-approval__icon {
101
+ color: var(--k2b-success-text);
102
+ background: var(--k2b-success-surface);
103
+ }
104
+
105
+ .k2b-ui .cloud-approval__main {
106
+ display: grid;
107
+ min-width: 0;
108
+ gap: 0.75rem;
109
+ container-type: inline-size;
110
+ }
111
+
112
+ .k2b-ui .cloud-approval__content {
113
+ display: grid;
114
+ min-width: 0;
115
+ gap: 0.5rem;
116
+ transition: opacity 150ms ease-out;
117
+ }
118
+
119
+ .k2b-ui .cloud-approval[data-decided] .cloud-approval__content {
120
+ opacity: 0.55;
121
+ }
122
+
123
+ .k2b-ui .cloud-approval__title,
124
+ .k2b-ui .cloud-approval__sheet-title {
125
+ margin: 0;
126
+ color: var(--k2b-text);
127
+ font-size: 0.875rem;
128
+ font-weight: 600;
129
+ line-height: 1.4;
130
+ overflow-wrap: anywhere;
131
+ }
132
+
133
+ .k2b-ui .cloud-approval__sheet-title {
134
+ font-size: 1.0625rem;
135
+ }
136
+
137
+ .k2b-ui .cloud-approval__origin {
138
+ margin: -0.25rem 0 0;
139
+ color: var(--k2b-text-muted);
140
+ font-size: 0.75rem;
141
+ overflow-wrap: anywhere;
142
+ }
143
+
144
+ .k2b-ui .cloud-approval__origin a {
145
+ color: inherit;
146
+ text-decoration: underline;
147
+ text-decoration-color: color-mix(in srgb, currentColor 35%, transparent);
148
+ text-underline-offset: 0.15em;
149
+ }
150
+
151
+ .k2b-ui .cloud-approval__origin a:hover {
152
+ color: var(--k2b-text);
153
+ }
154
+
155
+ .k2b-ui .cloud-approval__text {
156
+ margin: 0;
157
+ color: var(--k2b-text-secondary);
158
+ font-size: 0.8125rem;
159
+ white-space: pre-wrap;
160
+ overflow-wrap: anywhere;
161
+ }
162
+
163
+ .k2b-ui .cloud-approval__fields {
164
+ display: grid;
165
+ margin: 0;
166
+ gap: 0.25rem 1rem;
167
+ grid-template-columns: max-content minmax(0, 1fr);
168
+ font-size: 0.75rem;
169
+ }
170
+
171
+ .k2b-ui .cloud-approval__fields dt,
172
+ .k2b-ui .cloud-approval__label {
173
+ margin: 0;
174
+ color: var(--k2b-text-muted);
175
+ font-size: 0.75rem;
176
+ font-weight: 500;
177
+ }
178
+
179
+ .k2b-ui .cloud-approval__fields dd {
180
+ min-width: 0;
181
+ margin: 0;
182
+ color: var(--k2b-text);
183
+ white-space: pre-wrap;
184
+ overflow-wrap: anywhere;
185
+ }
186
+
187
+ .k2b-ui .cloud-approval__block {
188
+ display: grid;
189
+ min-width: 0;
190
+ gap: 0.25rem;
191
+ }
192
+
193
+ /* Long content sits inset, so it reads as quoted from the app without a frame or a rule. */
194
+ .k2b-ui .cloud-approval__quote,
195
+ .k2b-ui .cloud-approval__markdown {
196
+ margin: 0;
197
+ padding: 0.5rem 0.75rem;
198
+ border-radius: var(--k2b-radius-control);
199
+ color: var(--k2b-text-secondary);
200
+ background: var(--k2b-surface-muted);
201
+ font-size: 0.75rem;
202
+ line-height: 1.55;
203
+ white-space: pre-wrap;
204
+ overflow-wrap: anywhere;
205
+ }
206
+
207
+ /* The inner text clamps, so the quote's padding never shows a cut line. */
208
+ .k2b-ui .cloud-approval__quote[data-clamp] > span {
209
+ display: -webkit-box;
210
+ overflow: hidden;
211
+ -webkit-box-orient: vertical;
212
+ -webkit-line-clamp: 3;
213
+ }
214
+
215
+ .k2b-ui .cloud-approval__links {
216
+ display: flex;
217
+ flex-wrap: wrap;
218
+ gap: 0.25rem;
219
+ margin-left: -0.625rem;
220
+ }
221
+
222
+ .k2b-ui .cloud-approval__sheet {
223
+ display: grid;
224
+ min-width: 0;
225
+ gap: 1rem;
226
+ }
227
+
228
+ .k2b-ui .cloud-approval__sheet-foot {
229
+ width: 100%;
230
+ container-type: inline-size;
231
+ }
232
+
233
+ .k2b-ui .cloud-approval__callout {
234
+ display: flex;
235
+ align-items: flex-start;
236
+ gap: 0.5rem;
237
+ margin: 0;
238
+ color: var(--k2b-text-muted);
239
+ font-size: 0.75rem;
240
+ }
241
+
242
+ .k2b-ui .cloud-approval__callout i {
243
+ margin-top: 0.125rem;
244
+ }
245
+
246
+ /* The foot keeps its height in every state: the note is one line, and the decision slot keeps one button height, so a
247
+ receipt replaces the buttons without moving anything. A narrow row puts the decision on a line of its own. */
248
+ .k2b-ui .cloud-approval__foot {
249
+ display: grid;
250
+ min-width: 0;
251
+ align-items: center;
252
+ gap: 0.5rem 1rem;
253
+ grid-template-columns: minmax(0, 1fr) auto;
254
+ }
255
+
256
+ .k2b-ui .cloud-approval__note {
257
+ display: flex;
258
+ min-width: 0;
259
+ align-items: center;
260
+ gap: 0.375rem;
261
+ color: var(--k2b-text-muted);
262
+ font-size: 0.75rem;
263
+ white-space: nowrap;
264
+ }
265
+
266
+ .k2b-ui .cloud-approval__note > span {
267
+ min-width: 0;
268
+ overflow: hidden;
269
+ text-overflow: ellipsis;
270
+ }
271
+
272
+ .k2b-ui .cloud-approval__note[data-tone="danger"] {
273
+ color: var(--k2b-danger-text);
274
+ }
275
+
276
+ .k2b-ui .cloud-approval__actions {
277
+ display: flex;
278
+ min-height: 1.75rem;
279
+ min-width: 0;
280
+ align-items: center;
281
+ justify-content: flex-end;
282
+ gap: 0.375rem;
283
+ }
284
+
285
+ @container (max-width: 32rem) {
286
+ .k2b-ui .cloud-approval__foot {
287
+ grid-template-columns: minmax(0, 1fr);
288
+ }
289
+
290
+ /* The decision shares the width; a receipt keeps the same line. */
291
+ .k2b-ui .cloud-approval__actions > .k2b-button,
292
+ .k2b-ui .cloud-approval__actions > .k2b-split-button {
293
+ flex: 1;
294
+ min-width: 0;
295
+ justify-content: center;
296
+ }
297
+ }
298
+
299
+ .k2b-ui .cloud-approval__receipt {
300
+ display: inline-flex;
301
+ align-items: center;
302
+ gap: 0.375rem;
303
+ color: var(--k2b-text-muted);
304
+ font-size: 0.75rem;
305
+ font-weight: 500;
306
+ }
307
+
308
+ .k2b-ui .cloud-approval__receipt[data-outcome="approved"] {
309
+ color: var(--k2b-success-text);
310
+ }
311
+
312
+ /* The band sits above the resource a request would change, tinted like the approval card in a chat. */
313
+ .k2b-ui .cloud-approval-bands {
314
+ display: grid;
315
+ gap: 0.5rem;
316
+ }
317
+
318
+ /* Two rows in every width: the decision never shares a line with the title, so a receipt cannot rewrap it. */
319
+ .k2b-ui .cloud-approval-band {
320
+ display: grid;
321
+ min-width: 0;
322
+ align-items: center;
323
+ gap: 0.5rem 0.75rem;
324
+ grid-template-columns: auto minmax(0, 1fr);
325
+ container-type: inline-size;
326
+ padding: 0.75rem 1rem;
327
+ /* Transparent, so forced colours still draw an outline where the tint disappears. */
328
+ border: 1px solid transparent;
329
+ border-radius: var(--k2b-radius-surface);
330
+ color: var(--k2b-text-secondary);
331
+ background: color-mix(in srgb, var(--k2b-warning-surface) 70%, var(--k2b-surface-canvas));
332
+ font-size: 0.8125rem;
333
+ }
334
+
335
+ .k2b-ui.k2b-dark .cloud-approval-band,
336
+ .dark .k2b-ui .cloud-approval-band {
337
+ background: color-mix(in srgb, var(--k2b-warning-surface) 55%, var(--k2b-surface-canvas));
338
+ }
339
+
340
+ .k2b-ui .cloud-approval-band > i {
341
+ color: var(--k2b-warning-text);
342
+ font-size: 1.125rem;
343
+ }
344
+
345
+ .k2b-ui .cloud-approval-band[data-decided] {
346
+ background: var(--k2b-surface-muted);
347
+ }
348
+
349
+ .k2b-ui .cloud-approval-band[data-decided] > i {
350
+ color: var(--k2b-text-muted);
351
+ }
352
+
353
+ .k2b-ui .cloud-approval-band[data-decided="approved"] > i {
354
+ color: var(--k2b-success-text);
355
+ }
356
+
357
+ .k2b-ui .cloud-approval-band__text {
358
+ display: grid;
359
+ min-width: 0;
360
+ gap: 0.125rem;
361
+ }
362
+
363
+ .k2b-ui .cloud-approval-band__text strong {
364
+ color: var(--k2b-text);
365
+ font-weight: 600;
366
+ overflow-wrap: anywhere;
367
+ }
368
+
369
+ .k2b-ui .cloud-approval-band__text .cloud-approval__origin {
370
+ margin: 0;
371
+ }
372
+
373
+ .k2b-ui .cloud-approval-band > .cloud-approval__foot {
374
+ grid-column: 2;
375
+ }
376
+
377
+ @media (max-width: 40rem) {
378
+ .k2b-ui .cloud-approval {
379
+ gap: 0.75rem;
380
+ }
381
+
382
+ .k2b-ui .cloud-approval__fields {
383
+ grid-template-columns: minmax(0, 1fr);
384
+ gap: 0;
385
+ }
386
+
387
+ .k2b-ui .cloud-approval__fields dd {
388
+ margin-bottom: 0.35rem;
389
+ }
390
+ }
@@ -28,6 +28,7 @@
28
28
  @import "./utilities-markdown-editor.css";
29
29
  @import "./base-popover.css";
30
30
  @import "./effects.css";
31
+ @import "./approvals.css";
31
32
  @import "./input.css";
32
33
  @import "./resource-search.css";
33
34
  @import "./file-chooser.css";
@@ -123,7 +124,9 @@ html:has(.cloud-app-canvas[data-layout-full-page="true"]) {
123
124
  height: 100%;
124
125
  }
125
126
 
126
- :root .stdlib-chart {
127
+ /* Cloud's chart palette on every @k2b/ui surface, which sets its own palette on `.k2b-ui` (Cloud's body), so legends
128
+ and series filters, also in popovers, name the colors the chart draws. */
129
+ :root :is(.k2b-ui, .stdlib-chart, .k2b-chart-legend) {
127
130
  --stdlib-chart-c1: #14b8a6;
128
131
  --stdlib-chart-c2: #f97316;
129
132
  --stdlib-chart-c3: #8b5cf6;
@@ -332,8 +335,8 @@ solid-island {
332
335
  background: var(--k2b-surface);
333
336
  }
334
337
  .cloud-app-canvas[data-layout-authenticated] .layout-content-main .k2b-app-workspace:not(.k2b-app-workspace *) {
338
+ --k2b-workspace-radius: 0px;
335
339
  border: 0;
336
- border-radius: 0;
337
340
  box-shadow: none;
338
341
  }
339
342
  .cloud-app-canvas[data-layout-authenticated] > .layout-shell-content > :not(.layout-content-main) .k2b-notice-card {