([]);
- const { files } = useFile();
- const fileContents: { name: string; content: string }[] = filenames.map(
- (name) => ({ name, content: files[name] || "" })
- );
- const addReplOutput = useCallback(
- (command: string, output: ReplOutput[]) =>
- setReplOutputs((outs) => [...outs, { command, output }]),
- []
- );
- const addFile = useCallback(
- (filename: string) =>
- setFilenames((filenames) =>
- filenames.includes(filename) ? filenames : [...filenames, filename]
- ),
- []
- );
- const setExecResult = useCallback(
- (filename: string, output: ReplOutput[]) =>
- setExecResults((results) => {
- results[filename] = output;
- return results;
- }),
- []
- );
-
- // replOutputs: section内にあるターミナルにユーザーが入力したコマンドとその実行結果
- // fileContents: section内にあるファイルエディターの内容
- // execResults: section内にあるファイルの実行結果
- // console.log(section.title, replOutputs, fileContents, execResults);
-
return (
-
-
- {section.title}
-
-
-
+ <>
+ {section.title}
+
+ >
);
}
diff --git a/app/actions/chatActions.ts b/app/actions/chatActions.ts
index b126e93..c443ba5 100644
--- a/app/actions/chatActions.ts
+++ b/app/actions/chatActions.ts
@@ -12,7 +12,7 @@ const ChatSchema = z.object({
userQuestion: z
.string()
.min(1, { message: "メッセージを入力してください。" }),
- documentContent: z
+ splitMdContent: z
.string()
.min(1, { message: "コンテキストとなるドキュメントがありません。" }),
replOutputs: z
diff --git a/app/terminal/editor.tsx b/app/terminal/editor.tsx
index bed41ed..4ff26a8 100644
--- a/app/terminal/editor.tsx
+++ b/app/terminal/editor.tsx
@@ -22,7 +22,6 @@ const AceEditor = dynamic(
import "./editor.css";
import { useFile } from "./file";
import { useEffect } from "react";
-import { useSectionCode } from "../[docs_id]/section";
import clsx from "clsx";
import { useChangeTheme } from "../[docs_id]/themeToggle";
// snippetを有効化するにはsnippetもimportする必要がある: import "ace-builds/src-min-noconflict/snippets/python";
@@ -41,14 +40,13 @@ export function EditorComponent(props: EditorProps) {
const theme = useChangeTheme();
const { files, writeFile } = useFile();
const code = files[props.filename] || props.initContent;
- const sectionContext = useSectionCode();
- const addSectionFile = sectionContext?.addFile;
+ // const addSectionFile = sectionContext?.addFile;
useEffect(() => {
if (!files[props.filename]) {
writeFile(props.filename, props.initContent);
}
- addSectionFile?.(props.filename);
- }, [files, props.filename, props.initContent, writeFile, addSectionFile]);
+ // addSectionFile?.(props.filename);
+ }, [files, props.filename, props.initContent, writeFile]);
return (
diff --git a/app/terminal/exec.tsx b/app/terminal/exec.tsx
index 7bb2a29..461fcfd 100644
--- a/app/terminal/exec.tsx
+++ b/app/terminal/exec.tsx
@@ -8,10 +8,10 @@ import {
systemMessageColor,
useTerminal,
} from "./terminal";
-import { useSectionCode } from "../[docs_id]/section";
import { useWandbox } from "./wandbox/wandbox";
import { ReplOutput, writeOutput } from "./repl";
import { useState } from "react";
+import { useEmbed } from "../[docs_id]/embedContext";
export type ExecLang = "python" | "cpp";
@@ -34,7 +34,7 @@ export function ExecFile(props: ExecProps) {
}
},
});
- const sectionContext = useSectionCode();
+ const sectionContext = useEmbed();
const pyodide = usePyodide();
const wandbox = useWandbox();
diff --git a/app/terminal/repl.tsx b/app/terminal/repl.tsx
index 5cbda66..0bc859c 100644
--- a/app/terminal/repl.tsx
+++ b/app/terminal/repl.tsx
@@ -12,8 +12,8 @@ import {
systemMessageColor,
useTerminal,
} from "./terminal";
-import { useSectionCode } from "../[docs_id]/section";
import { Terminal } from "@xterm/xterm";
+import { useEmbed } from "../[docs_id]/embedContext";
export interface ReplOutput {
type: "stdout" | "stderr" | "error" | "return" | "trace" | "system"; // 出力の種類
@@ -58,6 +58,7 @@ export function writeOutput(
}
interface ReplComponentProps {
+ terminalId: string;
initRuntime: () => void;
runtimeInitializing: boolean;
runtimeReady: boolean;
@@ -79,10 +80,11 @@ export function ReplTerminal(props: ReplComponentProps) {
const inputBuffer = useRef([]);
const initDone = useRef(false);
- const sectionContext = useSectionCode();
+ const sectionContext = useEmbed();
const addReplOutput = sectionContext?.addReplOutput;
const {
+ terminalId,
initRuntime,
runtimeInitializing,
runtimeReady,
@@ -256,7 +258,7 @@ export function ReplTerminal(props: ReplComponentProps) {
sendCommand(command)
);
onOutput(outputs);
- addReplOutput?.(command, outputs);
+ addReplOutput?.(terminalId, command, outputs);
}
} else if (code === 127) {
// Backspace
@@ -293,6 +295,7 @@ export function ReplTerminal(props: ReplComponentProps) {
}
},
[
+ terminalId,
updateBuffer,
sendCommand,
onOutput,
From bfaf9f3e3c04048e8e50bbdcba0d60e46f200bfc Mon Sep 17 00:00:00 2001
From: na-trium-144 <100704180+na-trium-144@users.noreply.github.com>
Date: Thu, 23 Oct 2025 02:57:04 +0900
Subject: [PATCH 04/10] =?UTF-8?q?AI=E3=81=AB=E3=83=89=E3=82=AD=E3=83=A5?=
=?UTF-8?q?=E3=83=A1=E3=83=B3=E3=83=88=E5=85=A8=E4=BD=93=E3=81=A8=E3=82=BF?=
=?UTF-8?q?=E3=83=BC=E3=83=9F=E3=83=8A=E3=83=AB=E3=83=AD=E3=82=B0=E5=85=A8?=
=?UTF-8?q?=E3=81=A6=E3=82=92=E6=B8=A1=E3=81=99?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app/[docs_id]/chatForm.tsx | 4 ++
app/[docs_id]/embedContext.tsx | 15 +++--
app/[docs_id]/markdown.tsx | 33 +++++-----
app/[docs_id]/page.tsx | 6 +-
app/[docs_id]/pageContent.tsx | 2 +
app/actions/chatActions.ts | 107 ++++++++++++++++++-------------
app/terminal/python/embedded.tsx | 9 ++-
7 files changed, 109 insertions(+), 67 deletions(-)
diff --git a/app/[docs_id]/chatForm.tsx b/app/[docs_id]/chatForm.tsx
index fa86557..5cd4be8 100644
--- a/app/[docs_id]/chatForm.tsx
+++ b/app/[docs_id]/chatForm.tsx
@@ -12,6 +12,7 @@ import { useFile } from "../terminal/file";
interface ChatFormProps {
docs_id: string;
+ documentContent: string;
splitMdContent: MarkdownSection[];
sectionInView: boolean[];
onClose: () => void;
@@ -19,6 +20,7 @@ interface ChatFormProps {
export function ChatForm({
docs_id,
+ documentContent,
splitMdContent,
sectionInView,
onClose,
@@ -79,6 +81,7 @@ export function ChatForm({
const result = await askAI({
userQuestion,
+ documentContent,
splitMdContent,
sectionInView,
replOutputs,
@@ -95,6 +98,7 @@ export function ChatForm({
// updateChatHistory([userMessage, errorMessage]);
} else {
const aiMessage: Message = { sender: "ai", text: result.response };
+ console.log(aiMessage);
// updateChatHistory([userMessage, aiMessage]);
setInputValue("");
}
diff --git a/app/[docs_id]/embedContext.tsx b/app/[docs_id]/embedContext.tsx
index 7d1d5df..deeda93 100644
--- a/app/[docs_id]/embedContext.tsx
+++ b/app/[docs_id]/embedContext.tsx
@@ -35,10 +35,17 @@ export function EmbedContextProvider({ children }: { children: ReactNode }) {
);
const addReplOutput = useCallback(
(terminalId: string, command: string, output: ReplOutput[]) =>
- setReplOutputs((outs) => ({
- ...outs,
- terminalId: [...(outs[terminalId] ?? []), { command, output }],
- })),
+ setReplOutputs((outs) => {
+ outs = { ...outs };
+ if (!(terminalId in outs)) {
+ outs[terminalId] = [];
+ }
+ outs[terminalId] = [
+ ...outs[terminalId],
+ { command: command, output: output },
+ ];
+ return outs;
+ }),
[]
);
const setExecResult = useCallback(
diff --git a/app/[docs_id]/markdown.tsx b/app/[docs_id]/markdown.tsx
index ffdfd0a..49fda76 100644
--- a/app/[docs_id]/markdown.tsx
+++ b/app/[docs_id]/markdown.tsx
@@ -104,6 +104,23 @@ function CodeComponent({
);
}
+ } else if (match[2] === "-repl") {
+ // repl付きの言語指定
+ // 現状はPythonのみ対応
+ switch (match[1]) {
+ case "python":
+ return (
+
+ );
+ default:
+ console.warn(`Unsupported language for repl: ${match[1]}`);
+ break;
+ }
} else if (match[3]) {
// ファイル名指定がある場合、ファイルエディター
let aceLang: AceLang | undefined = undefined;
@@ -140,22 +157,6 @@ function CodeComponent({
/>