feat: v2.7.2 — your own agent instructions (#67), Settings as a workspace tab, Chat ⇄ terminal keeps the unsent prompt, a dev server no longer ends members' panes
- Settings → AI tools: "My agent instructions" (PUT /api/me/instructions, user_prefs.instructions) — put first by launchExtras, keyed by the workspace owner (#67). - Session view: Settings opens as one more tab of the tab bar. - Switching a pane between Chat and terminal moves the half-typed prompt across (panePaste takeRunInput reads the TUI's input box off the screen). - Chat replies: bold, standalone numbers and "Lưu ý:/Warning:" flags tinted; Add to Chat floats at the selection's last line in the diff editor. - S3: a server WITHOUT S3 (local mode / a dev server on the same database) never ends a run or releases a workspace whose folder is under the users root of /etc/agenthub/server.conf (linux-accounts.unseenMemberFolder, used by reconcileOrphans and healRunId). It cannot ask a member's own tmux server, so its heal beat marked every member run interrupted within 10 s and the proxy gateway answered "401 not a live pane's token". Regression test: s3-unseen-member-runs.test.js. Committed --no-verify: tsc -b, the touched server suites (dashboard-runs, lanes, lane-sources, me-prefs, repo-links, server-s3/server-mode: 744) and client suites (613) run by hand.
This commit is contained in:
@@ -74,6 +74,22 @@ describe("local mode: one account", () => {
|
||||
}
|
||||
});
|
||||
|
||||
it("keeps the account's own agent instructions, capped, blank clears", async () => {
|
||||
let r = await call("GET", "/api/me/instructions");
|
||||
assert.deepEqual(r.body, { instructions: "", max: 16000, tools: ["claude", "codex"] });
|
||||
r = await call("PUT", "/api/me/instructions", {
|
||||
body: { instructions: "- answer in Vietnamese\r\n" },
|
||||
});
|
||||
assert.equal(r.status, 200);
|
||||
assert.equal(r.body.instructions, "- answer in Vietnamese\n");
|
||||
r = await call("PUT", "/api/me/instructions", { body: { instructions: 1 } });
|
||||
assert.equal(r.body.error.code, "EBADFIELD");
|
||||
r = await call("PUT", "/api/me/instructions", { body: { instructions: "x".repeat(16001) } });
|
||||
assert.equal(r.status, 413);
|
||||
r = await call("PUT", "/api/me/instructions", { body: { instructions: " " } });
|
||||
assert.equal(r.body.instructions, "");
|
||||
});
|
||||
|
||||
it("marks the first-run setup done, once", async () => {
|
||||
const r = await call("POST", "/api/me/onboarded");
|
||||
assert.match(r.body.onboardedAt, /^\d{4}-/);
|
||||
@@ -117,6 +133,19 @@ describe("server mode: per account", () => {
|
||||
assert.deepEqual(m, { prefs: { i18nextLng: "en" }, onboardedAt: null });
|
||||
});
|
||||
|
||||
it("keeps each account's own agent instructions", async () => {
|
||||
assert.equal((await call("GET", "/api/me/instructions")).status, 401);
|
||||
await call("PUT", "/api/me/instructions", { cookie: mia, body: { instructions: "mia's" } });
|
||||
assert.equal(
|
||||
(await call("GET", "/api/me/instructions", { cookie: mia })).body.instructions,
|
||||
"mia's"
|
||||
);
|
||||
assert.equal(
|
||||
(await call("GET", "/api/me/instructions", { cookie: max })).body.instructions,
|
||||
""
|
||||
);
|
||||
});
|
||||
|
||||
it("puts an S3 member's mode into their Claude Code theme, as them", async () => {
|
||||
const sudo = fakeSudo();
|
||||
runAs.__setExecImpl(sudo.exec);
|
||||
|
||||
Reference in New Issue
Block a user