Skip to content

Commit 6e12c84

Browse files
catomeanclaude
andcommitted
style: format with prettier (12 files)
Mechanical. No behaviour change. This SHA is listed in .git-blame-ignore-revs so `git blame` skips it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
1 parent afdfb1e commit 6e12c84

12 files changed

Lines changed: 58 additions & 71 deletions

.github/dependabot.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
version: 2
1212
updates:
1313
- package-ecosystem: npm
14-
directory: "/"
14+
directory: '/'
1515
schedule:
1616
interval: weekly
1717
open-pull-requests-limit: 5
@@ -20,7 +20,7 @@ updates:
2020
update-types: [minor, patch]
2121

2222
- package-ecosystem: github-actions
23-
directory: "/"
23+
directory: '/'
2424
schedule:
2525
interval: weekly
2626
open-pull-requests-limit: 3

eslint.config.mjs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
// library code, and a bespoke rule set would be a second opinion to maintain
33
// for no benefit. The floor is "lint runs and can fail", not "lint encodes
44
// taste".
5-
import js from '@eslint/js'
6-
import globals from 'globals'
7-
import tseslint from 'typescript-eslint'
5+
import js from '@eslint/js';
6+
import globals from 'globals';
7+
import tseslint from 'typescript-eslint';
88

99
export default tseslint.config(
1010
{
@@ -22,4 +22,4 @@ export default tseslint.config(
2222
files: ['test/**/*.js', 'scripts/**/*.{js,mjs}'],
2323
languageOptions: { globals: { ...globals.node, ...globals.nodeBuiltin } },
2424
},
25-
)
25+
);

src/ai.ts

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -67,11 +67,11 @@ export function whenMentioned(aliases: readonly string[]): RespondPolicy {
6767
// addressed to it.
6868
const patterns = aliases
6969
.filter(Boolean)
70-
.map(a => new RegExp(`(^|\\W)${a.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}(\\W|$)`, 'i'));
70+
.map((a) => new RegExp(`(^|\\W)${a.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}(\\W|$)`, 'i'));
7171
return ({ visible, self }) => {
7272
const last = visible[visible.length - 1];
7373
if (!last || last.authorId === self.actorId) return false;
74-
return patterns.some(re => re.test(last.body));
74+
return patterns.some((re) => re.test(last.body));
7575
};
7676
}
7777

@@ -84,7 +84,7 @@ export function whenMentioned(aliases: readonly string[]): RespondPolicy {
8484
* clinical thread unusable the moment an assistant joined.
8585
*/
8686
export function defaultRespondPolicy(ctx: AiTurnContext): boolean {
87-
const active = ctx.thread.participants.filter(p => !p.leftAt);
87+
const active = ctx.thread.participants.filter((p) => !p.leftAt);
8888
if (active.length <= 2) return afterEveryMessage(ctx);
8989
return whenMentioned([ctx.self.role ?? 'assistant', 'ai'])(ctx);
9090
}
@@ -98,12 +98,9 @@ function trailingSelfMessages(visible: readonly Message[], actorId: string): num
9898
return n;
9999
}
100100

