mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-11-14 18:39:33 +01:00
fix(discord): digit replies without Enter, start the gateway after restore, hide other users' session ids, fix docs
- a lone digit reply is typed without Enter while the tab has a pending permission or question - the gateway starts after restoreMuxSessions (hold and release), so a reply during restore is not told the tab is gone - discord-notify resolves an id prefix only among sessions the caller may see - restore docs/architecture-invariants.md from base and add only the Discord section - docs: self-ignoring folder, no logging, Notifications group, Send test, local-tab-only Claude hint, typedHint wording
This commit is contained in:
1 parent
dc22519adb
commit
212989b349
10 files changed
+120
-49
No files matched your search
@@ -541,6 +541,16 @@ describe('DiscordBridge', () => {
|
||||
b.stop();
|
||||
});
|
||||
|
||||
it('keeps the gateway off while held (boot) and starts it on release', async () => {
|
||||
const b = bridge();
|
||||
b.hold();
|
||||
await b.reload();
|
||||
expect(b.gatewayState).toBe('off');
|
||||
await b.release();
|
||||
expect(b.gatewayState).not.toBe('off');
|
||||
b.stop();
|
||||
});
|
||||
|
||||
describe('sendTest', () => {
|
||||
it('posts with the config it is given and leaves the live config alone', async () => {
|
||||
const auth: string[] = [];
|
||||
@@ -721,7 +731,11 @@ describe('DiscordBridge files and startup hint', () => {
|
||||
let posted: Array<{ path: string; body?: Record<string, unknown> }>;
|
||||
let downloads: string[];
|
||||
|
||||
function make(cfg: Partial<DiscordConfig> = {}, dirFor: (id: string) => string | undefined = () => work) {
|
||||
function make(
|
||||
cfg: Partial<DiscordConfig> = {},
|
||||
dirFor: (id: string) => string | undefined = () => work,
|
||||
awaitingChoice?: (id: string) => boolean
|
||||
) {
|
||||
const b = new DiscordBridge({
|
||||
configDir: dir,
|
||||
fetchImpl: async (url, init) => {
|
||||
@@ -736,6 +750,7 @@ describe('DiscordBridge files and startup hint', () => {
|
||||
},
|
||||
sendInput: async (id, text, fromUser) => (sent.push([id, text, fromUser]), true),
|
||||
sessionDir: dirFor,
|
||||
awaitingChoice,
|
||||
socketFactory: () => new FakeSocket(),
|
||||
now: () => t,
|
||||
sleep: async () => undefined,
|
||||
@@ -819,6 +834,21 @@ describe('DiscordBridge files and startup hint', () => {
|
||||
b.stop();
|
||||
});
|
||||
|
||||
it('types a lone digit without Enter while a dialog is waiting, and with Enter otherwise', async () => {
|
||||
let waiting = true;
|
||||
const b = await make({}, undefined, () => waiting);
|
||||
await b.onGatewayMessage(reply({ content: '2', attachments: [] }));
|
||||
expect(sent.at(-1)?.[1]).toBe('2');
|
||||
t += 5_000;
|
||||
await b.onGatewayMessage(reply({ content: 'yes', attachments: [] }));
|
||||
expect(sent.at(-1)?.[1]).toBe('yes\r');
|
||||
t += 5_000;
|
||||
waiting = false;
|
||||
await b.onGatewayMessage(reply({ content: '2', attachments: [] }));
|
||||
expect(sent.at(-1)?.[1]).toBe('2\r');
|
||||
b.stop();
|
||||
});
|
||||
|
||||
it('does not save a file for a message id that is not a snowflake, and says so', async () => {
|
||||
const b = await make();
|
||||
await b.onGatewayMessage(reply({ id: '../../x' }));
|
||||
|
||||
@@ -162,6 +162,20 @@ describe('POST /api/sessions/:id/discord-notify', () => {
|
||||
bridge.stop();
|
||||
});
|
||||
|
||||
it("does not reveal another user's session through its id prefix (multi-user)", async () => {
|
||||
process.env.CODEMAN_MULTIUSER = '1';
|
||||
const { app, bridge, ctx } = await harness({ username: 'bob', role: 'user' });
|
||||
(ctx.sessions.get('test-session-1') as unknown as { owner: string }).owner = 'alice';
|
||||
const res = await app.inject({
|
||||
method: 'POST',
|
||||
url: '/api/sessions/test-ses/discord-notify',
|
||||
payload: { message: 'hi' },
|
||||
});
|
||||
expect(res.statusCode).toBe(404);
|
||||
expect(res.json().error).not.toContain('test-session-1');
|
||||
bridge.stop();
|
||||
});
|
||||
|
||||
it('lets two different deliberate messages from one tab through within 3 s (neither is lost)', async () => {
|
||||
const { app, bridge } = await harness();
|
||||
await app.inject({ method: 'PUT', url: '/api/discord', payload: FULL });
|
||||
|
||||
Reference in new issue
Block a user