Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions puter_gui.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@

> puter.com@2.5.0 start=gui
> nodemon --exec "node dev-server.js"

[nodemon] 3.1.0
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): *.*
[nodemon] watching extensions: js,json,mjs,jsx,svg,css
[nodemon] starting `node dev-server.js`
147 changes: 147 additions & 0 deletions src/contract-analyzer/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AI Contract Analyzer</title>
<script src="https://js.puter.com/v2/"></script>
<script src="https://unpkg.com/pdfjs-dist@4.4.168/build/pdf.mjs" type="module"></script>
<style>
body {
font-family: sans-serif;
padding: 2em;
background-color: #f4f4f9;
}
#container {
max-width: 800px;
margin: 0 auto;
background: white;
padding: 2em;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
button {
padding: 10px 15px;
font-size: 1em;
cursor: pointer;
border: none;
background-color: #007bff;
color: white;
border-radius: 5px;
}
#results {
margin-top: 2em;
padding: 1em;
border: 1px solid #ddd;
border-radius: 5px;
background-color: #fafafa;
min-height: 100px;
}
</style>
</head>
<body>
<div id="container">
<h1>AI Contract Analyzer</h1>
<p>Upload a contract (PDF format) to get an AI-powered analysis of potential red flags.</p>
<button id="upload-btn">Upload Contract</button>
<button id="test-btn">Test with Sample Data</button>
<h2>Analysis Results</h2>
<div id="results">
<p>Your analysis will appear here.</p>
</div>
</div>

<script type="module">
// Set up the PDF.js worker
pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://unpkg.com/pdfjs-dist@4.4.168/build/pdf.worker.mjs';

const uploadBtn = document.getElementById('upload-btn');
const testBtn = document.getElementById('test-btn');
const resultsDiv = document.getElementById('results');

async function analyzeContractText(text) {
resultsDiv.innerHTML = '<p>Analyzing contract with AI... This may take a moment.</p>';
try {
const prompt = `
You are an expert contract analysis AI specializing in contracts for creative professionals like athletes, musicians, and artists. Your task is to review the following contract text and identify potential red flags.

Please analyze the text below for common exploitative clauses, such as:
- **Unfair Royalty/Revenue Splits:** Are the percentages standard for the industry?
- **Perpetual or Excessively Long-Term Rights:** Does the other party own the rights to the work forever?
- **"360 Deals" or "Ancillary Rights":** Does the contract grant rights to unrelated income streams (e.g., a music contract taking a cut of acting revenue)?
- **Vague or Ambiguous Language:** Are there clauses that are unclear or could be interpreted in multiple ways?
- **Lack of a "Key Person" Clause:** If the talent is signing with a specific agent or manager, what happens if that person leaves the company?
- **Unreasonable Exclusivity Clauses:** Does the contract prevent the talent from pursuing other opportunities to an unreasonable degree?

For each potential red flag you identify, please:
1. Quote the specific clause or text from the contract.
2. Explain in simple, clear language why it might be a concern.
3. Suggest what a more standard or fair alternative might look like.

If the contract appears to be generally fair or you don't find any significant red flags, please state that as well.

Here is the contract text:
---
${text}
---
`;
const aiResponse = await puter.ai.chat(prompt);

resultsDiv.innerHTML = `
<h2>AI Analysis Complete:</h2>
<div style="white-space: pre-wrap; background-color: #fff; border: 1px solid #ccc; padding: 1em; border-radius: 5px;">${aiResponse}</div>
`;
} catch (error) {
console.error('AI analysis error:', error);
resultsDiv.innerHTML = `<p style="color: red;">Error during AI analysis: ${error.message}</p>`;
}
}

testBtn.addEventListener('click', async () => {
const sampleContract = `
This agreement is made on this 1st day of January 2025.
Between:
"The Label", a record company.
"The Artist", a musician.

1. Term: The term of this agreement shall be perpetual. The Label will own all rights to The Artist's music, likeness, and merchandise forever.
2. Royalties: The Artist shall receive a royalty of 5% of all net profits from music sales. The Label defines "net profits" after all of its own expenses, which it does not need to justify.
3. 360 Rights: The Label shall be entitled to 50% of all of The Artist's income from any and all sources, including but not limited to, touring, merchandise, acting, and book deals.
`;
await analyzeContractText(sampleContract);
});

uploadBtn.addEventListener('click', async () => {
resultsDiv.innerHTML = '<p>Opening file picker...</p>';
try {
const [fileHandle] = await puter.ui.showOpenFilePicker();
resultsDiv.innerHTML = `<p>Selected file: ${fileHandle.name}. Reading content...</p>`;

const file = await fileHandle.getFile();
const arrayBuffer = await file.arrayBuffer();

resultsDiv.innerHTML = '<p>Parsing PDF...</p>';
const pdf = await pdfjsLib.getDocument({ data: arrayBuffer }).promise;

let allText = '';
for (let i = 1; i <= pdf.numPages; i++) {
const page = await pdf.getPage(i);
const textContent = await page.getTextContent();
const pageText = textContent.items.map(item => item.str).join(' ');
allText += pageText + '\\n\\n';
}

await analyzeContractText(allText);

} catch (error) {
if (error.name === 'AbortError') {
resultsDiv.innerHTML = '<p>File picker was cancelled.</p>';
} else {
console.error('Error processing file:', error);
resultsDiv.innerHTML = `<p style="color: red;">Error: ${error.message}</p>`;
}
}
});
</script>
</body>
</html>