Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
cc8d6a3
Changed the Email Writer to support several forms that get submitted …
AndreiPauseAI May 21, 2025
f4c3bff
Merge branch 'main' of https://github.com/AndreiPauseAI/email-builder
AndreiPauseAI May 21, 2025
809be88
Merge branch 'PauseAI:main' into main
AndreiPauseAI Jun 4, 2025
73c5924
Fixed API to now allow tool use.
AndreiPauseAI Jun 4, 2025
11dd481
Merge branch 'PauseAI:main' into main
AndreiPauseAI Jun 16, 2025
9275255
Added fields to the Email Writer for autofilling responses.
AndreiPauseAI Jun 16, 2025
8bd2487
Small additional changes to the write api and page, mostly in regards…
AndreiPauseAI Jun 16, 2025
df2b1c3
Updated the functionality of the email writer. Aside from input token…
AndreiPauseAI Jun 18, 2025
faff810
Merge branch 'PauseAI:main' into main
AndreiPauseAI Jun 18, 2025
8a73a99
Fixed minor pnpm check errors in src/routes/write and src/routes/api/…
AndreiPauseAI Jun 19, 2025
4753ded
Merge branch 'PauseAI:main' into main
AndreiPauseAI Jun 21, 2025
176d940
Merge branch 'PauseAI:main' into main
AndreiPauseAI Jun 23, 2025
aaa9c99
Incomplete: Split api/write/+server.ts in twain.
AndreiPauseAI Jun 23, 2025
f74583b
Merge branch 'main' of https://github.com/AndreiPauseAI/email-builder
AndreiPauseAI Jun 23, 2025
56e9364
Went back to the last locally working version.
AndreiPauseAI Jun 23, 2025
3c1e719
Split write/+server.ts in twain.
AndreiPauseAI Jun 23, 2025
ccf0592
Added src/lib/storage.ts to better handle the write storage api.
AndreiPauseAI Jun 23, 2025
ae4d343
Merge branch 'PauseAI:main' into main
AndreiPauseAI Jun 23, 2025
70c9f7a
Moved storage.ts and process-step-background to fulfill netlify requi…
AndreiPauseAI Jun 23, 2025
515027d
Merge branch 'PauseAI:main' into main
AndreiPauseAI Jun 23, 2025
4959619
Changed every api/write function to a netlify function in /netlify/fu…
AndreiPauseAI Jun 23, 2025
0f4dd29
remove src/routes/api/write/status.ts
AndreiPauseAI Jun 23, 2025
c3f1585
Added @netlify/blobs as a runtime dependency to package.json.
AndreiPauseAI Jun 23, 2025
898580c
Fixed pnpm-lock.yaml and package.json incorrect @netlify/blobs version
AndreiPauseAI Jun 23, 2025
3d21b6c
Fixed outdated imports from when the api files were in src/routes/api…
AndreiPauseAI Jun 23, 2025
92a140e
Merge branch 'PauseAI:main' into main
AndreiPauseAI Jun 24, 2025
8562d41
Merge branch 'PauseAI:main' into locally-working-snapshot
AndreiPauseAI Jun 24, 2025
ca64353
Merge pull request #1 from AndreiPauseAI/locally-working-snapshot
AndreiPauseAI Jun 24, 2025
38a9ded
Merge branch 'PauseAI:main' into main
AndreiPauseAI Jun 26, 2025
e42a378
Merge branch 'PauseAI:main' into main
AndreiPauseAI Jun 27, 2025
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
674 changes: 674 additions & 0 deletions netlify/functions/process-step-background.ts

Large diffs are not rendered by default.

127 changes: 127 additions & 0 deletions netlify/functions/status.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
// SVELTEKIT SUBSTITUTE: Removed SvelteKit imports and replaced with Netlify Function structure
// SVELTEKIT SUBSTITUTE: Changed from '@sveltejs/kit' to standard Response objects
// SVELTEKIT SUBSTITUTE: Changed import paths to netlify/functions

import { JobStorage } from './storage'
import { prepareResponse } from './write'

