@mattstack/rt-client 0.9.0 → 0.10.1
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 +5 -7
- package/dist/client.d.ts +4 -42
- package/dist/commands.d.ts +43 -63
- package/dist/index.d.ts +2 -2
- package/dist/index.js +22 -52
- package/package.json +1 -1
- package/src/client.ts +21 -58
- package/src/commands.ts +42 -24
- package/src/index.ts +2 -5
package/README.md
CHANGED
|
@@ -90,7 +90,7 @@ await chatPost({ handle: 'matt', room: 'build', body: 'on it' });
|
|
|
90
90
|
|
|
91
91
|
const health = await daemonHealth(); // { reachable, error? }, never throws
|
|
92
92
|
const stop = createRelay({ // one daemon subscription, republished
|
|
93
|
-
match: t => t.startsWith('chat/'), // `chat/<room>/msg
|
|
93
|
+
match: t => t.startsWith('chat/'), // `chat/<room>/msg`
|
|
94
94
|
topic: 'chat',
|
|
95
95
|
publish: (topic, data) => server.publish(topic, data),
|
|
96
96
|
});
|
|
@@ -98,20 +98,18 @@ const stop = createRelay({ // one daemon sub
|
|
|
98
98
|
|
|
99
99
|
| Function | Daemon verb |
|
|
100
100
|
| --- | --- |
|
|
101
|
-
| `chatSignIn` / `chatSignOut` / `chatAway` / `chatBack`
|
|
101
|
+
| `chatSignIn` / `chatSignOut` / `chatAway` / `chatBack` | presence: the buddy-list row and its session heartbeat |
|
|
102
102
|
| `chatBuddies` / `chatWho` / `chatRooms` | the roster, one room's members, a handle's rooms |
|
|
103
103
|
| `chatJoin` / `chatLeave` / `chatArchive` | membership (`wakeOn: mention \| all \| none`); archive parks a room for everyone until a post revives it |
|
|
104
104
|
| `chatPost` / `chatDm` / `chatDmOpen` / `chatRead` / `chatMessages` / `chatMark` | messages: post, DM, open a DM room without posting, 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
105
|
| `paneList` / `panePeek` / `paneSpawn` / `paneAccounts` / `paneDirectories` | herdr panes: list with presence joined, peek a screen, start claude in a tab, cswap accounts, directory suggestions |
|
|
107
106
|
| `chatInvite` | type `/chat:join <room>` into a pane; `accepted`, `queued` or `refused` |
|
|
108
107
|
| `createRelay` / `subscribe` | the event stream; `daemonHealth` the reachability probe |
|
|
109
108
|
|
|
110
109
|
Pass `{ sockPath }` as the trailing options to reach a non-default daemon
|
|
111
|
-
socket. The verbs
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
`skills/rt-chat/SKILL.md`.
|
|
110
|
+
socket. The verbs and their payloads are specified in repo-tools
|
|
111
|
+
`docs/superpowers/specs/2026-08-28-rt-chat-delivery-v2-design.md`; the
|
|
112
|
+
agent-facing rules are `skills/rt-chat/SKILL.md`.
|
|
115
113
|
|
|
116
114
|
## License
|
|
117
115
|
|
package/dist/client.d.ts
CHANGED
|
@@ -96,35 +96,8 @@ export declare function chatMessages(a: {
|
|
|
96
96
|
}, o?: RtClientOptions): Promise<RtResponse<{
|
|
97
97
|
messages: ChatMessage[];
|
|
98
98
|
}>>;
|
|
99
|
-
export declare function chatArm(a: {
|
|
100
|
-
handle: string;
|
|
101
|
-
room?: string;
|
|
102
|
-
sessionId?: string;
|
|
103
|
-
}, o?: RtClientOptions): Promise<RtResponse<Record<string, never>>>;
|
|
104
|
-
export declare function chatTouch(a: {
|
|
105
|
-
handle: string;
|
|
106
|
-
room?: string;
|
|
107
|
-
sessionId?: string;
|
|
108
|
-
}, o?: RtClientOptions): Promise<RtResponse<Record<string, never>>>;
|
|
109
|
-
export declare function chatDisarm(a: {
|
|
110
|
-
handle: string;
|
|
111
|
-
sessionId?: string;
|
|
112
|
-
}, o?: RtClientOptions): Promise<RtResponse<Record<string, never>>>;
|
|
113
|
-
export declare function chatUnreadWaking(a: {
|
|
114
|
-
handle: string;
|
|
115
|
-
room?: string;
|
|
116
|
-
}, o?: RtClientOptions): Promise<RtResponse<{
|
|
117
|
-
rooms: {
|
|
118
|
-
room: string;
|
|
119
|
-
count: number;
|
|
120
|
-
mentions: number;
|
|
121
|
-
maxId: number;
|
|
122
|
-
}[];
|
|
123
|
-
}>>;
|
|
124
99
|
export declare function chatSignIn(a: Commands["chat:sign-in"]["payload"], o?: RtClientOptions): Promise<RtResponse<Commands["chat:sign-in"]["data"]>>;
|
|
125
|
-
export declare function chatSignOut(a:
|
|
126
|
-
sessionId: string;
|
|
127
|
-
}, o?: RtClientOptions): Promise<RtResponse<Record<string, never>>>;
|
|
100
|
+
export declare function chatSignOut(a: Commands["chat:sign-out"]["payload"], o?: RtClientOptions): Promise<RtResponse<Commands["chat:sign-out"]["data"]>>;
|
|
128
101
|
export declare function chatAway(a: {
|
|
129
102
|
sessionId: string;
|
|
130
103
|
text: string;
|
|
@@ -137,20 +110,6 @@ export declare function chatBuddies(o?: RtClientOptions): Promise<RtResponse<{
|
|
|
137
110
|
status: BuddyStatus;
|
|
138
111
|
}>;
|
|
139
112
|
}>>;
|
|
140
|
-
export declare function chatPulse(a: {
|
|
141
|
-
sessionId: string;
|
|
142
|
-
cwd?: string;
|
|
143
|
-
repo?: string;
|
|
144
|
-
branch?: string;
|
|
145
|
-
pane?: string;
|
|
146
|
-
}, o?: RtClientOptions): Promise<RtResponse<{
|
|
147
|
-
unread: {
|
|
148
|
-
dms: number;
|
|
149
|
-
mentions: number;
|
|
150
|
-
rooms: number;
|
|
151
|
-
};
|
|
152
|
-
status: BuddyStatus;
|
|
153
|
-
}>>;
|
|
154
113
|
export declare function chatDm(a: {
|
|
155
114
|
from: string;
|
|
156
115
|
to: string;
|
|
@@ -199,3 +158,6 @@ export declare function paneDirectories(a: Commands["pane:directories"]["payload
|
|
|
199
158
|
export declare function chatInvite(a: Commands["chat:invite"]["payload"], o?: RtClientOptions): Promise<RtResponse<Commands["chat:invite"]["data"]>>;
|
|
200
159
|
/** A working target holds the connection through its prompt wait, so the budget matches chatInvite's 30s. */
|
|
201
160
|
export declare function paneSend(a: Commands["pane:send"]["payload"], o?: RtClientOptions): Promise<RtResponse<Commands["pane:send"]["data"]>>;
|
|
161
|
+
/** Brings a herdr pane to the front. The daemon routes this to the tray, which
|
|
162
|
+
owns the herdr focus and the native terminal-window raise. */
|
|
163
|
+
export declare function paneFocus(a: Commands["pane:focus"]["payload"], o?: RtClientOptions): Promise<RtResponse<Commands["pane:focus"]["data"]>>;
|
package/dist/commands.d.ts
CHANGED
|
@@ -99,8 +99,6 @@ export interface ChatMember {
|
|
|
99
99
|
joinedAt: number;
|
|
100
100
|
lastReadId: number;
|
|
101
101
|
wakeOn: WakeMode;
|
|
102
|
-
lastSeenAt?: number;
|
|
103
|
-
armedAt?: number;
|
|
104
102
|
cwd?: string;
|
|
105
103
|
pane?: string;
|
|
106
104
|
/** Presence-joined by chat:who's handler — the only place this type is ever returned, and it always attaches one. */
|
|
@@ -137,7 +135,7 @@ export interface RoomSummary {
|
|
|
137
135
|
* above: mirrors lib/state/presence-store.ts's types, which rt-client
|
|
138
136
|
* cannot import.
|
|
139
137
|
*/
|
|
140
|
-
export type BuddyStatus = "live" | "idle" | "
|
|
138
|
+
export type BuddyStatus = "live" | "idle" | "offline";
|
|
141
139
|
export interface PresenceRow {
|
|
142
140
|
sessionId: string;
|
|
143
141
|
handle: string;
|
|
@@ -149,8 +147,6 @@ export interface PresenceRow {
|
|
|
149
147
|
statusText?: string;
|
|
150
148
|
signedInAt: number;
|
|
151
149
|
lastSeenAt: number;
|
|
152
|
-
tailSeenAt?: number;
|
|
153
|
-
armedAt?: number;
|
|
154
150
|
signedOutAt?: number;
|
|
155
151
|
}
|
|
156
152
|
export type AgentStatus = "idle" | "working" | "blocked" | "done" | "unknown";
|
|
@@ -193,6 +189,10 @@ export interface PaneSendResult {
|
|
|
193
189
|
delivered: PaneDelivery;
|
|
194
190
|
reason?: string;
|
|
195
191
|
}
|
|
192
|
+
export interface PaneFocusResult {
|
|
193
|
+
paneId: string;
|
|
194
|
+
focused: boolean;
|
|
195
|
+
}
|
|
196
196
|
export type Attention = {
|
|
197
197
|
needs: boolean;
|
|
198
198
|
reason: "failed" | "stale" | "stranded" | "blocked" | null;
|
|
@@ -278,6 +278,7 @@ export interface AgentRecord {
|
|
|
278
278
|
account?: string;
|
|
279
279
|
label?: string;
|
|
280
280
|
caller?: string;
|
|
281
|
+
handle?: string;
|
|
281
282
|
paneId?: string;
|
|
282
283
|
tabId?: string;
|
|
283
284
|
workspaceId?: string;
|
|
@@ -511,65 +512,56 @@ export interface Commands {
|
|
|
511
512
|
messages: ChatMessage[];
|
|
512
513
|
};
|
|
513
514
|
};
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
handle: string;
|
|
525
|
-
room?: string;
|
|
526
|
-
sessionId?: string;
|
|
527
|
-
};
|
|
528
|
-
data: Record<string, never>;
|
|
529
|
-
};
|
|
530
|
-
"chat:disarm": {
|
|
531
|
-
payload: {
|
|
532
|
-
handle: string;
|
|
533
|
-
sessionId?: string;
|
|
534
|
-
};
|
|
535
|
-
data: Record<string, never>;
|
|
536
|
-
};
|
|
537
|
-
"chat:unread-waking": {
|
|
538
|
-
payload: {
|
|
539
|
-
handle: string;
|
|
540
|
-
room?: string;
|
|
541
|
-
};
|
|
542
|
-
data: {
|
|
543
|
-
rooms: {
|
|
544
|
-
room: string;
|
|
545
|
-
count: number;
|
|
546
|
-
mentions: number;
|
|
547
|
-
maxId: number;
|
|
548
|
-
}[];
|
|
549
|
-
};
|
|
550
|
-
};
|
|
551
|
-
/** No `baseHandle` means "draw me a first name": the daemon picks the least recently used pool name no live session holds. */
|
|
515
|
+
/**
|
|
516
|
+
* No `baseHandle` means "draw me a first name": the daemon picks the least
|
|
517
|
+
* recently used pool name no live session holds. `viaPane` resolves
|
|
518
|
+
* `sessionId` daemon-side from herdr's `session.snapshot` for the pane id
|
|
519
|
+
* in `pane`, rather than trusting a caller-supplied id -- the caller may
|
|
520
|
+
* have none of its own (a human or another agent signing a target pane in
|
|
521
|
+
* on its behalf); the response's `sessionId` and `room` are then the only
|
|
522
|
+
* way that caller learns what got signed in and joined, since it has
|
|
523
|
+
* nothing local to derive either from.
|
|
524
|
+
*/
|
|
552
525
|
"chat:sign-in": {
|
|
553
526
|
payload: {
|
|
554
|
-
sessionId
|
|
527
|
+
sessionId?: string;
|
|
555
528
|
baseHandle?: string;
|
|
556
529
|
cwd?: string;
|
|
557
530
|
repo?: string;
|
|
558
531
|
branch?: string;
|
|
559
532
|
pane?: string;
|
|
560
533
|
statusText?: string;
|
|
534
|
+
viaPane?: boolean;
|
|
535
|
+
/** `viaPane` only: overrides the pane-cwd-derived room outright. */
|
|
536
|
+
room?: string;
|
|
537
|
+
/** `viaPane` only: skip room derivation/join entirely, same as --no-room on the non-pane path. */
|
|
538
|
+
noRoom?: boolean;
|
|
561
539
|
};
|
|
562
540
|
data: {
|
|
563
541
|
handle: string;
|
|
564
542
|
baseHandle: string;
|
|
565
543
|
reclaimed: boolean;
|
|
544
|
+
sessionId: string;
|
|
545
|
+
room: string | null;
|
|
566
546
|
};
|
|
567
547
|
};
|
|
548
|
+
/**
|
|
549
|
+
* `viaPane` mirrors `chat:sign-in`'s: the daemon resolves `pane` to a
|
|
550
|
+
* session id via herdr's `session.snapshot` rather than trusting a
|
|
551
|
+
* caller-supplied one, so a process signing another pane out (herdr-chat,
|
|
552
|
+
* or a human invoking a target pane) needs neither that pane's session id
|
|
553
|
+
* nor its own. The response's `sessionId` is the RESOLVED id, the only way
|
|
554
|
+
* such a caller learns which session file to delete locally.
|
|
555
|
+
*/
|
|
568
556
|
"chat:sign-out": {
|
|
569
557
|
payload: {
|
|
558
|
+
sessionId?: string;
|
|
559
|
+
pane?: string;
|
|
560
|
+
viaPane?: boolean;
|
|
561
|
+
};
|
|
562
|
+
data: {
|
|
570
563
|
sessionId: string;
|
|
571
564
|
};
|
|
572
|
-
data: Record<string, never>;
|
|
573
565
|
};
|
|
574
566
|
"chat:away": {
|
|
575
567
|
payload: {
|
|
@@ -592,24 +584,6 @@ export interface Commands {
|
|
|
592
584
|
}>;
|
|
593
585
|
};
|
|
594
586
|
};
|
|
595
|
-
/** `unread`'s three fields are disjoint and sum to the true total: `dms` is DM-room waking count; `mentions` is non-DM waking mentions; `rooms` is non-DM waking count minus those mentions (never negative). */
|
|
596
|
-
"chat:pulse": {
|
|
597
|
-
payload: {
|
|
598
|
-
sessionId: string;
|
|
599
|
-
cwd?: string;
|
|
600
|
-
repo?: string;
|
|
601
|
-
branch?: string;
|
|
602
|
-
pane?: string;
|
|
603
|
-
};
|
|
604
|
-
data: {
|
|
605
|
-
unread: {
|
|
606
|
-
dms: number;
|
|
607
|
-
mentions: number;
|
|
608
|
-
rooms: number;
|
|
609
|
-
};
|
|
610
|
-
status: BuddyStatus;
|
|
611
|
-
};
|
|
612
|
-
};
|
|
613
587
|
"chat:dm": {
|
|
614
588
|
payload: {
|
|
615
589
|
from: string;
|
|
@@ -748,6 +722,12 @@ export interface Commands {
|
|
|
748
722
|
};
|
|
749
723
|
data: PaneSendResult;
|
|
750
724
|
};
|
|
725
|
+
"pane:focus": {
|
|
726
|
+
payload: {
|
|
727
|
+
paneId: string;
|
|
728
|
+
};
|
|
729
|
+
data: PaneFocusResult;
|
|
730
|
+
};
|
|
751
731
|
}
|
|
752
732
|
export type CommandName = keyof Commands;
|
|
753
733
|
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,
|
|
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";
|
|
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, } 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";
|
|
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
|
@@ -117,36 +117,10 @@ function chatMessages(a, o = {}) {
|
|
|
117
117
|
payload.limit = a.limit;
|
|
118
118
|
return rtCommand("chat:messages", payload, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 1e4 });
|
|
119
119
|
}
|
|
120
|
-
function
|
|
121
|
-
const payload = {
|
|
122
|
-
if (a.room !== undefined)
|
|
123
|
-
payload.room = a.room;
|
|
124
|
-
if (a.sessionId !== undefined)
|
|
125
|
-
payload.sessionId = a.sessionId;
|
|
126
|
-
return rtCommand("chat:arm", payload, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 1e4 });
|
|
127
|
-
}
|
|
128
|
-
function chatTouch(a, o = {}) {
|
|
129
|
-
const payload = { handle: a.handle };
|
|
130
|
-
if (a.room !== undefined)
|
|
131
|
-
payload.room = a.room;
|
|
132
|
-
if (a.sessionId !== undefined)
|
|
133
|
-
payload.sessionId = a.sessionId;
|
|
134
|
-
return rtCommand("chat:touch", payload, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 1e4 });
|
|
135
|
-
}
|
|
136
|
-
function chatDisarm(a, o = {}) {
|
|
137
|
-
const payload = { handle: a.handle };
|
|
120
|
+
function chatSignIn(a, o = {}) {
|
|
121
|
+
const payload = {};
|
|
138
122
|
if (a.sessionId !== undefined)
|
|
139
123
|
payload.sessionId = a.sessionId;
|
|
140
|
-
return rtCommand("chat:disarm", payload, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 1e4 });
|
|
141
|
-
}
|
|
142
|
-
function chatUnreadWaking(a, o = {}) {
|
|
143
|
-
const payload = { handle: a.handle };
|
|
144
|
-
if (a.room !== undefined)
|
|
145
|
-
payload.room = a.room;
|
|
146
|
-
return rtCommand("chat:unread-waking", payload, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 1e4 });
|
|
147
|
-
}
|
|
148
|
-
function chatSignIn(a, o = {}) {
|
|
149
|
-
const payload = { sessionId: a.sessionId };
|
|
150
124
|
if (a.baseHandle !== undefined)
|
|
151
125
|
payload.baseHandle = a.baseHandle;
|
|
152
126
|
if (a.cwd !== undefined)
|
|
@@ -159,10 +133,23 @@ function chatSignIn(a, o = {}) {
|
|
|
159
133
|
payload.pane = a.pane;
|
|
160
134
|
if (a.statusText !== undefined)
|
|
161
135
|
payload.statusText = a.statusText;
|
|
136
|
+
if (a.viaPane !== undefined)
|
|
137
|
+
payload.viaPane = a.viaPane;
|
|
138
|
+
if (a.room !== undefined)
|
|
139
|
+
payload.room = a.room;
|
|
140
|
+
if (a.noRoom !== undefined)
|
|
141
|
+
payload.noRoom = a.noRoom;
|
|
162
142
|
return rtCommand("chat:sign-in", payload, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 1e4 });
|
|
163
143
|
}
|
|
164
144
|
function chatSignOut(a, o = {}) {
|
|
165
|
-
|
|
145
|
+
const payload = {};
|
|
146
|
+
if (a.sessionId !== undefined)
|
|
147
|
+
payload.sessionId = a.sessionId;
|
|
148
|
+
if (a.pane !== undefined)
|
|
149
|
+
payload.pane = a.pane;
|
|
150
|
+
if (a.viaPane !== undefined)
|
|
151
|
+
payload.viaPane = a.viaPane;
|
|
152
|
+
return rtCommand("chat:sign-out", payload, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 1e4 });
|
|
166
153
|
}
|
|
167
154
|
function chatAway(a, o = {}) {
|
|
168
155
|
return rtCommand("chat:away", { sessionId: a.sessionId, text: a.text }, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 1e4 });
|
|
@@ -173,18 +160,6 @@ function chatBack(a, o = {}) {
|
|
|
173
160
|
function chatBuddies(o = {}) {
|
|
174
161
|
return rtCommand("chat:buddies", {}, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 1e4 });
|
|
175
162
|
}
|
|
176
|
-
function chatPulse(a, o = {}) {
|
|
177
|
-
const payload = { sessionId: a.sessionId };
|
|
178
|
-
if (a.cwd !== undefined)
|
|
179
|
-
payload.cwd = a.cwd;
|
|
180
|
-
if (a.repo !== undefined)
|
|
181
|
-
payload.repo = a.repo;
|
|
182
|
-
if (a.branch !== undefined)
|
|
183
|
-
payload.branch = a.branch;
|
|
184
|
-
if (a.pane !== undefined)
|
|
185
|
-
payload.pane = a.pane;
|
|
186
|
-
return rtCommand("chat:pulse", payload, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 1e4 });
|
|
187
|
-
}
|
|
188
163
|
function chatDm(a, o = {}) {
|
|
189
164
|
const payload = { from: a.from, to: a.to, body: a.body };
|
|
190
165
|
if (a.sessionId !== undefined)
|
|
@@ -267,6 +242,9 @@ function paneSend(a, o = {}) {
|
|
|
267
242
|
payload.callerPane = a.callerPane;
|
|
268
243
|
return rtCommand("pane:send", payload, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 30000 });
|
|
269
244
|
}
|
|
245
|
+
function paneFocus(a, o = {}) {
|
|
246
|
+
return rtCommand("pane:focus", { paneId: a.paneId }, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 1e4 });
|
|
247
|
+
}
|
|
270
248
|
// src/commands.ts
|
|
271
249
|
var COMMAND_NAMES = [
|
|
272
250
|
"project-mrs:read",
|
|
@@ -289,16 +267,11 @@ var COMMAND_NAMES = [
|
|
|
289
267
|
"chat:who",
|
|
290
268
|
"chat:mark",
|
|
291
269
|
"chat:messages",
|
|
292
|
-
"chat:arm",
|
|
293
|
-
"chat:touch",
|
|
294
|
-
"chat:disarm",
|
|
295
|
-
"chat:unread-waking",
|
|
296
270
|
"chat:sign-in",
|
|
297
271
|
"chat:sign-out",
|
|
298
272
|
"chat:away",
|
|
299
273
|
"chat:back",
|
|
300
274
|
"chat:buddies",
|
|
301
|
-
"chat:pulse",
|
|
302
275
|
"chat:dm",
|
|
303
276
|
"chat:archive",
|
|
304
277
|
"chat:dm-open",
|
|
@@ -312,7 +285,8 @@ var COMMAND_NAMES = [
|
|
|
312
285
|
"pane:accounts",
|
|
313
286
|
"pane:directories",
|
|
314
287
|
"pane:spawn",
|
|
315
|
-
"pane:send"
|
|
288
|
+
"pane:send",
|
|
289
|
+
"pane:focus"
|
|
316
290
|
];
|
|
317
291
|
// src/relay.ts
|
|
318
292
|
var DEFAULT_WS_URL = "ws://127.0.0.1:9401/ws";
|
|
@@ -1764,6 +1738,7 @@ export {
|
|
|
1764
1738
|
paneSend,
|
|
1765
1739
|
panePeek,
|
|
1766
1740
|
paneList,
|
|
1741
|
+
paneFocus,
|
|
1767
1742
|
paneDirectories,
|
|
1768
1743
|
paneAccounts,
|
|
1769
1744
|
normalizeRemote,
|
|
@@ -1783,13 +1758,10 @@ export {
|
|
|
1783
1758
|
createRelay,
|
|
1784
1759
|
clearIdentityMemo,
|
|
1785
1760
|
chatWho,
|
|
1786
|
-
chatUnreadWaking,
|
|
1787
|
-
chatTouch,
|
|
1788
1761
|
chatSignOut,
|
|
1789
1762
|
chatSignIn,
|
|
1790
1763
|
chatRooms,
|
|
1791
1764
|
chatRead,
|
|
1792
|
-
chatPulse,
|
|
1793
1765
|
chatPost,
|
|
1794
1766
|
chatMessages,
|
|
1795
1767
|
chatMark,
|
|
@@ -1798,11 +1770,9 @@ export {
|
|
|
1798
1770
|
chatInvite,
|
|
1799
1771
|
chatDmOpen,
|
|
1800
1772
|
chatDm,
|
|
1801
|
-
chatDisarm,
|
|
1802
1773
|
chatBuddies,
|
|
1803
1774
|
chatBack,
|
|
1804
1775
|
chatAway,
|
|
1805
|
-
chatArm,
|
|
1806
1776
|
chatArchive,
|
|
1807
1777
|
allDefs,
|
|
1808
1778
|
agentStart,
|
package/package.json
CHANGED
package/src/client.ts
CHANGED
|
@@ -220,65 +220,35 @@ export function chatMessages(
|
|
|
220
220
|
return rtCommand<{ messages: ChatMessage[] }>("chat:messages", payload, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 10_000 });
|
|
221
221
|
}
|
|
222
222
|
|
|
223
|
-
export function chatArm(
|
|
224
|
-
a: { handle: string; room?: string; sessionId?: string },
|
|
225
|
-
o: RtClientOptions = {},
|
|
226
|
-
): Promise<RtResponse<Record<string, never>>> {
|
|
227
|
-
const payload: Record<string, unknown> = { handle: a.handle };
|
|
228
|
-
if (a.room !== undefined) payload.room = a.room;
|
|
229
|
-
if (a.sessionId !== undefined) payload.sessionId = a.sessionId;
|
|
230
|
-
return rtCommand<Record<string, never>>("chat:arm", payload, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 10_000 });
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
export function chatTouch(
|
|
234
|
-
a: { handle: string; room?: string; sessionId?: string },
|
|
235
|
-
o: RtClientOptions = {},
|
|
236
|
-
): Promise<RtResponse<Record<string, never>>> {
|
|
237
|
-
const payload: Record<string, unknown> = { handle: a.handle };
|
|
238
|
-
if (a.room !== undefined) payload.room = a.room;
|
|
239
|
-
if (a.sessionId !== undefined) payload.sessionId = a.sessionId;
|
|
240
|
-
return rtCommand<Record<string, never>>("chat:touch", payload, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 10_000 });
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
export function chatDisarm(
|
|
244
|
-
a: { handle: string; sessionId?: string },
|
|
245
|
-
o: RtClientOptions = {},
|
|
246
|
-
): Promise<RtResponse<Record<string, never>>> {
|
|
247
|
-
const payload: Record<string, unknown> = { handle: a.handle };
|
|
248
|
-
if (a.sessionId !== undefined) payload.sessionId = a.sessionId;
|
|
249
|
-
return rtCommand<Record<string, never>>("chat:disarm", payload, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 10_000 });
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
export function chatUnreadWaking(
|
|
253
|
-
a: { handle: string; room?: string },
|
|
254
|
-
o: RtClientOptions = {},
|
|
255
|
-
): Promise<RtResponse<{ rooms: { room: string; count: number; mentions: number; maxId: number }[] }>> {
|
|
256
|
-
const payload: Record<string, unknown> = { handle: a.handle };
|
|
257
|
-
if (a.room !== undefined) payload.room = a.room;
|
|
258
|
-
return rtCommand<{ rooms: { room: string; count: number; mentions: number; maxId: number }[] }>("chat:unread-waking", payload, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 10_000 });
|
|
259
|
-
}
|
|
260
|
-
|
|
261
223
|
// ─── Presence ──────────────────────────────────────────────────────────
|
|
262
224
|
|
|
263
225
|
export function chatSignIn(
|
|
264
226
|
a: Commands["chat:sign-in"]["payload"],
|
|
265
227
|
o: RtClientOptions = {},
|
|
266
228
|
): Promise<RtResponse<Commands["chat:sign-in"]["data"]>> {
|
|
267
|
-
const payload: Record<string, unknown> = {
|
|
229
|
+
const payload: Record<string, unknown> = {};
|
|
230
|
+
if (a.sessionId !== undefined) payload.sessionId = a.sessionId;
|
|
268
231
|
if (a.baseHandle !== undefined) payload.baseHandle = a.baseHandle;
|
|
269
232
|
if (a.cwd !== undefined) payload.cwd = a.cwd;
|
|
270
233
|
if (a.repo !== undefined) payload.repo = a.repo;
|
|
271
234
|
if (a.branch !== undefined) payload.branch = a.branch;
|
|
272
235
|
if (a.pane !== undefined) payload.pane = a.pane;
|
|
273
236
|
if (a.statusText !== undefined) payload.statusText = a.statusText;
|
|
237
|
+
if (a.viaPane !== undefined) payload.viaPane = a.viaPane;
|
|
238
|
+
if (a.room !== undefined) payload.room = a.room;
|
|
239
|
+
if (a.noRoom !== undefined) payload.noRoom = a.noRoom;
|
|
274
240
|
return rtCommand<Commands["chat:sign-in"]["data"]>("chat:sign-in", payload, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 10_000 });
|
|
275
241
|
}
|
|
276
242
|
|
|
277
243
|
export function chatSignOut(
|
|
278
|
-
a:
|
|
244
|
+
a: Commands["chat:sign-out"]["payload"],
|
|
279
245
|
o: RtClientOptions = {},
|
|
280
|
-
): Promise<RtResponse<
|
|
281
|
-
|
|
246
|
+
): Promise<RtResponse<Commands["chat:sign-out"]["data"]>> {
|
|
247
|
+
const payload: Record<string, unknown> = {};
|
|
248
|
+
if (a.sessionId !== undefined) payload.sessionId = a.sessionId;
|
|
249
|
+
if (a.pane !== undefined) payload.pane = a.pane;
|
|
250
|
+
if (a.viaPane !== undefined) payload.viaPane = a.viaPane;
|
|
251
|
+
return rtCommand<Commands["chat:sign-out"]["data"]>("chat:sign-out", payload, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 10_000 });
|
|
282
252
|
}
|
|
283
253
|
|
|
284
254
|
export function chatAway(
|
|
@@ -301,22 +271,6 @@ export function chatBuddies(
|
|
|
301
271
|
return rtCommand<{ buddies: Array<PresenceRow & { status: BuddyStatus }> }>("chat:buddies", {}, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 10_000 });
|
|
302
272
|
}
|
|
303
273
|
|
|
304
|
-
export function chatPulse(
|
|
305
|
-
a: { sessionId: string; cwd?: string; repo?: string; branch?: string; pane?: string },
|
|
306
|
-
o: RtClientOptions = {},
|
|
307
|
-
): Promise<RtResponse<{ unread: { dms: number; mentions: number; rooms: number }; status: BuddyStatus }>> {
|
|
308
|
-
const payload: Record<string, unknown> = { sessionId: a.sessionId };
|
|
309
|
-
if (a.cwd !== undefined) payload.cwd = a.cwd;
|
|
310
|
-
if (a.repo !== undefined) payload.repo = a.repo;
|
|
311
|
-
if (a.branch !== undefined) payload.branch = a.branch;
|
|
312
|
-
if (a.pane !== undefined) payload.pane = a.pane;
|
|
313
|
-
return rtCommand<{ unread: { dms: number; mentions: number; rooms: number }; status: BuddyStatus }>(
|
|
314
|
-
"chat:pulse",
|
|
315
|
-
payload,
|
|
316
|
-
{ sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 10_000 },
|
|
317
|
-
);
|
|
318
|
-
}
|
|
319
|
-
|
|
320
274
|
export function chatDm(
|
|
321
275
|
a: { from: string; to: string; body: string; sessionId?: string },
|
|
322
276
|
o: RtClientOptions = {},
|
|
@@ -434,3 +388,12 @@ export function paneSend(
|
|
|
434
388
|
if (a.callerPane !== undefined) payload.callerPane = a.callerPane;
|
|
435
389
|
return rtCommand<Commands["pane:send"]["data"]>("pane:send", payload, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 30_000 });
|
|
436
390
|
}
|
|
391
|
+
|
|
392
|
+
/** Brings a herdr pane to the front. The daemon routes this to the tray, which
|
|
393
|
+
owns the herdr focus and the native terminal-window raise. */
|
|
394
|
+
export function paneFocus(
|
|
395
|
+
a: Commands["pane:focus"]["payload"],
|
|
396
|
+
o: RtClientOptions = {},
|
|
397
|
+
): Promise<RtResponse<Commands["pane:focus"]["data"]>> {
|
|
398
|
+
return rtCommand<Commands["pane:focus"]["data"]>("pane:focus", { paneId: a.paneId }, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 10_000 });
|
|
399
|
+
}
|
package/src/commands.ts
CHANGED
|
@@ -92,8 +92,6 @@ export interface ChatMember {
|
|
|
92
92
|
joinedAt: number;
|
|
93
93
|
lastReadId: number;
|
|
94
94
|
wakeOn: WakeMode;
|
|
95
|
-
lastSeenAt?: number;
|
|
96
|
-
armedAt?: number;
|
|
97
95
|
cwd?: string;
|
|
98
96
|
pane?: string;
|
|
99
97
|
/** Presence-joined by chat:who's handler — the only place this type is ever returned, and it always attaches one. */
|
|
@@ -130,7 +128,7 @@ export interface RoomSummary {
|
|
|
130
128
|
* above: mirrors lib/state/presence-store.ts's types, which rt-client
|
|
131
129
|
* cannot import.
|
|
132
130
|
*/
|
|
133
|
-
export type BuddyStatus = "live" | "idle" | "
|
|
131
|
+
export type BuddyStatus = "live" | "idle" | "offline";
|
|
134
132
|
|
|
135
133
|
export interface PresenceRow {
|
|
136
134
|
sessionId: string;
|
|
@@ -143,8 +141,6 @@ export interface PresenceRow {
|
|
|
143
141
|
statusText?: string;
|
|
144
142
|
signedInAt: number;
|
|
145
143
|
lastSeenAt: number;
|
|
146
|
-
tailSeenAt?: number;
|
|
147
|
-
armedAt?: number;
|
|
148
144
|
signedOutAt?: number;
|
|
149
145
|
}
|
|
150
146
|
|
|
@@ -170,6 +166,7 @@ export interface InviteResult { paneId: string; delivered: "accepted" | "queued"
|
|
|
170
166
|
/** Duplicated shape on purpose: mirrors lib/daemon/inject.ts's InjectResult. */
|
|
171
167
|
export type PaneDelivery = "accepted" | "queued" | "refused";
|
|
172
168
|
export interface PaneSendResult { paneId: string; delivered: PaneDelivery; reason?: string }
|
|
169
|
+
export interface PaneFocusResult { paneId: string; focused: boolean }
|
|
173
170
|
|
|
174
171
|
// SKILLS-53: one judgment, computed once in rt, so the console and the tray
|
|
175
172
|
// never derive two verdicts that can disagree.
|
|
@@ -223,7 +220,7 @@ export interface AgentRecord {
|
|
|
223
220
|
id: string; repo: string; cwd: string; provider: string;
|
|
224
221
|
surface: AgentSurface; sessionId: string;
|
|
225
222
|
model?: string; effort?: string; account?: string;
|
|
226
|
-
label?: string; caller?: string;
|
|
223
|
+
label?: string; caller?: string; handle?: string;
|
|
227
224
|
paneId?: string; tabId?: string; workspaceId?: string;
|
|
228
225
|
extraArgs?: string; exitCode?: number; resultPath?: string;
|
|
229
226
|
createdAt: number; lastResumedAt?: number; finishedAt?: number;
|
|
@@ -293,27 +290,51 @@ export interface Commands {
|
|
|
293
290
|
"chat:who": { payload: { room: string }; data: { members: ChatMember[] } };
|
|
294
291
|
"chat:mark": { payload: { handle: string; room?: string }; data: Record<string, never> };
|
|
295
292
|
"chat:messages": { payload: { room: string; before?: number; limit?: number }; data: { messages: ChatMessage[] } };
|
|
296
|
-
"chat:arm": { payload: { handle: string; room?: string; sessionId?: string }; data: Record<string, never> };
|
|
297
|
-
"chat:touch": { payload: { handle: string; room?: string; sessionId?: string }; data: Record<string, never> };
|
|
298
|
-
"chat:disarm": { payload: { handle: string; sessionId?: string }; data: Record<string, never> };
|
|
299
|
-
"chat:unread-waking": { payload: { handle: string; room?: string }; data: { rooms: { room: string; count: number; mentions: number; maxId: number }[] } };
|
|
300
293
|
|
|
301
294
|
// A session id keys these to one signed-in handle, not a room-membership
|
|
302
295
|
// handle string.
|
|
303
|
-
/**
|
|
296
|
+
/**
|
|
297
|
+
* No `baseHandle` means "draw me a first name": the daemon picks the least
|
|
298
|
+
* recently used pool name no live session holds. `viaPane` resolves
|
|
299
|
+
* `sessionId` daemon-side from herdr's `session.snapshot` for the pane id
|
|
300
|
+
* in `pane`, rather than trusting a caller-supplied id -- the caller may
|
|
301
|
+
* have none of its own (a human or another agent signing a target pane in
|
|
302
|
+
* on its behalf); the response's `sessionId` and `room` are then the only
|
|
303
|
+
* way that caller learns what got signed in and joined, since it has
|
|
304
|
+
* nothing local to derive either from.
|
|
305
|
+
*/
|
|
304
306
|
"chat:sign-in": {
|
|
305
|
-
payload: {
|
|
306
|
-
|
|
307
|
+
payload: {
|
|
308
|
+
sessionId?: string;
|
|
309
|
+
baseHandle?: string;
|
|
310
|
+
cwd?: string;
|
|
311
|
+
repo?: string;
|
|
312
|
+
branch?: string;
|
|
313
|
+
pane?: string;
|
|
314
|
+
statusText?: string;
|
|
315
|
+
viaPane?: boolean;
|
|
316
|
+
/** `viaPane` only: overrides the pane-cwd-derived room outright. */
|
|
317
|
+
room?: string;
|
|
318
|
+
/** `viaPane` only: skip room derivation/join entirely, same as --no-room on the non-pane path. */
|
|
319
|
+
noRoom?: boolean;
|
|
320
|
+
};
|
|
321
|
+
data: { handle: string; baseHandle: string; reclaimed: boolean; sessionId: string; room: string | null };
|
|
322
|
+
};
|
|
323
|
+
/**
|
|
324
|
+
* `viaPane` mirrors `chat:sign-in`'s: the daemon resolves `pane` to a
|
|
325
|
+
* session id via herdr's `session.snapshot` rather than trusting a
|
|
326
|
+
* caller-supplied one, so a process signing another pane out (herdr-chat,
|
|
327
|
+
* or a human invoking a target pane) needs neither that pane's session id
|
|
328
|
+
* nor its own. The response's `sessionId` is the RESOLVED id, the only way
|
|
329
|
+
* such a caller learns which session file to delete locally.
|
|
330
|
+
*/
|
|
331
|
+
"chat:sign-out": {
|
|
332
|
+
payload: { sessionId?: string; pane?: string; viaPane?: boolean };
|
|
333
|
+
data: { sessionId: string };
|
|
307
334
|
};
|
|
308
|
-
"chat:sign-out": { payload: { sessionId: string }; data: Record<string, never> };
|
|
309
335
|
"chat:away": { payload: { sessionId: string; text: string }; data: Record<string, never> };
|
|
310
336
|
"chat:back": { payload: { sessionId: string }; data: Record<string, never> };
|
|
311
337
|
"chat:buddies": { payload: Record<string, never>; data: { buddies: Array<PresenceRow & { status: BuddyStatus }> } };
|
|
312
|
-
/** `unread`'s three fields are disjoint and sum to the true total: `dms` is DM-room waking count; `mentions` is non-DM waking mentions; `rooms` is non-DM waking count minus those mentions (never negative). */
|
|
313
|
-
"chat:pulse": {
|
|
314
|
-
payload: { sessionId: string; cwd?: string; repo?: string; branch?: string; pane?: string };
|
|
315
|
-
data: { unread: { dms: number; mentions: number; rooms: number }; status: BuddyStatus };
|
|
316
|
-
};
|
|
317
338
|
"chat:dm": { payload: { from: string; to: string; body: string; sessionId?: string }; data: { room: string; id: number; recipients: string[] } };
|
|
318
339
|
"chat:archive": { payload: { room: string; handle: string; archived: boolean }; data: { room: string; archivedAt: number | null } };
|
|
319
340
|
"chat:dm-open": { payload: { from: string; to: string; sessionId?: string }; data: { room: string; created: boolean } };
|
|
@@ -333,6 +354,7 @@ export interface Commands {
|
|
|
333
354
|
data: { pane: ChatPane; ready: boolean };
|
|
334
355
|
};
|
|
335
356
|
"pane:send": { payload: { paneId: string; text: string; callerPane?: string }; data: PaneSendResult };
|
|
357
|
+
"pane:focus": { payload: { paneId: string }; data: PaneFocusResult };
|
|
336
358
|
}
|
|
337
359
|
|
|
338
360
|
export type CommandName = keyof Commands;
|
|
@@ -358,16 +380,11 @@ export const COMMAND_NAMES: readonly CommandName[] = [
|
|
|
358
380
|
"chat:who",
|
|
359
381
|
"chat:mark",
|
|
360
382
|
"chat:messages",
|
|
361
|
-
"chat:arm",
|
|
362
|
-
"chat:touch",
|
|
363
|
-
"chat:disarm",
|
|
364
|
-
"chat:unread-waking",
|
|
365
383
|
"chat:sign-in",
|
|
366
384
|
"chat:sign-out",
|
|
367
385
|
"chat:away",
|
|
368
386
|
"chat:back",
|
|
369
387
|
"chat:buddies",
|
|
370
|
-
"chat:pulse",
|
|
371
388
|
"chat:dm",
|
|
372
389
|
"chat:archive",
|
|
373
390
|
"chat:dm-open",
|
|
@@ -382,4 +399,5 @@ export const COMMAND_NAMES: readonly CommandName[] = [
|
|
|
382
399
|
"pane:directories",
|
|
383
400
|
"pane:spawn",
|
|
384
401
|
"pane:send",
|
|
402
|
+
"pane:focus",
|
|
385
403
|
];
|
package/src/index.ts
CHANGED
|
@@ -18,16 +18,11 @@ export {
|
|
|
18
18
|
chatWho,
|
|
19
19
|
chatMark,
|
|
20
20
|
chatMessages,
|
|
21
|
-
chatArm,
|
|
22
|
-
chatTouch,
|
|
23
|
-
chatDisarm,
|
|
24
|
-
chatUnreadWaking,
|
|
25
21
|
chatSignIn,
|
|
26
22
|
chatSignOut,
|
|
27
23
|
chatAway,
|
|
28
24
|
chatBack,
|
|
29
25
|
chatBuddies,
|
|
30
|
-
chatPulse,
|
|
31
26
|
chatDm,
|
|
32
27
|
chatArchive,
|
|
33
28
|
chatDmOpen,
|
|
@@ -43,6 +38,7 @@ export {
|
|
|
43
38
|
paneDirectories,
|
|
44
39
|
chatInvite,
|
|
45
40
|
paneSend,
|
|
41
|
+
paneFocus,
|
|
46
42
|
} from "./client.ts";
|
|
47
43
|
|
|
48
44
|
export { COMMAND_NAMES } from "./commands.ts";
|
|
@@ -80,6 +76,7 @@ export type {
|
|
|
80
76
|
InviteResult,
|
|
81
77
|
PaneDelivery,
|
|
82
78
|
PaneSendResult,
|
|
79
|
+
PaneFocusResult,
|
|
83
80
|
} from "./commands.ts";
|
|
84
81
|
|
|
85
82
|
export { subscribe, createRelay, DEFAULT_WS_URL } from "./relay.ts";
|