···
191
-
<p class="prompt">C:\PLASTIC> DIR</p>
193
-
<div class="file-listing">
194
-
<div class="file-line">
195
-
Volume in drive C is PLASTIC-SYS
197
-
<div class="file-line">Directory of C:\PLASTIC</div>
198
-
<div class="file-line"></div>
199
-
<div class="file-line">
200
-
<span class="dir">SYSTEM <DIR></span> 12-15-95
203
-
<div class="file-line">
204
-
<span class="exe">PLASTIC EXE</span> 24,576 12-15-95
207
-
<div class="file-line">
208
-
<span class="txt">README TXT</span> 1,024 12-15-95 3:42p
210
-
<div class="file-line">
211
-
<span class="txt">CONFIG SYS</span> 512 12-15-95 3:42p
213
-
<div class="file-line">4 File(s) 26,112 bytes</div>
214
-
<div class="file-line">524,288 bytes free</div>
<p class="prompt">C:\PLASTIC> PLASTIC.EXE</p>
···
<li>Supports EGA/VGA graphics modes</li>
275
-
<h2>System Commands:</h2>
277
-
<span class="command">HELP</span>
278
-
<span class="command">DIR</span>
279
-
<span class="command">EDIT</span>
280
-
<span class="command">RUN</span>
281
-
<span class="command">EXIT</span>
════════════════════════════════════════════════════════════
288
-
<p>Runtime: 00:13:37 | Memory: 589K free | CPU: 80486DX-33</p>
290
-
WARNING: Unauthorized modification may corrupt system files
254
+
Runtime: <span id="runtime">00:13:37</span> | Memory:
255
+
<span id="memory">589K free</span> | CPU: 80486DX-33
293
-
<p class="prompt">C:\PLASTIC> <span class="cursor">_</span></p>
<span>F1=Help F2=Save F3=Load F10=Menu</span>
298
-
<span>12:34 PM</span>
// Tool call system for AI to interact with the page
305
-
replaceElement: function(selector, newHTML) {
268
+
replaceElement: function (selector, newHTML) {
const element = document.querySelector(selector);
element.outerHTML = newHTML;
309
-
return { success: true, message: `Replaced element: ${selector}` };
274
+
message: `Replaced element: ${selector}`,
311
-
return { success: false, message: `Element not found: ${selector}` };
279
+
message: `Element not found: ${selector}`,
314
-
updateElement: function(selector, newContent) {
283
+
updateElement: function (selector, newContent) {
const element = document.querySelector(selector);
element.innerHTML = newContent;
318
-
return { success: true, message: `Updated element: ${selector}` };
289
+
message: `Updated element: ${selector}`,
320
-
return { success: false, message: `Element not found: ${selector}` };
294
+
message: `Element not found: ${selector}`,
323
-
addElement: function(parentSelector, newHTML, position = 'beforeend') {
298
+
addElement: function (
301
+
position = "beforeend",
const parent = document.querySelector(parentSelector);
parent.insertAdjacentHTML(position, newHTML);
327
-
return { success: true, message: `Added element to: ${parentSelector}` };
308
+
message: `Added element to: ${parentSelector}`,
329
-
return { success: false, message: `Parent not found: ${parentSelector}` };
313
+
message: `Parent not found: ${parentSelector}`,
332
-
removeElement: function(selector) {
317
+
removeElement: function (selector) {
const element = document.querySelector(selector);
336
-
return { success: true, message: `Removed element: ${selector}` };
323
+
message: `Removed element: ${selector}`,
338
-
return { success: false, message: `Element not found: ${selector}` };
328
+
message: `Element not found: ${selector}`,
341
-
updateStyle: function(selector, styleObj) {
332
+
updateStyle: function (selector, styleObj) {
const element = document.querySelector(selector);
Object.assign(element.style, styleObj);
345
-
return { success: true, message: `Updated styles for: ${selector}` };
338
+
message: `Updated styles for: ${selector}`,
347
-
return { success: false, message: `Element not found: ${selector}` };
343
+
message: `Element not found: ${selector}`,
350
-
executeJS: function(code) {
347
+
executeJS: function (code) {
const result = eval(code);
353
-
return { success: true, message: 'JavaScript executed', result: result };
352
+
message: "JavaScript executed",
355
-
return { success: false, message: `JS Error: ${error.message}` };
358
+
message: `JS Error: ${error.message}`,
function executeToolCall(toolCall) {
const { function: func, arguments: args } = toolCall;
362
-
console.log('Executing tool call:', func, args);
366
+
console.log("Executing tool call:", func, args);
if (window.toolCallbacks[func]) {
// Handle different function signatures
367
-
if (func === 'removeElement') {
371
+
if (func === "removeElement") {
// removeElement expects just a selector
369
-
const selector = args.selector || Object.keys(args)[0] || Object.values(args)[0];
375
+
Object.keys(args)[0] ||
376
+
Object.values(args)[0];
return window.toolCallbacks[func](selector);
371
-
} else if (func === 'updateStyle' && args.styleObj) {
372
-
return window.toolCallbacks[func](args.selector, args.styleObj);
373
-
} else if (func === 'executeJS') {
378
+
} else if (func === "updateStyle" && args.styleObj) {
379
+
return window.toolCallbacks[func](
383
+
} else if (func === "executeJS") {
return window.toolCallbacks[func](args.code);
375
-
} else if (func === 'updateElement') {
376
-
return window.toolCallbacks[func](args.selector, args.newContent);
377
-
} else if (func === 'replaceElement') {
378
-
return window.toolCallbacks[func](args.selector, args.newHTML);
379
-
} else if (func === 'addElement') {
380
-
return window.toolCallbacks[func](args.parentSelector, args.newHTML, args.position);
385
+
} else if (func === "updateElement") {
386
+
return window.toolCallbacks[func](
390
+
} else if (func === "replaceElement") {
391
+
return window.toolCallbacks[func](
395
+
} else if (func === "addElement") {
396
+
return window.toolCallbacks[func](
397
+
args.parentSelector,
// Fallback: use all argument values in order
383
-
return window.toolCallbacks[func](...Object.values(args));
403
+
return window.toolCallbacks[func](
404
+
...Object.values(args),
386
-
return { success: false, message: `Error executing ${func}: ${error.message}` };
410
+
message: `Error executing ${func}: ${error.message}`,
return { success: false, message: `Unknown tool: ${func}` };
···
// Clean up response and extract JSON if present
let cleanResponse = generatedContent.trim();
// Remove markdown formatting
cleanResponse = cleanResponse
.replace(/```json\n?/g, "")
// Try to extract JSON from mixed content
463
-
const jsonMatch = cleanResponse.match(/\{[\s\S]*"tool_calls"[\s\S]*\}/);
488
+
const jsonMatch = cleanResponse.match(
489
+
/\{[\s\S]*"tool_calls"[\s\S]*\}/,
cleanResponse = jsonMatch[0];
468
-
console.log('Cleaned response:', cleanResponse);
495
+
console.log("Cleaned response:", cleanResponse);
// Check if response contains tool calls
const toolResponse = JSON.parse(cleanResponse);
473
-
if (toolResponse.tool_calls && Array.isArray(toolResponse.tool_calls)) {
501
+
toolResponse.tool_calls &&
502
+
Array.isArray(toolResponse.tool_calls)
for (const toolCall of toolResponse.tool_calls) {
const result = executeToolCall(toolCall);
479
-
console.log('Tool call result:', result);
509
+
console.log("Tool call result:", result);
statusDiv.textContent = `EXECUTED ${results.length} COMMANDS`;
// Send feedback to AI about tool results
484
-
setTimeout(() => sendToolFeedback(userPrompt, results), 100);
515
+
() => sendToolFeedback(userPrompt, results),
throw new Error("Invalid tool call format");
489
-
console.log('JSON parse error:', jsonError);
490
-
console.log('Raw response:', generatedContent);
491
-
console.log('Attempting to parse as HTML...');
522
+
console.log("JSON parse error:", jsonError);
523
+
console.log("Raw response:", generatedContent);
524
+
console.log("Attempting to parse as HTML...");
// Not JSON, treat as HTML code
let cleanCode = generatedContent
.replace(/```html\n?/g, "")
statusDiv.textContent = "INJECTING CODE...";
499
-
document.querySelector(".content").innerHTML += cleanCode;
532
+
document.querySelector(".content").innerHTML +=
statusDiv.textContent = "CODE EXECUTION SUCCESSFUL";
···
async function sendToolFeedback(originalPrompt, toolResults) {
const statusDiv = document.getElementById("statusDisplay");
statusDiv.textContent = "SENDING FEEDBACK TO AI...";
const currentPageHTML = document.documentElement.outerHTML;
527
-
const resultsText = toolResults.map(r =>
528
-
`${r.success ? '✓' : '✗'} ${r.message}${r.result ? ` (result: ${r.result})` : ''}`
561
+
const resultsText = toolResults
564
+
`${r.success ? "✓" : "✗"} ${r.message}${r.result ? ` (result: ${r.result})` : ""}`,
const response = await fetch(
"https://ai.hackclub.com/chat/completions",
···
550
-
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
588
+
`HTTP ${response.status}: ${response.statusText}`,
const data = await response.json();
556
-
if (data.choices && data.choices[0] && data.choices[0].message) {
598
+
data.choices[0].message
followUpContent = data.choices[0].message.content;
} else if (data.content) {
followUpContent = data.content;
···
followUpContent = followUpContent.trim();
567
-
console.log('Follow-up response:', followUpContent);
610
+
console.log("Follow-up response:", followUpContent);
if (followUpContent === "COMPLETE") {
statusDiv.textContent = "AI SATISFIED - TASK COMPLETE";
571
-
setTimeout(() => statusDiv.textContent = "", 3000);
614
+
setTimeout(() => (statusDiv.textContent = ""), 3000);
// Process follow-up commands
statusDiv.textContent = "AI MAKING ADJUSTMENTS...";
// Try to parse as tool calls
580
-
const jsonMatch = followUpContent.match(/\{[\s\S]*"tool_calls"[\s\S]*\}/);
623
+
const jsonMatch = followUpContent.match(
624
+
/\{[\s\S]*"tool_calls"[\s\S]*\}/,
const toolResponse = JSON.parse(jsonMatch[0]);
583
-
if (toolResponse.tool_calls && Array.isArray(toolResponse.tool_calls)) {
629
+
toolResponse.tool_calls &&
630
+
Array.isArray(toolResponse.tool_calls)
const followUpResults = [];
for (const toolCall of toolResponse.tool_calls) {
const result = executeToolCall(toolCall);
followUpResults.push(result);
588
-
console.log('Follow-up tool result:', result);
637
+
"Follow-up tool result:",
statusDiv.textContent = `AI EXECUTED ${followUpResults.length} ADJUSTMENTS`;
···
let cleanCode = followUpContent
.replace(/```html\n?/g, "")
597
-
document.querySelector(".content").innerHTML += cleanCode;
598
-
statusDiv.textContent = "AI ADDED FOLLOW-UP CONTENT";
648
+
document.querySelector(".content").innerHTML +=
650
+
statusDiv.textContent =
651
+
"AI ADDED FOLLOW-UP CONTENT";
601
-
console.log('Follow-up parsing error:', error);
654
+
console.log("Follow-up parsing error:", error);
statusDiv.textContent = "AI FEEDBACK ERROR";
605
-
setTimeout(() => statusDiv.textContent = "", 4000);
658
+
setTimeout(() => (statusDiv.textContent = ""), 4000);
statusDiv.textContent = `FEEDBACK ERROR: ${error.message}`;
609
-
console.error('Feedback error:', error);
610
-
setTimeout(() => statusDiv.textContent = "", 3000);
661
+
console.error("Feedback error:", error);
662
+
setTimeout(() => (statusDiv.textContent = ""), 3000);
···
const timeStr = now.toLocaleTimeString([], {
const statusBarTime = document.querySelector(
".status-bar span:last-child",
statusBarTime.textContent = timeStr;
693
+
// Update memory in status bar based on actual tab memory usage
694
+
const memoryUsage = Math.round(
696
+
? performance.memory.usedJSHeapSize / 1024
700
+
const memoryStr = `${589 - Math.min(Math.round(memoryUsage / 1024), 500)}K free`;
701
+
const memory = document.getElementById("memory");
703
+
memory.textContent = memoryStr;
706
+
// Update runtime in status bar - based on how long the page has been open
707
+
const pageOpenTime = performance.timing
708
+
? performance.timing.navigationStart || Date.now()
710
+
const timeOpen = Math.floor((Date.now() - pageOpenTime) / 1000);
711
+
const hours = Math.floor(timeOpen / 3600)
714
+
const minutes = Math.floor((timeOpen % 3600) / 60)
717
+
const seconds = Math.floor(timeOpen % 60)
720
+
const runtimeStr = `${hours}:${minutes}:${seconds}`;
721
+
const runtime = document.getElementById("runtime");
723
+
runtime.textContent = runtimeStr;