@mattstack/rt-client 0.6.0 → 0.6.2
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 +39 -0
- package/dist/client.d.ts +19 -1
- package/dist/commands.d.ts +157 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +135 -5
- package/package.json +1 -1
- package/src/client.ts +78 -1
- package/src/commands.ts +64 -2
- package/src/index.ts +17 -0
- package/src/settings/registry-defs.ts +58 -4
package/README.md
CHANGED
|
@@ -74,6 +74,45 @@ doesn't error, it resolves empty. `parseIdentity` is strict — only strings
|
|
|
74
74
|
`serializeIdentity` emitted parse — so validate payloads with it, and never
|
|
75
75
|
hand-assemble or string-split a wire.
|
|
76
76
|
|
|
77
|
+
## Chat
|
|
78
|
+
|
|
79
|
+
The `rt chat` surface the chat viewer (`~/Documents/GitHub/chat`) is built
|
|
80
|
+
on. Every call degrades to `{ ok: false, error }` instead of throwing, and a
|
|
81
|
+
daemon that is down and a daemon that refused look the same to the caller;
|
|
82
|
+
branch on `ok`, not on exceptions.
|
|
83
|
+
|
|
84
|
+
```ts
|
|
85
|
+
import { chatRooms, chatMessages, chatPost, createRelay, daemonHealth } from '@mattstack/rt-client';
|
|
86
|
+
|
|
87
|
+
const rooms = await chatRooms({ handle: 'matt' }); // { ok, data: { rooms } }
|
|
88
|
+
const page = await chatMessages({ room: 'build', limit: 50 }); // newest page; `before: <id>` pages older
|
|
89
|
+
await chatPost({ handle: 'matt', room: 'build', body: 'on it' });
|
|
90
|
+
|
|
91
|
+
const health = await daemonHealth(); // { reachable, error? }, never throws
|
|
92
|
+
const stop = createRelay({ // one daemon subscription, republished
|
|
93
|
+
match: t => t.startsWith('chat/'), // `chat/<room>/msg`, `chat/wake/<handle>`
|
|
94
|
+
topic: 'chat',
|
|
95
|
+
publish: (topic, data) => server.publish(topic, data),
|
|
96
|
+
});
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
| Function | Daemon verb |
|
|
100
|
+
| --- | --- |
|
|
101
|
+
| `chatSignIn` / `chatSignOut` / `chatAway` / `chatBack` / `chatPulse` | presence: the buddy-list row and its heartbeats |
|
|
102
|
+
| `chatBuddies` / `chatWho` / `chatRooms` | the roster, one room's members, a handle's rooms |
|
|
103
|
+
| `chatJoin` / `chatLeave` | membership (`wakeOn: mention \| all \| none`) |
|
|
104
|
+
| `chatPost` / `chatDm` / `chatRead` / `chatMessages` / `chatMark` | messages: post, DM, read-and-advance, page, advance the cursor |
|
|
105
|
+
| `chatArm` / `chatTouch` / `chatDisarm` / `chatUnreadWaking` | the tail's wake protocol; the CLI's `rt chat tail` uses these |
|
|
106
|
+
| `paneList` / `panePeek` / `paneSpawn` / `paneAccounts` / `paneDirectories` | herdr panes: list with presence joined, peek a screen, start claude in a tab, cswap accounts, directory suggestions |
|
|
107
|
+
| `chatInvite` | type `/chat:join <room>` into a pane; `accepted`, `queued` or `refused` |
|
|
108
|
+
| `createRelay` / `subscribe` | the event stream; `daemonHealth` the reachability probe |
|
|
109
|
+
|
|
110
|
+
Pass `{ sockPath }` as the trailing options to reach a non-default daemon
|
|
111
|
+
socket. The verbs, their payloads and the wake protocol are specified in
|
|
112
|
+
repo-tools `docs/superpowers/specs/2026-08-23-rt-chat-design.md` and
|
|
113
|
+
`2026-08-24-rt-chat-presence-design.md`; the agent-facing rules are
|
|
114
|
+
`skills/rt-chat/SKILL.md`.
|
|
115
|
+
|
|
77
116
|
## License
|
|
78
117
|
|
|
79
118
|
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 } from "./commands.ts";
|
|
2
|
+
import type { DemandDecl, ProjectMRsData, DiscussionsData, MrByBranchData, BranchEnrichment, ForgeSlug, ForgeTokenData, RunSummary, RunDetail, WakeMode, ChatMember, ChatMessage, 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
|
|
@@ -102,6 +102,7 @@ export declare function chatArm(a: {
|
|
|
102
102
|
}, o?: RtClientOptions): Promise<RtResponse<Record<string, never>>>;
|
|
103
103
|
export declare function chatTouch(a: {
|
|
104
104
|
handle: string;
|
|
105
|
+
room?: string;
|
|
105
106
|
sessionId?: string;
|
|
106
107
|
}, o?: RtClientOptions): Promise<RtResponse<Record<string, never>>>;
|
|
107
108
|
export declare function chatDisarm(a: {
|
|
@@ -173,3 +174,20 @@ export declare function chatDm(a: {
|
|
|
173
174
|
export declare function eventsHead(o?: RtClientOptions): Promise<RtResponse<{
|
|
174
175
|
cursor: number;
|
|
175
176
|
}>>;
|
|
177
|
+
export declare function agentStart(a: Commands["agent:start"]["payload"], o?: RtClientOptions): Promise<RtResponse<AgentRecord>>;
|
|
178
|
+
export declare function agentResume(a: Commands["agent:resume"]["payload"], o?: RtClientOptions): Promise<RtResponse<AgentRecord>>;
|
|
179
|
+
export declare function agentGet(a: {
|
|
180
|
+
id: string;
|
|
181
|
+
}, o?: RtClientOptions): Promise<RtResponse<AgentRecord>>;
|
|
182
|
+
export declare function agentList(a: {
|
|
183
|
+
repo?: string;
|
|
184
|
+
}, o?: RtClientOptions): Promise<RtResponse<{
|
|
185
|
+
agents: AgentRecord[];
|
|
186
|
+
}>>;
|
|
187
|
+
export declare function paneList(o?: RtClientOptions): Promise<RtResponse<Commands["pane:list"]["data"]>>;
|
|
188
|
+
export declare function panePeek(a: Commands["pane:peek"]["payload"], o?: RtClientOptions): Promise<RtResponse<Commands["pane:peek"]["data"]>>;
|
|
189
|
+
/** The spawn waits on claude starting, so its budget is minutes, not seconds. */
|
|
190
|
+
export declare function paneSpawn(a: Commands["pane:spawn"]["payload"], o?: RtClientOptions): Promise<RtResponse<Commands["pane:spawn"]["data"]>>;
|
|
191
|
+
export declare function paneAccounts(o?: RtClientOptions): Promise<RtResponse<Commands["pane:accounts"]["data"]>>;
|
|
192
|
+
export declare function paneDirectories(a: Commands["pane:directories"]["payload"], o?: RtClientOptions): Promise<RtResponse<Commands["pane:directories"]["data"]>>;
|
|
193
|
+
export declare function chatInvite(a: Commands["chat:invite"]["payload"], o?: RtClientOptions): Promise<RtResponse<Commands["chat:invite"]["data"]>>;
|
package/dist/commands.d.ts
CHANGED
|
@@ -10,17 +10,24 @@ export type Discussion = MRDetail["discussions"][number];
|
|
|
10
10
|
export interface DemandDecl {
|
|
11
11
|
client: string;
|
|
12
12
|
authors: string[];
|
|
13
|
+
/** Codeowner sections this client needs covered (spec: second demand axis). */
|
|
14
|
+
codeownerSections?: string[];
|
|
13
15
|
declaredAt: number;
|
|
14
16
|
}
|
|
15
17
|
export interface ProjectMRsScope {
|
|
16
18
|
authors: string[];
|
|
17
19
|
windowDays: number;
|
|
18
20
|
uncovered: string[];
|
|
21
|
+
/** Effective synced section union; absent from a pre-sections daemon. */
|
|
22
|
+
sections?: string[];
|
|
23
|
+
/** Demanded sections not yet swept for this client. */
|
|
24
|
+
uncoveredSections?: string[];
|
|
19
25
|
}
|
|
20
26
|
export interface ProjectMRsData {
|
|
21
27
|
mrs: Record<string, {
|
|
22
28
|
pr: PullRequest;
|
|
23
29
|
fetchedAt: number;
|
|
30
|
+
codeownerSections?: string[];
|
|
24
31
|
}>;
|
|
25
32
|
listSyncedAt: number;
|
|
26
33
|
source: "poll" | "events" | "mutation";
|
|
@@ -144,6 +151,39 @@ export interface PresenceRow {
|
|
|
144
151
|
armedAt?: number;
|
|
145
152
|
signedOutAt?: number;
|
|
146
153
|
}
|
|
154
|
+
export type AgentStatus = "idle" | "working" | "blocked" | "done" | "unknown";
|
|
155
|
+
/** Duplicated shape on purpose (see EventsBusEvent above): mirrors the daemon's pane row, which rt-client cannot import. */
|
|
156
|
+
export interface ChatPane {
|
|
157
|
+
paneId: string;
|
|
158
|
+
workspace: string;
|
|
159
|
+
title?: string;
|
|
160
|
+
cwd?: string;
|
|
161
|
+
repo?: string;
|
|
162
|
+
branch?: string;
|
|
163
|
+
agentStatus: AgentStatus;
|
|
164
|
+
sessionId?: string;
|
|
165
|
+
presence?: {
|
|
166
|
+
handle: string;
|
|
167
|
+
status: BuddyStatus;
|
|
168
|
+
rooms: string[];
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
export interface PaneAccount {
|
|
172
|
+
slot: number;
|
|
173
|
+
email: string;
|
|
174
|
+
alias?: string;
|
|
175
|
+
headroom?: string;
|
|
176
|
+
}
|
|
177
|
+
export interface PaneDirectory {
|
|
178
|
+
path: string;
|
|
179
|
+
repo: string;
|
|
180
|
+
branch?: string;
|
|
181
|
+
}
|
|
182
|
+
export interface InviteResult {
|
|
183
|
+
paneId: string;
|
|
184
|
+
delivered: "accepted" | "queued" | "refused";
|
|
185
|
+
reason?: string;
|
|
186
|
+
}
|
|
147
187
|
export type Attention = {
|
|
148
188
|
needs: boolean;
|
|
149
189
|
reason: "failed" | "stale" | "stranded" | "blocked" | null;
|
|
@@ -216,6 +256,29 @@ export interface RunDetail {
|
|
|
216
256
|
decisions: RunDecisionRow[];
|
|
217
257
|
schemaAhead: boolean;
|
|
218
258
|
}
|
|
259
|
+
export type AgentSurface = "herdr" | "headless";
|
|
260
|
+
export interface AgentRecord {
|
|
261
|
+
id: string;
|
|
262
|
+
repo: string;
|
|
263
|
+
cwd: string;
|
|
264
|
+
provider: string;
|
|
265
|
+
surface: AgentSurface;
|
|
266
|
+
sessionId: string;
|
|
267
|
+
model?: string;
|
|
268
|
+
effort?: string;
|
|
269
|
+
account?: string;
|
|
270
|
+
label?: string;
|
|
271
|
+
caller?: string;
|
|
272
|
+
paneId?: string;
|
|
273
|
+
tabId?: string;
|
|
274
|
+
workspaceId?: string;
|
|
275
|
+
extraArgs?: string;
|
|
276
|
+
exitCode?: number;
|
|
277
|
+
resultPath?: string;
|
|
278
|
+
createdAt: number;
|
|
279
|
+
lastResumedAt?: number;
|
|
280
|
+
finishedAt?: number;
|
|
281
|
+
}
|
|
219
282
|
export interface Commands {
|
|
220
283
|
"project-mrs:read": {
|
|
221
284
|
payload: {
|
|
@@ -449,6 +512,7 @@ export interface Commands {
|
|
|
449
512
|
"chat:touch": {
|
|
450
513
|
payload: {
|
|
451
514
|
handle: string;
|
|
515
|
+
room?: string;
|
|
452
516
|
sessionId?: string;
|
|
453
517
|
};
|
|
454
518
|
data: Record<string, never>;
|
|
@@ -547,6 +611,99 @@ export interface Commands {
|
|
|
547
611
|
recipients: string[];
|
|
548
612
|
};
|
|
549
613
|
};
|
|
614
|
+
"agent:start": {
|
|
615
|
+
payload: {
|
|
616
|
+
repo: string;
|
|
617
|
+
cwd: string;
|
|
618
|
+
prompt?: string;
|
|
619
|
+
surface?: AgentSurface;
|
|
620
|
+
model?: string;
|
|
621
|
+
effort?: string;
|
|
622
|
+
account?: string;
|
|
623
|
+
label?: string;
|
|
624
|
+
caller?: string;
|
|
625
|
+
workspace?: string;
|
|
626
|
+
tab?: string;
|
|
627
|
+
extraArgs?: string;
|
|
628
|
+
};
|
|
629
|
+
data: AgentRecord;
|
|
630
|
+
};
|
|
631
|
+
"agent:resume": {
|
|
632
|
+
payload: {
|
|
633
|
+
id: string;
|
|
634
|
+
prompt?: string;
|
|
635
|
+
surface?: AgentSurface;
|
|
636
|
+
};
|
|
637
|
+
data: AgentRecord;
|
|
638
|
+
};
|
|
639
|
+
"agent:get": {
|
|
640
|
+
payload: {
|
|
641
|
+
id: string;
|
|
642
|
+
};
|
|
643
|
+
data: AgentRecord;
|
|
644
|
+
};
|
|
645
|
+
"agent:list": {
|
|
646
|
+
payload: {
|
|
647
|
+
repo?: string;
|
|
648
|
+
};
|
|
649
|
+
data: {
|
|
650
|
+
agents: AgentRecord[];
|
|
651
|
+
};
|
|
652
|
+
};
|
|
653
|
+
"chat:invite": {
|
|
654
|
+
payload: {
|
|
655
|
+
paneId: string;
|
|
656
|
+
room: string;
|
|
657
|
+
note?: string;
|
|
658
|
+
from: string;
|
|
659
|
+
callerPane?: string;
|
|
660
|
+
};
|
|
661
|
+
data: InviteResult;
|
|
662
|
+
};
|
|
663
|
+
"pane:list": {
|
|
664
|
+
payload: Record<string, never>;
|
|
665
|
+
data: {
|
|
666
|
+
panes: ChatPane[];
|
|
667
|
+
};
|
|
668
|
+
};
|
|
669
|
+
"pane:peek": {
|
|
670
|
+
payload: {
|
|
671
|
+
paneId: string;
|
|
672
|
+
lines?: number;
|
|
673
|
+
};
|
|
674
|
+
data: {
|
|
675
|
+
paneId: string;
|
|
676
|
+
lines: string[];
|
|
677
|
+
};
|
|
678
|
+
};
|
|
679
|
+
"pane:accounts": {
|
|
680
|
+
payload: Record<string, never>;
|
|
681
|
+
data: {
|
|
682
|
+
accounts: PaneAccount[];
|
|
683
|
+
};
|
|
684
|
+
};
|
|
685
|
+
"pane:directories": {
|
|
686
|
+
payload: {
|
|
687
|
+
q?: string;
|
|
688
|
+
};
|
|
689
|
+
data: {
|
|
690
|
+
directories: PaneDirectory[];
|
|
691
|
+
};
|
|
692
|
+
};
|
|
693
|
+
"pane:spawn": {
|
|
694
|
+
payload: {
|
|
695
|
+
cwd: string;
|
|
696
|
+
account?: string;
|
|
697
|
+
model?: string;
|
|
698
|
+
effort?: string;
|
|
699
|
+
prompt?: string;
|
|
700
|
+
workspace?: string;
|
|
701
|
+
};
|
|
702
|
+
data: {
|
|
703
|
+
pane: ChatPane;
|
|
704
|
+
ready: boolean;
|
|
705
|
+
};
|
|
706
|
+
};
|
|
550
707
|
}
|
|
551
708
|
export type CommandName = keyof Commands;
|
|
552
709
|
export declare const COMMAND_NAMES: readonly CommandName[];
|
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, chatArm, chatTouch, chatDisarm, chatUnreadWaking, chatSignIn, chatSignOut, chatAway, chatBack, chatBuddies, chatPulse, chatDm, eventsHead, } from "./client.ts";
|
|
3
|
+
export { readProjectMRs, readDiscussions, readMrsByBranch, readBranchCache, resolveForgeToken, listRuns, getRun, abandonRun, chatJoin, chatLeave, chatPost, chatRead, chatRooms, chatWho, chatMark, chatMessages, chatArm, chatTouch, chatDisarm, chatUnreadWaking, chatSignIn, chatSignOut, chatAway, chatBack, chatBuddies, chatPulse, chatDm, eventsHead, agentStart, agentResume, agentGet, agentList, paneList, panePeek, paneSpawn, paneAccounts, paneDirectories, chatInvite, } 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, } 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, } 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
|
@@ -124,6 +124,8 @@ function chatArm(a, o = {}) {
|
|
|
124
124
|
}
|
|
125
125
|
function chatTouch(a, o = {}) {
|
|
126
126
|
const payload = { handle: a.handle };
|
|
127
|
+
if (a.room !== undefined)
|
|
128
|
+
payload.room = a.room;
|
|
127
129
|
if (a.sessionId !== undefined)
|
|
128
130
|
payload.sessionId = a.sessionId;
|
|
129
131
|
return rtCommand("chat:touch", payload, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 1e4 });
|
|
@@ -187,6 +189,64 @@ function chatDm(a, o = {}) {
|
|
|
187
189
|
function eventsHead(o = {}) {
|
|
188
190
|
return rtCommand("events:head", {}, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 1e4 });
|
|
189
191
|
}
|
|
192
|
+
function agentStart(a, o = {}) {
|
|
193
|
+
const payload = { repo: a.repo, cwd: a.cwd };
|
|
194
|
+
for (const k of ["prompt", "surface", "model", "effort", "account", "label", "caller", "workspace", "tab", "extraArgs"]) {
|
|
195
|
+
if (a[k] !== undefined)
|
|
196
|
+
payload[k] = a[k];
|
|
197
|
+
}
|
|
198
|
+
return rtCommand("agent:start", payload, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 30000 });
|
|
199
|
+
}
|
|
200
|
+
function agentResume(a, o = {}) {
|
|
201
|
+
const payload = { id: a.id };
|
|
202
|
+
if (a.prompt !== undefined)
|
|
203
|
+
payload.prompt = a.prompt;
|
|
204
|
+
if (a.surface !== undefined)
|
|
205
|
+
payload.surface = a.surface;
|
|
206
|
+
return rtCommand("agent:resume", payload, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 30000 });
|
|
207
|
+
}
|
|
208
|
+
function agentGet(a, o = {}) {
|
|
209
|
+
return rtCommand("agent:get", { id: a.id }, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 1e4 });
|
|
210
|
+
}
|
|
211
|
+
function agentList(a, o = {}) {
|
|
212
|
+
const payload = {};
|
|
213
|
+
if (a.repo !== undefined)
|
|
214
|
+
payload.repo = a.repo;
|
|
215
|
+
return rtCommand("agent:list", payload, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 1e4 });
|
|
216
|
+
}
|
|
217
|
+
function paneList(o = {}) {
|
|
218
|
+
return rtCommand("pane:list", {}, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 1e4 });
|
|
219
|
+
}
|
|
220
|
+
function panePeek(a, o = {}) {
|
|
221
|
+
const payload = { paneId: a.paneId };
|
|
222
|
+
if (a.lines !== undefined)
|
|
223
|
+
payload.lines = a.lines;
|
|
224
|
+
return rtCommand("pane:peek", payload, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 1e4 });
|
|
225
|
+
}
|
|
226
|
+
function paneSpawn(a, o = {}) {
|
|
227
|
+
const payload = { cwd: a.cwd };
|
|
228
|
+
for (const k of ["account", "model", "effort", "prompt", "workspace"])
|
|
229
|
+
if (a[k] !== undefined)
|
|
230
|
+
payload[k] = a[k];
|
|
231
|
+
return rtCommand("pane:spawn", payload, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 90000 });
|
|
232
|
+
}
|
|
233
|
+
function paneAccounts(o = {}) {
|
|
234
|
+
return rtCommand("pane:accounts", {}, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 1e4 });
|
|
235
|
+
}
|
|
236
|
+
function paneDirectories(a, o = {}) {
|
|
237
|
+
const payload = {};
|
|
238
|
+
if (a.q !== undefined)
|
|
239
|
+
payload.q = a.q;
|
|
240
|
+
return rtCommand("pane:directories", payload, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 1e4 });
|
|
241
|
+
}
|
|
242
|
+
function chatInvite(a, o = {}) {
|
|
243
|
+
const payload = { paneId: a.paneId, room: a.room, from: a.from };
|
|
244
|
+
if (a.note !== undefined)
|
|
245
|
+
payload.note = a.note;
|
|
246
|
+
if (a.callerPane !== undefined)
|
|
247
|
+
payload.callerPane = a.callerPane;
|
|
248
|
+
return rtCommand("chat:invite", payload, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 30000 });
|
|
249
|
+
}
|
|
190
250
|
// src/commands.ts
|
|
191
251
|
var COMMAND_NAMES = [
|
|
192
252
|
"project-mrs:read",
|
|
@@ -219,7 +279,17 @@ var COMMAND_NAMES = [
|
|
|
219
279
|
"chat:back",
|
|
220
280
|
"chat:buddies",
|
|
221
281
|
"chat:pulse",
|
|
222
|
-
"chat:dm"
|
|
282
|
+
"chat:dm",
|
|
283
|
+
"agent:start",
|
|
284
|
+
"agent:resume",
|
|
285
|
+
"agent:get",
|
|
286
|
+
"agent:list",
|
|
287
|
+
"chat:invite",
|
|
288
|
+
"pane:list",
|
|
289
|
+
"pane:peek",
|
|
290
|
+
"pane:accounts",
|
|
291
|
+
"pane:directories",
|
|
292
|
+
"pane:spawn"
|
|
223
293
|
];
|
|
224
294
|
// src/relay.ts
|
|
225
295
|
var DEFAULT_WS_URL = "ws://127.0.0.1:9401/ws";
|
|
@@ -659,7 +729,7 @@ var REGISTRY = [
|
|
|
659
729
|
type: "array",
|
|
660
730
|
scopes: ["team"],
|
|
661
731
|
merge: "replace",
|
|
662
|
-
description: "The
|
|
732
|
+
description: "The authors tab's roster: whose MRs the classic board lists, including hidden-by-default entries. Codeowners tabs list MRs from anyone."
|
|
663
733
|
},
|
|
664
734
|
{
|
|
665
735
|
key: "board.title",
|
|
@@ -680,14 +750,14 @@ var REGISTRY = [
|
|
|
680
750
|
type: "array",
|
|
681
751
|
scopes: ["team"],
|
|
682
752
|
merge: "replace",
|
|
683
|
-
description: "Ticket key prefixes (e.g. RT, MAT) the
|
|
753
|
+
description: "Ticket key prefixes (e.g. RT, MAT) that keep the authors tab to the team's own tickets and link out to Linear from an MR title; rows on a codeowners tab pass regardless of prefix."
|
|
684
754
|
},
|
|
685
755
|
{
|
|
686
756
|
key: "board.slack",
|
|
687
757
|
type: "object",
|
|
688
758
|
scopes: ["team"],
|
|
689
759
|
merge: "deep",
|
|
690
|
-
description: "The board's Slack posting config (app id, client id, channel, callback port);
|
|
760
|
+
description: "The board's Slack posting config (app id, client id, channel, callback port); channel is the default that a tab's slackChannel overrides per MR. Client secrets stay out of this store."
|
|
691
761
|
},
|
|
692
762
|
{
|
|
693
763
|
key: "board.doctorSkill",
|
|
@@ -703,6 +773,13 @@ var REGISTRY = [
|
|
|
703
773
|
merge: "replace",
|
|
704
774
|
description: "Doctor skill the board's own API-tier triage sweep runs on your MRs; deliberately never resolved through a repo's skills.jsonc manifest. A sibling flat key of board.triage, not a field inside it — the board reader assembles the two independently."
|
|
705
775
|
},
|
|
776
|
+
{
|
|
777
|
+
key: "board.tabs",
|
|
778
|
+
type: "array",
|
|
779
|
+
scopes: ["team"],
|
|
780
|
+
merge: "replace",
|
|
781
|
+
description: "Board tabs ({id, label, source, slackChannel?, reviewSkill?}), editable from the board's settings modal. source.kind 'authors' is the classic roster board; 'codeowners' lists MRs from any author blocked on an unapproved CODEOWNERS section. Absent = one implicit authors tab (fallback lives in the board reader, never here)."
|
|
782
|
+
},
|
|
706
783
|
{
|
|
707
784
|
key: "board.staleAfterDays",
|
|
708
785
|
type: "number",
|
|
@@ -729,7 +806,7 @@ var REGISTRY = [
|
|
|
729
806
|
type: "array",
|
|
730
807
|
scopes: ["user"],
|
|
731
808
|
merge: "replace",
|
|
732
|
-
description: "Usernames this developer hides from the
|
|
809
|
+
description: "Usernames this developer hides from the authors tab's board.members roster; overlays the team truth without editing it."
|
|
733
810
|
},
|
|
734
811
|
{
|
|
735
812
|
key: "board.triage",
|
|
@@ -809,6 +886,21 @@ var REGISTRY = [
|
|
|
809
886
|
merge: "replace",
|
|
810
887
|
description: "The human's own chat handle, so agents can @-mention them by name."
|
|
811
888
|
},
|
|
889
|
+
{
|
|
890
|
+
key: "chat.viewerUrl",
|
|
891
|
+
type: "string",
|
|
892
|
+
scopes: ["user"],
|
|
893
|
+
merge: "replace",
|
|
894
|
+
description: "Base URL of the chat viewer, no trailing slash. When set, rt chat post and the tail's wake lines end with a link to the room or message."
|
|
895
|
+
},
|
|
896
|
+
{
|
|
897
|
+
key: "chat.herdrWorkspace",
|
|
898
|
+
type: "string",
|
|
899
|
+
scopes: ["user"],
|
|
900
|
+
default: "chat",
|
|
901
|
+
merge: "replace",
|
|
902
|
+
description: "herdr workspace label that rt pane spawn opens new agent tabs in; created when missing."
|
|
903
|
+
},
|
|
812
904
|
{
|
|
813
905
|
key: "chat.push.provider",
|
|
814
906
|
type: "string",
|
|
@@ -822,6 +914,34 @@ var REGISTRY = [
|
|
|
822
914
|
scopes: ["user"],
|
|
823
915
|
merge: "replace",
|
|
824
916
|
description: "Destination (topic/URL/token) the configured chat.push.provider sends to."
|
|
917
|
+
},
|
|
918
|
+
{
|
|
919
|
+
key: "agent.model",
|
|
920
|
+
type: "string",
|
|
921
|
+
scopes: ["user", "machine"],
|
|
922
|
+
merge: "replace",
|
|
923
|
+
description: "Default --model for rt agent launches; unset omits the flag."
|
|
924
|
+
},
|
|
925
|
+
{
|
|
926
|
+
key: "agent.effort",
|
|
927
|
+
type: "string",
|
|
928
|
+
scopes: ["user", "machine"],
|
|
929
|
+
merge: "replace",
|
|
930
|
+
description: "Default --effort for rt agent launches; unset omits the flag."
|
|
931
|
+
},
|
|
932
|
+
{
|
|
933
|
+
key: "agent.account",
|
|
934
|
+
type: "string",
|
|
935
|
+
scopes: ["user", "machine"],
|
|
936
|
+
merge: "replace",
|
|
937
|
+
description: "cswap account email rt agent launches under; unset uses the default claude profile."
|
|
938
|
+
},
|
|
939
|
+
{
|
|
940
|
+
key: "agent.extraArgs",
|
|
941
|
+
type: "string",
|
|
942
|
+
scopes: ["user", "machine"],
|
|
943
|
+
merge: "replace",
|
|
944
|
+
description: "Opaque extra claude arguments appended to every rt agent launch (escape hatch)."
|
|
825
945
|
}
|
|
826
946
|
];
|
|
827
947
|
|
|
@@ -1617,6 +1737,11 @@ export {
|
|
|
1617
1737
|
readDiscussions,
|
|
1618
1738
|
readBranchCache,
|
|
1619
1739
|
parseIdentity,
|
|
1740
|
+
paneSpawn,
|
|
1741
|
+
panePeek,
|
|
1742
|
+
paneList,
|
|
1743
|
+
paneDirectories,
|
|
1744
|
+
paneAccounts,
|
|
1620
1745
|
normalizeRemote,
|
|
1621
1746
|
listTeams,
|
|
1622
1747
|
listSettings,
|
|
@@ -1646,6 +1771,7 @@ export {
|
|
|
1646
1771
|
chatMark,
|
|
1647
1772
|
chatLeave,
|
|
1648
1773
|
chatJoin,
|
|
1774
|
+
chatInvite,
|
|
1649
1775
|
chatDm,
|
|
1650
1776
|
chatDisarm,
|
|
1651
1777
|
chatBuddies,
|
|
@@ -1653,6 +1779,10 @@ export {
|
|
|
1653
1779
|
chatAway,
|
|
1654
1780
|
chatArm,
|
|
1655
1781
|
allDefs,
|
|
1782
|
+
agentStart,
|
|
1783
|
+
agentResume,
|
|
1784
|
+
agentList,
|
|
1785
|
+
agentGet,
|
|
1656
1786
|
abandonRun,
|
|
1657
1787
|
SCOPE_ORDER,
|
|
1658
1788
|
REGISTRY,
|
package/package.json
CHANGED
package/src/client.ts
CHANGED
|
@@ -21,6 +21,8 @@ import type {
|
|
|
21
21
|
RoomSummary,
|
|
22
22
|
BuddyStatus,
|
|
23
23
|
PresenceRow,
|
|
24
|
+
AgentRecord,
|
|
25
|
+
Commands,
|
|
24
26
|
} from "./commands.ts";
|
|
25
27
|
|
|
26
28
|
/**
|
|
@@ -227,10 +229,11 @@ export function chatArm(
|
|
|
227
229
|
}
|
|
228
230
|
|
|
229
231
|
export function chatTouch(
|
|
230
|
-
a: { handle: string; sessionId?: string },
|
|
232
|
+
a: { handle: string; room?: string; sessionId?: string },
|
|
231
233
|
o: RtClientOptions = {},
|
|
232
234
|
): Promise<RtResponse<Record<string, never>>> {
|
|
233
235
|
const payload: Record<string, unknown> = { handle: a.handle };
|
|
236
|
+
if (a.room !== undefined) payload.room = a.room;
|
|
234
237
|
if (a.sessionId !== undefined) payload.sessionId = a.sessionId;
|
|
235
238
|
return rtCommand<Record<string, never>>("chat:touch", payload, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 10_000 });
|
|
236
239
|
}
|
|
@@ -323,3 +326,77 @@ export function chatDm(
|
|
|
323
326
|
export function eventsHead(o: RtClientOptions = {}): Promise<RtResponse<{ cursor: number }>> {
|
|
324
327
|
return rtCommand<{ cursor: number }>("events:head", {}, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 10_000 });
|
|
325
328
|
}
|
|
329
|
+
|
|
330
|
+
// ─── Agent handoff (rt agent) ─────────────────────────────────────────────
|
|
331
|
+
|
|
332
|
+
export function agentStart(
|
|
333
|
+
a: Commands["agent:start"]["payload"], o: RtClientOptions = {},
|
|
334
|
+
): Promise<RtResponse<AgentRecord>> {
|
|
335
|
+
const payload: Record<string, unknown> = { repo: a.repo, cwd: a.cwd };
|
|
336
|
+
for (const k of ["prompt", "surface", "model", "effort", "account", "label", "caller", "workspace", "tab", "extraArgs"] as const) {
|
|
337
|
+
if (a[k] !== undefined) payload[k] = a[k];
|
|
338
|
+
}
|
|
339
|
+
return rtCommand<AgentRecord>("agent:start", payload, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 30_000 });
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
export function agentResume(
|
|
343
|
+
a: Commands["agent:resume"]["payload"], o: RtClientOptions = {},
|
|
344
|
+
): Promise<RtResponse<AgentRecord>> {
|
|
345
|
+
const payload: Record<string, unknown> = { id: a.id };
|
|
346
|
+
if (a.prompt !== undefined) payload.prompt = a.prompt;
|
|
347
|
+
if (a.surface !== undefined) payload.surface = a.surface;
|
|
348
|
+
return rtCommand<AgentRecord>("agent:resume", payload, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 30_000 });
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
export function agentGet(a: { id: string }, o: RtClientOptions = {}): Promise<RtResponse<AgentRecord>> {
|
|
352
|
+
return rtCommand<AgentRecord>("agent:get", { id: a.id }, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 10_000 });
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
export function agentList(a: { repo?: string }, o: RtClientOptions = {}): Promise<RtResponse<{ agents: AgentRecord[] }>> {
|
|
356
|
+
const payload: Record<string, unknown> = {};
|
|
357
|
+
if (a.repo !== undefined) payload.repo = a.repo;
|
|
358
|
+
return rtCommand<{ agents: AgentRecord[] }>("agent:list", payload, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 10_000 });
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
// ─── Panes (rt chat invite) ────────────────────────────────────────────────
|
|
362
|
+
// herdr-facing verbs; the daemon answers `herdr unavailable` without herdr.
|
|
363
|
+
|
|
364
|
+
export function paneList(o: RtClientOptions = {}): Promise<RtResponse<Commands["pane:list"]["data"]>> {
|
|
365
|
+
return rtCommand<Commands["pane:list"]["data"]>("pane:list", {}, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 10_000 });
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
export function panePeek(a: Commands["pane:peek"]["payload"], o: RtClientOptions = {}): Promise<RtResponse<Commands["pane:peek"]["data"]>> {
|
|
369
|
+
const payload: Record<string, unknown> = { paneId: a.paneId };
|
|
370
|
+
if (a.lines !== undefined) payload.lines = a.lines;
|
|
371
|
+
return rtCommand<Commands["pane:peek"]["data"]>("pane:peek", payload, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 10_000 });
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
/** The spawn waits on claude starting, so its budget is minutes, not seconds. */
|
|
375
|
+
export function paneSpawn(
|
|
376
|
+
a: Commands["pane:spawn"]["payload"],
|
|
377
|
+
o: RtClientOptions = {},
|
|
378
|
+
): Promise<RtResponse<Commands["pane:spawn"]["data"]>> {
|
|
379
|
+
const payload: Record<string, unknown> = { cwd: a.cwd };
|
|
380
|
+
for (const k of ["account", "model", "effort", "prompt", "workspace"] as const) if (a[k] !== undefined) payload[k] = a[k];
|
|
381
|
+
return rtCommand<Commands["pane:spawn"]["data"]>("pane:spawn", payload, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 90_000 });
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
export function paneAccounts(o: RtClientOptions = {}): Promise<RtResponse<Commands["pane:accounts"]["data"]>> {
|
|
385
|
+
return rtCommand<Commands["pane:accounts"]["data"]>("pane:accounts", {}, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 10_000 });
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
export function paneDirectories(a: Commands["pane:directories"]["payload"], o: RtClientOptions = {}): Promise<RtResponse<Commands["pane:directories"]["data"]>> {
|
|
389
|
+
const payload: Record<string, unknown> = {};
|
|
390
|
+
if (a.q !== undefined) payload.q = a.q;
|
|
391
|
+
return rtCommand<Commands["pane:directories"]["data"]>("pane:directories", payload, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 10_000 });
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
export function chatInvite(
|
|
395
|
+
a: Commands["chat:invite"]["payload"],
|
|
396
|
+
o: RtClientOptions = {},
|
|
397
|
+
): Promise<RtResponse<Commands["chat:invite"]["data"]>> {
|
|
398
|
+
const payload: Record<string, unknown> = { paneId: a.paneId, room: a.room, from: a.from };
|
|
399
|
+
if (a.note !== undefined) payload.note = a.note;
|
|
400
|
+
if (a.callerPane !== undefined) payload.callerPane = a.callerPane;
|
|
401
|
+
return rtCommand<Commands["chat:invite"]["data"]>("chat:invite", payload, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 30_000 });
|
|
402
|
+
}
|
package/src/commands.ts
CHANGED
|
@@ -12,6 +12,8 @@ export type Discussion = MRDetail["discussions"][number];
|
|
|
12
12
|
export interface DemandDecl {
|
|
13
13
|
client: string;
|
|
14
14
|
authors: string[];
|
|
15
|
+
/** Codeowner sections this client needs covered (spec: second demand axis). */
|
|
16
|
+
codeownerSections?: string[];
|
|
15
17
|
declaredAt: number;
|
|
16
18
|
}
|
|
17
19
|
|
|
@@ -19,10 +21,14 @@ export interface ProjectMRsScope {
|
|
|
19
21
|
authors: string[];
|
|
20
22
|
windowDays: number;
|
|
21
23
|
uncovered: string[];
|
|
24
|
+
/** Effective synced section union; absent from a pre-sections daemon. */
|
|
25
|
+
sections?: string[];
|
|
26
|
+
/** Demanded sections not yet swept for this client. */
|
|
27
|
+
uncoveredSections?: string[];
|
|
22
28
|
}
|
|
23
29
|
|
|
24
30
|
export interface ProjectMRsData {
|
|
25
|
-
mrs: Record<string, { pr: PullRequest; fetchedAt: number }>;
|
|
31
|
+
mrs: Record<string, { pr: PullRequest; fetchedAt: number; codeownerSections?: string[] }>;
|
|
26
32
|
listSyncedAt: number;
|
|
27
33
|
source: "poll" | "events" | "mutation";
|
|
28
34
|
syncedAt: number;
|
|
@@ -140,6 +146,25 @@ export interface PresenceRow {
|
|
|
140
146
|
signedOutAt?: number;
|
|
141
147
|
}
|
|
142
148
|
|
|
149
|
+
export type AgentStatus = "idle" | "working" | "blocked" | "done" | "unknown";
|
|
150
|
+
|
|
151
|
+
/** Duplicated shape on purpose (see EventsBusEvent above): mirrors the daemon's pane row, which rt-client cannot import. */
|
|
152
|
+
export interface ChatPane {
|
|
153
|
+
paneId: string;
|
|
154
|
+
workspace: string;
|
|
155
|
+
title?: string;
|
|
156
|
+
cwd?: string;
|
|
157
|
+
repo?: string;
|
|
158
|
+
branch?: string;
|
|
159
|
+
agentStatus: AgentStatus;
|
|
160
|
+
sessionId?: string;
|
|
161
|
+
presence?: { handle: string; status: BuddyStatus; rooms: string[] };
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
export interface PaneAccount { slot: number; email: string; alias?: string; headroom?: string }
|
|
165
|
+
export interface PaneDirectory { path: string; repo: string; branch?: string }
|
|
166
|
+
export interface InviteResult { paneId: string; delivered: "accepted" | "queued" | "refused"; reason?: string }
|
|
167
|
+
|
|
143
168
|
// SKILLS-53: one judgment, computed once in rt, so the console and the tray
|
|
144
169
|
// never derive two verdicts that can disagree.
|
|
145
170
|
export type Attention = {
|
|
@@ -186,6 +211,18 @@ export interface RunFieldRow { key: string; value: string; produced_by: string;
|
|
|
186
211
|
export interface RunDecisionRow { contract: string; scope: string; selection: string; decided_by: string; decided_at: number; }
|
|
187
212
|
export interface RunDetail { run: RunSummary; stages: RunStageRow[]; fields: RunFieldRow[]; decisions: RunDecisionRow[]; schemaAhead: boolean; }
|
|
188
213
|
|
|
214
|
+
export type AgentSurface = "herdr" | "headless";
|
|
215
|
+
|
|
216
|
+
export interface AgentRecord {
|
|
217
|
+
id: string; repo: string; cwd: string; provider: string;
|
|
218
|
+
surface: AgentSurface; sessionId: string;
|
|
219
|
+
model?: string; effort?: string; account?: string;
|
|
220
|
+
label?: string; caller?: string;
|
|
221
|
+
paneId?: string; tabId?: string; workspaceId?: string;
|
|
222
|
+
extraArgs?: string; exitCode?: number; resultPath?: string;
|
|
223
|
+
createdAt: number; lastResumedAt?: number; finishedAt?: number;
|
|
224
|
+
}
|
|
225
|
+
|
|
189
226
|
export interface Commands {
|
|
190
227
|
"project-mrs:read": { payload: { repoName: string; maxAgeMs?: number; demand?: DemandDecl }; data: ProjectMRsData };
|
|
191
228
|
"discussions:read": { payload: { repoName: string; iid: number }; data: DiscussionsData };
|
|
@@ -251,7 +288,7 @@ export interface Commands {
|
|
|
251
288
|
"chat:mark": { payload: { handle: string; room?: string }; data: Record<string, never> };
|
|
252
289
|
"chat:messages": { payload: { room: string; before?: number; limit?: number }; data: { messages: ChatMessage[] } };
|
|
253
290
|
"chat:arm": { payload: { handle: string; room?: string; sessionId?: string }; data: Record<string, never> };
|
|
254
|
-
"chat:touch": { payload: { handle: string; sessionId?: string }; data: Record<string, never> };
|
|
291
|
+
"chat:touch": { payload: { handle: string; room?: string; sessionId?: string }; data: Record<string, never> };
|
|
255
292
|
"chat:disarm": { payload: { handle: string; sessionId?: string }; data: Record<string, never> };
|
|
256
293
|
"chat:unread-waking": { payload: { handle: string; room?: string }; data: { rooms: { room: string; count: number; mentions: number; maxId: number }[] } };
|
|
257
294
|
|
|
@@ -271,6 +308,21 @@ export interface Commands {
|
|
|
271
308
|
data: { unread: { dms: number; mentions: number; rooms: number }; status: BuddyStatus };
|
|
272
309
|
};
|
|
273
310
|
"chat:dm": { payload: { from: string; to: string; body: string; sessionId?: string }; data: { room: string; id: number; recipients: string[] } };
|
|
311
|
+
|
|
312
|
+
// ─── Agent handoff (rt agent) ────────────────────────────────────────────
|
|
313
|
+
"agent:start": { payload: { repo: string; cwd: string; prompt?: string; surface?: AgentSurface; model?: string; effort?: string; account?: string; label?: string; caller?: string; workspace?: string; tab?: string; extraArgs?: string }; data: AgentRecord };
|
|
314
|
+
"agent:resume": { payload: { id: string; prompt?: string; surface?: AgentSurface }; data: AgentRecord };
|
|
315
|
+
"agent:get": { payload: { id: string }; data: AgentRecord };
|
|
316
|
+
"agent:list": { payload: { repo?: string }; data: { agents: AgentRecord[] } };
|
|
317
|
+
"chat:invite": { payload: { paneId: string; room: string; note?: string; from: string; callerPane?: string }; data: InviteResult };
|
|
318
|
+
"pane:list": { payload: Record<string, never>; data: { panes: ChatPane[] } };
|
|
319
|
+
"pane:peek": { payload: { paneId: string; lines?: number }; data: { paneId: string; lines: string[] } };
|
|
320
|
+
"pane:accounts": { payload: Record<string, never>; data: { accounts: PaneAccount[] } };
|
|
321
|
+
"pane:directories": { payload: { q?: string }; data: { directories: PaneDirectory[] } };
|
|
322
|
+
"pane:spawn": {
|
|
323
|
+
payload: { cwd: string; account?: string; model?: string; effort?: string; prompt?: string; workspace?: string };
|
|
324
|
+
data: { pane: ChatPane; ready: boolean };
|
|
325
|
+
};
|
|
274
326
|
}
|
|
275
327
|
|
|
276
328
|
export type CommandName = keyof Commands;
|
|
@@ -307,4 +359,14 @@ export const COMMAND_NAMES: readonly CommandName[] = [
|
|
|
307
359
|
"chat:buddies",
|
|
308
360
|
"chat:pulse",
|
|
309
361
|
"chat:dm",
|
|
362
|
+
"agent:start",
|
|
363
|
+
"agent:resume",
|
|
364
|
+
"agent:get",
|
|
365
|
+
"agent:list",
|
|
366
|
+
"chat:invite",
|
|
367
|
+
"pane:list",
|
|
368
|
+
"pane:peek",
|
|
369
|
+
"pane:accounts",
|
|
370
|
+
"pane:directories",
|
|
371
|
+
"pane:spawn",
|
|
310
372
|
];
|
package/src/index.ts
CHANGED
|
@@ -30,6 +30,16 @@ export {
|
|
|
30
30
|
chatPulse,
|
|
31
31
|
chatDm,
|
|
32
32
|
eventsHead,
|
|
33
|
+
agentStart,
|
|
34
|
+
agentResume,
|
|
35
|
+
agentGet,
|
|
36
|
+
agentList,
|
|
37
|
+
paneList,
|
|
38
|
+
panePeek,
|
|
39
|
+
paneSpawn,
|
|
40
|
+
paneAccounts,
|
|
41
|
+
paneDirectories,
|
|
42
|
+
chatInvite,
|
|
33
43
|
} from "./client.ts";
|
|
34
44
|
|
|
35
45
|
export { COMMAND_NAMES } from "./commands.ts";
|
|
@@ -58,6 +68,13 @@ export type {
|
|
|
58
68
|
RoomSummary,
|
|
59
69
|
BuddyStatus,
|
|
60
70
|
PresenceRow,
|
|
71
|
+
AgentRecord,
|
|
72
|
+
AgentSurface,
|
|
73
|
+
AgentStatus,
|
|
74
|
+
ChatPane,
|
|
75
|
+
PaneAccount,
|
|
76
|
+
PaneDirectory,
|
|
77
|
+
InviteResult,
|
|
61
78
|
} from "./commands.ts";
|
|
62
79
|
|
|
63
80
|
export { subscribe, createRelay, DEFAULT_WS_URL } from "./relay.ts";
|
|
@@ -308,7 +308,7 @@ export const REGISTRY: readonly SettingDef[] = [
|
|
|
308
308
|
type: "array",
|
|
309
309
|
scopes: ["team"],
|
|
310
310
|
merge: "replace",
|
|
311
|
-
description: "The
|
|
311
|
+
description: "The authors tab's roster: whose MRs the classic board lists, including hidden-by-default entries. Codeowners tabs list MRs from anyone.",
|
|
312
312
|
},
|
|
313
313
|
{
|
|
314
314
|
key: "board.title",
|
|
@@ -329,14 +329,14 @@ export const REGISTRY: readonly SettingDef[] = [
|
|
|
329
329
|
type: "array",
|
|
330
330
|
scopes: ["team"],
|
|
331
331
|
merge: "replace",
|
|
332
|
-
description: "Ticket key prefixes (e.g. RT, MAT) the
|
|
332
|
+
description: "Ticket key prefixes (e.g. RT, MAT) that keep the authors tab to the team's own tickets and link out to Linear from an MR title; rows on a codeowners tab pass regardless of prefix.",
|
|
333
333
|
},
|
|
334
334
|
{
|
|
335
335
|
key: "board.slack",
|
|
336
336
|
type: "object",
|
|
337
337
|
scopes: ["team"],
|
|
338
338
|
merge: "deep",
|
|
339
|
-
description: "The board's Slack posting config (app id, client id, channel, callback port);
|
|
339
|
+
description: "The board's Slack posting config (app id, client id, channel, callback port); channel is the default that a tab's slackChannel overrides per MR. Client secrets stay out of this store.",
|
|
340
340
|
},
|
|
341
341
|
{
|
|
342
342
|
key: "board.doctorSkill",
|
|
@@ -352,6 +352,13 @@ export const REGISTRY: readonly SettingDef[] = [
|
|
|
352
352
|
merge: "replace",
|
|
353
353
|
description: "Doctor skill the board's own API-tier triage sweep runs on your MRs; deliberately never resolved through a repo's skills.jsonc manifest. A sibling flat key of board.triage, not a field inside it — the board reader assembles the two independently.",
|
|
354
354
|
},
|
|
355
|
+
{
|
|
356
|
+
key: "board.tabs",
|
|
357
|
+
type: "array",
|
|
358
|
+
scopes: ["team"],
|
|
359
|
+
merge: "replace",
|
|
360
|
+
description: "Board tabs ({id, label, source, slackChannel?, reviewSkill?}), editable from the board's settings modal. source.kind 'authors' is the classic roster board; 'codeowners' lists MRs from any author blocked on an unapproved CODEOWNERS section. Absent = one implicit authors tab (fallback lives in the board reader, never here).",
|
|
361
|
+
},
|
|
355
362
|
|
|
356
363
|
// --- board (user) ----------------------------------------------------------
|
|
357
364
|
{
|
|
@@ -380,7 +387,7 @@ export const REGISTRY: readonly SettingDef[] = [
|
|
|
380
387
|
type: "array",
|
|
381
388
|
scopes: ["user"],
|
|
382
389
|
merge: "replace",
|
|
383
|
-
description: "Usernames this developer hides from the
|
|
390
|
+
description: "Usernames this developer hides from the authors tab's board.members roster; overlays the team truth without editing it.",
|
|
384
391
|
},
|
|
385
392
|
{
|
|
386
393
|
key: "board.triage",
|
|
@@ -466,6 +473,21 @@ export const REGISTRY: readonly SettingDef[] = [
|
|
|
466
473
|
merge: "replace",
|
|
467
474
|
description: "The human's own chat handle, so agents can @-mention them by name.",
|
|
468
475
|
},
|
|
476
|
+
{
|
|
477
|
+
key: "chat.viewerUrl",
|
|
478
|
+
type: "string",
|
|
479
|
+
scopes: ["user"],
|
|
480
|
+
merge: "replace",
|
|
481
|
+
description: "Base URL of the chat viewer, no trailing slash. When set, rt chat post and the tail's wake lines end with a link to the room or message.",
|
|
482
|
+
},
|
|
483
|
+
{
|
|
484
|
+
key: "chat.herdrWorkspace",
|
|
485
|
+
type: "string",
|
|
486
|
+
scopes: ["user"],
|
|
487
|
+
default: "chat",
|
|
488
|
+
merge: "replace",
|
|
489
|
+
description: "herdr workspace label that rt pane spawn opens new agent tabs in; created when missing.",
|
|
490
|
+
},
|
|
469
491
|
{
|
|
470
492
|
key: "chat.push.provider",
|
|
471
493
|
type: "string",
|
|
@@ -480,4 +502,36 @@ export const REGISTRY: readonly SettingDef[] = [
|
|
|
480
502
|
merge: "replace",
|
|
481
503
|
description: "Destination (topic/URL/token) the configured chat.push.provider sends to.",
|
|
482
504
|
},
|
|
505
|
+
|
|
506
|
+
// --- agent (rt agent handoff) --------------------------------------------
|
|
507
|
+
// No defaults by design: an unset key means the flag is omitted from the
|
|
508
|
+
// claude invocation entirely (spec "Settings").
|
|
509
|
+
{
|
|
510
|
+
key: "agent.model",
|
|
511
|
+
type: "string",
|
|
512
|
+
scopes: ["user", "machine"],
|
|
513
|
+
merge: "replace",
|
|
514
|
+
description: "Default --model for rt agent launches; unset omits the flag.",
|
|
515
|
+
},
|
|
516
|
+
{
|
|
517
|
+
key: "agent.effort",
|
|
518
|
+
type: "string",
|
|
519
|
+
scopes: ["user", "machine"],
|
|
520
|
+
merge: "replace",
|
|
521
|
+
description: "Default --effort for rt agent launches; unset omits the flag.",
|
|
522
|
+
},
|
|
523
|
+
{
|
|
524
|
+
key: "agent.account",
|
|
525
|
+
type: "string",
|
|
526
|
+
scopes: ["user", "machine"],
|
|
527
|
+
merge: "replace",
|
|
528
|
+
description: "cswap account email rt agent launches under; unset uses the default claude profile.",
|
|
529
|
+
},
|
|
530
|
+
{
|
|
531
|
+
key: "agent.extraArgs",
|
|
532
|
+
type: "string",
|
|
533
|
+
scopes: ["user", "machine"],
|
|
534
|
+
merge: "replace",
|
|
535
|
+
description: "Opaque extra claude arguments appended to every rt agent launch (escape hatch).",
|
|
536
|
+
},
|
|
483
537
|
];
|