@k2b/cloud 0.39.0 → 0.40.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.
- package/README.md +8 -0
- package/package.json +8 -4
- package/src/_internal/app-favicon.ts +4 -2
- package/src/_internal/capabilities.ts +72 -48
- package/src/_internal/capability-reviews.ts +81 -0
- package/src/_internal/capability-schemas.ts +29 -0
- package/src/_internal/capability-sentences.ts +216 -1
- package/src/_internal/capability-streams.ts +7 -0
- package/src/_internal/define-app.ts +36 -15
- package/src/_internal/font-preloads.ts +2 -1
- package/src/_internal/runtime-watcher.ts +6 -0
- package/src/_internal/static-assets.ts +52 -3
- package/src/_internal/status-preserving-ssr.ts +2 -0
- package/src/access/PermissionEditor.tsx +2 -2
- package/src/account/EntitySearch.tsx +1 -1
- package/src/ai/action-review.ts +101 -0
- package/src/ai/background-review.ts +72 -0
- package/src/ai/capabilities.ts +29 -11
- package/src/ai/capability-execution.ts +76 -43
- package/src/ai/capability-result.ts +95 -0
- package/src/ai/chat/action-card.ts +398 -0
- package/src/ai/chat/action-messages.ts +129 -0
- package/src/ai/chat/action-question.browser-harness.tsx +245 -0
- package/src/ai/chat/action-question.fixtures.ts +733 -0
- package/src/ai/chat/action-question.tsx +669 -0
- package/src/ai/chat/blocks.tsx +19 -25
- package/src/ai/chat/message-actions.tsx +6 -0
- package/src/ai/chat/tool-action.tsx +481 -0
- package/src/ai/chat/turn-view.tsx +10 -160
- package/src/ai/chat/view-block.tsx +15 -5
- package/src/ai/chat-task-contracts.ts +4 -1
- package/src/ai/chat-task-reasons-migrate.ts +7 -0
- package/src/ai/chat-task-reasons.ts +1 -1
- package/src/ai/chat-tasks.ts +55 -25
- package/src/ai/client/controller.ts +59 -0
- package/src/ai/default-tools.ts +9 -1
- package/src/ai/executor.ts +190 -39
- package/src/ai/index.ts +2 -0
- package/src/ai/migrate.ts +11 -2
- package/src/ai/projects-routes.ts +3 -0
- package/src/ai/protocol.ts +14 -2
- package/src/ai/recent-resources.ts +240 -0
- package/src/ai/recent-sent-refs.ts +38 -0
- package/src/ai/routes.ts +145 -1
- package/src/ai/runtime.ts +1 -0
- package/src/ai/skills-routes.ts +3 -0
- package/src/ai/skills.ts +10 -1
- package/src/ai/store.ts +227 -24
- package/src/ai/tool-audit.ts +8 -0
- package/src/ai/tool-wording.ts +24 -2
- package/src/ai/types.ts +28 -3
- package/src/api/accounts-entities.ts +2 -1
- package/src/api/admin-ai-projects.ts +2 -0
- package/src/api/admin-ai-skills.ts +2 -0
- package/src/api/admin-ai-usage.ts +2 -0
- package/src/api/admin-geoip.ts +80 -0
- package/src/api/admin-identity.ts +3 -0
- package/src/api/admin-lifecycle.ts +3 -0
- package/src/api/admin-outgoing-mail.ts +2 -0
- package/src/api/app-approval.ts +46 -5
- package/src/api/approvals-loader.ts +23 -1
- package/src/api/approvals.ts +2 -0
- package/src/api/auth.ts +25 -6
- package/src/api/capabilities.ts +44 -11
- package/src/api/capability-streams.ts +12 -0
- package/src/api/help.ts +4 -28
- package/src/api/index.ts +6 -1
- package/src/api/lasting-access-messages.ts +17 -0
- package/src/api/mcp.ts +3 -0
- package/src/api/me-panel-consent.ts +71 -0
- package/src/api/me.ts +80 -33
- package/src/api/search.ts +3 -1
- package/src/api/sync-ops.ts +2 -0
- package/src/api/widgets.ts +3 -0
- package/src/approvals/Approvals.tsx +180 -238
- package/src/approvals/messages.ts +12 -24
- package/src/browser/CloudResourceSearch.browser-harness.tsx +10 -2
- package/src/browser/app-approval.ts +54 -5
- package/src/browser/commands.ts +22 -6
- package/src/browser/composer-catalog.ts +45 -3
- package/src/browser/composer-insert.ts +10 -0
- package/src/browser/composer-open-messages.ts +17 -0
- package/src/browser/composer-open.ts +110 -0
- package/src/browser/discoverable-command.ts +6 -0
- package/src/browser/hints.ts +6 -0
- package/src/browser/live-connection.ts +26 -2
- package/src/browser/navigation-apps.ts +7 -0
- package/src/browser/panel-context-bridge.ts +30 -0
- package/src/browser/panel-context-receiver.ts +53 -0
- package/src/browser/panel-menu.tsx +56 -0
- package/src/browser/panel-messages.ts +11 -0
- package/src/browser/panel-shortcuts.ts +31 -0
- package/src/browser/panel-slot.ts +412 -10
- package/src/browser/panel.ts +37 -0
- package/src/browser/search-commands.ts +6 -3
- package/src/capabilities/client.ts +8 -2
- package/src/capabilities/reviews.ts +205 -0
- package/src/capabilities/server.ts +10 -3
- package/src/capabilities/testing.ts +47 -0
- package/src/capabilities/types.ts +2 -2
- package/src/cli/account.ts +13 -3
- package/src/cli/admin/geoip.ts +115 -0
- package/src/cli/admin/index.ts +3 -0
- package/src/contracts/app-approval.ts +120 -13
- package/src/contracts/approvals.ts +2 -2
- package/src/contracts/capabilities.ts +410 -18
- package/src/contracts/geoip.ts +42 -0
- package/src/contracts/index.ts +3 -0
- package/src/contracts/panel-context-plain.ts +99 -0
- package/src/contracts/panel-context.ts +93 -0
- package/src/contracts/seen-hints.ts +35 -0
- package/src/server/client-ip.ts +5 -0
- package/src/server/help-payload.ts +38 -0
- package/src/server/middleware/auth.ts +11 -1
- package/src/server/middleware/middleware.ts +9 -0
- package/src/server/middleware/no-transform.ts +19 -0
- package/src/server/middleware/rate-limit.ts +4 -6
- package/src/server/request-context/address.ts +45 -0
- package/src/server/request-context/geoip.ts +380 -0
- package/src/server/request-context/index.ts +33 -0
- package/src/server/request-context/user-agent.ts +95 -0
- package/src/services/app-approval.ts +382 -59
- package/src/services/approvals/device.ts +7 -5
- package/src/services/approvals/index.ts +6 -5
- package/src/services/approvals/list.ts +26 -5
- package/src/services/auth-flows/notification-sender.ts +3 -0
- package/src/services/geoip/index.ts +164 -0
- package/src/services/geoip/store.ts +30 -0
- package/src/services/geoip/upload.ts +150 -0
- package/src/services/identity/routes.ts +5 -1
- package/src/services/index.ts +11 -0
- package/src/services/known-browsers.ts +312 -0
- package/src/services/login-address-store.ts +51 -0
- package/src/services/login-context.ts +118 -0
- package/src/services/mandates/index.ts +3 -0
- package/src/services/mandates/policy.ts +15 -3
- package/src/services/notifications/email-frame.ts +1 -1
- package/src/services/oauth-tokens.ts +16 -2
- package/src/services/panel-context-consent.ts +58 -0
- package/src/services/service-account-credentials.ts +21 -0
- package/src/services/session/index.ts +97 -16
- package/src/services/session/recent.ts +13 -0
- package/src/services/webauthn.ts +12 -0
- package/src/shared/email-html.ts +2 -0
- package/src/shared/help.ts +3 -0
- package/src/shared-text/cursor.ts +22 -0
- package/src/shared-text/documents.ts +142 -0
- package/src/shared-text/events.ts +43 -0
- package/src/shared-text/index.ts +12 -0
- package/src/shared-text/log.ts +48 -0
- package/src/shared-text/text-diff.ts +23 -0
- package/src/shared-text/types.ts +41 -0
- package/src/ssr/AdminLayout.tsx +2 -0
- package/src/ssr/AppLaunchpadPanel.tsx +2 -2
- package/src/ssr/CloudShell.island.tsx +10 -2
- package/src/ssr/Layout.tsx +25 -2
- package/src/ssr/LayoutHelp.browser-harness.tsx +2 -0
- package/src/ssr/LayoutHelp.tsx +435 -274
- package/src/ssr/LayoutHelpPanel.browser-harness.tsx +136 -0
- package/src/ssr/LayoutHelpTrigger.tsx +27 -2
- package/src/ssr/MobileNavigation.tsx +2 -2
- package/src/ssr/PanelLayout.tsx +9 -1
- package/src/ssr/PanelRuntime.island.tsx +7 -0
- package/src/ssr/PanelSlot.tsx +53 -3
- package/src/ssr/ShellRuntime.island.tsx +11 -2
- package/src/ssr/app-color.ts +14 -9
- package/src/ssr/app-navigation.ts +16 -3
- package/src/ssr/compact-shell.browser-harness.ts +30 -22
- package/src/ssr/dialog-app-colors.browser-harness.tsx +43 -0
- package/src/ssr/help-messages.ts +4 -0
- package/src/ssr/help.ts +20 -0
- package/src/ssr/hints.ts +25 -0
- package/src/ssr/index.ts +2 -0
- package/src/ssr/islands/index.ts +4 -3
- package/src/ssr/layout-context.ts +2 -0
- package/src/ssr/layout-help-article.server.ts +50 -0
- package/src/ssr/layout-help-start.ts +33 -7
- package/src/ssr/panel-consent.ts +29 -0
- package/src/ssr/panel-context.ts +10 -0
- package/src/ssr/panel-slot.browser-harness.tsx +53 -4
- package/src/ssr/platform-messages.ts +18 -0
- package/src/ssr/shell-data.tsx +2 -1
- package/src/styles/effects.css +198 -9
- package/src/styles/file-chooser.css +2 -1
- package/src/styles/global.css +49 -12
- package/src/styles/panel.css +47 -4
- package/src/styles/resource-search.css +6 -2
- package/src/styles/tokens.css +17 -11
- package/src/styles/utilities-buttons.css +3 -2
- package/src/styles/utilities-data.css +2 -1
- package/src/styles/utilities-feedback.css +2 -2
- package/src/styles/utilities-layout.css +3 -13
- package/src/styles/utilities-markdown-editor.css +6 -6
- package/src/styles/utilities-navigation.css +17 -22
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export type SharedTextActor = { kind: "user" | "service_account"; id: string };
|
|
2
|
+
|
|
3
|
+
/** Actor is optional so events retained from older deployments remain readable. */
|
|
4
|
+
export type SharedTextEvent = {
|
|
5
|
+
kind: "sync" | "awareness";
|
|
6
|
+
payload: string;
|
|
7
|
+
originNodeId: string;
|
|
8
|
+
originPeerId: string | null;
|
|
9
|
+
actor?: SharedTextActor;
|
|
10
|
+
};
|
|
11
|
+
export type SharedTextSyncEvent = SharedTextEvent & { kind: "sync" };
|
|
12
|
+
export type SharedTextContributor = SharedTextActor & { lastContributedAt: Date };
|
|
13
|
+
|
|
14
|
+
/** The store anchors legacy cursors to this log before returning a snapshot. */
|
|
15
|
+
export type SharedTextStoredState = {
|
|
16
|
+
state: Uint8Array | null;
|
|
17
|
+
cursor: string | null;
|
|
18
|
+
restoreRevision: string;
|
|
19
|
+
text: string | null;
|
|
20
|
+
};
|
|
21
|
+
export type SharedTextSaveInput = {
|
|
22
|
+
state: Uint8Array;
|
|
23
|
+
text: string;
|
|
24
|
+
cursor: string;
|
|
25
|
+
restoreRevision: string;
|
|
26
|
+
requestedAt: number;
|
|
27
|
+
actor: SharedTextActor | null;
|
|
28
|
+
contributors: SharedTextContributor[];
|
|
29
|
+
};
|
|
30
|
+
export type SharedTextSnapshot = { state: Uint8Array | null; text: string | null; cursor: string | null };
|
|
31
|
+
export type SharedTextEditResult<Saved> =
|
|
32
|
+
| { status: "notFound" }
|
|
33
|
+
| { status: "unchanged"; text: string }
|
|
34
|
+
| { status: "syncFailed"; error: unknown }
|
|
35
|
+
| { status: "persistFailed"; cursor: string; error: unknown }
|
|
36
|
+
| { status: "edited"; text: string; cursor: string; saved: Saved };
|
|
37
|
+
|
|
38
|
+
export type SharedTextStore<Saved, Context> = {
|
|
39
|
+
load(docId: string, options: { signal?: AbortSignal }): Promise<SharedTextStoredState | null>;
|
|
40
|
+
save(docId: string, input: SharedTextSaveInput, context: Context | undefined): Promise<Saved>;
|
|
41
|
+
};
|
package/src/ssr/AdminLayout.tsx
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { AppWorkspace } from "@k2b/ui";
|
|
2
2
|
import type { JSX } from "solid-js/jsx-runtime";
|
|
3
|
+
import type { PanelConsentSnapshot } from "../contracts/panel-context";
|
|
3
4
|
import type { RailSnapshot } from "../contracts/rail-preferences";
|
|
4
5
|
import { getLocale } from "../server/locale";
|
|
5
6
|
import type { LayoutAnnouncementsState } from "../server/middleware/settings";
|
|
@@ -10,6 +11,7 @@ import { getLocalizedRuntimeContext, type RuntimeContext } from "./runtime";
|
|
|
10
11
|
|
|
11
12
|
type Breadcrumb = { title: string; href?: string };
|
|
12
13
|
type AdminLayoutContext = {
|
|
14
|
+
get(key: "panelConsent"): PanelConsentSnapshot | undefined;
|
|
13
15
|
get(key: "railPreferences"): RailSnapshot | undefined;
|
|
14
16
|
get(key: "user"): any;
|
|
15
17
|
get(key: "page"): any;
|
|
@@ -143,7 +143,7 @@ export const AppLaunchpadPanel = (
|
|
|
143
143
|
<i class={shortcut.iconClass} aria-hidden="true" />
|
|
144
144
|
<AppBadge endpoint={shortcut.badge} appId={shortcut.appId} />
|
|
145
145
|
</span>
|
|
146
|
-
<span class="max-w-full truncate text-[11px] font-medium text-primary dark:text-white">
|
|
146
|
+
<span class="max-w-full k2b-truncate-fade text-[11px] font-medium text-primary dark:text-white">
|
|
147
147
|
{shortcut.label}
|
|
148
148
|
<Show when={badge()}>
|
|
149
149
|
<span class="sr-only">, {badge()}</span>
|
|
@@ -173,7 +173,7 @@ export const AppLaunchpadPanel = (
|
|
|
173
173
|
<i class={app.iconClass} />
|
|
174
174
|
<AppBadge endpoint={app.badge} appId={app.id} />
|
|
175
175
|
</span>
|
|
176
|
-
<span class="max-w-full truncate text-[11px] font-medium text-primary sm:text-xs dark:text-white">
|
|
176
|
+
<span class="max-w-full k2b-truncate-fade text-[11px] font-medium text-primary sm:text-xs dark:text-white">
|
|
177
177
|
{app.label}
|
|
178
178
|
<Show when={badge()}>
|
|
179
179
|
<span class="sr-only">, {badge()}</span>
|
|
@@ -95,7 +95,11 @@ function RailNavigation(props: { currentPath: string; panelOpen?: boolean }) {
|
|
|
95
95
|
<div class="mt-auto shrink-0 flex flex-col items-center gap-1">
|
|
96
96
|
{(data.panel?.providers.length ?? 0) > 1 && <PanelTrigger variant="rail" open={props.panelOpen} />}
|
|
97
97
|
<GlobalSearchTrigger variant="rail" />
|
|
98
|
-
<LayoutHelpTrigger
|
|
98
|
+
<LayoutHelpTrigger
|
|
99
|
+
variant="rail"
|
|
100
|
+
panel={data.panel?.providers.some((provider) => provider.id === "core")}
|
|
101
|
+
helpOpen={!!props.panelOpen && data.panel?.provider === "core"}
|
|
102
|
+
/>
|
|
99
103
|
<ProfilePreferences
|
|
100
104
|
appHref={data.profile.appHref}
|
|
101
105
|
avatarSrc={data.profile.avatarSrc}
|
|
@@ -148,7 +152,11 @@ function HeaderControls(props: {
|
|
|
148
152
|
<div class="flex items-center gap-1 lg:hidden">
|
|
149
153
|
{(data.panel?.providers.length ?? 0) > 1 && <PanelTrigger variant="header" open={props.panelOpen} />}
|
|
150
154
|
{props.authenticated && <GlobalSearchTrigger variant="header" />}
|
|
151
|
-
<LayoutHelpTrigger
|
|
155
|
+
<LayoutHelpTrigger
|
|
156
|
+
variant="header"
|
|
157
|
+
panel={data.panel?.providers.some((provider) => provider.id === "core")}
|
|
158
|
+
helpOpen={!!props.panelOpen && data.panel?.provider === "core"}
|
|
159
|
+
/>
|
|
152
160
|
{props.launchpad && (
|
|
153
161
|
<AppLaunchpadButton
|
|
154
162
|
profile={
|
package/src/ssr/Layout.tsx
CHANGED
|
@@ -5,6 +5,8 @@ import { readAppWorkspaceLayoutCookie, resolveAppWorkspaceLayoutForSidebar } fro
|
|
|
5
5
|
import { readPanelCookie } from "../_internal/panel-cookie";
|
|
6
6
|
import { readShellFocusCookie } from "../_internal/shell-focus";
|
|
7
7
|
import { resolveNavMatch } from "../contracts/app"; // ==========================
|
|
8
|
+
import { type CloudResourceRef, CloudResourceRefSchema } from "../contracts/capabilities";
|
|
9
|
+
import { PANEL_HELP_ID_MAX_LENGTH, PanelPageContextSchema } from "../contracts/panel-context";
|
|
8
10
|
import { isPwaShellAvailable } from "../contracts/pwa";
|
|
9
11
|
import { defaultRailPreferences } from "../contracts/rail-preferences";
|
|
10
12
|
import { hasRole, type User } from "../contracts/shared";
|
|
@@ -42,6 +44,8 @@ type LayoutProps = {
|
|
|
42
44
|
title?: string | Breadcrumb[];
|
|
43
45
|
/** Up to three ids of the current app's Help articles that fit this page; Help lists them first under "For this view". Unknown ids and articles the reader may not see are ignored. */
|
|
44
46
|
help?: readonly string[];
|
|
47
|
+
/** Share only the current place with the visible panel; false disables context for this document. */
|
|
48
|
+
context?: { scope?: CloudResourceRef } | false;
|
|
45
49
|
fullPage?: boolean /** Keep the shell viewport-bound and suppress its footer. */;
|
|
46
50
|
fullWidth?: boolean /** Delegate scrolling and clipping to the page's work surface. */;
|
|
47
51
|
/** Hide the panel slot on this page (sign-in, print, presentation, public pages). */
|
|
@@ -165,7 +169,6 @@ export default function Layout(props: LayoutProps) {
|
|
|
165
169
|
providers.length ? cookie : undefined,
|
|
166
170
|
providers.map((provider) => provider.id),
|
|
167
171
|
);
|
|
168
|
-
const panel = providers.length ? { providers, provider: panelState.provider ?? providers[0]?.id } : undefined;
|
|
169
172
|
const pathname = new URL(c.req.raw.url).pathname;
|
|
170
173
|
const currentRoute = resolveRuntimeRoute(runtime.apps, pathname);
|
|
171
174
|
const currentApp = resolveCurrentApp(runtime.apps, pathname);
|
|
@@ -196,6 +199,7 @@ export default function Layout(props: LayoutProps) {
|
|
|
196
199
|
const page = c.get("page") as Record<string, unknown>;
|
|
197
200
|
const pageTitle = typeof title === "string" ? title : (title?.at(-1)?.title ?? appName);
|
|
198
201
|
if (!page.title) page.title = pageTitle;
|
|
202
|
+
page.appAccent = currentApp?.appearance?.accent;
|
|
199
203
|
const breadcrumbs: Breadcrumb[] = !title ? [{ title: appName }] : typeof title === "string" ? [{ title }] : title;
|
|
200
204
|
// The way up is derived from the title array by one rule (see `derivePageTrail`). Anonymous pages keep their
|
|
201
205
|
// header breadcrumbs, and focus surfaces such as pop-out editors have no way up; both show the title alone. The
|
|
@@ -228,7 +232,26 @@ export default function Layout(props: LayoutProps) {
|
|
|
228
232
|
.join(";") || undefined;
|
|
229
233
|
const appLabel = currentApp?.name ?? (pathname.startsWith("/admin") ? t.admin : undefined);
|
|
230
234
|
const helpIds = new Set(registeredHelp?.documents.map((topic) => topic.id));
|
|
231
|
-
const viewHelp = [...new Set(props.help)]
|
|
235
|
+
const viewHelp = [...new Set(props.help)]
|
|
236
|
+
.filter((id) => helpIds.has(id) && id.length <= PANEL_HELP_ID_MAX_LENGTH)
|
|
237
|
+
.slice(0, HELP_VIEW_LIMIT);
|
|
238
|
+
const scope = props.context && CloudResourceRefSchema.safeParse(props.context.scope);
|
|
239
|
+
// Fail closed: a page whose place does not validate shares nothing rather than failing to render.
|
|
240
|
+
const pageContext =
|
|
241
|
+
(providers.length &&
|
|
242
|
+
props.context !== false &&
|
|
243
|
+
PanelPageContextSchema.safeParse({
|
|
244
|
+
v: 1,
|
|
245
|
+
seq: 0,
|
|
246
|
+
pageId: crypto.randomUUID(),
|
|
247
|
+
app: currentApp?.id,
|
|
248
|
+
...(scope && scope.success ? { scope: scope.data } : {}),
|
|
249
|
+
...(viewHelp.length ? { help: viewHelp } : {}),
|
|
250
|
+
}).data) ||
|
|
251
|
+
null;
|
|
252
|
+
const panel: ShellData["panel"] = providers.length
|
|
253
|
+
? { providers, provider: panelState.provider ?? providers[0]?.id, context: pageContext, consent: c.get("panelConsent") }
|
|
254
|
+
: undefined;
|
|
232
255
|
const shellData: ShellData = {
|
|
233
256
|
...(panel ? { panel } : {}),
|
|
234
257
|
platform: keyboardPlatform(c.req.raw.headers.get("User-Agent") ?? ""),
|
|
@@ -75,6 +75,8 @@ window.fetch = Object.assign(
|
|
|
75
75
|
const ids = params.has("start")
|
|
76
76
|
? documents.filter((document) => document.title.toLocaleLowerCase().includes(query)).map((document) => document.id)
|
|
77
77
|
: ["topic-0", "topic-1"];
|
|
78
|
+
// Tests wait for an answered search by this count, not for a spinner that can come and go between two polls (#1403).
|
|
79
|
+
document.documentElement.dataset.helpSearches = String(Number(document.documentElement.dataset.helpSearches ?? 0) + 1);
|
|
78
80
|
return Response.json({ locale: "en", ids });
|
|
79
81
|
}
|
|
80
82
|
const id = path.split("/").at(-1) ?? "topic-0";
|