@mattstack/rt-client 0.11.0 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -0
- package/dist/client.d.ts +21 -1
- package/dist/commands.d.ts +61 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +83 -9
- package/package.json +1 -1
- package/src/client.ts +24 -3
- package/src/commands.ts +30 -1
- package/src/index.ts +4 -0
- package/src/settings/registry-defs.ts +73 -9
package/README.md
CHANGED
|
@@ -111,6 +111,10 @@ socket. The verbs and their payloads are specified in repo-tools
|
|
|
111
111
|
`docs/superpowers/specs/2026-08-28-rt-chat-delivery-v2-design.md`; the
|
|
112
112
|
agent-facing rules are `skills/rt-chat/SKILL.md`.
|
|
113
113
|
|
|
114
|
+
## Runs
|
|
115
|
+
|
|
116
|
+
`RunStageRow.status` is one of `running | done | failed | redirected`; `rt runs stage-redirect` writes the fourth when the work engine leaves a stage for another one, so a reader that maps statuses to icons or filters must handle all four.
|
|
117
|
+
|
|
114
118
|
## License
|
|
115
119
|
|
|
116
120
|
MIT
|
package/dist/client.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { RtResponse, RtClientOptions } from "./transport.ts";
|
|
2
|
-
import type { DemandDecl, ProjectMRsData, DiscussionsData, MrByBranchData, BranchEnrichment, ForgeSlug, ForgeTokenData, RunSummary, RunDetail, WakeMode, ChatMember, ChatMessage, RoomSummary, BuddyStatus, PresenceRow, AgentRecord, Commands } from "./commands.ts";
|
|
2
|
+
import type { DemandDecl, ProjectMRsData, DiscussionsData, MrByBranchData, BranchEnrichment, ForgeSlug, ForgeTokenData, RunSummary, RunDetail, WakeMode, ChatMember, ChatMessage, ChatClaimOutcome, RoomSummary, BuddyStatus, PresenceRow, AgentRecord, Commands } from "./commands.ts";
|
|
3
3
|
/**
|
|
4
4
|
* One repo's project open-MR store. A cold repo forces a full paginated sync
|
|
5
5
|
* on the daemon side when maxAgeMs demands it, which can run tens of seconds
|
|
@@ -59,9 +59,29 @@ export declare function chatPost(a: {
|
|
|
59
59
|
handle: string;
|
|
60
60
|
body: string;
|
|
61
61
|
mentions?: string[];
|
|
62
|
+
quiet?: boolean;
|
|
62
63
|
}, o?: RtClientOptions): Promise<RtResponse<{
|
|
63
64
|
id: number;
|
|
64
65
|
recipients: string[];
|
|
66
|
+
others: number;
|
|
67
|
+
}>>;
|
|
68
|
+
export declare function chatAck(a: {
|
|
69
|
+
id: number;
|
|
70
|
+
handle: string;
|
|
71
|
+
}, o?: RtClientOptions): Promise<RtResponse<{
|
|
72
|
+
author: string;
|
|
73
|
+
room: string;
|
|
74
|
+
already: boolean;
|
|
75
|
+
}>>;
|
|
76
|
+
export declare function chatClaim(a: {
|
|
77
|
+
id: number;
|
|
78
|
+
handle: string;
|
|
79
|
+
}, o?: RtClientOptions): Promise<RtResponse<ChatClaimOutcome>>;
|
|
80
|
+
export declare function chatRelease(a: {
|
|
81
|
+
id: number;
|
|
82
|
+
handle: string;
|
|
83
|
+
}, o?: RtClientOptions): Promise<RtResponse<{
|
|
84
|
+
holder: string;
|
|
65
85
|
}>>;
|
|
66
86
|
export declare function chatRead(a: {
|
|
67
87
|
handle: string;
|
package/dist/commands.d.ts
CHANGED
|
@@ -22,6 +22,10 @@ export interface ProjectMRsScope {
|
|
|
22
22
|
sections?: string[];
|
|
23
23
|
/** Demanded sections not yet swept for this client. */
|
|
24
24
|
uncoveredSections?: string[];
|
|
25
|
+
/** Section headers in the default-branch CODEOWNERS at the last deep or
|
|
26
|
+
backfill. `[]` when the project has none. Absent from a pre-knownSections
|
|
27
|
+
daemon or before the first sweep that demanded a section. */
|
|
28
|
+
knownSections?: string[];
|
|
25
29
|
}
|
|
26
30
|
export interface ProjectMRsData {
|
|
27
31
|
mrs: Record<string, {
|
|
@@ -113,6 +117,22 @@ export interface ChatMessage {
|
|
|
113
117
|
replyTo?: number;
|
|
114
118
|
postedAt: number;
|
|
115
119
|
}
|
|
120
|
+
/** `claimed` is the only outcome that woke anyone; `previousHolder` marks a takeover of an expired claim. */
|
|
121
|
+
export type ChatClaimOutcome = {
|
|
122
|
+
outcome: "claimed";
|
|
123
|
+
author: string;
|
|
124
|
+
room: string;
|
|
125
|
+
previousHolder?: string;
|
|
126
|
+
} | {
|
|
127
|
+
outcome: "held";
|
|
128
|
+
author: string;
|
|
129
|
+
room: string;
|
|
130
|
+
} | {
|
|
131
|
+
outcome: "lost";
|
|
132
|
+
holder: string;
|
|
133
|
+
claimedAt: number;
|
|
134
|
+
expiresAt: number;
|
|
135
|
+
};
|
|
116
136
|
export interface RoomSummary {
|
|
117
137
|
room: string;
|
|
118
138
|
memberCount: number;
|
|
@@ -347,6 +367,15 @@ export interface StatusData {
|
|
|
347
367
|
dormant: false;
|
|
348
368
|
};
|
|
349
369
|
}
|
|
370
|
+
/** Duplicated shape on purpose: mirrors lib/worktree/ready-held.ts's ReadyHeldRepo. */
|
|
371
|
+
export interface ReadyHeldRepo {
|
|
372
|
+
/** Serialized repo identity. A key, never displayed. */
|
|
373
|
+
repo: string;
|
|
374
|
+
/** Decoded display name. Never sent back as a key. */
|
|
375
|
+
label: string;
|
|
376
|
+
hash: string;
|
|
377
|
+
approveCommand: string;
|
|
378
|
+
}
|
|
350
379
|
export interface TrayStatusData {
|
|
351
380
|
pid: number;
|
|
352
381
|
uptime: number;
|
|
@@ -364,6 +393,8 @@ export interface TrayStatusData {
|
|
|
364
393
|
};
|
|
365
394
|
metrics: HealthMetrics;
|
|
366
395
|
eventLoop: HealthEventLoop;
|
|
396
|
+
/** Optional because a daemon older than RT-98 does not send it. */
|
|
397
|
+
worktreeReadyHeld?: ReadyHeldRepo[];
|
|
367
398
|
}
|
|
368
399
|
/** Duplicated shape on purpose: mirrors lib/port-scanner.ts's PortEntry. */
|
|
369
400
|
export interface PortEntry {
|
|
@@ -700,16 +731,46 @@ export interface Commands {
|
|
|
700
731
|
};
|
|
701
732
|
data: Record<string, never>;
|
|
702
733
|
};
|
|
734
|
+
/** `others` counts the room's members besides the author, so a caller can tell "woke nobody of 7" from "nobody else is here". */
|
|
703
735
|
"chat:post": {
|
|
704
736
|
payload: {
|
|
705
737
|
room: string;
|
|
706
738
|
handle: string;
|
|
707
739
|
body: string;
|
|
708
740
|
mentions?: string[];
|
|
741
|
+
quiet?: boolean;
|
|
709
742
|
};
|
|
710
743
|
data: {
|
|
711
744
|
id: number;
|
|
712
745
|
recipients: string[];
|
|
746
|
+
others: number;
|
|
747
|
+
};
|
|
748
|
+
};
|
|
749
|
+
"chat:ack": {
|
|
750
|
+
payload: {
|
|
751
|
+
id: number;
|
|
752
|
+
handle: string;
|
|
753
|
+
};
|
|
754
|
+
data: {
|
|
755
|
+
author: string;
|
|
756
|
+
room: string;
|
|
757
|
+
already: boolean;
|
|
758
|
+
};
|
|
759
|
+
};
|
|
760
|
+
"chat:claim": {
|
|
761
|
+
payload: {
|
|
762
|
+
id: number;
|
|
763
|
+
handle: string;
|
|
764
|
+
};
|
|
765
|
+
data: ChatClaimOutcome;
|
|
766
|
+
};
|
|
767
|
+
"chat:release": {
|
|
768
|
+
payload: {
|
|
769
|
+
id: number;
|
|
770
|
+
handle: string;
|
|
771
|
+
};
|
|
772
|
+
data: {
|
|
773
|
+
holder: string;
|
|
713
774
|
};
|
|
714
775
|
};
|
|
715
776
|
"chat:read": {
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
export { rtCommand, DEFAULT_SOCK } from "./transport.ts";
|
|
2
2
|
export type { RtResponse, RtClientOptions } from "./transport.ts";
|
|
3
|
-
export { readProjectMRs, readDiscussions, readMrsByBranch, readBranchCache, resolveForgeToken, listRuns, getRun, abandonRun, chatJoin, chatLeave, chatPost, chatRead, chatRooms, chatWho, chatMark, chatMessages, chatSignIn, chatSignOut, chatAway, chatBack, chatBuddies, chatDm, chatArchive, chatDmOpen, eventsHead, agentStart, agentResume, agentGet, agentList, paneList, panePeek, paneSpawn, paneAccounts, paneDirectories, chatInvite, paneSend, paneFocus, } from "./client.ts";
|
|
3
|
+
export { readProjectMRs, readDiscussions, readMrsByBranch, readBranchCache, resolveForgeToken, listRuns, getRun, abandonRun, chatJoin, chatLeave, chatAck, chatClaim, chatRelease, chatPost, chatRead, chatRooms, chatWho, chatMark, chatMessages, chatSignIn, chatSignOut, chatAway, chatBack, chatBuddies, chatDm, chatArchive, chatDmOpen, eventsHead, agentStart, agentResume, agentGet, agentList, paneList, panePeek, paneSpawn, paneAccounts, paneDirectories, chatInvite, paneSend, paneFocus, } from "./client.ts";
|
|
4
4
|
export { COMMAND_NAMES } from "./commands.ts";
|
|
5
|
-
export type { Discussion, DemandDecl, ProjectMRsScope, ProjectMRsData, DiscussionsData, MrByBranchEntry, MrByBranchData, BranchEnrichment, Commands, CommandName, ForgeSlug, ForgeTokenData, Attention, RunSummary, RunStageRow, RunFieldRow, RunDecisionRow, RunDetail, WakeMode, ChatMember, ChatMessage, RoomSummary, BuddyStatus, PresenceRow, AgentRecord, AgentSurface, AgentStatus, ChatPane, PaneAccount, PaneDirectory, InviteResult, PaneDelivery, PaneSendResult, PaneFocusResult, } from "./commands.ts";
|
|
5
|
+
export type { Discussion, DemandDecl, ProjectMRsScope, ProjectMRsData, DiscussionsData, MrByBranchEntry, MrByBranchData, BranchEnrichment, Commands, CommandName, ForgeSlug, ForgeTokenData, Attention, RunSummary, RunStageRow, RunFieldRow, RunDecisionRow, RunDetail, WakeMode, ChatMember, ChatMessage, ChatClaimOutcome, RoomSummary, BuddyStatus, PresenceRow, AgentRecord, AgentSurface, AgentStatus, ChatPane, PaneAccount, PaneDirectory, InviteResult, PaneDelivery, PaneSendResult, PaneFocusResult, } from "./commands.ts";
|
|
6
6
|
export { subscribe, createRelay, DEFAULT_WS_URL } from "./relay.ts";
|
|
7
7
|
export type { RelayEventType } from "./relay.ts";
|
|
8
8
|
export { daemonHealth } from "./health.ts";
|
package/dist/index.js
CHANGED
|
@@ -82,8 +82,19 @@ function chatPost(a, o = {}) {
|
|
|
82
82
|
const payload = { room: a.room, handle: a.handle, body: a.body };
|
|
83
83
|
if (a.mentions !== undefined)
|
|
84
84
|
payload.mentions = a.mentions;
|
|
85
|
+
if (a.quiet)
|
|
86
|
+
payload.quiet = true;
|
|
85
87
|
return rtCommand("chat:post", payload, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 1e4 });
|
|
86
88
|
}
|
|
89
|
+
function chatAck(a, o = {}) {
|
|
90
|
+
return rtCommand("chat:ack", { id: a.id, handle: a.handle }, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 1e4 });
|
|
91
|
+
}
|
|
92
|
+
function chatClaim(a, o = {}) {
|
|
93
|
+
return rtCommand("chat:claim", { id: a.id, handle: a.handle }, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 1e4 });
|
|
94
|
+
}
|
|
95
|
+
function chatRelease(a, o = {}) {
|
|
96
|
+
return rtCommand("chat:release", { id: a.id, handle: a.handle }, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 1e4 });
|
|
97
|
+
}
|
|
87
98
|
function chatRead(a, o = {}) {
|
|
88
99
|
const payload = { handle: a.handle };
|
|
89
100
|
if (a.room !== undefined)
|
|
@@ -259,6 +270,9 @@ var COMMAND_NAMES = [
|
|
|
259
270
|
"runs:list",
|
|
260
271
|
"runs:get",
|
|
261
272
|
"runs:abandon",
|
|
273
|
+
"chat:ack",
|
|
274
|
+
"chat:claim",
|
|
275
|
+
"chat:release",
|
|
262
276
|
"chat:join",
|
|
263
277
|
"chat:leave",
|
|
264
278
|
"chat:post",
|
|
@@ -802,6 +816,13 @@ var REGISTRY = [
|
|
|
802
816
|
migrated: true,
|
|
803
817
|
description: "User-confirmed integration hosts (forgeHost, switchboardUrl), written only by an explicit `rt setup <id> connect --host` after that host validates a real credential. The one trusted source a credential is ever sent to — mattstack.integrations' team-declared host is shown to the user but never auto-used for a fetch."
|
|
804
818
|
},
|
|
819
|
+
{
|
|
820
|
+
key: "mattstack.roster",
|
|
821
|
+
type: "array",
|
|
822
|
+
scopes: ["team"],
|
|
823
|
+
merge: "replace",
|
|
824
|
+
description: "The suite-wide team roster: [{username, name?}] GitLab usernames with optional display names. Any suite app that lists people reads this; hiding someone is the app's own overlay (e.g. boxscore.hiddenMembers)."
|
|
825
|
+
},
|
|
805
826
|
{
|
|
806
827
|
key: "claude.marketplaces",
|
|
807
828
|
type: "array",
|
|
@@ -856,7 +877,7 @@ var REGISTRY = [
|
|
|
856
877
|
type: "array",
|
|
857
878
|
scopes: ["team"],
|
|
858
879
|
merge: "replace",
|
|
859
|
-
description: "The authors tab's roster: whose MRs the classic board lists, including hidden-by-default entries. Codeowners tabs list MRs from anyone."
|
|
880
|
+
description: "The authors tab's roster: whose MRs the classic board lists, including hidden-by-default entries. Codeowners tabs list MRs from anyone. The cross-app roster successor is mattstack.roster; this key remains the board's own list until the board adopts it."
|
|
860
881
|
},
|
|
861
882
|
{
|
|
862
883
|
key: "board.title",
|
|
@@ -956,13 +977,6 @@ var REGISTRY = [
|
|
|
956
977
|
merge: "deep",
|
|
957
978
|
description: "Local working directories the board's review/respond/doctor panes launch from."
|
|
958
979
|
},
|
|
959
|
-
{
|
|
960
|
-
key: "board.rtRepos",
|
|
961
|
-
type: "array",
|
|
962
|
-
scopes: ["machine"],
|
|
963
|
-
merge: "replace",
|
|
964
|
-
description: "rt-registered repo names the board resolves MRs against on this machine."
|
|
965
|
-
},
|
|
966
980
|
{
|
|
967
981
|
key: "board.triageMaxConcurrent",
|
|
968
982
|
type: "number",
|
|
@@ -977,6 +991,62 @@ var REGISTRY = [
|
|
|
977
991
|
merge: "replace",
|
|
978
992
|
description: "Local switchboard URL the board's POST /peer/join writer targets."
|
|
979
993
|
},
|
|
994
|
+
{
|
|
995
|
+
key: "boxscore.projects",
|
|
996
|
+
type: "array",
|
|
997
|
+
scopes: ["team"],
|
|
998
|
+
merge: "replace",
|
|
999
|
+
description: 'GitLab projects boxscore scores, as full paths ("group/project").'
|
|
1000
|
+
},
|
|
1001
|
+
{
|
|
1002
|
+
key: "boxscore.linearDoneStates",
|
|
1003
|
+
type: "array",
|
|
1004
|
+
scopes: ["team"],
|
|
1005
|
+
merge: "replace",
|
|
1006
|
+
description: "Linear workflow state names that count as done. Empty means the completed and canceled state types."
|
|
1007
|
+
},
|
|
1008
|
+
{
|
|
1009
|
+
key: "boxscore.sizeBand",
|
|
1010
|
+
type: "object",
|
|
1011
|
+
scopes: ["team"],
|
|
1012
|
+
merge: "deep",
|
|
1013
|
+
description: "MR size health band in changed lines: {tooSmall, tooLarge}. At or below tooSmall, or above tooLarge, is outside the healthy band."
|
|
1014
|
+
},
|
|
1015
|
+
{
|
|
1016
|
+
key: "boxscore.excludeFilePatterns",
|
|
1017
|
+
type: "array",
|
|
1018
|
+
scopes: ["team"],
|
|
1019
|
+
merge: "replace",
|
|
1020
|
+
description: 'Glob patterns for files excluded from addition/deletion counts (e.g. "**/*.json").'
|
|
1021
|
+
},
|
|
1022
|
+
{
|
|
1023
|
+
key: "boxscore.ignoredMrs",
|
|
1024
|
+
type: "array",
|
|
1025
|
+
scopes: ["team"],
|
|
1026
|
+
merge: "replace",
|
|
1027
|
+
description: 'MRs excluded from all metrics: "!123" or "group/project!123".'
|
|
1028
|
+
},
|
|
1029
|
+
{
|
|
1030
|
+
key: "boxscore.botPatterns",
|
|
1031
|
+
type: "array",
|
|
1032
|
+
scopes: ["team"],
|
|
1033
|
+
merge: "replace",
|
|
1034
|
+
description: "Extra regex sources treated as bot accounts, beyond boxscore's built-in detection."
|
|
1035
|
+
},
|
|
1036
|
+
{
|
|
1037
|
+
key: "boxscore.hiddenMembers",
|
|
1038
|
+
type: "array",
|
|
1039
|
+
scopes: ["user"],
|
|
1040
|
+
merge: "replace",
|
|
1041
|
+
description: "Usernames from mattstack.roster hidden from this developer's leaderboard."
|
|
1042
|
+
},
|
|
1043
|
+
{
|
|
1044
|
+
key: "boxscore.defaultRange",
|
|
1045
|
+
type: "string",
|
|
1046
|
+
scopes: ["user"],
|
|
1047
|
+
merge: "replace",
|
|
1048
|
+
description: 'Default comparison window for the API and CLI when none is given: "7d", "30d", or "90d".'
|
|
1049
|
+
},
|
|
980
1050
|
{
|
|
981
1051
|
key: "gitq.workSlots",
|
|
982
1052
|
type: "object",
|
|
@@ -1018,7 +1088,8 @@ var REGISTRY = [
|
|
|
1018
1088
|
type: "string",
|
|
1019
1089
|
scopes: ["user"],
|
|
1020
1090
|
merge: "replace",
|
|
1021
|
-
|
|
1091
|
+
default: "https://chat.mattstack",
|
|
1092
|
+
description: "Base URL of the chat viewer, no trailing slash; rt chat post and the tail's wake lines end with a link to the room or message. Defaults to the viewer deck serves on the mattstack TLD."
|
|
1022
1093
|
},
|
|
1023
1094
|
{
|
|
1024
1095
|
key: "chat.herdrWorkspace",
|
|
@@ -1931,6 +2002,7 @@ export {
|
|
|
1931
2002
|
chatSignOut,
|
|
1932
2003
|
chatSignIn,
|
|
1933
2004
|
chatRooms,
|
|
2005
|
+
chatRelease,
|
|
1934
2006
|
chatRead,
|
|
1935
2007
|
chatPost,
|
|
1936
2008
|
chatMessages,
|
|
@@ -1940,10 +2012,12 @@ export {
|
|
|
1940
2012
|
chatInvite,
|
|
1941
2013
|
chatDmOpen,
|
|
1942
2014
|
chatDm,
|
|
2015
|
+
chatClaim,
|
|
1943
2016
|
chatBuddies,
|
|
1944
2017
|
chatBack,
|
|
1945
2018
|
chatAway,
|
|
1946
2019
|
chatArchive,
|
|
2020
|
+
chatAck,
|
|
1947
2021
|
allDefs,
|
|
1948
2022
|
agentStart,
|
|
1949
2023
|
agentResume,
|
package/package.json
CHANGED
package/src/client.ts
CHANGED
|
@@ -18,6 +18,7 @@ import type {
|
|
|
18
18
|
WakeMode,
|
|
19
19
|
ChatMember,
|
|
20
20
|
ChatMessage,
|
|
21
|
+
ChatClaimOutcome,
|
|
21
22
|
RoomSummary,
|
|
22
23
|
BuddyStatus,
|
|
23
24
|
PresenceRow,
|
|
@@ -166,12 +167,32 @@ export function chatLeave(
|
|
|
166
167
|
}
|
|
167
168
|
|
|
168
169
|
export function chatPost(
|
|
169
|
-
a: { room: string; handle: string; body: string; mentions?: string[] },
|
|
170
|
+
a: { room: string; handle: string; body: string; mentions?: string[]; quiet?: boolean },
|
|
170
171
|
o: RtClientOptions = {},
|
|
171
|
-
): Promise<RtResponse<{ id: number; recipients: string[] }>> {
|
|
172
|
+
): Promise<RtResponse<{ id: number; recipients: string[]; others: number }>> {
|
|
172
173
|
const payload: Record<string, unknown> = { room: a.room, handle: a.handle, body: a.body };
|
|
173
174
|
if (a.mentions !== undefined) payload.mentions = a.mentions;
|
|
174
|
-
|
|
175
|
+
if (a.quiet) payload.quiet = true;
|
|
176
|
+
return rtCommand<{ id: number; recipients: string[]; others: number }>("chat:post", payload, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 10_000 });
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export function chatAck(
|
|
180
|
+
a: { id: number; handle: string },
|
|
181
|
+
o: RtClientOptions = {},
|
|
182
|
+
): Promise<RtResponse<{ author: string; room: string; already: boolean }>> {
|
|
183
|
+
return rtCommand<{ author: string; room: string; already: boolean }>(
|
|
184
|
+
"chat:ack",
|
|
185
|
+
{ id: a.id, handle: a.handle },
|
|
186
|
+
{ sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 10_000 },
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
export function chatClaim(a: { id: number; handle: string }, o: RtClientOptions = {}): Promise<RtResponse<ChatClaimOutcome>> {
|
|
191
|
+
return rtCommand<ChatClaimOutcome>("chat:claim", { id: a.id, handle: a.handle }, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 10_000 });
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
export function chatRelease(a: { id: number; handle: string }, o: RtClientOptions = {}): Promise<RtResponse<{ holder: string }>> {
|
|
195
|
+
return rtCommand<{ holder: string }>("chat:release", { id: a.id, handle: a.handle }, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 10_000 });
|
|
175
196
|
}
|
|
176
197
|
|
|
177
198
|
export function chatRead(
|
package/src/commands.ts
CHANGED
|
@@ -25,6 +25,10 @@ export interface ProjectMRsScope {
|
|
|
25
25
|
sections?: string[];
|
|
26
26
|
/** Demanded sections not yet swept for this client. */
|
|
27
27
|
uncoveredSections?: string[];
|
|
28
|
+
/** Section headers in the default-branch CODEOWNERS at the last deep or
|
|
29
|
+
backfill. `[]` when the project has none. Absent from a pre-knownSections
|
|
30
|
+
daemon or before the first sweep that demanded a section. */
|
|
31
|
+
knownSections?: string[];
|
|
28
32
|
}
|
|
29
33
|
|
|
30
34
|
export interface ProjectMRsData {
|
|
@@ -108,6 +112,12 @@ export interface ChatMessage {
|
|
|
108
112
|
postedAt: number;
|
|
109
113
|
}
|
|
110
114
|
|
|
115
|
+
/** `claimed` is the only outcome that woke anyone; `previousHolder` marks a takeover of an expired claim. */
|
|
116
|
+
export type ChatClaimOutcome =
|
|
117
|
+
| { outcome: "claimed"; author: string; room: string; previousHolder?: string }
|
|
118
|
+
| { outcome: "held"; author: string; room: string }
|
|
119
|
+
| { outcome: "lost"; holder: string; claimedAt: number; expiresAt: number };
|
|
120
|
+
|
|
111
121
|
export interface RoomSummary {
|
|
112
122
|
room: string;
|
|
113
123
|
memberCount: number;
|
|
@@ -254,11 +264,23 @@ export interface StatusData {
|
|
|
254
264
|
worktreePool: { dormant: true; repos: string[]; message: string } | { dormant: false };
|
|
255
265
|
}
|
|
256
266
|
|
|
267
|
+
/** Duplicated shape on purpose: mirrors lib/worktree/ready-held.ts's ReadyHeldRepo. */
|
|
268
|
+
export interface ReadyHeldRepo {
|
|
269
|
+
/** Serialized repo identity. A key, never displayed. */
|
|
270
|
+
repo: string;
|
|
271
|
+
/** Decoded display name. Never sent back as a key. */
|
|
272
|
+
label: string;
|
|
273
|
+
hash: string;
|
|
274
|
+
approveCommand: string;
|
|
275
|
+
}
|
|
276
|
+
|
|
257
277
|
export interface TrayStatusData {
|
|
258
278
|
pid: number; uptime: number; memoryUsage: number; watchedRepos: number; cacheEntries: number;
|
|
259
279
|
portsCached: number; portCacheAge: number | null; lastRefresh: number | null;
|
|
260
280
|
portsByRepo: Record<string, number>; pendingNotifications: number;
|
|
261
281
|
health: { level: HealthLevel; reasons: string[] }; metrics: HealthMetrics; eventLoop: HealthEventLoop;
|
|
282
|
+
/** Optional because a daemon older than RT-98 does not send it. */
|
|
283
|
+
worktreeReadyHeld?: ReadyHeldRepo[];
|
|
262
284
|
}
|
|
263
285
|
|
|
264
286
|
/** Duplicated shape on purpose: mirrors lib/port-scanner.ts's PortEntry. */
|
|
@@ -405,7 +427,11 @@ export interface Commands {
|
|
|
405
427
|
"runs:abandon": { payload: { runId: string; repo?: string; reason?: string }; data: { ok: boolean } };
|
|
406
428
|
"chat:join": { payload: { room: string; handle: string; wakeOn?: WakeMode; cwd?: string; pane?: string }; data: { handle: string; memberCount: number; unread: number } };
|
|
407
429
|
"chat:leave": { payload: { room: string; handle: string }; data: Record<string, never> };
|
|
408
|
-
|
|
430
|
+
/** `others` counts the room's members besides the author, so a caller can tell "woke nobody of 7" from "nobody else is here". */
|
|
431
|
+
"chat:post": { payload: { room: string; handle: string; body: string; mentions?: string[]; quiet?: boolean }; data: { id: number; recipients: string[]; others: number } };
|
|
432
|
+
"chat:ack": { payload: { id: number; handle: string }; data: { author: string; room: string; already: boolean } };
|
|
433
|
+
"chat:claim": { payload: { id: number; handle: string }; data: ChatClaimOutcome };
|
|
434
|
+
"chat:release": { payload: { id: number; handle: string }; data: { holder: string } };
|
|
409
435
|
"chat:read": { payload: { handle: string; room?: string; limit?: number; sinceMs?: number }; data: { rooms: { room: string; messages: ChatMessage[] }[] } };
|
|
410
436
|
"chat:rooms": { payload: { handle: string; includeArchived?: boolean }; data: { rooms: RoomSummary[] } };
|
|
411
437
|
"chat:who": { payload: { room: string }; data: { members: ChatMember[] } };
|
|
@@ -547,6 +573,9 @@ export const COMMAND_NAMES: readonly CommandName[] = [
|
|
|
547
573
|
"runs:list",
|
|
548
574
|
"runs:get",
|
|
549
575
|
"runs:abandon",
|
|
576
|
+
"chat:ack",
|
|
577
|
+
"chat:claim",
|
|
578
|
+
"chat:release",
|
|
550
579
|
"chat:join",
|
|
551
580
|
"chat:leave",
|
|
552
581
|
"chat:post",
|
package/src/index.ts
CHANGED
|
@@ -12,6 +12,9 @@ export {
|
|
|
12
12
|
abandonRun,
|
|
13
13
|
chatJoin,
|
|
14
14
|
chatLeave,
|
|
15
|
+
chatAck,
|
|
16
|
+
chatClaim,
|
|
17
|
+
chatRelease,
|
|
15
18
|
chatPost,
|
|
16
19
|
chatRead,
|
|
17
20
|
chatRooms,
|
|
@@ -64,6 +67,7 @@ export type {
|
|
|
64
67
|
WakeMode,
|
|
65
68
|
ChatMember,
|
|
66
69
|
ChatMessage,
|
|
70
|
+
ChatClaimOutcome,
|
|
67
71
|
RoomSummary,
|
|
68
72
|
BuddyStatus,
|
|
69
73
|
PresenceRow,
|
|
@@ -288,6 +288,16 @@ export const REGISTRY: readonly SettingDef[] = [
|
|
|
288
288
|
"User-confirmed integration hosts (forgeHost, switchboardUrl), written only by an explicit `rt setup <id> connect --host` after that host validates a real credential. The one trusted source a credential is ever sent to — mattstack.integrations' team-declared host is shown to the user but never auto-used for a fetch.",
|
|
289
289
|
},
|
|
290
290
|
|
|
291
|
+
// --- mattstack (shared team truth) ---------------------------------------
|
|
292
|
+
{
|
|
293
|
+
key: "mattstack.roster",
|
|
294
|
+
type: "array",
|
|
295
|
+
scopes: ["team"],
|
|
296
|
+
merge: "replace",
|
|
297
|
+
description:
|
|
298
|
+
"The suite-wide team roster: [{username, name?}] GitLab usernames with optional display names. Any suite app that lists people reads this; hiding someone is the app's own overlay (e.g. boxscore.hiddenMembers).",
|
|
299
|
+
},
|
|
300
|
+
|
|
291
301
|
// --- claude (installer-lane) --------------------------------------------
|
|
292
302
|
{
|
|
293
303
|
key: "claude.marketplaces",
|
|
@@ -351,7 +361,7 @@ export const REGISTRY: readonly SettingDef[] = [
|
|
|
351
361
|
type: "array",
|
|
352
362
|
scopes: ["team"],
|
|
353
363
|
merge: "replace",
|
|
354
|
-
description: "The authors tab's roster: whose MRs the classic board lists, including hidden-by-default entries. Codeowners tabs list MRs from anyone.",
|
|
364
|
+
description: "The authors tab's roster: whose MRs the classic board lists, including hidden-by-default entries. Codeowners tabs list MRs from anyone. The cross-app roster successor is mattstack.roster; this key remains the board's own list until the board adopts it.",
|
|
355
365
|
},
|
|
356
366
|
{
|
|
357
367
|
key: "board.title",
|
|
@@ -455,13 +465,6 @@ export const REGISTRY: readonly SettingDef[] = [
|
|
|
455
465
|
merge: "deep",
|
|
456
466
|
description: "Local working directories the board's review/respond/doctor panes launch from.",
|
|
457
467
|
},
|
|
458
|
-
{
|
|
459
|
-
key: "board.rtRepos",
|
|
460
|
-
type: "array",
|
|
461
|
-
scopes: ["machine"],
|
|
462
|
-
merge: "replace",
|
|
463
|
-
description: "rt-registered repo names the board resolves MRs against on this machine.",
|
|
464
|
-
},
|
|
465
468
|
{
|
|
466
469
|
key: "board.triageMaxConcurrent",
|
|
467
470
|
type: "number",
|
|
@@ -477,6 +480,66 @@ export const REGISTRY: readonly SettingDef[] = [
|
|
|
477
480
|
description: "Local switchboard URL the board's POST /peer/join writer targets.",
|
|
478
481
|
},
|
|
479
482
|
|
|
483
|
+
// --- boxscore -------------------------------------------------------------
|
|
484
|
+
// No `default` on any boxscore row: fallbacks live in boxscore's app-side
|
|
485
|
+
// read (server/config), so an unset key resolves as absent here.
|
|
486
|
+
{
|
|
487
|
+
key: "boxscore.projects",
|
|
488
|
+
type: "array",
|
|
489
|
+
scopes: ["team"],
|
|
490
|
+
merge: "replace",
|
|
491
|
+
description: "GitLab projects boxscore scores, as full paths (\"group/project\").",
|
|
492
|
+
},
|
|
493
|
+
{
|
|
494
|
+
key: "boxscore.linearDoneStates",
|
|
495
|
+
type: "array",
|
|
496
|
+
scopes: ["team"],
|
|
497
|
+
merge: "replace",
|
|
498
|
+
description: "Linear workflow state names that count as done. Empty means the completed and canceled state types.",
|
|
499
|
+
},
|
|
500
|
+
{
|
|
501
|
+
key: "boxscore.sizeBand",
|
|
502
|
+
type: "object",
|
|
503
|
+
scopes: ["team"],
|
|
504
|
+
merge: "deep",
|
|
505
|
+
description: "MR size health band in changed lines: {tooSmall, tooLarge}. At or below tooSmall, or above tooLarge, is outside the healthy band.",
|
|
506
|
+
},
|
|
507
|
+
{
|
|
508
|
+
key: "boxscore.excludeFilePatterns",
|
|
509
|
+
type: "array",
|
|
510
|
+
scopes: ["team"],
|
|
511
|
+
merge: "replace",
|
|
512
|
+
description: "Glob patterns for files excluded from addition/deletion counts (e.g. \"**/*.json\").",
|
|
513
|
+
},
|
|
514
|
+
{
|
|
515
|
+
key: "boxscore.ignoredMrs",
|
|
516
|
+
type: "array",
|
|
517
|
+
scopes: ["team"],
|
|
518
|
+
merge: "replace",
|
|
519
|
+
description: "MRs excluded from all metrics: \"!123\" or \"group/project!123\".",
|
|
520
|
+
},
|
|
521
|
+
{
|
|
522
|
+
key: "boxscore.botPatterns",
|
|
523
|
+
type: "array",
|
|
524
|
+
scopes: ["team"],
|
|
525
|
+
merge: "replace",
|
|
526
|
+
description: "Extra regex sources treated as bot accounts, beyond boxscore's built-in detection.",
|
|
527
|
+
},
|
|
528
|
+
{
|
|
529
|
+
key: "boxscore.hiddenMembers",
|
|
530
|
+
type: "array",
|
|
531
|
+
scopes: ["user"],
|
|
532
|
+
merge: "replace",
|
|
533
|
+
description: "Usernames from mattstack.roster hidden from this developer's leaderboard.",
|
|
534
|
+
},
|
|
535
|
+
{
|
|
536
|
+
key: "boxscore.defaultRange",
|
|
537
|
+
type: "string",
|
|
538
|
+
scopes: ["user"],
|
|
539
|
+
merge: "replace",
|
|
540
|
+
description: "Default comparison window for the API and CLI when none is given: \"7d\", \"30d\", or \"90d\".",
|
|
541
|
+
},
|
|
542
|
+
|
|
480
543
|
// --- gitq ------------------------------------------------------------------
|
|
481
544
|
{
|
|
482
545
|
key: "gitq.workSlots",
|
|
@@ -521,7 +584,8 @@ export const REGISTRY: readonly SettingDef[] = [
|
|
|
521
584
|
type: "string",
|
|
522
585
|
scopes: ["user"],
|
|
523
586
|
merge: "replace",
|
|
524
|
-
|
|
587
|
+
default: "https://chat.mattstack",
|
|
588
|
+
description: "Base URL of the chat viewer, no trailing slash; rt chat post and the tail's wake lines end with a link to the room or message. Defaults to the viewer deck serves on the mattstack TLD.",
|
|
525
589
|
},
|
|
526
590
|
{
|
|
527
591
|
key: "chat.herdrWorkspace",
|