101-
function renderTranscript(
102-
ctx: AiTurnContext,
103-
label: (p: Participant) => string
104-
): string {
101+
function renderTranscript(ctx: AiTurnContext, label: (p: Participant) => string): string {
105102
return ctx.visible
106-
.map(m => {
103+
.map((m) => {
107104
const author = findParticipant(ctx.thread, m.authorId);
108105
const who = author ? label(author) : 'unknown';
109106
return `${who}: ${m.body}`;
@@ -124,7 +121,7 @@ function renderTranscript(
124121
export async function runAiTurn(
125122
thread: Thread,
126123
allMessages: readonly Message[],
127-
config: AiParticipantConfig
124+
config: AiParticipantConfig,
128125
): Promise<AiTurnResult> {
129126
const self = findParticipant(thread, config.actorId);
130127
if (!self) return { status: 'skipped', reason: 'not a participant in this thread' };

src/index.ts

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,5 @@ export { unreadCount, unreadMessages, unreadThreadCount } from './unread.js';
2222

2323
export { compareMessages, isPending, mergeMessages } from './merge.js';
2424

25-
export {
26-
afterEveryMessage,
27-
defaultRespondPolicy,
28-
runAiTurn,
29-
whenMentioned,
30-
} from './ai.js';
31-
export type {
32-
AiParticipantConfig,
33-
AiTurnContext,
34-
AiTurnResult,
35-
RespondPolicy,
36-
} from './ai.js';
25+
export { afterEveryMessage, defaultRespondPolicy, runAiTurn, whenMentioned } from './ai.js';
26+
export type { AiParticipantConfig, AiTurnContext, AiTurnResult, RespondPolicy } from './ai.js';

src/merge.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export function compareMessages(a: Message, b: Message): number {
2626
*/
2727
export function mergeMessages(
2828
existing: readonly Message[],
29-
incoming: readonly Message[]
29+
incoming: readonly Message[],
3030
): Message[] {
3131
const byId = new Map<string, Message>();
3232
const idByClientId = new Map<string, string>();

src/participants.ts

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,8 @@ import type { Message, Participant, Thread } from './types.js';
1010
* thread does not have that failure mode.
1111
*/
1212

13-
export function findParticipant(
14-
thread: Thread,
15-
actorId: string
16-
): Participant | undefined {
17-
return thread.participants.find(p => p.actorId === actorId);
13+
export function findParticipant(thread: Thread, actorId: string): Participant | undefined {
14+
return thread.participants.find((p) => p.actorId === actorId);
1815
}
1916

2017
/** Has this actor ever been part of the thread? Necessary, never sufficient — see `canSeeMessage`. */
@@ -63,11 +60,11 @@ export function canSeeMessage(p: Participant, message: Message): boolean {
6360
export function visibleMessages(
6461
thread: Thread,
6562
actorId: string,
66-
messages: readonly Message[]
63+
messages: readonly Message[],
6764
): Message[] {
6865
const p = findParticipant(thread, actorId);
6966
if (!p) return [];
70-
return messages.filter(m => m.threadId === thread.id && canSeeMessage(p, m));
67+
return messages.filter((m) => m.threadId === thread.id && canSeeMessage(p, m));
7168
}
7269

7370
/**
@@ -78,7 +75,7 @@ export function visibleMessages(
7875
* access that does not exist.
7976
*/
8077
export function readersOf(thread: Thread, message: Message): Participant[] {
81-
return thread.participants.filter(p => {
78+
return thread.participants.filter((p) => {
8279
if (p.actorId === message.authorId) return false;
8380
if (!canSeeMessage(p, message)) return false;
8481
if (!p.lastReadAt) return false;

src/unread.ts

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,12 @@ import { findParticipant, canSeeMessage } from './participants.js';
1515
export function unreadMessages(
1616
thread: Thread,
1717
actorId: string,
18-
messages: readonly Message[]
18+
messages: readonly Message[],
1919
): Message[] {
2020
const p = findParticipant(thread, actorId);
2121
if (!p) return [];
2222
const since = p.lastReadAt?.getTime() ?? null;
23-
return messages.filter(m => {
23+
return messages.filter((m) => {
2424
if (m.threadId !== thread.id) return false;
2525
if (m.authorId === actorId) return false;
2626
if (!canSeeMessage(p, m)) return false;
@@ -30,11 +30,7 @@ export function unreadMessages(
3030
});
3131
}
3232

33-
export function unreadCount(
34-
thread: Thread,
35-
actorId: string,
36-
messages: readonly Message[]
37-
): number {
33+
export function unreadCount(thread: Thread, actorId: string, messages: readonly Message[]): number {
3834
return unreadMessages(thread, actorId, messages).length;
3935
}
4036

@@ -46,7 +42,7 @@ export function unreadCount(
4642
*/
4743
export function unreadThreadCount(
4844
entries: readonly { thread: Thread; messages: readonly Message[] }[],
49-
actorId: string
45+
actorId: string,
5046
): number {
51-
return entries.filter(e => unreadCount(e.thread, actorId, e.messages) > 0).length;
47+
return entries.filter((e) => unreadCount(e.thread, actorId, e.messages) > 0).length;
5248
}

test/ai.test.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ function msg(id, authorId, createdAt, body = 'hello') {
1818
/** Records what the model was shown, so the test can assert on the prompt itself. */
1919
function spyComplete(reply = 'a reply') {
2020
const seen = [];
21-
const complete = async input => {
21+
const complete = async (input) => {
2222
seen.push(input);
2323
return reply;
2424
};
@@ -47,7 +47,7 @@ test('the AI sees only what it was granted, not the whole transcript', async ()
4747
assert.equal(seen.length, 1);
4848
assert.ok(
4949
!seen[0].prompt.includes('private history'),
50-
'a model added later must not be handed the history it was not granted'
50+
'a model added later must not be handed the history it was not granted',
5151
);
5252
assert.ok(seen[0].prompt.includes('summarise my sleep'));
5353
});

test/authorization.test.js

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,7 @@
11
import { test } from 'node:test';
22
import assert from 'node:assert/strict';
33

4-
import {
5-
canRead,
6-
canWrite,
7-
readersOf,
8-
unreadCount,
9-
visibleMessages,
10-
} from '../dist/index.js';
4+
import { canRead, canWrite, readersOf, unreadCount, visibleMessages } from '../dist/index.js';
115

126
const T0 = new Date('2026-01-01T09:00:00Z');
137
const T1 = new Date('2026-01-01T10:00:00Z');
@@ -40,7 +34,7 @@ test('a clinician added later does not see what was said before they joined', ()
4034
const t = thread([patient, drA, drB]);
4135
const messages = [msg('m1', 'patient-1', T1), msg('m2', 'dr-a', T3)];
4236

43-
const seen = visibleMessages(t, 'dr-b', messages).map(m => m.id);
37+
const seen = visibleMessages(t, 'dr-b', messages).map((m) => m.id);
4438
assert.deepEqual(seen, ['m2'], 'history before joining is not granted by default');
4539
});
4640

@@ -55,7 +49,7 @@ test('granting thread-start hands over the whole history, on purpose', () => {
5549
const t = thread([patient, drA, drB]);
5650
const messages = [msg('m1', 'patient-1', T1), msg('m2', 'dr-a', T3)];
5751

58-
const seen = visibleMessages(t, 'dr-b', messages).map(m => m.id);
52+
const seen = visibleMessages(t, 'dr-b', messages).map((m) => m.id);
5953
assert.deepEqual(seen, ['m1', 'm2']);
6054
});
6155

@@ -70,7 +64,10 @@ test('someone who left keeps their history and stops receiving what comes next',
7064
const t = thread([patient, locum]);
7165
const messages = [msg('m1', 'patient-1', T1), msg('m2', 'patient-1', T3)];
7266

73-
assert.deepEqual(visibleMessages(t, 'locum', messages).map(m => m.id), ['m1']);
67+
assert.deepEqual(
68+
visibleMessages(t, 'locum', messages).map((m) => m.id),
69+
['m1'],
70+
);
7471
assert.equal(canWrite(t, 'locum', T3), false, 'a departed participant loses their voice');
7572
assert.equal(canRead(t, 'locum'), true, 'but not what they already saw');
7673
});
@@ -112,5 +109,8 @@ test('a read receipt never implies access the reader does not have', () => {
112109
const early = msg('m1', 'patient-1', T1);
113110

114111
// dr-b's clock says they have read up to T3, but m1 predates their window.
115-
assert.deepEqual(readersOf(t, early).map(p => p.actorId), []);
112+
assert.deepEqual(
113+
readersOf(t, early).map((p) => p.actorId),
114+
[],
115+
);
116116
});

test/merge.test.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ test('messages sharing a timestamp keep a stable order', () => {
4141
const a = { id: 'b', threadId: 't1', authorId: 'x', body: 'a', createdAt: T1 };
4242
const b = { id: 'a', threadId: 't1', authorId: 'x', body: 'b', createdAt: T1 };
4343

44-
const once = mergeMessages([a, b], []).map(m => m.id);
45-
const twice = mergeMessages([b, a], []).map(m => m.id);
44+
const once = mergeMessages([a, b], []).map((m) => m.id);
45+
const twice = mergeMessages([b, a], []).map((m) => m.id);
4646
assert.deepEqual(once, twice, 'insertion order must not change what the user sees');
4747
assert.deepEqual(once, ['a', 'b']);
4848
});
@@ -51,7 +51,10 @@ test('merging is ordered by time, not by arrival', () => {
5151
const late = { id: 'm2', threadId: 't1', authorId: 'x', body: 'second', createdAt: T2 };
5252
const early = { id: 'm1', threadId: 't1', authorId: 'x', body: 'first', createdAt: T1 };
5353

54-
assert.deepEqual(mergeMessages([late], [early]).map(m => m.id), ['m1', 'm2']);
54+
assert.deepEqual(
55+
mergeMessages([late], [early]).map((m) => m.id),
56+
['m1', 'm2'],
57+
);
5558
});
5659

5760
test('a pending message is distinguishable from a confirmed one', () => {

0 commit comments

Comments
 (0)