Skip to content

Commit

Permalink
Merge pull request #231 from oaknational/rc-2024-10-15
Browse files Browse the repository at this point in the history
build: release
  • Loading branch information
oak-machine-user authored Oct 15, 2024
2 parents 446e6db + dc747c3 commit 3aa42aa
Show file tree
Hide file tree
Showing 22 changed files with 786 additions and 226 deletions.
2 changes: 2 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
"gdrive",
"Geist",
"gleap",
"gstatic",
"Hardman",
"haroset",
"Hasura",
Expand Down Expand Up @@ -109,6 +110,7 @@
"PSED",
"PSHE",
"psql",
"pusherapp",
"ratelimit",
"Regen",
"remeda",
Expand Down
2 changes: 1 addition & 1 deletion apps/nextjs/src/app/aila/[id]/share/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export default function ShareChat({
<h1 className="text-3xl font-bold">{lessonPlan.title}</h1>
<div className="mt-10 pb-30">
<OakSmallPrimaryButton
data-testId="copy-link"
data-testid="copy-link"
onClick={() => {
navigator.clipboard.writeText(window.location.href).then(() => {
setUserHasCopiedLink(true);
Expand Down
14 changes: 8 additions & 6 deletions apps/nextjs/src/app/api/chat/errorHandling.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ import { RateLimitExceededError } from "@oakai/core/src/utils/rateLimiting/userB
import { PrismaClientWithAccelerate } from "@oakai/db";
import invariant from "tiny-invariant";

import { consumeStream } from "@/utils/testHelpers/consumeStream";
import {
consumeStream,
extractStreamMessage,
} from "@/utils/testHelpers/consumeStream";

import { handleChatException } from "./errorHandling";

Expand Down Expand Up @@ -35,7 +38,7 @@ describe("handleChatException", () => {
expect(response.status).toBe(200);

invariant(response.body instanceof ReadableStream);
const message = JSON.parse(await consumeStream(response.body));
const message = extractStreamMessage(await consumeStream(response.body));

expect(message).toEqual({
type: "error",
Expand Down Expand Up @@ -85,8 +88,7 @@ describe("handleChatException", () => {
expect(response.status).toBe(200);

const consumed = await consumeStream(response.body as ReadableStream);
expect(consumed).toMatch(/^\{/);
const message = JSON.parse(consumed);
const message = extractStreamMessage(consumed);

expect(message).toEqual({
type: "error",
Expand All @@ -112,7 +114,7 @@ describe("handleChatException", () => {

expect(response.status).toBe(200);

const message = JSON.parse(
const message = extractStreamMessage(
await consumeStream(response.body as ReadableStream),
);
expect(message).toEqual({
Expand All @@ -121,4 +123,4 @@ describe("handleChatException", () => {
});
});
});
});
});
3 changes: 2 additions & 1 deletion apps/nextjs/src/app/api/chat/protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import {
import { StreamingTextResponse } from "ai";

export function streamingJSON(message: ErrorDocument | ActionDocument) {
const errorMessage = JSON.stringify(message);
const jsonContent = JSON.stringify(message);
const errorMessage = `0:"${jsonContent.replace(/"/g, '\\"')}"`;

const errorEncoder = new TextEncoder();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
PromptDocument,
StateDocument,
TextDocument,
UnknownDocument,
parseMessageParts,
} from "@oakai/aila/src/protocol/jsonPatchProtocol";
import { isSafe } from "@oakai/core/src/utils/ailaModeration/helpers";
Expand Down Expand Up @@ -234,10 +235,14 @@ function ChatMessagePart({
action: ActionMessagePart,
moderation: ModerationMessagePart,
id: IdMessagePart,
}[part.document.type];
unknown: UnknownMessagePart,
}[part.document.type] as React.ComponentType<{
part: typeof part.document;
moderationModalHelpers: ModerationModalHelpers;
}>;

if (!PartComponent) {
console.log("Unknown part type", part.document.type, part); // eslint-disable-line no-console
console.log("Unknown part type", part.document.type, JSON.stringify(part)); // eslint-disable-line no-console
return null;
}

Expand Down Expand Up @@ -311,6 +316,11 @@ function ActionMessagePart({
return null;
}

// eslint-disable-next-line @typescript-eslint/no-unused-vars
function UnknownMessagePart({ part }: Readonly<{ part: UnknownDocument }>) {
return null;
}

function PartInspector({ part }: Readonly<{ part: MessagePart }>) {
return (
<div className="w-full bg-gray-200 px-8 py-16">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { useCallback } from "react";

import { findLast } from "remeda";

import { useLessonChat } from "@/components/ContextProviders/ChatProvider";
import { Icon } from "@/components/Icon";
import { useLessonPlanTracking } from "@/lib/analytics/lessonPlanTrackingContext";
Expand Down Expand Up @@ -61,7 +63,7 @@ const QuickActionButtons = ({ isEmptyScreen }: QuickActionButtonsProps) => {
const handleRegenerate = useCallback(() => {
trackEvent("chat:regenerate", { id: id });
const lastUserMessage =
messages.findLast((m) => m.role === "user")?.content || "";
findLast(messages, (m) => m.role === "user")?.content || "";
lessonPlanTracking.onClickRetry(lastUserMessage);
queueUserAction("regenerate");
}, [queueUserAction, lessonPlanTracking, messages, trackEvent, id]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ const ExportButtons = ({
<OakSmallSecondaryButton
element={!isStreaming ? Link : "button"}
disabled={isStreaming}
data-testId="chat-download-resources"
data-testid="chat-download-resources"
href={demo.isSharingEnabled ? `/aila/download/${id}` : "#"}
title={demo.isSharingEnabled ? undefined : "Not available"}
onClick={() => {
Expand Down
9 changes: 9 additions & 0 deletions apps/nextjs/src/lib/errors/getRootErrorCause.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export function getRootErrorCause(error: unknown) {
if (!(error instanceof Error)) {
return error;
}
if ("cause" in error && error.cause) {
return getRootErrorCause(error.cause);
}
return error;
}
30 changes: 20 additions & 10 deletions apps/nextjs/src/lib/hooks/use-enter-submit.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,33 @@
import { useRef, type RefObject } from 'react'
import { useRef, type RefObject } from "react";

export function useEnterSubmit(): {
formRef: RefObject<HTMLFormElement>
onKeyDown: (event: React.KeyboardEvent<HTMLTextAreaElement>) => void
formRef: RefObject<HTMLFormElement>;
onKeyDown: (event: React.KeyboardEvent<HTMLTextAreaElement>) => void;
} {
const formRef = useRef<HTMLFormElement>(null)
const formRef = useRef<HTMLFormElement>(null);

const handleKeyDown = (
event: React.KeyboardEvent<HTMLTextAreaElement>
event: React.KeyboardEvent<HTMLTextAreaElement>,
): void => {
if (
event.key === 'Enter' &&
event.key === "Enter" &&
!event.shiftKey &&
!event.nativeEvent.isComposing
) {
formRef.current?.requestSubmit()
event.preventDefault()
try {
if (formRef.current?.requestSubmit) {
formRef.current.requestSubmit();
} else if (formRef.current?.submit) {
formRef.current.submit();
} else {
throw new Error("Form submission not supported");
}
} catch (error) {
console.error("Failed to submit form:", error);
}
event.preventDefault();
}
}
};

return { formRef, onKeyDown: handleKeyDown }
return { formRef, onKeyDown: handleKeyDown };
}
Loading

0 comments on commit 3aa42aa

Please sign in to comment.