Skip to content

Commit b4b49be

Browse files
committed
Prepare 1.0.4 responsiveness release
1 parent 011c945 commit b4b49be

6 files changed

Lines changed: 43 additions & 6 deletions

File tree

‎CHANGELOG.md‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
## [1.0.4] - 2026-08-12
11+
12+
### Fixed
13+
14+
- Opening Files in a large resident workspace no longer blocks every channel,
15+
thread, or health request while recursively walking dependency and cache
16+
trees. Files now loads one bounded directory at a time, upgrade cleanup
17+
removes obsolete auto-indexed metadata while preserving uploads and explicit
18+
attachments, and ordinary shell commands no longer rebuild that metadata.
19+
- Channel history no longer repeats the same inline profile photo in every
20+
message. The client reuses the user and agent records it already loaded,
21+
keeping channel switches fast on bandwidth- or latency-sensitive links.
22+
- SQLite write durability, read receipts, checkpoints, and fleet reconciliation
23+
no longer put avoidable synchronous storage pressure on foreground requests.
24+
- Denied service-user `sudo` calls no longer start mail delivery processes that
25+
can retry forever inside the hardened Linux service sandbox.
26+
1027
## [1.0.3] - 2026-08-10
1128

1229
### Added

‎package-lock.json‎

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎package.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "1helm",
33
"productName": "1Helm",
4-
"version": "1.0.3",
4+
"version": "1.0.4",
55
"private": true,
66
"type": "module",
77
"license": "AGPL-3.0-only",

‎src/server/database-migrations.ts‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
type Execute = (sql: string, ...params: unknown[]) => unknown;
2+
3+
/** Remove legacy recursive file indexes without touching uploads or attachments. */
4+
export function cleanupLegacyWorkspaceArtifacts(run: Execute): void {
5+
run(`DELETE FROM artifacts
6+
WHERE kind='file'
7+
AND NOT EXISTS (
8+
SELECT 1 FROM attachments at
9+
JOIN messages m ON m.id=at.message_id
10+
WHERE m.channel_id=artifacts.channel_id
11+
AND at.workspace_path=artifacts.path
12+
)`);
13+
}

‎src/server/db.ts‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,15 @@ import { createHash, randomBytes, scryptSync, timingSafeEqual } from "node:crypt
33
import { existsSync, mkdirSync, readFileSync } from "node:fs";
44
import { join } from "node:path";
55
import { BUILTIN_SKILLS } from "./builtin-skills.ts";
6+
import { cleanupLegacyWorkspaceArtifacts } from "./database-migrations.ts";
67

78
export const UNIVERSAL_RESIDENT_SKILL_SLUGS = [
89
"outcome-ownership", "blocker-resolution", "skipper-escalation", "capability-discovery",
910
"durable-memory", "workspace-artifacts", "quality-verification",
1011
] as const;
1112

1213
export const DATA_DIR = process.env.CTRL_DATA_DIR || join(process.cwd(), "data");
13-
export const UPLOAD_DIR = join(DATA_DIR, "uploads");
14-
mkdirSync(UPLOAD_DIR, { recursive: true });
14+
export const UPLOAD_DIR = join(DATA_DIR, "uploads"); mkdirSync(UPLOAD_DIR, { recursive: true });
1515

1616
export const db = new DatabaseSync(join(DATA_DIR, "ctrl-pane.db"));
1717
db.function("sha256", { deterministic: true }, (value: unknown) => createHash("sha256").update(String(value ?? "")).digest("hex"));
@@ -113,7 +113,6 @@ const addColumn = (table: string, name: string, ddl: string): void => {
113113

114114
const hostLabel = (url: string): string => { try { return new URL(url).host; } catch { return url || "provider"; } };
115115
const providerKind = (url: string): string => /openrouter\.ai/i.test(url) ? "openrouter" : "openai";
116-
117116
/** Additive migrations keep the legacy bot runtime usable while agents become canonical. */
118117
export function migrate(): void {
119118
addColumn("bots", "provider_id", "provider_id INTEGER");
@@ -586,6 +585,7 @@ export function migrate(): void {
586585
SELECT bot_id, NEW.channel_id FROM agents WHERE id=NEW.agent_id AND bot_id IS NOT NULL;
587586
END;
588587
`);
588+
cleanupLegacyWorkspaceArtifacts(run);
589589
// Photon is a private Captain ↔ Skipper inbox. Legacy channel mappings are
590590
// retained only long enough to migrate conversation history; they are no
591591
// longer a user-facing routing primitive.

‎test/files-latency.mjs‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,13 @@ test("Files directory reads stay responsive while an explicit VM refresh is slow
3535
db.run("UPDATE users SET avatar=? WHERE id=?", `data:image/png;base64,${"a".repeat(30_000)}`, userId);
3636
const messageId = store.createMessage({ channelId: provisioned.channelId, parentId: null, userId, body: "Compact navigation payload" });
3737
assert.equal(Object.hasOwn(store.serializeMessage(messageId).author, "avatar"), false, "message history references the already-loaded user record instead of repeating its avatar per message");
38+
db.run("INSERT INTO artifacts (channel_id,path,kind,created_by,created) VALUES (?,?, 'file','agent',?)", provisioned.channelId, "workspace/node_modules/dependency.js", Date.now());
39+
db.run("INSERT INTO artifacts (channel_id,path,kind,created_by,created) VALUES (?,?, 'file','agent',?)", provisioned.channelId, "workspace/attached.md", Date.now());
40+
db.run("INSERT INTO artifacts (channel_id,path,kind,created_by,created) VALUES (?,?, 'upload','user',?)", provisioned.channelId, "files/upload.txt", Date.now());
41+
db.run("INSERT INTO attachments (message_id,name,mime,size,path,workspace_path) VALUES (?,?,?,?,?,?)", messageId, "attached.md", "text/markdown", 7, "token", "workspace/attached.md");
42+
db.migrate();
43+
assert.equal(db.q1("SELECT COUNT(*) n FROM artifacts WHERE channel_id=? AND path='workspace/node_modules/dependency.js'", provisioned.channelId).n, 0, "upgrade migration removes recursively indexed workspace internals");
44+
assert.equal(db.q1("SELECT COUNT(*) n FROM artifacts WHERE channel_id=? AND path IN ('workspace/attached.md','files/upload.txt')", provisioned.channelId).n, 2, "upgrade migration preserves explicit attachments and uploads");
3845
const computer = await computers.provisionChannelComputer(provisioned.channelId);
3946
agents.createWorkspaceFile(provisioned.channelId, "", "cached.txt", "cached");
4047
agents.createWorkspaceDirectory(provisioned.channelId, "", "large-project");

0 commit comments

Comments
 (0)