@k2b/cloud 0.36.0 → 0.38.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/package.json +5 -3
- package/scripts/README.md +1 -0
- package/scripts/cli-pack.ts +123 -0
- package/src/_internal/help-catalog.ts +123 -4
- package/src/_internal/help.ts +27 -6
- package/src/_internal/shell-focus.ts +11 -0
- package/src/access/PermissionEditor.browser-harness.tsx +46 -0
- package/src/access/PermissionEditor.tsx +38 -9
- package/src/access/ui.ts +1 -0
- package/src/account/Avatar.tsx +20 -2
- package/src/account/ui.ts +1 -1
- package/src/ai/browser.ts +1 -0
- package/src/ai/chart-block.ts +44 -13
- package/src/ai/chat/answer-links.ts +8 -0
- package/src/ai/chat/chart-block.tsx +2 -11
- package/src/ai/chat/messages.ts +12 -0
- package/src/ai/chat/primitives.tsx +2 -1
- package/src/ai/chat/web-tools.tsx +23 -6
- package/src/ai/chat-tasks.ts +65 -1
- package/src/ai/default-tool-contracts.ts +30 -13
- package/src/ai/executor.ts +46 -3
- package/src/ai/fetch-file-tool.ts +37 -3
- package/src/ai/migrate.ts +19 -2
- package/src/ai/readable-html.ts +1057 -0
- package/src/ai/types.ts +1 -0
- package/src/api/help.ts +23 -4
- package/src/api/mcp.ts +8 -2
- package/src/browser/FileChooser.tsx +11 -3
- package/src/browser/choose-files.browser-harness.tsx +4 -1
- package/src/browser/file-chooser-messages.ts +4 -0
- package/src/browser/file-providers.ts +14 -1
- package/src/browser/provider-folder.tsx +58 -5
- package/src/browser/resource-picker.tsx +5 -1
- package/src/browser/shell-focus.ts +67 -0
- package/src/cli/admin/workflows.ts +1 -0
- package/src/cli/commands.ts +2 -0
- package/src/cli/plugin.ts +5 -5
- package/src/config/env.ts +14 -0
- package/src/contracts/file-provider.ts +48 -1
- package/src/contracts/outgoing-mail.ts +8 -1
- package/src/server/help.ts +136 -10
- package/src/server/services/geo.ts +21 -4
- package/src/services/allowed-network-fetch.ts +189 -0
- package/src/services/help/index.ts +46 -5
- package/src/services/help/store.ts +26 -5
- package/src/services/help/types.ts +10 -2
- package/src/services/index.ts +2 -0
- package/src/services/network-security.ts +28 -0
- package/src/services/outgoing-mail/dispatcher.ts +7 -2
- package/src/services/outgoing-mail/resolve-host.ts +39 -0
- package/src/services/outgoing-mail/test-send.ts +18 -3
- package/src/services/outgoing-mail/transport.ts +24 -13
- package/src/services/settings/index.ts +48 -26
- package/src/shared/help.ts +41 -0
- package/src/shared/index.ts +9 -1
- package/src/shared/markdown/extensions/guided-help.ts +208 -64
- package/src/shared/markdown/formula.ts +8 -8
- package/src/shared/markdown/index.ts +72 -11
- package/src/shared/network-address.ts +9 -0
- package/src/ssr/CloudShell.island.tsx +2 -0
- package/src/ssr/GlobalSearchTrigger.tsx +1 -1
- package/src/ssr/Layout.tsx +28 -2
- package/src/ssr/LayoutHelp.browser-harness.tsx +130 -27
- package/src/ssr/LayoutHelp.tsx +569 -410
- package/src/ssr/LayoutHelpTrigger.tsx +1 -1
- package/src/ssr/LayoutRail.tsx +1 -1
- package/src/ssr/ProfilePreferences.tsx +1 -1
- package/src/ssr/RailApps.tsx +1 -1
- package/src/ssr/ShellFocusToggle.tsx +43 -0
- package/src/ssr/ShellRuntime.island.tsx +53 -26
- package/src/ssr/app-launchpad.tsx +1 -1
- package/src/ssr/help-messages.ts +60 -38
- package/src/ssr/help.ts +3 -0
- package/src/ssr/layout-help-article.ts +41 -0
- package/src/ssr/layout-help-navigation.ts +0 -12
- package/src/ssr/layout-help-registry.tsx +4 -11
- package/src/ssr/layout-help-search.ts +9 -12
- package/src/ssr/layout-help-start.ts +68 -0
- package/src/ssr/platform-messages.ts +14 -0
- package/src/ssr/shell-data.tsx +7 -0
- package/src/ssr/shell-focus.browser-harness.tsx +83 -0
- package/src/ssr/shell-shortcuts.ts +8 -0
- package/src/styles/effects.css +688 -185
- package/src/styles/global.css +155 -26
- package/src/styles/resource-search.css +25 -0
- package/src/styles/utilities-navigation.css +11 -3
- package/src/workflows/store/events.ts +24 -0
- package/src/workflows/store/index.ts +8 -0
- package/src/workflows/store/observability.ts +6 -1
- package/src/workflows/store/retention.ts +157 -0
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import type { ClientRequest, IncomingHttpHeaders, IncomingMessage } from "node:http";
|
|
2
2
|
import { type RequestOptions as HttpsRequestOptions, request as httpsRequest } from "node:https";
|
|
3
3
|
import { z } from "zod";
|
|
4
|
+
import { DOCUMENT_EXTRACTION_MAX_INPUT_BYTES, DOCUMENT_EXTRACTION_MAX_OUTPUT_BYTES } from "../services/document-extraction";
|
|
4
5
|
import { type PublicNetworkAddress, resolvePublicNetworkAddresses } from "../services/network-security";
|
|
5
6
|
import { AI_FILES_MAX_FILE_BYTES_DEFAULT, aiFileStore, guessAiMediaType, normalizeAiFilePath } from "./files-store";
|
|
6
7
|
import { authorizeWebRead } from "./firecrawl-tools";
|
|
8
|
+
import { htmlToReadableMarkdown } from "./readable-html";
|
|
7
9
|
import { defineAiTool } from "./tools";
|
|
8
10
|
|
|
9
11
|
const FETCH_FILE_MAX_REDIRECTS = 5;
|
|
@@ -38,6 +40,7 @@ export const CloudAiFetchFileOutputSchema = z.object({
|
|
|
38
40
|
size: z.number().int().nonnegative(),
|
|
39
41
|
mediaType: z.string(),
|
|
40
42
|
url: z.string().url(),
|
|
43
|
+
readable: z.object({ path: z.string(), size: z.number().int().nonnegative(), note: z.string() }).optional(),
|
|
41
44
|
});
|
|
42
45
|
|
|
43
46
|
const publicHttpsUrl = (rawUrl: string): URL => {
|
|
@@ -309,20 +312,51 @@ export const runCloudAiFetchFile = async (
|
|
|
309
312
|
bytes: downloaded.bytes,
|
|
310
313
|
mediaType: responseMediaType(downloaded.headers, path),
|
|
311
314
|
});
|
|
312
|
-
|
|
315
|
+
const result = { path: stat.path, size: stat.size, mediaType: stat.mediaType, url: downloaded.url.toString() };
|
|
316
|
+
if (stat.mediaType !== "text/html" && stat.mediaType !== "application/xhtml+xml") return result;
|
|
317
|
+
try {
|
|
318
|
+
const contentType = downloaded.headers["content-type"];
|
|
319
|
+
const markdown = await htmlToReadableMarkdown(downloaded.bytes, {
|
|
320
|
+
baseUrl: downloaded.url,
|
|
321
|
+
contentType: Array.isArray(contentType) ? contentType[0] : contentType,
|
|
322
|
+
// The same bounds as any other document converted to Markdown for the model.
|
|
323
|
+
maxInputBytes: DOCUMENT_EXTRACTION_MAX_INPUT_BYTES,
|
|
324
|
+
maxBytes: DOCUMENT_EXTRACTION_MAX_OUTPUT_BYTES,
|
|
325
|
+
signal: context.signal,
|
|
326
|
+
});
|
|
327
|
+
if (!markdown) return result;
|
|
328
|
+
const basename = stat.path.slice(stat.path.lastIndexOf("/") + 1).replace(/\.(?:html?|xhtml|xht)$/i, "");
|
|
329
|
+
const readable = await aiFileStore.createAssistantFile({
|
|
330
|
+
conversationId: context.conversationId,
|
|
331
|
+
path: `/imports/${basename}.md`,
|
|
332
|
+
bytes: new TextEncoder().encode(markdown),
|
|
333
|
+
mediaType: "text/markdown",
|
|
334
|
+
});
|
|
335
|
+
return {
|
|
336
|
+
...result,
|
|
337
|
+
readable: {
|
|
338
|
+
path: readable.path,
|
|
339
|
+
size: readable.size,
|
|
340
|
+
note: "Readable Markdown of the page's main content. Read this path first; use the raw path only when you need the HTML markup.",
|
|
341
|
+
},
|
|
342
|
+
};
|
|
343
|
+
} catch {
|
|
344
|
+
// The raw import already succeeded; a readable copy is best-effort, including on cancellation.
|
|
345
|
+
return result;
|
|
346
|
+
}
|
|
313
347
|
};
|
|
314
348
|
|
|
315
349
|
export const createCloudAiFetchFileTool = (dependencies: FetchFileDependencies = {}) =>
|
|
316
350
|
defineAiTool({
|
|
317
351
|
name: "fetch_file",
|
|
318
352
|
description:
|
|
319
|
-
"Download one exact public HTTPS file URL into
|
|
353
|
+
"Download one exact public HTTPS file URL into this conversation for inspection. Supports images, documents, raw repository files, and web pages; no repository browsing, website authentication, or private network access. For web pages, read readable.path (main-content Markdown) first with read_file when returned; use raw HTML only when markup matters. Inspect other returned paths with read_file or view_image and use present to deliver files.",
|
|
320
354
|
inputSchema: CloudAiFetchFileInputSchema,
|
|
321
355
|
outputSchema: CloudAiFetchFileOutputSchema,
|
|
322
356
|
approval: "never",
|
|
323
357
|
timeoutMs: 90_000,
|
|
324
358
|
promptHint:
|
|
325
|
-
"fetch an exact public HTTPS source file into the chat
|
|
359
|
+
"fetch an exact public HTTPS source file into the chat; for web pages read readable.path (main-content Markdown) first with read_file when returned; use raw HTML only when markup matters. Inspect other files with read_file or view_image; present when useful.",
|
|
326
360
|
}).server(async (input, context) => {
|
|
327
361
|
const url = publicHttpsUrl(input.url);
|
|
328
362
|
const allowedForChat = await authorizeWebRead("file", url.toString(), context);
|
package/src/ai/migrate.ts
CHANGED
|
@@ -516,6 +516,12 @@ export const migrateCloudAi = async (): Promise<void> => {
|
|
|
516
516
|
WHERE status = 'completed' AND run_config->>'kind' = 'chat'
|
|
517
517
|
`.simple();
|
|
518
518
|
|
|
519
|
+
await sql`
|
|
520
|
+
CREATE INDEX IF NOT EXISTS idx_ai_turns_background_finished
|
|
521
|
+
ON ai.turns(completed_at, id)
|
|
522
|
+
WHERE run_config ? 'background' AND status IN ('completed', 'failed', 'aborted')
|
|
523
|
+
`.simple();
|
|
524
|
+
|
|
519
525
|
await sql`
|
|
520
526
|
CREATE TABLE IF NOT EXISTS ai.conversation_resource_refs (
|
|
521
527
|
conversation_id UUID NOT NULL REFERENCES ai.conversations(id) ON DELETE CASCADE,
|
|
@@ -999,12 +1005,23 @@ export const migrateCloudAi = async (): Promise<void> => {
|
|
|
999
1005
|
ON ai.chat_task_occurrences(request_key)
|
|
1000
1006
|
`.simple();
|
|
1001
1007
|
|
|
1008
|
+
await sql`
|
|
1009
|
+
CREATE INDEX IF NOT EXISTS idx_ai_chat_task_occurrences_turn
|
|
1010
|
+
ON ai.chat_task_occurrences(turn_id)
|
|
1011
|
+
`.simple();
|
|
1012
|
+
|
|
1002
1013
|
await sql`
|
|
1003
1014
|
CREATE INDEX IF NOT EXISTS idx_ai_chat_task_occurrences_queued
|
|
1004
1015
|
ON ai.chat_task_occurrences(created_at ASC, id ASC)
|
|
1005
1016
|
WHERE state = 'queued'
|
|
1006
1017
|
`.simple();
|
|
1007
1018
|
|
|
1019
|
+
await sql`
|
|
1020
|
+
CREATE INDEX IF NOT EXISTS idx_ai_chat_task_occurrences_finished
|
|
1021
|
+
ON ai.chat_task_occurrences(completed_at, id)
|
|
1022
|
+
WHERE state IN ('completed', 'failed')
|
|
1023
|
+
`.simple();
|
|
1024
|
+
|
|
1008
1025
|
await sql`
|
|
1009
1026
|
CREATE UNIQUE INDEX IF NOT EXISTS idx_ai_chat_task_occurrences_active_task
|
|
1010
1027
|
ON ai.chat_task_occurrences(task_id)
|
|
@@ -1273,7 +1290,7 @@ export const migrateCloudAi = async (): Promise<void> => {
|
|
|
1273
1290
|
CONSTRAINT ai_memory_learning_runs_kind_check CHECK (run_kind IN ('turn', 'workflow')),
|
|
1274
1291
|
CONSTRAINT ai_memory_learning_runs_evidence_check CHECK (
|
|
1275
1292
|
(run_kind = 'turn' AND evidence_key IS NULL)
|
|
1276
|
-
OR (run_kind = 'workflow' AND
|
|
1293
|
+
OR (run_kind = 'workflow' AND evidence_key IS NOT NULL)
|
|
1277
1294
|
),
|
|
1278
1295
|
CONSTRAINT ai_memory_learning_runs_changes_check CHECK (jsonb_typeof(changes) = 'array')
|
|
1279
1296
|
)
|
|
@@ -1299,7 +1316,7 @@ export const migrateCloudAi = async (): Promise<void> => {
|
|
|
1299
1316
|
await sql`
|
|
1300
1317
|
ALTER TABLE ai.memory_learning_runs ADD CONSTRAINT ai_memory_learning_runs_evidence_check CHECK (
|
|
1301
1318
|
(run_kind = 'turn' AND evidence_key IS NULL)
|
|
1302
|
-
OR (run_kind = 'workflow' AND
|
|
1319
|
+
OR (run_kind = 'workflow' AND evidence_key IS NOT NULL)
|
|
1303
1320
|
)
|
|
1304
1321
|
`.simple();
|
|
1305
1322
|
await sql`
|