@usabledev/usable-chat 1.165.1 → 1.167.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/cli.js +52 -5
- package/package.json +1 -1
package/cli.js
CHANGED
|
@@ -90993,7 +90993,7 @@ var init_data_staging_prompt = __esm({
|
|
|
90993
90993
|
"use strict";
|
|
90994
90994
|
DATA_STAGING_PROMPT = `# Staged Data \u2014 read THIS first
|
|
90995
90995
|
|
|
90996
|
-
The user can drop CSV / TSV / Parquet / XLSX / XLS / JSON / NDJSON / \`.duckdb\` files, paste
|
|
90996
|
+
The user can drop CSV / TSV / Parquet / XLSX / XLS / JSON / NDJSON / \`.duckdb\` files, paste URL, or attach a browser folder. Files stage into browser DuckDB. \`RAW\` entries have no rows/cols; host uses \`chat.data.readBytes(alias)\`.
|
|
90997
90997
|
|
|
90998
90998
|
In the actual tool list these usually appear with a \`parent_\` prefix, e.g. \`parent_data_list\`, \`parent_data_load_browser_file\`, \`parent_data_describe\`, \`parent_data_query\`. If present, call the exact \`parent_data_*\` tool; shorter \`data_*\` names below are canonical.
|
|
90999
90999
|
|
|
@@ -91001,7 +91001,7 @@ In the actual tool list these usually appear with a \`parent_\` prefix, e.g. \`p
|
|
|
91001
91001
|
|
|
91002
91002
|
Whenever the user types any of these (or anything similar): **"analyze this"**, **"what's in the file"**, **"the data"**, **"the file"**, **"this CSV / spreadsheet / parquet / dataset"**, **"summarise this"**, **"chart this"**, **"plot this"**, **"what does the data look like"** \u2014 **ALWAYS** call \`data_list\` BEFORE you reply.
|
|
91003
91003
|
|
|
91004
|
-
- If \`data_list\` returns
|
|
91004
|
+
- If \`data_list\` returns a structured file, **THAT IS WHAT THE USER MEANS**. Proceed with \`data_describe\` \u2192 tools. If only \`RAW\` matches, explain that the host app parses it.
|
|
91005
91005
|
- **NEVER** reply *"please upload a file"*, *"share the file with me"*, *"I don't have access to the file"*, or any variation when \`data_list\` returns \u2265 1 entry. The file is already staged. Just analyse it.
|
|
91006
91006
|
- **NEVER** ask the user to paste rows. They already gave you the file; query it through the tools.
|
|
91007
91007
|
- If the user names a file in the attached local folder and it is NOT in \`data_list\`, call \`parent_data_load_browser_file({ path })\` / \`data_load_browser_file({ path })\` first, then list + describe.
|
|
@@ -91432,6 +91432,20 @@ var init_parent_tools = __esm({
|
|
|
91432
91432
|
required: ["alias"]
|
|
91433
91433
|
}
|
|
91434
91434
|
},
|
|
91435
|
+
{
|
|
91436
|
+
name: "data_get_bytes",
|
|
91437
|
+
description: "Return a staged file's raw browser bytes as base64 so the embed host can parse host-specific formats (for example GPX, KML, KMZ) without Usable Chat shipping per-format parsers. Pass a parent alias from data_list; child table aliases are rejected.",
|
|
91438
|
+
parameters: {
|
|
91439
|
+
type: "object",
|
|
91440
|
+
properties: {
|
|
91441
|
+
alias: {
|
|
91442
|
+
type: "string",
|
|
91443
|
+
description: "Alias from data_list. For .duckdb files, pass the parent alias."
|
|
91444
|
+
}
|
|
91445
|
+
},
|
|
91446
|
+
required: ["alias"]
|
|
91447
|
+
}
|
|
91448
|
+
},
|
|
91435
91449
|
{
|
|
91436
91450
|
name: "data_load_remote",
|
|
91437
91451
|
description: "Fetch a CSV/TSV/Parquet/JSON/NDJSON/XLSX/.duckdb file from an HTTPS URL and stage it as if the user had uploaded it. By DEFAULT the request routes through a same-origin proxy (/api/data-proxy with RFC 7233 Range support) \u2014 this is required because the chat's CSP `connect-src` is locked to a small allowlist, so direct cross-origin fetches will fail. Only pass `useProxy: false` when the URL is on a CSP-allowlisted host (rare). Format is auto-detected from the URL extension; pass `format` explicitly when the URL has no extension (e.g. share-link APIs that return a UUID). For `.duckdb` files, multiple sub-aliases are returned \u2014 one per attached table.",
|
|
@@ -285711,6 +285725,16 @@ var init_file_storage_service = __esm({
|
|
|
285711
285725
|
});
|
|
285712
285726
|
this.totalCacheBytes += size2;
|
|
285713
285727
|
}
|
|
285728
|
+
clearFileCache(fileId, userId) {
|
|
285729
|
+
for (const ensureCompressed of [false, true]) {
|
|
285730
|
+
const key = this.makeCacheKey(fileId, userId, ensureCompressed);
|
|
285731
|
+
const cached2 = this.cache.get(key);
|
|
285732
|
+
if (cached2) {
|
|
285733
|
+
this.cache.delete(key);
|
|
285734
|
+
this.totalCacheBytes -= cached2.size;
|
|
285735
|
+
}
|
|
285736
|
+
}
|
|
285737
|
+
}
|
|
285714
285738
|
/**
|
|
285715
285739
|
* Estimate tokens from content (rough estimation: 4 chars/token for text, size-based for images)
|
|
285716
285740
|
*/
|
|
@@ -285724,12 +285748,13 @@ var init_file_storage_service = __esm({
|
|
|
285724
285748
|
/**
|
|
285725
285749
|
* Store a file's extracted content with rotating storage
|
|
285726
285750
|
* Automatically removes oldest files if user exceeds limit
|
|
285727
|
-
* For images: stores both original (full quality) and compressed (for LLM) versions
|
|
285751
|
+
* For images: stores both original (full quality) and compressed (for LLM) versions.
|
|
285752
|
+
* For documents: keeps extractedContent as text and optional originalContent as base64 bytes.
|
|
285728
285753
|
*/
|
|
285729
285754
|
async storeFile(params) {
|
|
285730
285755
|
const fileId = randomUUID4();
|
|
285731
285756
|
let extractedContent = params.extractedContent;
|
|
285732
|
-
let originalContent = null;
|
|
285757
|
+
let originalContent = params.originalContent ?? null;
|
|
285733
285758
|
if (params.fileType === "image" && params.contentType === "base64") {
|
|
285734
285759
|
originalContent = params.extractedContent;
|
|
285735
285760
|
try {
|
|
@@ -285885,6 +285910,28 @@ var init_file_storage_service = __esm({
|
|
|
285885
285910
|
).orderBy(desc(fileStorage.createdAt)).limit(1);
|
|
285886
285911
|
return existing || null;
|
|
285887
285912
|
}
|
|
285913
|
+
/**
|
|
285914
|
+
* Backfill original uploaded bytes onto a legacy duplicate row.
|
|
285915
|
+
* This preserves the rotating-storage dedupe behaviour while making older
|
|
285916
|
+
* text-only rows usable by file_to_sandbox after a user re-uploads the file.
|
|
285917
|
+
*/
|
|
285918
|
+
async ensureOriginalContent(file2, userId, originalContent) {
|
|
285919
|
+
if (!originalContent || file2.originalContent) {
|
|
285920
|
+
return file2;
|
|
285921
|
+
}
|
|
285922
|
+
const [updatedFile] = await db.update(fileStorage).set({
|
|
285923
|
+
originalContent,
|
|
285924
|
+
lastUsedAt: /* @__PURE__ */ new Date()
|
|
285925
|
+
}).where(and(eq(fileStorage.id, file2.id), eq(fileStorage.userId, userId))).returning();
|
|
285926
|
+
this.clearFileCache(file2.id, userId);
|
|
285927
|
+
logger.info("FileStorage", "backfilled original bytes for duplicate upload", {
|
|
285928
|
+
fileId: file2.id,
|
|
285929
|
+
fileName: file2.fileName,
|
|
285930
|
+
fileType: file2.fileType,
|
|
285931
|
+
fileSize: file2.fileSize
|
|
285932
|
+
});
|
|
285933
|
+
return updatedFile || file2;
|
|
285934
|
+
}
|
|
285888
285935
|
/**
|
|
285889
285936
|
* Check if a file exists by ID
|
|
285890
285937
|
*/
|
|
@@ -308939,7 +308986,7 @@ init_tui_select();
|
|
|
308939
308986
|
init_model_registry();
|
|
308940
308987
|
|
|
308941
308988
|
// package.json
|
|
308942
|
-
var version2 = "1.
|
|
308989
|
+
var version2 = "1.167.0";
|
|
308943
308990
|
|
|
308944
308991
|
// src/adapters/cli/model-catalog.ts
|
|
308945
308992
|
init_codex_auth();
|