// SVELTEKIT SUBSTITUTE: Converted to Netlify Function handler
export const handler = async (event: any, context: any) => {
// SVELTEKIT SUBSTITUTE: Handle CORS for browser requests
const headers = {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Headers': 'Content-Type',
'Access-Control-Allow-Methods': 'GET, POST, OPTIONS'
}

// Handle preflight requests
if (event.httpMethod === 'OPTIONS') {
return {
statusCode: 200,
headers,
body: ''
}
}

// Handle GET requests
if (event.httpMethod === 'GET') {
// SVELTEKIT SUBSTITUTE: Parse query parameters from event instead of url.searchParams
const jobId = event.queryStringParameters?.jobId

if (!jobId) {
return {
statusCode: 400,
headers,
body: JSON.stringify({ error: 'Job ID is required' })
}
}

try {
const jobData = await JobStorage.getJob(jobId)

if (!jobData) {
return {
statusCode: 404,
headers,
body: JSON.stringify({ error: 'Job not found' })
}
}

// Prepare response using your existing function
const response = prepareResponse(jobData.writeState)

return {
statusCode: 200,
headers,
body: JSON.stringify({
...response,
jobId,
status: jobData.status,
error: jobData.error,
createdAt: jobData.createdAt,
completedAt: jobData.completedAt
})
}
} catch (error) {
console.error('Error checking job status:', error)
return {
statusCode: 500,
headers,
body: JSON.stringify({ error: 'Internal server error' })
}
}
}

// Handle POST requests (for compatibility)
if (event.httpMethod === 'POST') {
try {
const { jobId } = JSON.parse(event.body || '{}')

if (!jobId) {
return {
statusCode: 400,
headers,
body: JSON.stringify({ error: 'Job ID is required' })
}
}

const jobData = await JobStorage.getJob(jobId)

if (!jobData) {
return {
statusCode: 404,
headers,
body: JSON.stringify({ error: 'Job not found' })
}
}

const response = prepareResponse(jobData.writeState)

return {
statusCode: 200,
headers,
body: JSON.stringify({
...response,
jobId,
status: jobData.status,
error: jobData.error
})
}
} catch (error) {
console.error('Error checking job status:', error)
return {
statusCode: 500,
headers,
body: JSON.stringify({ error: 'Internal server error' })
}
}
}

// Handle unsupported methods
return {
statusCode: 405,
headers,
body: JSON.stringify({ error: 'Method not allowed' })
}
}
111 changes: 111 additions & 0 deletions netlify/functions/storage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
// SVELTEKIT SUBSTITUTE: This file already uses Netlify Blobs correctly, minimal changes needed
// SVELTEKIT SUBSTITUTE: Fixed initialization to properly handle Netlify Functions environment

let jobStore: any = null

async function getJobStore() {
if (!jobStore) {
const { getStore } = await import('@netlify/blobs')
jobStore = getStore('email-jobs')
}
return jobStore
}

// Storage interface functions
export const JobStorage = {
// Create new job entry
async createJob(jobId: string, initialWriteState: any) {
const store = await getJobStore() // SVELTEKIT SUBSTITUTE: Ensure store is initialized
const jobData = {
jobId,
status: 'pending',
writeState: initialWriteState,
createdAt: new Date().toISOString(),
error: null,
completedAt: null
}

await store.set(jobId, JSON.stringify(jobData))
return jobData
},

// Get job by ID
async getJob(jobId: string) {
try {
const store = await getJobStore() // SVELTEKIT SUBSTITUTE: Ensure store is initialized
const data = await store.get(jobId)
if (!data) return null
return JSON.parse(data)
} catch (error) {
console.error('Error retrieving job:', error)
return null
}
},

// Update job status
async updateJobStatus(jobId: string, status: string, error: string | null = null) {
const jobData = await this.getJob(jobId)
if (!jobData) throw new Error(`Job ${jobId} not found`)

jobData.status = status
jobData.error = error

if (status === 'completed' || status === 'failed') {
jobData.completedAt = new Date().toISOString()
}

const store = await getJobStore() // SVELTEKIT SUBSTITUTE: Ensure store is initialized
await store.set(jobId, JSON.stringify(jobData))
return jobData
},

// Update WriteState for job
async updateWriteState(jobId: string, newWriteState: any) {
const jobData = await this.getJob(jobId)
if (!jobData) throw new Error(`Job ${jobId} not found`)

jobData.writeState = newWriteState
jobData.status = 'processing'

const store = await getJobStore() // SVELTEKIT SUBSTITUTE: Ensure store is initialized
await store.set(jobId, JSON.stringify(jobData))
return jobData
},

// Complete job with final results
async completeJob(jobId: string, finalWriteState: any) {
const jobData = await this.getJob(jobId)
if (!jobData) throw new Error(`Job ${jobId} not found`)

jobData.writeState = finalWriteState
jobData.status = 'completed'
jobData.completedAt = new Date().toISOString()

const store = await getJobStore() // SVELTEKIT SUBSTITUTE: Ensure store is initialized
await store.set(jobId, JSON.stringify(jobData))
return jobData
},

// Mark job as failed
async failJob(jobId: string, errorMessage: string) {
return await this.updateJobStatus(jobId, 'failed', errorMessage)
},

// Delete job (cleanup)
async deleteJob(jobId: string) {
const store = await getJobStore() // SVELTEKIT SUBSTITUTE: Ensure store is initialized
await store.delete(jobId)
},

// List all jobs (for debugging/admin)
async listJobs() {
const store = await getJobStore() // SVELTEKIT SUBSTITUTE: Ensure store is initialized
const { blobs } = await store.list()
return blobs.map((blob: any) => blob.key)
}
}

// Utility function to generate unique job IDs
export function generateJobId(): string {
return `job_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
}
Loading