Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@
// call in `answer()`. When Freya lands, swap `answer()` for a Freya session and
// keep this handler's request/response contract unchanged. Look for FREYA-SEAM.

const { getStore } = require('@netlify/blobs');
import { getStore } from '@netlify/blobs';
import { createRequire } from 'node:module';

const require = createRequire(import.meta.url);

const CORS_HEADERS = {
'Access-Control-Allow-Origin': '*',
Expand All @@ -38,9 +41,9 @@
const MAX_MESSAGES = 12; // trim conversation history sent to the model
const MAX_CHARS = 4000; // per-message input clamp

function clientIp(event) {
const xff = event.headers['x-nf-client-connection-ip'] ||
event.headers['x-forwarded-for'] || '';
function clientIp(request, context) {
const xff = context.ip || request.headers.get('x-nf-client-connection-ip') ||
request.headers.get('x-forwarded-for') || '';
return (xff.split(',')[0] || 'unknown').trim();
}

Expand Down Expand Up @@ -237,7 +240,7 @@
apis: require('../roadmap/data/apis.json'),
};
} catch (e) {
console.log('roadmap data unavailable:', e && e.message ? e.message : e);

Check warning on line 243 in website/friggframework-api/assistant.mjs

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Prefer using an optional chain expression instead, as it's more concise and easier to read.

See more on https://sonarcloud.io/project/issues?id=friggframework_frigg&issues=AZ-Sk0pq7dtt045fiyXl&open=AZ-Sk0pq7dtt045fiyXl&pullRequest=631
ROADMAP_DATA = { adrs: [], apis: {} };
}
return ROADMAP_DATA;
Expand All @@ -259,7 +262,7 @@
messages,
data: loadRoadmapData(),
});
return (reply && reply.trim()) || "I didn't catch that. Could you rephrase?";

Check warning on line 265 in website/friggframework-api/assistant.mjs

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Prefer using an optional chain expression instead, as it's more concise and easier to read.

See more on https://sonarcloud.io/project/issues?id=friggframework_frigg&issues=AZ-Sk0pq7dtt045fiyXm&open=AZ-Sk0pq7dtt045fiyXm&pullRequest=631
}

const OFFLINE_REPLY =
Expand All @@ -268,22 +271,20 @@
"https://github.com/friggframework/frigg, and the roadmap and API directory " +
"are at /roadmap/ on this site.";

exports.handler = async function (event) {
if (event.httpMethod === 'OPTIONS') {
return { statusCode: 200, headers: CORS_HEADERS };
export default async function (request, context) {

Check warning on line 274 in website/friggframework-api/assistant.mjs

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

The async function should be named.

See more on https://sonarcloud.io/project/issues?id=friggframework_frigg&issues=AZ-Sk0pq7dtt045fiyXn&open=AZ-Sk0pq7dtt045fiyXn&pullRequest=631
if (request.method === 'OPTIONS') {
return new Response(null, { status: 200, headers: CORS_HEADERS });
}
if (event.httpMethod !== 'POST') {
return {
statusCode: 405,
headers: { ...CORS_HEADERS, 'content-type': 'application/json' },
body: JSON.stringify({ error: 'method not allowed' }),
};
if (request.method !== 'POST') {
return Response.json(
{ error: 'method not allowed' },
{ status: 405, headers: CORS_HEADERS },
);
}

const json = (status, obj) => ({
statusCode: status,
headers: { ...CORS_HEADERS, 'content-type': 'application/json' },
body: JSON.stringify(obj),
const json = (status, obj) => Response.json(obj, {
status,
headers: CORS_HEADERS,
});

// No gateway configured -> degrade gracefully, don't 500.
Expand All @@ -293,17 +294,17 @@

let payload;
try {
payload = JSON.parse(event.body || '{}');
payload = await request.json();
} catch (e) {
return json(400, { error: 'invalid JSON' });
}

const messages = sanitizeMessages(payload.messages);
if (!messages.length || messages[messages.length - 1].role !== 'user') {

Check warning on line 303 in website/friggframework-api/assistant.mjs

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Prefer `.at(…)` over `[….length - index]`.

See more on https://sonarcloud.io/project/issues?id=friggframework_frigg&issues=AZ-Sk0pq7dtt045fiyXo&open=AZ-Sk0pq7dtt045fiyXo&pullRequest=631
return json(400, { error: 'expected a non-empty messages array ending with a user turn' });
}

const rate = await checkRateLimit(clientIp(event));
const rate = await checkRateLimit(clientIp(request, context));
if (!rate.ok) {
return json(429, {
reply: "You're going a little fast for me. Give it a few seconds and try again.",
Expand All @@ -316,7 +317,7 @@
const reply = await answer(messages);
return json(200, { reply });
} catch (e) {
console.log('assistant error:', e && e.message ? e.message : e);

Check warning on line 320 in website/friggframework-api/assistant.mjs

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Prefer using an optional chain expression instead, as it's more concise and easier to read.

See more on https://sonarcloud.io/project/issues?id=friggframework_frigg&issues=AZ-Sk0pq7dtt045fiyXp&open=AZ-Sk0pq7dtt045fiyXp&pullRequest=631
return json(200, { reply: OFFLINE_REPLY, offline: true });
}
};
}
Loading
Loading