@mattstack/rt-client 0.4.1 → 0.6.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/dist/client.d.ts +62 -1
- package/dist/commands.d.ts +149 -1
- package/dist/health.d.ts +11 -0
- package/dist/index.d.ts +4 -3
- package/dist/index.js +118 -15
- package/dist/relay.d.ts +15 -0
- package/dist/settings/identity-codec.d.ts +28 -0
- package/dist/settings/identity-codec.js +53 -0
- package/dist/settings/identity.d.ts +3 -20
- package/dist/transport.d.ts +9 -0
- package/package.json +8 -2
- package/src/client.ts +110 -17
- package/src/commands.ts +85 -5
- package/src/health.ts +15 -0
- package/src/index.ts +14 -1
- package/src/relay.ts +31 -0
- package/src/settings/identity-codec.ts +82 -0
- package/src/settings/identity.ts +3 -72
- package/src/settings/registry-defs.ts +7 -0
- package/src/transport.ts +9 -0
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, ForgeSlug, ForgeTokenData, RunSummary, RunDetail, WakeMode, ChatMember, ChatMessage, RoomSummary } from "./commands.ts";
|
|
2
|
+
import type { DemandDecl, ProjectMRsData, DiscussionsData, MrByBranchData, BranchEnrichment, ForgeSlug, ForgeTokenData, RunSummary, RunDetail, WakeMode, ChatMember, ChatMessage, RoomSummary, BuddyStatus, PresenceRow } 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
|
|
@@ -13,6 +13,12 @@ import type { DemandDecl, ProjectMRsData, DiscussionsData, MrByBranchData, Forge
|
|
|
13
13
|
export declare function readProjectMRs(repoName: string, maxAgeMs?: number, opts?: RtClientOptions, demand?: DemandDecl): Promise<RtResponse<ProjectMRsData>>;
|
|
14
14
|
export declare function readDiscussions(repoName: string, iid: number, opts?: RtClientOptions): Promise<RtResponse<DiscussionsData>>;
|
|
15
15
|
export declare function readMrsByBranch(repoName: string, branches: string[], opts?: RtClientOptions): Promise<RtResponse<MrByBranchData>>;
|
|
16
|
+
/**
|
|
17
|
+
* Cached ticket/MR enrichment for a set of branches, keyed by branch name
|
|
18
|
+
* (the cache's own primary key -- see lib/state/branch-cache.ts). Serves
|
|
19
|
+
* whatever the daemon already has; it does not trigger a fetch.
|
|
20
|
+
*/
|
|
21
|
+
export declare function readBranchCache(branches: string[], opts?: RtClientOptions): Promise<RtResponse<Record<string, BranchEnrichment>>>;
|
|
16
22
|
/**
|
|
17
23
|
* The forge token for one tracked repo (MAT-33). Grant-gated on the daemon
|
|
18
24
|
* side: an untracked repo comes back `ok: false` with the `rt daemon track`
|
|
@@ -52,6 +58,7 @@ export declare function chatPost(a: {
|
|
|
52
58
|
room: string;
|
|
53
59
|
handle: string;
|
|
54
60
|
body: string;
|
|
61
|
+
mentions?: string[];
|
|
55
62
|
}, o?: RtClientOptions): Promise<RtResponse<{
|
|
56
63
|
id: number;
|
|
57
64
|
recipients: string[];
|
|
@@ -91,12 +98,15 @@ export declare function chatMessages(a: {
|
|
|
91
98
|
export declare function chatArm(a: {
|
|
92
99
|
handle: string;
|
|
93
100
|
room?: string;
|
|
101
|
+
sessionId?: string;
|
|
94
102
|
}, o?: RtClientOptions): Promise<RtResponse<Record<string, never>>>;
|
|
95
103
|
export declare function chatTouch(a: {
|
|
96
104
|
handle: string;
|
|
105
|
+
sessionId?: string;
|
|
97
106
|
}, o?: RtClientOptions): Promise<RtResponse<Record<string, never>>>;
|
|
98
107
|
export declare function chatDisarm(a: {
|
|
99
108
|
handle: string;
|
|
109
|
+
sessionId?: string;
|
|
100
110
|
}, o?: RtClientOptions): Promise<RtResponse<Record<string, never>>>;
|
|
101
111
|
export declare function chatUnreadWaking(a: {
|
|
102
112
|
handle: string;
|
|
@@ -109,6 +119,57 @@ export declare function chatUnreadWaking(a: {
|
|
|
109
119
|
maxId: number;
|
|
110
120
|
}[];
|
|
111
121
|
}>>;
|
|
122
|
+
export declare function chatSignIn(a: {
|
|
123
|
+
sessionId: string;
|
|
124
|
+
baseHandle: string;
|
|
125
|
+
cwd?: string;
|
|
126
|
+
repo?: string;
|
|
127
|
+
branch?: string;
|
|
128
|
+
pane?: string;
|
|
129
|
+
statusText?: string;
|
|
130
|
+
}, o?: RtClientOptions): Promise<RtResponse<{
|
|
131
|
+
handle: string;
|
|
132
|
+
reclaimed: boolean;
|
|
133
|
+
}>>;
|
|
134
|
+
export declare function chatSignOut(a: {
|
|
135
|
+
sessionId: string;
|
|
136
|
+
}, o?: RtClientOptions): Promise<RtResponse<Record<string, never>>>;
|
|
137
|
+
export declare function chatAway(a: {
|
|
138
|
+
sessionId: string;
|
|
139
|
+
text: string;
|
|
140
|
+
}, o?: RtClientOptions): Promise<RtResponse<Record<string, never>>>;
|
|
141
|
+
export declare function chatBack(a: {
|
|
142
|
+
sessionId: string;
|
|
143
|
+
}, o?: RtClientOptions): Promise<RtResponse<Record<string, never>>>;
|
|
144
|
+
export declare function chatBuddies(o?: RtClientOptions): Promise<RtResponse<{
|
|
145
|
+
buddies: Array<PresenceRow & {
|
|
146
|
+
status: BuddyStatus;
|
|
147
|
+
}>;
|
|
148
|
+
}>>;
|
|
149
|
+
export declare function chatPulse(a: {
|
|
150
|
+
sessionId: string;
|
|
151
|
+
cwd?: string;
|
|
152
|
+
repo?: string;
|
|
153
|
+
branch?: string;
|
|
154
|
+
pane?: string;
|
|
155
|
+
}, o?: RtClientOptions): Promise<RtResponse<{
|
|
156
|
+
unread: {
|
|
157
|
+
dms: number;
|
|
158
|
+
mentions: number;
|
|
159
|
+
rooms: number;
|
|
160
|
+
};
|
|
161
|
+
status: BuddyStatus;
|
|
162
|
+
}>>;
|
|
163
|
+
export declare function chatDm(a: {
|
|
164
|
+
from: string;
|
|
165
|
+
to: string;
|
|
166
|
+
body: string;
|
|
167
|
+
sessionId?: string;
|
|
168
|
+
}, o?: RtClientOptions): Promise<RtResponse<{
|
|
169
|
+
room: string;
|
|
170
|
+
id: number;
|
|
171
|
+
recipients: string[];
|
|
172
|
+
}>>;
|
|
112
173
|
export declare function eventsHead(o?: RtClientOptions): Promise<RtResponse<{
|
|
113
174
|
cursor: number;
|
|
114
175
|
}>>;
|
package/dist/commands.d.ts
CHANGED
|
@@ -40,6 +40,31 @@ export interface MrByBranchData {
|
|
|
40
40
|
byBranch: Record<string, MrByBranchEntry | null>;
|
|
41
41
|
syncedAt: number;
|
|
42
42
|
}
|
|
43
|
+
/**
|
|
44
|
+
* Trimmed, structural view of the daemon's `CacheEntry` (lib/state/branch-cache.ts) --
|
|
45
|
+
* rt-client cannot import daemon/lib internals, so this names only the fields
|
|
46
|
+
* console's run-view rows read, spelled exactly as they land on the wire
|
|
47
|
+
* (`mr` is `toMRInfo(pr)`, i.e. `getMRDashboardProps` -- camelCase `webUrl`,
|
|
48
|
+
* nested `pipeline.status`, no `ciStatus`). Extra wire fields (including the
|
|
49
|
+
* rest of `pipeline`) are fine; anything this shape doesn't name is simply
|
|
50
|
+
* not surfaced.
|
|
51
|
+
*/
|
|
52
|
+
export interface BranchEnrichment {
|
|
53
|
+
ticket: {
|
|
54
|
+
identifier: string;
|
|
55
|
+
title: string;
|
|
56
|
+
url: string;
|
|
57
|
+
} | null;
|
|
58
|
+
mr: {
|
|
59
|
+
iid: number;
|
|
60
|
+
webUrl: string | null;
|
|
61
|
+
state: string;
|
|
62
|
+
pipeline: {
|
|
63
|
+
status: string;
|
|
64
|
+
} | null;
|
|
65
|
+
} | null;
|
|
66
|
+
fetchedAt: number;
|
|
67
|
+
}
|
|
43
68
|
/** Forges the daemon can hold a token for. */
|
|
44
69
|
export type ForgeSlug = "gitlab" | "github";
|
|
45
70
|
export interface ForgeTokenData {
|
|
@@ -71,6 +96,8 @@ export interface ChatMember {
|
|
|
71
96
|
armedAt?: number;
|
|
72
97
|
cwd?: string;
|
|
73
98
|
pane?: string;
|
|
99
|
+
/** Presence-joined by chat:who's handler — the only place this type is ever returned, and it always attaches one. */
|
|
100
|
+
status: BuddyStatus;
|
|
74
101
|
}
|
|
75
102
|
export interface ChatMessage {
|
|
76
103
|
id: number;
|
|
@@ -87,10 +114,39 @@ export interface RoomSummary {
|
|
|
87
114
|
unread: number;
|
|
88
115
|
mentions: number;
|
|
89
116
|
lastPostedAt?: number;
|
|
117
|
+
/** Set only by chat:rooms's left join against chat_dms. */
|
|
118
|
+
kind?: "dm";
|
|
119
|
+
participants?: {
|
|
120
|
+
a: string;
|
|
121
|
+
b: string;
|
|
122
|
+
};
|
|
123
|
+
/** Set only by chat:rooms's left join against chat_room_defaults; undefined for a room never stamped a default (every DM room included). */
|
|
124
|
+
defaultWake?: WakeMode;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Duplicated shape on purpose, same reasoning as ChatMember/ChatMessage
|
|
128
|
+
* above: mirrors lib/state/presence-store.ts's types, which rt-client
|
|
129
|
+
* cannot import.
|
|
130
|
+
*/
|
|
131
|
+
export type BuddyStatus = "live" | "idle" | "deaf" | "offline";
|
|
132
|
+
export interface PresenceRow {
|
|
133
|
+
sessionId: string;
|
|
134
|
+
handle: string;
|
|
135
|
+
baseHandle: string;
|
|
136
|
+
cwd?: string;
|
|
137
|
+
repo?: string;
|
|
138
|
+
branch?: string;
|
|
139
|
+
pane?: string;
|
|
140
|
+
statusText?: string;
|
|
141
|
+
signedInAt: number;
|
|
142
|
+
lastSeenAt: number;
|
|
143
|
+
tailSeenAt?: number;
|
|
144
|
+
armedAt?: number;
|
|
145
|
+
signedOutAt?: number;
|
|
90
146
|
}
|
|
91
147
|
export type Attention = {
|
|
92
148
|
needs: boolean;
|
|
93
|
-
reason: "failed" | "stale" | "stranded" | null;
|
|
149
|
+
reason: "failed" | "stale" | "stranded" | "blocked" | null;
|
|
94
150
|
evidence: string;
|
|
95
151
|
};
|
|
96
152
|
export interface RunSummary {
|
|
@@ -115,6 +171,21 @@ export interface RunSummary {
|
|
|
115
171
|
the run has not produced that field yet. */
|
|
116
172
|
ticket: string | null;
|
|
117
173
|
branch: string | null;
|
|
174
|
+
/** The herdr agent attributed to this run (matched by recorded claude
|
|
175
|
+
session, else by worktree), mirrored live from `herdr agent list`.
|
|
176
|
+
Null when no agent matches or herdr is unavailable; absent on
|
|
177
|
+
pre-mirror daemons. */
|
|
178
|
+
agent?: RunAgent | null;
|
|
179
|
+
/** Executed stages only, in run order — the pipeline may define more that have not started. */
|
|
180
|
+
stages?: {
|
|
181
|
+
name: string;
|
|
182
|
+
status: string;
|
|
183
|
+
started_at: number | null;
|
|
184
|
+
}[];
|
|
185
|
+
}
|
|
186
|
+
export interface RunAgent {
|
|
187
|
+
status: "working" | "idle" | "blocked" | "done" | "unknown";
|
|
188
|
+
pane: string;
|
|
118
189
|
}
|
|
119
190
|
export interface RunStageRow {
|
|
120
191
|
name: string;
|
|
@@ -313,6 +384,7 @@ export interface Commands {
|
|
|
313
384
|
room: string;
|
|
314
385
|
handle: string;
|
|
315
386
|
body: string;
|
|
387
|
+
mentions?: string[];
|
|
316
388
|
};
|
|
317
389
|
data: {
|
|
318
390
|
id: number;
|
|
@@ -370,18 +442,21 @@ export interface Commands {
|
|
|
370
442
|
payload: {
|
|
371
443
|
handle: string;
|
|
372
444
|
room?: string;
|
|
445
|
+
sessionId?: string;
|
|
373
446
|
};
|
|
374
447
|
data: Record<string, never>;
|
|
375
448
|
};
|
|
376
449
|
"chat:touch": {
|
|
377
450
|
payload: {
|
|
378
451
|
handle: string;
|
|
452
|
+
sessionId?: string;
|
|
379
453
|
};
|
|
380
454
|
data: Record<string, never>;
|
|
381
455
|
};
|
|
382
456
|
"chat:disarm": {
|
|
383
457
|
payload: {
|
|
384
458
|
handle: string;
|
|
459
|
+
sessionId?: string;
|
|
385
460
|
};
|
|
386
461
|
data: Record<string, never>;
|
|
387
462
|
};
|
|
@@ -399,6 +474,79 @@ export interface Commands {
|
|
|
399
474
|
}[];
|
|
400
475
|
};
|
|
401
476
|
};
|
|
477
|
+
"chat:sign-in": {
|
|
478
|
+
payload: {
|
|
479
|
+
sessionId: string;
|
|
480
|
+
baseHandle: string;
|
|
481
|
+
cwd?: string;
|
|
482
|
+
repo?: string;
|
|
483
|
+
branch?: string;
|
|
484
|
+
pane?: string;
|
|
485
|
+
statusText?: string;
|
|
486
|
+
};
|
|
487
|
+
data: {
|
|
488
|
+
handle: string;
|
|
489
|
+
reclaimed: boolean;
|
|
490
|
+
};
|
|
491
|
+
};
|
|
492
|
+
"chat:sign-out": {
|
|
493
|
+
payload: {
|
|
494
|
+
sessionId: string;
|
|
495
|
+
};
|
|
496
|
+
data: Record<string, never>;
|
|
497
|
+
};
|
|
498
|
+
"chat:away": {
|
|
499
|
+
payload: {
|
|
500
|
+
sessionId: string;
|
|
501
|
+
text: string;
|
|
502
|
+
};
|
|
503
|
+
data: Record<string, never>;
|
|
504
|
+
};
|
|
505
|
+
"chat:back": {
|
|
506
|
+
payload: {
|
|
507
|
+
sessionId: string;
|
|
508
|
+
};
|
|
509
|
+
data: Record<string, never>;
|
|
510
|
+
};
|
|
511
|
+
"chat:buddies": {
|
|
512
|
+
payload: Record<string, never>;
|
|
513
|
+
data: {
|
|
514
|
+
buddies: Array<PresenceRow & {
|
|
515
|
+
status: BuddyStatus;
|
|
516
|
+
}>;
|
|
517
|
+
};
|
|
518
|
+
};
|
|
519
|
+
/** `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). */
|
|
520
|
+
"chat:pulse": {
|
|
521
|
+
payload: {
|
|
522
|
+
sessionId: string;
|
|
523
|
+
cwd?: string;
|
|
524
|
+
repo?: string;
|
|
525
|
+
branch?: string;
|
|
526
|
+
pane?: string;
|
|
527
|
+
};
|
|
528
|
+
data: {
|
|
529
|
+
unread: {
|
|
530
|
+
dms: number;
|
|
531
|
+
mentions: number;
|
|
532
|
+
rooms: number;
|
|
533
|
+
};
|
|
534
|
+
status: BuddyStatus;
|
|
535
|
+
};
|
|
536
|
+
};
|
|
537
|
+
"chat:dm": {
|
|
538
|
+
payload: {
|
|
539
|
+
from: string;
|
|
540
|
+
to: string;
|
|
541
|
+
body: string;
|
|
542
|
+
sessionId?: string;
|
|
543
|
+
};
|
|
544
|
+
data: {
|
|
545
|
+
room: string;
|
|
546
|
+
id: number;
|
|
547
|
+
recipients: string[];
|
|
548
|
+
};
|
|
549
|
+
};
|
|
402
550
|
}
|
|
403
551
|
export type CommandName = keyof Commands;
|
|
404
552
|
export declare const COMMAND_NAMES: readonly CommandName[];
|
package/dist/health.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { RtClientOptions } from "./transport.ts";
|
|
2
|
+
/**
|
|
3
|
+
* A daemon-down result is a successful probe, not a failure of this call —
|
|
4
|
+
* eventsHead already never throws (transport.ts degrades every fetch to
|
|
5
|
+
* `{ ok: false, error }`), so this only reshapes that envelope for callers
|
|
6
|
+
* who want a boolean, not `{ ok, data, error }`.
|
|
7
|
+
*/
|
|
8
|
+
export declare function daemonHealth(opts?: RtClientOptions): Promise<{
|
|
9
|
+
reachable: boolean;
|
|
10
|
+
error?: string;
|
|
11
|
+
}>;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
export { rtCommand, DEFAULT_SOCK } from "./transport.ts";
|
|
2
2
|
export type { RtResponse, RtClientOptions } from "./transport.ts";
|
|
3
|
-
export { readProjectMRs, readDiscussions, readMrsByBranch, resolveForgeToken, listRuns, getRun, abandonRun, chatJoin, chatLeave, chatPost, chatRead, chatRooms, chatWho, chatMark, chatMessages, chatArm, chatTouch, chatDisarm, chatUnreadWaking, 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, } from "./client.ts";
|
|
4
4
|
export { COMMAND_NAMES } from "./commands.ts";
|
|
5
|
-
export type { Discussion, DemandDecl, ProjectMRsScope, ProjectMRsData, DiscussionsData, MrByBranchEntry, MrByBranchData, Commands, CommandName, ForgeSlug, ForgeTokenData, Attention, RunSummary, RunStageRow, RunFieldRow, RunDecisionRow, RunDetail, WakeMode, ChatMember, ChatMessage, RoomSummary, } from "./commands.ts";
|
|
6
|
-
export { subscribe, DEFAULT_WS_URL } from "./relay.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";
|
|
6
|
+
export { subscribe, createRelay, DEFAULT_WS_URL } from "./relay.ts";
|
|
7
7
|
export type { RelayEventType } from "./relay.ts";
|
|
8
|
+
export { daemonHealth } from "./health.ts";
|
|
8
9
|
export { repoNameForPath } from "./repos.ts";
|
|
9
10
|
export { getSetting, listSettings, explainSetting, expandVariables, SCOPE_ORDER } from "./settings/resolve.ts";
|
|
10
11
|
export type { Scope, Provenance, ResolveOpts, Resolved, InvalidScope, ListedSetting, ExplainRow, ExpandCtx, } from "./settings/resolve.ts";
|
package/dist/index.js
CHANGED
|
@@ -39,6 +39,9 @@ function readDiscussions(repoName, iid, opts = {}) {
|
|
|
39
39
|
function readMrsByBranch(repoName, branches, opts = {}) {
|
|
40
40
|
return rtCommand("mr:by-branch", { repoName, branches }, { sockPath: opts.sockPath, timeoutMs: 60000 });
|
|
41
41
|
}
|
|
42
|
+
function readBranchCache(branches, opts = {}) {
|
|
43
|
+
return rtCommand("cache:read", { branches }, { sockPath: opts.sockPath, timeoutMs: 1e4 });
|
|
44
|
+
}
|
|
42
45
|
function resolveForgeToken(repoName, forge, opts = {}) {
|
|
43
46
|
return rtCommand("secrets:forge-token", { repoName, forge }, { sockPath: opts.sockPath, timeoutMs: 1e4 });
|
|
44
47
|
}
|
|
@@ -70,13 +73,16 @@ function chatJoin(a, o = {}) {
|
|
|
70
73
|
payload.cwd = a.cwd;
|
|
71
74
|
if (a.pane !== undefined)
|
|
72
75
|
payload.pane = a.pane;
|
|
73
|
-
return rtCommand("chat:join", payload, { sockPath: o.sockPath, timeoutMs: 1e4 });
|
|
76
|
+
return rtCommand("chat:join", payload, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 1e4 });
|
|
74
77
|
}
|
|
75
78
|
function chatLeave(a, o = {}) {
|
|
76
|
-
return rtCommand("chat:leave", { room: a.room, handle: a.handle }, { sockPath: o.sockPath, timeoutMs: 1e4 });
|
|
79
|
+
return rtCommand("chat:leave", { room: a.room, handle: a.handle }, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 1e4 });
|
|
77
80
|
}
|
|
78
81
|
function chatPost(a, o = {}) {
|
|
79
|
-
|
|
82
|
+
const payload = { room: a.room, handle: a.handle, body: a.body };
|
|
83
|
+
if (a.mentions !== undefined)
|
|
84
|
+
payload.mentions = a.mentions;
|
|
85
|
+
return rtCommand("chat:post", payload, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 1e4 });
|
|
80
86
|
}
|
|
81
87
|
function chatRead(a, o = {}) {
|
|
82
88
|
const payload = { handle: a.handle };
|
|
@@ -86,19 +92,19 @@ function chatRead(a, o = {}) {
|
|
|
86
92
|
payload.limit = a.limit;
|
|
87
93
|
if (a.sinceMs !== undefined)
|
|
88
94
|
payload.sinceMs = a.sinceMs;
|
|
89
|
-
return rtCommand("chat:read", payload, { sockPath: o.sockPath, timeoutMs: 1e4 });
|
|
95
|
+
return rtCommand("chat:read", payload, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 1e4 });
|
|
90
96
|
}
|
|
91
97
|
function chatRooms(a, o = {}) {
|
|
92
|
-
return rtCommand("chat:rooms", { handle: a.handle }, { sockPath: o.sockPath, timeoutMs: 1e4 });
|
|
98
|
+
return rtCommand("chat:rooms", { handle: a.handle }, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 1e4 });
|
|
93
99
|
}
|
|
94
100
|
function chatWho(a, o = {}) {
|
|
95
|
-
return rtCommand("chat:who", { room: a.room }, { sockPath: o.sockPath, timeoutMs: 1e4 });
|
|
101
|
+
return rtCommand("chat:who", { room: a.room }, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 1e4 });
|
|
96
102
|
}
|
|
97
103
|
function chatMark(a, o = {}) {
|
|
98
104
|
const payload = { handle: a.handle };
|
|
99
105
|
if (a.room !== undefined)
|
|
100
106
|
payload.room = a.room;
|
|
101
|
-
return rtCommand("chat:mark", payload, { sockPath: o.sockPath, timeoutMs: 1e4 });
|
|
107
|
+
return rtCommand("chat:mark", payload, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 1e4 });
|
|
102
108
|
}
|
|
103
109
|
function chatMessages(a, o = {}) {
|
|
104
110
|
const payload = { room: a.room };
|
|
@@ -106,28 +112,80 @@ function chatMessages(a, o = {}) {
|
|
|
106
112
|
payload.before = a.before;
|
|
107
113
|
if (a.limit !== undefined)
|
|
108
114
|
payload.limit = a.limit;
|
|
109
|
-
return rtCommand("chat:messages", payload, { sockPath: o.sockPath, timeoutMs: 1e4 });
|
|
115
|
+
return rtCommand("chat:messages", payload, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 1e4 });
|
|
110
116
|
}
|
|
111
117
|
function chatArm(a, o = {}) {
|
|
112
118
|
const payload = { handle: a.handle };
|
|
113
119
|
if (a.room !== undefined)
|
|
114
120
|
payload.room = a.room;
|
|
115
|
-
|
|
121
|
+
if (a.sessionId !== undefined)
|
|
122
|
+
payload.sessionId = a.sessionId;
|
|
123
|
+
return rtCommand("chat:arm", payload, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 1e4 });
|
|
116
124
|
}
|
|
117
125
|
function chatTouch(a, o = {}) {
|
|
118
|
-
|
|
126
|
+
const payload = { handle: a.handle };
|
|
127
|
+
if (a.sessionId !== undefined)
|
|
128
|
+
payload.sessionId = a.sessionId;
|
|
129
|
+
return rtCommand("chat:touch", payload, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 1e4 });
|
|
119
130
|
}
|
|
120
131
|
function chatDisarm(a, o = {}) {
|
|
121
|
-
|
|
132
|
+
const payload = { handle: a.handle };
|
|
133
|
+
if (a.sessionId !== undefined)
|
|
134
|
+
payload.sessionId = a.sessionId;
|
|
135
|
+
return rtCommand("chat:disarm", payload, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 1e4 });
|
|
122
136
|
}
|
|
123
137
|
function chatUnreadWaking(a, o = {}) {
|
|
124
138
|
const payload = { handle: a.handle };
|
|
125
139
|
if (a.room !== undefined)
|
|
126
140
|
payload.room = a.room;
|
|
127
|
-
return rtCommand("chat:unread-waking", payload, { sockPath: o.sockPath, timeoutMs: 1e4 });
|
|
141
|
+
return rtCommand("chat:unread-waking", payload, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 1e4 });
|
|
142
|
+
}
|
|
143
|
+
function chatSignIn(a, o = {}) {
|
|
144
|
+
const payload = { sessionId: a.sessionId, baseHandle: a.baseHandle };
|
|
145
|
+
if (a.cwd !== undefined)
|
|
146
|
+
payload.cwd = a.cwd;
|
|
147
|
+
if (a.repo !== undefined)
|
|
148
|
+
payload.repo = a.repo;
|
|
149
|
+
if (a.branch !== undefined)
|
|
150
|
+
payload.branch = a.branch;
|
|
151
|
+
if (a.pane !== undefined)
|
|
152
|
+
payload.pane = a.pane;
|
|
153
|
+
if (a.statusText !== undefined)
|
|
154
|
+
payload.statusText = a.statusText;
|
|
155
|
+
return rtCommand("chat:sign-in", payload, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 1e4 });
|
|
156
|
+
}
|
|
157
|
+
function chatSignOut(a, o = {}) {
|
|
158
|
+
return rtCommand("chat:sign-out", { sessionId: a.sessionId }, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 1e4 });
|
|
159
|
+
}
|
|
160
|
+
function chatAway(a, o = {}) {
|
|
161
|
+
return rtCommand("chat:away", { sessionId: a.sessionId, text: a.text }, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 1e4 });
|
|
162
|
+
}
|
|
163
|
+
function chatBack(a, o = {}) {
|
|
164
|
+
return rtCommand("chat:back", { sessionId: a.sessionId }, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 1e4 });
|
|
165
|
+
}
|
|
166
|
+
function chatBuddies(o = {}) {
|
|
167
|
+
return rtCommand("chat:buddies", {}, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 1e4 });
|
|
168
|
+
}
|
|
169
|
+
function chatPulse(a, o = {}) {
|
|
170
|
+
const payload = { sessionId: a.sessionId };
|
|
171
|
+
if (a.cwd !== undefined)
|
|
172
|
+
payload.cwd = a.cwd;
|
|
173
|
+
if (a.repo !== undefined)
|
|
174
|
+
payload.repo = a.repo;
|
|
175
|
+
if (a.branch !== undefined)
|
|
176
|
+
payload.branch = a.branch;
|
|
177
|
+
if (a.pane !== undefined)
|
|
178
|
+
payload.pane = a.pane;
|
|
179
|
+
return rtCommand("chat:pulse", payload, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 1e4 });
|
|
180
|
+
}
|
|
181
|
+
function chatDm(a, o = {}) {
|
|
182
|
+
const payload = { from: a.from, to: a.to, body: a.body };
|
|
183
|
+
if (a.sessionId !== undefined)
|
|
184
|
+
payload.sessionId = a.sessionId;
|
|
185
|
+
return rtCommand("chat:dm", payload, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 1e4 });
|
|
128
186
|
}
|
|
129
187
|
function eventsHead(o = {}) {
|
|
130
|
-
return rtCommand("events:head", {}, { sockPath: o.sockPath, timeoutMs: 1e4 });
|
|
188
|
+
return rtCommand("events:head", {}, { sockPath: o.sockPath, timeoutMs: o.timeoutMs ?? 1e4 });
|
|
131
189
|
}
|
|
132
190
|
// src/commands.ts
|
|
133
191
|
var COMMAND_NAMES = [
|
|
@@ -154,7 +212,14 @@ var COMMAND_NAMES = [
|
|
|
154
212
|
"chat:arm",
|
|
155
213
|
"chat:touch",
|
|
156
214
|
"chat:disarm",
|
|
157
|
-
"chat:unread-waking"
|
|
215
|
+
"chat:unread-waking",
|
|
216
|
+
"chat:sign-in",
|
|
217
|
+
"chat:sign-out",
|
|
218
|
+
"chat:away",
|
|
219
|
+
"chat:back",
|
|
220
|
+
"chat:buddies",
|
|
221
|
+
"chat:pulse",
|
|
222
|
+
"chat:dm"
|
|
158
223
|
];
|
|
159
224
|
// src/relay.ts
|
|
160
225
|
var DEFAULT_WS_URL = "ws://127.0.0.1:9401/ws";
|
|
@@ -199,6 +264,25 @@ function subscribe(onEvent, opts = {}) {
|
|
|
199
264
|
} catch {}
|
|
200
265
|
};
|
|
201
266
|
}
|
|
267
|
+
function createRelay(cfg, opts = {}) {
|
|
268
|
+
const doSubscribe = opts.subscribeImpl ?? subscribe;
|
|
269
|
+
return doSubscribe((type, data) => {
|
|
270
|
+
if (type !== "event")
|
|
271
|
+
return;
|
|
272
|
+
const frame = data;
|
|
273
|
+
if (typeof frame?.topic !== "string" || !cfg.match(frame.topic))
|
|
274
|
+
return;
|
|
275
|
+
const payload = JSON.stringify(data);
|
|
276
|
+
try {
|
|
277
|
+
cfg.publish(cfg.topic, payload);
|
|
278
|
+
} catch {}
|
|
279
|
+
}, opts);
|
|
280
|
+
}
|
|
281
|
+
// src/health.ts
|
|
282
|
+
async function daemonHealth(opts = {}) {
|
|
283
|
+
const res = await eventsHead(opts);
|
|
284
|
+
return { reachable: res.ok, error: res.ok ? undefined : res.error };
|
|
285
|
+
}
|
|
202
286
|
// src/repos.ts
|
|
203
287
|
import { existsSync, readFileSync } from "fs";
|
|
204
288
|
import { homedir as homedir2 } from "os";
|
|
@@ -506,6 +590,13 @@ var REGISTRY = [
|
|
|
506
590
|
merge: "replace",
|
|
507
591
|
description: "Absolute path to the installed mattstack.app bundle, written by the app at launch so rt stops hardcoding ~/Applications."
|
|
508
592
|
},
|
|
593
|
+
{
|
|
594
|
+
key: "mattstack.mode",
|
|
595
|
+
type: "string",
|
|
596
|
+
scopes: ["machine"],
|
|
597
|
+
merge: "replace",
|
|
598
|
+
description: 'The machine\'s intended flavor, "dev" or "prod". Normally written by `rt settings dev-mode` after a successful handoff; a manual `rt settings set` is the blessed repair escape hatch — the daemon park loop converges on whatever this says. Unset ⇒ derived from the dev wrapper\'s presence.'
|
|
599
|
+
},
|
|
509
600
|
{
|
|
510
601
|
key: "rt.integrations",
|
|
511
602
|
type: "object",
|
|
@@ -1395,7 +1486,7 @@ async function runCapture(argv, opts = {}) {
|
|
|
1395
1486
|
}
|
|
1396
1487
|
}
|
|
1397
1488
|
|
|
1398
|
-
// src/settings/identity.ts
|
|
1489
|
+
// src/settings/identity-codec.ts
|
|
1399
1490
|
var URL_RE = /^[a-zA-Z][a-zA-Z0-9+.-]*:\/\/(?:[^@/]+@)?([^/]+)\/(.+)$/;
|
|
1400
1491
|
var SCP_RE = /^(?:[^@/\s]+@)?([^:/\s]+):(.+)$/;
|
|
1401
1492
|
function serializeIdentity(id) {
|
|
@@ -1443,6 +1534,8 @@ function normalizeRemote(remote) {
|
|
|
1443
1534
|
return null;
|
|
1444
1535
|
return `${host.toLowerCase()}/${normalizedPath}`;
|
|
1445
1536
|
}
|
|
1537
|
+
|
|
1538
|
+
// src/settings/identity.ts
|
|
1446
1539
|
function identityFromRemote(remote) {
|
|
1447
1540
|
const store = readStore(machineSettingsPath());
|
|
1448
1541
|
const overrides = store.global["rt.repoIdentityOverrides"];
|
|
@@ -1522,6 +1615,7 @@ export {
|
|
|
1522
1615
|
readProjectMRs,
|
|
1523
1616
|
readMrsByBranch,
|
|
1524
1617
|
readDiscussions,
|
|
1618
|
+
readBranchCache,
|
|
1525
1619
|
parseIdentity,
|
|
1526
1620
|
normalizeRemote,
|
|
1527
1621
|
listTeams,
|
|
@@ -1536,18 +1630,27 @@ export {
|
|
|
1536
1630
|
expandVariables,
|
|
1537
1631
|
eventsHead,
|
|
1538
1632
|
deriveRepoIdentity,
|
|
1633
|
+
daemonHealth,
|
|
1634
|
+
createRelay,
|
|
1539
1635
|
clearIdentityMemo,
|
|
1540
1636
|
chatWho,
|
|
1541
1637
|
chatUnreadWaking,
|
|
1542
1638
|
chatTouch,
|
|
1639
|
+
chatSignOut,
|
|
1640
|
+
chatSignIn,
|
|
1543
1641
|
chatRooms,
|
|
1544
1642
|
chatRead,
|
|
1643
|
+
chatPulse,
|
|
1545
1644
|
chatPost,
|
|
1546
1645
|
chatMessages,
|
|
1547
1646
|
chatMark,
|
|
1548
1647
|
chatLeave,
|
|
1549
1648
|
chatJoin,
|
|
1649
|
+
chatDm,
|
|
1550
1650
|
chatDisarm,
|
|
1651
|
+
chatBuddies,
|
|
1652
|
+
chatBack,
|
|
1653
|
+
chatAway,
|
|
1551
1654
|
chatArm,
|
|
1552
1655
|
allDefs,
|
|
1553
1656
|
abandonRun,
|
package/dist/relay.d.ts
CHANGED
|
@@ -13,3 +13,18 @@ export declare const DEFAULT_WS_URL = "ws://127.0.0.1:9401/ws";
|
|
|
13
13
|
* the daemon being down just means silence, never a crash.
|
|
14
14
|
*/
|
|
15
15
|
export declare function subscribe(onEvent: (type: RelayEventType, data: unknown) => void, opts?: RtClientOptions): () => void;
|
|
16
|
+
/**
|
|
17
|
+
* One daemon subscription for the whole process, republished onto a
|
|
18
|
+
* caller-chosen pub/sub topic. Every subscriber to that topic then shares
|
|
19
|
+
* one relay connection instead of each opening its own — filtering here
|
|
20
|
+
* (rather than at each subscriber) is what keeps an unrelated event from
|
|
21
|
+
* making every subscriber re-render.
|
|
22
|
+
*
|
|
23
|
+
* Ported from console's `startRelay` (src/server/ws.ts) with the match
|
|
24
|
+
* predicate and target topic lifted to arguments.
|
|
25
|
+
*/
|
|
26
|
+
export declare function createRelay(cfg: {
|
|
27
|
+
match: (topic: string) => boolean;
|
|
28
|
+
topic: string;
|
|
29
|
+
publish: (topic: string, data: string) => void;
|
|
30
|
+
}, opts?: RtClientOptions): () => void;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The pure half of the repo-identity contract: the wire codec and the
|
|
3
|
+
* remote-URL normalizer. Split from identity.ts so browser bundles can key
|
|
4
|
+
* and label repos without dragging in fs/child_process — this module must
|
|
5
|
+
* never import node builtins or anything that does (the `./identity`
|
|
6
|
+
* subpath export points here, and a browser consumer evaluates it at module
|
|
7
|
+
* scope). Override-aware and derivation entry points stay in identity.ts.
|
|
8
|
+
*/
|
|
9
|
+
export type RepoIdentity = {
|
|
10
|
+
kind: "remote";
|
|
11
|
+
id: string;
|
|
12
|
+
} | {
|
|
13
|
+
kind: "path";
|
|
14
|
+
id: string;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* The wire form crosses the daemon socket, sits in board config, and lands in
|
|
18
|
+
* console's `/runs/:repo/...` URL — all of which need one slash-free segment.
|
|
19
|
+
* `encodeURIComponent` guarantees that and is exactly reversible.
|
|
20
|
+
*/
|
|
21
|
+
export declare function serializeIdentity(id: RepoIdentity): string;
|
|
22
|
+
export declare function parseIdentity(wire: string): RepoIdentity | null;
|
|
23
|
+
/**
|
|
24
|
+
* Pure normalization: `remote` → `host/path` (lowercase host, `.git` and
|
|
25
|
+
* embedded credentials stripped) or null when the remote doesn't match a
|
|
26
|
+
* recognized host form (local paths, garbage input).
|
|
27
|
+
*/
|
|
28
|
+
export declare function normalizeRemote(remote: string): string | null;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
// src/settings/identity-codec.ts
|
|
2
|
+
var URL_RE = /^[a-zA-Z][a-zA-Z0-9+.-]*:\/\/(?:[^@/]+@)?([^/]+)\/(.+)$/;
|
|
3
|
+
var SCP_RE = /^(?:[^@/\s]+@)?([^:/\s]+):(.+)$/;
|
|
4
|
+
function serializeIdentity(id) {
|
|
5
|
+
return `${id.kind}:${encodeURIComponent(id.id)}`;
|
|
6
|
+
}
|
|
7
|
+
function parseIdentity(wire) {
|
|
8
|
+
const colon = wire.indexOf(":");
|
|
9
|
+
if (colon === -1)
|
|
10
|
+
return null;
|
|
11
|
+
const kind = wire.slice(0, colon);
|
|
12
|
+
if (kind !== "remote" && kind !== "path")
|
|
13
|
+
return null;
|
|
14
|
+
const encoded = wire.slice(colon + 1);
|
|
15
|
+
let id;
|
|
16
|
+
try {
|
|
17
|
+
id = decodeURIComponent(encoded);
|
|
18
|
+
} catch {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
if (encodeURIComponent(id) !== encoded)
|
|
22
|
+
return null;
|
|
23
|
+
return { kind, id };
|
|
24
|
+
}
|
|
25
|
+
function normalizeRemote(remote) {
|
|
26
|
+
const trimmed = remote.trim();
|
|
27
|
+
if (!trimmed)
|
|
28
|
+
return null;
|
|
29
|
+
let host;
|
|
30
|
+
let path;
|
|
31
|
+
const urlMatch = URL_RE.exec(trimmed);
|
|
32
|
+
if (urlMatch) {
|
|
33
|
+
host = urlMatch[1];
|
|
34
|
+
path = urlMatch[2];
|
|
35
|
+
} else if (!trimmed.startsWith("/") && !trimmed.startsWith("~")) {
|
|
36
|
+
const scpMatch = SCP_RE.exec(trimmed);
|
|
37
|
+
if (scpMatch) {
|
|
38
|
+
host = scpMatch[1];
|
|
39
|
+
path = scpMatch[2];
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
if (!host || !path)
|
|
43
|
+
return null;
|
|
44
|
+
const normalizedPath = path.replace(/\.git$/, "").replace(/^\/+/, "").replace(/\/+$/, "");
|
|
45
|
+
if (!normalizedPath)
|
|
46
|
+
return null;
|
|
47
|
+
return `${host.toLowerCase()}/${normalizedPath}`;
|
|
48
|
+
}
|
|
49
|
+
export {
|
|
50
|
+
serializeIdentity,
|
|
51
|
+
parseIdentity,
|
|
52
|
+
normalizeRemote
|
|
53
|
+
};
|