- Add `agents/reports/` to `.gitignore` to prevent generated agent report files from being tracked - Implement `_TimestampStream` class and `install_timestamps()` function in `agents/agent.py` for prefixing stdout/stderr with timestamps and elapsed time - Export `install_timestamps`, `set_write_budget`, `clear_write_budget`, and `set_shell_restricted` from `agents/base.py`; add `_RUN_LOCK`, `AGENT_ICONS` dictionary, and `WRITE_BUDGET = 20` constant - Add `report_codename()` function and `CODENAME_ADJECTIVES`/`CODENAME_ANIMALS` tuples to `agents/core/__init__.py` for generating random agent report codenames - Expand `WRITE_TOOLS` tuple in `agents/core/__init__.py` to include `replace_lines`, `insert_lines`, and `delete_lines`; remove `SWARM_TOOLS` from `payloads_for` exclusion list - Update `CLAUDE.md` and `AGENTS.md` documentation with dataset column initialization rules and new agent infrastructure details - Reorder route table in `README.md` to list `/uploads` before `/messages` and document Swagger/ReDoc/OpenAPI schema endpoints
83 lines
2.6 KiB
JavaScript
83 lines
2.6 KiB
JavaScript
// retoor <retoor@molodetz.nl>
|
|
|
|
import { CodeMirrorModes } from "./codemirrorModes.js";
|
|
|
|
class GistEditor {
|
|
constructor(textareaId, langSelectId) {
|
|
this.editor = null;
|
|
this.initialized = false;
|
|
this.textareaId = textareaId || "gist-source-editor";
|
|
this.langSelectId = langSelectId || "gist-language";
|
|
this.maxLength = 400000;
|
|
}
|
|
|
|
init() {
|
|
if (this.initialized) return;
|
|
if (typeof CodeMirror === "undefined") return;
|
|
|
|
const textarea = document.getElementById(this.textareaId);
|
|
if (!textarea) return;
|
|
this.initialized = true;
|
|
|
|
this.editor = CodeMirror.fromTextArea(textarea, {
|
|
lineNumbers: true,
|
|
mode: textarea.dataset.language || "plaintext",
|
|
theme: "monokai",
|
|
indentUnit: 4,
|
|
tabSize: 4,
|
|
lineWrapping: true,
|
|
extraKeys: {
|
|
"Ctrl-S": () => {
|
|
const form = textarea.closest("form");
|
|
if (form) {
|
|
this.editor.save();
|
|
form.submit();
|
|
}
|
|
},
|
|
},
|
|
});
|
|
|
|
this.editor.setSize(null, 400);
|
|
|
|
const langSelect = document.getElementById(this.langSelectId);
|
|
if (langSelect) {
|
|
langSelect.addEventListener("change", () => {
|
|
const mode = langSelect.value;
|
|
this.editor.setOption("mode", CodeMirrorModes.LANGUAGE_MODES[mode] || mode);
|
|
});
|
|
}
|
|
|
|
const form = textarea.closest("form");
|
|
if (form) {
|
|
form.addEventListener("submit", (event) => {
|
|
this.editor.save();
|
|
if (textarea.value.length > this.maxLength) {
|
|
event.preventDefault();
|
|
this.showLengthError(textarea);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
showLengthError(textarea) {
|
|
const field = textarea.closest(".auth-field");
|
|
const target = field || textarea.parentElement;
|
|
let message = target.querySelector(".gist-length-error");
|
|
if (!message) {
|
|
message = document.createElement("div");
|
|
message.className = "gist-length-error";
|
|
target.appendChild(message);
|
|
}
|
|
const length = textarea.value.length.toLocaleString();
|
|
const limit = this.maxLength.toLocaleString();
|
|
message.textContent = `Source code is ${length} characters; the maximum is ${limit}.`;
|
|
}
|
|
|
|
refresh() {
|
|
if (this.editor) {
|
|
setTimeout(() => this.editor.refresh(), 100);
|
|
}
|
|
}
|
|
}
|
|
window.GistEditor = GistEditor;
|