feat(demo): per-folder media merge + AIUI seed-chats bootstrap
- Curated files loader now MERGES per top-level folder: dropping real files into demo/files/Music/ swaps only Music and keeps the sample Documents/Photos/Videos (verified). Media plays with the Range support already in place. - AIUI index.html: a ?seed bootstrap pre-loads the example "Content Showcase" conversation into AIUI's IndexedDB by calling the bundle's own seedPromptsToConversation() (identical to its /seed command), so the chat history isn't empty when the demo points users to "previous chats". Guarded by try/catch + an existence check; no-op without ?seed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
445f08a5c1
commit
7efebb4a8c
@ -14,6 +14,31 @@
|
|||||||
<link rel="icon" href="/aiui/favicon.svg" type="image/svg+xml" />
|
<link rel="icon" href="/aiui/favicon.svg" type="image/svg+xml" />
|
||||||
<link rel="apple-touch-icon" href="/aiui/apple-touch-icon-180x180.png" />
|
<link rel="apple-touch-icon" href="/aiui/apple-touch-icon-180x180.png" />
|
||||||
<title>AIUI</title>
|
<title>AIUI</title>
|
||||||
|
<!-- Demo (?seed): pre-load the example "Content Showcase" conversation into
|
||||||
|
AIUI's IndexedDB so the chat history isn't empty (live chat is disabled
|
||||||
|
in the demo and points users to these previous chats). Mirrors the app's
|
||||||
|
own /seed exactly by calling its seedPromptsToConversation(). -->
|
||||||
|
<script type="module">
|
||||||
|
(async () => {
|
||||||
|
try {
|
||||||
|
if (!new URLSearchParams(location.search).has('seed')) return;
|
||||||
|
const db = await new Promise((res, rej) => {
|
||||||
|
const r = indexedDB.open('aiui-store', 1);
|
||||||
|
r.onupgradeneeded = (e) => { const d = e.target.result; if (!d.objectStoreNames.contains('conversations')) d.createObjectStore('conversations', { keyPath: 'id' }); };
|
||||||
|
r.onsuccess = () => res(r.result); r.onerror = () => rej(r.error);
|
||||||
|
});
|
||||||
|
const exists = await new Promise((res) => {
|
||||||
|
try { const q = db.transaction('conversations', 'readonly').objectStore('conversations').getKey('seed-all'); q.onsuccess = () => res(!!q.result); q.onerror = () => res(false); }
|
||||||
|
catch { res(false); }
|
||||||
|
});
|
||||||
|
if (exists) return;
|
||||||
|
const { seedPromptsToConversation } = await import('/aiui/assets/seedPrompts-CLWaUv28.js');
|
||||||
|
const conv = seedPromptsToConversation();
|
||||||
|
await new Promise((res, rej) => { const t = db.transaction('conversations', 'readwrite'); t.objectStore('conversations').put(conv); t.oncomplete = () => res(); t.onerror = () => rej(t.error); });
|
||||||
|
try { localStorage.setItem('aiui-active-conversation', conv.id); } catch {}
|
||||||
|
} catch (e) { console.warn('[demo] AIUI seed bootstrap failed', e); }
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
<script type="module" crossorigin src="/aiui/assets/index-Lh5NfTCq.js"></script>
|
<script type="module" crossorigin src="/aiui/assets/index-Lh5NfTCq.js"></script>
|
||||||
<link rel="stylesheet" crossorigin href="/aiui/assets/index-CHQ7uqBj.css">
|
<link rel="stylesheet" crossorigin href="/aiui/assets/index-CHQ7uqBj.css">
|
||||||
<link rel="manifest" href="/aiui/manifest.webmanifest"><script id="vite-plugin-pwa:register-sw" src="/aiui/registerSW.js"></script></head>
|
<link rel="manifest" href="/aiui/manifest.webmanifest"><script id="vite-plugin-pwa:register-sw" src="/aiui/registerSW.js"></script></head>
|
||||||
|
|||||||
@ -3626,11 +3626,21 @@ function loadDemoDiskFiles() {
|
|||||||
}
|
}
|
||||||
walk(root, '/')
|
walk(root, '/')
|
||||||
if (!tree['/'].length) return // empty folder → keep the hardcoded seeds
|
if (!tree['/'].length) return // empty folder → keep the hardcoded seeds
|
||||||
for (const k of Object.keys(SEED_FILES)) delete SEED_FILES[k]
|
// Per-folder MERGE: a top-level folder present in demo/files replaces that
|
||||||
Object.assign(SEED_FILES, tree)
|
// seed folder; seed folders the curator didn't provide (e.g. sample Documents)
|
||||||
for (const k of Object.keys(SEED_FILE_CONTENTS)) delete SEED_FILE_CONTENTS[k]
|
// are kept. So dropping real Music/ doesn't wipe the sample Documents.
|
||||||
|
const provided = new Set(tree['/'].map(e => e.name))
|
||||||
|
for (const k of Object.keys(SEED_FILES)) {
|
||||||
|
if (k !== '/' && provided.has(k.split('/')[1])) delete SEED_FILES[k]
|
||||||
|
}
|
||||||
|
for (const k of Object.keys(SEED_FILE_CONTENTS)) {
|
||||||
|
if (provided.has(k.split('/')[1])) delete SEED_FILE_CONTENTS[k]
|
||||||
|
}
|
||||||
|
const keptRoot = (SEED_FILES['/'] || []).filter(e => !provided.has(e.name))
|
||||||
|
for (const [k, v] of Object.entries(tree)) { if (k !== '/') SEED_FILES[k] = v }
|
||||||
|
SEED_FILES['/'] = [...keptRoot, ...tree['/']]
|
||||||
Object.assign(SEED_FILE_CONTENTS, contents)
|
Object.assign(SEED_FILE_CONTENTS, contents)
|
||||||
console.log(`[Demo] Loaded curated files from demo/files (${Object.keys(diskFilePaths).length} binary, ${Object.keys(contents).length} text)`)
|
console.log(`[Demo] Merged curated files from demo/files (${Object.keys(diskFilePaths).length} binary, ${Object.keys(contents).length} text; folders: ${[...provided].join(', ')})`)
|
||||||
}
|
}
|
||||||
loadDemoDiskFiles()
|
loadDemoDiskFiles()
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user