@krmxd/onegpt 0.2.4-beta → 0.2.5-fix-beta
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/agent.js +12 -1
- package/src/tools.js +60 -0
package/package.json
CHANGED
package/src/agent.js
CHANGED
|
@@ -112,6 +112,8 @@ const TOOL_GUIDANCE = (
|
|
|
112
112
|
"- Call tools ONLY as exact JSON: {\"name\": \"write_file\", \"arguments\": {...}}. " +
|
|
113
113
|
"NEVER invent formats like 'name_file:path' or bare '<html>' dumps - those are NOT " +
|
|
114
114
|
"tool calls, they will be ignored, and you must redo them properly.\n" +
|
|
115
|
+
"- To add files use write_file (or create_project to scaffold a starter folder). " +
|
|
116
|
+
"Never copy_path/move_path from folders you have not created yourself.\n" +
|
|
115
117
|
"- To act, output plain JSON tool calls (never shell commands in code fences):\n" +
|
|
116
118
|
'{"name": "write_file", "arguments": {"path": "widgets/gadget.py", ' +
|
|
117
119
|
'"content": "print(\'hi\')"}}\n' +
|
|
@@ -210,6 +212,14 @@ function degenerateRepeat(text, minLen = 12, maxHits = 4) {
|
|
|
210
212
|
counts.set(line, n);
|
|
211
213
|
if (n >= maxHits) return line;
|
|
212
214
|
}
|
|
215
|
+
// Single-line degeneration: models spam JSON fragments like
|
|
216
|
+
// '"name":"name":"create"...' inside ONE line - count key markers.
|
|
217
|
+
const flat = String(text || "");
|
|
218
|
+
for (const marker of ['"name"', '"arguments"', '{"name"']) {
|
|
219
|
+
let hits = 0, i = -1;
|
|
220
|
+
while ((i = flat.indexOf(marker, i + 1)) !== -1 && hits < maxHits + 1) hits++;
|
|
221
|
+
if (hits >= maxHits) return `...${marker} x${hits}`;
|
|
222
|
+
}
|
|
213
223
|
return null;
|
|
214
224
|
}
|
|
215
225
|
|
|
@@ -781,7 +791,8 @@ class Agent {
|
|
|
781
791
|
// A tool-call blob typed as plain text must not scroll into the
|
|
782
792
|
// chat as garbage - hold it back; the executor prints chips.
|
|
783
793
|
const acc = contentParts.join("");
|
|
784
|
-
|
|
794
|
+
const lead = acc.trim().toLowerCase();
|
|
795
|
+
if (!jsonHold && (((/^\s*[{"]/.test(acc) || /^json/.test(lead)) && acc.includes('"name"'))
|
|
785
796
|
|| (/^\s*```/.test(acc) && (acc.includes('"name"') || acc.includes('"arguments"'))))) {
|
|
786
797
|
jsonHold = true;
|
|
787
798
|
}
|
package/src/tools.js
CHANGED
|
@@ -71,6 +71,9 @@ const TOOL_ALIASES = {
|
|
|
71
71
|
removefile: "delete_path", remove_file: "delete_path", deletefile: "delete_path",
|
|
72
72
|
delete_file: "delete_path", deletefolder: "delete_path", delete_folder: "delete_path",
|
|
73
73
|
rmdir: "delete_path", unlink: "delete_path", trash: "delete_path",
|
|
74
|
+
createproject: "create_project", new_project: "create_project", newproject: "create_project",
|
|
75
|
+
scaffold_project: "create_project", scaffoldproject: "create_project",
|
|
76
|
+
create_app: "create_project", createapp: "create_project", build_project: "create_project",
|
|
74
77
|
// file writing
|
|
75
78
|
writefile: "write_file", filewrite: "write_file", createfile: "write_file",
|
|
76
79
|
create_file: "write_file", newfile: "write_file", new_file: "write_file",
|
|
@@ -581,6 +584,14 @@ const TOOLS = [
|
|
|
581
584
|
new ToolDef("delete_path", "Delete a file or folder (recursive)", {
|
|
582
585
|
type: "object", properties: { path: { type: "string" } }, required: ["path"],
|
|
583
586
|
}, true),
|
|
587
|
+
new ToolDef("create_project", "Scaffold a new project folder with starter files", {
|
|
588
|
+
type: "object",
|
|
589
|
+
properties: {
|
|
590
|
+
path: { type: "string" }, template: { type: "string",
|
|
591
|
+
description: "'web' (html/css/js) or 'flask' (python)" },
|
|
592
|
+
},
|
|
593
|
+
required: ["path"],
|
|
594
|
+
}, true),
|
|
584
595
|
new ToolDef("edit_file", "Replace exact text in file", {
|
|
585
596
|
type: "object",
|
|
586
597
|
properties: {
|
|
@@ -891,6 +902,55 @@ const IMPLEMENTATIONS = {
|
|
|
891
902
|
return new ToolResult(`Deleted ${kind}: ${p}`);
|
|
892
903
|
},
|
|
893
904
|
|
|
905
|
+
create_project(args) {
|
|
906
|
+
const raw = String(args.path || args.name || "").trim();
|
|
907
|
+
if (!raw) return new ToolResult("", "Empty path", false);
|
|
908
|
+
const p = path.resolve(raw.replace(/^~(?=$|\/)/, os.homedir()));
|
|
909
|
+
const template = String(args.template || "web").toLowerCase();
|
|
910
|
+
if (fs.existsSync(p) && fs.readdirSync(p).length) {
|
|
911
|
+
return new ToolResult("", `Folder not empty: ${p} - pick a new project name.`, false);
|
|
912
|
+
}
|
|
913
|
+
fs.mkdirSync(p, { recursive: true });
|
|
914
|
+
const wf = (rel, content) => {
|
|
915
|
+
const f = path.join(p, rel);
|
|
916
|
+
fs.mkdirSync(path.dirname(f), { recursive: true });
|
|
917
|
+
fs.writeFileSync(f, content, "utf-8");
|
|
918
|
+
return rel;
|
|
919
|
+
};
|
|
920
|
+
const made = [];
|
|
921
|
+
const title = path.basename(p).replace(/[-_]/g, " ");
|
|
922
|
+
if (template === "flask") {
|
|
923
|
+
made.push(wf("app.py",
|
|
924
|
+
"from flask import Flask, render_template\n\n" +
|
|
925
|
+
"app = Flask(__name__)\n\n\n" +
|
|
926
|
+
"@app.route(\"/\")\n" +
|
|
927
|
+
"def index():\n" +
|
|
928
|
+
` return render_template(\"index.html\", title=\"${title}\")\n\n\n` +
|
|
929
|
+
"if __name__ == \"__main__\":\n" +
|
|
930
|
+
" app.run(debug=True)\n"));
|
|
931
|
+
made.push(wf("requirements.txt", "flask\n"));
|
|
932
|
+
made.push(wf("templates/index.html",
|
|
933
|
+
"<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n" +
|
|
934
|
+
" <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n" +
|
|
935
|
+
` <title>${title}</title>\n</head>\n<body>\n <h1>${title}</h1>\n` +
|
|
936
|
+
" {% block content %}{% endblock %}\n</body>\n</html>\n"));
|
|
937
|
+
made.push(wf("static/style.css", "/* Styles */\nbody { font-family: system-ui; }\n"));
|
|
938
|
+
} else {
|
|
939
|
+
// web / website / static starter
|
|
940
|
+
made.push(wf("index.html",
|
|
941
|
+
"<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n" +
|
|
942
|
+
" <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n" +
|
|
943
|
+
` <title>${title}</title>\n <link rel=\"stylesheet\" href=\"styles.css\">\n` +
|
|
944
|
+
"</head>\n<body>\n <script src=\"script.js\" defer></script>\n</body>\n</html>\n"));
|
|
945
|
+
this.write_file({ path: path.join(p, "styles.css"), content: "" });
|
|
946
|
+
this.write_file({ path: path.join(p, "script.js"), content: "" });
|
|
947
|
+
made.push("styles.css (starter)", "script.js (starter)");
|
|
948
|
+
}
|
|
949
|
+
return new ToolResult(
|
|
950
|
+
`Created ${template} project '${path.basename(p)}' with: ` +
|
|
951
|
+
made.join(", ") + ". Extend these files with write_file/edit_file next.");
|
|
952
|
+
},
|
|
953
|
+
|
|
894
954
|
edit_file(args) {
|
|
895
955
|
const p = path.resolve(anchorPath(String(args.path)).replace(/^~(?=$|\/)/, os.homedir()));
|
|
896
956
|
if (!fs.existsSync(p)) return new ToolResult("", `Not found: ${p}`, false);
|