NPLLMfavicon.http.tsx1 match
10return new Response(svg, {
11headers: {
12"Content-Type": "image/svg+xml",
13},
14});
NPLLMstyles.css11 matches
747background-color: var(--highlight);
748}
749.card-image {
750display: flex;
751align-items: center;
774}
775776.image-placeholder,
777.image-thumbnail {
778flex-shrink: 0;
779width: 40px;
782object-fit: cover;
783}
784.image-placeholder {
785background-color: var(--muted);
786}
793}
794795.image-row {
796display: flex;
797gap: var(--space-1);
798}
799.input-image {
800position: relative;
801border: 1px solid var(--muted);
802border-radius: 6px;
803}
804.remove-image-button {
805position: absolute;
806top: 0;
815opacity: 0;
816}
817.input-image:hover .remove-image-button {
818opacity: 1;
819}
820821.image-drop-overlay {
822position: fixed;
823top: 0;
832justify-content: center;
833}
834.image-drop-inner {
835padding: var(--space-2);
836background-color: var(--background);
837}
838839.transition, .input-box, .icon-button, .button, .remove-image-button {
840transition-property: color, background-color, border-color, opacity;
841transition-duration: 200ms;
NPLLMsend-message.ts11 matches
26}
2728const { messages, project, branchId, anthropicApiKey, selectedFiles, images } = await c.req.json();
2930// do we want to allow user-provided tokens still
48branch_id: branchId,
49val_id: project.id,
50num_images: images?.length || 0,
51model: "claude-3-7-sonnet-20250219",
52});
58let coreMessages = convertToCoreMessages(messages);
5960// If there are images, we need to add them to the last user message
61if (images && Array.isArray(images) && images.length > 0) {
62// Find the last user message
63const lastUserMessageIndex = coreMessages.findIndex(
81};
8283// Add each image to the content array using the correct ImagePart format
84for (const image of images) {
85if (image && image.url) {
86// Extract mime type from data URL if available
87let mimeType = undefined;
88if (image.url.startsWith("data:")) {
89const matches = image.url.match(/^data:([^;]+);/);
90if (matches && matches.length > 1) {
91mimeType = matches[1];
9495newUserMessage.content.push({
96type: "image",
97image: image.url,
98mimeType,
99});
NPLLMuser-summary.ts2 matches
18SUM(cache_write_tokens) as total_cache_write_tokens,
19SUM(price) as total_price,
20SUM(num_images) as total_images
21FROM ${USAGE_TABLE}
22WHERE our_api_token = 1
101total_cache_write_tokens: userData.cache_write_tokens,
102total_price: userData.price,
103total_images: 0,
104used_inference_data: true
105});
NPLLMdashboard.ts3 matches
11total_cache_write_tokens: number;
12total_price: number;
13total_images: number;
14used_inference_data?: boolean;
15}
40<th>Cache Write</th>
41<th>Total Price</th>
42<th>Images</th>
43</tr>
44</thead>
54<td>${formatNumber(row.total_cache_write_tokens)} ${row.used_inference_data ? '<span class="badge badge-info" title="Using inference data">I</span>' : ''}</td>
55<td class="price">${formatPrice(row.total_price)} ${row.used_inference_data ? '<span class="badge badge-info" title="Using inference data">I</span>' : ''}</td>
56<td>${formatNumber(row.total_images)}</td>
57</tr>
58`).join("")}
NPLLMrequests.ts3 matches
16price: number | null;
17finish_reason: string | null;
18num_images: number | null;
19our_api_token: number;
20}
191<th>Price</th>
192<th>Finish</th>
193<th>Images</th>
194<th>Our API</th>
195</tr>
215<td class="price">${formatPrice(row.price)}</td>
216<td>${row.finish_reason || '-'}</td>
217<td>${formatNumber(row.num_images)}</td>
218<td>${formatBoolean(row.our_api_token)}</td>
219</tr>
NPLLMqueries.tsx4 matches
109model,
110our_api_token,
111num_images,
112}: {
113bearerToken: string;
116model: string;
117our_api_token: boolean;
118num_images: number;
119}) {
120const user = await getUser(bearerToken);
128model,
129our_api_token,
130num_images
131) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
132`,
139model,
140our_api_token ? 1 : 0,
141num_images,
142],
143);
NPLLMschema.tsx2 matches
18price?: number;
19finish_reason?: string;
20num_images?: number;
21our_api_token: boolean;
22}
43price REAL,
44finish_reason TEXT,
45num_images INTEGER,
46our_api_token INTEGER NOT NULL,
47finish_timestamp INTEGER
29- [x] File write as a code embed
30- [x] str_replace as a diff view
31- [x] make image drop area invisible and bigger
32- [x] Give it all the code (except maybe .txt files) as initial context (like cursor sonnet max)
33- [x] I seem to have lost the delete file tool and instructions, try to find them back in history or re-create?
55- [x] Create branch
56- [x] URL input + pathname
57- [x] Image upload controls
58- [x] Preview refresh button
59- [x] Audio controls
1// Global variables
2let currentWebsiteId = null;
3let currentImageKey = null;
4let websites = [];
5let users = [];
78// DOM elements
9const imageUpload = document.getElementById('imageUpload');
10const previewImg = document.getElementById('previewImg');
11const selectImageBtn = document.getElementById('selectImageBtn');
12const websiteUrl = document.getElementById('websiteUrl');
13const isActive = document.getElementById('isActive');
42// Set up all event listeners
43function setupEventListeners() {
44// Image upload
45selectImageBtn.addEventListener('click', () => {
46imageUpload.click();
47});
48
49imageUpload.addEventListener('change', handleImageUpload);
50
51// Form inputs
61}
6263// Handle image upload
64async function handleImageUpload(event) {
65const file = event.target.files[0];
66if (!file) return;
75// Upload to server
76const formData = new FormData();
77formData.append('image', file);
78
79try {
80const response = await fetch('/api/upload-image', {
81method: 'POST',
82body: formData
86
87if (result.success) {
88currentImageKey = result.key;
89markAsDirty();
90} else {
91alert('Error uploading image: ' + result.error);
92}
93} catch (error) {
94console.error('Error uploading image:', error);
95alert('Error uploading image. Please try again.');
96}
97}
174const tdLogo = document.createElement('td');
175const img = document.createElement('img');
176img.src = website.image_key ? `/api/image/${website.image_key}` : '/frontend/placeholder.jpg';
177img.alt = 'Logo';
178img.style.width = '100px';
251// Set current website ID
252currentWebsiteId = website.id;
253currentImageKey = website.image_key;
254
255// Populate form
256if (website.image_key) {
257previewImg.src = `/api/image/${website.image_key}`;
258} else {
259previewImg.src = '/frontend/placeholder.jpg';
297const data = {
298id: currentWebsiteId,
299image_key: currentImageKey,
300url: websiteUrl.value.trim(),
301is_active: isActive.checked,
382function resetForm() {
383currentWebsiteId = null;
384currentImageKey = null;
385
386previewImg.src = '/frontend/placeholder.jpg';