Browse the file manager ("Dateien") as a filesystem
Many teachers never use topics or boards; their material sits in the course's file area, and the tools answered "0 files" for courses holding dozens of worksheets — 21 of 26 courses on the live account. Persönliche, Kurs-, Team- and Geteilte Dateien live in the legacy file store, not in files-storage, and its service is not in the public ingress. The only way in is the legacy client: HTML listings, and GET /files/signedurl for a pre-signed download. core/legacy-files.ts turns that into one path tree — /my, /courses/<course>, /teams/<team>, /shared — resolving names that contain "/", ids anywhere in a path, and wrong or ambiguous names with a message saying what is there. A listing that does not parse throws; it never reads as an empty folder. Some of the legacy client's GET routes write (GET /files/share/ mints a share token), so getFileManagerPage allows only the listing routes, by pattern. Signed URLs are fetched with no credentials and must be https. - MCP: fs_list, fs_tree, fs_find and fs_read; get_course lists course files. - CLI: schulcloud fs ls, tree, find and get, recursive and resumable. - API: /api/fs/list, tree, find and file. - Index: the crawl walks the file manager (INDEX_FILE_MANAGER, on by default), so search covers the text inside those files and sync mirrors them under <course>/Kurs-Dateien. The local instance gains a fixture for all four areas. It needed a loopback, so signed URLs open from the host, and a pre-created bucket, since MinIO does not implement PutBucketCors. 135 tests. Smoke 55/55 live; 57/57 and 55/55 on the local instance. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -4,6 +4,7 @@ import { ServerContext } from '../context.ts';
|
||||
import type { Services } from '../services.ts';
|
||||
import { registerContentTools } from './tools/content.ts';
|
||||
import { registerFileTools } from './tools/files.ts';
|
||||
import { registerFilesystemTools } from './tools/filesystem.ts';
|
||||
import { registerOverviewTools } from './tools/overview.ts';
|
||||
import { registerRawTool } from './tools/raw.ts';
|
||||
import { registerIndexTools } from './tools/index-tools.ts';
|
||||
@@ -26,6 +27,11 @@ How the content is organised, and the usual path through it:
|
||||
- **Tasks** ("Aufgaben") — homework. list_tasks across all courses, get_task for one.
|
||||
- **Files** hang off boards, lessons and tasks. Every listing shows file ids; download_file fetches one and
|
||||
extracts its text (PDF, Word, Excel, PowerPoint, OpenDocument) or returns an image inline.
|
||||
- **The file manager ("Dateien")** is a separate store with a real folder tree, browsed with the fs_* tools:
|
||||
/my (Persönliche Dateien), /courses/<course> (Kurs-Dateien), /teams/<team> (Team-Dateien) and /shared
|
||||
(Geteilte Dateien). **Many teachers put their material only here**, so when a course page looks empty or the
|
||||
worksheets are not on its boards, look in /courses/<course name>. fs_list and fs_tree browse, fs_find finds by
|
||||
name, fs_read opens a file. list_files and download_file do not see these files.
|
||||
- **Submissions** ("Abgaben") — what the user handed in. get_task shows that task's submission: the files,
|
||||
the graded flag, the grade, what the user wrote, and the teacher's written feedback. A grade is a
|
||||
percentage (0-100) or absent — there is no textual grade — and teachers often grade with the written
|
||||
@@ -51,6 +57,7 @@ export function createServer(config: Config, services?: Services): { server: Mcp
|
||||
registerContentTools(server, context);
|
||||
registerRoomTools(server, context);
|
||||
registerFileTools(server, context);
|
||||
registerFilesystemTools(server, context);
|
||||
registerSearchTool(server, context);
|
||||
registerSubmissionTools(server, context);
|
||||
registerIndexTools(server, context);
|
||||
|
||||
Reference in New Issue
Block a user