@k2b/cloud 0.6.0-rc.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 +98 -0
- package/package.json +128 -0
- package/public/logo.svg +1 -0
- package/scripts/app-favicon.test.ts +49 -0
- package/scripts/app-favicon.ts +51 -0
- package/scripts/build.ts +205 -0
- package/scripts/preload.ts +164 -0
- package/scripts/sync-recovery-smoke.ts +200 -0
- package/src/_internal/app-favicon.ts +2 -0
- package/src/_internal/app-presentation.ts +61 -0
- package/src/_internal/app-workspace-state.ts +24 -0
- package/src/_internal/bounded-json.ts +47 -0
- package/src/_internal/build-metadata.ts +9 -0
- package/src/_internal/capabilities.ts +1118 -0
- package/src/_internal/define-app.ts +801 -0
- package/src/_internal/heartbeat.ts +167 -0
- package/src/_internal/help-catalog.ts +241 -0
- package/src/_internal/help.ts +95 -0
- package/src/_internal/nats-connection.ts +34 -0
- package/src/_internal/page-responses.ts +40 -0
- package/src/_internal/process-sync.ts +117 -0
- package/src/_internal/readiness.ts +3 -0
- package/src/_internal/registry-validation.ts +136 -0
- package/src/_internal/registry-watch.ts +52 -0
- package/src/_internal/registry.ts +338 -0
- package/src/_internal/runtime-compatibility.ts +64 -0
- package/src/_internal/runtime-context.ts +84 -0
- package/src/_internal/runtime-watcher.ts +78 -0
- package/src/_internal/static-assets.ts +86 -0
- package/src/_internal/status-preserving-ssr.ts +49 -0
- package/src/access/PermissionEditor.tsx +486 -0
- package/src/access/ResourceApiKeys.tsx +271 -0
- package/src/access/messages.ts +121 -0
- package/src/access/ui.ts +16 -0
- package/src/account/Avatar.tsx +28 -0
- package/src/account/EntitySearch.tsx +363 -0
- package/src/account/avatar-upload-dialog.tsx +197 -0
- package/src/account/avatar-upload.ts +149 -0
- package/src/account/ui.ts +3 -0
- package/src/ai/admin.ts +47 -0
- package/src/ai/approval-routes.ts +130 -0
- package/src/ai/approvals.ts +139 -0
- package/src/ai/assistant-models.ts +61 -0
- package/src/ai/attachments.ts +40 -0
- package/src/ai/browser.ts +92 -0
- package/src/ai/capabilities.ts +714 -0
- package/src/ai/capability-execution.ts +151 -0
- package/src/ai/chat/blocks.render.test.tsx +1108 -0
- package/src/ai/chat/blocks.tsx +730 -0
- package/src/ai/chat/builtin-tools.tsx +428 -0
- package/src/ai/chat/capability-table.tsx +87 -0
- package/src/ai/chat/composer-adapter.ts +169 -0
- package/src/ai/chat/file-tools.tsx +81 -0
- package/src/ai/chat/message-actions.tsx +370 -0
- package/src/ai/chat/message-utils.ts +479 -0
- package/src/ai/chat/messages.ts +43 -0
- package/src/ai/chat/presentation.tsx +395 -0
- package/src/ai/chat/primitives.tsx +3 -0
- package/src/ai/chat/tool-disclosure.tsx +41 -0
- package/src/ai/chat/turn-navigator-utils.ts +28 -0
- package/src/ai/chat/turn-navigator.tsx +164 -0
- package/src/ai/chat/user-message.tsx +149 -0
- package/src/ai/chat/visual-tools.tsx +435 -0
- package/src/ai/chat/web-tools.tsx +202 -0
- package/src/ai/chat-task-contracts.ts +113 -0
- package/src/ai/chat-tasks.ts +952 -0
- package/src/ai/client/controller.ts +1211 -0
- package/src/ai/client/file-source.ts +95 -0
- package/src/ai/client/live-connection.ts +140 -0
- package/src/ai/client/projection.ts +178 -0
- package/src/ai/client/transport.ts +111 -0
- package/src/ai/compaction.ts +182 -0
- package/src/ai/credentials.ts +124 -0
- package/src/ai/default-tool-contracts.ts +108 -0
- package/src/ai/default-tools.ts +127 -0
- package/src/ai/enrich.ts +280 -0
- package/src/ai/executor.ts +1624 -0
- package/src/ai/fetch-file-tool.ts +313 -0
- package/src/ai/file-context.ts +92 -0
- package/src/ai/file-media-type.ts +28 -0
- package/src/ai/file-mount.ts +16 -0
- package/src/ai/file-tools.ts +566 -0
- package/src/ai/files-store.ts +390 -0
- package/src/ai/firecrawl-tools.ts +305 -0
- package/src/ai/grids-skill.ts +126 -0
- package/src/ai/http.ts +265 -0
- package/src/ai/index.ts +337 -0
- package/src/ai/kit-skill.ts +22 -0
- package/src/ai/limits.ts +5 -0
- package/src/ai/live-events.ts +289 -0
- package/src/ai/live-messages.ts +45 -0
- package/src/ai/live-outbox.ts +102 -0
- package/src/ai/live-routes.ts +412 -0
- package/src/ai/live.ts +2 -0
- package/src/ai/maintenance.ts +302 -0
- package/src/ai/markdown-pdf-tool.ts +95 -0
- package/src/ai/memories.ts +605 -0
- package/src/ai/memory-learning-runs.ts +222 -0
- package/src/ai/memory-learning.ts +619 -0
- package/src/ai/memory-tool.ts +120 -0
- package/src/ai/memory-workflow-evidence.ts +158 -0
- package/src/ai/migrate.ts +2082 -0
- package/src/ai/model-access-migrate.ts +30 -0
- package/src/ai/model-access.ts +191 -0
- package/src/ai/personal-agent.ts +6 -0
- package/src/ai/prefs.ts +72 -0
- package/src/ai/project-tool.ts +94 -0
- package/src/ai/projects-routes.ts +277 -0
- package/src/ai/projects.ts +902 -0
- package/src/ai/protocol.ts +279 -0
- package/src/ai/provider.ts +73 -0
- package/src/ai/public-projection.ts +25 -0
- package/src/ai/resource-markers.ts +31 -0
- package/src/ai/resource-refs.ts +70 -0
- package/src/ai/routes.ts +1131 -0
- package/src/ai/runtime-tools.ts +39 -0
- package/src/ai/runtime.ts +544 -0
- package/src/ai/settings.ts +529 -0
- package/src/ai/short-id.ts +45 -0
- package/src/ai/skill-catalog.ts +73 -0
- package/src/ai/skill-format.ts +145 -0
- package/src/ai/skill-seeds.ts +430 -0
- package/src/ai/skill-tool.ts +81 -0
- package/src/ai/skills-routes.ts +143 -0
- package/src/ai/skills.ts +934 -0
- package/src/ai/solid.ts +27 -0
- package/src/ai/store.ts +3113 -0
- package/src/ai/stream.ts +308 -0
- package/src/ai/structured-runs.ts +66 -0
- package/src/ai/structured.ts +186 -0
- package/src/ai/system-prompt.ts +170 -0
- package/src/ai/task-prompt.ts +22 -0
- package/src/ai/timeline.ts +148 -0
- package/src/ai/tool-audit.ts +177 -0
- package/src/ai/tool-result-budget.ts +16 -0
- package/src/ai/tools.ts +155 -0
- package/src/ai/types.ts +967 -0
- package/src/ai/ui.tsx +39 -0
- package/src/ai/usage-migrate.ts +81 -0
- package/src/ai/usage.ts +315 -0
- package/src/ai/validate.ts +54 -0
- package/src/ai/vision-tool.ts +79 -0
- package/src/api/accounts-entities.ts +174 -0
- package/src/api/admin-ai-projects.ts +74 -0
- package/src/api/admin-ai-skills.ts +76 -0
- package/src/api/admin-ai-usage.ts +42 -0
- package/src/api/admin-core-settings.ts +508 -0
- package/src/api/admin-identity.ts +148 -0
- package/src/api/admin-lifecycle.ts +206 -0
- package/src/api/admin-linux-identities.ts +66 -0
- package/src/api/announcements.ts +131 -0
- package/src/api/app-approval.ts +129 -0
- package/src/api/apps.ts +51 -0
- package/src/api/auth/schemas.ts +54 -0
- package/src/api/auth.ts +370 -0
- package/src/api/capabilities.ts +658 -0
- package/src/api/help-messages.ts +19 -0
- package/src/api/help.ts +78 -0
- package/src/api/index.ts +108 -0
- package/src/api/mcp.ts +744 -0
- package/src/api/me-rail.ts +45 -0
- package/src/api/me.ts +753 -0
- package/src/api/search/schemas.ts +79 -0
- package/src/api/search.bench.ts +185 -0
- package/src/api/search.ts +407 -0
- package/src/api/sync-ops.ts +79 -0
- package/src/api/widgets.ts +143 -0
- package/src/browser/CloudResourceSearch.behavior.test.tsx +74 -0
- package/src/browser/CloudResourceSearch.tsx +791 -0
- package/src/browser/app-approval-vault.ts +305 -0
- package/src/browser/app-approval.ts +234 -0
- package/src/browser/live-websocket.ts +268 -0
- package/src/browser/locale-preference.ts +25 -0
- package/src/browser/notification-target.ts +27 -0
- package/src/browser/notification-timeout.ts +14 -0
- package/src/browser/notifications.ts +181 -0
- package/src/browser/resource-clipboard.ts +70 -0
- package/src/browser/resource-picker.tsx +39 -0
- package/src/browser/resource-search-messages.ts +55 -0
- package/src/browser/resource-search.ts +27 -0
- package/src/capabilities/client.ts +149 -0
- package/src/capabilities/response.ts +39 -0
- package/src/capabilities/server.ts +215 -0
- package/src/capabilities/signals.ts +4 -0
- package/src/capabilities/testing.ts +12 -0
- package/src/capabilities/types.ts +32 -0
- package/src/cli/access.ts +499 -0
- package/src/cli/account.ts +382 -0
- package/src/cli/admin/account-administration.ts +45 -0
- package/src/cli/admin/account-categories.ts +49 -0
- package/src/cli/admin/ai-usage.ts +118 -0
- package/src/cli/admin/app-sign-in.ts +49 -0
- package/src/cli/admin/data.ts +343 -0
- package/src/cli/admin/documentation.ts +34 -0
- package/src/cli/admin/gateway.ts +155 -0
- package/src/cli/admin/index.ts +61 -0
- package/src/cli/admin/instance.ts +250 -0
- package/src/cli/admin/jobs.ts +223 -0
- package/src/cli/admin/legal.ts +122 -0
- package/src/cli/admin/linux.ts +53 -0
- package/src/cli/admin/logs.ts +324 -0
- package/src/cli/admin/metrics.ts +142 -0
- package/src/cli/admin/nats.ts +167 -0
- package/src/cli/admin/notifications.ts +516 -0
- package/src/cli/admin/shared.ts +113 -0
- package/src/cli/admin/sync.ts +188 -0
- package/src/cli/admin/telemetry.ts +314 -0
- package/src/cli/admin/webhooks.ts +222 -0
- package/src/cli/admin/workflows.ts +367 -0
- package/src/cli/apps.ts +40 -0
- package/src/cli/capabilities.ts +239 -0
- package/src/cli/commands.ts +604 -0
- package/src/cli/index.ts +61 -0
- package/src/cli/locale.ts +31 -0
- package/src/cli/output.ts +58 -0
- package/src/clients/core.ts +20 -0
- package/src/config/env.ts +54 -0
- package/src/config/index.ts +6 -0
- package/src/contracts/account-categories.ts +62 -0
- package/src/contracts/announcements.ts +121 -0
- package/src/contracts/app-approval.ts +197 -0
- package/src/contracts/app.ts +162 -0
- package/src/contracts/capabilities.ts +484 -0
- package/src/contracts/index.ts +14 -0
- package/src/contracts/notification-live.ts +66 -0
- package/src/contracts/notification-types.ts +235 -0
- package/src/contracts/posix.ts +69 -0
- package/src/contracts/profile.ts +85 -0
- package/src/contracts/rail-preferences.ts +53 -0
- package/src/contracts/registry.ts +110 -0
- package/src/contracts/resource-clipboard.ts +33 -0
- package/src/contracts/settings-types.ts +98 -0
- package/src/contracts/shared.ts +408 -0
- package/src/contracts/user-notifications.ts +101 -0
- package/src/contracts/widgets.ts +183 -0
- package/src/desktop/index.ts +704 -0
- package/src/desktop/solid.tsx +938 -0
- package/src/index.ts +58 -0
- package/src/server/actor.ts +41 -0
- package/src/server/api/index.ts +2 -0
- package/src/server/api/respond.ts +96 -0
- package/src/server/api-client.ts +54 -0
- package/src/server/app-context.ts +39 -0
- package/src/server/help.ts +187 -0
- package/src/server/index.ts +89 -0
- package/src/server/locale.ts +55 -0
- package/src/server/middleware/auth.ts +386 -0
- package/src/server/middleware/index.ts +28 -0
- package/src/server/middleware/invocation.ts +55 -0
- package/src/server/middleware/middleware.ts +65 -0
- package/src/server/middleware/openapi.ts +126 -0
- package/src/server/middleware/rate-limit.ts +125 -0
- package/src/server/middleware/request-logger.ts +41 -0
- package/src/server/middleware/route-template.ts +46 -0
- package/src/server/middleware/runtime.ts +22 -0
- package/src/server/middleware/settings.ts +55 -0
- package/src/server/middleware/validator.ts +49 -0
- package/src/server/middleware/workload.ts +22 -0
- package/src/server/ratelimit.ts +151 -0
- package/src/server/request-cookies.ts +18 -0
- package/src/server/services/access.ts +644 -0
- package/src/server/services/freeipa/client.ts +137 -0
- package/src/server/services/freeipa/index.ts +9 -0
- package/src/server/services/freeipa/session.ts +123 -0
- package/src/server/services/freeipa/test-certificates.ts +44 -0
- package/src/server/services/freeipa/tls.ts +44 -0
- package/src/server/services/freeipa/transport.ts +116 -0
- package/src/server/services/freeipa/util.ts +59 -0
- package/src/server/services/geo.ts +198 -0
- package/src/server/services/index.ts +48 -0
- package/src/server/services/pagination.ts +22 -0
- package/src/server/services/services.ts +13 -0
- package/src/server/time.ts +33 -0
- package/src/services/account-category-policy.ts +51 -0
- package/src/services/account-lifecycle/audit.ts +41 -0
- package/src/services/account-lifecycle/index.ts +940 -0
- package/src/services/account-lifecycle/ipa-backfill.ts +152 -0
- package/src/services/account-lifecycle/notification-sender.ts +13 -0
- package/src/services/account-lifecycle/scheduler.ts +506 -0
- package/src/services/account-model.ts +22 -0
- package/src/services/accounts/app.ts +1671 -0
- package/src/services/accounts/authz.ts +44 -0
- package/src/services/accounts/avatar.ts +120 -0
- package/src/services/accounts/base-group.ts +11 -0
- package/src/services/accounts/base-user.ts +46 -0
- package/src/services/accounts/duplicate-emails.ts +82 -0
- package/src/services/accounts/entities.ts +622 -0
- package/src/services/accounts/group-sql.ts +106 -0
- package/src/services/accounts/groups.ts +272 -0
- package/src/services/accounts/index.ts +14 -0
- package/src/services/accounts/ipa-data.ts +66 -0
- package/src/services/accounts/lifecycle.ts +2 -0
- package/src/services/accounts/local-groups.ts +499 -0
- package/src/services/accounts/model.ts +129 -0
- package/src/services/accounts/notification-sender.ts +31 -0
- package/src/services/accounts/posix.ts +386 -0
- package/src/services/accounts/request-policy.ts +11 -0
- package/src/services/accounts/switching.ts +126 -0
- package/src/services/accounts/users.ts +745 -0
- package/src/services/announcements/index.ts +224 -0
- package/src/services/app-approval.ts +498 -0
- package/src/services/audit/index.ts +438 -0
- package/src/services/auth-flows/index.ts +15 -0
- package/src/services/auth-flows/ipa.ts +197 -0
- package/src/services/auth-flows/magic-link.ts +185 -0
- package/src/services/auth-flows/notification-sender.ts +10 -0
- package/src/services/auth-flows/password-reset.ts +268 -0
- package/src/services/auth-flows/proxy-return.ts +49 -0
- package/src/services/document-extraction.ts +148 -0
- package/src/services/freeipa-config.ts +179 -0
- package/src/services/gateway.ts +186 -0
- package/src/services/identity/constants.ts +18 -0
- package/src/services/identity/index.ts +52 -0
- package/src/services/identity/invocation-actor.ts +120 -0
- package/src/services/identity/invocation-authority.ts +53 -0
- package/src/services/identity/invocation-operations.ts +15 -0
- package/src/services/identity/invocation-token.ts +276 -0
- package/src/services/identity/key-config.ts +41 -0
- package/src/services/identity/key-ring.ts +530 -0
- package/src/services/identity/metrics.ts +29 -0
- package/src/services/identity/routes.ts +18 -0
- package/src/services/identity/runtime-config.ts +88 -0
- package/src/services/identity/session-token.ts +152 -0
- package/src/services/identity/signer-refresh.ts +44 -0
- package/src/services/identity/workload-auth.ts +64 -0
- package/src/services/index.ts +187 -0
- package/src/services/ipa/auth.ts +216 -0
- package/src/services/ipa/connection.ts +57 -0
- package/src/services/ipa/effective-groups.ts +70 -0
- package/src/services/ipa/groups.ts +722 -0
- package/src/services/ipa/guard.ts +17 -0
- package/src/services/ipa/index.ts +17 -0
- package/src/services/ipa/posix.ts +19 -0
- package/src/services/ipa/profile.ts +132 -0
- package/src/services/ipa/runtime.ts +28 -0
- package/src/services/ipa/search.ts +154 -0
- package/src/services/ipa/service-account.ts +15 -0
- package/src/services/ipa/sync-planning.ts +100 -0
- package/src/services/ipa/sync.ts +862 -0
- package/src/services/ipa/users.ts +806 -0
- package/src/services/legal-consent.ts +76 -0
- package/src/services/logging/index.ts +477 -0
- package/src/services/logging/redaction.ts +20 -0
- package/src/services/logging/trace.ts +1231 -0
- package/src/services/mandates/index.ts +855 -0
- package/src/services/mandates/policy.ts +85 -0
- package/src/services/network-security.ts +31 -0
- package/src/services/notifications/batches.ts +722 -0
- package/src/services/notifications/browser.ts +252 -0
- package/src/services/notifications/catalog.ts +113 -0
- package/src/services/notifications/channels.ts +104 -0
- package/src/services/notifications/dispatcher.ts +139 -0
- package/src/services/notifications/email.ts +118 -0
- package/src/services/notifications/index.ts +633 -0
- package/src/services/notifications/live.ts +50 -0
- package/src/services/notifications/observability.ts +407 -0
- package/src/services/notifications/platform.ts +421 -0
- package/src/services/notifications/runtime.ts +120 -0
- package/src/services/notifications/user.ts +248 -0
- package/src/services/notifications/web-push-transport.ts +135 -0
- package/src/services/oauth-tokens.ts +209 -0
- package/src/services/outbox.ts +187 -0
- package/src/services/pdf/gotenberg.ts +290 -0
- package/src/services/pdf/index.ts +43 -0
- package/src/services/pdf/markdown.ts +209 -0
- package/src/services/pdf/template-preview.ts +122 -0
- package/src/services/postgres.ts +76 -0
- package/src/services/providers/index.ts +27 -0
- package/src/services/providers/local/auth.ts +51 -0
- package/src/services/providers/local/index.ts +4 -0
- package/src/services/providers/local/users.ts +263 -0
- package/src/services/rail-preferences.ts +27 -0
- package/src/services/runtime-lifecycle.ts +191 -0
- package/src/services/secrets.ts +10 -0
- package/src/services/service-account-credentials.ts +891 -0
- package/src/services/service-accounts.ts +184 -0
- package/src/services/session/index.ts +236 -0
- package/src/services/session/test-fixture.ts +18 -0
- package/src/services/session/user.ts +144 -0
- package/src/services/settings/api.ts +61 -0
- package/src/services/settings/app.ts +86 -0
- package/src/services/settings/core-settings.ts +796 -0
- package/src/services/settings/crypto.ts +69 -0
- package/src/services/settings/defaults.ts +374 -0
- package/src/services/settings/index.ts +215 -0
- package/src/services/settings/namespace.ts +9 -0
- package/src/services/settings/snapshot.ts +49 -0
- package/src/services/settings/store.ts +241 -0
- package/src/services/settings/templates.ts +4 -0
- package/src/services/sync-ops.ts +403 -0
- package/src/services/topic-cursor.ts +22 -0
- package/src/services/weather/forecast.ts +323 -0
- package/src/services/weather/geo.ts +119 -0
- package/src/services/weather/index.ts +67 -0
- package/src/services/weather/location.ts +24 -0
- package/src/services/weather/locations.ts +133 -0
- package/src/services/weather/migrate.ts +45 -0
- package/src/services/weather/settings.ts +66 -0
- package/src/services/weather/short-id.ts +57 -0
- package/src/services/weather/types.ts +61 -0
- package/src/services/weather/ui.ts +50 -0
- package/src/services/webauthn.ts +385 -0
- package/src/shared/account-action-notice.ts +70 -0
- package/src/shared/account-display.ts +15 -0
- package/src/shared/account-session.ts +15 -0
- package/src/shared/ai-platform-prompt.ts +134 -0
- package/src/shared/ai-usage.ts +49 -0
- package/src/shared/app-presentation.ts +48 -0
- package/src/shared/app-url.ts +12 -0
- package/src/shared/branding.ts +14 -0
- package/src/shared/capability-messages.ts +70 -0
- package/src/shared/email-html.ts +54 -0
- package/src/shared/format.ts +91 -0
- package/src/shared/help.ts +68 -0
- package/src/shared/icons.ts +400 -0
- package/src/shared/index.ts +54 -0
- package/src/shared/locale.ts +48 -0
- package/src/shared/login-method.ts +44 -0
- package/src/shared/markdown/client.ts +130 -0
- package/src/shared/markdown/extensions/code.ts +105 -0
- package/src/shared/markdown/extensions/guided-help.ts +100 -0
- package/src/shared/markdown/extensions/images.ts +79 -0
- package/src/shared/markdown/extensions/info-blocks.ts +97 -0
- package/src/shared/markdown/extensions/katex.ts +120 -0
- package/src/shared/markdown/extensions/links.ts +43 -0
- package/src/shared/markdown/extensions/mark.ts +48 -0
- package/src/shared/markdown/extensions/sub-sup.ts +60 -0
- package/src/shared/markdown/extensions/tables.ts +109 -0
- package/src/shared/markdown/extensions/task-list.ts +53 -0
- package/src/shared/markdown/formula.ts +1187 -0
- package/src/shared/markdown/index.ts +193 -0
- package/src/shared/markdown/shared.ts +36 -0
- package/src/shared/mock-cover.ts +130 -0
- package/src/shared/network-address.ts +106 -0
- package/src/shared/redirect.ts +56 -0
- package/src/shared/template-rendering.ts +140 -0
- package/src/shared/theme.ts +68 -0
- package/src/shared/time.ts +13 -0
- package/src/ssr/AdminLayout.tsx +53 -0
- package/src/ssr/AdminSidebar.tsx +50 -0
- package/src/ssr/AppLaunchpad.island.tsx +236 -0
- package/src/ssr/AppWorkspaceController.island.tsx +21 -0
- package/src/ssr/BrowserNotifications.island.tsx +135 -0
- package/src/ssr/GlobalAnnouncements.island.tsx +142 -0
- package/src/ssr/GlobalSearchDialog.behavior.test.tsx +96 -0
- package/src/ssr/GlobalSearchDialog.tsx +35 -0
- package/src/ssr/GlobalSearchHelpDialog.tsx +104 -0
- package/src/ssr/GlobalSearchTrigger.island.tsx +55 -0
- package/src/ssr/HotkeysHelpRail.island.tsx +55 -0
- package/src/ssr/Layout.render.test.tsx +148 -0
- package/src/ssr/Layout.tsx +292 -0
- package/src/ssr/LayoutBreadcrumbs.island.tsx +44 -0
- package/src/ssr/LayoutFooter.tsx +22 -0
- package/src/ssr/LayoutHeader.tsx +81 -0
- package/src/ssr/LayoutHelp.tsx +869 -0
- package/src/ssr/LayoutPreferences.island.tsx +36 -0
- package/src/ssr/LayoutRail.tsx +58 -0
- package/src/ssr/MinimalLayout.tsx +46 -0
- package/src/ssr/PageError.tsx +29 -0
- package/src/ssr/ProfilePreferences.island.tsx +92 -0
- package/src/ssr/RailApps.island.tsx +61 -0
- package/src/ssr/RailEditor.tsx +293 -0
- package/src/ssr/RegisteredHelpDocuments.island.tsx +3 -0
- package/src/ssr/TimezoneCookie.island.tsx +23 -0
- package/src/ssr/admin-active-link.ts +47 -0
- package/src/ssr/admin-navigation.ts +78 -0
- package/src/ssr/app-appearance.ts +23 -0
- package/src/ssr/app-navigation.ts +41 -0
- package/src/ssr/help-messages.ts +104 -0
- package/src/ssr/index.ts +14 -0
- package/src/ssr/islands/SearchBar.island.tsx +80 -0
- package/src/ssr/islands/index.ts +16 -0
- package/src/ssr/layout-context.ts +17 -0
- package/src/ssr/layout-help-markdown.ts +9 -0
- package/src/ssr/layout-help-navigation.ts +24 -0
- package/src/ssr/layout-help-url.ts +5 -0
- package/src/ssr/layout-runtime.ts +22 -0
- package/src/ssr/page-error-messages.ts +25 -0
- package/src/ssr/platform-messages.ts +135 -0
- package/src/ssr/preference-controller.ts +44 -0
- package/src/ssr/profile-preferences-messages.ts +29 -0
- package/src/ssr/rail-context.ts +21 -0
- package/src/ssr/rail-messages.ts +66 -0
- package/src/ssr/rail-navigation.ts +60 -0
- package/src/ssr/runtime.ts +31 -0
- package/src/ssr/url-filter.ts +127 -0
- package/src/styles/base-popover.css +36 -0
- package/src/styles/effects.css +851 -0
- package/src/styles/global.css +268 -0
- package/src/styles/input.css +58 -0
- package/src/styles/tokens.css +230 -0
- package/src/styles/utilities-buttons.css +405 -0
- package/src/styles/utilities-data.css +33 -0
- package/src/styles/utilities-feedback.css +232 -0
- package/src/styles/utilities-layout.css +603 -0
- package/src/styles/utilities-markdown-editor.css +525 -0
- package/src/styles/utilities-markdown-table.css +234 -0
- package/src/styles/utilities-navigation.css +1054 -0
- package/src/types/ambient.d.ts +24 -0
- package/src/workflows/ai/index.ts +17 -0
- package/src/workflows/ai/runtime.ts +286 -0
- package/src/workflows/ai/store.ts +314 -0
- package/src/workflows/ai/types.ts +111 -0
- package/src/workflows/ai-actions.ts +269 -0
- package/src/workflows/authoring.ts +88 -0
- package/src/workflows/builtins.ts +193 -0
- package/src/workflows/contracts.ts +280 -0
- package/src/workflows/definition.ts +334 -0
- package/src/workflows/editor.ts +113 -0
- package/src/workflows/index.ts +71 -0
- package/src/workflows/language/binder.ts +45 -0
- package/src/workflows/language/canonical.ts +29 -0
- package/src/workflows/language/compiler.ts +396 -0
- package/src/workflows/language/expressions.ts +34 -0
- package/src/workflows/language/index.ts +20 -0
- package/src/workflows/language/references.ts +55 -0
- package/src/workflows/language/schema.ts +134 -0
- package/src/workflows/language/strict-yaml.ts +131 -0
- package/src/workflows/manifest.ts +24 -0
- package/src/workflows/module.ts +12 -0
- package/src/workflows/runtime/coordinator.ts +115 -0
- package/src/workflows/runtime/executor.ts +1003 -0
- package/src/workflows/runtime/index.ts +60 -0
- package/src/workflows/runtime/instant.ts +8 -0
- package/src/workflows/runtime/ports.ts +213 -0
- package/src/workflows/runtime/schedule.ts +203 -0
- package/src/workflows/runtime/trigger.ts +37 -0
- package/src/workflows/runtime/wake.ts +13 -0
- package/src/workflows/store/actions.ts +438 -0
- package/src/workflows/store/budget.ts +145 -0
- package/src/workflows/store/definitions.ts +345 -0
- package/src/workflows/store/events.ts +383 -0
- package/src/workflows/store/index.ts +107 -0
- package/src/workflows/store/observability.ts +594 -0
- package/src/workflows/store/runs.ts +975 -0
- package/src/workflows/store/transaction.ts +23 -0
- package/src/workflows/store/worker.ts +439 -0
- package/src/workflows/testing/conformance.ts +72 -0
- package/src/workflows/testing/index.ts +11 -0
- package/src/workflows/testing/process-fixtures.ts +275 -0
|
@@ -0,0 +1,479 @@
|
|
|
1
|
+
import type { Message, Usage } from "@k2b/nessi";
|
|
2
|
+
import { fileIcons } from "@k2b/stdlib";
|
|
3
|
+
import { formatBytes as sharedFormatBytes } from "../../shared/format";
|
|
4
|
+
import { type AiAttachmentRef, parseAiAttachmentMarkers } from "../attachments";
|
|
5
|
+
import { AI_IMAGE_INPUT_MAX_BYTES, AI_TURN_ATTACHMENT_MAX_ITEMS } from "../limits";
|
|
6
|
+
import { type AiResourceMarker, parseAiResourceMarker } from "../resource-markers";
|
|
7
|
+
import { assistantVisibleTextFromMessage } from "../timeline";
|
|
8
|
+
import type { AiStoredMessage, AiUserContentPart } from "../types";
|
|
9
|
+
import { AI_IMAGE_MEDIA_TYPES, isAiImageMediaType } from "../types";
|
|
10
|
+
|
|
11
|
+
type AssistantToolResultMessage = Extract<Message, { role: "tool_result" }>;
|
|
12
|
+
|
|
13
|
+
export type AiRetryMessageInput = {
|
|
14
|
+
mode?: "retry" | "details" | "concise";
|
|
15
|
+
content?: AiUserContentPart[];
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export type AiForkMessageInput = {
|
|
19
|
+
title?: string;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export type AiComposerAttachment =
|
|
23
|
+
| {
|
|
24
|
+
kind: "image";
|
|
25
|
+
id: string;
|
|
26
|
+
name: string;
|
|
27
|
+
size: number;
|
|
28
|
+
mediaType: string;
|
|
29
|
+
data: string;
|
|
30
|
+
file: File;
|
|
31
|
+
}
|
|
32
|
+
| {
|
|
33
|
+
// Any non-image file: uploaded into conversation files on
|
|
34
|
+
// send, referenced by path — never inlined into the model context.
|
|
35
|
+
kind: "file";
|
|
36
|
+
id: string;
|
|
37
|
+
name: string;
|
|
38
|
+
size: number;
|
|
39
|
+
mediaType: string;
|
|
40
|
+
file: File;
|
|
41
|
+
icon: string;
|
|
42
|
+
}
|
|
43
|
+
| {
|
|
44
|
+
kind: "stored-file";
|
|
45
|
+
id: string;
|
|
46
|
+
name: string;
|
|
47
|
+
size: number;
|
|
48
|
+
mediaType: string;
|
|
49
|
+
path: string;
|
|
50
|
+
version: number;
|
|
51
|
+
icon: string;
|
|
52
|
+
}
|
|
53
|
+
| {
|
|
54
|
+
kind: "resource";
|
|
55
|
+
id: string;
|
|
56
|
+
name: string;
|
|
57
|
+
ref: { type: string; id: string };
|
|
58
|
+
icon: string;
|
|
59
|
+
href?: string;
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
export type PendingAiImage = Extract<AiComposerAttachment, { kind: "image" }>;
|
|
63
|
+
export type PendingAiVfsFile = Extract<AiComposerAttachment, { kind: "file" }>;
|
|
64
|
+
export type PendingAiAttachment = AiComposerAttachment;
|
|
65
|
+
|
|
66
|
+
export const MAX_ATTACHMENTS = AI_TURN_ATTACHMENT_MAX_ITEMS;
|
|
67
|
+
export const IMAGE_MAX_BYTES = AI_IMAGE_INPUT_MAX_BYTES;
|
|
68
|
+
export const VFS_FILE_MAX_BYTES = 50 * 1024 * 1024;
|
|
69
|
+
export const ATTACHMENT_CONTEXT_PREFIX = "Attached files for this message:";
|
|
70
|
+
export const TEXT_ATTACHMENT_EXTENSIONS = [
|
|
71
|
+
"txt",
|
|
72
|
+
"md",
|
|
73
|
+
"markdown",
|
|
74
|
+
"json",
|
|
75
|
+
"csv",
|
|
76
|
+
"ts",
|
|
77
|
+
"tsx",
|
|
78
|
+
"js",
|
|
79
|
+
"jsx",
|
|
80
|
+
"py",
|
|
81
|
+
"html",
|
|
82
|
+
"css",
|
|
83
|
+
"yaml",
|
|
84
|
+
"yml",
|
|
85
|
+
"xml",
|
|
86
|
+
"log",
|
|
87
|
+
] as const;
|
|
88
|
+
export const DOCUMENT_ATTACHMENT_EXTENSIONS = [
|
|
89
|
+
"pdf",
|
|
90
|
+
"doc",
|
|
91
|
+
"docx",
|
|
92
|
+
"odt",
|
|
93
|
+
"ppt",
|
|
94
|
+
"pptx",
|
|
95
|
+
"odp",
|
|
96
|
+
"xlsx",
|
|
97
|
+
"ods",
|
|
98
|
+
"rtf",
|
|
99
|
+
"epub",
|
|
100
|
+
"csv",
|
|
101
|
+
] as const;
|
|
102
|
+
export const TEXT_ATTACHMENT_MEDIA_TYPES = new Set([
|
|
103
|
+
"application/json",
|
|
104
|
+
"application/ld+json",
|
|
105
|
+
"application/xml",
|
|
106
|
+
"application/yaml",
|
|
107
|
+
"application/x-yaml",
|
|
108
|
+
"text/csv",
|
|
109
|
+
"text/markdown",
|
|
110
|
+
"text/plain",
|
|
111
|
+
]);
|
|
112
|
+
export const FILE_INPUT_ACCEPT = [
|
|
113
|
+
...AI_IMAGE_MEDIA_TYPES,
|
|
114
|
+
"text/*",
|
|
115
|
+
...Array.from(TEXT_ATTACHMENT_MEDIA_TYPES),
|
|
116
|
+
...Array.from(new Set([...TEXT_ATTACHMENT_EXTENSIONS, ...DOCUMENT_ATTACHMENT_EXTENSIONS]), (extension) => `.${extension}`),
|
|
117
|
+
].join(",");
|
|
118
|
+
|
|
119
|
+
/** Seconds-granular work duration ("8s", "2m 14s") — stdlib's dates.formatDuration is deliberately minute-granular. */
|
|
120
|
+
export const formatWorkedDuration = (ms: number): string => {
|
|
121
|
+
const totalSeconds = Math.max(1, Math.round(ms / 1000));
|
|
122
|
+
const hours = Math.floor(totalSeconds / 3600);
|
|
123
|
+
const minutes = Math.floor((totalSeconds % 3600) / 60);
|
|
124
|
+
const seconds = totalSeconds % 60;
|
|
125
|
+
if (hours > 0) return `${hours}h ${minutes}m`;
|
|
126
|
+
if (minutes > 0) return seconds > 0 ? `${minutes}m ${seconds}s` : `${minutes}m`;
|
|
127
|
+
return `${seconds}s`;
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
export const formatTokens = (tokens: number): string => {
|
|
131
|
+
if (tokens >= 1_000_000) return `${(tokens / 1_000_000).toFixed(1)}M`;
|
|
132
|
+
if (tokens >= 1_000) return `${(tokens / 1_000).toFixed(1)}k`;
|
|
133
|
+
return String(tokens);
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
export const textFromMessage = (message: Message): string => {
|
|
137
|
+
if (message.role === "tool_result") return typeof message.result === "string" ? message.result : JSON.stringify(message.result, null, 2);
|
|
138
|
+
return message.content
|
|
139
|
+
.map((part) => {
|
|
140
|
+
if (typeof part === "string") return part;
|
|
141
|
+
if (part.type === "text") return part.text;
|
|
142
|
+
if (part.type === "thinking") return part.thinking;
|
|
143
|
+
return "";
|
|
144
|
+
})
|
|
145
|
+
.join("")
|
|
146
|
+
.trim();
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
export const userVisibleTextFromMessage = (message: Message): string => {
|
|
150
|
+
if (message.role !== "user") return textFromMessage(message);
|
|
151
|
+
return message.content
|
|
152
|
+
.map((part) => {
|
|
153
|
+
const text = typeof part === "string" ? part : part.type === "text" ? part.text : "";
|
|
154
|
+
if (text.startsWith(ATTACHMENT_CONTEXT_PREFIX)) return "";
|
|
155
|
+
if (parseAiResourceMarker(text)) return "";
|
|
156
|
+
return parseAiAttachmentMarkers(text).text;
|
|
157
|
+
})
|
|
158
|
+
.join("")
|
|
159
|
+
.trim();
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
/** VFS attachments referenced by this user message (rendered as chips). */
|
|
163
|
+
export const vfsAttachmentsFromMessage = (message: Message): (AiAttachmentRef & { name: string; icon: string })[] => {
|
|
164
|
+
if (message.role !== "user") return [];
|
|
165
|
+
return message.content.flatMap((part) => {
|
|
166
|
+
const text = typeof part === "string" ? part : part.type === "text" ? part.text : "";
|
|
167
|
+
return parseAiAttachmentMarkers(text).attachments.map((attachment) => {
|
|
168
|
+
const name = attachment.path.slice(attachment.path.lastIndexOf("/") + 1);
|
|
169
|
+
return { ...attachment, name, icon: fileIcons.getFileIcon({ name, type: "file", mimeType: attachment.mediaType }) };
|
|
170
|
+
});
|
|
171
|
+
});
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
export const resourcesFromMessage = (message: Message): AiResourceMarker[] => {
|
|
175
|
+
if (message.role !== "user") return [];
|
|
176
|
+
return message.content.flatMap((part) => {
|
|
177
|
+
const text = typeof part === "string" ? part : part.type === "text" ? part.text : "";
|
|
178
|
+
const resource = parseAiResourceMarker(text);
|
|
179
|
+
return resource ? [resource] : [];
|
|
180
|
+
});
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
export const isAttachmentContextPart = (part: AiUserContentPart): boolean => {
|
|
184
|
+
const text = typeof part === "string" ? part : part.type === "text" ? part.text : "";
|
|
185
|
+
if (text.startsWith(ATTACHMENT_CONTEXT_PREFIX)) return true;
|
|
186
|
+
if (parseAiResourceMarker(text)) return true;
|
|
187
|
+
return parseAiAttachmentMarkers(text).attachments.length > 0 && !parseAiAttachmentMarkers(text).text;
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
export const userContentWithEditedVisibleText = (message: Message, text: string): AiUserContentPart[] => {
|
|
191
|
+
if (message.role !== "user") return text.trim() ? [{ type: "text", text: text.trim() }] : [];
|
|
192
|
+
const preserved = message.content.filter((part) => {
|
|
193
|
+
if (typeof part === "string") return isAttachmentContextPart(part);
|
|
194
|
+
return isAttachmentContextPart(part);
|
|
195
|
+
});
|
|
196
|
+
const visible = text.trim();
|
|
197
|
+
return visible ? [{ type: "text", text: visible }, ...preserved] : preserved;
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
export const imageSrc = (part: { mediaType: string; data: string }) => `data:${part.mediaType};base64,${part.data}`;
|
|
201
|
+
|
|
202
|
+
export const cleanFileName = (name: string): string => name.replace(/[\r\n]+/g, " ").trim() || "untitled";
|
|
203
|
+
|
|
204
|
+
export const textAttachmentSummariesFromMessage = (message: Message) => {
|
|
205
|
+
if (message.role !== "user") return [];
|
|
206
|
+
return message.content.flatMap((part) => {
|
|
207
|
+
const text = typeof part === "string" ? part : part.type === "text" ? part.text : "";
|
|
208
|
+
if (!text.startsWith(ATTACHMENT_CONTEXT_PREFIX)) return [];
|
|
209
|
+
return text
|
|
210
|
+
.split("\n")
|
|
211
|
+
.map((line) => /^--- file: (.+?) \((.+?), (.+?)\) ---$/.exec(line))
|
|
212
|
+
.filter((match): match is RegExpExecArray => Boolean(match))
|
|
213
|
+
.map((match) => ({
|
|
214
|
+
name: match[1] ?? "file",
|
|
215
|
+
mediaType: match[2] ?? "text/plain",
|
|
216
|
+
size: match[3] ?? "",
|
|
217
|
+
icon: fileIcons.getFileIcon({ name: match[1] ?? "file", type: "file", mimeType: match[2] ?? "text/plain" }),
|
|
218
|
+
}));
|
|
219
|
+
});
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
export type AiLatestUsageSnapshot = {
|
|
223
|
+
request: Usage;
|
|
224
|
+
loop: Usage;
|
|
225
|
+
modelProfileId: string | null;
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
export const latestUsageSnapshot = (messages: AiStoredMessage[]): AiLatestUsageSnapshot | null => {
|
|
229
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
230
|
+
const entry = messages[i];
|
|
231
|
+
const request = entry?.loopAggregate?.turns.findLast((turn) => Boolean(turn.usage))?.usage ?? entry?.usage;
|
|
232
|
+
if (request) {
|
|
233
|
+
return {
|
|
234
|
+
request,
|
|
235
|
+
loop: entry?.loopAggregate?.usage ?? entry?.usage ?? request,
|
|
236
|
+
modelProfileId: entry?.modelProfileId ?? null,
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
return null;
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
export const latestUsage = (messages: AiStoredMessage[]): Usage | null => latestUsageSnapshot(messages)?.request ?? null;
|
|
244
|
+
|
|
245
|
+
export const latestLoopUsage = (messages: AiStoredMessage[]): Usage | null => latestUsageSnapshot(messages)?.loop ?? null;
|
|
246
|
+
|
|
247
|
+
export const copyTextFromMessage = (message: Message): string => {
|
|
248
|
+
if (message.role === "user") return userVisibleTextFromMessage(message);
|
|
249
|
+
if (message.role === "assistant") return assistantVisibleTextFromMessage(message);
|
|
250
|
+
return textFromMessage(message);
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
export const isRecord = (value: unknown): value is Record<string, unknown> =>
|
|
254
|
+
Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
255
|
+
|
|
256
|
+
export const isCardToolName = (name: string) => name === "card" || name === "cloud_card";
|
|
257
|
+
|
|
258
|
+
export const isSurveyToolName = (name: string) => name === "survey" || name === "cloud_survey";
|
|
259
|
+
|
|
260
|
+
export const isTextEditorToolName = (name: string) => name === "text_editor" || name === "cloud_text_editor";
|
|
261
|
+
|
|
262
|
+
export const displayToolName = (name: string) => {
|
|
263
|
+
if (isCardToolName(name)) return "card";
|
|
264
|
+
if (isSurveyToolName(name)) return "survey";
|
|
265
|
+
if (isTextEditorToolName(name)) return "text editor";
|
|
266
|
+
if (name === "local_bash") return "Local Bash";
|
|
267
|
+
const words = name.split("_").filter(Boolean).join(" ");
|
|
268
|
+
return `${words.slice(0, 1).toUpperCase()}${words.slice(1)}`;
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
const BUILT_IN_TOOL_ICONS = new Map<string, string>([
|
|
272
|
+
["card", "ti ti-layout-cards"],
|
|
273
|
+
["cloud_card", "ti ti-layout-cards"],
|
|
274
|
+
["survey", "ti ti-forms"],
|
|
275
|
+
["cloud_survey", "ti ti-forms"],
|
|
276
|
+
["text_editor", "ti ti-edit"],
|
|
277
|
+
["cloud_text_editor", "ti ti-edit"],
|
|
278
|
+
["local_bash", "ti ti-terminal-2"],
|
|
279
|
+
["list_files", "ti ti-file-spark"],
|
|
280
|
+
["read_file", "ti ti-file-spark"],
|
|
281
|
+
["write_file", "ti ti-file-spark"],
|
|
282
|
+
["fetch_file", "ti ti-world-download"],
|
|
283
|
+
["markdown_to_pdf", "ti ti-file-type-pdf"],
|
|
284
|
+
["present", "ti ti-file-spark"],
|
|
285
|
+
["calculate", "ti ti-calculator"],
|
|
286
|
+
["web_search", "ti ti-search"],
|
|
287
|
+
["web_extract", "ti ti-world-download"],
|
|
288
|
+
["view_image", "ti ti-photo-spark"],
|
|
289
|
+
["memory", "ti ti-brain"],
|
|
290
|
+
["search_project", "ti ti-folder-search"],
|
|
291
|
+
["read_project_knowledge", "ti ti-notebook"],
|
|
292
|
+
["search_help", "ti ti-help-hexagon"],
|
|
293
|
+
["read_help", "ti ti-help-hexagon"],
|
|
294
|
+
["search_tools", "ti ti-ai-gateway"],
|
|
295
|
+
["load_tools", "ti ti-ai-gateway"],
|
|
296
|
+
["load_skill", "ti ti-sparkles"],
|
|
297
|
+
["list_apps", "ti ti-apps"],
|
|
298
|
+
["read_cloud_resource", "ti ti-ai-gateway"],
|
|
299
|
+
]);
|
|
300
|
+
|
|
301
|
+
export const aiToolIcon = (name: string, appIcon?: string | null): string => {
|
|
302
|
+
if (appIcon) return appIcon;
|
|
303
|
+
return BUILT_IN_TOOL_ICONS.get(name) ?? (/__(?:query|action)__/.test(name) ? "ti ti-ai-gateway" : "ti ti-tool");
|
|
304
|
+
};
|
|
305
|
+
|
|
306
|
+
export const jsonPreview = (value: unknown) => {
|
|
307
|
+
try {
|
|
308
|
+
return JSON.stringify(value, null, 2);
|
|
309
|
+
} catch {
|
|
310
|
+
return String(value);
|
|
311
|
+
}
|
|
312
|
+
};
|
|
313
|
+
|
|
314
|
+
const isWebSearchResultList = (value: unknown): value is { title?: unknown; url?: unknown; snippet?: unknown }[] =>
|
|
315
|
+
Array.isArray(value) && value.length > 0 && value.every((item) => isRecord(item) && "url" in item);
|
|
316
|
+
|
|
317
|
+
const stringOf = (value: unknown): string => (typeof value === "string" ? value : "");
|
|
318
|
+
|
|
319
|
+
/** Human-readable tool detail text: search results as a numbered list, page extracts as labeled fields, flat objects as key/value lines, JSON only as the fallback. */
|
|
320
|
+
export const formatToolDetailText = (toolName: string, value: unknown): string => {
|
|
321
|
+
if (value === undefined || value === null) return "";
|
|
322
|
+
if (typeof value === "string") return value;
|
|
323
|
+
|
|
324
|
+
if (toolName === "web_search" && isWebSearchResultList(value)) {
|
|
325
|
+
return value
|
|
326
|
+
.map(
|
|
327
|
+
(item, index) =>
|
|
328
|
+
`${index + 1}. ${stringOf(item.title) || "Untitled"}\n Url: ${stringOf(item.url)}\n Snippet: ${stringOf(item.snippet)}`,
|
|
329
|
+
)
|
|
330
|
+
.join("\n\n");
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
if (toolName === "web_extract" && isRecord(value) && typeof value.content === "string") {
|
|
334
|
+
const lines = [
|
|
335
|
+
`Url: ${stringOf(value.url)}`,
|
|
336
|
+
...(value.title ? [`Title: ${stringOf(value.title)}`] : []),
|
|
337
|
+
...(value.description ? [`Description: ${stringOf(value.description)}`] : []),
|
|
338
|
+
];
|
|
339
|
+
return `${lines.join("\n")}\n\n${value.content}${value.truncated === true ? " (truncated)" : ""}`;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
// Flat objects read better as key/value lines than as JSON.
|
|
343
|
+
if (isRecord(value) && Object.values(value).every((entry) => entry === null || typeof entry !== "object")) {
|
|
344
|
+
return Object.entries(value)
|
|
345
|
+
.map(([key, entry]) => `${key}: ${typeof entry === "string" ? entry : JSON.stringify(entry)}`)
|
|
346
|
+
.join("\n");
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
return jsonPreview(value);
|
|
350
|
+
};
|
|
351
|
+
|
|
352
|
+
/** Short row description for a finished tool call. */
|
|
353
|
+
export const toolBlockSummary = (result: unknown): string => {
|
|
354
|
+
if (Array.isArray(result)) return `${result.length} result${result.length === 1 ? "" : "s"}`;
|
|
355
|
+
if (typeof result === "string") return result.slice(0, 80);
|
|
356
|
+
if (isRecord(result)) {
|
|
357
|
+
if (typeof result.message === "string" && result.message.trim()) return result.message.slice(0, 80);
|
|
358
|
+
return Object.keys(result).slice(0, 4).join(", ");
|
|
359
|
+
}
|
|
360
|
+
return "";
|
|
361
|
+
};
|
|
362
|
+
|
|
363
|
+
export type MemoryToolPresentation = {
|
|
364
|
+
label: string;
|
|
365
|
+
description: string;
|
|
366
|
+
failed: boolean;
|
|
367
|
+
};
|
|
368
|
+
|
|
369
|
+
export type FetchFileErrorPresentation = {
|
|
370
|
+
label: string;
|
|
371
|
+
description: string;
|
|
372
|
+
};
|
|
373
|
+
|
|
374
|
+
const boundedErrorText = (value: string): string => {
|
|
375
|
+
const compact = value.replace(/\s+/g, " ").trim();
|
|
376
|
+
return compact.length > 500 ? `${compact.slice(0, 497)}...` : compact;
|
|
377
|
+
};
|
|
378
|
+
|
|
379
|
+
/** Canonical capability failure text for the compact chat row. Raw input and output remain in the audit trail. */
|
|
380
|
+
export const capabilityErrorDescription = (result: unknown): string => {
|
|
381
|
+
if (typeof result === "string") return boundedErrorText(result) || "The action could not be completed.";
|
|
382
|
+
if (isRecord(result)) {
|
|
383
|
+
const message = typeof result.message === "string" ? result.message : typeof result.error === "string" ? result.error : "";
|
|
384
|
+
const code = typeof result.code === "string" ? result.code : "";
|
|
385
|
+
const text = code && message && !message.startsWith(code) ? `${code}: ${message}` : message || code;
|
|
386
|
+
if (text) return boundedErrorText(text);
|
|
387
|
+
}
|
|
388
|
+
return "The action could not be completed.";
|
|
389
|
+
};
|
|
390
|
+
|
|
391
|
+
/** Compact user-facing copy for fetch_file failures; the full response remains in the disclosure and audit trail. */
|
|
392
|
+
export const fetchFileErrorPresentation = (result: unknown): FetchFileErrorPresentation => {
|
|
393
|
+
const message =
|
|
394
|
+
typeof result === "string"
|
|
395
|
+
? result.trim()
|
|
396
|
+
: isRecord(result) && typeof (result.error ?? result.message) === "string"
|
|
397
|
+
? String(result.error ?? result.message).trim()
|
|
398
|
+
: "";
|
|
399
|
+
const separator = message.indexOf(" — ");
|
|
400
|
+
if (separator > 0) {
|
|
401
|
+
return { label: message.slice(0, separator), description: message.slice(separator + 3) };
|
|
402
|
+
}
|
|
403
|
+
return {
|
|
404
|
+
label: "File download failed",
|
|
405
|
+
description: message || "The linked file could not be imported into this chat.",
|
|
406
|
+
};
|
|
407
|
+
};
|
|
408
|
+
|
|
409
|
+
/** End-user copy for memory updates; full tool input/result remains available in persisted audit data. */
|
|
410
|
+
export const memoryToolPresentation = (args: unknown, result: unknown): MemoryToolPresentation | null => {
|
|
411
|
+
if (!isRecord(args) || !["list", "search", "add", "update", "delete"].includes(String(args.action))) return null;
|
|
412
|
+
if (!isRecord(result) || typeof result.ok !== "boolean" || typeof result.message !== "string") return null;
|
|
413
|
+
|
|
414
|
+
if (!result.ok) return { label: "Memory not updated", description: result.message, failed: true };
|
|
415
|
+
if (args.action === "add")
|
|
416
|
+
return { label: "Remembered", description: typeof args.content === "string" ? args.content.trim() : result.message, failed: false };
|
|
417
|
+
if (args.action === "update")
|
|
418
|
+
return { label: "Updated memory", description: result.message.replace(/^Updated memory:\s*/, ""), failed: false };
|
|
419
|
+
if (args.action === "delete")
|
|
420
|
+
return { label: "Forgot memory", description: result.message.replace(/^Forgot memory:\s*/, ""), failed: false };
|
|
421
|
+
return { label: args.action === "search" ? "Searched memories" : "Listed memories", description: result.message, failed: false };
|
|
422
|
+
};
|
|
423
|
+
|
|
424
|
+
export const toolResultSummary = (message: AssistantToolResultMessage | null | undefined): string => {
|
|
425
|
+
if (!message) return "Tool result";
|
|
426
|
+
const content = textFromMessage(message);
|
|
427
|
+
const firstIssue = /Issues:\s*\n1\.\s*([^\n]+)/.exec(content)?.[1];
|
|
428
|
+
if (firstIssue) return firstIssue;
|
|
429
|
+
const firstLine = content.split("\n").find((line) => line.trim());
|
|
430
|
+
if (firstLine) {
|
|
431
|
+
const line = firstLine.trim();
|
|
432
|
+
if (line.startsWith("{") || line.startsWith("[")) return message.isError ? "Tool failed" : "Tool result";
|
|
433
|
+
return line.slice(0, 160);
|
|
434
|
+
}
|
|
435
|
+
return message.isError ? "Tool failed" : "Tool result";
|
|
436
|
+
};
|
|
437
|
+
|
|
438
|
+
export const readImageFile = (file: File): Promise<PendingAiImage> => {
|
|
439
|
+
if (!isAiImageMediaType(file.type)) throw new Error(`${file.name} must be PNG, JPEG, WebP, or GIF.`);
|
|
440
|
+
if (file.size > IMAGE_MAX_BYTES) throw new Error(`${file.name} is larger than ${formatBytes(IMAGE_MAX_BYTES)}.`);
|
|
441
|
+
|
|
442
|
+
return new Promise((resolve, reject) => {
|
|
443
|
+
const reader = new FileReader();
|
|
444
|
+
reader.onerror = () => reject(reader.error ?? new Error(`Failed to read ${file.name}.`));
|
|
445
|
+
reader.onload = () => {
|
|
446
|
+
const result = String(reader.result ?? "");
|
|
447
|
+
const comma = result.indexOf(",");
|
|
448
|
+
const data = comma >= 0 ? result.slice(comma + 1) : result;
|
|
449
|
+
resolve({
|
|
450
|
+
kind: "image",
|
|
451
|
+
id: `${file.name}-${file.size}-${Date.now()}-${Math.random().toString(36).slice(2)}`,
|
|
452
|
+
name: file.name,
|
|
453
|
+
size: file.size,
|
|
454
|
+
mediaType: file.type,
|
|
455
|
+
data,
|
|
456
|
+
file,
|
|
457
|
+
});
|
|
458
|
+
};
|
|
459
|
+
reader.readAsDataURL(file);
|
|
460
|
+
});
|
|
461
|
+
};
|
|
462
|
+
|
|
463
|
+
/** Wrap any non-image file for deferred upload into the conversation VFS. */
|
|
464
|
+
export const readVfsFile = (file: File): PendingAiVfsFile => {
|
|
465
|
+
if (file.size > VFS_FILE_MAX_BYTES) throw new Error(`${file.name} is larger than ${formatBytes(VFS_FILE_MAX_BYTES)}.`);
|
|
466
|
+
const mediaType = file.type || "application/octet-stream";
|
|
467
|
+
return {
|
|
468
|
+
kind: "file",
|
|
469
|
+
id: `${file.name}-${file.size}-${Date.now()}-${Math.random().toString(36).slice(2)}`,
|
|
470
|
+
name: cleanFileName(file.name),
|
|
471
|
+
size: file.size,
|
|
472
|
+
mediaType,
|
|
473
|
+
file,
|
|
474
|
+
icon: fileIcons.getFileIcon({ name: file.name, type: "file", mimeType: mediaType }),
|
|
475
|
+
};
|
|
476
|
+
};
|
|
477
|
+
|
|
478
|
+
/** Re-exported for existing callers; the implementation is shared. */
|
|
479
|
+
export const formatBytes = (bytes: number): string => sharedFormatBytes(bytes);
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { i18n } from "@k2b/stdlib";
|
|
2
|
+
|
|
3
|
+
const messages = i18n.define({
|
|
4
|
+
baseLocale: "en",
|
|
5
|
+
messages: {
|
|
6
|
+
en: {
|
|
7
|
+
tableLinks: "Links",
|
|
8
|
+
tableOpen: "Open",
|
|
9
|
+
tableEmpty: "No matching rows.",
|
|
10
|
+
tableCapped: "Showing the first 100 returned rows. The full tool result remains available in details.",
|
|
11
|
+
tableMore: "More rows are available. Ask for the next page or open the result in the application.",
|
|
12
|
+
assistantTurns: "Assistant turns",
|
|
13
|
+
workSteps: "Work steps",
|
|
14
|
+
surveyNoAnswer: "No answer",
|
|
15
|
+
surveyNoAnswers: "No answers submitted.",
|
|
16
|
+
toolCalls: "Tool calls",
|
|
17
|
+
toolIssues: "Tool issues",
|
|
18
|
+
none: "None",
|
|
19
|
+
read: "Read",
|
|
20
|
+
byteRange: ({ start, end }: { start: string; end: string }) => `Bytes ${start}–${end}`,
|
|
21
|
+
},
|
|
22
|
+
de: {
|
|
23
|
+
tableLinks: "Links",
|
|
24
|
+
tableOpen: "Öffnen",
|
|
25
|
+
tableEmpty: "Keine passenden Zeilen.",
|
|
26
|
+
tableCapped:
|
|
27
|
+
"Die ersten 100 zurückgegebenen Zeilen werden angezeigt. Das vollständige Werkzeugergebnis bleibt in den Details verfügbar.",
|
|
28
|
+
tableMore: "Weitere Zeilen sind verfügbar. Frage nach der nächsten Seite oder öffne das Ergebnis in der Anwendung.",
|
|
29
|
+
assistantTurns: "Antwortdurchläufe",
|
|
30
|
+
workSteps: "Arbeitsschritte",
|
|
31
|
+
surveyNoAnswer: "Keine Antwort",
|
|
32
|
+
surveyNoAnswers: "Keine Antworten abgegeben.",
|
|
33
|
+
toolCalls: "Werkzeugaufrufe",
|
|
34
|
+
toolIssues: "Werkzeugprobleme",
|
|
35
|
+
none: "Keine",
|
|
36
|
+
read: "Gelesen",
|
|
37
|
+
byteRange: ({ start, end }) => `Bytes ${start}–${end}`,
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
export const aiChatMessages = (locale: string) => messages.resolve([locale]).t;
|
|
43
|
+
export const checkAiChatMessages = () => messages.check();
|