-
Notifications
You must be signed in to change notification settings - Fork 0
Release 1.0.4 responsiveness fixes #85
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -152,7 +152,8 @@ install -o root -g root -m 0755 "$APP_SOURCE/scripts/1helm-oci-runtime" "$HELPER | |
|
|
||
| TEMP_ROOT="$(mktemp -d)" | ||
| trap 'rm -rf -- "$TEMP_ROOT"' EXIT | ||
| printf '%s ALL=(root) NOPASSWD: %s *\n' "$SERVICE_USER" "$HELPER_PATH" >"$TEMP_ROOT/sudoers" | ||
| printf 'Defaults:%s !mail_badpass, !mail_no_user\n%s ALL=(root) NOPASSWD: %s *\n' \ | ||
| "$SERVICE_USER" "$SERVICE_USER" "$HELPER_PATH" >"$TEMP_ROOT/sudoers" | ||
|
Comment on lines
+155
to
+156
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -eu
printf '%s\n' '--- installer context ---'
sed -n '130,175p' site/public/install-oci-runtime.sh
printf '%s\n' '--- regression test context ---'
sed -n '300,345p' test/site.mjs
printf '%s\n' '--- changelog context ---'
sed -n '15,32p' CHANGELOG.md
printf '%s\n' '--- related sudoers/mail references ---'
rg -n --glob '!node_modules' 'mail_no_(user|perms|badpass)|sudoers|TEMP_ROOT/sudoers|denied' site/public/install-oci-runtime.sh test/site.mjs CHANGELOG.mdRepository: gitcommit90/1Helm Length of output: 11791 🌐 Web query:
💡 Result: In the sudoers configuration file, mail_no_perms, mail_no_user, and related mail flags are Boolean Defaults options that control whether administrative mail is sent when a user attempts to use sudo under specific conditions [1][2]. 1. mail_no_perms: When set, this flag causes sudo to send mail to the mailto user if the invoking user is permitted to use sudo, but the specific command they are attempting to execute is not listed in their sudoers entry or is explicitly denied [1][2]. This flag is off by default [1][2]. 2. mail_no_user: When set, this flag causes sudo to send mail to the mailto user if the invoking user is not present in the sudoers file at all [1][2]. This flag is on by default [1][2]. Defaults Settings and User-Specific Configuration These flags are defined using the Defaults syntax within the /etc/sudoers file [3]. Defaults entries can be applied globally or restricted to specific users, hosts, or runas users [4][3]. When applying these settings to specific users, the syntax follows the order: Defaults:user_name parameter1, parameter2 Example: To disable mail notifications for a specific user (e.g., 'john'), you could add a user-specific Defaults entry: Defaults:john!mail_no_user,!mail_no_perms Important implementation notes: - Parsing Order: Defaults settings are parsed in the order: global, host, user, runas, and then command-specific defaults [4][3]. If multiple settings of the same type exist, the last matching setting is applied [4][3]. - Overriding: Boolean flags can be enabled by simply listing the name (e.g., mail_no_perms) or disabled by prefixing with an exclamation mark (e.g.,!mail_no_perms) [2]. - Controlling Mail: The destination for these notifications is configured via the mailto Defaults entry, which defaults to root [5][6]. Additionally, the NOMAIL tag can be used on a per-command basis to override these global or user-specific mail settings for specific command executions [5][7]. Citations:
🏁 Script executed: #!/bin/bash
set -eu
python3 - <<'PY'
from pathlib import Path
import re
installer = Path("site/public/install-oci-runtime.sh").read_text()
test = Path("test/site.mjs").read_text()
changelog = Path("CHANGELOG.md").read_text()
rule = re.search(
r"printf 'Defaults:%s ([^\\n]+)\\n%s ALL=\\(root\\) NOPASSWD: %s \\*\\n'",
installer,
)
assert rule, "generated sudoers rule not found"
defaults, principal, command = rule.group(1), "%s ALL=(root)", "*"
print("generated Defaults options:", defaults)
print("has !mail_no_user:", "!mail_no_user" in defaults)
print("has !mail_no_perms:", "!mail_no_perms" in defaults)
print("service-user rule grants only helper path with arbitrary arguments:", "NOPASSWD: %s *" in installer)
print("test asserts !mail_no_perms:", "!mail_no_perms" in test)
print("test exercises denied-command path:", bool(re.search(r"denied|not allowed|sudo.*(?:false|cat|sh|id)", test, re.I)))
print("changelog claim present:", "Denied service-user `sudo` calls no longer start mail delivery processes" in changelog)
PY
if command -v man >/dev/null 2>&1; then
man sudoers 2>/dev/null | col -b 2>/dev/null | grep -A8 -B3 -E 'mail_no_(perms|user)' || true
else
echo "local sudoers man page unavailable"
fiRepository: gitcommit90/1Helm Length of output: 278 🏁 Script executed: #!/bin/bash
set -eu
python3 - <<'PY'
from pathlib import Path
import re
installer = Path("site/public/install-oci-runtime.sh").read_text()
test = Path("test/site.mjs").read_text()
changelog = Path("CHANGELOG.md").read_text()
defaults_line = next(
line for line in installer.splitlines()
if "Defaults:%s" in line and "mail_badpass" in line
)
assert "!mail_no_user" in defaults_line
print("defaults line:", defaults_line.strip())
print("has !mail_no_user:", "!mail_no_user" in defaults_line)
print("has !mail_no_perms:", "!mail_no_perms" in defaults_line)
rule_lines = installer.splitlines()
rule_index = next(i for i, line in enumerate(rule_lines) if "ALL=(root)" in line)
rule = "\n".join(rule_lines[rule_index:rule_index + 1])
print("service-user rule:", rule.strip())
print("explicit helper-only command rule:", "NOPASSWD:" in rule and "HELPER_PATH" in rule)
assert "!mail_no_perms" not in test
print("test asserts !mail_no_perms:", "!mail_no_perms" in test)
denied_patterns = re.compile(
r"(denied|not allowed|permission denied|mail_no_perms|sudo.*(?:false|cat|sh|id))",
re.I,
)
print("test contains denied-command coverage:", bool(denied_patterns.search(test)))
print(
"changelog claim present:",
"Denied service-user `sudo` calls no longer start mail delivery processes" in changelog,
)
PYRepository: gitcommit90/1Helm Length of output: 557 Explicitly disable mail for denied service-user commands.
📍 Affects 2 files
🤖 Prompt for AI Agents |
||
| visudo -cf "$TEMP_ROOT/sudoers" >/dev/null | ||
| install -o root -g root -m 0440 "$TEMP_ROOT/sudoers" "$SUDOERS_PATH" | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -79,8 +79,8 @@ const OCI_HELPER_CANDIDATES = [ | |
| ].filter(Boolean) as string[]; | ||
| const COMMAND_TIMEOUT_MS = Math.max(5_000, Number(process.env.HELM_MACHINE_COMMAND_TIMEOUT_MS || 120_000)); | ||
| const IDLE_AFTER_MS = Math.max(60_000, Number(process.env.HELM_MACHINE_IDLE_MS || 15 * 60_000)); | ||
| const RECONCILE_EVERY_MS = Math.max(15_000, Number(process.env.HELM_FLEET_INTERVAL_MS || 60_000)); | ||
| const INITIAL_RECONCILE_MS = Math.max(25, Number(process.env.HELM_FLEET_INITIAL_MS || 2_000)); | ||
| const RECONCILE_EVERY_MS = Math.max(15_000, Number(process.env.HELM_FLEET_INTERVAL_MS || 5 * 60_000)); | ||
| const INITIAL_RECONCILE_MS = Math.max(25, Number(process.env.HELM_FLEET_INITIAL_MS || 30_000)); | ||
|
Comment on lines
+82
to
+83
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -eu
printf '%s\n' '--- relevant source ---'
sed -n '60,100p' src/server/channel-computers.ts
sed -n '1625,1695p' src/server/channel-computers.ts
printf '%s\n' '--- constant usages ---'
rg -n -C 3 'RECONCILE_EVERY_MS|INITIAL_RECONCILE_MS|HELM_FLEET_INTERVAL_MS|HELM_FLEET_INITIAL_MS|setInterval|setTimeout' src/server/channel-computers.ts
printf '%s\n' '--- related tests ---'
rg -n -C 2 'HELM_FLEET_INTERVAL_MS|HELM_FLEET_INITIAL_MS|reconcil|channel-computers' --glob '*test*' --glob '*spec*' .Repository: gitcommit90/1Helm Length of output: 9889 🏁 Script executed: #!/bin/bash
set -eu
node - <<'JS'
const delays = [NaN, Infinity, -Infinity, 2_147_483_647, 2_147_483_648, 1e15];
for (const delay of delays) {
const timeout = setTimeout(() => {}, delay);
const interval = setInterval(() => {}, delay);
console.log(JSON.stringify({
delay,
timeout: { _idleTimeout: timeout._idleTimeout },
interval: { _idleTimeout: interval._idleTimeout },
}));
clearTimeout(timeout);
clearInterval(interval);
}
JSRepository: gitcommit90/1Helm Length of output: 1605 🏁 Script executed: #!/bin/bash
set -eu
printf '%s\n' '--- reconciliation workload ---'
rg -n -B 12 -A 45 'async function reconcileOne|function reconcileOne|reconcileOne\\(' src/server/channel-computers.ts
printf '%s\n' '--- test setup and environment handling ---'
sed -n '1,180p' test/channel-computers.mjs
rg -n -C 3 'process\\.env|import\\(|channel-computers' test/channel-computers.mjs test/channel-computers-isolated-backends.mjsRepository: gitcommit90/1Helm Length of output: 312 🏁 Script executed: #!/bin/bash
set -eu
printf '%s\n' '--- reconciliation workload ---'
rg -n -F -B 12 -A 45 'reconcileOne' src/server/channel-computers.ts
printf '%s\n' '--- test setup and environment handling ---'
sed -n '1,180p' test/channel-computers.mjs
rg -n -C 3 'process\.env|import\(|channel-computers' test/channel-computers.mjs test/channel-computers-isolated-backends.mjsRepository: gitcommit90/1Helm Length of output: 28045 Validate fleet timer overrides before starting reconciliation.
🤖 Prompt for AI Agents |
||
| const UPDATE_EVERY_MS = Math.max(24 * 60 * 60_000, Number(process.env.HELM_MACHINE_UPDATE_MS || 7 * 24 * 60 * 60_000)); | ||
| const UPDATE_RETRY_MS = Math.max(60 * 60_000, Number(process.env.HELM_MACHINE_UPDATE_RETRY_MS || 6 * 60 * 60_000)); | ||
| const MAX_WORKSPACE_SYNC_BYTES = Math.max(64 * 1024 ** 2, Number(process.env.HELM_WORKSPACE_SYNC_MAX_BYTES || 2 * 1024 ** 3)); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| type Execute = (sql: string, ...params: unknown[]) => unknown; | ||
|
|
||
| /** Remove legacy recursive file indexes without touching uploads or attachments. */ | ||
| export function cleanupLegacyWorkspaceArtifacts(run: Execute): void { | ||
| run(`DELETE FROM artifacts | ||
| WHERE kind='file' | ||
| AND NOT EXISTS ( | ||
| SELECT 1 FROM attachments at | ||
| JOIN messages m ON m.id=at.message_id | ||
| WHERE m.channel_id=artifacts.channel_id | ||
| AND at.workspace_path=artifacts.path | ||
| )`); | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -8,7 +8,7 @@ import { platform } from "node:os"; | |||||||||||||
| import { WebSocketServer, type WebSocket } from "ws"; | ||||||||||||||
| import { applyMobileCors, body, clearRateLimit, jbody, json, MIME, rateLimited, requestAddress, SECURITY_HEADERS, UPLOAD_BODY_LIMIT } from "./http.ts"; | ||||||||||||||
| import { db, isMainChannel, normalizeWorkspaceName, q, q1, run, now, hashPassword, verifyPassword, newToken, seed, DATA_DIR, UPLOAD_DIR, type Row } from "./db.ts"; | ||||||||||||||
| import { createMessage, deleteMessage, serializeMessage, setModelPref, setModelPolicy, resolvedModelPolicy, botView, providerView, botEndpoint, botsInChannel, botIsInChannel, addBotToChannel, findMentionedBots } from "./store.ts"; | ||||||||||||||
| import { createMessage, deleteMessage, serializeMessage, setModelPref, setModelPolicy, resolvedModelPolicy, botView, providerView, botEndpoint, botsInChannel, botIsInChannel, addBotToChannel, findMentionedBots, queueLastRead, shutdownReadStateWorker } from "./store.ts"; | ||||||||||||||
| import { computerRowView, fetchModels } from "./computer.ts"; | ||||||||||||||
| import { cancelChannelTurns, resumeQueuedAgentTurns, runBot, stopThreadTurn } from "./bots.ts"; | ||||||||||||||
| import { register, unregister, broadcastToChannel, broadcastAll, broadcastAdmins, sendToUsers } from "./events.ts"; | ||||||||||||||
|
|
@@ -35,6 +35,7 @@ import { | |||||||||||||
| listChannelNotes, | ||||||||||||||
| listWorkspaceDirectory, | ||||||||||||||
| listWorkspaceDirectories, | ||||||||||||||
| listWorkspaceFiles, | ||||||||||||||
| moveWorkspaceEntry, | ||||||||||||||
| normalizeChannelName, | ||||||||||||||
| provisionChannelWithComputer, | ||||||||||||||
|
|
@@ -48,7 +49,6 @@ import { | |||||||||||||
| restoreChannel, | ||||||||||||||
| saveChannelNote, | ||||||||||||||
| saveWorkspaceTextFile, | ||||||||||||||
| syncWorkspaceArtifacts, | ||||||||||||||
| threadIdForRoot, | ||||||||||||||
| updateChannelPurpose, | ||||||||||||||
| } from "./agents.ts"; | ||||||||||||||
|
|
@@ -1321,13 +1321,9 @@ const server = createServer(async (req, res) => { | |||||||||||||
| } | ||||||||||||||
| if (action === "files" && m === "GET") { | ||||||||||||||
| try { | ||||||||||||||
| if (!url.searchParams.has("path")) { | ||||||||||||||
| await refreshChannelWorkspaceMirror(channelId); | ||||||||||||||
| const files = syncWorkspaceArtifacts(channelId, null, "agent"); | ||||||||||||||
| return json(res, 200, { path: "", files, artifacts: q("SELECT * FROM artifacts WHERE channel_id=? ORDER BY modified DESC", channelId) }); | ||||||||||||||
| } | ||||||||||||||
| if (!url.searchParams.has("path")) return json(res, 200, { path: "", files: listWorkspaceFiles(channelId) }); | ||||||||||||||
| const directory = listWorkspaceDirectory(channelId, url.searchParams.get("path") || ""); | ||||||||||||||
| return json(res, 200, { ...directory, artifacts: q("SELECT * FROM artifacts WHERE channel_id=? ORDER BY modified DESC", channelId) }); | ||||||||||||||
| return json(res, 200, directory); | ||||||||||||||
|
Comment on lines
+1324
to
+1326
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🚀 Performance & Scalability | 🟠 Major | ⚡ Quick win Bound the root Files response. Line 1324 calls Return the direct directory listing for the root path, or add an explicit bounded traversal contract. Add an endpoint test with a deep dependency tree. Proposed fix- if (!url.searchParams.has("path")) return json(res, 200, { path: "", files: listWorkspaceFiles(channelId) });
- const directory = listWorkspaceDirectory(channelId, url.searchParams.get("path") || "");
+ const directory = listWorkspaceDirectory(channelId, url.searchParams.get("path") || "");
return json(res, 200, directory);📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||
| } catch (error) { return json(res, 400, { error: (error as Error).message }); } | ||||||||||||||
| } | ||||||||||||||
| if (action === "memory" && m === "GET") return json(res, 200, { memory: q("SELECT m.*, t.root_message_id FROM memory_items m LEFT JOIN threads t ON t.id=m.thread_id WHERE m.channel_id=? AND m.kind<>'summary' ORDER BY m.status, m.created DESC", channelId) }); | ||||||||||||||
|
|
@@ -1611,16 +1607,14 @@ const server = createServer(async (req, res) => { | |||||||||||||
| if (!canSee(user, cid)) return json(res, 403, { error: "No access" }); | ||||||||||||||
| // Never advance past an in-flight Working placeholder — that ate finished agent turns. | ||||||||||||||
| const maxId = maxSettledMessageId(cid); | ||||||||||||||
| run("INSERT INTO members (channel_id, user_id, last_read) VALUES (?,?,?) ON CONFLICT(channel_id,user_id) DO UPDATE SET last_read=excluded.last_read", | ||||||||||||||
| cid, user.id, maxId); | ||||||||||||||
| queueLastRead(Number(user.id), cid, maxId); | ||||||||||||||
| return json(res, 200, { ok: true, last_read: maxId }); | ||||||||||||||
| } | ||||||||||||||
| if ((mm = p.match(/^\/api\/channels\/(\d+)\/messages$/))) { | ||||||||||||||
| const cid = Number(mm[1]); | ||||||||||||||
| if (!canSee(user, cid)) return json(res, 403, { error: "No access" }); | ||||||||||||||
| if (m === "GET") { | ||||||||||||||
| run("INSERT INTO members (channel_id, user_id, last_read) VALUES (?,?,?) ON CONFLICT(channel_id,user_id) DO UPDATE SET last_read=excluded.last_read", | ||||||||||||||
| cid, user.id, maxSettledMessageId(cid)); | ||||||||||||||
| queueLastRead(Number(user.id), cid, maxSettledMessageId(cid)); | ||||||||||||||
| const rows = q("SELECT id FROM messages WHERE channel_id=? AND parent_id IS NULL AND photon_conversation_id IS NULL AND workflow_id IS NULL ORDER BY id DESC LIMIT 100", cid).reverse(); | ||||||||||||||
| return json(res, 200, { messages: rows.map((r) => serializeMessage(Number(r.id))), bots: botsInChannel(cid).map(botView), agent: agentViewForChannel(cid) }); | ||||||||||||||
| } | ||||||||||||||
|
|
@@ -2278,6 +2272,7 @@ const shutdown = async (forNativeUpdate = false): Promise<void> => { | |||||||||||||
| new Promise<void>((resolve) => server.close(() => resolve())), | ||||||||||||||
| new Promise<void>((resolve) => { const timer = setTimeout(resolve, 12_000); timer.unref(); }), | ||||||||||||||
| ]); | ||||||||||||||
| await shutdownReadStateWorker().catch(() => undefined); | ||||||||||||||
| if (!forNativeUpdate) process.exit(0); | ||||||||||||||
| }; | ||||||||||||||
| process.once("SIGTERM", () => { void shutdown(); }); | ||||||||||||||
|
|
||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
Repository: gitcommit90/1Helm
Length of output: 2644
🏁 Script executed:
Repository: gitcommit90/1Helm
Length of output: 6330
🏁 Script executed:
Repository: gitcommit90/1Helm
Length of output: 1527
Run the required checks before merge.
The focused test and architecture report passed.
npm run cirequires an environment with the locked dependencies installed;node_modulesis absent. Rerunnpm run ciand record all results in the handoff.🤖 Prompt for AI Agents
Source: Coding guidelines