Spaces:
Running
Running
File size: 12,445 Bytes
dcc955a | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 | // shared.js β common catalog, system prompts, and 0G helpers for Oga Market
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
// GOOD ONLINE PRODUCT CATALOG (lifted from Oga Mi)
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
window.GOOD_CATALOG = `
## GOOD ONLINE PRODUCT CATALOG (good.online)
"Made by Nigerians. Curated for you." β A marketplace connecting you with Nigerian creators committed to quality and positive impact. Delivers within Lagos only.
### FEATURED PRODUCTS
- Coconut Rice (430g) by Chumbys β N5,400 [Cook it Yourself]
- Glow Oil by Arami β N13,600 [Beauty]
- Whole Cashew Jar by The M & W Nuts Company β N11,875 [Snacks]
- Gym Socks Box by Smileys Africa β N17,500 [Fashion]
- Miniature Trio by Dala Craft β N54,000 [Home & Living]
- Sugar Wax Kit by Sugar Wax By Audrey β N17,000 [Beauty]
- Dudu Ball Chain by ITURA Jewelry β N40,000 [Fashion/Jewelry]
- Mini Scented Candle Gift Set by Jacque Lagos β N70,000 [Gifts/Home]
- Plantain Clusters by Good Originals β N5,520 [Snacks]
### CATEGORIES
Fashion, Beauty, Home & Living, Wellness, Gifts, Leisure, Good Originals, Snacks, Drinks, Cook it Yourself, Worklife, For Moms, For Women
### CURATED LISTS (with starting prices)
- "For Everyone Carrying This Economy on Their Back" β from N3,000
- "A Good Place to Start" β from N500
- "Something to Add to Your Skincare Routine" β from N4,000
- "Some Thoughtful Gifts for Everyone" β from N13,000
- "The Faster Way to Familiar Dishes" β from N2,250
- "Everyday Comforts That Make Life Feel Lighter" β from N7,500
- "For the Kids We're All Soft For" β from N5,160
- "Cyn Ugwu's Picks to Living a Good Life" β from N4,200
- "Travel Essentials That Actually Come in Handy" β from N4,500
### TOP CREATORS (50+)
Fashion: Smileys Africa, TETE AFRICA, Garmisland, Asabithebrand, AZACH, Claic Design, Captain Atelier, Marte Egele, Sarima By Ama, TwentySix, Crivel, OhMyCowries, Floy NG, Rade Label, 1403 Luxury, Lano Lagos, THESHOEBLOCC, Outlash, Vinc & Eliz, ITURA Jewelry, KunbiWorks
Beauty: Arami, Tamed Lux, Infused Organics, ESTEVAN PERFUMERY, Sugar Wax By Audrey, Sublime Skin by Jumai, Msmetics, Viektors Bath and Body, TGIN, Onoh Naturals
Home & Living: Jacque Lagos, Wallinggs Interior, Silkluxe Hub, Oeuvre Designs, Alore Lifestyle, Ediye Home Scents, Iluna Candles & Co, Hingees, The DA Brand, Scent L'avie
Wellness: Soft Mum Era, Enjoca, Olile Enterprises, Clove and Nectar, Just Journals
Snacks & Food: Chumbys, The M & W Nuts Company, Good Originals
Gifts: The Kulture Company, Not Just Pulp, FCAL (FC Accessories), The Ajala Game Store
Leisure: Atito, The Ajala Game Store
### STORE INFO
- Website: good.online
- Good House: 19B Sasegbon Street, Ikeja GRA, Lagos
- Good Village: Plot 33 Block 15, Admiralty Way, Lekki Phase 1, Lagos
- Contact: +2348142511154 / support@goodthingco.xyz
- Delivery: Lagos only
- Gift vouchers available at good.online
`;
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
// SYSTEM PROMPTS
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
window.buildShopperPrompt = function (customerName, history, wishlist) {
let prompt = `You are Oga Mi, a warm AI shopping assistant for Good Online (good.online), Nigeria's curated marketplace.
PERSONALITY:
- Warm, like a helpful Lagos market seller who genuinely cares
- Mix English with light Pidgin/Yoruba naturally ("Oga mi!", "Na good choice!", "E kaaro!")
- Enthusiastic about Nigerian creators
- Keep responses to 2-4 sentences. Recommend 1-2 products, not a long list
- Always finish your sentences
- Use Naira prices (write as N5,400)
${window.GOOD_CATALOG}
WHEN RECOMMENDING:
- Always mention price + creator
- Budget: "A Good Place to Start" (from N500)
- Gifts: "Some Thoughtful Gifts for Everyone" (from N13,000)
- Skincare: "Something to Add to Your Skincare Routine" (from N4,000)
When you recommend a specific product, end your message with [PRODUCT:Product Name|Creator|Price] so the UI can show an add-to-wishlist button. Example: [PRODUCT:Glow Oil|Arami|13600]. Only include this tag for products from the catalog above.`;
if (customerName) {
prompt += `\n\nCUSTOMER: ${customerName}. Use their name naturally.`;
}
if (wishlist && wishlist.length > 0) {
prompt += `\n\nWISHLIST: ${wishlist.map(w => w.name).join(', ')}. Reference these naturally if relevant.`;
}
if (history && history.length > 0) {
prompt += `\n\nPREVIOUS INTERACTIONS:\n${history.map(h => `- ${h}`).join('\n')}`;
}
return prompt;
};
window.buildCreatorPrompt = function (visionDescription, productName, price, creator) {
return `You are a copywriter for Good Online (good.online), a Nigerian curated marketplace. A creator is listing a new product. Generate a beautiful, warm, Nigerian-style product listing.
PRODUCT INFO:
- Name from creator: "${productName}"
- Creator: "${creator}"
- Price: N${Number(price).toLocaleString()}
- Vision analysis of the photo: "${visionDescription}"
Reference catalog (for style + category matching):
${window.GOOD_CATALOG}
OUTPUT REQUIREMENTS β respond ONLY with valid JSON, no other text:
{
"title": "A polished product name (max 6 words, sentence case)",
"tagline": "A 1-sentence editorial hook in warm, Nigerian voice (max 14 words)",
"description": "A 2-3 sentence description that tells the product's story, mentions the creator, and feels handmade/curated. Sentence case. No emoji.",
"category": "One category from this list: Fashion, Beauty, Home & Living, Wellness, Gifts, Leisure, Snacks, Drinks, Cook it Yourself, Worklife, For Moms, For Women",
"curatedList": "One of these curated lists if relevant, or null: A Good Place to Start | Some Thoughtful Gifts for Everyone | Something to Add to Your Skincare Routine | Everyday Comforts That Make Life Feel Lighter | For the Kids We're All Soft For | Travel Essentials That Actually Come in Handy",
"priceFeedback": "1 sentence: is this price aligned with similar products on Good? Be honest."
}`;
};
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
// 0G COMPUTE HELPERS (Direct mode, browser-CORS-friendly)
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
window.OG_ENDPOINTS = {
chat: 'https://compute-network-1.integratenetwork.work/v1/proxy/chat/completions',
whisper: 'https://compute-network-16.integratenetwork.work/v1/proxy/audio/transcriptions',
// Vision provider may live on a different compute-network β verify on pc.0g.ai
vision: 'https://compute-network-1.integratenetwork.work/v1/proxy/chat/completions',
};
window.askAI = async function (chatKey, model, messages, { maxTokens = 512 } = {}) {
const res = await fetch(window.OG_ENDPOINTS.chat, {
method: 'POST',
headers: { 'Authorization': `Bearer ${chatKey}`, 'Content-Type': 'application/json' },
body: JSON.stringify({ model, messages, max_tokens: maxTokens }),
});
if (!res.ok) throw new Error(`Chat ${res.status}: ${(await res.text()).slice(0, 200)}`);
const data = await res.json();
return (data.choices?.[0]?.message?.content || '').trim();
};
window.askVision = async function (chatKey, model, imageDataUrl, instruction, { maxTokens = 256 } = {}) {
// OpenAI-compatible vision message format
const res = await fetch(window.OG_ENDPOINTS.vision, {
method: 'POST',
headers: { 'Authorization': `Bearer ${chatKey}`, 'Content-Type': 'application/json' },
body: JSON.stringify({
model,
messages: [{
role: 'user',
content: [
{ type: 'text', text: instruction },
{ type: 'image_url', image_url: { url: imageDataUrl } },
],
}],
max_tokens: maxTokens,
}),
});
if (!res.ok) throw new Error(`Vision ${res.status}: ${(await res.text()).slice(0, 200)}`);
const data = await res.json();
return (data.choices?.[0]?.message?.content || '').trim();
};
// Convert browser webm/opus audio to PCM WAV (0G Whisper rejects raw webm)
window.webmBlobToWav = async function (blob) {
const buf = await blob.arrayBuffer();
const ctx = new (window.AudioContext || window.webkitAudioContext)();
const audio = await ctx.decodeAudioData(buf);
try { ctx.close(); } catch (_) {}
const ch0 = audio.getChannelData(0);
const len = ch0.length;
const sampleRate = audio.sampleRate;
const out = new ArrayBuffer(44 + len * 2);
const v = new DataView(out);
const ws = (off, s) => { for (let i = 0; i < s.length; i++) v.setUint8(off + i, s.charCodeAt(i)); };
ws(0, 'RIFF'); v.setUint32(4, 36 + len * 2, true); ws(8, 'WAVE');
ws(12, 'fmt '); v.setUint32(16, 16, true);
v.setUint16(20, 1, true); v.setUint16(22, 1, true);
v.setUint32(24, sampleRate, true); v.setUint32(28, sampleRate * 2, true);
v.setUint16(32, 2, true); v.setUint16(34, 16, true);
ws(36, 'data'); v.setUint32(40, len * 2, true);
let off = 44;
for (let i = 0; i < len; i++) {
const s = Math.max(-1, Math.min(1, ch0[i]));
v.setInt16(off, s < 0 ? s * 0x8000 : s * 0x7FFF, true);
off += 2;
}
return new Blob([out], { type: 'audio/wav' });
};
window.transcribe = async function (sttKey, webmBlob) {
const wav = await window.webmBlobToWav(webmBlob);
const form = new FormData();
form.append('file', wav, 'audio.wav');
form.append('model', 'openai/whisper-large-v3');
form.append('response_format', 'json');
const res = await fetch(window.OG_ENDPOINTS.whisper, {
method: 'POST',
headers: { 'Authorization': `Bearer ${sttKey}` },
body: form,
});
if (!res.ok) throw new Error(`STT ${res.status}: ${(await res.text()).slice(0, 200)}`);
return (await res.json()).text || '';
};
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
// 0G CHAIN HELPERS
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
window.OG_CHAIN = {
rpc: 'https://evmrpc-testnet.0g.ai',
chainId: 16602,
explorerTx: (h) => `https://chainscan-galileo.0g.ai/tx/${h}`,
// Deployed ListingNFT contract address β paste after running contract/deploy.js
listingNFT: '',
};
window.LISTING_NFT_ABI = [
'function mint(string dataDescription, bytes32 dataHash) external returns (uint256)',
'function getData(uint256 tokenId) external view returns (string dataDescription, bytes32 dataHash, address creator, uint256 timestamp)',
'function totalSupply() external view returns (uint256)',
'function ownerOf(uint256 tokenId) external view returns (address)',
'function transferFrom(address from, address to, uint256 tokenId) external',
'event ListingMinted(uint256 indexed tokenId, address indexed creator, string dataDescription, bytes32 dataHash, uint256 timestamp)',
];
window.shortHash = function (h) {
return h.slice(0, 10) + 'β¦' + h.slice(-6);
};
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
// LOCAL STORAGE HELPERS (0G Storage proxy)
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
window.OG_STORAGE = {
load(key) {
try { return JSON.parse(localStorage.getItem(key) || 'null'); } catch (_) { return null; }
},
save(key, value) {
localStorage.setItem(key, JSON.stringify(value));
},
};
|