@inetafrica/open-claudia 1.8.1 → 1.9.1
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/bot-agent.js +1 -5
- package/bot.js +5 -9
- package/package.json +1 -1
- package/web.js +53 -2
package/bot-agent.js
CHANGED
|
@@ -830,11 +830,7 @@ async function runClaude(prompt, cwd, replyToMsgId, opts = {}) {
|
|
|
830
830
|
const chunks = splitMessage(finalText);
|
|
831
831
|
const firstChunk = chunks[0];
|
|
832
832
|
|
|
833
|
-
|
|
834
|
-
firstChunk.length < 4000 && chunks.length === 1 &&
|
|
835
|
-
lastUpdate.includes(firstChunk.slice(0, 200));
|
|
836
|
-
|
|
837
|
-
if (progressAlreadyHasFinal) {
|
|
833
|
+
if (statusMessageId && chunks.length === 1) {
|
|
838
834
|
await editMessage(statusMessageId, firstChunk);
|
|
839
835
|
} else {
|
|
840
836
|
const sent = await send(firstChunk, { replyTo: replyToMsgId });
|
package/bot.js
CHANGED
|
@@ -862,15 +862,11 @@ async function runClaude(prompt, cwd, replyToMsgId, opts = {}) {
|
|
|
862
862
|
const chunks = splitMessage(finalText);
|
|
863
863
|
const firstChunk = chunks[0];
|
|
864
864
|
|
|
865
|
-
// If
|
|
866
|
-
//
|
|
867
|
-
// or multi-chunk
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
lastUpdate.includes(firstChunk.slice(0, 200));
|
|
871
|
-
|
|
872
|
-
if (progressAlreadyHasFinal) {
|
|
873
|
-
// Edit the progress message to show clean final text (remove tool steps header)
|
|
865
|
+
// If there's already a progress message showing, edit it to the final text
|
|
866
|
+
// instead of sending a duplicate. Only send a NEW message if there was no
|
|
867
|
+
// progress message or the response is multi-chunk (too long for one edit).
|
|
868
|
+
if (statusMessageId && chunks.length === 1) {
|
|
869
|
+
// Edit progress message to clean final text
|
|
874
870
|
await editMessage(statusMessageId, firstChunk);
|
|
875
871
|
} else {
|
|
876
872
|
// Send final result as a new message (triggers notification)
|
package/package.json
CHANGED
package/web.js
CHANGED
|
@@ -30,8 +30,24 @@ function getPassword() {
|
|
|
30
30
|
return initial;
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
+
const PASSWORD_CHANGED_FILE = path.join(CONFIG_DIR, ".password-changed");
|
|
34
|
+
|
|
35
|
+
function isPasswordChanged() {
|
|
36
|
+
return fs.existsSync(PASSWORD_CHANGED_FILE);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function validatePasswordComplexity(pw) {
|
|
40
|
+
if (pw.length < 12) return "Password must be at least 12 characters";
|
|
41
|
+
if (!/[A-Z]/.test(pw)) return "Must contain at least one uppercase letter";
|
|
42
|
+
if (!/[a-z]/.test(pw)) return "Must contain at least one lowercase letter";
|
|
43
|
+
if (!/[0-9]/.test(pw)) return "Must contain at least one number";
|
|
44
|
+
if (!/[^A-Za-z0-9]/.test(pw)) return "Must contain at least one symbol (!@#$%^&*)";
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
|
|
33
48
|
function setPassword(newPassword) {
|
|
34
49
|
fs.writeFileSync(WEB_PASSWORD_FILE, newPassword);
|
|
50
|
+
fs.writeFileSync(PASSWORD_CHANGED_FILE, new Date().toISOString());
|
|
35
51
|
}
|
|
36
52
|
|
|
37
53
|
function checkAuth(req) {
|
|
@@ -122,7 +138,7 @@ async function handleAPI(req, res, body) {
|
|
|
122
138
|
"Content-Type": "application/json",
|
|
123
139
|
"Set-Cookie": `oc_session=${authToken()}; Path=/; HttpOnly; SameSite=Strict; Max-Age=86400`,
|
|
124
140
|
});
|
|
125
|
-
return res.end(JSON.stringify({ ok: true }));
|
|
141
|
+
return res.end(JSON.stringify({ ok: true, mustChangePassword: !isPasswordChanged() }));
|
|
126
142
|
}
|
|
127
143
|
res.writeHead(401, { "Content-Type": "application/json" });
|
|
128
144
|
return res.end(JSON.stringify({ ok: false, error: "Wrong password" }));
|
|
@@ -309,6 +325,11 @@ async function handleAPI(req, res, body) {
|
|
|
309
325
|
res.writeHead(400, { "Content-Type": "application/json" });
|
|
310
326
|
return res.end(JSON.stringify({ error: "Wrong current password" }));
|
|
311
327
|
}
|
|
328
|
+
const complexityError = validatePasswordComplexity(newPassword);
|
|
329
|
+
if (complexityError) {
|
|
330
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
331
|
+
return res.end(JSON.stringify({ error: complexityError }));
|
|
332
|
+
}
|
|
312
333
|
setPassword(newPassword);
|
|
313
334
|
res.writeHead(200, {
|
|
314
335
|
"Content-Type": "application/json",
|
|
@@ -409,10 +430,40 @@ function showLogin() {
|
|
|
409
430
|
async function doLogin() {
|
|
410
431
|
const pw = $("#pw").value;
|
|
411
432
|
const r = await api("/api/login", { method: "POST", body: { password: pw } });
|
|
412
|
-
if (r?.ok)
|
|
433
|
+
if (r?.ok && r.mustChangePassword) showForceChangePassword(pw);
|
|
434
|
+
else if (r?.ok) init();
|
|
413
435
|
else $("#login-msg").innerHTML = '<div class="msg err">Wrong password</div>';
|
|
414
436
|
}
|
|
415
437
|
|
|
438
|
+
function showForceChangePassword(currentPw) {
|
|
439
|
+
$("#app").innerHTML = \`
|
|
440
|
+
<div class="login-page"><div class="login-box">
|
|
441
|
+
<h1>Change Password</h1>
|
|
442
|
+
<p class="subtitle">You must set a secure password before continuing</p>
|
|
443
|
+
<div id="change-msg"></div>
|
|
444
|
+
<div class="card">
|
|
445
|
+
<div class="form-group">
|
|
446
|
+
<input type="password" id="new-pw-1" placeholder="New password">
|
|
447
|
+
</div>
|
|
448
|
+
<div class="form-group">
|
|
449
|
+
<input type="password" id="new-pw-2" placeholder="Confirm password" onkeydown="if(event.key==='Enter')doForceChange()">
|
|
450
|
+
</div>
|
|
451
|
+
<p style="font-size:11px;color:#888;margin:8px 0">Min 12 chars, uppercase, lowercase, number, and symbol</p>
|
|
452
|
+
<button onclick="doForceChange()" style="width:100%">Set Password</button>
|
|
453
|
+
</div>
|
|
454
|
+
</div></div>\`;
|
|
455
|
+
window._forceChangePw = currentPw;
|
|
456
|
+
setTimeout(() => $("#new-pw-1")?.focus(), 100);
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
async function doForceChange() {
|
|
460
|
+
const p1 = $("#new-pw-1").value, p2 = $("#new-pw-2").value;
|
|
461
|
+
if (p1 !== p2) { $("#change-msg").innerHTML = '<div class="msg err">Passwords do not match</div>'; return; }
|
|
462
|
+
const r = await api("/api/password", { method: "POST", body: { current: window._forceChangePw, newPassword: p1 } });
|
|
463
|
+
if (r?.ok) { delete window._forceChangePw; init(); }
|
|
464
|
+
else $("#change-msg").innerHTML = '<div class="msg err">' + (r?.error || "Failed") + '</div>';
|
|
465
|
+
}
|
|
466
|
+
|
|
416
467
|
function render() {
|
|
417
468
|
const tabs = [
|
|
418
469
|
{ id: "dashboard", label: "Dashboard" },
|